§2 — P1: Deprecation architecture (accepted names only) ✓ landed 2026-07-10
Quick status
| Item | Status | Commit |
|---|---|---|
| Export-time deprecation stubs + chain collapse + status mapping | ✓ shipped | bb76411e (codex) |
| Stage-at-supersession recording (both supersede sites) | ✓ shipped | bb76411e (codex) |
| ISN stub validation + successor-forward rendering | ✓ shipped | d5d3687 (ISN) |
| sn merge round-trip preserves stubs | ✓ shipped (tested) | bb76411e (codex) |
What shipped
- Export stubs (
export.py:_fetch_deprecation_stubs+_build_stub_entry): every superseded name that had reached the published bar emits astatus: deprecatedstub withsuperseded_by= the live successor resolved along theREFINED_FROM*chain — chains collapse A→B→C to a single A→C stub; successors outside the published set are skipped (no dangling pointers). Exported accepted names publishstatus: active(decision d-status-mapping); draft leaves the published vocabulary.deprecated_stub_countlands in.export_report.jsononly — the catalog manifest model stays closed. - Stage recording (
graph_ops.py, +24):superseded_from_stagewritten at both supersede sites. Drift adaptation:persist_refined_namecannot see the name-axis stage (edit.py flips the predecessor torefiningbefore persist), so it records the durable published proxydocs_stage='accepted'— stricter than the letter of the decision: a stub is emitted only for names that actually reached consumers; accepted-but-never-published renames emit nothing (decision d-dep-scope honoured in spirit and effect). - ISN side: models + SQLite schema already carried deprecated/superseded_by;
added the structural rule (deprecated ⇒ superseded_by present; resolution itself is P3's semantic check)
and successor-forward fields in
tools/fetch.py. Round-trip test proves stubs persist across build/read. - sn merge (post-catalog-import architecture):
read_pr_changesleaves unchanged stubs alone; docs edits on live names still flow.
Verification
- Test classes required by done-when all green: accepted rename → stub; draft rename → no stub
(
superseded_from_stage='accepted'Cypher gate); chain collapse; ISN validate on stub-bearing catalog; merge preserves stubs. Orchestrator re-ran independently: 17 passed (codex) + 5 passed (ISN). - Full suites at HEAD: ISN 1683 passed / 0 failed (the 3 failures P1 saw mid-flight were P3's in-progress
semantic.py state, since fixed). Codex blast-radius 130 passed / 1 pre-existing graph-marked failure
(
test_escalation_at_final_attempt: RefinedName now requiressegments; fixture drift predates P1, folded into P6). - Scope audit: commits touch exactly the allocated files; no AI trailers.