Adds state-hub/scripts/consistency_check.py with C-01 through C-12 checks: bidirectional file↔DB validation, --fix for auto-fixable issues, --all for all repos, --json output, exit codes 0/1/2. MCP tool: check_repo_consistency(repo_slug, fix=False) Makefile: check-consistency, fix-consistency, check-consistency-all, fix-consistency-all Auto-fixes applied across all repos: - C-09: activity-core-foundation + activity-core-triggers-ops repo_id → activity-core - C-04: railiance phase-0-operational-baseline status → completed - C-05: railiance phase-0 title synced from file - C-10/C-11: task status drifts resolved; state_hub_task_id injected into CUST-WP-0006 and CUST-WP-0007 task blocks Remaining orphans reported for human review: repo-integration-activity-core, infospace-s3-closeout, testdrive-jsui-publication, staged-promotion-lifecycle, three-phoenix-ha-cluster, current-env-safety-net. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7.4 KiB
id, type, title, domain, status, owner, topic_slug, repo_slug, created, updated, state_hub_workstream_id
| id | type | title | domain | status | owner | topic_slug | repo_slug | created | updated | state_hub_workstream_id |
|---|---|---|---|---|---|---|---|---|---|---|
| CUST-WP-0007 | workplan | GEMS Migration — Three-Pass State-Hub Alignment | custodian | completed | custodian | the-custodian | the-custodian | 2026-03-02 | 2026-03-02 | 22e18151-fc83-438c-b732-10e056e64a20 |
CUST-WP-0007 — GEMS Migration: Three-Pass State-Hub Alignment
Implements the migration decided in CUST-WP-0006. Fixes all structural inconsistencies identified in the GEMS audit (I-1 through I-6) in three independently releasable passes.
Decisions resolved: DEC-GEMS-001 (Option C), DEC-GEMS-002, DEC-GEMS-003, DEC-GEMS-004. DEC-GEMS-005 and DEC-GEMS-006 deferred.
Pass 1 — Fix Domain FK Inconsistencies
Scope: Resolve I-1 and I-6. No API breaking changes. Fixes observable dashboard domain-filtering bugs on EP/TD pages.
Alembic migration ID: e1f2a3b4c5d6 (down_revision: d3e4f5a6b7c8)
Task T01: Alembic migration — Pass 1
id: T01
status: done
priority: critical
assignee: custodian
state_hub_task_id: "1c21c419-30f8-4208-9a55-c2fd83d5005a"
Operations:
- Add
domain_idUUID FK (nullable) toextension_points - Add
domain_idUUID FK (nullable) totechnical_debt - Add
repo_idUUID FK (nullable) tocontributions - Backfill
extension_points.domain_idfromdomains.slugmatch - Backfill
technical_debt.domain_idfromdomains.slugmatch - Make
domain_idNOT NULL on both tables (all rows must be backfilled first) - Drop
domainString column fromextension_points - Drop
domainString column fromtechnical_debt
Task T02: Update ExtensionPoint and TechnicalDebt models
id: T02
status: done
priority: critical
assignee: custodian
state_hub_task_id: "fe4f5673-6053-404a-8930-4bc0c7d29fd9"
Replace domain: Mapped[str] with domain_id: Mapped[uuid.UUID] FK +
domain: Mapped["Domain"] relationship. Add domain_slug property.
Task T03: Update Contribution model
id: T03
status: done
priority: high
assignee: custodian
state_hub_task_id: "c1ccf2ae-6241-4281-a443-12953796c1ee"
Add repo_id: Mapped[uuid.UUID | None] nullable FK to managed_repos.
Task T04: Update EP and TD routers
id: T04
status: done
priority: high
assignee: custodian
state_hub_task_id: "4997aa59-39c0-46d6-8c63-f13fffd8d6ea"
- Filter by
domain_idFK instead of domain string - Accept
domainslug in create/filter params, resolve todomain_id
Task T05: Update MCP EP/TD tools
id: T05
status: done
priority: high
assignee: custodian
state_hub_task_id: "50fdb7ee-91c3-4a2b-be27-e171c144aec6"
register_extension_point and register_technical_debt still accept
domain as a slug string. Router resolves to domain_id FK.
Task T06: Update EP/TD dashboard pages
id: T06
status: done
priority: medium
assignee: custodian
state_hub_task_id: "4b19bb95-7200-4fa4-a240-afe14012bafa"
extensions.md and techdept.md load domain list from /domains/ API and
use domain_id FK for filtering. Remove reliance on string comparison.
Pass 2 — Align Workstream with ADR-001
Scope: Resolve I-2. Breaking change to workstream schema. topic_id
becomes a nullable secondary annotation; repo_id becomes the primary FK.
Workplan frontmatter format gains repo_slug field.
Alembic migration ID: f2a3b4c5d6e7 (down_revision: e1f2a3b4c5d6)
Task T07: Alembic migration — Pass 2
id: T07
status: done
priority: critical
assignee: custodian
state_hub_task_id: "b34b6bb0-3968-464f-b340-389c4758821e"
Operations:
- Add
repo_idUUID FK (nullable) toworkstreams - Backfill
repo_idusing heuristic: workstream → topic → domain → first repo for that domain (adequate for current data; all custodian workstreams map to the-custodian repo) - For topics without a repo: leave nullable (MCP tooling handles this)
Task T08: Update Workstream model
id: T08
status: done
priority: critical
assignee: custodian
state_hub_task_id: "6f1fcf2c-824b-4e3e-884f-5e48b5dea51d"
Add repo_id: Mapped[uuid.UUID | None] nullable FK to managed_repos.
Keep topic_id as nullable secondary. Add repo relationship.
Task T09: Update workstream router and MCP tools
id: T09
status: done
priority: high
assignee: custodian
state_hub_task_id: "58a23afa-601a-40a5-b658-2603dc006d13"
create_workstreamMCP tool: add optionalrepo_id/repo_slugparam- Workstream read schema: expose
repo_idandrepo_slug - Dependency resolution in
state/summaryusesrepo.domainwhen available
Task T10: Update workplan frontmatter format
id: T10
status: done
priority: high
assignee: custodian
state_hub_task_id: "b0bf1338-b097-4130-ab18-95b4980cf551"
Add repo_slug field to ADR-001 workplan frontmatter spec. Update existing
workplan files (CUST-WP-0001 through CUST-WP-0006) to include repo_slug.
Task T11: Update Dependencies dashboard domain resolution
id: T11
status: done
priority: high
assignee: custodian
state_hub_task_id: "2a49ad8e-8d6d-4082-8833-a79d9ace0b34"
dependencies.md currently resolves domain via topicMap[w.topic_id]?.domain_slug.
Change to prefer wsMap[w.id]?.repo?.domain_slug when available.
Pass 3 — SBOMSnapshot Container
Scope: Resolve I-5. Adds sbom_snapshots as a container entity between
Repository and SBOMEntry. Enables snapshot history and diff queries.
Alembic migration ID: a3b4c5d6e7f8 (down_revision: f2a3b4c5d6e7)
Task T12: Alembic migration — Pass 3
id: T12
status: done
priority: critical
assignee: custodian
state_hub_task_id: "1ab3b919-64f7-432a-b173-7b66b042955f"
Operations:
- Create
sbom_snapshotstable (id, repo_id FK, snapshot_at, source, created_at) - Add
snapshot_idUUID FK (nullable) tosbom_entries - Backfill: for each (repo_id, snapshot_at) group in sbom_entries, create one sbom_snapshots row; set snapshot_id on all matching entries
- Make
snapshot_idNOT NULL onsbom_entries - Consider: drop
repo_idfromsbom_entries(reachable via snapshot)
Task T13: Add SBOMSnapshot model
id: T13
status: done
priority: critical
assignee: custodian
state_hub_task_id: "015462de-2095-48ff-8b2e-3f53e41dfe32"
New model api/models/sbom_snapshot.py with FK to managed_repos.
Task T14: Update SBOMEntry model
id: T14
status: done
priority: critical
assignee: custodian
state_hub_task_id: "f0f1a2d0-f0a3-45a4-ad10-b86f32849a84"
Add snapshot_id FK to sbom_snapshots. Update repo relationship to go
via snapshot.
Task T15: Update SBOM router and ingest API
id: T15
status: done
priority: high
assignee: custodian
state_hub_task_id: "2a90b3f7-4938-4235-8ab6-1f9ad9cb06a7"
- Ingest creates/finds a snapshot record, then creates entries under it
- New endpoints:
GET /sbom/snapshots/,GET /sbom/snapshots/{id}/ - Existing
GET /sbom/still returns flat entries for backward compatibility
Task T16: Update MCP ingest tool and SBOM resources
id: T16
status: done
priority: high
assignee: custodian
state_hub_task_id: "081ef72e-e19c-4938-b6de-c0c17b98d99a"
ingest_sbom_tool returns snapshot_id in result. New MCP resource:
state://sbom/snapshots/{repo_slug}.
Task T17: Update SBOM dashboard
id: T17
status: done
priority: medium
assignee: custodian
state_hub_task_id: "5626cd89-ff77-4f45-90e6-2059673e4247"
sbom.md "By Repo" section adds a snapshot history row showing ingest dates
with package count delta from previous snapshot.