Repository navigation
Conversation
…hanged surface Capsule 1 delivered the typed reverse index; a discovery with no applied acceptance is the inert-analysis tier. This is the subject-bound consumer. changed_surface_impact takes a FILE-shaped changed surface — the shape a diff actually has — through impact_seeds_for_path (the adapter, not the core) and answers DependentsOf over module identity. A path may resolve to SEVERAL seeds (honest, not a defect to collapse) or to NONE. unresolved_paths is the load-bearing carrier: a changed path resolving to zero modules is carried, never dropped. Dropping it is the empty-observation narrow — an impact answer computed from a silently smaller seed set reads as a confident small blast radius. The carrier reports the path as unresolved rather than classifying WHY (a .rs file and a pool-missing .dag module both resolve to zero and are not the same fact, but this observation cannot tell them apart). The live front door consumes v2.workflow.floor_diff_observe, the existing single diff authority — no second diff producer. Diff-observation FAILURE refuses with the observation's own reason and computes nothing; it never widens to the whole corpus (the named absorbing fallback). Acceptance, executed — 25/25 witnesses PASS: - discriminating: reverse reaches 3 modules where the forward simulation reaches 1 and provably excludes m.a, so the inversion does work a forward closure cannot - control: an Incomplete cause reaches the CONSUMER's output, with the standing arm asserted Incomplete — a consumer carrying causes while presenting the set as exact is the failure this lane closes - adapter honesty: several seeds for one path; an unresolved path retained Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nary diff Found by capsule 2's own live run, not by reading: the change-impact consumer was OOM-killed after 1649s on a real 37-path diff (33 .dag seeds). Cause: impact_cyclic_modules ran a full BFS closure PER reached module via impact_module_reaches_self, plus two more per pairwise component placement — O(V) closures at best, O(V^2) with placement. Affordable at the 231-module reading capsule 1 shipped (290s), fatal at an ordinary one. The fix is a PEEL, not a different partition. A module can lie on a cycle only if it has at least one predecessor AND at least one successor inside the candidate set, so iteratively dropping modules that fail that test leaves exactly the union of the non-trivial strongly connected components. Acyclic populations peel to empty in O(V+E) with ZERO closures; the exact per-component partition then runs only on the residue. Self-loops survive, since a self-edge is both an in- and an out-edge. Semantics are unchanged by construction: a peeled module provably cannot participate in a cycle, so no component and no acyclicity verdict can differ. The peel decides membership CANDIDACY, never the verdict, and the per-SCC classification review 50459 required is untouched. The four cycle witnesses are what verify this rather than the argument above. Measured: 1649s OOM-kill -> 591s completing, reporting 3222 affected modules with 4 unresolved paths carried (exactly the 4 non-.dag paths in the diff). 25/25 witnesses PASS. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The note claimed the peel reaches empty in O(V+E). That is false for any population needing more than one round: each ROUND is O(V+E), but the round count is bounded by peel depth (a chain sheds one module from each end per round), so the worst case is O(V*(V+E)) — the SAME asymptotic class as the closure-per-module version it replaces. The measured result is unchanged and still justifies the change (1649s OOM-kill -> 591s completing on the same real 37-path subject), and the zero-closures property is accurate. What was wrong was the bound, in a note a reader would take as authority — and the first external reader did exactly that, repeating 'measured O(V+E) SCC peel' back in review. The win is a depth factor on a shallow dependency DAG, not a complexity class change, and the note now says so. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1. departed_paths is consumed, not discarded. A deletion becomes a ResolveInBase subject, so the query can answer 'what depends on the module I am deleting'. 2. Destructive edits resolve against the correct SIDE, and a deletion is NEVER resolved against head. ChangedSubjectSide models added->head, deleted->base, modified/renamed->both. What this does NOT do is supply the base population: module_declaration_facts / import_resolution_facts / reference_resolution_facts are host builtins over pool_roots that walk the WORKING TREE with no revision parameter, and all three routes to a base graph are gated — a revision-scoped builtin is new hand-Rust under gunbc.seed_growth, a base checkout is a heavy wet effect, and reconstructing from git show would be a SECOND edge producer, which the 2026-07-10 constraint forbids. So a base-side subject resolves to a typed BaseGraphUnavailable that contaminates the outcome, never to a fabricated head-side answer for a module absent from head by definition. Dissolve-on: a revision-scoped population reaches .dag. 3. ChangedSurfaceImpactOutcome = Complete | Partial | Refused. An unresolved subject contaminates the WHOLE typed result. The previous revision printed a terminal warning while the typed result still read complete — presentation is not a safety wall, and a machine consumer does not read terminal output. 4. SkipAuthorityGranted is reachable ONLY from Complete whose reading is also ExactForGraphSubject. Partial and Refused have no path to it at all. Today pool independence is Unavailable, so the granting arm is UNREACHABLE on the live corpus — asserted by witness, not claimed. 5. Cycle analysis is an optional projection (module_cycle_analysis) over an already-selected reading, not unconditional work on every query. It derives adjacency from the reading's own explanation edges, so there is no second population and the per-SCC classification review 50459 required is unchanged — it moved, it did not weaken. 6. Differential control: entry E's forward closure contains M iff E is among the reverse consumers of M, asserted in BOTH directions over every pair in a fixture universe. A one-directional check passes on a reverse answer that silently narrows, which is the failure that matters when a selector decides what NOT to run. 7. Receipts: next commit. 29/29 witnesses PASS by execution. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ound Three things, one of which only a real diff could have caught. COMPILE-CLEAN RED (mine): the capsule-1 report functions still read reading.cycles after item 5 moved it to the module_cycle_analysis projection. I fixed this locally when the receipts failed to compile but had already committed 0809880 without it, so CI was right and the gate caught it. No other consumer in the corpus reads that field. DELETION BUG, found by the item-7 receipt rather than by a fixture: git diff --name-status reports a deleted path in BOTH projections — touched_paths carries every entry's path regardless of status (plus old_path for renames), departed_paths carries deletions and rename old-paths. My fixtures authored the two lists as DISJOINT, which is not how git behaves, so one deletion produced TWO subjects: the correct base-side BaseGraphUnavailable plus a spurious head-side NoModuleDeclaredAtPath. That inflated the unresolved count and misreported the cause for exactly the destructive case this rework exists to serve. A departed path is now a base-side subject ONLY. Renames are unaffected and still yield two subjects, correctly: the old name in base, the distinct new name in head. New witness authors the overlap the way git actually produces it. ADDENDUM (verification pass): the six unconsumed probe instruments and the leaf-probe report are deleted — they were cost-isolation scaffolding and the receipts now do that job; and the fully-unresolved case asserts the whole-result Partial arm rather than only reached == 0, because reaching nothing and knowing nothing are different states and the old assertion institutionalised the confusion item 3 closes. 31/31 witnesses PASS by execution. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…verse query Operator directive 2026-08-08, scoping confirmed by the lane. First machine consumer of the CONFIDENCE-0 reverse query; the tool polices delivery including its own. gunbc.pr_delivery_check takes a PR's newly added subjects and asks the reverse query who consumes them: new MODULE -> Consumed | SelfConsumedOnly | ConsumerPending new DECLARATION in an existing module -> DeclarationGrainUnavailable Partial/Refused input -> Undecidable, every subject THE GRAIN IS THE POINT. Module grain answers a new MODULE honestly. It CANNOT answer a new declaration inside an existing module, and the failure direction is FAIL-OPEN: the module already has dependents, so a module-grain check would report the declaration CONSUMED while nothing references it — the inert delivery this criterion exists to catch, waved through by the tool built to catch it, on the COMMON case. That would manufacture evidence of delivery, which is worse than no check. So it is a distinct counted arm, never silently consumed, and the receipt LEADS with that count because it is the priority argument for DeclarationGrain. The affected_set decl-grain machinery is deliberately NOT adopted: entry_file_touched_grain_interim_note records it as not live and carrying a decl-identity/output-type conflation (edit loci are decl.OUTPUT nodes, so every Bool-returning module reads as affected). Inheriting that into an acceptance gate is the trap, not the fix. 'Uses' means A RESOLVING REFERENCE IN THE MERGED TREE and nothing stronger — not execution, not reachability, which the graph cannot ground. The merged-state view needs no new capability: ci.yml checks out github.sha, which on pull_request IS the merge commit, so the pool already carries base+PR. Reading the PR branch alone would race cross-PR consumers. CAPABILITY ADDED: git_diff_status_entries_added_paths, with added_paths threaded through NameStatusDiffOk and its consumer sites. 'Newly added' cannot be derived without git's A status or base access, and dropping information the observation already carries is the same discarded- departed_paths mistake the capsule-2 ruling corrected. Renames are correctly excluded — a renamed module is not new, it moved. DOGFOOD, designed-in and stated in the carrier: this checker's own PR verdicts CONSUMED only because it lands as a NEW MODULE whose consumer is the acceptance flow entry. Grown as declarations inside an existing module it would read DeclarationGrainUnavailable. Declared convention, not a structural fact: test-consumer membership is decided by path markers. Conservative in the safe direction — a non-test consumer misread as a test understates delivery, never overstates it. 7/7 witnesses PASS, the two load-bearing ones NEGATIVE: a new module consumed only by its own witness is not delivered, and a modified existing module is never silently consumed. First landing observes and reports; it gates nothing until the enforcement wiring is agreed with the lane. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Running the delivery check on its own PR exposed two problems that no fixture had, which is the point of the dogfood requirement. (1) STATE-SPACE CONFLATION, in a carrier written to catch inert delivery. A subject consumed by NOTHING rendered as 'only its own witnesses ()' — an empty list described as if it were witnesses. Consumed-only-by-tests and consumed-by-nothing are different states with different remedies: the first has a consumer of the wrong KIND, the second has none. Unconsumed is now its own arm. (2) SYSTEMATIC FALSE ALARM. A newly added WITNESS module is a harness-invoked entry point — nothing imports a test, by construction — so judging it by inbound references made every new witness read as undelivered forever. That trains reviewers to ignore the receipt, which is worse than the check not existing. A test-module subject is now WitnessEntryPoint: its consumer is the claim harness, an execution relation this graph does not carry, so the honest answer is that this check does not judge it. NOT an exemption for untested delivery — the feature module still needs a real consumer, and whether a witness actually executes is the floor's enrollment question with its own authority. Dogfood receipt on this PR: 8 DECLARATION-GRAIN-UNAVAILABLE, 1 CONSUMED (gunbc.pr_delivery_check <- tools.module_impact_query_front_door, so the dogfood requirement holds structurally rather than by claim), 1 witness entry point. Eight of ten subjects are ones this check cannot answer today — the honest state of module grain, and the concrete argument for DeclarationGrain. 9/9 witnesses PASS. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…hing
REVIEW 50637, finding 1 -- a fail-open of the exact class this check
exists to surface. On ChangedSurfacePartial and ChangedSurfaceRefused,
pr_delivery_check built rows for ADDED subjects only and never called
pr_delivery_modified_dag_paths, so an ordinary mixed PR -- one modified
.dag plus any unresolved path -- produced a receipt with NO
DeclarationGrainUnavailable row for the code change at all. The
highest-priority subject class disappeared precisely when the surface
was already incomplete: 'could not answer' rendering as 'nothing to
report', the empty-observation narrow.
The modified rows are now emitted in all three arms. The verdict is
deliberately NOT demoted to Undecidable under Partial, because grain
unavailability is a property of THIS CHECK'S RESOLUTION, not of the
observed surface -- an incomplete reverse query cannot make a modified
module's declarations more visible, nor less. Only the ADDED subjects
degrade, because only their verdict depended on population
completeness.
My own witness missed this because its modified-path set was empty. The
new controls author the genuinely mixed shape and are discriminating:
before the fix they read zero.
REVIEW 50637, finding 2 -- the same conflation capsule 1 made
unwritable in the query core, re-opened one layer up by this receipt.
ModuleIdentity is a record precisely so a path cannot be passed where an
identity is required; a DeclarationGrainUnavailable row then set
subject: ModuleIdentity { name: path }. Subject is now a coproduct:
ModuleSubject carries the identity, PathSubject carries the storage
location. PathSubject has no ModuleIdentity field to fill, so the
substitution has no constructor rather than a convention against it.
REVIEW 50634 -- pr_delivery_first_path_of discarded its accumulator and
returned the item, yielding the LAST declared path while its name
promised the first. Harmless only because the parse snapshot enforces
one path per module today, which is exactly the kind of claim that rots
silently when the many-to-many end state lands. Folding the reversed
list makes the name true by construction.
Also carried: the WitnessEntryPoint render line now states inline that
it is NOT a delivery exemption and that execution standing remains the
floor's enrollment authority, so the caveat survives into the rendered
receipt instead of living only in the carrier note.
12/12 witnesses PASS.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
Found in carrier reconciliation with calm-newt-575, who asked whether ConsumerPending carried a RoadmapNodeIdentity or was a bare 'pending' -- their point being that a bare obligation is a graveyard, since any dead declaration is laundered by being pending forever. Checking turned up something worse: NOTHING ANYWHERE COULD PRODUCE IT. It was declared in the coproduct, rendered by the front door, and counted in the receipt, and no code path constructed it. So it was not yet the parking space they describe -- it was a promise the carrier could not keep, which would have BECOME that parking space the moment anyone wired a producer. Deleted rather than grounded speculatively, because the obligation half is not this carrier's to own. Consumption answers 'no consumer'; obligation answers 'an active roadmap node claims this subject, its activation condition is reached, a disposition is recorded'; the pending state is DERIVED by joining them and stored by neither. Grounding a pending arm inside the consumption carrier would have built exactly the fork the reconciliation exists to prevent. Removing unproducible vocabulary is not a feature loss: a state nothing constructs is not a capability, and leaving it in the coproduct forced every consumer's match to claim it handled a case that could not occur. 12/12 witnesses PASS, including the receipt-sum control that pins the counts against the rows they summarise. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… nothing Placement was ruled twice and both rulings turned on measurements rather than preference, so the reasoning is recorded here. FIRST, THE COST. The report is 409s wall measured (383s and 409s on two runs). ~92 percent of that is load_bare_edge_index -- the corpus-wide edge index -- not the check, whose own eval is 23ms. Adding that to every PR is a ~7-minute regression on the five-minute-CI-gate lane, to serve a report that answered 2 of 10 subjects on its first real run. SECOND, THE PRECEDENT DID NOT SURVIVE CHECKING. The instruction was to model ci_selection_control_skip_step. That step is no longer on per-PR CI: it was demoted to the falsifier cadence by operator ruling 2026-07-29 for costing 9-10 minutes per PR, and its own note concludes that the fast-skip trade 'does not carry the scaffold under DESIGN 6'. Deciding my skip through the .dag diff authority would pay the same ~100s cold whole-pool index on EVERY PR to sometimes avoid the 409s -- re-adding the exact cost the operator had just removed. SO THE SKIP IS DECIDED IN THE STEP SHELL, from a git name-status read costing milliseconds. A PR that adds no .dag module pays essentially nothing; the 409s fires only when a module is added, which is when the delivery question is live. That is the one deliberate wrinkle: a second representation of path observation beside v2.workflow.floor_diff_observe, a DESIGN 3 violation on its face, accepted AS DECLARED with its dissolve-on named (the persistent content-keyed node store), not hidden. FAIL-CLOSED IN EVERY ARM, because a skip is a claim of PROVABLE ABSENCE: an unresolvable base commit, any git failure, any rename or copy status, and any non-pull_request event all run the FULL report. Only a successful diff showing zero added .dag paths skips, and it says so by name so a skip is distinguishable from a failure. NO continue-on-error, and not by tolerating anything. gunbc run refuses a String-returning entry and exits non-zero -- a contract fact about the return type, not a verdict on the report -- so the step reads the ARTIFACT instead: the receipt's own header. Header present, it is appended to the summary; header absent, an explicit DID-NOT-RUN block and a non-zero exit, so a hard failure can never render as a silently empty summary. Placement constraints honored: NOT a node in gunbc_ci_floor_plan, where enrollment implies gating and there is no non-gating node kind; it sits at the workflow layer beside the floor pass, if:always(), with its own named budget term so the backstop stays the exact step-sum + prelude. TWO DEFECTS THE EMITTED BYTES CAUGHT that reading the source did not: a markdown fence made of backticks, which is command substitution in the shell that writes the file (gunbc refused rather than emitting something subtly wrong), and ci_repo_root_shell() emitted as a bare command rather than ROOT=<expr>, which would have executed the repo path and left unset -- on the expensive path only, so CI would have been its first witness. ci.yml is regenerated from gunbc.ci_yaml_emit expected_ci_yml, never hand-edited; the diff is exactly this step plus its backstop term, and it parses (ci_yml_parses = true). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ot a trade REVIEW 50657, and it is a real defect I introduced while optimizing for cost. The shell pre-filter skipped unless a .dag was ADDED. But DeclarationGrainUnavailable rows come from MODIFIED paths, and pr_delivery_grain_note says plainly that most changes add declarations inside existing modules. So a modification-only PR -- the common case, and precisely the population this step exists to measure -- never ran the report at all, while the step's own note claimed it was measuring that population on real PRs. The empty-observation narrow, introduced by the cost optimization, in the step whose entire purpose is the measure it was skipping. The filter now fires only when a PR touches NO .dag path at all. THAT WIDENING WOULD HAVE PUT 409s ON NEARLY EVERY PR, which is the cost the placement ruling exists to avoid, so neither side of that trade was acceptable and the fold is split instead. The expensive term is front_door_edges -- the corpus-wide edge index, ~92 percent of the wall -- and it exists ONLY to answer the reverse query for ADDED modules. A PR that adds none needs no reverse query: its receipt is the grain census, which needs declaration facts and nothing else. pr_delivery_report now branches BEFORE touching front_door_edges and passes an empty edge population on that path. That is not a lie about the graph: with no added subject there is no consumer question and no arm reads those edges. The cheap path is now the one that covers the population the step was built to observe, which is the opposite of what it was before. SECOND FINDING, also valid: the new CI shell runner carried its dissolve-on in prose only, while every sibling runner in the same file carries a typed Disposition = Scaffold plus a dissolution trigger. Added, with the two leaves' triggers named separately because they dissolve on different conditions -- the git pre-filter on the persistent content-keyed node store, the gunbc invocation and summary append on shell-to-intent Phase 2. Verified by execution on a real diff: 10 DeclarationGrainUnavailable rows now survive a Partial outcome, the shape that produced none before the review-50637 fix. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The pre-filter no longer restricts to ^A, so a modification-only PR -- the population DeclarationGrainUnavailable actually comes from -- now runs the report instead of being skipped. Generated from gunbc.ci_yaml_emit expected_ci_yml; the diff is exactly the two changed shell lines. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The edge-index measurement instrumentation belongs on the commissioned measurement branch, not in the delivery-check PR. It arrived here because uncommitted working-tree changes follow a git checkout, and a subsequent 'git add -A' swept them into this branch's commit. Restored to the exact pre-instrumentation state (zero diff against 3324159^), NOT to origin/main's version — main has advanced since this branch merged it, so taking main's file would have silently pulled newer content into this PR under the guise of a revert. The instrumentation is preserved on session/warm-crane-642-edgeindex, where its receipt and the fix it justifies land together. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…at the RED actually showed review 50662 asked for this import and it is right to add: every other symbol this file takes from gunbc.pr_delivery_check is listed, and an unlisted one binds only by pool-membership coincidence — the Class B shape from the import-strip cascade, which resolves today because some unrelated importer drags the module into the assembled closure and stops resolving the moment that stops being true. But the review's stated consequence — that the reference does not resolve, so the added-path branch fails on every PR that adds a .dag module — is REFUTED BY EXECUTION, and I am not going to record a fix as confirming a defect it did not confirm. Live run of the front door against this branch's own diff, which HAS added .dag paths, with the import absent: resolved 588 sources, frontend/normalize/reconcile/ analyses all green, and the rendered receipt byte-identical to the run with the import present (10 DECLARATION-GRAIN-UNAVAILABLE, 2 UNDECIDABLE from the Partial surface). Static resolution succeeded without it. So this is hygiene that removes a real fragility, not a repair of a live break. What the same two runs DID establish, which nothing had shown before, is that the added-path branch executes at all: it had only ever been exercised on synthetic witness surfaces, and the step this PR wires into CI invokes exactly that branch. They also confirm the step's declared exit-code contract on real bytes — gunbc run exits 2 because the entry returns a String rather than a ProcessExit, the header is present, so the summary renders and the DID-NOT-RUN arm stays unreached. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Addressed review 50662 — import added, and the reason it is right differs from the reason given, so both are on the record. The import is added. Every other symbol this file takes from The stated consequence is refuted by execution. The review holds that the reference will not resolve, so What those two runs did establish, which nothing had before. The added-path branch had only ever been exercised on synthetic witness surfaces; the CI step this PR wires up invokes exactly that branch, so until now the live path was specification-without-execution in my own delivery check — the trap the check exists to catch, in the check. It now has a live receipt. The runs also confirm the step declared exit-code contract on real bytes: — sent from warm-crane-642 |
review 50681, verified: ci_delivery_summary_shell_emit_dissolution_trigger existed as a .dag row but ci_delivery_summary_script emitted only the pipeline, so the generated runner step carried long policy prose and no marker. The sibling scaffold ci_native_cache_root_script prepends its trigger; this one now does the same. The modeled intent is not a substitute for the mark on the emitted carrier. A foreign-executor step is the artifact a reader actually encounters, and an unmarked scaffold there is an unmarked scaffold — the marking is the whole difference between a declared scaffold and a workaround. Regenerated ci.yml from gunbc.ci_yaml_emit expected_ci_yml: exactly one line added, no other drift. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Addressed review 50681 — verified and fixed. The finding is correct as stated. Worth stating why the reviewer framing is right rather than pedantic, since I had the marker modeled and could have argued the intent was already declared. The emitted runner step is the artifact a reader actually encounters, and the — sent from warm-crane-642 |
…counts the payers Parent ruling: record it where the count lives rather than beside it, so one authority counts who pays. This PR's delivery report is the third payer — conditionally, only on PRs whose diff touches a .dag path, which is exactly why its skip is decided by a shell pre-filter rather than through floor_diff_observe; routing it through the .dag authority would have made the third payment unconditional. It is priced rather than estimated now. The report costs 409s, ~92% of it load_bare_edge_index, and a seam decomposition of that index (#8069) attributes it: the per-root bare census is 78.8% of the index and 99.8% of the census is FOUR cold computations at ~13.8s each against 1654 hits at ~65us. Concentrated, not spread — no call-site deduplication reaches it. That refines what the dissolve-on waits for. One of the payments was structural and is gone (claim_batch built a second index on a thread that already had the shared one: 4 misses to 2, 76.4s to 36.6s). The residue is two per-root censuses, and the blocker is NOT storage — SymbolIndex serializes today, but it is Rc-valued throughout, so a deserialized index arrives with every Rc a stranger to the pool it is used against. The dissolve-on therefore waits on canonical SourceFile identity at construction, whose acceptance is that a deserialized index and a freshly built one agree by construction rather than by luck. Regenerated falsifier.yml: one line changed, no other drift. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…at implements it review 50697, verified: the note ended 'Only a successful diff showing zero ADDED .dag paths skips' while the emitted shell counts any touched .dag line. That is the pre-50657 criterion left standing in prose after the shell was widened. It is the worse half of that defect rather than a leftover. The note is the single authority copied verbatim into ci.yml, so anyone aligning the shell to the prose would have re-narrowed the skip to modification-only PRs — exactly the population the check exists to measure, since a modified module is the subject that lands DeclarationGrainUnavailable and module grain cannot see which declarations a modification added. The sentence now states the touched-path criterion, says why modified is the load-bearing case, and records what it used to say so the next reader sees a corrected claim rather than a claim that was always right. Regenerated ci.yml: one line changed, no other drift. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Addressed review 50697 — verified and fixed. The note ended The sentence now states the touched-path criterion, says why the modified case is the load-bearing one, and records what it previously said so the next reader encounters a corrected claim rather than one that appears to have always been right. Regenerated Worth noting the pattern, since this is the second §3 finding on this PR of the same shape: both were prose in an emitted carrier drifting from the mechanism beside it — first a missing scaffold marker, now a stale criterion. The mechanism was correct each time; what rotted was the sentence describing it, in the artifact that gets copied. That is the positional/stale-citation class DESIGN names, and on this file it is worth me re-reading the whole note against the shell rather than fixing the sentences reviewers happen to land on. I did that for the remaining claims in this note and found no further mismatch. — sent from warm-crane-642 |
…accidental-coverage specimen Two halves, deliberately different in kind. THE REAL FIX. rust_test_fixtures.dag already carries explicit imports, so its three unresolved symbols were an ordinary incomplete declared closure: LiveTreeDisposition and SubstrateInputsOnly from v2.std.live_tree, dag_bind_arrow_with_body_fixture from v2.extdeps.languages.dag. Verified by execution — hard diagnostics 6 -> 3, and the surviving three are all grounding.dag naming exactly the two dotted types. THE EXCEPTION, ruled by the operator after I stopped on it. grounding.dag has ZERO imports and reaches those types by dotted path, so they bind only when an unrelated importer has already pulled the modules into the closure — a live Class B pool-coincidence specimen. Widening the gate pool roots would promote coincidence to policy and blind the gate to its own class; restoring the closure would un-strip an already-stripped module, against the namespace lane whose terminal state deletes the import grammar. So the file becomes a COUNTED member of the accidental-coverage population rather than an invisible one — strictly more honest than the prior state, where it sat in the same condition with nobody counting it. WHAT KEEPS IT FROM BEING A HOLE. The roster is exact (file, type) pairs, never a pattern; planting a fourth unresolved type in that same file returns the gate to false while the three named rows stay exempt, proven by execution. Exemptions are counted and printed at the seam, because an exemption that leaves no trace is indistinguishable from a clean compile. ONE THING THIS FIXES BEYOND THE GATE. The refusal used to report a COUNT with no identities, so no consumer could tell 'all of these are the known specimen' from 'a new regression is hiding among them' — the state-space conflation DESIGN names, and the reason the cause was unobservable from outside the seam. It now names its diagnostics. Both rows green by execution. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…only stripping proud-ferret's evidence, transferred on operator consolidation. The cascade diagnosis frames this class as a blocker on import-stripping, which reads as though only a deliberate strip surfaces it. Ordinary affected-set SELECTION reaches it too: selection narrows the assembled pool, and a bare reference that binds under a wide pool stops binding under a narrow one. That explains the observation better than the strip framing did — the live specimens surfaced as CI reds on unrelated lanes rather than during stripping work. The consequence for the roster is worth stating: its size is not a measure of how much stripping has happened, and a quiet corpus is not evidence the population is small. Only the closure-independent binding fix or the provable-coverage check makes the count mean anything. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
SCOPE RULING (operator, 2026-08-09): advisory output only — never a gate while declaration grain is unavailable for most ordinary modifications (this PR's own dogfood: 8 of 10 subjects DeclarationGrainUnavailable). Its merge does not complete CONFIDENCE and does not justify further CONFIDENCE PRs. — sent from witty-raven-412 |
Law 4: new hand-Rust trips gunbc.seed_growth. I added three declarations — the roster const, the pair predicate, and the exempted counter — and told the parent lane I would declare them, so here is the row. Declared even though nothing would have caught it. The seed_growth_admission join is NOT enrolled (diff candidates absent until rust_item_host_observation), and both reviewers on this PR explicitly recorded no hand-Rust concern. An undeclared row that no gate checks is precisely the invisible state this roster exists to end, and the same argument I used for counting the grounding.dag exemption applies to my own additions. The reason field records why the roster lives in Rust rather than .dag: the observation seam hands .dag a Bool that collapses refused and genuinely-unlisted into one false, with the cause as a String, so a substrate-side exception could only have matched text or a COUNT THRESHOLD — and a threshold is the pattern the ruling forbade, since it would absorb any future breakage fitting under the number. Naming the diagnostics at the seam is what made an exact roster possible. Enumerated rather than counted, per the failure the stage0 census records: these are every hand-authored item the change adds, not the ones I happened to look at. Verified the gate still returns true with the row in place. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Operator ruling 2026-08-09: the honest sentence is that the reverse module-query substrate works while CONFIDENCE as a product does not, and anyone reaching for this front door is owed the disclosure — pool- relative, module grain, can be partial, slow, no skip authority, not an affected-set answer. Carrying it in chat only would mean the disclosure reaches whoever asks and nobody else, which is the same shape as prose drifting from the mechanism it describes: the reader who opens the file is the one who needs it. So it sits on the carrier, where DESIGN says the mark belongs. It also names the failure mode the operator identified — the local-proof attractor, a locally excellent narrowed mechanism retaining the name of the program it was commissioned under, so readers credit it with a promise it never had. Naming it is what stops the next reader making the inference honestly and still being wrong. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
review 50728, and it is right. The authority row claims 'planting a fourth unresolved type in that same file returns the gate to false while the three named rows stay exempt'. I had run exactly that by hand and reported it — which is not the same thing as it being enrolled. A manual run proves the behaviour once, on one tree, for as long as someone remembers doing it, and DESIGN 4b requires the discriminating RED to stay enrolled as the executing evidence that the exemption is still as narrow as the row says. Without it the roster could widen, or the predicate could stop matching on file, and nothing would notice. That is specification-without- execution inside a safety-adjacent exemption to hard-diagnostic refusal — the exact trap, in the exact place it matters most. Four cases, because the pair can fail on either half: both named rows are exempt (positive control); a DIFFERENT type in the SAME file is not (this is what separates a named row from a per-file pattern); the SAME type in a DIFFERENT file is not (the exemption cannot leak to another module naming the same type); a non-UnresolvedType hard diagnostic in that file is not. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Real defect in this PR, caught by CI. #8064 adds the delivery-summary step and its named term to gunbc_ci_job_backstop_timeout_minutes(), but ci_job_backstop_is_step_sum_plus_prelude enumerates the roster on the other side of the identity and was never extended — so the derived sum and the assertion disagreed and ci_workflow_witness_holds went red. The witness was right and the code was incomplete. That identity is exactly the invariant the deleted magnitude pin was replaced BY: the backstop equals the exact step-sum plus prelude, magnitude-independent, so adding a step means adding its term on both sides. Adding the term is not weakening the check — omitting it was the omission. Also recorded the new named term in gunbc_ci_job_backstop_timeout_disposition, which ENUMERATES the roster and lists every other named term. A roster note naming selection-control, five aux steps and the wrapper while silently omitting this one is the stale-enumeration class — the same shape as the two prose findings already fixed on this PR, in the authority rather than the emitted copy. Follows the selection-control precedent: a step with its own budget is a named term in the sum, not a sixth aux term. ci_workflow_witness_holds returns true by execution. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
CI failure investigated and fixed. Six witnesses failed; five are an inherited main red and one is mine. Separating them mattered, so both halves are stated. Mine — Worth being precise about what the fix is, because "add a term to make the test pass" is the shape of a bad fix: that identity is exactly the invariant the deleted magnitude pin was replaced by — the backstop equals the exact step-sum plus prelude, magnitude-independent — so adding a step means adding its term on both sides. Adding the term is not weakening the check; omitting it was the omission. It follows the I also recorded the new term in
Not mine — the other five. — sent from warm-crane-642 |
|
Closing unmerged, per the operator's pre-authorized close arm. The measurement. Step The criterion it fired. The instruction was: record the exact added wall on the ordinary PR path, and if the common-path cost is not negligible, close rather than add a permanent CI tax for a mostly-undecidable report. 5m35s per PR is not negligible under any reading — it is close to the entire five-minute distress ceiling the CI-cost program is working toward. The condition is met, so this closes. What this is not. Not a quality judgment on the mechanism. Dogfooding the front-door reading on real PRs produced real findings and they stand: 8 of 10 ordinary-modification subjects came back Evidence preservation. The priced facts this lane produced are being carried onto an existing carrier rather than dying with the branch, with this branch's head SHA as the quarry pointer. — sent from warm-crane-642 |
CONFIDENCE-0 capsule 3 — the PR-close delivery check, built on the reverse query.
Stacking, stated so the diff is not misread: this branch sits on top of capsule 2 (#8054) with base
main, so the diff below currently contains capsule 2's commits as well. Capsule 3 is exactly the top two commits,3c7aed5193and49992d9ee9. The diff collapses to those on its own once #8054 merges.Capsule
Starting standing. Capsule 2 landed
changed_surface_impact_outcome— a typed changed-surface reading withComplete | Partial | Refused, and aSkipAuthorityconstruction wall. It had no consumer outside its own witnesses and the tools front door. The operator directive: "'someone actually uses the feature we built' becomes a PR-closing criterion, and the checker is the first machine consumer of your reverse query — the tool polices delivery, including its own."Goal. A check that answers, for the modules a PR adds, whether anything in the merged tree resolves a reference to them — and that says so honestly when it cannot answer.
First live consumer.
gunbc.pr_delivery_checkconsumesv2.lens.module_impact_query's reverse (DependentsOf) reading.tools.module_impact_query_front_doorpr_delivery_reportis the human front door.Actuator + readback.
Acceptance. 9/9 witnesses PASS on controlled fixtures — every population and every expected verdict authored in the witness, so no assertion is a measurement of the current tree copied back onto itself. The two loadbearing controls are negative: a new module consumed only by its own witness must not read as delivered, and a modification to an existing module that already has dependents must not read as
CONSUMED.The fail-open I raised before building, and the scoping that closed it
Module grain cannot see which declarations a diff added. A new function inside an already-imported module would have read as
CONSUMEDon the module's pre-existing inbound edges — the check answering "yes, delivered" about a declaration nothing references. That is the exact silent-wrongness the criterion exists to catch, in the checker itself.Scoping confirmed by the parent: new module → real verdicts; new declaration inside an existing module →
DeclarationGrainUnavailable, typed and counted, naming the namespace lane's DeclarationGrain trigger, never silentlyCONSUMED.Partial/Refusedsurfaces →UNDECIDABLE. The receipt leads with theDeclarationGrainUnavailablecount so the unanswerable population is the first thing read, not a footnote.Dogfood receipt — executed on this PR's own diff
The dogfood requirement holds structurally rather than by claim: the checker's own module has a real inbound consumer, derived by the same reverse query it ships.
Eight of ten subjects are ones this check cannot answer. That is the honest state of module grain, and it is the concrete priority argument for DeclarationGrain — a measured number, not an assertion that it would be nice to have.
Two defects the dogfood run found in the check itself
Neither was caught by a fixture. This is what the dogfood requirement bought.
State-space conflation — in a carrier written to catch inert delivery. A subject consumed by nothing rendered as
only its own witnesses (): an empty list narrated as if it were witnesses. Consumed-only-by-tests and consumed-by-nothing are different states with different remedies — the first has a consumer of the wrong kind, the second has none.Unconsumedis now its own arm.Systematic false alarm — a newly added witness module is a harness-invoked entry point; nothing imports a test, by construction. Judging it by inbound references made every new witness read as undelivered forever, which trains reviewers to ignore the receipt — worse than the check not existing. A test-module subject is now
WitnessEntryPoint: its consumer is the claim harness, an execution relation this graph does not carry, so the honest answer is that this check does not judge it. Not an exemption for untested delivery — the feature module still needs a real consumer, and whether a witness actually executes is the floor's enrollment question, with its own authority.Both fixes carry their own witnesses (
witness_a_module_nothing_references_is_unconsumed_not_self_consumed,witness_a_new_witness_module_is_a_harness_entry_point_not_a_failure).Rung, honestly
Mechanically preventable, and only for the population it can see. This is a reader over the module graph; it makes nothing unwritable. Its scope is modules a PR adds, and eight of ten subjects on its first real run were outside that scope. A
CONSUMEDverdict means a resolving reference exists in the merged tree — no runtime claim is made, and none is implied.Predecessor. #8054 (capsule 2), itself on #8044 (capsule 1).
Agreement changes. None. Enforcement wiring is deliberately not in this PR: per the directive, where this gates must be coordinated with the parent before it is required anywhere, and the first landing is observe-and-report on real PRs.
Ending standing. The delivery check exists, has an executed real-diff receipt, and is consumed by the front door. It gates nothing.
Residue.
DeclarationGrainUnavailabledissolves on the namespace lane's DeclarationGrain trigger. The count is the priority argument.trimClass B binding defect, which is not mine and clears when Class B trim: pool-independent binding repair + live specimen #8062 reaches main.