Orchestrata Ultimate › Plans › briefs › 2026-09-22-adr-0047-register-aware-adr-tooling

Brief: make the ADR tooling register-aware (execute ADR-0047)

Source: plans/briefs/2026-09-22-adr-0047-register-aware-adr-tooling.md at 8a2cb42ad · last changed 2026-09-22 · first committed 2026-09-22 · 105 lines.

Prose pending.

Plan text

Brief: make the ADR tooling register-aware (execute ADR-0047)

DESIGN_WAIVER: ADR-0047 (Accepted 2026-08-29). Scope is exactly that ADR's mandate: "ids match as zero-padded strings — ADR-0001 (factory register, docs/adr) and ADR-001 (project register, the wiki page) are different ids. register becomes a graph-node property; the gate matches (register, padded id); nothing renumbers."

GOAL

parse_adrs, ArchitectureWriter.upsert_architecture_decision, scripts/sync_architecture_to_graph.py --adrs and scripts/check_adr_graph_sync.py all key an ADR by (register, padded_id) so the two registers on the wiki page never collapse onto one integer.

FACTS (measured 2026-09-22)

FILES

DESIGN (settled)

  1. ParsedAdr gains two fields: register: str ("factory" when the heading id has 4 digits, "project" when it has 1–3 digits) and padded_id: str (the heading's digits verbatim, e.g. "0001" / "001"). number: int stays for callers that only need the integer. parse_adrs and parse_adr_file populate both; parse_adr_file (docs/adr files) is always factory.
  2. upsert_architecture_decision takes padded_id: str and register: str (keyword, required alongside adr_number); the node id becomes f"{project}:ADR-{padded_id}"; register and padded_id are written as node properties; adr_number stays as today. Every existing caller is updated; the immutability check is unchanged.
  3. sync_adrs passes register and padded_id through.
  4. The gate keys every corpus by (register, padded_id): load_repo_adrs (factory only, from filenames/headings), load_wiki_adrs (both registers, from headings), load_graph_adrs (reads n.register, n.padded_id; a node lacking them is reported as a LEGACY_UNKEYED violation naming its id and title, never silently binned). AdrSyncRow carries register and padded_id; output lines print ADR-<padded_id> prefixed by the register when it is project. A wiki project entry with no docs mirror is NOT a violation (the wiki is that register's file of record).
  5. Tests: extend the four test modules with real cases: a page holding ## ADR-001: and ## ADR-0001: with different titles parses to two entries with distinct (register, padded_id); the writer creates two distinct nodes for them on the real test graph and neither raises immutability; the gate on that fixture reports 0 violations; a legacy node without register surfaces as LEGACY_UNKEYED. Writer/gate tests use the real graph exactly as the existing tests in those modules do.

CONSTRAINTS

DONE WHEN

VERIFY (report verbatim)