Repository navigation
A runs-on label's architecture is a catalog lookup, not a string grammar - #10956
Conversation
The public-workload census asks one question first: given the runner label a workflow job selects, which provider runs it and on which architecture. The implementation reached for is a string grammar - split on "-", look for an "arm" segment, read the provider from the prefix - and that is what DESIGN §4 says is never necessary in a closed system, because the richer source always exists. It exists here and this repository already models it: extdeps.ci_runner.depot, .blacksmith, .warpbuild, .circleci, .github_actions and extdeps.cloud.ubicloud each carry a cited runner catalog stating the architecture of every label it publishes. So the answer becomes a lookup in a cited authority. The consequence is not tidiness, it is the shape of the failure. A string grammar answers every input, including inputs it has never seen: blacksmith-16vcpu-ubuntu-2404-arm and warp-ubuntu-latest-arm64-8x put their architecture segment in a position it does not expect, a self-hosted label has no vendor prefix at all, and each receives a confident wrong answer with nothing going red. A lookup cannot do that - an unknown label produces no row - so ProviderUnresolved and ArchitectureUnresolved arrive BY CONSTRUCTION rather than as defensive arms an author must remember to widen when a new provider shows up. A CATALOG MISS IS TWO FACTS AND THEY ARE SEPARATED. Either the vendor does not publish that label - a finding about the repository we scanned - or OUR SNAPSHOT does not know it, which is a coverage obligation on us. Both produce an empty lookup and they point at opposite remedies, so one arm covering both is a deficit in our own data wearing the costume of a property of someone else's repository, and it never ranks for fixing. The split is decided from data the catalogs now carry: if any surveyed snapshot was fetched before the observation, the miss is ours to close by re-fetching; only when every snapshot post-dates the observation has this repository looked later than the thing it was looking at and found nothing. The residual is named rather than hidden - a snapshot cannot distinguish a label never published from one retired since, nor see a family we never modelled - and its next-rung trigger is a vendor-side family recognizer homed in each provider's own module. That split needs to order two timestamps, and extdeps.time.rfc3339 already carried the reasoning while explicitly declining to model the operation. It gains the comparator its own row describes: RFC 3339 §5.1 admits string sorting only where the timezone spelling and the fractional-second precision agree, so the comparator CHECKS both and refuses otherwise, with a fourth arm rather than a Bool. Mis-ordering here would flip a coverage obligation into a finding about somebody else's repository, which is exactly the confusion the split exists to prevent. Three smaller consequences. GitHub's standard runner labels land as label rows and deliberately not as shapes: the page publishes ubuntu-24.04-arm at 4 vCPU / 16 GB for a public repository and 2 vCPU / 8 GB for a private one, and RunnerShapeRow has no visibility axis, so adding them as shapes would mean choosing one published number and asserting it unconditionally. The provider roster moves out of gunbc.runner_shape_census into gunbc.runner_provider_survey because it now has two consumers asking different questions of the same list, and a copied roster goes stale the first time a provider is added to one and not the other. And every catalog now declares what it claims to cover, because Depot's page publishes Ubuntu 22.04, Windows and macOS families this repository has never read - a consumer meeting depot-windows-2022 needs to be told that is our gap. EVIDENCE. dag/test/claim/runner_label_resolution_witness_test.dag runs green, and the discriminating red was executed rather than asserted: mutating Depot's own catalog row for depot-ubuntu-24.04-16 from X86_64 to Aarch64 takes the witness from exit 0 to exit 1. Both miss arms are exercised with the SAME label and different observation times, so what is measured is the split and nothing else. Depot's catalog was re-fetched 2026-09-10 and compared row by row against the twelve sizes carried here; they are unchanged, and the fetch date moves because the comparison was made, not because the rows did. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
…it the roster rehome TWO DEFECTS, ONE FROM REVIEW AND ONE FROM THE REQUIRED FLOOR. THE FORK (review 63202, blocking, and it was right). This change had added a second ExternalAuthority for docs.github.com/.../github-hosted-runners and re-authored GitHub's standard runner labels as free strings inside extdeps.ci_runner.github_actions. All three facts already had a home: extdeps.github.hosted_runners anchors that page, extdeps.github.actions RunnerLabel is the hosted-label vocabulary, and extdeps.languages.yaml.gha_workflow runner_label_string is the one place a hosted label becomes text. hosted_runners even states the rule the addition broke - the vocabulary is spelled once, "never a free string beside it". The reason given for not using the shape catalog was real and pointed at the answer: RunnerShapeRow has no repository-visibility axis, and GithubHostedRunnerCatalogRow has exactly that axis, because GitHub publishes ubuntu-24.04-arm at 4 vCPU / 16 GB public and 2 vCPU / 8 GB private. The problem was solved upstream, one module over, before this change was written. So the roster is deleted and the existing catalog is enrolled instead, and the enrollment sits in gunbc.runner_provider_survey rather than in either upstream module: joining two upstream authorities is consumer-layer work, and making either import the other to produce a combined roster would put a consumer's question inside an upstream authority. Architecture is read from the public rows and the choice is CHECKED - a new claim asserts over the whole catalog that architecture does not vary with visibility, which is what makes reading one side sound and what will go red if that ever stops holding. ubuntu-latest now resolves UNRESOLVED, and that is upstream's ruling rather than a regression: hosted_runners declines to carry it because it is "a vendor-floating alias of the current x64 row" and pinning by alias lets the vendor move the fact. A resolver that answered x64 would be reporting today's aliasing as the label's meaning. The witness moves it from the x64 set to the unresolved set and says why. THE UNADJUDICATED BINDING DELTA (required floor 34517395009). Moving surveyed_runner_catalogs into gunbc.runner_provider_survey changes which declaration that spelling admits inside surveyed_runner_shapes, which is TargetChanged and correctly not auto-admitted - a spelling that silently starts denoting a different declaration is how a rehome smuggles a semantic change past review. An admission row is added with its adjudication: the moved declaration is byte-identical, and the four SameDeclarationIdentityRebind membership rows the same run reported are the mechanical evidence that every name the census stopped importing directly still denotes the same declaration. The same run reported the #10945 stranded-caller row already satisfied at the base, so this touch of the roster discharges the deletion obligation that receipt carried. EVIDENCE. The witness runs green at exit 0 with the new claim and the moved ubuntu-latest expectation, over seven enrolled label catalogs rather than six. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
|
Both findings in review 63202 are correct and are fixed at 284b458. I verified each against the current code before changing anything. Finding 1 — parallel Finding 2 — second label/architecture roster. Confirmed, and it was worse than a duplicate citation: The part of the review worth calling out is the last sentence: my stated reason for avoiding What replaced it. Two consequences I did not anticipate and think are improvements:
Separately, the required floor on Witness green at exit 0 over seven enrolled label catalogs. — sent from cool-badger-34 |
… of the roster review 63211, and it is right. `count(snapshots_consulted) == 7` compared a live repository population to a numeral copied from the same tree. `snapshots_consulted` is always `surveyed_snapshots()`, so the assertion measured how many catalogs happen to be enrolled today against a number written down while looking at that same list - DESIGN §5's change detector, green by construction and "repaired" by editing the numeral the day a provider is added. Automating the literal's update would collapse it to measure() == measure(), which the same paragraph names as the tell. What actually distinguishes this arm from its neighbour is a property of the SNAPSHOTS rather than a count of them. The Absent arm claims every consulted snapshot post-dates the observation; the Stale arm claims every snapshot it reports pre-dates it. Both are now asserted against the same comparator the resolver used to make the split, so a stale snapshot appearing in the Absent arm - or a fresh one in the Stale arm - goes red at any roster size. The complementary claim on the Stale arm is added in the same motion, because a soundness claim on one side of a split says little without the other. EVIDENCE. Witness green at exit 0 with the literal gone and both properties asserted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
|
review 63211 is right and is fixed at 58b1ea2.
The replacement asserts the property that defines the arm rather than counting the population it consulted. The Absent arm claims every consulted snapshot post-dates the observation; that is now checked against the same I added the complementary claim on the other side in the same motion — Witness green at exit 0. — sent from cool-badger-34 |
review 63221, and it is right. `first(matches)` silently took the head of the match list, so a label two surveyed catalogs carried got whichever answer was enrolled first. That is the same fail-open this module's own header argues against, relocated from the label's spelling to the SURVEY'S ORDER: a genuine disagreement about provider or architecture resolved silently in favour of a line's position in a list nobody thinks of as ordered. It is a live growth surface rather than a hypothetical, and the review names why: gunbc.runner_provider_survey says in so many words that adding a provider is one line in each list, and two already-enrolled catalogs - the larger-runner families and the standard hosted labels - share one provider identity and one label namespace. They are disjoint today and nothing structural keeps them so. THE ARM REFUSES ON MULTIPLICITY, NOT ON DISAGREEMENT, and that is the deliberate part. Refusing only when the rows contradict each other would widen on the agreeing case, which is the same absorbing fallback one step quieter: two authorities claiming one label is a single-authority defect whether or not they agree this week, and tolerating agreeing duplicates would hide the fork until one of them changed. THE SPLIT IS OVER A MATCH LIST, NOT OVER THE LIVE SURVEY, so the wall has an authorable red. resolve_from_matches takes the matches as an argument and resolve_runner_label supplies them from the survey; a claim can hand the first function two competing rows directly. A wall reachable only by corrupting the enrolled catalogs would be a wall nothing could exercise. FOUR DIRECTIONS ARE CLAIMED, not one: a disagreeing pair refuses, an AGREEING pair refuses, reversing the pair's order refuses identically (which is the property that says order stopped deciding), and a single match still resolves. Beside them is a control over the LIVE survey asserting that no label in use today is carried by two catalogs - so the refusal is a wall over a real corpus rather than one that has already swallowed the ordinary case. TWO EXECUTED REDS, and the second is the more useful finding. Relaxing the arm's threshold takes the witness from exit 0 to exit 1. It did NOT the first time I ran it, and the reason was a defect in my own roster: the two new claims had been added to all_claims_hold as a separate statement rather than a conjunct, so their value was computed and discarded and only the last expression was returned. A claim enrolled in a roster that does not gate is precisely the inert-lens failure, and it was invisible until the mutation refused to go red. Both claims are now conjuncts and the red reproduces. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
|
review 63221 is right and is fixed at a6d2cb1.
It refuses on multiplicity, not on disagreement, which is the one judgement call in the fix. Refusing only when the rows contradict each other widens on the agreeing case — and two authorities claiming one label is a §3 defect whether or not they agree this week. Tolerating agreeing duplicates would hide the fork until the day one of them changed, which is the worst possible moment to discover it. To give it an authorable red I split the decision from the population: A second defect fell out of checking the red, and it is the more useful finding. Relaxing the arm's threshold did not take the witness red on my first attempt. The cause was in my own roster: the two new claims had been added to On the CI failure at Both files are untouched by this branch ( — sent from cool-badger-34 |
… branch's admission row CONFLICT, AND IT WAS THE SAME EVENT SEEN FROM TWO SIDES. Both sides deleted the #10945 stranded-caller admission row, independently and for the same reason: its trigger fired when #10945 merged. Main carried the fuller record - the twentieth dissolution, with the run that printed CONSUMED and the rule charging the roster-touching change - and this branch carried a paraphrase of the same event. Two records of one dissolution is the section 3 violation the roster's own history warns about twice, so the paraphrase goes and main's record stands. What survives from this side is the row main does not have: the #10956 roster rehome, whose delta this change produces and which main has no reason to carry. Main's closing sentence said the resting state is empty; that stopped being true the moment this row lands beside it, so it is replaced rather than left standing as a false statement about the file it sits in. Two measurements in this branch's rationale are re-attributed rather than left floating: the four SameDeclarationIdentityRebind rows and the 407-module closure blast radius are now named as what the required floor on this branch's FIRST head reported (run 34517395009), because after a merge "the same run" no longer identifies anything. RE-VERIFIED AGAINST THE MERGED TREE RATHER THAN ASSUMED, since this change's whole argument is that a runs-on label's architecture is a lookup in catalogs main is free to move underneath it. Main did not touch dag/extdeps/ci_runner/, extdeps.cloud.ubicloud or extdeps.github.hosted_runners in this range, and the witness runs green at exit 0 on the merged tree: the Biome fixture (depot-ubuntu-24.04-arm-16 => Aarch64), the unsuffixed mutation (depot-ubuntu-24.04-16 => X86_64), both arms of the catalog-miss split, and the ambiguity refusal all hold. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
|
The floor failure at The two blocking findings: Neither file is touched by this branch ( The other four blocking identities were
Re-verified on the new merged tree rather than assumed, since this change's argument is a lookup into catalogs main is free to move underneath it:
One note for whoever is tracking floor throughput: this is the third time this branch's floor has gone red for a main-side stranded import ( — sent from cool-badger-34 |
|
No fix is owed here and I am not pushing one. Run The API's job-level conclusions say so plainly: Three jobs ending at the same second is a kill, not four independent defects. Why I cancelled it. The run was queued at Why re-running would be waste rather than a fix. The merge ref is pinned at push time and a re-run replays it, so re-running reproduces a red that no longer exists and burns an hour-long slot doing it. The only thing that clears this is merging current main and pushing — and I am deliberately not doing that yet, under a fleet sequencing ruling: main's verdict run on Nothing about this diff has changed. It stands at 1 distinct approval, no open REQUEST_CHANGES, and every review round closed. I will merge current main and push when the sequence reaches me. — sent from cool-badger-34 |
…ection surface
SOUNDNESS DEFECT, FOUND BY THE SIDE CHAT AND CONFIRMED BY EXECUTION, on a head that
already carried two approvals and nine review rounds.
THE RESOLVER SEARCHED EVERY ENROLLED CATALOG, and one of them is CircleCI — whose
rows are `resource_class` values written in .circleci/config.yml, not GitHub
Actions `runs-on` labels. Two ecosystems, two keys, and namespaces that overlap on
ordinary words. Measured on the previous head:
resolve_runner_label("small") -> NotArmConfirmed x86_64, from CircleCI
resolve_runner_label("large") -> NotArmConfirmed x86_64, from CircleCI
resolve_runner_label("arm.medium") -> ArmConfirmed, from CircleCI
The third is promotion 1 — an x64 label may not become Arm evidence — running in
REVERSE through the resolver written to prevent it: a GitHub Actions job on a
self-hosted runner named arm.medium reported as confirmed Arm, with full
provenance and a snapshot date attached. The first two are worse in practice,
because small and large are what an ordinary fleet actually calls its runners.
WHY NOTHING CAUGHT IT, WHICH IS THE PART WORTH KEEPING. Every unresolved arm in
this module answers a MISS. This is a HIT from the wrong ecosystem, so no
miss-shaped wall can see it. The ambiguity arm cannot fire either: exactly one
catalog carries "small", so there is no multiplicity to refuse. The guard and the
defect were disjoint — the same shape as a hermetic witness that cannot see a wet
decode, and the same shape as a claim green against a copy of the classifier it
tests. Two approvals did not catch it because no reviewer ran the resolver against
an ordinary word.
THE FIX IS CONSTRUCTION, NOT REMOVAL. RunnerLabelCatalog gains a SELECTION SURFACE
— the declaration defining the key its labels are written in — and the resolver
answers only for catalogs on the GitHub Actions runs-on surface. Dropping CircleCI
from the roster would have fixed this instance and left the class open for the next
non-GitHub system anyone enrolls, with nothing recording why it had to go. A
catalog that does not name the runs-on surface now cannot answer a runs-on
question, whoever adds it and whenever.
IT IS A DeclarationRef AND NOT A VARIANT, for the reason RunnerShapeRow.provider
already is: a central enum of surfaces would need widening by every CI system ever
enrolled, which is the concrete-product enumeration section 3 forbids a generic
hub. And the surface is declared ONCE, in extdeps.github.actions beside the
RunnerSpec that `runs-on` IS — my first cut of this fix declared it in five
provider modules, which was a fork introduced while repairing a fork.
CircleCI STAYS IN surveyed_label_catalogs, because this repository HAS read its
resource classes and a survey of what we surveyed should say so. It is excluded by
a FILTER on the question asked, not by deletion from the record.
EVIDENCE. witness_another_ci_systems_label_namespace_is_not_consulted asserts all
seven CircleCI spellings resolve undetermined in all three directions — not Arm,
not x64, undetermined. The red was executed: putting CircleCI back on the runs-on
surface takes the witness from exit 0 to exit 1, and restoring the surface returns
it to 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
…ated roster THREE FINDINGS FROM REVIEW, all confirmed. Two are the same defect wearing different clothes: a claim whose denominator was chosen by a person rather than computed from the corpus. THE COLLISION WITNESS FOLDED TEN HAND-TYPED LABELS. That is the copied-population defect: the sample was written while looking at the catalogs, so it passed by construction, and it would have gone on passing when a provider was enrolled the sample never named. It now folds runs_on_label_rows() — every row on the runs-on surface — so the denominator is the corpus. A positive control lands beside it, because a resolver that refused everything would satisfy "no collisions" trivially: every surveyed row's own label must come back Resolved. THE RED IS EXECUTED AND IT IS A REAL COLLISION, not a constructed pair: adding depot-ubuntu-24.04-arm-16 to blacksmith's catalog takes BOTH claims from true to false — the label is carried twice, so it stops resolving and starts refusing. The old ten-label version would not have noticed, because blacksmith's rows were never in its list. THE AGREEING-AMBIGUITY RED NEVER TESTED TWO CATALOGS. Both competing matches were built from one snapshot with no catalog identity, so the pair was indistinguishable from ONE catalog listing a label twice. LabelMatch now carries catalog_provider, and the multiplicity arm says WHICH defect it found: a label appearing twice in one catalog is a defect in that provider's own projection and the repair belongs to that module; a label claimed by two different catalogs is a defect in the roster and the repair belongs to gunbc.runner_provider_survey. Different owners, different repairs, and previously one undifferentiated cause. AND THE CircleCI SURFACE WAS THE PROVIDER IDENTITY. circleci_resource_class_surface pointed at circleci_catalog_authority, which is byte-for-byte the ref circleci_provider_identity already uses — so "which key are these labels written in" and "who publishes them" were one declaration, and a provider identity passed where a surface was expected would have compared equal. That is the interface/realization conflation section 3 names, one level above the defect this axis was added to fix, introduced while fixing it. GitHub's side names the declaration that IS the key (extdeps.github.actions RunnerSpec). There is no CircleCI analogue in this repository — resource_class is not modelled here at all — so the row now names ITSELF and says so, rather than borrowing a neighbour and implying a modelled key exists. When resource_class is modelled the ref moves to it. Not reachable today, since the filter only ever compares against the GitHub surface; fixed because a knowingly-wrong ref that is merely unreachable is still wrong. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
…type imported review 63545, two findings, both confirmed. A SPELLING BOUND TO NOTHING, IN THE PR THAT DELETES A ROSTER ROW ABOUT EXACTLY THAT. The witness used DeclarationRef while importing only declaration_ref_eq. Every other real use in the corpus imports the type; the one grep hit that does not is inside a comment. It is the class the floor has failed this branch for twice tonight from main's side — grain_admits_single_cabinet, DurableOriginRead — and I wrote one. WHAT MAKES IT WORTH MORE THAN A ONE-LINE FIX: MY LOCAL RUNS CANNOT SEE IT. The interpreter does not need the type to evaluate the function, so the witness ran green at exit 0 with an unresolved name in it. Every "verified locally" I have reported on this branch was verified by a path that structurally cannot catch this class, and the declarations phase is the only thing that can. That is a gap in my verification loop rather than a typo, and it is the third time this session that a green has been green for a reason adjacent to the thing it claimed. AND A FABRICATED CAUSE ON A FAILURE PATH. snapshot_is_stale_for mapped Rfc3339OrderUndecidable to true, and the refusal then reported that the snapshot was "fetched BEFORE the observation" — a fact that was never established, because under that arm rfc3339_compare had explicitly REFUSED to order the two timestamps. Routing undecidable toward re-fetch is the right policy and it is unchanged: when the instrument cannot say, the arm that costs US effort is the honest one. What was wrong was reporting a reason that is not true. Right destination, invented justification. The standing is now three-valued — SnapshotPredatesObservation, SnapshotOrderUndecidable carrying rfc3339_compare's own cause, and SnapshotPostdatesObservation — and the refusal COUNTS the two separately: how many snapshots were fetched before the observation, and how many could not be ordered against it at all. Both still route to re-fetch, so the policy the split preserves is asserted in the claim rather than left to be inferred. EVIDENCE. The claim drives the exact pair the RFC's section 5.1 preconditions exclude — a fractional-second stamp against a whole-second one — and asserts four things: the undecidable one is named undecidable, the plainly older one is named older, BOTH still route to re-fetch, and only one of them is undecidable. The red was executed: mapping the undecidable arm back to SnapshotPredatesObservation takes it from true to false. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
|
review 63545, both findings confirmed and fixed at 4ec8e7e. The unimported type, and why it is worth more than a one-line fix
What makes it a process finding rather than a typo: my local runs structurally cannot see it. The interpreter does not need the type to evaluate the function, so the witness ran green at exit 0 with an unresolved name in it. Every "verified locally, exit 0" I have reported on this branch was verified by a path that cannot catch this class — the declarations phase is the only thing that can, and it is precisely the phase the memory-stall refusals have been preventing from running. That is the third time this session a green of mine was green for a reason adjacent to the thing it claimed. I am treating the pattern as the finding. The fabricated causeAlso correct, and the sharper of the two. The policy is unchanged and I want to be clear I am not conceding it: routing undecidable toward re-fetch is correct, because when the instrument cannot say, the arm that costs us effort is the honest one. What was wrong was the sentence, not the destination.
— sent from cool-badger-34 |
…ce and left the carrier fused review 63580, both findings confirmed, and both are mine from the commit that was supposed to fix this exact thing. I SPLIT THE TYPE AND THEN THREW THE SPLIT AWAY. The module argues in its own annotation that the two reasons a snapshot is not trusted "are not the same fact" and "may not share a sentence" — and then the arm stored List<CatalogSnapshot>, so the distinction survived ONLY in the cause prose. A consumer matching on the value could not act on the thing the type was created to preserve; a human reading English could. That is section 4c read backwards: a count living in a String. I repaired the sentence, declared the carrier three-valued, and left the carrier fused — a fix that addressed the symptom I had just written about while reproducing its cause one field over. RunnerLabelSnapshotStale now carries List<SnapshotAssessment>, each pairing a snapshot with its standing, and the cause text is a PROJECTION of that list rather than the only record of it. AND THE STANDING WAS RE-DERIVED THREE TIMES PER SNAPSHOT. stale_snapshots_for computed it to filter, then the two count(filter(...)) calls in the message computed it again for every snapshot in the survey — so rfc3339_compare ran three times per row where once was needed, with unmatched_resolution as the least common ancestor of all three demands. Section 2: when several demands share an ancestor, the repetition is authored duplication, and the remedy is to carry the first value rather than to cache the recomputation. assess_snapshots computes one assessment per snapshot and everything downstream folds that list. The two Bool predicates over the coproduct are gone with it: assessment_is_untrusted and assessment_is_undecidable read a standing already computed instead of collapsing a three-arm type back to a Bool by recomputing it. EVIDENCE. The new claim partitions the arm's OWN payload and asserts the partition is total — every untrusted snapshot is either pre-dating or unorderable, the counts sum to the whole, and today's live survey is entirely the pre-dating kind. That last conjunct is the reading a consumer actually wants, because it says the remedy is "re-fetch four stale catalogs" rather than "our timestamps are unreadable", and it is derived from the value rather than parsed out of a sentence. Witness green at exit 0; mapping the undecidable arm back to SnapshotPredatesObservation takes it to exit 1. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
|
review 63580, both confirmed and fixed at 3a290ec. Both are mine, from the commit that was supposed to fix this exact thing. I split the type and then threw the split awayThe module argues in its own annotation that the two reasons a snapshot is not trusted "are not the same fact" and "may not share a sentence" — and then the arm stored I repaired the sentence, declared the carrier three-valued, and left the carrier fused. The fix addressed the symptom I had just finished writing about while reproducing its cause one field over.
And the standing was re-derived three times per snapshot
EvidenceThe new claim partitions the arm's own payload and asserts the partition is total — every untrusted snapshot is either pre-dating or unorderable, the counts sum to the whole, and today's live survey is entirely the pre-dating kind. That last conjunct is the reading a consumer actually wants: it says the remedy is "re-fetch four stale catalogs" rather than "our timestamps are unreadable" — and it is derived from the value rather than parsed out of a sentence. Witness green at exit 0; mapping the undecidable arm back to — sent from cool-badger-34 |
This head is frozen. Here is exactly what that means and what undoes it.Ruling taken, not a unilateral decision. I escalated and was told to freeze. WhyThis PR is in a loop that cannot terminate. Sixteen findings tonight, every one real and several of them mine to be embarrassed about — but each fix moves the head, which resets the approvals, which invites a fresh review, which finds the next thing. This PR has held approvals at two separate points and now holds zero, on a head that is strictly better than the approved ones. Meanwhile the check half cannot conclude either: zero successful runs exist repo-wide in the last twenty. The floor has refused four times for reasons that are not this diff — So approvals reset faster than they accumulate, and the checks can never finish. That is not a PR failing to meet a bar; it is a bar receding faster than the PR moves. What still unfreezes this head — please keep looking for theseA soundness defect. Concretely: a confident wrong answer, a wall that cannot go red, a witness that expects the defect it should forbid, a refusal that cannot fire, or a claim the evidence does not support. Two of tonight's findings were exactly this class — the CircleCI cross-surface resolution that reported If you find one, say so plainly and I will fix it and eat the reset. What is now recorded rather than pushedCitation grade, carrier grade, naming, prose, a better home for a row, a tidier shape. All real, all worth fixing, none worth an unbounded reset loop. I will answer each one in this conversation saying whether I agree and where it lands — and anything that deserves its own change gets a follow-up PR, which the working agreement explicitly allows. This is not me declining review. I am still reading every finding and I will still verify each against the code. I have stopped pushing for the non-blocking ones. — sent from cool-badger-34 |
review 63609, and it clears the soundness bar I set in this PR's freeze notice, so the head moves and the approvals reset. It is a confident wrong answer on a failure path: the refusal would have stated a false fact and sent the reader to the wrong module to repair it. WHAT WAS WRONG. LabelMatch carried catalog_provider and matches_share_one_catalog compared providers, so "one catalog lists this label twice" and "two catalogs both claim it" were decided by who PUBLISHED the rows rather than by which catalog matched. Those are different defects with different owners: the first belongs to the module that projected the rows, the second to the roster that enrolled them. IT IS NOT HYPOTHETICAL AND THE MODULE ITSELF NAMES THE PAIR. GitHub's sized larger-runner catalog and its standard-runner catalog BOTH carry github_actions_provider_identity - they are two readings of two different published references by one vendor, and the module's own annotation calls them the live growth surface. An overlap between them would still have refused, but the cause would have read "this label appears twice in ONE catalog's rows... the repair belongs to that module" when the duplication was in the survey. Right refusal, false explanation, wrong module. RunnerLabelCatalog now carries its own identity - a DeclarationRef naming the catalog declaration - distinct from the provider naming who published it. A provider can have several catalogs in one survey and now that is representable. LabelMatch keys on the catalog, and RunnerLabelAmbiguousAcrossCatalogs carries List<LabelMatch> rather than List<RunnerLabelRow>, because bare rows cannot recover which catalog matched and a consumer reading the arm needs exactly that. WHY MY EXISTING CLAIM COULD NOT SEE IT: both competing matches went through control_match, which set the same provider, so the pair never exercised two catalogs at all - let alone two that share a provider. Guard and defect disjoint, again, and this is the third time in this module that the carrier was keyed on a neighbouring fact while the annotation argued for the distinction. EVIDENCE, in both directions so the two causes are not interchangeable. Two catalogs sharing GitHub as provider now read as two catalogs and the cause names the ROSTER; one catalog listing a label twice names THAT CATALOG and its module. The red was executed: keying matches_share_one_catalog back on row.provider takes the shared-provider claim from true to false. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
|
review 63609 confirmed, and it clears the soundness bar I set in the freeze notice — so the head moves and the approvals reset. That was the right trade and I would take it again. Why this is soundness and not carrier gradeThe refusal would have stated a false fact and sent the reader to the wrong module. And the pair is the one this module itself names as its live growth surface. GitHub's sized larger-runner catalog and its standard-runner catalog both carry The fix
Why my existing claim could not see itBoth competing matches went through That is the third time in this module that a carrier was keyed on a neighbouring fact while the annotation argued for the distinction: the snapshot standing split into three arms and stored as bare snapshots; the selection surface pointed at the provider anchor; and now the match keyed on provider instead of catalog. I have started treating "the annotation argues for a distinction the type does not carry" as a thing to grep for in my own diffs, because I have now produced it three times in one file. Evidence, in both directionsTwo catalogs sharing GitHub as provider read as two catalogs and the cause names the roster; one catalog listing a label twice names that catalog and its module — so the two causes are not interchangeable and neither claim is satisfied by a refusal that always says the same thing. Red executed: keying The head is frozen again at — sent from cool-badger-34 |
Correcting myself: I misread this failure twice, and said so publiclyI reported on this PR that the floor was refusing with Main's own floor run at The real cause was ten lines above it and I never looked up: I grepped for What it actually is, and it is still not this diffMain's So any branch carrying current main fails the floor here, and merging main does not help, because main is where it comes from. Same shape as the I am not repairing it inside this PR. It is main's file, and #10968 set the precedent that these land separately. What I got right by accidentMy conclusion — "not my diff" — was correct. My reason was wrong, and I published the wrong reason. Worth stating plainly since anyone reading this thread later would otherwise inherit it. — sent from cool-badger-34 |
…ronology Two more soundness findings from the side chat, both unfreezing the head. THE PUBLIC SEAM WAS A DOOR BESIDE THE WALL. resolve_from_matches is split out precisely so a claim can hand it constructed matches - which means ANY caller can, and the surface filter lived only in surveyed_matches. So the path that was already safe was guarded and the path a caller reaches was not: a bare CircleCI row handed straight to the seam resolved happily as a runs-on label. LabelMatch now carries its selection surface and the seam refuses a match from any other one, so the wall holds for a constructed call exactly as it does for the survey. AND RFC 3339 PERMITS LOWERCASE, WHICH REVERSES LEXICAL ORDER. The grammar's own note allows "t" and "z" in place of "T" and "Z", so 2026-09-04t16:04:06Z and 2026-09-04T16:04:06Z are the same instant spelled two admissible ways - and 't' is code point 0x74 against 'T' at 0x54, so lexical comparison puts the lowercase one AFTER every uppercase one whatever its date. An OLDER stamp compares as NEWER. That is not imprecision, it is a reversal, and it lands exactly where this branch cares: a snapshot that pre-dates an observation would read as post-dating it, which flips our own coverage obligation into a finding about somebody else's repository - the confusion the three-valued standing was built to prevent, reintroduced underneath it by the comparator that standing is derived from. Section 5.1's precondition is "expressed using the same string", and case is part of the string. The comparator now requires the canonical uppercase spelling of both designators and refuses anything else, including an internally-consistent lowercase pair, because admitting that would mean admitting the mixed pair. EVIDENCE. A lowercase separator against an uppercase one refuses as undecidable; the same two instants in canonical spelling still order correctly, so the refusal is not blanket. A CircleCI row handed to the seam is refused naming the surface it came from. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
…e its own arm review 63694, and it is the FOURTH time in this module that a carrier fused two facts while an annotation argued for the distinction. I added the surface check one commit ago and reported the refusal through RunnerLabelAmbiguousAcrossCatalogs, whose declared meaning is "two surveyed catalogs both carry this label". THEY ARE DIFFERENT FACTS WITH DIFFERENT OWNERS. A wrong-surface match means a caller asked a resource_class value as a runs-on question - the repair is at the CALL SITE. Ambiguity means the roster enrolled one label twice - the repair is in gunbc.runner_provider_survey. Reported through one arm, nothing on the value separated them and the English cause was the only discriminator. MY OWN WITNESS PROVED IT, which is the part worth keeping. The claim I wrote to check the seam had to assert string_contains(cause, "does not answer for") to tell the two refusals apart - a claim reaching into prose because the value would not answer. I wrote that claim, ran it, watched it pass, and did not notice that its SHAPE was the evidence of the defect. The same module says three declarations later, about the snapshot standing, that "the distinction survived in the English and nowhere a consumer could match on it." RunnerLabelWrongSelectionSurface is now its own arm. The seam claim matches on it by variant and the ambiguity claim matches on the other, so the two are separated by value and neither reads a sentence. WHAT I WOULD FLAG ABOUT THE PATTERN: four instances, one module, all mine, and each introduced while repairing the previous one. Snapshot standing split three ways and stored as bare snapshots. Selection surface pointed at the provider anchor. Match keyed on provider rather than catalog. Now a new refusal reusing an existing arm. I said last round I would grep my own diffs for "the annotation argues for a distinction the type does not carry" and then did not, because I was adding a check rather than a type and did not think the rule applied. It applies to the REFUSAL as much as to the carrier: a new way to fail is a new fact, and reaching for an existing arm is the same reach as reusing a neighbouring key. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
…own name review 63714, the FIFTH instance of this shape in this module, and this time the arm was the one I wrote the criterion about. Two commits ago I split RunnerLabelWrongSelectionSurface off ambiguity BECAUSE the two had different owners and different repairs. RunnerLabelAmbiguousAcrossCatalogs was already fusing two facts by the same test, one line away, and I did not look. THE THREE FACTS AND THEIR THREE OWNERS. A label appearing twice in ONE catalog is a defect in that provider module's projection of its own published surface. A label claimed by TWO catalogs is a defect in gunbc.runner_provider_survey's roster. A match on another CI system's surface is neither - a caller asked a resource_class value as a runs-on question and the repair is at the call site. The name AcrossCatalogs was simply FALSE for the same-catalog case. RunnerLabelDuplicatedWithinCatalog and RunnerLabelClaimedByTwoCatalogs now carry their own names, and every witness matches on the VARIANT. The file has zero string_contains on a cause left in it - the claims had been reading English to tell two refusals apart, which is the tell, and which I had described in my own commit message one commit earlier while leaving four instances of it in the same file. EVIDENCE, AND THE RED IS PRECISE RATHER THAN MERELY PRESENT: collapsing the split so both multiplicities report as cross-catalog takes the same-catalog claim from true to false and leaves the cross-catalog claim GREEN. A pair of claims that both went red would not have shown they test different things. FIVE INSTANCES, ONE MODULE, ALL MINE, EACH INTRODUCED WHILE REPAIRING THE LAST. Snapshot standing split three ways and stored as bare snapshots; selection surface pointed at the provider anchor; match keyed on provider not catalog; a new refusal reusing an existing arm; and now the arm that refusal was split off FROM. The mechanical check I keep failing to run is cheap and I am stating it so the next reader can hold me to it: after any change to a coproduct, grep the witnesses for string_contains on a cause. Every hit is a place the value does not carry what the prose claims. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH
… do not have Fourth conflict in this file from this branch, and the second of the both-sides-live kind: 40 SCM rows here, one for gunbc#10956 from main. Unioned. THE SHORTCUT I DID NOT TAKE is the part worth recording. Last time both sides were live, I unioned main's fresh row, and the floor then reported it CONSUMED at this base and charged its deletion to the roster-touching change. The same is likely about to happen to #10956's row, since #10956 is in this branch's base as of this merge. Deleting it now on that reasoning would save a CI cycle and would be PREDICTING a disposition rather than holding one. Main's own rule decides it: THE RECEIPT IS THE DISPOSITION, NOT THE SIDE. A row goes because the wall computed its transition and printed it. "I expect the wall will say consumed" is not that, and acting on an expected measurement is the exact error class this branch has spent its whole review history repairing -- an annotation asserting a mint did not exist, a control green on the wrong refusal, a scenario green against a leaked sibling, all of them a claim standing where an observation belonged. So the row stays, and if the floor says consumed, that receipt deletes it. cargo check -p v1-compiler --lib finished clean on the working tree. Section 4c: 0 violations. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
…iction The previous commit kept main's gunbc#10956 admission row through the merge and said plainly that the floor would probably report it consumed, but that predicting a disposition is not holding one. Required floor run 34594161197 has now computed it: CONSUMED ADMISSION gunbc#10956 runner provider roster rehome ... already satisfied at the base 1 consumed admission(s) due for deletion on this roster-touching change required-floor: verdict=FloorClean unexpected_failures=0 So the row goes, and what deletes it is that receipt -- not the paragraph I wrote yesterday that happened to agree with it. The floor was otherwise clean; this was the only blocker, and the 40 SCM rows stay because the same run still shows them ADMITTING. I am keeping the pre-run paragraph in place beside the post-run one rather than tidying it away. Together they are the only honest record of the distinction: the first states an expectation while it is still an expectation, the second states the measurement that settled it. Collapsing them into one after-the-fact sentence would make it read as though I had known, which is the retroactive certainty this branch has spent its whole review history removing from annotations. cargo check -p v1-compiler --lib finished clean on the working tree. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
…wn rule The floor reported CONSUMED ADMISSION for main's runner-roster row -- already satisfied at the base, consumed by its own merge -- and refused adjudication because a roster-touching change owes the deletion. This is the toucher, so the row and main's account of its subject go here rather than being deferred to a follow-up nobody owes. The union note records what happened, citing the wall's own line rather than asserting it. Also scoped a sentence that had become false: 'the resting state is empty again as of this change' was true of the change that wrote it and is not true of a roster carrying eighteen rows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YT3CM7TgQNeyBp1REtuxWE
#10956's consumed row The required floor refused with `3 unadjudicated delta(s), 0 stale admission(s), 1 consumed admission(s)`, and both halves are this change's to pay. The three deltas are the brand move itself: `LinuxKernelRelease` is authored on both sides inside ContainerVisibleHostKernel, the playwright run row, and the witness's execution-identity law, and what changed is which declaration the spelling admits -- base gunbc.served_surface_browser_observation, head extdeps.linux.kernel. That is exactly the motion the wall exists to make an author say out loud, so it gets three rows and the adjudication beside them: the moved declaration is byte-identical including the brand STRING (a changed brand would have altered what every `as LinuxKernelRelease` ascription means, which is a semantic change wearing a relocation's name), and the two consumers are the complete population -- both edited here, no third site left resolving through a module that no longer authors the name. The consumed row is #10956's, which merged this morning; the wall computed its transition as already satisfied at the base and printed it. This file is the roster, so this touch is the toucher the rule charges and the deletion is paid here rather than deferred to a follow-up nobody owes. Empty was the resting state and empty is not permissive: authoring different rows back into it is the ordinary motion, not a regression of that dissolution. Floor itself was clean on the refused run -- verdict=FloorClean, claims_failed=0, and all 12 of the new EDAC witnesses reported standing=planned-and-passed as changed witnesses. Only the namespace phase refused. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JGu7gNotcNwnQLyddmmkXs
…ream carrier (#11071) * GHES/APEI firmware-first is a Linux fact: ghes_edac gets its own upstream carrier Under ACPI APEI firmware-first mode the firmware handles memory errors and hands the OS finished error records; the OS never enumerates the memory controller. ghes_edac exists so one of those records has a DIMM to name -- it registers ONE synthetic controller and mirrors the SMBIOS Type 17 device list into it. It is an error-attribution shim, not a memory-controller topology authority, so no csrow or channel node exists to read on ANY boot absent a native driver. That sentence was living as prose inside one unit's observation (gunbc#10965's mtcollins1_edac_channel_map_unavailable_reason), where it is a fact about a Linux/firmware arrangement wearing a receipt's clothes. DESIGN 3's external upstream decomposition puts it in extdeps.linux.edac, keyed to the kernel release it was read against, and leaves the receipt its readings. What the carrier makes decidable rather than restatable: - EdacDriverBinding is a trichotomy, not an enum of drivers. The native-driver roster is genuinely open upstream (one per memory controller), so the closed part is the only part that is closed: a controller-enumerating driver is bound, ghes_edac is, or nothing is. - The two absences are separate causes with separate standings. FirmwareFirstErrorAttributionShim is AbsentOnEveryBoot -- the errand is over; NoMemoryControllerDriverBound is AbsentUntilDriverBound -- there is something to try. Collapsing them into one "unavailable" is exactly what books the next pointless boot. - edac_dimm_node_source asks both drivers the same question and gets different answers, which IS the shim: a controller's enumeration carries channel position, an SMBIOS Type 17 mirror names slots and never locates a part in the topology. - apei_firmware_first_from_dmesg matches the kernel's own line rather than a paraphrase. LinuxKernelRelease moves to a new extdeps.linux.kernel with it. It was declared inside gunbc.served_surface_browser_observation, a downstream receipt; an extdeps module cannot import a gunbc one, so keying an upstream fact to a kernel release would have had to re-coin the brand -- the fork. Its one consumer imports it from the new home. Consumption (DESIGN 3c): test.claim.linux_edac_topology_authority_witness exercises every arm of every fold, with a discriminating red on the dmesg detector whose fixture mentions GHES, EDAC, APEI and firmware and is still not the marker. Both controls were executed red by mutation before landing. The named later consumer is #10965's receipt, trigger stated in the module: that PR merging, after which it keeps driver ghes_edac, apei_firmware_first true, csrow_node_count 0 and the dmesg line, and resolves the WHY here. Observations this repo produces are receipts in the observing layer, never facts owned by the observed upstream. edac.dag leaves the frozen legacy scope manifest and joins scope_carrier_paths, with the extdeps_model_scope it owed; kernel.dag lands as a carrier. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JGu7gNotcNwnQLyddmmkXs * Admit the LinuxKernelRelease rehome at the wave-admission wall, and pay #10956's consumed row The required floor refused with `3 unadjudicated delta(s), 0 stale admission(s), 1 consumed admission(s)`, and both halves are this change's to pay. The three deltas are the brand move itself: `LinuxKernelRelease` is authored on both sides inside ContainerVisibleHostKernel, the playwright run row, and the witness's execution-identity law, and what changed is which declaration the spelling admits -- base gunbc.served_surface_browser_observation, head extdeps.linux.kernel. That is exactly the motion the wall exists to make an author say out loud, so it gets three rows and the adjudication beside them: the moved declaration is byte-identical including the brand STRING (a changed brand would have altered what every `as LinuxKernelRelease` ascription means, which is a semantic change wearing a relocation's name), and the two consumers are the complete population -- both edited here, no third site left resolving through a module that no longer authors the name. The consumed row is #10956's, which merged this morning; the wall computed its transition as already satisfied at the base and printed it. This file is the roster, so this touch is the toucher the rule charges and the deletion is paid here rather than deferred to a follow-up nobody owes. Empty was the resting state and empty is not permissive: authoring different rows back into it is the ordinary motion, not a regression of that dissolution. Floor itself was clean on the refused run -- verdict=FloorClean, claims_failed=0, and all 12 of the new EDAC witnesses reported standing=planned-and-passed as changed witnesses. Only the namespace phase refused. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JGu7gNotcNwnQLyddmmkXs * The controller count was a literal compared to itself; make it a fold with a real other arm `ghes_edac_registers_exactly_one_controller_holds` read `ghes_edac_registered_controller_count == 1` against a data row declared as 1. That is statically decided: it can only go red if someone edits the row, which makes it a change detector rather than a check -- DESIGN §5's own tell, that automating the literal's update collapses the assertion to measure() == measure(). eager-owl-205 hit the same shape from the other direction today (a witness comparing DeclarationRef strings to literals, green and proving nothing) and flagged it; this is that shape. The repair is not to delete the row but to notice the fact it was standing in for. How many controllers are registered is TWO different kinds of fact depending on who is bound. Under the shim it is ONE regardless of what the hardware has, because it is a property of ghes_edac rather than of the platform -- which is exactly why one memory controller beside sixteen DIMMs is the expected reading and not an anomaly. Under a native driver it is whatever the machine actually has, which this module cannot know: that is a per-platform reading for the observing layer. So the count becomes an arm of a fold, and the discriminating half is the other arm -- a native driver must NOT come back as a driver-fixed number, because answering one here would be the fabricated-plausible-output failure with a Nat on it. Executed red by mutation: pointing the native arm at ControllerCountFixedByDriver reds native_driver_controller_count_is_not_fixed_by_the_driver_holds while the ghes arm stays green, so the two arms are independently discriminating rather than one law wearing two names. 14 witnesses, all passing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JGu7gNotcNwnQLyddmmkXs * A controller count is a Count, not a Nat: MemoryControllerCount joins its siblings in std.measure review 63971, and it is right. `ghes_edac_registered_controller_count: Nat = 1` and the `ControllerCountFixedByDriver { count: Nat }` payload carried a domain count on a bare scalar, in a module whose entire point is that ONE controller beside sixteen DIMMs means something specific. Nothing in that type distinguished the 1 from a DIMM count, a channel count, or a slot number -- which is the §2 test failing one step earlier than a fork: not a second name for the axis, but no name at all. std.measure already owns the axis and the corpus has refused this exact move twice by name. MergeQueueEntryCount sits there rather than in the module decoding GitHub's merge_queue rule because "an extdeps module minting its own alias for it would fork that axis once per upstream that happens to count something"; PowerCordCount was put there so a product module "consumes it rather than re-minting a local alias for the same axis". An extdeps module counting memory controllers is the same shape, so MemoryControllerCount lands beside them with its constructor and accessor, and edac.dag consumes it. The witness's oracle becomes memory_controller_count_value(c: n) == 1 rather than n == 1. The stage0 mirror is regenerated by its own producer rather than hand-edited: one `--required-regen` round emitted the three additions to std_measure.rs, applied as hunks, and the second round reports first_generation_equal=true with no drift line. clippy --all-targets clean, 14 witnesses passing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JGu7gNotcNwnQLyddmmkXs * The kernel release was a dangling row; make the reading carry it review 63982, and it is right: `git grep edac_topology_model_read_at_release` returned one line, its own declaration. No fold read it, it was not carried on the scope, and my own §3c block claimed consumption for "every arm of every fold" — which that row was not. DESIGN §3c names this exact tell ("a data row no fold reads") and says it is red regardless of how well modeled the dangling piece is. The fix is not to drop it. The brief asked for the fact to be keyed to the relevant kernel, and the reason is load-bearing rather than decorative: this module's whole claim is that an absent channel map is STRUCTURAL and not a missing driver, and that claim is falsifiable only against a stated release — a mainline that grew a native Altra memory-controller driver would answer ChannelTopologyEnumerated for the same question. A provenance a consumer can quote the answer without is a provenance that will be dropped. So the release travels WITH the reading, in the same value: edac_channel_topology_availability now returns EdacChannelTopologyReading { availability, read_at_release }. Deliberately ONE fold — a release-free route beside it would be the path every caller takes, and the row would be dangling again one caller later. The reviewer's other suggestion, carrying it on the citation row, I did not take: the `?h=v6.8` source URL in further_citations is reachable but it is a citation, not a value any consumer can join on, so the receipt in #10965 still could not say which kernel its answer was keyed to. Executed red by mutation: pointing read_at_release at a literal "9.9.9" reds every_reading_carries_the_release_it_was_read_at_holds, which checks all three arms and not only the interesting one. 15 witnesses passing. Also merged current main (the branch had picked up a main-integration merge) and re-ran the regen against it: first_generation_equal=true, no drift. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JGu7gNotcNwnQLyddmmkXs --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Brian Searls <11205878+briansrls@users.noreply.github.com>
…solution is recorded once main took 9243870, which edits the same NAMESPACE_TRANSITION_ADMISSIONS roster this branch appends to. namespace_wave_admission.rs is HAND-WRITTEN (//! header, no generated banner), so a regen cannot resolve it and the hunks are authored text. Git interleaved the two appends mid-literal, so the sides could not be concatenated: the conflict boundaries cut through TransitionAdmission structs. Resolved by reconstructing the roster from each side's complete file and taking the union -- main's 3 gunbc#11071 LinuxKernelRelease rows first, then this branch's 175 v2-native-route module-split rows. 178 total, none dropped, and neither side's #10956 rows return (both had already deleted them as consumed). THE DISSOLUTION IS RECORDED ONCE. Both sides wrote a TWENTY-FIRST DISSOLUTION paragraph for the same #10956 event -- recording one dissolution twice is a rostered failure mode in this repo, and two accounts of one event is the fork DESIGN section 3 forbids. Main's account survives: it landed first and it cites the receipt (required floor run 34627055157 reporting the row CONSUMED), where this branch's cited only the merge sha. The duplicate is deleted rather than merged into a third wording. Main's narrative says "the rows below are a DIFFERENT relocation", which was true when its rows were the only ones. After the union it would read as covering this branch's rows too, so a bridge paragraph states that the roster now carries two independent relocations with different dissolve-on triggers and that neither narrative covers the other's rows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013aZDLk2CxsCDznqn49Xhe8
… from its own blob The freeze is lifted by the trigger review named for it -- a CONCRETE CONFLICT, not elapsed commits. This branch sat at 265a92d through 9, 13 and 28 commits of drift without merging, because absorbing main on a schedule buys nothing while nobody can execute the missing acceptance receipt and every absorption moves the subject SHA. GitHub reported the branch unmergeable at 55 behind, so the condition is met and the merge happens now. FIFTH CONFLICT IN THIS FILE, AND THE FIRST QUALITATIVELY DIFFERENT ONE. Both sides appended rows, so git interleaved the two arrays and produced THREE hunks across one list: 40 SCM rows here, 3 for gunbc#11071 from main. Patching interleaved hunks is exactly how a row gets silently dropped in the middle of a list nobody re-counts, and a dropped row here is an unadjudicated delta the wall exists to refuse. So the resolution does not touch the hunks at all: each side's array is reconstructed from its OWN staged blob (`git show :2:` and `git show :3:`) and the two are concatenated. UNION, for the reason that decided the second and fourth conflicts: taking either side whole deletes obligations the other still owes. 43 rows, verified by label census -- 31 SCM_MERGE_BASE_COHOME, 9 SCM_SOURCE_RECOVERY_REHOME, 3 gunbc#11071 -- rather than by trusting the patch applied cleanly. Main's #11071 TRIGGER paragraph is kept verbatim. It records when those rows come due and this branch is not the authority that retires them; the same receipt rule that deleted #10945 and #10956 from this roster will delete these when the wall says so, and not before. cargo check -p v1-compiler --lib finished clean on the working tree. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ4iThiZ1B9LPB9ePr8qa9
What this is
The first half of the public-workflow scanner vertical (year_end_plan
public-workload-census, the technical half ofcohort-qualified). It is the piece the scanner cannot be written without: given the runner label a workflow job selects, which provider runs it and on which architecture.The brief asked for explicit
ProviderUnresolved/ArchitectureUnresolvedarms on the existing closed-world classifiers, which split a label on-and treat every non-Depot/non-Ubicloud prefix as GitHub-hosted. This does something stronger and smaller: it deletes the question the grammar was answering, because the answer is already in this repository as a cited authority.extdeps.ci_runner.depot,.blacksmith,.warpbuild,.circleci,.github_actionsandextdeps.cloud.ubicloudeach carry a runner catalog fetched from that vendor's own published page, and every one states the architecture of every label it publishes.depot-ubuntu-24.04-arm-16 => Aarch64anddepot-ubuntu-24.04-16 => X86_64— the fixture and its mutation — are literal rows. DESIGN §4: "in a closed system a heuristic is never necessary: the richer source always exists or can be written."Why the shape of the failure is the point
A string grammar answers every input, including inputs it has never seen.
blacksmith-16vcpu-ubuntu-2404-armandwarp-ubuntu-latest-arm64-8xput the architecture segment where it does not look; a self-hosted label has no vendor prefix at all. Each gets a confident wrong answer and nothing goes red.A lookup cannot do that. An unknown label produces no row, so the unresolved arms arrive by construction rather than as defensive arms someone has to remember to widen when Blacksmith or WarpBuild or an expression-valued
runs-onshows up. A defensive arm that depends on being remembered is the one that is not there when it matters.A catalog miss is two facts, and they are separated
Either the vendor does not publish that label — a finding about the repository we scanned — or our snapshot does not know it, which is a coverage obligation on us. Both produce an empty lookup, and they point at opposite remedies: report it, versus go and re-fetch. One arm covering both is a deficit in our own data wearing the costume of a property of somebody else's repository, and it never ranks for fixing (§5, a failure arm must refuse rather than widen).
The split is decided from data the catalogs now carry. If any surveyed snapshot was fetched before the observation, a catalog could have gained the label in between and the miss is ours. Only when every snapshot post-dates the observation has this repository looked later than the thing it was looking at and found nothing. An undecidable timestamp comparison counts as stale, deliberately: when the instrument cannot say, the arm that costs us effort is the honest one.
The residual is named, not hidden: a snapshot cannot distinguish a label never published from one retired since, and it cannot see a family this repository never modelled. Its next-rung trigger is a vendor-side family recognizer homed in each provider's own module, and it is not built here.
The comparator that split rests on
extdeps.time.rfc3339already carried the whole argument — that lexical ordering is sound only where the timezone spelling and the fractional-second precision agree — while explicitly declining to model the operation ("the operations land with the consumer that needs them"). This is that consumer. It gainsrfc3339_compare, which checks both preconditions and refuses with a fourth arm rather than returning a Bool. RFC 3339 §5.1 is quoted in the row. Mis-ordering here flips a coverage obligation into a finding about someone else's repository.Three smaller consequences
ubuntu-24.04-armat 4 vCPU / 16 GB for a public repository and 2 vCPU / 8 GB for a private one, on the same page under the same label.RunnerShapeRowhas no visibility axis, so adding them as shapes would mean choosing one published number and asserting it unconditionally — a fabricated fact, and the kind that reads as cited because it sits beside cited ones. The architecture column does not vary that way, which is all the label roster claims.gunbc.runner_shape_censusintogunbc.runner_provider_survey, because it now has two consumers asking different questions of the same list. A roster copied into the second goes stale the first time a provider is added to one and not the other.depot-windows-2022needs to be told that is our gap and not a label Depot lacks.Evidence, executed
dag/test/claim/runner_label_resolution_witness_test.dag— ten claims, green.The discriminating red was run, not asserted: mutating Depot's own catalog row for
depot-ubuntu-24.04-16fromX86_64toAarch64takes the witness from exit 0 to exit 1, and restoring it returns exit 0.Both miss arms are exercised with the same label (
depot-ubuntu-24.04-arm-small) at two different observation times, so what is measured is the split and nothing else.2026-09-04(Biome's admitted baseline run) post-dates four of the six snapshots → coverage obligation;2026-06-01pre-dates all six → finding.Depot's catalog was re-fetched from
depot.dev/docs/github-actions/runner-typeson 2026-09-10 and compared row by row against the twelve sizes carried here. They are unchanged; the snapshot date moves because the comparison was made, not because the rows did. The GitHub standard-runner rows were read fromdocs.github.com/en/actions/reference/runners/github-hosted-runnersthe same day.Scope, and what is next
No scanner, no network effect, no contact of any kind is in this PR. The
extdeps.githuboperations the scan needs (code search carrying upstreamincomplete_results, repository-contents blob read, observed runnerlabelsonWorkflowJobRun) are the next public change and land with consumers rather than as dangling declarations. The privatestrategy.workload_benchmark_suiteclassifiers dissolve into this resolver in the private repo once this lands.One live specimen worth recording: Biome's own observed run mix contains
depot-ubuntu-24.04-arm-small, and Depot's page today publishes nosmallsize at any position. Under the string grammar that label reads silently as Arm-on-Depot. Under this resolver it is a miss — and today it correctly reports as our coverage obligation rather than a finding, because four of the six catalog snapshots predate the observation. That is a true statement about the state of our data, and re-fetching those four is what converts it into a finding.🤖 Generated with Claude Code
https://claude.ai/code/session_015xnR1WBywRAkc4JiWJW1DH