Skip to content

Follow the rename #10865 made: grain_admits_single_cabinet is now grain_offers_single_cabinet - #10968

Merged
briansrls merged 1 commit into
mainfrom
session/quiet-cat-23-grain-rename
Sep 10, 2026
Merged

briansrls merged 1 commit into
mainfrom
session/quiet-cat-23-grain-rename

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

main is red; this is the repair

required-ci: declarations FAIL IMPORT-MEMBER-ABSENT
  dag/test/claim/colo_nj_central_south_census_test.dag:13:51
  `test.claim.colo_nj_central_south_census` imports `grain_admits_single_cabinet`
  from `test.claim.colo_cabinet_density_witness`, which declares no such name

Neither contributing change is wrong in isolation

#10865 a675b706275 19:45:49Z renamed grain_admits_single_cabinet → grain_offers_single_cabinet in the shared witness module, updating every call site it could see
#10864 de7622e408f 19:46:19Z imports the old name — which existed when that PR was written

Thirty seconds apart. Both MERGEABLE/CLEAN with all four required checks green. Neither floor verdict could contain the other's change, because each was computed against a base that excluded the other.

Third instance today of one class

A stranded caller, produced by two changes whose verdicts were each concluded, correct, and about a base that no longer existed at merge time:

  1. the megarac §4c break (Boot Mt. Collins diskless through modeled operations #10630)
  2. mutation_status_is_commit_ambiguous — The R2 account and bucket are declarations, and the mint refuses before it creates #10925 wrote the import edge, Give GitHubEffect a REST performer whose shape is hermetically verdicted #10923 deleted its target (repaired in main is red: import mutation_status_is_commit_ambiguous from the module that declares it #10945)
  3. this one

The 30-second gap is the sharpest form, because it defeats the obvious remedy: waiting longer for a floor to conclude does not help when both floors had already concluded. Only a verdict computed against the base a change actually lands on catches this class.

The repair follows the rename rather than reverting it

grain_offers_single_cabinet carries the identical signature (g: RetailGrainStanding) -> Bool and the identical body — it folds retail_grain_single_cabinet_wording to a Bool. So this is a pure spelling change at eight call sites, onto the name the shared module now declares.

Evidence

  • GREEN by execution: gunbc compile --entry dag/test/claim/colo_nj_central_south_census_test.dag → rc=0, 0 blocking error(s), compiled: 61 files emitted, zero IMPORT-MEMBER-ABSENT. The completion marker is quoted beside the count deliberately — a count with no completion marker beside it is a claim about the pipeline, not about the subject.
  • RED control, on the real acceptance path: main's own required floor on de7622e408f, run 34522373789, reporting this exact finding. The failing content is this commit's parent.

Both contributing lanes are archived, so this was cut by a blocked lane rather than routed to an owner.

🤖 Generated with Claude Code

https://claude.ai/code/session_01998xs4ojJKWGptxcuxVWHN

…in_offers_single_cabinet

main is RED on the declarations check:

  required-ci: declarations FAIL IMPORT-MEMBER-ABSENT
    dag/test/claim/colo_nj_central_south_census_test.dag:13:51
    `test.claim.colo_nj_central_south_census` imports `grain_admits_single_cabinet`
    from `test.claim.colo_cabinet_density_witness`, which declares no such name

NEITHER CONTRIBUTING CHANGE IS WRONG IN ISOLATION, and the composition is the defect.
#10865 (a675b70, merged 19:45:49Z) renamed `grain_admits_single_cabinet` to
`grain_offers_single_cabinet` in the shared witness module and updated every call site it
could see. #10864 (de7622e, merged 19:46:19Z) imports the old name, which existed when
that PR was written. The two merged THIRTY SECONDS APART, both MERGEABLE/CLEAN with all four
required checks green, and neither floor verdict could contain the other's change.

This is the third instance today of one class: a stranded caller, produced by two changes
whose verdicts were each concluded, correct, and computed against a base that excluded the
other. The earlier two were the megarac §4c break (#10630) and the
`mutation_status_is_commit_ambiguous` rehoming (#10925 wrote the edge, #10923 deleted its
target). A 30-second gap is the sharpest form: waiting longer for a floor to conclude does
not help when both floors HAD concluded.

The repair follows the rename rather than reverting it. `grain_offers_single_cabinet` carries
the identical signature `(g: RetailGrainStanding) -> Bool` and the identical body — it folds
`retail_grain_single_cabinet_wording` to a Bool — so this is a pure spelling change at eight
call sites, and the new name is the one the shared module now declares.

EVIDENCE
- GREEN by execution: `gunbc compile --entry dag/test/claim/colo_nj_central_south_census_test.dag`
  -> rc=0, `0 blocking error(s)`, `compiled: 61 files emitted`, zero IMPORT-MEMBER-ABSENT.
  The completion marker is quoted beside the count deliberately: a count with no completion
  marker beside it is a claim about the pipeline rather than about the subject.
- RED control, on the real acceptance path: main's own required floor on de7622e, run
  34522373789, reporting this exact finding. The failing content is the parent of this commit.

Both contributing lanes are archived, so this was cut by a blocked lane rather than routed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01998xs4ojJKWGptxcuxVWHN
@briansrls
briansrls merged commit 291e31f into main Sep 10, 2026
4 checks passed
@briansrls
briansrls deleted the session/quiet-cat-23-grain-rename branch September 10, 2026 21:41
@briansrls
briansrls restored the session/quiet-cat-23-grain-rename branch September 10, 2026 21:43
gunbai-bot Bot pushed a commit that referenced this pull request Sep 10, 2026
… separately true

Operator ruling (crisp-lynx-452, 2026-09-10): file the row now, before these land;
the repair is dispatched as its own lane. An unrecorded wall found at 21:00 is one
the next person trying an effectful read rediscovers from scratch.

THE CLASS IS SHARPER THAN THE SYMPTOM. Not "the contents read is broken" but: a
REST operation is declared, hermetically witnessed and green, while its LIVE
decode path has never produced a value. The outcome classifies as SUCCESS because
a 200 did come back, and the decoded record is Null, so a consumer reads a
successful fetch that fetched nothing. Success and decode are separately true and
only one of them is checked.

THE DISTINGUISHING FACT IS WHY NO HERMETIC CLAIM CAN REACH IT. A mock_response
never passes through the wire decoder - it is authored .dag data published beside
the operation and substituted for the exchange. So the witness and the defect are
DISJOINT: not a weak test of the right thing, but a correct test of a different
one. Every strengthening of the hermetic claims makes the coverage look better
while leaving this exactly where it was, which is what makes it green for the
wrong reason rather than merely under-covered.

THE THREE NEGATIVE CONTROLS ARE IN THE ROW, not just the symptom, because without
them the next reader re-runs all three. Reverting the field to `size: Int` does not
change it, which rules out the Measure the review asked for. A throwaway operation
whose entire response type is one `sha: String` does not change it, which rules out
field-set strictness. And the outcome classified as RestExchangeSucceeded rather
than a transport arm, which rules out network and credentials and fixes the state
precisely: request made, 200 returned, body did not become the declared record.

THE BLAST RADIUS AND THE CITATION THAT STOPS AN ASSUMPTION. Every effectful REST
consumer inherits it, and on the evidence available no live REST read has passing
evidence anywhere in this corpus - gunbc.github_authenticated_user_read is the
only other live-capable consumer and its own annotation says live GET /user is not
executed. gunbc#10923 landed the performer they all sit on, titled "Give
GitHubEffect a REST performer whose shape is hermetically verdicted";
shape-verdicted and live-unexercised is exactly this gap, cited so the next reader
does not assume that change covered it.

RUNG mitigatable at best - loud when a consumer touches a field, silent for one
that does not, and a fold over a decoded list would report a repository with no
matching workflow, which is a fabricated observation through the success path.
CEILING a live-path probe enrolled as executing evidence. TRIGGER that probe
existing: one operation, one real credential, one asserted decoded field, run where
a required lane can see it.

Merged origin/main, which carries #10968's rename repair - the declarations
finding that was failing this branch's floor and was never attributable to it. The
claims re-run green on the merged tree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
gunbai-bot Bot added a commit that referenced this pull request Sep 12, 2026
… 200 is not an answer (#10964)

* The GitHub reads a public CI-workflow scan needs, with the arms where 200 is not an answer

THREE UPSTREAM OPERATIONS AND ONE CONSUMER, all read-only. A public-workflow scan
asks GitHub two questions - which repositories name a runner label, and what does
that workflow file say at an exact revision - and observes a third, what a run
actually did. Nothing here contacts anyone, executes third-party code, or is
reachable from an outreach or authorization constructor.

extdeps.github.code_search models GET /search/code, and models the reason a
population found this way is a DECLARED population: the endpoint caps a query at
1000 results, paginates at 100, is rate limited far more tightly than the rest of
the surface, and returns incomplete_results when its own search gave up early.

total_count IS MODELLED AND NAMED AS NOT A COUNT, because refusing to model what
upstream returns leaves a consumer nowhere to see that. Measured 2026-09-10 on
"depot-ubuntu-24.04-arm" path:.github/workflows: all three pages reported
total_count 250 while delivering 100, 100 and 91 items - 291 distinct
(repository, path, blob) triples, MORE than the total those same responses
declared. A population size read from that field is wrong by 41 in the direction
that under-counts, with nothing in the response saying so. Same class as the
actions/runs total_count the workload census already found reporting a 40000 cap
wearing the shape of a total. code_search_hits_read sits beside the field it
exists to displace so a reader choosing between them meets the reason.

THE REPOSITORY OBJECT IS NOT extdeps.github.github.Repository and modelling it as
one would have been a fabricated field. Observed: the repository inside a
code-search item carries id, name, full_name, owner, private and fork, and does
NOT carry default_branch, which Repository requires. That is a reduced upstream
representation, not a subset someone forgot to fill in, so it gets its own row.
`fork` is carried and explicitly not trusted: all 124 repositories that query
returned report fork: false, and whether the index excludes forks or none matched
is not established by the observation - while the same population contains several
independent copies of one upstream project under different owners, none of them
forks. A scan that deduplicates on that flag alone has not deduplicated.

extdeps.github.repository_contents is what turns a search hint into an identity. A
hit names a path and a blob at whatever revision the index held, which is not
something a later reader can return to; the ref is a REQUIRED input here, so no
arm of the interface reads "whatever the default branch says today". The returned
sha is the git BLOB sha, which is the identity a workflow-source observation is
keyed by: byte-identical workflow files share it and a commit that does not touch
the file does not change it. Measured: biomejs/biome at 47d7383d returns
.github/workflows/main.yml at blob 99f1255bbfa20a11197716a8fdb4c4e3359a588b.

ENCODING IS CARRIED BECAUSE 200 IS NOT ALWAYS AN ANSWER. Above its size ceiling
the contents endpoint returns 200 with an empty content string and encoding
"none". A reader that decoded unconditionally would get an empty file, find no
jobs in it, and record a repository as having no CI - a fabricated observation
arriving through the success path with no error anywhere. gunbc.ci_workflow_source_read
gives that its own refusing arm, beside an unrecognized-encoding arm, because a
reader that refused only the oversized one would still fabricate on the other.

WorkflowJobRun gains labels, run_attempt and runner_name. labels is the OBSERVED
runner label, which is a different fact from the declared one - a runs-on written
as an expression resolves at dispatch, and this fleet's own census carries a job
whose workflow offers a Ubicloud alternative and which ran on GitHub-hosted
ubuntu-24.04-arm. run_attempt is what makes a job identity re-findable, since a
re-run reuses run_id and mints new job ids. runner_name is a corroborating
observation and explicitly not a classifier: reading a provider out of
"depot-1mw2k81zm2" is the string grammar gunbc.runner_label_resolution exists to
refuse, wearing a different field's name.

A HIT IS NOT AN OBSERVATION, AND THE TYPE SAYS SO. canonicalize_hit is the only
bridge and it takes the ref as an argument, so no caller can promote an index
entry into an identity without naming one; an unread file never becomes an
identity however complete the hit that pointed at it was.

EVIDENCE, EXECUTED HERMETICALLY. Five claims in
dag/test/claim/ci_workflow_source_read_witness_test.dag, all green under
--dry-run against the published mock fixtures. The code-search fixture carries the
real total_count of 250 beside a single delivered item, so the fixture itself
EXHIBITS the defect rather than describing it, and a claim asserts the
disagreement - it goes red the day the two are made to agree. Without --dry-run
the same witness performs a real GET against api.github.com and fails, which is
the control that the mock is what the green is bound to.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* The refusing arms are exercised through the classifier the production read calls

review 63220, four findings, all confirmed against the code and all fixed.

THE ONE THAT MATTERED. read_of in the witness re-implemented, arm for arm, the
encoding decision inside perform_workflow_source_read - so the two arms this
change exists for were green only through the test's private copy, and the
production function's TooLargeForContentsApi and EncodingUnrecognized arms were
never executed by any claim. A copy cannot go red when the original is wrong.
That is specification-without-execution wearing coverage's clothes, and the arms
looked covered precisely because the copy agreed with them.

The cause was a fused concern rather than a lazy test. Fetching a page is an
effect; deciding what the page that came back MEANS is a total function over its
content. Fused, the refusing arms were unreachable through the effectful function,
because the published mock is a single base64 200 - so the only way to exercise
them was a twin. Split, they are ordinary function calls:
classify_workflow_source and classify_code_search_page are what the effectful
reads now call, and what the claims now drive.

THE RED WAS EXECUTED, NOT ARGUED: changing classify_workflow_source's
encoding-none arm to return WorkflowSourceObserved takes
the_oversized_response_is_refused_by_the_production_classifier from true to false.
Under the old shape that mutation changed nothing any claim could see.

THE SAME GAP EXISTED ON THE SEARCH SIDE AND WAS NOT FLAGGED. The mock publishes
incomplete_results false, so the truncated arm had no execution either. Upstream
saying it gave up is the one signal separating a small population from an
abandoned query, and a scan that never exercises that arm cannot claim to honour
it. It now has a claim, with its complete-arm control beside it.

THE PROSE ROW IS GONE. code_search_total_count_is_not_a_count was a String
declaration whose entire content was commentary, in a file already using // for
exactly that - section 4c's misplaced data, and nothing read it, so section 3c
dangling as well. It also transcribed an instrument's output. The replacement
annotation NAMES the instrument instead: the published mock carries the real
total_count beside a single delivered item, so the fixture exhibits the defect,
and total_count_disagrees_with_the_hits_actually_read is the claim that asserts
it. A real scan's page-by-page figures belong to that scan's own receipt, where a
reader re-derives them rather than reading a copy that cannot rot visibly.

hit_repository is deleted: no call site anywhere, and a second name for a field
access the record already names. The duplicated imports of code_search and
repository_contents collapse to one row each.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* The size ceilings become ByteSize; the size FIELD does not, and the probe says why

review 63237, two findings. The second is taken as asked. The first is taken in
part, and the part not taken is refused with an executed probe rather than an
argument.

TAKEN: THE CEILING WAS PROSE AND IS NOW A DECLARED ByteSize. The whole reason
WorkflowSourceTooLargeForContentsApi exists is a size bound, and that bound lived
only in a comment - section 4c's rule that an invariant belongs in a typed
carrier, read against the threshold the module's central arm turns on. Reading the
reference again to declare it found there are THREE bands and my prose had one:
"1 MB or smaller: All features of this endpoint are supported"; "Between 1-100 MB:
Only the raw or object custom media types are supported"; "Greater than 100 MB:
This endpoint is not supported." So the refusing arm covers the middle band and a
file above the top band is not served at all, arriving as a REST refusal rather
than through this arm. Both bounds are declared as ByteSize and the refusal cause
now carries them, because a refusal that cannot say what bound it hit is one a
reader cannot act on.

THE CLASSIFIER STILL DOES NOT KEY ON THEM, deliberately. What upstream SIGNALS is
the encoding - "none" is the endpoint saying it declined to inline the bytes - and
re-deriving that from a threshold of our own would be a second representation of
one fact, free to disagree with the vendor the day they move the band. The
vendor's signal decides; the ceilings are what the refusal reports.

NOT TAKEN: size STAYS A WIRE Int, and the sibling module cited is not a
counter-example. extdeps.github.hosted_runners carries ByteSize on AUTHORED
catalog rows read off a documentation page, not on a decoded response body, and no
response type anywhere in extdeps decodes into a Measure - measured by scanning
every 2xx response type in dag/extdeps for a Measure-typed field: zero. A bound
this repository asserts is a magnitude and is a ByteSize; the size field is the
shape of a JSON number upstream sends, which section 3 says an extdeps module
models as it is. Converting once at the boundary is the move when an inward
consumer needs the magnitude, and nothing here has one yet.

AND THE PROBE FOUND SOMETHING WORSE THAN THE QUESTION IT WAS BUILT TO ANSWER.
Running perform_workflow_source_read against LIVE GitHub with a real token, at the
exact fixture ref, refuses inside classify_workflow_source with `cannot access
field 'encoding' on Null`: the outcome classified as success, so a 200 came back,
and got.file is Null - the body did not decode into the declared record. Reverting
size to Int does not change it. A probe operation whose entire response type is a
single `sha: String` does not change it either. So this is not about ByteSize and
not about field-set strictness: the live JSON-body decode for a `200 => Record`
response produced nothing, and the hermetic path cannot see that because a
mock_response is authored .dag data that never passes through the wire decoder.

That is recorded here rather than worked around, and it bounds what this change
may be said to deliver: the classifiers and their refusal arms are executed and
green, the operations are modelled against a cited spec, and the LIVE read path
has no passing evidence in this change or anywhere else in the corpus - the one
existing live-capable consumer, gunbc.github_authenticated_user_read, says in its
own annotation that live GET /user is not executed either.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* File the class the live probe found: REST success and REST decode are separately true

Operator ruling (crisp-lynx-452, 2026-09-10): file the row now, before these land;
the repair is dispatched as its own lane. An unrecorded wall found at 21:00 is one
the next person trying an effectful read rediscovers from scratch.

THE CLASS IS SHARPER THAN THE SYMPTOM. Not "the contents read is broken" but: a
REST operation is declared, hermetically witnessed and green, while its LIVE
decode path has never produced a value. The outcome classifies as SUCCESS because
a 200 did come back, and the decoded record is Null, so a consumer reads a
successful fetch that fetched nothing. Success and decode are separately true and
only one of them is checked.

THE DISTINGUISHING FACT IS WHY NO HERMETIC CLAIM CAN REACH IT. A mock_response
never passes through the wire decoder - it is authored .dag data published beside
the operation and substituted for the exchange. So the witness and the defect are
DISJOINT: not a weak test of the right thing, but a correct test of a different
one. Every strengthening of the hermetic claims makes the coverage look better
while leaving this exactly where it was, which is what makes it green for the
wrong reason rather than merely under-covered.

THE THREE NEGATIVE CONTROLS ARE IN THE ROW, not just the symptom, because without
them the next reader re-runs all three. Reverting the field to `size: Int` does not
change it, which rules out the Measure the review asked for. A throwaway operation
whose entire response type is one `sha: String` does not change it, which rules out
field-set strictness. And the outcome classified as RestExchangeSucceeded rather
than a transport arm, which rules out network and credentials and fixes the state
precisely: request made, 200 returned, body did not become the declared record.

THE BLAST RADIUS AND THE CITATION THAT STOPS AN ASSUMPTION. Every effectful REST
consumer inherits it, and on the evidence available no live REST read has passing
evidence anywhere in this corpus - gunbc.github_authenticated_user_read is the
only other live-capable consumer and its own annotation says live GET /user is not
executed. gunbc#10923 landed the performer they all sit on, titled "Give
GitHubEffect a REST performer whose shape is hermetically verdicted";
shape-verdicted and live-unexercised is exactly this gap, cited so the next reader
does not assume that change covered it.

RUNG mitigatable at best - loud when a consumer touches a field, silent for one
that does not, and a fold over a decoded list would report a repository with no
matching workflow, which is a fabricated observation through the success path.
CEILING a live-path probe enrolled as executing evidence. TRIGGER that probe
existing: one operation, one real credential, one asserted decoded field, run where
a required lane can see it.

Merged origin/main, which carries #10968's rename repair - the declarations
finding that was failing this branch's floor and was never attributable to it. The
claims re-run green on the merged tree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* The refusal arm carries its refusal; two annotations move above what they describe

review 63269, three findings, all confirmed and all fixed.

THE ONE THAT MATTERED, and it is the module's own rule broken one screen below
where the module states it. canonicalize_hit bound the RestExchangePerformance and
discarded it, so a 404 on a deleted path, a 403 rate limit and a 500 all left as
one identical sentence. This module's opening note says in so many words that a
scan which cannot tell a rate-limit refusal from a repository with no matching
workflow folds both into "no candidate here" and never learns which - and the
function twenty lines later did exactly that. The other two non-reading arms
propagate their own located cause; only this one laundered a typed refusal into
prose.

IT IS A SEPARATE ARM RATHER THAN AN EXTRA FIELD, because the two states are not
the same kind of thing. HitNotCanonicalized means the bytes arrived and could not
be used - a fact about the file, already carrying the classifier's located cause.
HitReadRefused means the bytes never arrived, and what a caller needs then is the
performance, where the status and the transport disposition live. An optional
refusal on a row that usually has none is the shape that gets defaulted away.

THE ARM ALSO HAD NO CLAIM, which is why the collapse was unobserved as well as
unmodelled, and the new claims pick the pair that actually matters to a scan: 404
shrinks the population legitimately, 403 shrinks it because we ran out of budget,
and a scan that reads the second as the first reports a smaller world and never
learns it was rate limited. A transport loss is claimed too, since it reaches the
same arm and would otherwise be flattened into a zero by a reader expecting a
status. THE RED WAS EXECUTED: restoring the old collapsing arm takes
a_read_refusal_reaches_canonicalization_carrying_its_status from true to false.

TWO ANNOTATIONS WERE ATTACHED TO THEIR NEIGHBOURS. The WorkflowJobRun field
rationale sat after that type and immediately before WorkflowJobRunList, and the
total_count / incomplete_results rationale sat above CodeSearchRepository while
both fields live on CodeSearchPage two types later. Section 4c admits standalone
leading blocks attached to module-scope declarations, so as written each attached
to the wrong one - and a rationale attached to a neighbour decays silently the next
time a type is inserted between them. Both move above the declaration they are
about.

AND THE FRONTIER NOTE STOPS RESTATING ITS OWN ROW. The annotation and the
DissolutionCondition description carried the same NAMED CONSUMER / TRIGGER /
SUFFICIENT FOR content twice, free to drift; the typed row is the authority, so the
note is cut back to the irreducible why - that landing the page walk here would
mean landing a bounded-scan policy inside the change that models the endpoints it
calls.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* runner_name had no consumer in any change, so it goes; the other two get their frontier

review 63281, and it is right about all three fields. The answer splits, because
two of them have a named later consumer and one does not.

runner_name IS DELETED. It was added in the same motion as the other two because
the vendor's machine name is corroborating - the Biome baseline job reports
"depot-1mw2k81zm2" - and then nothing read it. Not in this change, and not in the
change that consumes the other two, which I checked rather than assumed. Section
3c admits a declaration whose consumer LANDS IN A NAMED LATER CHANGE, and there is
no such change for this field: interesting is not a consumer. Parking it behind a
frontier would have been the frontier used as a place to keep things, which is the
one way that mechanism goes bad.

labels AND run_attempt GET THE FRONTIER ROW THE REVIEW ASKS FOR, in the same file
and the same shape as the one already beside it. The review's sharpest line is the
one about padding: filling the starvation census's fixtures with labels: [] and
run_attempt: 1 is shape-completion, not consumption, and the annotation arguing why
the facts MATTER names no consumer and no trigger. Both are now stated.

THE TRIGGER NAMES THE CAPABILITY AND NOT AN ARTIFACT, per 4b(3): a production fold
outside test.claim reading BOTH fields, the capability being that an observed
runner label and attempt reach a consumer that can tell them apart from the
declared ones. Explicitly not satisfied by a witness constructing a WorkflowJobRun,
by a fixture carrying the fields, or by a consumer that reads one of the two - the
last because a consumer reading labels without run_attempt cannot tell a re-run's
warm timing from a cold one, which is half the reason the pair was added.

The annotation the fields carry keeps its argument and gains the record of the
deletion, so the next author meets the question rather than re-adding a field
whose only recommendation is that upstream returns it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* Narrow the live-REST row to what the evidence licenses, and add the two controls that isolate it

Two narrowings from the side chat's review of the relay, both correct, and one of
them resolves stronger than it asked for because it was checkable.

NARROWING 1, THE IMPORTANT ONE: THE ROW NAMED A MECHANISM IT HAD NOT ISOLATED. It
said "the live JSON-body decode produced nothing". What the evidence establishes is
the SYMPTOM at one boundary - a wet 200 did not become the declared record - and
the decoder is one candidate stage among acquisition, body reading, request
composition and projection. An error class that asserts an unisolated cause sends
its own repair to the wrong place. The row now carries the symptom and the absence
claim (no wet REST read in this corpus has evidence of producing a value), which is
what a failure-mode row should carry, and says explicitly that it names no
mechanism.

NARROWING 2 WAS ABOUT THE LOG AND IS NOW A FACT. The claim "at the exact fixture
ref" could not be read off the printed URL, because the run log renders the path
and not the query. Rather than downgrade it to "intended", it was established by a
discriminating status: the same call with a nonexistent ref - forty zeros - returns
404. The file exists on the default branch, so a dropped `ref` would have returned
200. The ref IS applied.

THAT CONTROL ALSO NARROWS THE FAULT, which is why it is worth more than the claim
it was run to defend. A 404 arriving as a typed RestExchangeStatusRefused proves
acquisition reached the service, the request was composed correctly including its
query, auth was accepted, and the status-refusal path works end to end. What has no
evidence of working is the step between a 200 body and a declared record.

A FIFTH CONTROL RULES OUT ONE OPERATION'S DECLARATION: the same symptom reproduces
on GET /search/code, whose response is a page record rather than a file record,
refusing with "cannot access field 'incomplete_results' on Null".

THE CEILING AND TRIGGER TAKE THE PROPOSED REPAIR GATE, which is better than "fix
the decoder" precisely because it isolates the stage these controls could not: a
captured 200 receipt with body byte count and hash, content type, requested ref and
body-read arm; a REPLAY of that exact body through the production dispatcher
asserting encoding, sha, content and size against a UNIQUE SENTINEL so a replay
cannot pass on a coincidence; then a wet rerun at the same ref.

AND THE ROW NOW CARRIES THE SAME SHAPE ONE LEVEL UP, owed by any queue built over
these reads: a decode or projection failure must produce a typed retry or requeue
disposition and never Succeeded, and a ledger may not admit Leased -> Succeeded
without a non-null schema-valid result AND a durable commit. That is this defect
restated as a state machine, and the reason to write the rule before the queue.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* Both frontier rows reach the fold that reads them, and one stops being an unreadable shape

review 63297, two findings, both confirmed. They are the same defect at two
grains, and it is the one this PR spent a round complaining about in someone
else's code: a declaration nothing reads.

FINDING 1: workflow_job_run_observed_runner_frontier_rows was a List<FrontierRow>
that no fold reached. gunbc.census_closure_frontier is the only fold over frontier
rows and it is fed by an explicit import list - its SIBLING IN THE SAME FILE is
enrolled there and the new one was not, so the row was invisible to
gunbc.dissolution_census and its trigger could never fire through the modeled path.
Enrolled beside it.

FINDING 2 IS THE SAME DEFECT ONE LEVEL WORSE. ci_workflow_scan_producer_frontier
was authored as a standalone DissolutionCondition, which is not merely unenrolled
but UNENROLLABLE: the census folds List<FrontierRow>, there is no
List<DissolutionCondition> anywhere in the corpus, and the module's entire
declared-frontier state was therefore recorded in a shape no fold can read. A
trigger stated only in prose is not stated to the machine. It is now a FrontierRow
and enrolled.

WHAT MAKES THIS WORTH MORE THAN TWO LINE EDITS: the same change used FrontierRow
correctly one file over, in extdeps.github.workflow_runs, and still authored the
other one as a bare condition. The reason is traceable - the pattern was copied
from gunbc.github_authenticated_user_read, which carries
github_authenticated_user_read_consumer_frontier as a bare DissolutionCondition
and appears nowhere in census_closure_frontier. So the shape was inherited from a
row that has the same defect, and copying a neighbour is how an unreadable
carrier propagates. That row is not repaired here - it is not this change's
subject and it deserves its own diff - but it is named so the next author copying
it meets the question.

Both groups verified to reach the fold by running it:
census_closure_frontier_row_groups now contains the ci_workflow_source_read and
WorkflowJobRun subjects. Claims re-run green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* An identity is a join of two things that agree, not a concatenation of two in scope

THE POSITIVE WITNESS REQUIRED THE DEFECT, which is the part that makes this worse
than an ordinary bug. canonicalize_hit took the search hit and the file read as
INDEPENDENT arguments and combined them without comparison, so it admitted a
fabricated hybrid: LLVM's repository identity carrying Biome's path and blob,
asserted as one observation of a file that has never existed. And
a_read_file_canonicalizes_to_an_identity_carrying_the_ref_and_blob asserted
exactly that combination was correct. Repairing the code would have turned the
witness RED and the repair would have read as a regression. A wall that requires
the invalid state is worse than no wall.

IT IS THE CircleCI CLASS AGAIN, one PR over. Every guard here answers a MISS - the
file was too large, the encoding was unrecognized, the read was refused. A hybrid
is a HIT: two well-formed values combined into a third that is wrong about the
world, and no miss-shaped arm can see it.

THE CAUSE WAS THAT THE READ DID NOT CARRY ITS REQUEST. RepositoryFileContent has
name, path, sha, size, encoding and content, and NO repository - so a file record
cannot say where it came from and a consumer holding one cannot check it got what
it asked for. WorkflowSourceRead now carries a WorkflowSourceRequest beside the
response, and canonicalization is a JOIN that refuses when the hit and the request
disagree on repository or on path.

BOTH MISMATCH DIRECTIONS ARE CLAIMED, because refusing only the repository case
would still admit a blob from a different FILE in the right repository - which is
the subtler one and the one a scan would actually hit, since a repository holds
many workflows.

THE REF IS NO LONGER A CALLER ARGUMENT and it is no longer a String. It comes from
the request the read was made with, so an identity cannot be labelled with a ref
the fetch did not use; and it is a CommitSha because "main" is not an exact ref - a
branch name names whatever it points at today, and an observation keyed by one
cannot be returned to. The previous signature accepted "main" and called the result
an exact-ref boundary.

EVIDENCE. Six claims green, and the red executed: removing the repository
comparison takes an_identity_is_never_assembled_from_two_different_subjects from
true to false. The fixture pair is now coherent - the LLVM hit against an LLVM
request for LLVM's own premerge.yaml - so the positive claim asserts agreement
rather than requiring a hybrid.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* The total_count anomaly is a property of a page WALK, and the old claim was true of every response

review finding, confirmed. total_count_disagrees_with_the_hits_actually_read
asserted 250 != 1 on a single mocked page. That is true of EVERY paginated
response ever returned — a first page of 100 out of a genuine 250 satisfies it
just as well — so the claim was green for a reason with nothing to do with the
anomaly it was named for. Same shape as a roster-size oracle: an assertion whose
truth is guaranteed by the shape of the data rather than by the property under
test.

THE ACTUAL ANOMALY IS A SUM ACROSS PAGES. Measured 2026-09-10 on the depot-arm
query: three pages each reported total_count 250 and delivered 100 + 100 + 91 =
291. The population handed over EXCEEDED the total those same responses declared,
which ordinary pagination cannot do. The fixture now carries all three real page
sizes rather than one item standing in for a walk, and the claim folds them and
compares the sum.

AND THE ORDINARY CASE MUST NOT SATISFY IT, which is the part the old claim had no
way to express. A first page of 100 out of a genuine 250 is normal, and the second
claim asserts that shape stays FALSE — otherwise the property is once again true
of everything and says nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* Delete the anomaly claims rather than write a third vacuous version, and drop the stale citation

review 63571, both findings confirmed, and the second is the harsher one: I
replaced a vacuous claim with a differently vacuous claim and reported it as a
fix.

THE REPLACEMENT EXECUTED NO PRODUCTION CODE. observed_page_sizes = [100, 100, 91]
is a transcribed measurement; pages_total_delivered sums it; the claim then asserts
the sum equals 291, the count equals 3, the sum exceeds 250, and 250 equals 250.
Every conjunct is a literal compared against the sum of literals. Automating the
literals collapses it to measure() == measure(), which is section 5's own tell for
a change detector — and section 6's "name the instrument, never transcribe its
output" forbids the constants outright.

THE CLAIMS ARE DELETED RATHER THAN REWRITTEN, because a third version would have
been vacuous too and I would not have seen why. THE ANOMALY IS A PROPERTY OF A
WALK AND THIS MODULE DOES NOT WALK: it classifies ONE page, the pagination belongs
to the caller, and the receipt recording how many pages were read and what each
delivered belongs to the scan that performed them. A claim here could only ever
re-type numbers produced somewhere else. The witness now asserts what it can
actually drive — a page upstream marked incomplete is not a complete one, and an
ordinary page is — and says in the module why the cross-page reading is absent.

AND A STALE SYMBOL CITATION I CREATED ONE COMMIT EARLIER. The annotation named
total_count_disagrees_with_the_hits_actually_read as its instrument; that claim was
renamed out of existence by the commit that wrote the replacement, leaving the
citation's only grep hit as the comment itself. Section 3 is explicit that a stale
name is decidable and enforceable — and this one was created by the same change
that should have checked it.

The same block was also substantively false beside being stale: it said the
published mock "EXHIBITS the defect", which a single item beside a total of 250
does not — that is ordinary pagination, and the witness three files over now says
so explicitly. Two sources answering one question with one of them known wrong.
Both sentences are deleted rather than repaired, and the block now says why no
local instrument can be named here at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* Delete the exhibits claim where it actually lived, and stop asserting a deletion I had not verified

review 63598, confirmed. The sentence I reported as removed survived verbatim in
the mock_response description a hundred lines below the annotation announcing its
removal — so for one commit this file carried BOTH the removal notice and the thing
it said had been removed, and a reader had two contradictory statements about one
fact with no way to tell which was current.

WHAT I ACTUALLY DID LAST TIME: deleted one copy, wrote "both are gone rather than
repaired", and did not grep. The claim of completion was the defect, not the
sentence I missed — one grep would have shown two hits, and I asserted a whole-file
property from a single-site edit. That is the same shape as every other finding
against me tonight: evidence that is correct about the thing I looked at and wrong
about the thing I claimed.

THE MOCK NOTE NOW STATES WHAT THE FIXTURE SHOWS rather than what I wanted it to
prove: a real hit and a real total_count of 250, and explicitly nothing about the
cross-page anomaly, because one item beside a total of 250 is ordinary pagination.
A mock description asserting evidence it does not carry is exactly the string a
later reader cites as coverage.

AND THE ANNOTATION NOW RECORDS THE SECOND ATTEMPT rather than claiming a clean
removal. It says a witness claim was named here and deleted for being green by
construction; that an exhibits sentence was removed from that block and survived
below where review found it; and that the note now says what the fixture actually
shows. A removal notice that was itself wrong is worth keeping as a record rather
than quietly correcting.

SWEPT THE REST OF THE DIFF RATHER THAN FIXING THE CITED LINE ALONE, since the
finding is about asserting an unverified property: every specific symbol these
annotations cite resolves to a real declaration, and the one other completion claim
in the diff — "THE REF IS NO LONGER A CALLER ARGUMENT" — checks out, canonicalize_hit
takes hit and read only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* Three subjects have to agree, and a branch name is not an exact ref

Two exact-head findings from the side chat, both soundness, both unfreezing the
head. Both are residuals of MY OWN previous fix to this function.

I CHECKED TWO OF THREE SUBJECTS. canonicalize_hit compared the hit against the
REQUEST and then built identity.workflow_path from the RESPONSE, without ever
checking that the response named the file the request asked for. So a coherent LLVM
request could return a record naming Biome's main.yml and the hybrid was minted
anyway - one field further along than the version I had just repaired, and my
positive claim did not catch it because its fixture happened to have request and
response agree. The join now requires all three to agree and says so.

AND DECLARING A FIELD CommitSha DID NOT MAKE "main" UNWRITABLE, though I wrote in
the annotation that it did. CommitSha is an unvalidated String alias on this tree;
the declaration renamed the obligation and created no wall. std.types already
carries commit_sha_text_holds for exactly this - a validating CHECK a caller must
remember to run, whose own comment says it dissolves when CommitSha gains a
validating constructor - and the join runs it. The annotation is corrected rather
than quietly fixed, because the false sentence is the more dangerous half: a reader
would have believed the type was doing work it was not.

EVIDENCE. A response naming another file is refused with the response's own path in
the cause. A request at ref "main" is refused naming the 40-hex requirement, with a
real sha still admitted beside it so the check is not refusing everything.

WHAT I WOULD FLAG ABOUT THIS PAIR: both are inside the fix for the previous
finding, and both are the same shape as it - an identity assembled from sources
that were never compared. I repaired the two comparisons I had been shown and did
not ask what else the identity was built from. The answer was: the response, which
I had verified agreed in the one fixture I happened to write.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* Split the canonicalization refusal by repair, before review had to ask twice

NOT A REVIEW FINDING ON THIS PR. review 63714 found the same defect in the sibling
module - one arm carrying materially different contracts with English as the only
discriminator - and I checked here rather than waiting to be told twice. The
measurement: seven HitNotCanonicalized construction sites and five string_contains
on a cause in the witness.

SIX CONTRACTS WERE IN ONE ARM. A file too large for the contents endpoint, an
unrecognized encoding, a repository that differs from the hit, a requested path
that differs from the hit, a response path that differs from the request, and a ref
that is not a commit sha. A consumer could not route any of them and the claims
reached into the cause to tell them apart.

THE SPLIT IS BY REPAIR, WHICH IS WHAT MAKES IT A SPLIT RATHER THAN A RENAME.
HitFileUnreadable: the bytes arrived and cannot be used, re-read through a
different endpoint. HitSubjectsDisagree: a caller paired the wrong things, and it
carries a typed SubjectDisagreement naming WHICH pair - repository, requested path,
or response path - because those three share an owner but not a remedy.
HitRefNotExact: a caller supplied a branch name, and the arm carries the ref so a
consumer does not parse it out of a sentence. HitReadRefused already existed and is
unchanged: the bytes never arrived at all.

THE WITNESSES NOW MATCH ON THE VALUE. The three subject-disagreement claims read
the typed disagreement rather than a phrase; the ref claim asserts ref == "main"
rather than searching for "40-character lowercase hex". Two string_contains remain
in the file and both are content checks on a single-fact arm's only payload - they
verify a cause carries the right information, not which fact occurred.

WHY I DID THIS UNASKED, ON A PR THAT IS APPROVED AND FROZEN: the freeze admits
soundness, and by the criterion the sibling review applied - one name, two
materially different contracts, consumers unable to route - this is the same class
at larger scale. Five times tonight I fixed the instance I was shown and left the
neighbourhood; the pattern is the thing worth acting on, and acting on it here cost
one head reset against a finding that was going to arrive anyway.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* Make the fixture I already edit compile against the WorkflowRun main gave it

MAIN'S TYPE GAINED FIVE FIELDS AND MAIN'S OWN FIXTURE DID NOT FOLLOW.
extdeps.github.workflow_runs WorkflowRun now carries head_branch, event,
run_attempt, actor and triggering_actor; the four WorkflowRun literals in
dag/test/claim/superseded_run_starvation_census_witness_test.dag still construct it
without them, on main as of 51405ad. I verified that with git show against
origin/main rather than inferring it from my own tree.

WHY I AM REPAIRING IT HERE RATHER THAN LEAVING IT, having refused to do exactly
this twice tonight. The break only bites a branch whose floor subject closure
INCLUDES that file, which is why session/proud-newt-20 went green through it an
hour ago. Mine includes it because this change EDITS it - the WorkflowJobRun
fixture updates are in this diff. So no other lane is blocked, no other lane will
fix it, and waiting is waiting indefinitely for a repair nobody is motivated to
make. That is the unattainable-gate shape again, and the honest move is to say so
and clear it.

The distinction from the colo rename and the DurableOriginRead stranding, which I
did leave alone: those were files this change does not touch, where a separate PR
was the right home and one already existed. This is a file this change already
modifies, and the fields are added to literals I am already editing.

MECHANICAL AND VERIFIED, NOT GUESSED: event takes "push" and run_attempt 1, which
are the values a first attempt of an ordinary push-triggered run carries; the three
optional fields take none. The census's own claims resolve and pass afterwards,
where before the file did not resolve at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* The arm the check order made unreachable, and an edit that silently did nothing

review 63755, confirmed exactly as described, and the diagnosis is precise:
RequestedPathDiffersFromHit was unreachable on its own fixture. canonicalize_hit
checks response-against-request BEFORE request-against-hit, and the fixture's
response ALSO differed from the request - so the earlier arm fired every time and
the later one never ran. The claim passed on the wrong refusal.

Compounding it, the match accepted HitFileUnreadable, HitRefNotExact and ANY
HitSubjectsDisagree as success, so deleting or miswiring the arm changed nothing it
could see. An arm that looks covered and is not - the class this PR keeps fixing
elsewhere, now in the claim written to fix it.

THE FIXTURE NOW REACHES THE ARM: a response carrying the REQUESTED path, so
response-against-request agrees and only the hit disagrees. The claim names
RequestedPathDiffersFromHit specifically and asserts both paths off the typed
disagreement.

AND THE PART WORTH RECORDING ABOVE THE FIX. My first attempt at this repair
SILENTLY DID NOTHING. The replacement searched for text containing
HitNotCanonicalized, which the previous commit had already renamed into the split
arms, so the anchor did not exist and the edit was a no-op - while I moved on
believing the claim had changed. The only thing that caught it was running the
mutation: the arm was deleted and the claim still returned true. Had I not run the
red I would have pushed an unchanged claim and reported it fixed, which is the
exact failure this review is about, one level up.

The replacement now asserts its own anchor before writing. That is the cheap
mechanical guard for the class: an edit that cannot find what it is replacing must
fail loudly rather than leave the file alone and let the author narrate a change
that did not happen.

EVIDENCE: green true; disabling the request-against-hit arm takes it to false;
restoring returns true.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

* Three witness defects, all from my own mechanical edits — and one near-miss worth recording

review 63777, three findings, all confirmed and all introduced by ME expanding
match arms with a regex two commits ago.

ONE TRUE ARM, NOT THREE. an_unread_file_never_becomes_an_identity returned true
from HitFileUnreadable, HitSubjectsDisagree AND HitRefNotExact, so it discriminated
only against HitCanonicalized and HitReadRefused. The oversized half one line above
got this right; the encoding half did not, because the regex that split the arms
set every non-canonicalized arm to the value the old single arm had. It is now
HitFileUnreadable alone, pinned to the repository name.

WORTH BEING PRECISE ABOUT THE RED HERE RATHER THAN CLAIMING MORE THAN I HAVE:
misrouting this read to a different refusal arm is a COMPILE refusal, not a runtime
red, because the arms carry different payloads - HitReadRefused takes a performance,
HitSubjectsDisagree takes a disagreement. I tried that mutation and it failed to
resolve. The classification distinction that CAN vary at runtime - too-large versus
unrecognized-encoding, both landing in HitFileUnreadable - is guarded by
an_unrecognized_encoding_is_refused_by_the_production_classifier, which I mutated
and watched go false. So the coverage is real but it is split across two claims, and
saying "this claim now has a discriminating red" would have overstated it.

TWO DUPLICATED HitCanonicalized ARMS deleted, in the two matches where my earlier
edit added an arm a block already had. A second arm on a closed variant is dead
code at best and a mis-edited elimination at worst, in the file that exists to be
the executing evidence.

CommitSha IMPORTED. Used at fixture_ref and never imported - the same class I fixed
in the sibling witness four commits ago, and the same class the floor has failed
this branch for twice from main's side.

THE NEAR-MISS, RECORDED BECAUSE IT IS THE MOST USEFUL THING IN THIS COMMIT. My
first repair was a whole-file regex that deduplicated arms by name. Its block
detector never reset, because most matches in this file open across several lines
and did not match its pattern - so it treated arms from LATER blocks as duplicates
of earlier ones and deleted real assertions, including
HitRefNotExact => ref == "main" and the positive identity check. The file then
failed to resolve for an unrelated-looking reason and I reverted rather than
chasing it. Had it happened to still compile, I would have pushed a witness with
its assertions silently removed while reporting three findings fixed.

Both repairs in this commit are anchored: every replacement asserts its target
exists before writing, and the two duplicate deletions are by line number after
reading the blocks. A mechanical edit over a file I cannot fully see is the tool
that produced the defect and the tool I reached for to fix it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant