Repository navigation
Follow the rename #10865 made: grain_admits_single_cabinet is now grain_offers_single_cabinet - #10968
Merged
Merged
Conversation
…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
This was referenced Sep 10, 2026
Closed
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
main is red; this is the repair
Neither contributing change is wrong in isolation
a675b706275grain_admits_single_cabinet→grain_offers_single_cabinetin the shared witness module, updating every call site it could seede7622e408fThirty seconds apart. Both
MERGEABLE/CLEANwith 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:
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)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_cabinetcarries the identical signature(g: RetailGrainStanding) -> Booland the identical body — it foldsretail_grain_single_cabinet_wordingto aBool. So this is a pure spelling change at eight call sites, onto the name the shared module now declares.Evidence
gunbc compile --entry dag/test/claim/colo_nj_central_south_census_test.dag→rc=0,0 blocking error(s),compiled: 61 files emitted, zeroIMPORT-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.de7622e408f, run34522373789, 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