Skip to content

Agent Registry migration tool: runtime.transform.duplicateNames="suffix" is documented but not implemented #1983

Description

@dgallitelli

Summary

In 01-features/07-centralize-and-govern-your-ai-infrastructure/03-registry/04-migrate-to-new-namespace, the config setting runtime.transform.duplicateNames (values "fail" / "suffix", documented in docs/configuration.md and docs/detaileddoc.md) has no effect when set to "suffix". Records that collide on name+recordVersion in the target namespace still hard-fail at load time exactly as if the setting were absent or set to "fail".

Repro

  1. Preview (bedrock-agentcore) registry has ≥2 records with the same name and no/matching recordVersion (legal there — name was just a display label).
  2. migration.config.json sets:
    "runtime": { "transform": { "duplicateNames": "suffix" } }
  3. Run init/target-config --createcheckextractload --dry-run (or --live).

Expected (per docs): colliding records are migrated under distinct, deterministically-suffixed target names (suffix "derived from the source record's identity" per docs/configuration.md), nothing is dropped.

Actual: each colliding record after the first fails with:

Preview records '<acct>/<region>/<reg>/<idA>' and '<acct>/<region>/<reg>/<idB>' both migrate to the target registry name '<name>' (recordVersion '<version>'). That identity is already claimed in registry <target>; the new version requires it to be unique, so loading the second would overwrite the first. Rename one of them in the source registry, or give them distinct recordVersions, and re-extract.

identical whether duplicateNames is "fail" (default), "suffix", or absent from the config entirely.

Root cause

duplicateNames is never read by the code that actually claims target names. Searching the whole tool subtree:

  • grep -r duplicateNames lib/ cli/ dist/ glue/common/migration_common/zero matches in any implementation file.
  • It only appears in docs/configuration.md, docs/detaileddoc.md, and in comments/test scaffolding (glue/common/tests/test_jobs_end_to_end.py, glue/common/tests/test_report_html.py, tools/seed_preview_test_registry.py).
  • The actual failure originates in glue/common/migration_common/jobs/transform_load.py (claim_in_order) → glue/common/migration_common/registry_api.py (claim / _claim_target_record), which raises unconditionally on a name collision with no branch on the configured duplicateNames mode.
  • Notably, tools/seed_preview_test_registry.py (lines ~52-63, ~512-517) documents the intended behavior in comments — extract should detect the clash and resolve it once duplicateNames="suffix" — and states a duplicate-name fixture was deliberately removed from the seed matrix "because... extract detects the clash... and resolves it once runtime.transform.duplicateNames is set to suffix." That resolution path does not exist in the shipped code, so the fixture's removal currently masks a live gap in test coverage for this setting.

Default ("fail"/unset) behavior otherwise matches its documented contract (the run completes with PARTIAL_SUCCESS, colliding records are skipped and listed in the failure report) — this issue is scoped specifically to "suffix" mode being a no-op.

Impact

With the default runtime.load.failOnRecordError=false, a migration under an unattended/Glue-managed run can silently skip colliding records while reporting PARTIAL_SUCCESS — a user who set duplicateNames="suffix" believing it protects against this will not get an error signal distinct from the unset case, and could lose records without realizing it unless they inspect the failure report closely.

Suggested fix

Wire duplicateNames through to claim_in_order/claim in migration_common: when "suffix", assign each colliding record (after the first claimant) a deterministic target name suffix derived from the source record's identity, preserve the original name as displayName/previewName per the existing crosswalk semantics, and continue instead of raising. Happy to open a PR for this — will follow up.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions