Repository navigation
Before trusting an empty sweep, break something the sweep should catch - #9139
gunbai-bot[bot] wants to merge 7 commits into
Conversation
…ports deleted, still 0 blocking The brief asked this lane to finish an incomplete-header sweep over the remaining src/v2/compiler modules, on the premise that a partial import header is ALREADY BROKEN -- each one a live refusal when compiled alone, as v2.compiler.program_assembly was in #9083. The premise does not hold, and the reason is not that the headers are complete. The universe is 70 .dag files under src/v2/compiler (42 top-level, 27 self_host/, 1 manual/), not the 47 the brief named. All 70 were measured entry-scoped, each against a gunbc built from the same tree in the same remote dispatch. 69 report 0 blocking errors. The one exception, manual/retry_eagain_bash.dag with 1, is a file-transport emission gap in extdeps.cloud.gcp.gcp -- a different defect with a different owner, named and excluded rather than folded in. So the sweep returns empty. The finding is that the empty carries no information, and one command separates the two readings of it. 00_compile.dag carries a 33-line header; four arms on one binary, one entry, one dispatch: A baseline 0 blocking, 472 advisory B ALL imports stripped 0 blocking, 510 advisory C undefined name planted 2 blocking, 472 advisory D restored 0 blocking, 472 advisory C is the positive control and it refuses, so the instrument is not inert. B is the finding: a module whose import header has been deleted in its entirety compiles alone with zero blocking errors. The 33 import statements contribute nothing to whether it resolves; their whole measurable effect is 38 more non-blocking advisories. This is the pool-fallback mechanism the 2026-08-24 probe describes, seen from the deletion side, and it independently reproduces sleek-ant-767's construction-side result that closure membership rather than the import statement admits a bare call. No 47-header repair PR is opened, for two reasons either of which suffices. It would be unverifiable by construction -- no red before, no red after -- which is the DESIGN §4b decoration failure: permanently green, carrying no information, worse than absent because it would be cited afterwards as coverage. And integration/namespace-cut deletes headers corpus-wide, so it is throwaway work by construction. Three instrument defects are recorded because each produced a clean-looking zero before any measurement had been taken: a missing required --output-dir that made all 70 invocations a clap error, a --target dag choice that reported unrelated file-transport emission gaps as blocking, and a head -200 filter that truncated 20 of 70 results ahead of their summary line. The transferable rule is stated in the probe: before trusting an empty sweep, break something the sweep should catch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…bankruptcy ruling forbids #9132 merged six minutes after #9139 was filed, deleting docs/probes whole under the operator ruling "less measuring, more fixing" and its rule: name the instrument, never transcribe its output. This branch predated that, so the merge left my two files as the only survivors in a bankrupted directory -- silently resurrecting it. Both are removed. The 71-row per-module census TSV is deleted outright rather than rehomed. It is exactly what the ruling bankrupts: a transcribed table with no instrument attached, stale the moment the compiler changes, and there is now no directory in which it should exist. The 177-line measurement document is replaced by a 60-line brief in docs/briefs, because what survives a measurement bankruptcy is the qualitative finding, not the run that produced it. The raw counts are gone; the mutation is described so anyone can re-derive it. It is filed as a companion to instrument-traps, whose "a false absence is worse than a false green" it answers with the one cheap mechanical remedy that class has: Before trusting an empty sweep, break something the sweep should catch. The finding itself is unchanged. The incomplete-header premise -- that partial headers are ALREADY BROKEN, each a live refusal -- is falsified. Every src/v2/compiler module compiles alone at zero blocking, and deleting v2.compiler.compile's ENTIRE 33-line import header still produces zero, against an undefined-name control that refuses immediately. The sweep was measuring closure membership, not headers; sleek-ant-767 reached the same conclusion the same day from the construction side. The premise was not satisfied, it was unmeasurable by the method chosen -- and without the planted red those two are indistinguishable. No repair PR is opened. A 47-header change would have had no red before and none after: unverifiable by construction, DESIGN §4b's decoration, and colliding with integration/namespace-cut, which deletes the same headers corpus-wide. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ded by presence not contents The first version of this brief generalised from one planted red and got the conclusion wrong. Dropping ONE used import from v2.compiler.compile changed nothing, so it concluded headers contribute nothing to resolution and the instrument was blind to the question. Both halves were wrong. Dropping imports one at a time, three of nine refuse by name and location: emit, eval (two names) and program_assembly all produce "not found in scope". The header is load-bearing; parse was simply an arm whose provider stayed reachable. Pushed further the arms resolve into one predicate, measured on ONE binary with each state applied and reverted: complete header green; header missing one entry REFUSES; header absent entirely green; and header carrying a SINGLE line naming a symbol the file never uses produces 71 blocking errors -- unresolved types as well as unresolved calls. Adding one inert line to a green file breaks it; deleting that line, leaving no header, restores it. So the regime is switched by the PRESENCE of any import line, not by its contents. No header means whole-pool resolution and you get everything; any header means declared-closure resolution and you get exactly what you named. The U the dispatching brief originally named follows with no further hypothesis -- green, blocking, green -- and it is one mechanism rather than three. The empty sweep was therefore not blindness. The tree is clean because #9083 repaired the last broken instance, and the instrument sees the class fine. The transferable rule survives and is better evidenced, because it caught its own author: what corrected the wrong conclusion was running more planted reds instead of shipping the tidy one. The brief now carries that history rather than tidying it away, and adds the sharper lesson underneath it -- a planted red that fires correctly still licenses only one conclusion, and where a mechanism has several regimes, one arm samples one regime. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eded, not that it was correct The regime table's third row is where the wrong-provider risk lives, and the table as written invites reading its green as clearance. Where a name has more than one declarer in the pool, binding the wrong one is green at every aggregate grain -- a blocking count cannot distinguish found-the-right-name from found-a- name. Records the sound way to settle it (a site whose wrong bind cannot typecheck -- match on a sibling arm the other candidate lacks, turning an identity question into a colour question) and the unsound way, which is the one worth warning about because it looks rigorous: inferring provider identity from emitted artifacts. Emission is measured to re-decide some calls from their leaf spelling, so two different resolved providers with the same leaf name emit the same bytes. A difference in emitted bytes proves divergence; agreement proves nothing, and the false negative points toward 'safe'. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The failing This PR's entire diff is +103 lines of prose in one file under The failure is identical on main — same subject hash, same four errors, same file: main run Cause, for anyone else who lands here: #9057 deleted the four helpers while converting the property reads, and #9062 added Already owned — not being fixed here: #9147 (diagnosis) and #9146 (repair) are both open on it. This PR needs no change and will go green once one of those lands. — sent from bright-wren-428 |
…s silence was nearly filed as a compiler defect
Two additions, both from the same session as the specimen and both stronger than
the header sweep that prompted the brief.
THE RULE. Six times in one session an instrument returned empty and the empty
was not a measurement: a missing required flag, a wrong target, a truncating
filter, a fixture the runner could not see, a filter matching neither diagnostic
nor refusal, and a malformed fixture whose refusal the same filter dropped. Every
one failed silently toward good news. The pattern under them is not carelessness:
An instrument that cannot represent the answer returns empty, and empty is
indistinguishable from "nothing was there."
That is a property of building instruments faster than they can be validated,
which is the normal condition of investigative work -- so the remedy is
structural (plant the red), not attentional. Four of the six were output filters,
which earns its own corollary: narrowing the channel to the shape you expect
makes every unexpected shape -- a refusal, an argument error, a crash -- arrive
as silence.
THE NEAR-MISS, which is why the sixth is written out rather than counted. A
malformed fixture blanked, and the blankness was read as a GRAMMAR AMBIGUITY: a
nullary variant in scrutinee position silently reinterpreted as a record literal,
two readings of one text with no refusal on either side. That would be a real
defect and it was one edit away from being filed as one. Re-run with the filter
removed, the compiler refuses -- typed, located, fail-closed:
module index refused: 1 unparseable .dag source(s)
<probe>.dag:110-112: expected expression, found FatArrow
There is no ambiguity and no silent reinterpretation. The substrate did exactly
what DESIGN §5 requires; the only defect was the filter between the refusal and
the reader. A blank output is consistent with "the compiler said nothing wrong"
and with "the compiler refused and I could not hear it", and those have opposite
owners. Attributing an instrument's silence to its subject is how a clean
mechanism acquires a bug report it did not earn.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
'Narrow your filter and unexpected shapes arrive as silence' names the symptom. The mechanism is that a grep for `^error|blocking` is not a VIEW of the output, it is a HYPOTHESIS ABOUT the output -- and it discards exactly the cases where the hypothesis is wrong. That is actionable in a way 'check your instruments' is not, because it says which artifact to distrust. Generalises past greps to any flag suppressing a channel a conclusion is about to be drawn from: a quiet push that hides a rejection leaves the author claiming content that was never delivered. Framing credited to smart-ram-730, who arrived at it from a -q on a push while I arrived at it from four blanked sweeps. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rehome the finding as a qualitative brief, and delete the census the bankruptcy ruling forbids
#9132 merged six minutes after #9139 was filed, deleting docs/probes whole under
the operator ruling "less measuring, more fixing" and its rule: name the
instrument, never transcribe its output. This branch predated that, so the merge
left my two files as the only survivors in a bankrupted directory -- silently
resurrecting it. Both are removed.
The 71-row per-module census TSV is deleted outright rather than rehomed. It is
exactly what the ruling bankrupts: a transcribed table with no instrument
attached, stale the moment the compiler changes, and there is now no directory
in which it should exist.
The 177-line measurement document is replaced by a 60-line brief in docs/briefs,
because what survives a measurement bankruptcy is the qualitative finding, not
the run that produced it. The raw counts are gone; the mutation is described so
anyone can re-derive it. It is filed as a companion to instrument-traps, whose
"a false absence is worse than a false green" it answers with the one cheap
mechanical remedy that class has:
Before trusting an empty sweep, break something the sweep should catch.
The finding itself is unchanged. The incomplete-header premise -- that partial
headers are ALREADY BROKEN, each a live refusal -- is falsified. Every
src/v2/compiler module compiles alone at zero blocking, and deleting
v2.compiler.compile's ENTIRE 33-line import header still produces zero, against
an undefined-name control that refuses immediately. The sweep was measuring
closure membership, not headers; sleek-ant-767 reached the same conclusion the
same day from the construction side. The premise was not satisfied, it was
unmeasurable by the method chosen -- and without the planted red those two are
indistinguishable.
No repair PR is opened. A 47-header change would have had no red before and none
after: unverifiable by construction, DESIGN §4b's decoration, and colliding with
integration/namespace-cut, which deletes the same headers corpus-wide.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com