Repository navigation
Bind documentary system references to live declarations - #8066
Conversation
The repository already generates DESIGN.md, ROADMAP.md and every registered plan with a byte-drift wall. That wall proves checked-in Markdown equals prose stored in .dag; it does not prove the prose equals the standing of the implementation. gunbc.design_document builds its sections from literal p(text:) and li(text:) strings, so a sentence there can become false without any file it describes being touched, and nothing in the tree can see it. Carriers: - gunbc.design_truth: subject identity, contract, contract proof, realization binding, production-consumer reachability, and the standing fold (Declared | Realized | RealizedContractProofUnmeasured | Ambiguous | ContractChanged | Retired | Unreadable). No stored status field and no rendered standing string. - gunbc.design_projection: every sentence is a function of typed rows; no parameter accepts a status, so a migrated section cannot build one. - gunbc.design_subject_registry: the declared subject population, one subject. - dag/test/claim/design_truth_witness_test.dag: every arm in discriminating pairs. First migrated thread: the "gated on the namespace lane's containment SymbolIndex" claim. That gate is discharged (v2.std.symbol_index is consumed by v2.compiler.resolve lookup_symbol_index_atom_identity on the production path) and the sentence had FOUR copies -- design_document (hence DESIGN.md), the plan doc, and two in wave2_prep_design. All four retired; DESIGN.md renders the binding from the registry. Stage A itself remains open and is unchanged. Also deletes the superseded six-step five-minute-CI sequence from design_document, citing gunbc.roadmap_authority five_minute_ci_gate_program_note by symbol only. #8034 recut that note, so a draft that summarized its contents was already false on main. DeliverableSubject wraps RoadmapNodeIdentity rather than minting a fifth subject key space; a scheduled subject with an independent key has no representation. RealizationContractProof is a coproduct rather than a required digest: the first draft carried 0000000000000000, a fabricated value in the position whose job is to record what a realization was proven against. Measurement exceeded a 45-minute executor budget (CONFIDENCE-0 measured the same class at 409s wall, ~92% in load_bare_edge_index), so the state is typed with a named trigger instead of guessed. Contract-drift detection is not active for the production row; the mechanism is proven on fixtures. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Correcting my own PR description before review starts — two defects, both mine. 1. DESIGN.md in this branch is stale relative to its generator, so the drift gate will red. I edited 2. The evidence claim in the description is overstated and I am withdrawing part of it. The description says 14 witnesses were green before the They passed on the pre-refactor run, so the likely cause is the refactor, but 'likely' is not a result. The run also died on a 45-minute executor timeout caused by an unpaged Until that lands, the honest state of this branch is: 10 witnesses confirmed green by execution, 5 unverified, DESIGN.md drift-red. Please weight the description's Evidence section accordingly — the reachability, retirement, identity-fork, unmeasured-proof, dissolution and registry-citation controls are confirmed; the contract-digest discrimination is not. |
|
Witness result: all 15 green by execution. Withdrawing the doubt I raised, not the caution. The five unaccounted witnesses were re-run in isolation against the same head and all five PASS: Combined with the 10 from the prior run at the same head, 15 of 15 are confirmed green, including the moved/unmoved contract pair — the discriminator the Evidence section rests on. The What I will not do is invent a cause for the earlier silence. The run that lost them died on a 45-minute executor timeout triggered by an unpaged DESIGN.md drift: the regenerated five-minute sentence has been applied locally and a regeneration run is verifying that the committed bytes now equal the generator output. Pushing once that returns clean — I am not pushing a fix I have not verified, which is the same discipline that kept the placeholder digest out of this branch. Corrected standing of the branch: 15/15 witnesses green by execution; DESIGN.md drift fix verified-and-pushed pending. The Evidence section in the description is accurate as written. |
The prior commit edited gunbc.design_document's five-minute sentence without re-running main_wet, so the committed DESIGN.md was stale relative to its generator and the drift gate would have redded. Regenerated bytes verified by executing the generator and comparing output. Worth recording rather than fixing silently: the PR that removes stale generated-doc drift shipped stale generated-doc drift, and the byte-drift wall is what caught it. That is the wall working, and it is also why the projection half matters -- the drift wall proves the Markdown equals the .dag prose, and only a derived projection can make the .dag prose track the tree. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every authored row now receives a disposition, and three fields that were stored-but-unread became load-bearing. - design_standing no longer filters rejected realizations out before counting them. It partitions admitted/rejected and disposes of both: DesignMixedValidAndInvalidRealizations, DesignRealizationUnreachable, DesignRealizationUnreadable. The previous fold was the empty-observation narrow this carrier exists to close, and the witness that blessed it asserted DesignDeclared for an unreachable realization; it now requires a refusal. - Retirement cardinality is counted, not list_head-selected, in BOTH folds. Two retirements is DesignDuplicateRetirement / AuthoredDuplicateRetirement; a retirement beside a live realization is DesignRetiredWithLiveRealization rather than a silent DesignRetired. - design_contract_for_subject returned Optional, so two registered contracts for one subject produced the first one and made standing depend on authoring order. It returns DesignContractSelection with ContractSubjectUnregistered and ContractSubjectDuplicated as separate arms, and drops a bare `filter` that was the capture hazard this module's own note documents. - DeclarationPresence replaces the Optional presence probe: module-absent maps to unreadable rather than absent, because on a corpus that does not whole-tree-resolve it is routinely a universe hole, and DeclarationAbsentCondition was reading every failure arm as DissolutionReached. - evidence enters admission. A realization whose named witness declaration does not resolve is refused (DesignRealizationEvidenceMissing / EvidenceUnreadable) rather than reading DesignRealized off an unread field. Presence is not execution and the note says so. - design_projection_note no longer calls itself a construction wall without qualification: the guarantee is scoped to sections that consume the projection, and corpus-wide coverage is monotone. 21/21 witnesses green by execution, including four new controls for the dropped-row class and one for evidence admission. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
All six blocking findings are real and all six are fixed. Pushed; 21/21 witnesses green by execution (12 + 10 in two runs, the retirement control re-run after its expectation changed). 1 — the fold dropped broken rows before counting. Confirmed, and it is the sharpest of the six: I built the empty-observation narrow I have been citing all session, inside the carrier that exists to close it, and wrote a witness that blessed it ( 2 — retirement cardinality. Counted in both folds. Two retirements → 3 — dissolution conditions fail open on ambiguity. 4 — 5 — 6 — "construction wall" overstated. Corrected in On the required finish line — I am declining part of it, with reasons. You wrote that #8066 should not merge while its production standing depends on acknowledged fail-open module-grain reachability, and that the migration should complete in this PR. I accept the defect and decline the remedy, on three grounds:
What I have done instead is make the gap typed, cited, and dissolving: If you want the merge blocked until the declaration-grain authority lands, say so and I will park the branch rather than argue it — but that authority is a separate lane with a separate owner, and this PR does not get better by waiting inside it. — sent from calm-newt-575 |
|
Moved to draft under the new operating guidance, before the approvals could carry it to merge. This PR is a specimen of the local-proof attractor, and I should name it rather than wait to be told. The stale-doc problem I was given is: a documentary claim in this repository cannot be false without something reddening. What I hit was the missing declaration-grain reachability authority. What I then did is the exact sequence in the ruling — typed the missing capability ( Displacement standing, in the denomination that matters:
The witnesses are green by execution and the carrier is real, but by the merge-is-evidence-not-acceptance rule this is support delivered, outcome displacement ~0. There is no executing consumer, so the mechanism cannot yet make any document wrong. What it would take to earn the outcome, so the residue is a bounded list rather than a gesture: a gate that runs Holding here for the operator's ending sentence rather than opening a successor. — sent from calm-newt-575 |
Steps 1-2 of the absorbed blocker. One shared authority answering "which declarations reference this declaration", built once per run, cheap point queries thereafter -- the doc standing gate consumes it now and the PR delivery check consumes it later, neither approximating it and neither forking it. v2.lens.witness_cost_locality states in tree that module grain IS the declared precision frontier and fn-grain reachability does not exist. That is what this replaces. Module grain is fail-open exactly where both consumers care: a declaration added to a module that already has dependents reads as reached while nothing references it. Design decisions worth the review time: - Resolution is over the DECLARATION universe (decl_facts), not the BINDING universe (SymbolIndex.global_bare). Same shape, different populations: the binding index contains parameters and let binders, so it would refuse edges the declaration question determines. The reconciliation trigger is named -- the namespace lane's containment tree makes both one index. - Consumers are carried as DeclarationIdentity, not DeclarationRef. The only composer in tree runs ref -> qualified name; splitting on the final dot to manufacture the inverse would be a second naming scheme decided by punctuation, and would fabricate a module_path for any name the guess did not fit. So the index keys on qualified names and the point query composes. - A subject the fact pack does not declare REFUSES (SubjectUniverseAbsent) rather than answering zero consumers. Those two states license opposite actions -- the first is a universe hole, the second licenses deleting the declaration. - An ambiguous short name lands in unresolvable and credits NEITHER candidate. Undecidable edges are carried, never dropped: a dropped edge renders as "no consumers", and the action taken on that answer is deletion. - Self-references are excluded. Every fn names itself at its own definition site and host-backed stubs call themselves, so counting them would give every declaration a consumer by construction. The residual imprecision is stated rather than asserted absent: a local binder colliding with a declaration name produces an edge no reference justifies. Fail-open, narrow, and it dissolves on the same containment-tree walk. 6/6 witnesses green by execution, each asserted against its opposite population. The orphan control is the one the predecessor cannot reach: fx.m.orphan sits in a module that has dependents. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The floor's naming-hygiene walk refused v2.lens.decl_consumption for carrying no construction_justification, which is the DESIGN §5/§6 gate asking why the bad-state class is not made unwritable instead. Classified WallAfterGrounding, dissolving to SingleAuthority, because the honest answer is neither of the easy ones. The class -- an authored declaration no live consumer reaches -- is DECIDABLE given the declaration universe, so calling it RatchetForever would be the "never" trap §5 names. But consumption is not a LOCAL property: a declaration and its consumer can be authored in one commit, so nothing at the authoring site separates the good case from the bad one and only a whole-corpus read decides it. A whole-corpus read is a reader. It becomes a wall on the same trigger the module's other two residues name -- the containment tree as single naming authority, at which point a reference is an edge in a structure the compiler already walks and an unreached declaration is refusable the way an unbound name already is. One grounding closes the universe fork, the binder-shadowing imprecision, and this justification together. 6/6 witnesses still green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Step 3. A root is a declaration nothing needs to reference, so the purpose law cannot read an unreferenced declaration as dead without first knowing the root set. Joining an explicit ScheduleWitnessEntry roster to decl_facts by (rel_path, name) yields real declarations -- legitimate rather than positional citation in disguise, because the roster natively carries a path and a name and this join CONSUMES the identity it already has instead of inventing one. The finding is what is NOT enumerable. Since the discovery flip most executing witnesses are found by a host-side directory scan (CiSpec.discovery_scan_dirs) that no .dag fold can read, and generated-artifact producers are dispatched by a match in gunbc.generated_artifact_emit rather than listed as declaration names. So the root set is structurally incomplete here. decl_consumption_roots therefore returns RootEnumerationPartial and CANNOT return RootsEnumerated today -- the total arm exists because the population becomes enumerable once discovery is declared, and it is deliberately unselectable until then. An empty root set must read as unknown, never as proof a declaration is unrooted, because that conclusion licenses deleting live code. Its witness asserts the partial arm even though every roster entry resolved, which is the claim that matters: the incompleteness is not about the roster. 7/7 witnesses green by execution. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The floor's lens_registry_completeness_holds_live failed: a new module under v2.lens.* is either an enrolled enforcing lens or a declared infra row, and mine was neither. That is the inert-lens backstop working -- coverage by illusion is the tier where machinery exists and nothing gates on it, so an unenrolled module must red. Enrolled as infra rather than as a LensIdV0 row, and the distinction is the real one rather than the convenient one: decl_consumption produces facts (subject in, consuming declarations out) and carries no verdict and no remedy. The verdict lives in the documentary standing fold that consumes it. That is precisely the class v2.lens.module_impact_query already occupies one grain up, whose row says the same thing -- a reading with no verdict authority. The generic infra dissolve_on applies unchanged: the row deletes if the module ever gains its own verdict authority or leaves src/v2/lens. Verified by executing the failing witness, not by reasoning about the roster. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Conflicts: # dag/gunbc/doc_graph_roots.dag
…ion/calm-newt-575 # Conflicts: # DESIGN.md
* Derive documentary standing from typed rows instead of authored prose The repository already generates DESIGN.md, ROADMAP.md and every registered plan with a byte-drift wall. That wall proves checked-in Markdown equals prose stored in .dag; it does not prove the prose equals the standing of the implementation. gunbc.design_document builds its sections from literal p(text:) and li(text:) strings, so a sentence there can become false without any file it describes being touched, and nothing in the tree can see it. Carriers: - gunbc.design_truth: subject identity, contract, contract proof, realization binding, production-consumer reachability, and the standing fold (Declared | Realized | RealizedContractProofUnmeasured | Ambiguous | ContractChanged | Retired | Unreadable). No stored status field and no rendered standing string. - gunbc.design_projection: every sentence is a function of typed rows; no parameter accepts a status, so a migrated section cannot build one. - gunbc.design_subject_registry: the declared subject population, one subject. - dag/test/claim/design_truth_witness_test.dag: every arm in discriminating pairs. First migrated thread: the "gated on the namespace lane's containment SymbolIndex" claim. That gate is discharged (v2.std.symbol_index is consumed by v2.compiler.resolve lookup_symbol_index_atom_identity on the production path) and the sentence had FOUR copies -- design_document (hence DESIGN.md), the plan doc, and two in wave2_prep_design. All four retired; DESIGN.md renders the binding from the registry. Stage A itself remains open and is unchanged. Also deletes the superseded six-step five-minute-CI sequence from design_document, citing gunbc.roadmap_authority five_minute_ci_gate_program_note by symbol only. #8034 recut that note, so a draft that summarized its contents was already false on main. DeliverableSubject wraps RoadmapNodeIdentity rather than minting a fifth subject key space; a scheduled subject with an independent key has no representation. RealizationContractProof is a coproduct rather than a required digest: the first draft carried 0000000000000000, a fabricated value in the position whose job is to record what a realization was proven against. Measurement exceeded a 45-minute executor budget (CONFIDENCE-0 measured the same class at 409s wall, ~92% in load_bare_edge_index), so the state is typed with a named trigger instead of guessed. Contract-drift detection is not active for the production row; the mechanism is proven on fixtures. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * chore: regenerate drifted generated artifacts (ci auto-heal) * Regenerate DESIGN.md after the five-minute citation rewrite The prior commit edited gunbc.design_document's five-minute sentence without re-running main_wet, so the committed DESIGN.md was stale relative to its generator and the drift gate would have redded. Regenerated bytes verified by executing the generator and comparing output. Worth recording rather than fixing silently: the PR that removes stale generated-doc drift shipped stale generated-doc drift, and the byte-drift wall is what caught it. That is the wall working, and it is also why the projection half matters -- the drift wall proves the Markdown equals the .dag prose, and only a derived projection can make the .dag prose track the tree. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Close the six blocking review findings on the design-truth carrier Every authored row now receives a disposition, and three fields that were stored-but-unread became load-bearing. - design_standing no longer filters rejected realizations out before counting them. It partitions admitted/rejected and disposes of both: DesignMixedValidAndInvalidRealizations, DesignRealizationUnreachable, DesignRealizationUnreadable. The previous fold was the empty-observation narrow this carrier exists to close, and the witness that blessed it asserted DesignDeclared for an unreachable realization; it now requires a refusal. - Retirement cardinality is counted, not list_head-selected, in BOTH folds. Two retirements is DesignDuplicateRetirement / AuthoredDuplicateRetirement; a retirement beside a live realization is DesignRetiredWithLiveRealization rather than a silent DesignRetired. - design_contract_for_subject returned Optional, so two registered contracts for one subject produced the first one and made standing depend on authoring order. It returns DesignContractSelection with ContractSubjectUnregistered and ContractSubjectDuplicated as separate arms, and drops a bare `filter` that was the capture hazard this module's own note documents. - DeclarationPresence replaces the Optional presence probe: module-absent maps to unreadable rather than absent, because on a corpus that does not whole-tree-resolve it is routinely a universe hole, and DeclarationAbsentCondition was reading every failure arm as DissolutionReached. - evidence enters admission. A realization whose named witness declaration does not resolve is refused (DesignRealizationEvidenceMissing / EvidenceUnreadable) rather than reading DesignRealized off an unread field. Presence is not execution and the note says so. - design_projection_note no longer calls itself a construction wall without qualification: the guarantee is scoped to sections that consume the projection, and corpus-wide coverage is monotone. 21/21 witnesses green by execution, including four new controls for the dropped-row class and one for evidence admission. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Land the declaration-grain consumption authority Steps 1-2 of the absorbed blocker. One shared authority answering "which declarations reference this declaration", built once per run, cheap point queries thereafter -- the doc standing gate consumes it now and the PR delivery check consumes it later, neither approximating it and neither forking it. v2.lens.witness_cost_locality states in tree that module grain IS the declared precision frontier and fn-grain reachability does not exist. That is what this replaces. Module grain is fail-open exactly where both consumers care: a declaration added to a module that already has dependents reads as reached while nothing references it. Design decisions worth the review time: - Resolution is over the DECLARATION universe (decl_facts), not the BINDING universe (SymbolIndex.global_bare). Same shape, different populations: the binding index contains parameters and let binders, so it would refuse edges the declaration question determines. The reconciliation trigger is named -- the namespace lane's containment tree makes both one index. - Consumers are carried as DeclarationIdentity, not DeclarationRef. The only composer in tree runs ref -> qualified name; splitting on the final dot to manufacture the inverse would be a second naming scheme decided by punctuation, and would fabricate a module_path for any name the guess did not fit. So the index keys on qualified names and the point query composes. - A subject the fact pack does not declare REFUSES (SubjectUniverseAbsent) rather than answering zero consumers. Those two states license opposite actions -- the first is a universe hole, the second licenses deleting the declaration. - An ambiguous short name lands in unresolvable and credits NEITHER candidate. Undecidable edges are carried, never dropped: a dropped edge renders as "no consumers", and the action taken on that answer is deletion. - Self-references are excluded. Every fn names itself at its own definition site and host-backed stubs call themselves, so counting them would give every declaration a consumer by construction. The residual imprecision is stated rather than asserted absent: a local binder colliding with a declaration name produces an edge no reference justifies. Fail-open, narrow, and it dissolves on the same containment-tree walk. 6/6 witnesses green by execution, each asserted against its opposite population. The orphan control is the one the predecessor cannot reach: fx.m.orphan sits in a module that has dependents. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Classify decl_consumption's construction justification The floor's naming-hygiene walk refused v2.lens.decl_consumption for carrying no construction_justification, which is the DESIGN §5/§6 gate asking why the bad-state class is not made unwritable instead. Classified WallAfterGrounding, dissolving to SingleAuthority, because the honest answer is neither of the easy ones. The class -- an authored declaration no live consumer reaches -- is DECIDABLE given the declaration universe, so calling it RatchetForever would be the "never" trap §5 names. But consumption is not a LOCAL property: a declaration and its consumer can be authored in one commit, so nothing at the authoring site separates the good case from the bad one and only a whole-corpus read decides it. A whole-corpus read is a reader. It becomes a wall on the same trigger the module's other two residues name -- the containment tree as single naming authority, at which point a reference is an edge in a structure the compiler already walks and an unreached declaration is refusable the way an unbound name already is. One grounding closes the universe fork, the binder-shadowing imprecision, and this justification together. 6/6 witnesses still green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Enumerate roots at declaration grain, and type what is not enumerable Step 3. A root is a declaration nothing needs to reference, so the purpose law cannot read an unreferenced declaration as dead without first knowing the root set. Joining an explicit ScheduleWitnessEntry roster to decl_facts by (rel_path, name) yields real declarations -- legitimate rather than positional citation in disguise, because the roster natively carries a path and a name and this join CONSUMES the identity it already has instead of inventing one. The finding is what is NOT enumerable. Since the discovery flip most executing witnesses are found by a host-side directory scan (CiSpec.discovery_scan_dirs) that no .dag fold can read, and generated-artifact producers are dispatched by a match in gunbc.generated_artifact_emit rather than listed as declaration names. So the root set is structurally incomplete here. decl_consumption_roots therefore returns RootEnumerationPartial and CANNOT return RootsEnumerated today -- the total arm exists because the population becomes enumerable once discovery is declared, and it is deliberately unselectable until then. An empty root set must read as unknown, never as proof a declaration is unrooted, because that conclusion licenses deleting live code. Its witness asserts the partial arm even though every roster entry resolved, which is the claim that matters: the incompleteness is not about the roster. 7/7 witnesses green by execution. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Enroll decl_consumption in the lens registry as a fact producer The floor's lens_registry_completeness_holds_live failed: a new module under v2.lens.* is either an enrolled enforcing lens or a declared infra row, and mine was neither. That is the inert-lens backstop working -- coverage by illusion is the tier where machinery exists and nothing gates on it, so an unenrolled module must red. Enrolled as infra rather than as a LensIdV0 row, and the distinction is the real one rather than the convenient one: decl_consumption produces facts (subject in, consuming declarations out) and carries no verdict and no remedy. The verdict lives in the documentary standing fold that consumes it. That is precisely the class v2.lens.module_impact_query already occupies one grain up, whose row says the same thing -- a reading with no verdict authority. The generic infra dissolve_on applies unchanged: the row deletes if the module ever gains its own verdict authority or leaves src/v2/lens. Verified by executing the failing witness, not by reasoning about the roster. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP recut: delete design_truth chain and decl_consumption; bind documentary refs * wip: single-line data initializers * wip: logical qualified names; retire the prose-substring control * wip: escape the interpolation brace exposed by the new import edge * chore: regenerate drifted generated artifacts (ci auto-heal) * wip: regenerate DESIGN.md from the ref rows * Repair the stale citations the recut left behind The #8066 recut deleted design_truth, design_subject_registry and design_projection but left four paragraphs citing them, including one that claimed to name only a single symbol while naming three that no longer existed. Also homes the three body-lowering DeclarationRef rows once instead of twice, and drops the out-of-scope five-minute roadmap ref from the general-body-producer bind. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Strip the conflict markers the merge committed * chore: regenerate drifted generated artifacts (ci auto-heal) * Delete the machinery narration rather than replacing stale status with it Both repairs replaced a stale gate claim with prose describing the reference mechanism -- the same habit one level up. general-body-producer said it named no system while naming four, and wave2_prep claimed typed coverage it does not consume. Deletion is the durable form. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Register the 84 unbound plan documents at subject grain Each document names one primary_work plus the supporting authorities whose movement would make its purpose false -- not every system its prose mentions. Subjects were selected from a measured candidate manifest and every new reference resolves uniquely through v2.std.decl_ref_resolution. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Point the floor-materialization ref at the module name, not the file basename * Drop the bind whose decl_name literal trips the mock-corpus prefilter precompute_whole_tree_published_mock_keys selects declarer files by sf.content.contains("PublishedMockCase") and strict-resolves their closure under dag-only roots. A bind row naming that type as a document subject put the literal into doc_graph_roots.dag, which imports v2 modules -- unresolvable under dag-only roots, so the precompute errored and claim_batch exited 1. The row is removed rather than reworded: that document's subject was a single weak candidate and asserting a different one to dodge a substring match would be a workaround. The seed prefilter defect is reported separately -- its comment claims a false positive can only widen the closure, but a widened closure needing absent roots fails the build. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Decide mock-corpus declarers structurally, not by substring precompute_whole_tree_published_mock_keys selected declarer files with sf.content.contains("PublishedMockCase") and strict-resolved their closure under dag-only roots. The prefilter's comment argued a false positive was safe because it 'cannot fabricate a key' -- true about keys, false about builds: a dag/ module that merely MENTIONS the string and imports src/v2 has a closure that cannot resolve under those roots, so the precompute returned Err and the floor refused before running a witness. Observed by execution on this PR (run 31353487916). The substring scan stays as a candidate prefilter; the DECISION is now the exact type-annotation check that already existed downstream, hoisted ahead of the closure. An unparseable candidate refuses with a located cause rather than being dropped as clean. Controls, both executed: genuine declarers still yield 89 operation keys, and doc_graph_roots -- a v2-importing dag/ module -- now carries a note that mentions the type without declaring one, so restoring the substring shortcut reds the floor there first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Documents in this repository name the systems they discuss in prose, so a system can be renamed, deleted, or forked in two while every sentence describing it stays green. This binds those names to live declarations instead.
The measured specimen. The body-lowering paragraph named
v2.std.symbol_indexSymbolIndexas an open prerequisite gating Stage A. The prerequisite was discharged; the declaration existed the whole time; the sentence stayed. Nothing was wrong with the declaration, so no declaration-level check could fire — and the sentence was not a reference to anything, so no reference-level check could either. Four copies of that one claim were live across DESIGN.md and two plan documents.What this does
gunbc.documentary_refscarries one typedDeclarationRefper system a migrated paragraph names, and the paragraph renders its symbol text from those rows. A row typed beside a paragraph that independently spells the same name would be two representations of one fact, so the bytes come from the row.v2.lens.cited_symbol_resolution's denominator widens from hand-authored binds to hand-authored plus generated-document references. The population widened; no second resolver was written —v2.std.decl_ref_resolutionstays the single authority for what resolving a reference means, because a second algorithm that agrees today is a fork that disagrees later.docs/plans/general-body-producer-design.mdis enrolled as aHandAuthoredDocBindcarrying the same three systems.gunbc.roadmap_authorityfive_minute_ci_gate_program_note— rendered from its row, asserting nothing about its mutable contents.What this deliberately does NOT establish
A resolved reference proves the named system exists and is uniquely identified. It does not prove a production relationship — that a consumer invokes an implementation on a live path is a different claim needing an executing witness, and a reference population cannot carry it. Reference resolution is the honest rung here.
Product RED
documentary_refs_witness_testruns the perturbations againstcited_declaration_ref_refusal_count— the resolver the required gate itself calls, not a second one agreeing with it:Recut history
An earlier head of this branch built a documentary-standing subsystem (
design_truth,design_projection,design_subject_registry) and a declaration-grain consumption authority (v2.lens.decl_consumption). Both are deleted here, per operator ruling: the consumption module was not consumed by documentary standing or PR delivery on this branch, was knowingly binder-imprecise, and its root population was structurally always partial — it could not become an authority. The concrete stale-claim cleanup survives; the architecture does not.One repair that was not mine
gunbc.doc_graph_rootscarriedNativeBlocked{GeneralWitnessTargetModelUnavailable}unescaped in a dissolution string. It compiles on main only because nothing in that closure pulled the module in; the newdesign_document→documentary_refs→doc_graph_rootsedge exposed it as a parse-time undefined variable. Escaped rather than routed around — dodging it by dropping the import would have been the workaround DESIGN §5 names.