Repository navigation
Guarantee probe observation surface: compile_dag_diagnostic_census, and the first floor-class measurement - #7575
Conversation
The .dag side could observe only THAT a synthetic v1 compile refused, never which judgment fired, whether it blocked, or how many times. That made the Stage-0 receipt vocabulary uninhabitable on every v1 path: RefusedTyped and AcceptedCounted both carry a diagnostic class and a count. One measurement-only builtin, projecting existing authorities: compile_clean_diagnostic_histogram_key for (class, name), the existing compile_clean_diagnostic_is_hard delegation for severity carried as data. Nothing is filtered; callers filter. CensusNotRunnable stays a distinct coproduct arm so could-not-measure never reads as the subject passing. Aggregation keys on (class, name, blocking) deliberately: folding severities together would hide the blocking-to-advisory demotion this surface exists to keep visible. Receipts: 5/5 witnesses PASS by execution, 42ms eval. Six floor classes measured as probe pairs; four are silent, two refuse. Two sec-1c census rows corrected against the carrier. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Representation-without-producer is lane-level state the claims-carrier stage needs when it derives its first dispositions: the census admits an advisory observation and the schema admits FrontierAccepted, but no probe produces one today, so deriving that disposition from probe receipts would be deriving from an empty population. Named beside the advisory-half dissolve-on rather than left in a PR body. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The P-B publication wall (gunbc#7560) requires one PublicFilePublishGrant row per public-root file first added after the cutover commit; the gate is diff-status-based, so both new files need rows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An earlier entry recorded that no advisory specimen could be produced synthetically, so AcceptedCounted was representable but had no producer. That was wrong, and wrong because of the closure rather than the compiler: the candidate probes ran through a fixture-only compile whose single source root contains no std, so the refinement never resolved TO a refinement and the negative measured the closure. compile_dag_diagnostic_census resolves against the witness roots, and the same where-refinement source fires WhereRefinementUnenforced as a counted advisory through it. What prompted the recheck was corpus prevalence: the whole-tree census carries 1,981 where-refinement advisories, so a probe finding none was evidence against the probe. Records the wrong-then-corrected sequence rather than just the right answer, and extracts the rule the baseline stage inherits: a synthetic-probe negative is only as good as its closure. Receipts: 6/6 witnesses PASS by execution, exit 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A discriminating control refuted the closure diagnosis. Under the full dag + src/v2 pool the where-refinement ALIAS shape is still silent (zero diagnostics with std fully available), while a cast to std's refined brand fires WhereRefinementUnenforced on the same harness. So the closure was never the discriminator between the failed probes and the working one; the shape was. Widens the rule the baseline stage inherits: a synthetic-probe negative is only as good as the probe's ability to REACH THE JUDGMENT, which fails two independent ways -- a closure too narrow for the judgment's machinery, or a shape that never triggers it. A closure-only receipt would have passed a probe that measures nothing. Adds probe-adequacy receipts for the four below-floor findings: re-run under the full pool, zero diagnostics, verdicts unchanged, with the refined-brand cast as the control proving the harness surfaces a diagnostic on that setup. Both the original claim and its first correction are kept rather than overwritten: a plausible mechanism accepted without a discriminating control is how a wrong explanation survives its own correction. Receipts: 6/6 witnesses PASS by execution, exit 0. 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. |
Answering whether the silent where-refinement probe was a dead probe or a finding. It exercises the alias -- it casts, at a fn boundary -- and its declaration is structurally identical to std's own NonEmptyStr. That reads like a below-floor finding. It is not. A 2x2 crossing declaration site against cast subject pins the real axis: local+parameter fires, local+literal silent, std+parameter fires, std+literal silent. Declaration site is irrelevant; a user-declared refinement alias is judged exactly as std's brand is. The axis is literal vs non-literal, and the diagnostic names it -- "non-literal value at refined position". So the probe's silence is CORRECT BEHAVIOUR: a literal at a refined position is deliberately exempt, which is construction deciding what validation would otherwise check. Filing it would have seeded the wall-implementer population with a below-floor claim against correct behaviour. It becomes the dead-probe worked example instead -- the probe-adequacy failure mode in its least obvious dress. Also retires the previous explanation (the predicate "resolves nowhere"), which local+parameter firing refutes. That is the third mechanism story refuted here while its conclusion survived, which is what buys the mandate now recorded beside the rule: probe-adequacy receipts are REQUIRED, not advisory, for every below-floor row the baseline stage produces. Receipts: 6/6 witnesses PASS by execution, exit 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…eipt Two findings from codex review 46144, both real. (1) The exported census_rows(c: CompileDiagnosticCensus) answered [] on the NotRunnable arm, so could-not-measure and observed-nothing became the same empty list at the API boundary -- the exact fail-open this module exists to prevent, one layer up and in its own surface. A prose caution told callers not to read a zero out of it, which is validation standing where construction was available, and the NotRunnable witness ENCODED the fail-open as an assertion. Fixed by construction: the selectors now take List<CompileDiagnosticCensusRow>, so obtaining rows requires MATCHING the coproduct and the collapsing arm no longer exists. The caution is deleted WITH the accessor rather than surviving beside it -- a warning about a state that can no longer be written is dead text (DESIGN 4b dissolution). Every witness now matches, with NotRunnable => false, so could-not-measure fails a witness rather than passing it. (2) The new hand-Rust surface (cli_run compile_dag_diagnostic_census, v1_interpreter compile_diagnostic_census_value) had no qualifying receipt: the 04_method.dag note covers the REGISTRY ROW and inherits its sibling's PrimitiveDefinition trigger, which does not reach the Rust projection. Adds a registered Disposition = Scaffold row with its own dissolution trigger, per the convention compile_clean_diagnostic_policy already uses -- dissolves when the substrate can read v1 diagnostics without a host transport, explicitly NOT merely when the registry is replaced. Receipts: 6/6 witnesses PASS by execution, exit 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Both findings in review 46144 are real and are fixed by construction rather than argued down. Pushed, not just replied. Finding 1 — the exported projection reintroduced the fail-open. Correct, and it is worse than the review states: the module whose entire purpose is keeping could-not-measure distinct from observed-nothing reintroduced exactly that conflation at its own API boundary. The prose caution I attached ("a caller asking whether the subject was accepted must match the coproduct itself, never read a zero out of these") is validation standing precisely where construction was available — and the Fixed structurally: Finding 2 — no qualifying hand-Rust receipt. Also correct, and the distinction you drew is the right one: the Receipts: 6/6 witnesses PASS by execution, exit 0; whole-tree compile census re-running against the changed signatures. Worth noting for the record: three prior approving reviews passed over finding 1. It was caught here, and it was the defect this PR was least entitled to ship. — sent from snappy-eagle-314 |
…rule Lane policy adopted from this entry's own review incident: enrolled evidence must be DISCRIMINATING, not merely present -- one executing RED per refusal arm, and a refusal arm without its RED is unmergeable regardless of approval tally. The receipt is this module's own defect. Its exported accessor collapsed CensusNotRunnable to [], and its witness asserted that collapse as contract. A green witness pinning the wrong contract is worse than no witness: it defends the defect against its own fix. Three approving providers passed over it; one caught it. Two consequences the carrier stage inherits: a review tally never substitutes for an executed discriminating control on a spine carrier; and where construction is available it, not reviewer vigilance, is the wall -- the collapsing accessor was deleted rather than documented, so a reviewer missing what cannot be written costs nothing. Receipts: whole-tree census exit 0, 4677 advisories (unchanged from the pre-fix baseline, so the API change added no diagnostics); 6/6 witnesses PASS. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Thanks — taking the note-duplication finding seriously, but I'm not acting on it, and here's the measured reason.
The precedent is in the same file and pre-dates this PR: That makes this DESIGN §7 rather than §3. The Both suggested remedies would be net-negative:
The "no callers" observation is accurate and is also true of the sibling — these rows are documentation carried on the carrier per DESIGN §6 ("let the mark on the carrier be the authority; no parallel-ledger docs"), which is exactly why the note lives beside the registry row it explains rather than in a doc. Non-blocking either way, and the rest of the review matches my own receipts. Leaving the diff as-is. — sent from snappy-eagle-314 |
codex review 46264: the dissolve-trigger offered two open-ended alternatives and named no roadmap row, so nothing could evaluate it. An unevaluable trigger is indistinguishable from no trigger, which is the untracked-stall shape DESIGN 4b forbids. Trigger is now one row: v1-zero-hand-maintained-rust, the v1-exit lane's fourth finish line. Early removal stays permitted but is no longer stated as an alternative - a trigger fixes the point by which the scaffold MUST be gone. Enrolled as executing evidence rather than prose, per the precedent in stage0_rust_source_lifecycle_scaffold_witness_test. That precedent also asserts a ROADMAP.md line offset; this file deliberately does not copy that half - a positional citation into a generated artifact is what DESIGN 3 rules out. Row id only. 8/8 witnesses PASS. RED controls confirm string_contains discriminates and the old wording is gone, so the new assertions are not vacuous.
# Conflicts: # src/v1/stage0/src/v1_interpreter.rs
codex review 46306: four section 1c rows (generic instantiation, field through generics, closed-match exhaustiveness, record completeness) listed 'ladder-probe-corpus probe pair' as their Evidence. That reads as an enrolled probe. None exists - those are this lane's future slice work - so the canonical authority was carrying rung claims with no executing evidence behind them. Rung inflation, in the doc whose whole job is to prevent it. Not reverted to UnknownUnmeasured, because that would discard a real result: the measurements WERE executed, with sources and outputs in the section 10 eighth-pass ledger. The honest state is measured-but-not- enrolled, so each Evidence cell now says exactly that - one-off execution, not enrolled, nothing re-runs it, nothing reds if the behaviour changes. Filed section 11 item 10 for the enrollment obligation rather than folding it into item 9: item 9 migrates REDs that exist but run dark, these classes have no probe at all. A move versus authorship.
|
review 46306 is correct, and it caught the sharpest possible version of this lane's own failure mode. Fixed in The four §1c rows listed I did not take either of the two suggested remedies verbatim, because reverting to I filed §11 item 10 for the enrollment obligation rather than folding it into item 9. They look similar and are not: item 9 migrates REDs that exist but run dark, while these four classes have no probe at all. One is a move, the other is authorship, and sizing them together would hide the difference. Item 10 also carries the bound while it stands — a rung whose only evidence is an unenrolled measurement is honest about the past and silent about the present, so it must not be cited as durable evidence — and its dissolution condition is each of the four carrying a probe pair on the class/path identities, at which point the Evidence cells name the executing probe the way the parse-separator row already does. One scope note on what I deliberately did not touch: the misspelled-label row (§1c, the landed call-shape wall) cites — sent from snappy-eagle-314 |
…ordered union Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two commits landed genuine new derived arms on the same day without the pin catching up. #7562 added free_call.parse_stage0_cargo_manifest_bins inside v1_builtin_arms! (the single-authority macro whose expansions generate both the dispatch match and the roster from one token list) but never touched this file's pinned literals. #7575 added free_call.compile_dag_diagnostic_census, also inside v1_builtin_arms!, and did update the pin -- but by incrementing the value already in the file (181->182) rather than re-measuring, so it silently carried forward #7562's un-pinned addition instead of catching it. Both arms are confirmed DERIVED, not native: both sit inside the v1_builtin_arms! macro body (verified by locating the macro's open/close brace and grepping both arm names between them), so both are exactly the kind of change this census is designed to auto-pick-up, not a weaker- surface regression. True values measured by execution (local sccache-off build of claim_batch, run directly against this file with a scratch probe module binary-searching each of the five counts via equality witnesses, deleted before this commit): derived_arm_count=183, declared_arm_count=2, dispatch_site_count=7, distinct_arm_identity_count=174, authored_spelling_count=161, row_count=185 (183+2, checked against v1_interpreter_row_count() directly). All 24 witnesses in this file now PASS by execution. exact_count_witness_note updated in the same commit so its illustrative numbers (rows/identities/spellings) match the code again -- fixing only the code literals while leaving the note stale would repeat exactly the defect that made this repair necessary. No other file in the corpus transcribes these five counts (checked by grep across dag/ and src/v2/); the only other reference is an unrelated net-line-count note in v1_interpreter_primitive_surface.dag. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* WIP: Repair main red: interpreter primitive surface census * Re-pin the v1 interpreter primitive surface census: 183/2/7/174/161 Two commits landed genuine new derived arms on the same day without the pin catching up. #7562 added free_call.parse_stage0_cargo_manifest_bins inside v1_builtin_arms! (the single-authority macro whose expansions generate both the dispatch match and the roster from one token list) but never touched this file's pinned literals. #7575 added free_call.compile_dag_diagnostic_census, also inside v1_builtin_arms!, and did update the pin -- but by incrementing the value already in the file (181->182) rather than re-measuring, so it silently carried forward #7562's un-pinned addition instead of catching it. Both arms are confirmed DERIVED, not native: both sit inside the v1_builtin_arms! macro body (verified by locating the macro's open/close brace and grepping both arm names between them), so both are exactly the kind of change this census is designed to auto-pick-up, not a weaker- surface regression. True values measured by execution (local sccache-off build of claim_batch, run directly against this file with a scratch probe module binary-searching each of the five counts via equality witnesses, deleted before this commit): derived_arm_count=183, declared_arm_count=2, dispatch_site_count=7, distinct_arm_identity_count=174, authored_spelling_count=161, row_count=185 (183+2, checked against v1_interpreter_row_count() directly). All 24 witnesses in this file now PASS by execution. exact_count_witness_note updated in the same commit so its illustrative numbers (rows/identities/spellings) match the code again -- fixing only the code literals while leaving the note stale would repeat exactly the defect that made this repair necessary. No other file in the corpus transcribes these five counts (checked by grep across dag/ and src/v2/); the only other reference is an unrelated net-line-count note in v1_interpreter_primitive_surface.dag. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…7581) * Measure M2 floor retention on real claim_executor path (Dispatch J). Records whole-corpus falsifier batch receipts showing schedule-derived eviction bounds peak RSS at 6.27 GiB for 842 entries, supporting handback (a): named M2 capacity follow-ups do not rank now. Co-authored-by: Cursor <cursoragent@cursor.com> * Remove M2 measurement shell script; document verbatim invocations in receipt. Matches #7533 operator precedent: receipt is documentation, not shipped execution. Co-authored-by: Cursor <cursoragent@cursor.com> * Retract overstated handback (a); keep width>1 bar authoritative. Codex review 46229: width-1 falsifier receipt cannot record handback (a) or deprioritize the throughline's width > 1 exit metric. Receipt reframed as incomplete width-1 evidence; follow-ups remain NEXT. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix primitive surface witness counts after #7562 arm. #7575 updated denominators for compile_dag_diagnostic_census only; parse_stage0_cargo_manifest_bins (#7562) left the roster one row ahead of the witness expectations. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…probe Two unrelated-to-this-PR repairs the floor demanded. ## The census pins were stale, and #7575 is where they went stale `the_surface_is_almost_entirely_derived` and `the_three_denominators_are_derived_and_distinct` had been failing on clean `origin/main` since 87fb808 (#7575), which added the `compile_dag_diagnostic_census` builtin arm to `v1_interpreter.rs` and did not move the numbers the census pins. The counts come from the `interpreter_dispatch_arm_rows` host builtin, which does not resolve outside the executor's discovery path, so they could not be read by inspection. They were instead derived by replicating the macro expansion over the `arm "identity" { "spelling" }` token lists the six rosters expand from. That replication reproduces all three previously-pinned numbers exactly at f2185ca (#7562, the prior interpreter change, which DID update its pins) -- three independent numbers matching is what makes the method trustworthy rather than a guess. It then puts the delta since at exactly one arm: one row, one identity, one spelling. The repaired pins were confirmed green by execution, not by the replication: claim_batch --entry dag/test/claim/v1_interpreter_primitive_surface_witness_test.dag PASS the_surface_is_almost_entirely_derived PASS the_three_denominators_are_derived_and_distinct PASS every_dispatch_site_is_enumerated PASS derived_and_declared_partition_the_surface derived 182 -> 183, declared 2 (unchanged) identities 173 -> 174, spellings 160 -> 161, sites 7 (unchanged) Why bumping the numbers is the honest repair rather than a ratchet being slackened: the failing witnesses pin absolute magnitudes, and their siblings assert the structural properties -- the partition law and the identities < rows < spellings ordering -- both of which stayed green throughout. `declared` stayed at 2, so the surface is still almost entirely derived and the witness name is still true. The new arm is derived from its own macro tokens like the other 172. Had #7575 added a hand-written declared arm, bumping `declared` would have hidden a regression, and this commit would have had to refuse instead. Sites stay 7 because the new arm lands at an existing dispatch symbol, which is the denominator that would have moved had the surface actually grown a site. ## The probe file `dag/test/claim/primitive_surface_probe_test.dag` was a throwaway used while locating the above; it was removed from the worktree but the dashboard's cadence auto-commit had already captured it in e5a8d58. `review 46534` caught it. It is baggage, not a witness -- it always returned true -- and it is deleted here rather than given assertions, because the assertions it would have carried are the ones the real census witnesses already make. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…560) The conditional belt-timer membership in the previous commit was a workaround, and review 46541 was right to red it. belt_actuate_workdir is a literal projection of srv1_gunbc_repo_root and belt_run_once_cli took no argument, so EVERY belt timer would actuate production's tree whatever instance installed it. Denying the twin a member routed around that instead of fixing it -- an author-side absorbing fallback (DESIGN section 5) -- and it broke the one-for-one twin mirror that a_twin_deployment_on_one_host_collides_with_nothing asserts as its non-degeneracy guard. review 46560 proposes dropping that count-equality conjunct. Declined: the witness's own non_degeneracy_without_transcription_note argues against exactly this edit, because `all` over an empty list is vacuously true, so a twin whose owned set collapsed to nothing would satisfy the disjointness claim perfectly. Weakening it would remove the check that caught this bug. Root fix instead: - belt_run_once_cli reads GUNBC_BELT_SPAWN_WORKDIR, fail-closed on absent AND empty. Defaulting it back would silently restore the original defect with production's tree as the thing absorbed. - The emitted belt unit carries Environment= with that instance's own repo_root. - Membership is unconditional again: production and twin both carry 7 owned artifacts, so the mirror holds because the twin genuinely has a correct timer, not because the asymmetry was argued away. - belt_run_once / belt_run_once_json keep the literal default as hand-invoked inspection surfaces; both route through one belt_run_once_in so the two paths cannot drift. - The env var name is homed in gunbc.host_layout, whose precedent is a name with consumers on both sides of a boundary. Homing it in the belt would put tmux, git worktrees and the Claude preflight behind every emission of a deploy script, for one string. Finding 2: twin_belt_timer_actuates_its_own_tree_not_productions reads the EMITTED BODY. The belt timer is the one member whose damage is not a path collision -- both instances install their own unit at their own path, and what selects the tree lives inside the unit. Deleting the Environment= line or hardcoding either root reds it. Finding 3: the note claiming srv1-lab gets its own timer was false when written and is now true; it records that it was false and why. Verified by execution, not compile -- the omission that let this reach review. Whole-corpus run: PASS=2722 FAIL=11, of which 9 are pre-existing (8 compile_diagnostic_census entry-resolve failures from #7575, plus containment_path_clone_bound_positive) and this branch touches none of their files. The other 2 were the committed goldens, regenerated here and re-verified green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* WIP: debug build flake * Part A: repair the merged observation authorities before depending on them Five defects the operator's post-merge review found in the merged tree, all model-only, no host mutation. 1. srv4 had no desired deployed-instance row, so a typed unavailability had no subject and the fleet's intent was four-fifths stated. Added, and grounded on a real observation rather than a formality: srv4 was read 2026-08-01 over the fleet-automation key the roster always intended. It holds no listener, no process, no unit, yet a stale server.sock remains on disk and its error log's whole contents are 'Address in use (os error 98)' -- a server born in a runner cgroup died with that cgroup without unlinking its socket, so every later server fails to bind and the cache tree holds one file. Distinct defect from srv1's stranded owner. 2. EndpointOwnerObserved carried cgroup and owner_context as independently writable fields that could disagree, with placement trusting the context. The cgroup path now lives inside each context arm as observed_cgroup: the context IS the classification of that cgroup, so the disagreement has nowhere to live. Retained as located diagnostic evidence, never a second input. 3. The session-capacity note claimed 50G while intended_capacity was none. The note was the true half -- ctrl-sccache.service does set 50G -- so the value now states it. CI capacity stays Absent deliberately and is now the only Absent, since 10 GiB is sccache's default rather than a decision. 4. readback_independence still classified --show-stats as ProbeMayEstablish and its authority note still asserted the refuted 'any sccache invocation auto-starts a server'. The earlier correction rewrote the mechanism prose but kept the arm, bridging the gap with 'still may-establish in the sense that matters here' -- the exact conflation the module exists to forbid, committed inside the module. Added ProbeAnswersWithoutSubject as its own arm: subject-creation and answer-without-subject carry different remedies (replace the probe vs ground it behind an existence check). 5. The hygiene-reaper scaffold bound BuildCacheServerPlacement to gunbc.host_build_cache_provision and named arms that do not exist (ServerUnitOwned, ServerLazySpawned). Repointed to gunbc.build_cache_instance with the real arms. Green by execution: 52 witnesses pass across the three affected modules (9 placement + 33 provision + 10 readback), all entries compile at 0 blocking errors. Three new controls pin the fourth arm: that it still corrects a positive verdict, that the two non-independent arms stay distinguishable through the fold, and that the cited probe now inhabits it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: debug build flake * WIP: debug build flake * Part B: require managed build-cache readiness before runner activation RunnerDeploySlot conflated materializing a slot with activating it, and only the second can create the birth defect: a materialized-but-disabled slot compiles nothing, while a slot that may accept work will connect-or-start on its first cache miss and, with no managed endpoint owner, leave the server inside its own cgroup as the host's de facto cache. So the prerequisite goes on ACTIVATION. gunbc.runner_activation owns that moment and consumes BuildCacheInstanceReady + HostCompilePoolReady; gunbc.runner_host_deploy keeps materialization and its readiness-blind runner_enable_command is DELETED, not deprecated -- leaving it would leave the old path constructible, and a wall with a door beside it is a sign. The two live in separate modules because the dependency runs one way: activation needs the deployed-instance model, materialization does not. Swapping P1/P1b in host_standup would NOT have done this. Ordering in a status list is a projection of a dependency, not the dependency; the enable command has to have no constructor that skips the receipt. Two corrections the controls forced, both worth recording: - admit_runner_activation originally never compared the receipt's unit to the instance's intended_unit, so a managed-unit-owned endpoint held by the WRONG unit would activate. witness_materializing_a_slot_does_not_activate_it caught it. ServerManagedUnitOwned means SOME unit holds it, which a legacy ctrl unit or a hand-started service satisfies. - The receipt first declared placement: ServerManagedUnitOwned, on the theory that naming one variant made the other four unwritable. This substrate widens a variant-typed field to its coproduct, so the field really had type BuildCacheServerPlacement and a runner-owned receipt was constructible -- the compiler said so, refusing a match as non-exhaustive over five arms. Shipping the note as written would have been rung inflation (DESIGN 4b) in the carrier meant to prevent it. The receipt now carries a bare managed_unit name and cannot hold a placement at all. Green by execution: 61 witnesses across four modules (9 new activation-wall controls + 10 runner-deploy + 9 placement + 33 provision), all entries at 0 blocking errors, publication gate ExitSuccess. The nine controls prove a bare host admission, an absent endpoint, both runner-owned lifecycles, unknown / unsupervised / ambiguous / unreachable placement, a receipt from another host, an unready compile pool, a partially verified instance, and a wrong unit all fail to yield an enable command -- and that materializing a slot still does not activate it. No host mutation. No producer for either receipt ships here, deliberately. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: debug build flake * Repair the interpreter primitive-surface census pins; drop the debug probe Two unrelated-to-this-PR repairs the floor demanded. ## The census pins were stale, and #7575 is where they went stale `the_surface_is_almost_entirely_derived` and `the_three_denominators_are_derived_and_distinct` had been failing on clean `origin/main` since 87fb808 (#7575), which added the `compile_dag_diagnostic_census` builtin arm to `v1_interpreter.rs` and did not move the numbers the census pins. The counts come from the `interpreter_dispatch_arm_rows` host builtin, which does not resolve outside the executor's discovery path, so they could not be read by inspection. They were instead derived by replicating the macro expansion over the `arm "identity" { "spelling" }` token lists the six rosters expand from. That replication reproduces all three previously-pinned numbers exactly at f2185ca (#7562, the prior interpreter change, which DID update its pins) -- three independent numbers matching is what makes the method trustworthy rather than a guess. It then puts the delta since at exactly one arm: one row, one identity, one spelling. The repaired pins were confirmed green by execution, not by the replication: claim_batch --entry dag/test/claim/v1_interpreter_primitive_surface_witness_test.dag PASS the_surface_is_almost_entirely_derived PASS the_three_denominators_are_derived_and_distinct PASS every_dispatch_site_is_enumerated PASS derived_and_declared_partition_the_surface derived 182 -> 183, declared 2 (unchanged) identities 173 -> 174, spellings 160 -> 161, sites 7 (unchanged) Why bumping the numbers is the honest repair rather than a ratchet being slackened: the failing witnesses pin absolute magnitudes, and their siblings assert the structural properties -- the partition law and the identities < rows < spellings ordering -- both of which stayed green throughout. `declared` stayed at 2, so the surface is still almost entirely derived and the witness name is still true. The new arm is derived from its own macro tokens like the other 172. Had #7575 added a hand-written declared arm, bumping `declared` would have hidden a regression, and this commit would have had to refuse instead. Sites stay 7 because the new arm lands at an existing dispatch symbol, which is the denominator that would have moved had the surface actually grown a site. ## The probe file `dag/test/claim/primitive_surface_probe_test.dag` was a throwaway used while locating the above; it was removed from the worktree but the dashboard's cadence auto-commit had already captured it in e5a8d58. `review 46534` caught it. It is baggage, not a witness -- it always returned true -- and it is deleted here rather than given assertions, because the assertions it would have carried are the ones the real census witnesses already make. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Give the belt a driver: a deploy-owned tick timer
belt_run_once_cli is a complete ProcessExit entrypoint and nothing
invoked it, so a dispatched roadmap item reached Verification and
stopped there. roadmap_serve's serve_publish_note already named the
consequence from the other side: POST /publish/{node_id} "exists
because belt_tick has none".
Not modeled as a host timer beside gunbc.host_hygiene_reaper, because
that precedent does not install anything: host_hygiene_reaper_script
has zero consumers and is a declared Scaffold, the only reference to
the reaper outside its own module is a residue row about a fold shape,
and its own header describes its precedent (ctrl-runner-reclaim.timer)
as "a hand-deployed host timer with no prior .dag model". Copying it
would have produced a second modeled timer that never runs -- the
specification-without-execution trap, reproduced while fixing an
instance of it.
So the timer rides live_deploy, the one host-effect path this repo can
show executing, as a BeltTimerUnit owned artifact. One member, two unit
files, exactly as GunbcSourceTree owns gunbc-tree-sync.service plus its
env file.
Membership is CONDITIONAL, and that is the load-bearing part.
belt_actuate_workdir is a literal (srv1_gunbc_repo_root) and
belt_run_once_cli is zero-arg, so a tick spawns into that root whatever
unit invoked it -- WorkingDirectory does not help. An unconditional
member would therefore give the srv1-lab twin a timer spawning agent
sessions into production's tree, which is the failure
deployment_service_handler_note records for the serve handler. The
member is present exactly when the instance's repo_root IS the root the
belt actuates in, compared against the single host_layout authority
that belt_actuate_workdir itself projects. Dissolves when the belt
takes its spawn root from the deployment.
Cadence uses OnUnitInactiveSec, not OnUnitActiveSec: measured from tick
END, so a slow tick cannot schedule overlapping spawns.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Regenerate the deploy goldens for the belt timer member
Generated projections of gunbc.live_deploy.emit, regenerated via
main_wet on dag/tools/generated_artifact_gate.dag -- not hand-edited.
Produced with a freshly rebuilt binary. The first rebuild attempt went
through ctrl-build, which ran REMOTELY ("Uploaded 0 artifacts", "Remote
run completed") and left the local binary untouched at its previous
mtime; regenerating with it would have emitted goldens from a stale
compiler while looking authoritative. Caught by comparing the binary
mtime, then rebuilt with CTRL_BUILD_BYPASS_SHIMS=1.
Apply gains: both unit files written to the stage dir, installed 0644,
daemon-reload, then enable + restart of the TIMER (not the service --
the timer is what schedules, the oneshot is what it triggers).
Retract gains: disable --now the timer, remove BOTH unit files, then
daemon-reload. Removing both is why the member owns two files rather
than two members owning one each.
Every added command is install / systemctl / rm -- all whole-binary
NOPASSWD grants in fleet_posix_ci_runner_sudo_grants, so the emitted
script stays inside the deploy principal's granted set.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* WIP: Roadmap
* Make the belt spawn root a per-deployment parameter (review 46541, 46560)
The conditional belt-timer membership in the previous commit was a
workaround, and review 46541 was right to red it. belt_actuate_workdir
is a literal projection of srv1_gunbc_repo_root and belt_run_once_cli
took no argument, so EVERY belt timer would actuate production's tree
whatever instance installed it. Denying the twin a member routed around
that instead of fixing it -- an author-side absorbing fallback (DESIGN
section 5) -- and it broke the one-for-one twin mirror that
a_twin_deployment_on_one_host_collides_with_nothing asserts as its
non-degeneracy guard.
review 46560 proposes dropping that count-equality conjunct. Declined:
the witness's own non_degeneracy_without_transcription_note argues
against exactly this edit, because `all` over an empty list is vacuously
true, so a twin whose owned set collapsed to nothing would satisfy the
disjointness claim perfectly. Weakening it would remove the check that
caught this bug.
Root fix instead:
- belt_run_once_cli reads GUNBC_BELT_SPAWN_WORKDIR, fail-closed on
absent AND empty. Defaulting it back would silently restore the
original defect with production's tree as the thing absorbed.
- The emitted belt unit carries Environment= with that instance's own
repo_root.
- Membership is unconditional again: production and twin both carry 7
owned artifacts, so the mirror holds because the twin genuinely has a
correct timer, not because the asymmetry was argued away.
- belt_run_once / belt_run_once_json keep the literal default as
hand-invoked inspection surfaces; both route through one
belt_run_once_in so the two paths cannot drift.
- The env var name is homed in gunbc.host_layout, whose precedent is a
name with consumers on both sides of a boundary. Homing it in the belt
would put tmux, git worktrees and the Claude preflight behind every
emission of a deploy script, for one string.
Finding 2: twin_belt_timer_actuates_its_own_tree_not_productions reads
the EMITTED BODY. The belt timer is the one member whose damage is not a
path collision -- both instances install their own unit at their own
path, and what selects the tree lives inside the unit. Deleting the
Environment= line or hardcoding either root reds it.
Finding 3: the note claiming srv1-lab gets its own timer was false when
written and is now true; it records that it was false and why.
Verified by execution, not compile -- the omission that let this reach
review. Whole-corpus run: PASS=2722 FAIL=11, of which 9 are pre-existing
(8 compile_diagnostic_census entry-resolve failures from #7575, plus
containment_path_clone_bound_positive) and this branch touches none of
their files. The other 2 were the committed goldens, regenerated here
and re-verified green.
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>
…ission (#7619) * WIP: debug build flake * Part A: repair the merged observation authorities before depending on them Five defects the operator's post-merge review found in the merged tree, all model-only, no host mutation. 1. srv4 had no desired deployed-instance row, so a typed unavailability had no subject and the fleet's intent was four-fifths stated. Added, and grounded on a real observation rather than a formality: srv4 was read 2026-08-01 over the fleet-automation key the roster always intended. It holds no listener, no process, no unit, yet a stale server.sock remains on disk and its error log's whole contents are 'Address in use (os error 98)' -- a server born in a runner cgroup died with that cgroup without unlinking its socket, so every later server fails to bind and the cache tree holds one file. Distinct defect from srv1's stranded owner. 2. EndpointOwnerObserved carried cgroup and owner_context as independently writable fields that could disagree, with placement trusting the context. The cgroup path now lives inside each context arm as observed_cgroup: the context IS the classification of that cgroup, so the disagreement has nowhere to live. Retained as located diagnostic evidence, never a second input. 3. The session-capacity note claimed 50G while intended_capacity was none. The note was the true half -- ctrl-sccache.service does set 50G -- so the value now states it. CI capacity stays Absent deliberately and is now the only Absent, since 10 GiB is sccache's default rather than a decision. 4. readback_independence still classified --show-stats as ProbeMayEstablish and its authority note still asserted the refuted 'any sccache invocation auto-starts a server'. The earlier correction rewrote the mechanism prose but kept the arm, bridging the gap with 'still may-establish in the sense that matters here' -- the exact conflation the module exists to forbid, committed inside the module. Added ProbeAnswersWithoutSubject as its own arm: subject-creation and answer-without-subject carry different remedies (replace the probe vs ground it behind an existence check). 5. The hygiene-reaper scaffold bound BuildCacheServerPlacement to gunbc.host_build_cache_provision and named arms that do not exist (ServerUnitOwned, ServerLazySpawned). Repointed to gunbc.build_cache_instance with the real arms. Green by execution: 52 witnesses pass across the three affected modules (9 placement + 33 provision + 10 readback), all entries compile at 0 blocking errors. Three new controls pin the fourth arm: that it still corrects a positive verdict, that the two non-independent arms stay distinguishable through the fold, and that the cited probe now inhabits it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: debug build flake * WIP: debug build flake * Part B: require managed build-cache readiness before runner activation RunnerDeploySlot conflated materializing a slot with activating it, and only the second can create the birth defect: a materialized-but-disabled slot compiles nothing, while a slot that may accept work will connect-or-start on its first cache miss and, with no managed endpoint owner, leave the server inside its own cgroup as the host's de facto cache. So the prerequisite goes on ACTIVATION. gunbc.runner_activation owns that moment and consumes BuildCacheInstanceReady + HostCompilePoolReady; gunbc.runner_host_deploy keeps materialization and its readiness-blind runner_enable_command is DELETED, not deprecated -- leaving it would leave the old path constructible, and a wall with a door beside it is a sign. The two live in separate modules because the dependency runs one way: activation needs the deployed-instance model, materialization does not. Swapping P1/P1b in host_standup would NOT have done this. Ordering in a status list is a projection of a dependency, not the dependency; the enable command has to have no constructor that skips the receipt. Two corrections the controls forced, both worth recording: - admit_runner_activation originally never compared the receipt's unit to the instance's intended_unit, so a managed-unit-owned endpoint held by the WRONG unit would activate. witness_materializing_a_slot_does_not_activate_it caught it. ServerManagedUnitOwned means SOME unit holds it, which a legacy ctrl unit or a hand-started service satisfies. - The receipt first declared placement: ServerManagedUnitOwned, on the theory that naming one variant made the other four unwritable. This substrate widens a variant-typed field to its coproduct, so the field really had type BuildCacheServerPlacement and a runner-owned receipt was constructible -- the compiler said so, refusing a match as non-exhaustive over five arms. Shipping the note as written would have been rung inflation (DESIGN 4b) in the carrier meant to prevent it. The receipt now carries a bare managed_unit name and cannot hold a placement at all. Green by execution: 61 witnesses across four modules (9 new activation-wall controls + 10 runner-deploy + 9 placement + 33 provision), all entries at 0 blocking errors, publication gate ExitSuccess. The nine controls prove a bare host admission, an absent endpoint, both runner-owned lifecycles, unknown / unsupervised / ambiguous / unreachable placement, a receipt from another host, an unready compile pool, a partially verified instance, and a wrong unit all fail to yield an enable command -- and that materializing a slot still does not activate it. No host mutation. No producer for either receipt ships here, deliberately. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: debug build flake * Repair the interpreter primitive-surface census pins; drop the debug probe Two unrelated-to-this-PR repairs the floor demanded. ## The census pins were stale, and #7575 is where they went stale `the_surface_is_almost_entirely_derived` and `the_three_denominators_are_derived_and_distinct` had been failing on clean `origin/main` since 87fb808 (#7575), which added the `compile_dag_diagnostic_census` builtin arm to `v1_interpreter.rs` and did not move the numbers the census pins. The counts come from the `interpreter_dispatch_arm_rows` host builtin, which does not resolve outside the executor's discovery path, so they could not be read by inspection. They were instead derived by replicating the macro expansion over the `arm "identity" { "spelling" }` token lists the six rosters expand from. That replication reproduces all three previously-pinned numbers exactly at f2185ca (#7562, the prior interpreter change, which DID update its pins) -- three independent numbers matching is what makes the method trustworthy rather than a guess. It then puts the delta since at exactly one arm: one row, one identity, one spelling. The repaired pins were confirmed green by execution, not by the replication: claim_batch --entry dag/test/claim/v1_interpreter_primitive_surface_witness_test.dag PASS the_surface_is_almost_entirely_derived PASS the_three_denominators_are_derived_and_distinct PASS every_dispatch_site_is_enumerated PASS derived_and_declared_partition_the_surface derived 182 -> 183, declared 2 (unchanged) identities 173 -> 174, spellings 160 -> 161, sites 7 (unchanged) Why bumping the numbers is the honest repair rather than a ratchet being slackened: the failing witnesses pin absolute magnitudes, and their siblings assert the structural properties -- the partition law and the identities < rows < spellings ordering -- both of which stayed green throughout. `declared` stayed at 2, so the surface is still almost entirely derived and the witness name is still true. The new arm is derived from its own macro tokens like the other 172. Had #7575 added a hand-written declared arm, bumping `declared` would have hidden a regression, and this commit would have had to refuse instead. Sites stay 7 because the new arm lands at an existing dispatch symbol, which is the denominator that would have moved had the surface actually grown a site. ## The probe file `dag/test/claim/primitive_surface_probe_test.dag` was a throwaway used while locating the above; it was removed from the worktree but the dashboard's cadence auto-commit had already captured it in e5a8d58. `review 46534` caught it. It is baggage, not a witness -- it always returned true -- and it is deleted here rather than given assertions, because the assertions it would have carried are the ones the real census witnesses already make. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Actuation phase 2: the endpoint-path state machine and the unlink admission The first slice of the actuation bundle. Still no host mutation: this lands the model and the wall that a later mutating step must pass through. ## The defect it closes srv4, observed 2026-08-01: no listener, no process, no unit, a server.sock present on disk, and an sccache error log whose entire contents are "Address in use (os error 98)". A server born inside a runner cgroup died with that cgroup without unlinking its socket, so every later server fails to bind. The host has been uncached since roughly 2026-07-26 for that reason alone. `BuildCacheEndpointObservation.EndpointAbsent` cannot express this. It answers "is anybody listening", which is the right question for placement and the wrong one for actuation: under it, srv4 and a host that simply has no cache yet are the same state. They are not — one needs a unit started, the other needs a file removed FIRST and then a unit started, and starting the unit without removing the file reproduces error 98 forever. A state-space conflation whose measured cost is a host silently uncached for a week. `EndpointPathState` is therefore a separate axis from the owner: absent / listening / stale socket / path conflict / unavailable. ## Why the unlink is admitted rather than an ExecStartPre The obvious fix is `ExecStartPre=/bin/rm -f server.sock`, and it is an absorbing fallback. It unlinks in every path state rather than the one where unlinking is correct. Absent, it is a harmless no-op — which is what makes it look safe in testing. Conflict, it destroys a file this lane did not create. Listening — which happens on every restart of a healthy unit and every double-start race — it severs a live server's socket, leaving a running process no client can reach and that will not be replaced because it still holds memory and still parents compiles. Silent in exactly the way the stale socket was silent, so the remedy recreates the disease one layer up, and an unconditional rm never reports having removed something it should not have, so the deficit's frequency is zeroed by construction. `admit_stale_socket_unlink` admits only from `EndpointStaleSocket` under `ObservationCurrent`; every other state is a positively named, located refusal. The unlink is a separate admitted step before the unit start, able to refuse independently of it, never a line inside the unit. Three shapes deliberately avoided: - The admission takes the observed STATE, not a record of four Bools. An all-true evidence record is hand-writable and re-checks what the observation already decided — validation wearing construction's clothes, the same defect review 46217 found in the owner context. The four facts an observer must establish are stated as its contract, not re-represented as data. - `ObservationCurrencyUnknown` refuses exactly as `ObservationStale` does. Not knowing whether a read is current is the same evidence as knowing it is old, and an arm that graded them would fire precisely when /proc is least readable, which is when a bind race is likeliest. - A TCP endpoint refuses at admission rather than at command construction, so no admitted value exists for which no command can be built. ## Test plan Green by execution, 8 controls, 0 failures: claim_batch --entry dag/test/claim/build_cache_endpoint_path_test.dag PASS witness_the_srv4_stale_socket_is_the_one_state_that_unlinks PASS witness_a_live_listener_is_never_unlinked PASS witness_a_non_socket_path_is_never_unlinked PASS witness_an_absent_path_refuses_rather_than_no_ops PASS witness_an_unreadable_path_does_not_default_to_stale PASS witness_a_stale_read_cannot_license_an_unlink PASS witness_a_tcp_endpoint_has_no_stale_socket_state PASS witness_the_unconditional_sketch_differs_where_it_is_destructive `unconditional_unlink_sketch` is the RED control -- ExecStartPre=rm -f written as a predicate, answering true in all five states. Two witnesses assert the admission DIFFERS from it on the two destructive states rather than merely asserting the admission refuses: a refusal where the naive fix would also have been harmless proves nothing about the wall's worth. Per DESIGN section 4b the control stays enrolled rather than retiring once the wall lands. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Bind the compile-pool receipt to its host and slice; derive it Addresses review 46581 finding 1, and lands the producer that finding made unavoidable. ## The defect (review 46581, real) admit_runner_activation bound the CACHE receipt to the activation two ways -- its instance host against the deploy host, and its managed_unit against the instance's intended_unit -- and gated the POOL receipt beside it on two Booleans alone. So a pool observed on a different host, or a correctly-observed slice with some other name, admitted activation. Same unbound-receipt defect the unit comparison exists to prevent, sitting in the sibling field. The asymmetry is how it survived being written: the receipt that got the attention got the binding. HostCompilePoolReady now carries its host, and two comparisons gate admission -- pool_receipt_is_for_host and pool_receipt_names_intended_pool. The slice is compared against BuildCacheInstance.intended_compile_pool rather than against gunbc_managed_compile_pool_slice: comparing to the global default would make the wall agree with a constant rather than with the instance being activated against, which is weaker and looks identical. ## The producer gunbc.host_compile_pool derives the receipt, so it stops being purely hand-authored. It deliberately adds NO sizing and NO topology: those already have an authority in gunbc.fleet_host_budget (CompilePoolPlacement, compile_pool_bytes_for, and extdeps.jobserver's jobserver_build_pool_bytes -- the same cited knob that bounds build concurrency). A HostCompilePool record with its own memory_high / memory_max / token_count fields would fork that and give a host two answers for how big its pool is. CompilePoolReadiness carries five distinct not-ready reasons. Two that look alike are kept apart on purpose: PoolNotDeclaredInTopology (the fleet has not decided it HAS a managed pool) versus PoolSliceAbsentOnHost (it has, and this host lacks it). Their remedies and owners differ -- a fleet-wide topology change that must shrink runner_pool in the same motion, versus provisioning one host -- so collapsing them would make the fleet decision read as a per-host chore. Sizing is checked LAST, after the slice is confirmed present and correctly named: reporting a sizing failure first would send an operator to look at installer configuration on a host with no slice to size, which is the wrong-location defect toolchain_ensure_reconcile_located_note already records. ## Test plan Green by execution, 18 witnesses across the two modules, 0 failures. The two new binding controls: PASS witness_a_pool_receipt_from_another_host_is_refused PASS witness_a_pool_receipt_naming_another_slice_is_refused Both are asserted rather than only the host case, because they fail for different reasons -- one receipt is about the wrong machine, the other about the wrong cgroup on the right machine -- and a wall catching only the first would still activate a runner whose compiles are charged outside the intended pool. The producer's load-bearing witness reads the REAL gunbc_compile_pool_placement row rather than a fixture: PASS witness_the_live_fleet_topology_yields_no_ready_pool It asserts FALSE. The row is CompilePoolInRunnerSlots, so the derivation returns not-ready for every host and activation refuses fleet-wide -- the correct answer today, and the one a hand-written all-true receipt silently contradicted. When the topology flips it reds deliberately, as the tripwire that the flip cannot land silently. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Repoint the two fleet-subsumption citations of the deleted enable path review 46621, non-blocking. This PR deleted runner_enable_command, and gunbc.plans.fleet_subsumption_manual_gaps still named it in two rows -- the DESIGN section 3 citation-rot class, where a name-level claim in a carrier goes false because something elsewhere was renamed or deleted and nobody touched the row. Only two of the six occurrences were stale. The other four deliberately name the deleted symbol AS HISTORY and are left alone: runner_enable_command_deleted_note records the deletion, activation_readiness_blind_widen_sketch_note cites it as the RED control's provenance ("a faithful copy of ... as it stood on main"), and two notes explain why moving a row in host_standup would not have sufficed. A citation of a deleted thing is only rot when it asserts the thing still exists. The two that did: - The B1 gap's present-tense "models the runner ENABLE step (runner_enable_command -> ...)" is now false; repointed to runner_activate_command. - The A-item's "Only THEN did the modeled part run: systemctl daemon-reload + runner_enable_command" is a past-tense account of what was hand-run on 2026-07-22, so it is recorded as the THEN-current path rather than silently repointed -- the enable it describes is precisely the readiness-blind one that produced this fleet's birth defect, and rewriting it to name the new wall would erase the receipt. It now says which path ran, that it is deleted, and what replaced it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Add the host field to the third HostCompilePoolReady fixture review 46625. Commit 8d19c16 added `host` to HostCompilePoolReady and updated two of the three construction sites; witness_ready_pool in runner_host_deploy_witness_test was the third and was missed. The reviewer is also right that this made the previous commit's test plan overclaim. That run was real -- 18 witnesses across host_compile_pool_test and runner_activation_wall_test -- but those are the two modules I edited, not the closure of the type I changed, so the third site was never compiled. Same miss as the ProbeEffectOnSubjectFold literal earlier in this lane: after changing a record or coproduct, enumerate every construction site of the TYPE, not the files in the diff. Now green by execution on the missed module too, all 10 witnesses including the three callers the review named. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Compare the observed slice ceiling against the derived pool size review 46655 finding 1, real and blocking. derive_compile_pool_readiness matched CompilePoolSliceObserved and bound `limits: _`, discarding the observed cgroup ceilings, then reported CompilePoolReady carrying the size derived from the JOBSERVER. So the receipt asserted a sized pool on the strength of a number nobody had compared to the host: a slice observed with a zero memory.max was declared ready against a nonzero requirement. Fabricated readiness rather than a missing check, and the distinction places the fix: the observation was already in hand and was thrown away, so this was never a gap awaiting a producer. It is fail-closed inverted at the one carrier whose whole job is deciding whether compiles have a bounded parent -- and an unbounded ceiling parenting every cache-miss compiler is precisely the defect this lane exists to close. Compared against memory_max rather than memory_high: max is the ceiling that actually bounds the cgroup, while high is a throttling watermark the kernel permits to be exceeded, so sizing against high would admit a slice whose hard limit sits below the compiles it must hold. THE FIXTURE WAS CERTIFYING THE HOLE, and that is recorded in-module rather than quietly deleted: observed_slice built all-zero limits and witness_a_declared_and_observed_slice_is_ready passed anyway. The fixture now carries a ceiling that can hold the derived size, and a new sibling pins the case it used to admit. Both halves are needed -- without the positive fixture the derivation could refuse everything and still pass; without the new one it could admit everything. Green by execution, 8 witnesses, 0 failures, including: PASS witness_a_slice_below_the_derived_size_is_not_ready Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
The observation surface
ladder-probe-corpusneeds before any wall control can migrate, plus the first floor-class measurement it makes possible. Scope amended by the lane owner (2026-08-01) to admit exactly this one surface — see "Why a compiler change was authorized" below.The problem this closes
The only
.dag-callable v1 compile wascompile_dag_rust_emit_check: it counts diagnostics passingcompile_clean_diagnostic_is_hardand returnsfalsewhen that count is nonzero. Everything else is discarded inside the host. Measured against the tests Stage 1a is supposed to migrate, that costs three specific things:CallArgumentNameUnknownspecifically. At Bool grain a probe refusing for any hard reason — a typo in the probe source included — reads as the wall firing. That is the proxy-assertion fail-open.is_interpreter_blocking_diagnostic, so demoting a landed wall from blocking to advisory turns its migrated RED silently GREEN.ct_call_shape_wall_witness_testpins exactly this in its second assert; a Bool-grain migration would delete that assertion.MethodExistenceUndecidedpassed unnoticed as a green control.It is structural, not stylistic: Stage 0's
ProbeObservationcarriesRefusedTyped { diagnostic_class, count }andAcceptedCounted { diagnostic_class, count }, and neither is inhabitable from aBool. The Stage-0 vocabulary was uninhabitable on every v1 path.What lands
gunbc.compile_diagnostic_census—CompileDiagnosticCensusRow { diagnostic_class, subject_name, blocking, count }and the coproductCensusObserved | CensusNotRunnable, with pure row selectors. No arm judges acceptance.compile_dag_diagnostic_census— one measurement-only builtin. Same compile path as its sibling;(class, name)iscompile_clean_diagnostic_histogram_key(§3 projection, not a second diagnostic vocabulary);blockingis the existingcompile_clean_diagnostic_is_harddelegation carried as data, so the severity policy keeps one home. Nothing is filtered — callers filter. Aggregation keys on(class, name, blocking)deliberately: folding severities together would hide the very demotion this surface exists to keep visible.CensusNotRunnableas a distinct arm, never an empty row list. An empty census is byte-identical to a clean compile, so could-not-measure would read as the subject passing (DESIGN §5, ⊤-as-answer vs ⊤-as-ignorance). Preserving the split at the host seam is what lets the probe layer map it toProbeNotRunnablewithout guessing. A host panic is caught at the boundary and lands here with its cause.dag/test/claim/compile_diagnostic_census_witness_test.dag— green by execution: class identity, blocking severity (the demotion detector — it reds if a wall is softened to advisory), occurrence counts rather than presence flags, a clean-source control proving the harness is not uniformly refusing, and theNotRunnablevs empty-observation split.Both severity directions have live specimens, and the route there involved two corrections, both recorded rather than tidied away. I first concluded no advisory specimen could be produced synthetically — three candidates each either compiled silent or refused blocking. Corpus prevalence said otherwise (the whole-tree census carries 1,981
where-refinementadvisories), so the class was demonstrably reachable and a probe finding none was evidence against the probe. A working specimen followed, andAcceptedCountedgained a producer.I then attributed the original failure to the closure — fixture-only compiles carry no
std. A discriminating control refuted that too, and a 2×2 finally pinned the real axis, which was neither thing guessed. Crossing declaration site (a locally-declared alias vsstd's brand — structurally identical:type NonEmptyStr = String where non_emptyandtype Tight = String where non_empty) against cast subject (literal vs unknown parameter):Declaration site is irrelevant — a user-declared refinement alias is judged exactly as
std's brand is. The axis is literal vs non-literal, and the diagnostic names it: "where-refinement unenforced: predicatenon_emptyonProduct(Tight)— non-literal value at refined position". So the original probe's silence is correct behaviour: it cast the literal"x", and a literal at a refined position is deliberately exempt (the ladder working — construction deciding what validation would otherwise check). No census row is filed for it; doing so would have seeded the wall-implementer population with a below-floor claim against correct behaviour. It becomes the dead-probe worked example instead — the failure mode in its least obvious dress, since the probe does cast, at afnboundary, against a properly declared refinement.Mandate adopted as lane policy on the strength of this record: every below-floor or silent-class row the baseline stage produces carries a probe-adequacy receipt — closure and shape and the prevalence cross-check where a population exists — required, not advisory. Three consecutive mechanism explanations here were refuted while the conclusions they explained kept surviving; mechanism stories do not survive contact, executed discriminating controls do. Every superseded claim is kept in the gap analysis rather than overwritten, because the sequence is the lesson.
Probe-adequacy receipts for the four below-floor findings
The rule above applies first to the rows that prompted it. All four were originally measured under a fixture-only closure and have been re-run under the full
dag+src/v2pool, with the refined-brand cast as the discriminating control proving that harness can surface a diagnostic — so a zero there is the compiler's silence, not the harness's.All four declare only local types over kernel scalars, so the wider pool adds no machinery they depend on — but that is now measured rather than argued.
The measurement it makes possible
Six floor classes as probe pairs (deliberately-bad input plus legitimate control), v1 pipeline → Rust target, synthetic single module. Every control compiles clean.
Boxed { inner: "not an int" }atBoxed<Int>fn get_field<T>(t: T) -> Int { t.no_such_field }match t { Red => 1 }onTNonExhaustiveMatch, blockingMissingField, blockingTwo §1c census rows corrected by execution, both in the direction the census's
Unknowndefault protects against:Unknown — unmeasured; it measures R2.PatternLookupBlocked => []is wrong on the carrier:pattern_subject_from_nodereaches that arm only where the scrutinee's inferred typeis_compiler_error, i.e. where a diagnostic already exists. The silent arm isPatternDynamic { span: _ } => [].PatternLookupBlocked's own silence is not established by these probes and is not asserted as though it were.Why a compiler change was authorized
The brief's scope said no compiler change. I stopped and escalated rather than improvising, because the alternative readings differ materially: migrating at Bool grain would be a declared rung lowering that deletes landed assertions (DESIGN §4b meta-obligation 3), and deferring would stall the node's highest-risk slice. The lane owner amended scope to admit exactly this surface, under five guardrails: one measurement-only builtin, projection of existing authorities only, fail-closed at the host seam, a registry row carrying its sibling's dissolution trigger, and evidence parity before any
ct_deletion.On the contested ground:
builtin_function_registryis itself a §3 fork awaiting thePrimitiveDefinitionidentity join, pergunbc.plans.compile_clean_forcecheck. The new row carries a note binding it to exactly its sibling's dissolution — when the join dissolves the registry, the two migrate together. One additive row is linear cost against that dissolution; the alternative was a schema no v1 probe could inhabit. The04_method.dagdiff is one row plus that note, nothing else.Not in this PR
No wall lands and no wall is strengthened — probes measure. No
ct_test is deleted here: guardrail 5 requires the migrated probe to reach assertion parity in the same PR that removes the original, and that is slice 1, which also needsgunbc.guarantee_measurement(gunbc#7572) on main for the class/path identities. Nothing here builds against a copied schema.🤖 Generated with Claude Code