Skip to content

fix(intake): resolve fabricated agents by registry record id and sanitised name when reading build status - #403

Merged
gibbsie merged 1 commit into
mainfrom
fix/intake-status-by-record-id
Oct 26, 2026
Merged

gibbsie merged 1 commit into
mainfrom
fix/intake-status-by-record-id

Conversation

@gibbsie

@gibbsie gibbsie commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Problem

postfab._resolve_live_statuses passed the job row's display name (e.g. 'Arbiter Agent', 'Catering & Fuel Sequencing Agent') as the name filter value to ListRegistryRecords. The AgentCore Registry API rejects names containing spaces or special characters with ValidationException: Invalid value for filter name, so every live-status read failed and the stale write-once snapshot won by default.

Fix

Three-path resolution order (most-to-least precise):

  1. registryRecordId (new field on the job row) → GetRegistryRecord — one call, exact match.
  2. registryName (new field) → ListRegistryRecords using the stamped sanitised name the fabricator created the record with.
  3. Fallback for pre-fix rows: sanitise the display name with sanitize_registry_name().lower() (the same function the fabricator uses to derive record names) and list with filters.

The raw display name is never passed to the name filter.

Changes

arbiter/fabricator/index.py

  • _RegistrationRunState gains agent_record_info: dict[str, tuple[str, str]] mapping agent_id → (record_id, registry_name).
  • store_agent_config_registry stashes the record coordinates on both create and reuse paths.
  • _write_fabrication_status accepts registry_record_id and registry_name optional params, writing them to DynamoDB when present.
  • process_event's COMPLETED write threads the record info from the run state.

service/agent_intake_single/tools/postfab.py

  • _resolve_registry_status takes registry_record_id and registry_name params and follows the three-path resolution.
  • _resolve_live_statuses reads the new fields from each job item and passes them through.

Tests (test_postfab_live_registry.py)

  • 7 new test classes: TestResolveByRegistryRecordId, TestResolveByRegistryName, TestFallbackSanitiseDisplayName, TestRecordIdFallbackToName.
  • Existing _stub_list calls updated to expect lowercased names matching the new fallback convention.
  • All fixtures use botocore Stubber + ParamValidator — no mocks that could drift from the API shape.

Testing

# service (474 passed)
cd service/agent_intake_single && PYTHONPATH=. pytest tests/ -v --tb=short

# arbiter fabricator (individual files pass; cross-file failures are pre-existing isolation issues)
cd arbiter/fabricator && PYTHONPATH=. pytest __tests__/test_store_agent_config_registry_properties.py -v --tb=short

Live verification

by_name("Arbiter Agent") = 'APPROVED'     # sanitised to 'arbiter-agent', matched
by_id("MshBnaCcFECO")    = 'APPROVED'     # exact GetRegistryRecord

…tised name when reading build status

The fabrication status check (postfab._resolve_live_statuses) passed the
job row's DISPLAY name (e.g. 'Arbiter Agent') as the registry name filter
value. The AgentCore Registry API rejects names containing spaces or
special characters with ValidationException, so every live-status read
failed and the stale snapshot was used instead.

Three-path resolution:
1. registryRecordId (new field on the job row) -> GetRegistryRecord (one
   call, exact). The fabricator now captures the record id from
   store_agent_config_registry via _RegistrationRunState.agent_record_info
   and writes it to the COMPLETED status row.
2. registryName (new field) -> ListRegistryRecords with the stamped
   sanitised name (the exact name the registry record was created with).
3. Fallback for pre-fix rows: sanitise the display name with
   sanitize_registry_name().lower() (same function the fabricator uses
   to derive record names) before passing it to the filter.

The raw display name is never passed to the name filter.

Changes:
- arbiter/fabricator/index.py: _RegistrationRunState gains
  agent_record_info dict; store_agent_config_registry stashes
  (record_id, registry_name) on both create and reuse paths;
  _write_fabrication_status accepts registry_record_id and registry_name;
  process_event's COMPLETED write threads them from the run state.
- service/agent_intake_single/tools/postfab.py: _resolve_registry_status
  takes registry_record_id and registry_name params with the three-path
  resolution; _resolve_live_statuses reads the new fields from job items.
- tests: 7 new test classes covering by-id, by-name, sanitised-fallback,
  and GetRegistryRecord-failure-to-name-fallback paths.
  Existing tests updated: _stub_list calls use lowercased names to match
  the new sanitise-and-lowercase fallback convention.

Live-verified: _resolve_registry_status('Arbiter Agent', '',
registry_record_id='MshBnaCcFECO') -> 'APPROVED'; by sanitised name ->
'APPROVED'.
@gibbsie
gibbsie merged commit 536090f into main Oct 26, 2026
15 checks passed
@gibbsie
gibbsie deleted the fix/intake-status-by-record-id branch October 26, 2026 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant