Skip to content

A training run's identity must move when its seed does: resolve the manifest, derive the contract, and let derive_work_key stay the only authority - #9574

Merged
briansrls merged 12 commits into
mainfrom
session/zesty-crane-477
Aug 28, 2026
Merged

briansrls merged 12 commits into
mainfrom
session/zesty-crane-477

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 28, 2026 •

Copy link
Copy Markdown
Contributor

Why

The resident-model programme compares training runs — control against candidate, base against adapter — and every comparison joins on a Work identity. So that identity must name one computation. Nothing on this tree modelled the step between an authored recipe and an exact run, so a run's identity could be minted from values the trainer had not yet chosen.

Scope (this PR now carries four slices — the description below was written for the first and is kept because each slice's reasoning still stands):

  1. resolution — observations → TrainingResolution → ResolvedTrainingWork → TrainingRunDesired, the join key everything else needs.
  2. readback — an independent observation of a run, five axes, each a population with no absent arm.
  3. coordinate projection — one axis-keyed material projection read by both the work key and the manifest comparator, so a coordinate cannot enter the key without being comparable.
  4. attempt graph — membership decided against an admitted lineage graph rather than inferred from resemblance; rootedness as a bounded fixpoint.

Still not here: reconciliation and actuation. Reconciliation additionally needs a temporal observation cut, without which a fold would manufacture contradictions out of ordinary staleness. Checkpoint evidence is deliberately named TrainingCheckpointObservation — it records that an artifact was seen and binds none of optimizer/scheduler/RNG/data-order state, so no arm may derive "resume required" from it until a checkpoint admission lands. Production episode initiation stays blocked on owned_host (#9534).

See the PR comments for each later slice's reasoning and evidence.

Construction walls

No deferral is writable. No Auto/Latest/Default arm; zero-invalid axes are PositiveInt; convention-word axes are closed enums — numeric_format: NonEmptyStr admits "auto", which is the failure wearing the shape of a value. An unpinned coordinate is AxisUnresolved and refuses, naming a closed axis, so a new coordinate can't be added without failing every exhaustive match.

Dropout is bounded by a sealed mint. Zero is meaningful so PositiveInt would be wrong, but Nat admits 1001. No bounded refinement predicate exists to consume, so the mint refuses above 1000 — with both boundary admissions asserted beside the refusal, so the wall can't be satisfied by refusing everything.

The manifest is a total projection of the evidence, not an argument beside it. sole_constructor confines who may construct and establishes nothing about what is true of supplied values — a manifest naming base B beside evidence attesting base A was constructible and no wall could see it.

The contract is derived, not accepted. derive_work_key reads only contract and requirements, so a caller could resolve a manifest pinning seed 7 and pass a contract mentioning nothing about it: two runs differing in seed, optimizer and numeric format would have shared one Work key while producing different weights. Field-tagged, delimiter-separated over delimiter-free renderings, with serialize_content_hash preserving the hash family — a dropped family is an identity collision, not a formatting detail.

Global batch is derived, never stored. micro_batch, gradient_accumulation and global_batch as three independent coordinates with no worker count meant (2,8,16) and (2,8,64) both construct, their difference an omitted topology fact rather than two spellings of one computation. This slice admits single-worker only; worker count and reduction policy are semantic, not placement, and belong here when a coordinated multi-host realization exists.

Low-rank adaptation only. An earlier revision carried FullParameter | LowRankAdaptation while keeping rank/scaling/dropout unconditional — so a full-parameter run carried a LoRA rank its trainer never reads, and two identical full-parameter runs would derive different keys from an authored rank. That is one computation receiving many identities. The arm is deleted; a full-parameter arm kept only to anticipate a nonexistent consumer is a carrier-before-consumer scaffold. The later shape is a sum of products.

Admission derives under demand.work.principal. Requester and accounting scope are different roles sharing a representation; deriving under the requester refused every demand whose work was scoped to an organization, making service accounts and delegated execution unrepresentable.

Evidence — green by execution

  • one control per coordinate, all 23 perturbed independently, each moving the key
  • changed receipt does not move it — the negative control that stops the projection hashing provenance instead of computation
  • dropout boundary pair (0 and 1000 admit, 1001 refuses)
  • derived global batch equals micro × accumulation
  • unresolved coordinate refuses naming SeedAxis
  • cross-principal pair: delegated demand admitted; wrong demand.work refused

The control is proven falsifiable on a coordinate a single-field mutation could not reach: deleting the packing row from the identity material flips it to false; restoring flips it back.

Correction to an earlier version of this PR body

It claimed the completeness wall covered every semantic coordinate while the suite varied only two — seed and base artifact — with the other twenty-one fixed in one fixture. The seed mutation proved the seed control falsifiable and established nothing about the rest. The claim was wider than its executable population, which is the inflation DESIGN §4b rates as worse than sitting low. That is what this PR's latest commit repairs.

What this does not do

No production initiation. Training consumes the fabric's standing and models no cost cause of its own — owned_host returns an offer with OperatingCostUnread and the selection fold owns whether it can be priced, so a training-specific refusal would be a fourth authority for a question three layers already answer.

No TuningRecipe record and no TuningRecipeIdentity: no recipe artifact exists, so an opaque hash would name nothing.

Brian Searls and others added 4 commits August 28, 2026 04:40
…anifest, derive the contract, and let derive_work_key stay the only authority

The resident-model programme compares training runs -- control against candidate,
base against adapter -- and every one of those comparisons joins on a Work
identity. So the identity has to name ONE computation. Measured on this tree
nothing modelled the step between an authored recipe and an exact run, which
meant a run's identity could be minted from values the trainer had not yet
chosen.

THE SHAPE, and each piece exists because the alternative was constructible:

The manifest carries no deferral. There is no Auto, Latest, Default or
BestAvailable arm, and the zero-invalid axes are PositiveInt rather than Nat
while the convention-word axes (numeric format, method, packing, loss mask) are
closed enums rather than NonEmptyStr -- `numeric_format: NonEmptyStr` admits
"auto" and "default", which is the failure wearing the shape of a value. A
caller that has not pinned a coordinate cannot say so in the manifest; its
observation is AxisUnresolved and resolve_training refuses, naming a CLOSED
axis so a new coordinate cannot be added without failing every exhaustive match
over the refusal population.

The manifest is a total projection of the evidence, not an argument beside it.
An earlier revision took both and sealed the door, which confines WHO may
construct and establishes nothing about WHAT IS TRUE of the values -- a manifest
naming base B beside evidence attesting base A was constructible and no wall
could see it. That is the ceiling this repository already records for
sole_constructor, and the repair is derivation rather than a comparison.

THE CONTRACT IS DERIVED, AND THIS IS THE ONE THAT WOULD HAVE SHIPPED.
resolve_training previously took the WorkContract as an argument. derive_work_key
reads ONLY the contract and requirements, so a caller could resolve a manifest
pinning seed 7 and pass a contract mentioning nothing about it: two runs
differing in seed, optimizer and numeric format would have shared one Work key
while producing different weights. The contract now descends from the evidence,
over field-tagged length-separated material, with ContentHash coordinates going
through serialize_content_hash rather than a bare digest cast so the hash family
survives -- a dropped family coordinate is an identity collision, not a
formatting detail. derive_work_key remains the sole identity authority and
nothing stores its result, so a stored key cannot disagree with the derived one.

The admission derives under demand.work.principal, not demand.id.principal. The
requester and the accounting scope are different roles that share a
representation; deriving under the requester refused every legitimate demand
whose work was scoped to an organization, which would have made service accounts
and delegated execution unrepresentable. The admission establishes exactly one
relation -- this resolution derives the Work this demand NAMES -- and leaves
authorization to the grant machinery that owns it.

EVIDENCE, all green BY EXECUTION rather than by compiling. Seven witnesses run
through the interpreter and return true: a changed seed and a changed base
artifact each move the Work key; a changed resolution RECEIPT does not, which is
the negative control that stops the projection from hashing provenance instead
of the computation; an unresolved coordinate refuses naming SeedAxis; and the
cross-principal pair admits a requester asking for work scoped elsewhere while
refusing a demand naming a Work this resolution does not derive.

The completeness witness is proven to be falsifiable, not merely green: deleting
the seed row from the material flips it to false and restoring it flips it back.
Without that mutation the control could not be distinguished from one that
passes because the key ignores every coordinate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nto a source annotation

Review on #9574 flagged training_resolution_excludes_dispatch_note as a
`data ...: String` whose sole purpose is commentary, which DESIGN 4c calls
misplaced or dead data, and noted it matches the repo-wide `*_note: String`
idiom.

Both halves are true and the conclusion goes the other way for NEW code. That
idiom is a compensating convention the corpus adopted when `//` was a parse
error: prose had to be hoisted into a String row to survive at all, and 4c
records the cost -- intent became mechanically indistinguishable from program
data, and the first cleanup it forced swept 215 dead rows across ~130 files.
Annotations parse now, so the reason for the workaround is gone; matching it
here would author one more row of the debt that convention exists to explain.

The content is unchanged and belongs in an annotation by 4c's own test: it is
irreducible rationale about WHY the manifest has its shape -- which coordinates
change the promised answer and which are execution policy -- rather than a
restatement of what the declaration structurally says, and nothing machine-
consumed lives in it. No `Accepted` program could read it either way, so it was
never evidence for any claim; as a String it merely looked like it could be.

Module now carries zero commentary String rows. Compile unchanged at 0 blocking,
and the falsifiable completeness witness still returns true, so the annotation
move is inert to the semantic graph exactly as 4c requires.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…oordinate, a bounded dropout, and a method sum that stopped carrying dead parameters

Four defects, and the first is in the PR body rather than the code.

THE OVERCLAIM. This PR stated that every semantic coordinate reaches the Work
key. The suite varied TWO -- seed and base artifact -- and held the other
twenty-one fixed in one fixture. The seed mutation proved the SEED control was
falsifiable and established nothing about the rest, so the claim was stronger
than its executable population. That is the inflation DESIGN 4b rates as worse
than sitting low, because an overclaimed wall never ranks for the work that
would make it real. Now one perturbation control per coordinate, all twenty
three, each moving exactly one field.

THE METHOD WAS A SUM WHOSE PARAMETERS WERE A PRODUCT. TrainingMethod carried
FullParameter | LowRankAdaptation while target_modules, rank, scaling and
dropout stayed UNCONDITIONAL manifest coordinates, so a full-parameter
computation carried a LoRA rank its trainer never reads -- and two identical
full-parameter runs would derive DIFFERENT Work keys because someone authored
rank 16 rather than 32. That is the exact inverse of the collision this module
exists to prevent: one computation receiving many identities, because dead
fields participate in equality. The arm is deleted rather than fixed in place:
the programme is low-rank adaptation, and an arm kept only to anticipate a
consumer that does not exist is the carrier-before-consumer scaffold this module
otherwise refuses. The honest later shape is a sum OF PRODUCTS.

BATCH IDENTITY HAD THREE WRITABLE REPRESENTATIONS AND NO TOPOLOGY. micro_batch,
gradient_accumulation and global_batch were stored independently with no worker
count anywhere. Under global = micro * accumulation * workers the fixture's 2, 8
and 64 silently asserted four data-parallel workers -- a fact the manifest never
carried -- and both (2, 8, 16) and (2, 8, 64) construct, their difference being
an OMITTED topology rather than two spellings of one computation. Global batch is
now DERIVED from the two independent causes and never stored. Worker count and
gradient reduction are semantic rather than placement and belong here when a
coordinated multi-host realization exists; this slice admits single-worker only.

A DROPOUT RATE IS BOUNDED AND Nat IS NOT. Zero is meaningful so PositiveInt was
the wrong narrowing, but Nat admits 1001 and 5000, which are not probabilities.
No bounded refinement predicate exists to consume, so the bound is a sealed mint
refusing above one thousand, with BOTH boundary admissions asserted beside the
refusal so the wall cannot be satisfied by refusing everything.

Also: the material annotation said length-separated when the implementation is
delimiter-separated over delimiter-free renderings. The encoding is injective
either way on this domain, but a mechanism described as one it does not
implement is a defect in the description, and it would become a real defect the
first time a rendering could contain a delimiter. And the witness still carried
its own commentary `data ...: String` row -- the same form rejected in the
production module one commit earlier -- now an annotation.

EVIDENCE, green by execution: the twenty-three-coordinate control, the receipt
negative control, the dropout boundary pair with its refusal, and the derived
global batch. THE NEW CONTROL IS PROVEN FALSIFIABLE ON A COORDINATE THE OLD ONE
COULD NOT HAVE REACHED: deleting the `packing` row from the identity material
flips it to false and restoring it flips it back. A mutation against seed alone
would have said nothing about that field, which is precisely why the previous
evidence did not support the previous claim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… picked the winner

The readback slice: an independent observation of a training run, kept apart from the
runner's own receipt. A trainer that writes "success" has established only that it believed
it finished -- not that the artifact still exists and hashes correctly, that no process is
still running, or that the receipt belongs to this run rather than another using the same
recipe. Convergence that read the receipt would be asking the thing it is checking.

The first draft carried one process state, one terminal standing, one output and one
effective manifest per run. That was wrong at the grain, and the error was structural rather
than a missing case. One demand reaches several execution attempts -- infrastructure retry,
capability escalation and requested re-execution are all NEW attempts rather than mutations
of an earlier one -- so a singular output field makes two produced artifacts unrepresentable,
a singular terminal discards the local failure the moment an escalated attempt succeeds, and
a singular effective manifest hides the exact disagreement that axis exists to detect. A
carrier admitting one member has selected a winner before the reconciler ever runs.

So every axis is TrainingPopulationObservation<T>, and it has no absent arm. A complete read
that found nothing is an observed population with zero members; that is a different fact from
"nobody ran the observation" and from "the observation ran and could not produce a reading",
because empty licenses a conclusion -- restart the run -- that ignorance does not. The two
negative arms stay apart because their owners and remedies differ: not-attempted is owed to
the scheduling driver and repaired by dispatching an observer; refused is owed to the
transport or store and repaired by fixing that path. The refused arm carries its attempt
receipt, without which the two would be differently-named strings.

Three further corrections. The readback stays generic in P: narrowing to NonEmptyStr would
mean product.training can represent readback only for bindings whose principal happens to be
a string, which is a binding-level restriction inside a provider-neutral module. The effective
manifest carries the typed TrainingResolvedManifest rather than a hash, because the axis
exists to answer WHICH coordinate disagreed and a hash answers only same-or-different. The
output member carries a Sha256Digest with its producing attempt and materialization evidence,
because the model-artifact path needs an exact produced artifact and not an arbitrary
structural hash.

The top-level subject was not enough on its own. Without a per-axis subject the shape admits a
readback whose subject is run A while its checkpoints came from run B and its terminal from
run C, and every field typechecks. Raw reads are therefore subject-bound and the binder
compares all five against the subject derived from the desired run, refusing on a closed axis
coordinate before any axis fact enters the readback.

Nine witnesses, all green by execution. One refusal control per axis, reading the axis back
out of the refusal so a binder refusing on the wrong axis fails rather than passing as a
generic refusal; a positive control, without which an unconditionally-refusing binder would
pass every refusal witness. And two controls that an earlier revision of this suite would have
missed: it varied only the work identity, so an equality comparing work and ignoring the
demand would have passed everything -- the suite would have measured one half of a pair while
claiming the pair. The two halves are now separated, each differing in exactly one coordinate.
The sole_constructor wall on the subject was confirmed by execution, not asserted: a forged
cross-module literal refuses with "cannot be constructed outside its defining module", and the
probe was removed after it fired.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Second slice pushed: readback (dag/product/training/readback.dag + 9 witnesses)

This PR now carries two slices. The resolution slice is unchanged from the three approvals above; this comment covers only what was added.

What it is. An independent observation of a training run, kept apart from the runner's own receipt. A trainer that writes "success" has established only that it believed it finished — not that the artifact still exists and hashes correctly, that no process is still running, or that the receipt belongs to this run rather than another using the same recipe.

What the side-chat review refused in my first draft, and why it was right. I had one process state, one terminal standing, one output and one effective manifest per run. That is wrong at the grain: one demand reaches several execution attempts — infrastructure retry, capability escalation and requested re-execution are all new attempts, per the ExecutionAttemptLineage arms that landed in #9546 — so a singular output field makes two produced artifacts unrepresentable, and a singular terminal discards a local failure the moment an escalated attempt succeeds. Every axis is now TrainingPopulationObservation<T>, with no absent arm: a complete read finding nothing is an observed population with zero members, which is a different fact from nobody ran the observation and from the observation ran and could not produce a reading. Empty licenses a conclusion (restart) that ignorance does not.

Also corrected: the readback stays generic in P (narrowing to NonEmptyStr would restrict a provider-neutral module to string principals); the effective manifest carries the typed TrainingResolvedManifest rather than a hash, because the axis exists to answer which coordinate disagreed; the output member carries Sha256Digest with its producing attempt and materialization evidence.

The subject binding. A top-level subject does not bind anonymous evidence beneath it — the shape otherwise admits a readback whose subject is run A while its checkpoints came from run B. Raw reads are subject-bound and the binder compares all five before sealing.

Evidence — nine witnesses, green by execution, not by typecheck. One refusal control per axis, each reading the axis back out of the refusal so a binder refusing on the wrong axis fails rather than passing as a generic refusal. A positive control, without which an unconditionally-refusing binder would pass every refusal witness.

A hole I put in my own suite and then closed. The first version varied only the work identity, so a subject_eq that compared work and ignored the demand would have passed every control — the suite would have measured one half of a pair while claiming the pair. There are now two controls differing in exactly one coordinate each.

One claim verified rather than asserted: the sole_constructor wall on TrainingRunSubject was checked by compiling a forged cross-module literal, which refuses with sole_constructor type 'TrainingRunSubject' cannot be constructed outside its defining module. The probe was removed after it fired.

Not claimed: no reconciliation fold, no actuation, and no checkpoint admission — those are the next cuts. This slice can only observe. Production episode initiation stays blocked on owned_host (#9534) per the ruling from silent-bear-842, so training models no cost cause of its own here.

CI: required-witnesses-build green. The floor lane is red with main's own signature — every recent witnesses.yml run on main is failing, so this is not the branch's.

Brian Searls and others added 2 commits August 28, 2026 09:29
…eyed projection instead of two folds of the same manifest

The effective-manifest axis has to name WHICH coordinate diverged, not merely that something did.
The obvious way to build that comparator is to fold the manifest a second time beside
training_manifest_material -- and that is a second spelling of the coordinate set, with two
failure modes that both compile: a coordinate present in the key fold and absent from the
comparator is invisible to the comparison forever, and the two spellings can drift.

So the per-coordinate projection is hoisted into a single authority.
training_manifest_coordinate_material(m, axis) is where a coordinate's material lives,
training_resolution_axes() enumerates the roster once, and training_manifest_material now folds
that roster rather than listing the coordinates itself. Any consumer that needs to compare, name
or serialize a coordinate reads the same function, so a coordinate cannot enter the work key
without being comparable -- the relation is structural rather than maintained by hand.

This preserves the material bytes and their order. The regression check that matters is the
23-control work-key witness, which perturbs each coordinate independently and requires the key to
move: it still returns true by execution after the refactor.

A hand-listed axis roster in a consumer would have been the same defect one level out -- a second,
silently narrower roster whose forgotten coordinate is the one that drifts -- which is why the
roster is a function rather than a convention.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…an admitted attempt graph, and rootedness as a bounded fixpoint

The readback binds each of its five populations to the run's Demand/Work subject, which stops a
whole population being filed against the wrong run. It stops nothing about the individual members.
Every process, checkpoint, terminal, output and manifest receipt carries a freely supplied
execution attempt identity, so a member naming an attempt from another run passes every check the
readback can perform: the wrapper is honest, the member is foreign, and a subject comparison cannot
see one level down. Reconciliation joins evidence at attempt grain, so it cannot be written
correctly until membership is decidable.

Membership is therefore decided against an admitted graph and never inferred from a shared
materialization path, a similar key, adjacency in time, or the wrapper's own asserted subject. Each
of those is a resemblance, and a resemblance admitted as identity is how another run's artifact
becomes this run's output. The witness for that is direct: an attempt key under a different
principal is not a member.

ROOTEDNESS IS A BOUNDED FIXPOINT RATHER THAN A WALK, and the case that forces it passes every local
check. Two attempts each naming the other as predecessor are both present, neither predecessor is
absent, no work is foreign -- and neither chain ever reaches the demand. A recursive walk over that
pair does not terminate. Folding over the attempt list, whose length bounds the longest possible
chain, reaches the fixpoint and reports both as unrooted. The same machinery catches the quieter
case: a chain whose root is an initial attempt for ANOTHER run's demand, which would otherwise be
admitted and then joined as evidence about a run it belongs to only by resemblance.

Every way the graph can be wrong is its own named refusal, because the remedies differ -- a foreign
work is a routing defect, an absent predecessor is a lost observation, a duplicate identity is a
producer emitting twice, an unrooted chain is not an attempt at this run at all. The refusal
carries first + more rather than the first defect found: an ordered refusal would hide the second
until the first was repaired, so a graph with three problems would take three round trips and the
hidden defects would read as new regressions each time.

A duplicated identity is reported at EVERY occurrence rather than once per repeated identity. Which
occurrence is "the original" is not a fact the graph has -- the members arrive unordered -- so
nominating one as legitimate would be the fold inventing a precedence it cannot establish.

Nine witnesses, all green by execution, including the positive control without which an admitter
that refused everything would satisfy all of them, and the RequestedReexecution case: a rerun roots
directly in the demand like an initial attempt and unlike a retry, so a rootedness rule recognizing
only InitialAttempt would report every rerun as unrooted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Fourth slice: the admitted attempt graph (dag/product/training/attempt_graph.dag + 9 witnesses)

Why this exists, and why reconciliation is not in this PR. I wrote a reconciliation fold, reviewed it against the fabric's execution model, and pulled it before it landed — it was wrong at the grain. I had keyed contradictions at run level, but retry, capability escalation and requested re-execution are distinct attempts. So E1 failed, E2 succeeded is the ordinary local-model-to-Opus escalation history this programme is measured on, not a conflict; likewise E1 terminal, E2 running (normal continuation) and E1 → digest A, E2 → digest B (separate attempts, separate artifacts). The genuine contradictions are all same-attempt. Being blunt about one consequence: my witness a_success_beside_a_failure_contradicts_rather_than_converging asserted the wrong rule. Had it gone green I'd have had an executing witness pinning wrong semantics — worse than no witness, because it would have counted as coverage.

Reconciliation joins evidence at attempt grain, so it can't be written correctly until membership is decidable. That is this slice.

The gap it closes. The readback binds each of its five populations to the run's Demand/Work subject — but each member carries a freely supplied attempt identity. A member naming an attempt from another run passes every check the readback can perform: the wrapper is honest, the member is foreign, and a subject comparison cannot see one level down. Membership is now decided against an admitted graph and never inferred from a shared materialization path, a similar key, or adjacency in time — each is a resemblance, and a resemblance admitted as identity is how another run's artifact becomes this run's output.

Rootedness is a bounded fixpoint, not a walk, and the forcing case passes every local check: two attempts each naming the other as predecessor are both present, neither predecessor is absent, no work is foreign — and neither chain reaches the demand. A recursive walk doesn't terminate on that pair. Folding over the attempt list (whose length bounds the longest chain) reaches the fixpoint and reports both unrooted. The same machinery catches the quieter case — a chain rooted in another run's demand, which would otherwise be admitted and then joined as evidence about a run it belongs to only by resemblance.

A judgement call worth flagging for review. A duplicated identity is reported at every occurrence, not once per repeated identity. Which occurrence is "the original" isn't a fact the graph has — members arrive unordered — so nominating one as legitimate would be the fold inventing a precedence it can't establish.

Evidence: 9 witnesses, all green by execution. Including the positive control (an admitter that refused everything would satisfy every refusal witness), the identity-not-resemblance control (an attempt key under a different principal is not a member), and the RequestedReexecution case — a rerun roots directly in the demand like an initial attempt and unlike a retry, so a rule recognising only InitialAttempt would report every rerun as unrooted.

Also in this push: the per-coordinate projection in resolution.dag. The manifest comparator must name which coordinate diverged; writing it as a second fold would be two spellings of the coordinate set, and a coordinate present in the key fold but absent from the comparator is invisible to comparison forever. There's now one axis-keyed projection that training_manifest_material folds. The 23-control work-key witness still returns true after the refactor.

Not claimed: still no reconciliation and no actuation. Reconciliation additionally needs a temporal observation cut — the five axes are independent observations, so process running at 09:00 beside terminal success at 09:05 is stale-but-previously-true evidence, and a fold without observation ordering would manufacture contradictions out of ordinary staleness. Production episode initiation remains blocked on owned_host (#9534).

— sent from zesty-crane-477

…control per axis cannot see two foreign axes at once

The readback binder compared its five axis subjects in a nested if-chain and returned on the first
mismatch. So a readback whose execution AND outputs both came from another run reported only
execution, and the second defect would have surfaced as a fresh regression the moment the first was
repaired. This is the same first-wins failure the reconciliation notes in this module reject,
committed one layer down by the author who wrote them.

WHAT DID NOT CATCH IT IS THE POINT. Nine witnesses passed, including one refusal control per axis,
and six approvals read the diff -- one of them crediting the branch with "admission refusals carry
every defect", which was true of the attempt graph and false of this binder at that head. The
per-axis controls are not weak evidence; they are evidence of a different proposition. Each makes a
single axis foreign, so each proves its comparison EXISTS and none can express what happens when
two mismatch at once. No amount of that family reaches this bug, which is why the new control is
added beside them rather than replacing them: they fail on different bugs.

The refusal now carries first + more, making the population non-empty structurally so a refusal
holding no mismatch is unrepresentable, and the binder folds all five before deciding.

THE NEW CONTROL IS SHOWN TO DISCRIMINATE RATHER THAN ASSERTED TO. Reintroducing first-wins by
returning an empty `more` turns it red; restoring the fold turns it green, with the file restored
byte-exactly afterwards. A witness that passes against both the fix and the bug would have been
decoration, and this repository rates that as worse than absent because it gets cited as coverage.

TrainingCheckpointReceipt is renamed TrainingCheckpointObservation in the same change. It records
that a checkpoint-like artifact was seen and binds none of optimizer state, scheduler state, RNG
state, data-order position, atomic publication standing, or a materialization readback -- so it
cannot establish that training could resume from it. Under the old name a later reconciliation arm
could reasonably have derived "resume required" from it; the carrier now says what it is, and no
arm may until a checkpoint admission lands.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Correction: the readback binder had a first-wins defect, and nine green witnesses plus six approvals did not see it

Posting this against my own earlier slice, because the way it was missed is more useful than the fix.

The defect. bind_training_run_readback compared its five axis subjects in a nested if-chain and returned on the first mismatch. A readback whose execution and outputs both came from another run reported only execution — and the hidden one would have read as a fresh regression the moment the visible one was repaired. This is exactly the first-wins shape I rejected when the reconciliation verdict was being designed, committed one layer down by the same author in the same PR.

What did not catch it. Nine witnesses passed, including one refusal control per axis. Six approvals read the diff — review 57243 credits the branch with "admission refusals carry every defect", which was true of the attempt graph and false of this binder at that head. The per-axis controls aren't weak evidence; they're evidence of a different proposition. Each makes exactly one axis foreign, so each proves its comparison exists, and none can express two simultaneous mismatches. No number of them reaches this bug. The new control is added beside them rather than replacing them, because the two families fail on different bugs.

The fix. The refusal carries first + more, so a refusal holding no mismatch is structurally unrepresentable, and the binder folds all five axes before deciding.

The control is shown to discriminate, not asserted to. Reintroducing first-wins by returning an empty more turns two_foreign_axes_are_both_reported red; restoring the fold turns it green; the file was restored byte-exactly afterwards (diff clean). A witness that passed against both the fix and the bug would be decoration, and decoration is worse than absence here because it gets cited as coverage.

Also in this push: TrainingCheckpointReceipt → TrainingCheckpointObservation. It records that a checkpoint-like artifact was seen and binds none of optimizer state, scheduler state, RNG state, data-order position, atomic publication standing, or a materialization readback — so it cannot establish resumability. Under the old name a later reconciliation arm could reasonably have derived "resume required" from it. No arm may, until a checkpoint admission lands.

PR description updated — it still said "first slice / no readback" while carrying four slices.

— sent from zesty-crane-477

…e stage ladder that is not yet the wall it looks like

The readback's axes are observed separately, so evidence taken at different moments cannot be read
as simultaneous state. A process seen running at 09:00 beside a terminal success written at 09:05
is stale-but-previously-true evidence, not a contradiction, and a fold treating the pair as
simultaneous would manufacture contradictions out of ordinary staleness. It cuts the other way too:
"terminal success and the output population is empty" is a contradiction ONLY when the output
enumeration happened after the successful terminal was observable.

So a cross-axis temporal conclusion is available only from a producer that establishes read order,
and the answer is three-valued. "The relation was not observed" is neither ordered nor unordered:
collapsing it into a negative would let a missing sweep read as evidence that two reads were
unordered, which a reconciler would take as licence to ignore a conflict it cannot rule out. A cut
belonging to another run answers Unobserved for the same reason -- it is well-formed, its sweep
really happened, and it orders a different run's reads; borrowing it is authority substitution,
where both halves check out and only the relation between them is invented.

THE ORDER IS READ OFF THE SEQUENCE THE SWEEP TRAVERSED. An earlier revision of this file carried a
hand-written position table beside the stage ladder under an annotation claiming it was derived
from it. It was not: it was a second ordering, free to disagree, and the disagreement would have
compiled -- the cut establishing one order while every comparison read another. Each stage now
appends its own axis, so the ordering is a consequence of which stage functions ran.

AND THE LADDER IS NOT THE WALL IT LOOKS LIKE, which is the part worth reading. The stages consume
one another's tokens so that skipping one should be unwritable. Measured, it is not: passing a
SweepStarted where a TerminalsEnumerated is declared compiles with ZERO blocking diagnostics. The
cause is not local to this module. A value of one PARAMETERIZED type is silently accepted where a
different parameterized type is declared at a direct-call argument, while the same mismatch on
non-generic types refuses with `type mismatch: expected 'Product(Beta)', got 'Product(Alpha)'` and
a bare scalar at that same position refuses with `value does not inhabit its declared type at the
direct call argument`. The check runs there and does not separate two parameterized node types;
different field names do not save it, and it is not the generic callee, since a fully concrete
parameter fails identically.

The annotation therefore states the rung as MITIGATABLE with its next-rung trigger named, rather
than describing the shape as construction-over-validation. The ladder makes the correct order the
obvious thing to write and gives the sweep one home; it does not make the wrong order unwritable,
and an inflated rung is the thing that stops a class ever ranking for repair. When the direct-call
argument judgment separates distinct parameterized types, this ladder becomes a wall with no edit
here.

Five witnesses, green by execution: no cut answers Unobserved rather than a negative; a completed
sweep orders outputs and processes after terminals; the reverse pair reports out-of-order, without
which a comparison answering "in order" for everything would pass the positive case and establish
nothing; a foreign run's cut orders nothing here while this run's does; and the swept sequence
holds every axis exactly once in stage order.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Fifth slice: the temporal observation cut — plus a below-floor compiler defect found while testing my own claim

The slice

The readback's five axes are observed separately, so evidence taken at different moments cannot be read as simultaneous state. A process seen running at 09:00 beside a terminal success written at 09:05 is stale-but-previously-true evidence, not a contradiction — a fold treating the pair as simultaneous would manufacture contradictions out of ordinary staleness. It cuts the other way too: terminal success and the output population is empty is a contradiction only when the output enumeration happened after the successful terminal was observable.

The answer is deliberately three-valued. "The relation was not observed" is neither ordered nor unordered; collapsing it into a negative would let a missing sweep read as evidence that two reads were unordered, which a reconciler would take as licence to ignore a conflict it cannot rule out. A cut belonging to another run answers Unobserved for the same reason — it's well-formed, its sweep really happened, and it orders a different run's reads. Borrowing it is authority substitution: both halves check out and only the relation between them is invented.

A defect I introduced and caught in the same file

The first revision carried a hand-written position table beside the stage ladder, under an annotation claiming it was derived from it. It wasn't — it was a second ordering, free to disagree, and the disagreement would have compiled: the cut establishing one order while every comparison read another. Each stage now appends its own axis, so the ordering is a consequence of which stage functions ran.

The finding that is bigger than this PR

The stages consume one another's tokens so that skipping one should be unwritable. I tested it. It isn't. Passing a SweepStarted where a TerminalsEnumerated is declared compiles with zero blocking diagnostics, and the cause is not local to this module:

case result
Alpha{a} where Beta{b} declared, non-generic 1 blocking — type mismatch: expected 'Product(Beta)', got 'Product(Alpha)'
Alpha<NonEmptyStr> where Beta<P> declared 0 blocking, silent
Alpha<NonEmptyStr> where Beta<NonEmptyStr> declared (fully concrete) 0 blocking, silent
control: bare string where Beta<NonEmptyStr> declared 1 blocking — value does not inhabit its declared type at the direct call argument

The check runs at that position and refuses a scalar; it does not separate two parameterized node types. Different field names don't save it, and it isn't the generic callee — a fully concrete parameter fails identically.

Load-bearing consequence beyond this PR: FabricIdentity<NonEmptyStr, WorkKey> is silently accepted where FabricIdentity<NonEmptyStr, DemandKey> is declared. The product.fabric identity discipline rests on the phantom K keeping demand/work/attempt/grant/offer/receipt identities non-interchangeable. Two causes, only one of which is the brand: DemandKey and WorkKey are both NonEmptyStr where brand(...), and brands report where-refinement unenforced — predicate deferred at compile time; but Alpha/Beta involves no brand at all, so the parameterized-type nominal hole is separate and stronger. Runtime equality over the pair still holds and is what witnesses exercise — the compile-time half is absent.

This is below floor per §4b ("values inhabit declared types"). It is not claimed as fixed here and I am not absorbing it into this lane; it needs a compiler owner.

Rung, stated honestly

The annotation says mitigatable, with the next-rung trigger named (the direct-call argument judgment separating distinct parameterized types). The ladder makes the correct order the obvious thing to write and gives the sweep one home; it does not make the wrong order unwritable. Calling it construction-over-validation would be the inflation that stops a class ever ranking for repair — and when that judgment lands, this ladder becomes a wall with no edit here.

Five witnesses, green by execution, including the reverse-pair control — without it, a comparison answering "in order" for every pair would pass the positive case and establish nothing.

— sent from zesty-crane-477

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Correction to my previous comment: both of my claims about the compiler finding were wrong

Two things I asserted in the observation-cut comment need retracting, and the second is the dangerous one.

1. "Two causes, only one of which is the brand" — not established. I demonstrated two failing surfaces, not two root causes. The isolating probe:

case result
Wrapper<KindB> where Wrapper<KindA> declared, no brand anywhere 0 blocking, silent
Alpha<NonEmptyStr> where Alpha<NonEmptyStr> declared (anti-refuse-everything control) 0 blocking, correct

Applied type arguments are not compared even without refinement, which explains the FabricIdentity case without needing a brand-specific cause. The honest statement is two independently demonstrated failing surfaces; root-cause count not established.

2. "Runtime equality over the pair still holds — only the compile-time half is absent." This understated it. FabricIdentity<P, K> stores only principal and key, and fabric_identity_eq compares only those two. There is no runtime kind discriminator. So once the call boundary admits a WorkKey identity where a DemandKey is declared, fabric_identity_eq returns true on equal principal+key — it cannot see the lost K. The runtime comparison doesn't merely fail to compensate; it actively confirms a false match.

The exact standing:

principal-and-key equality                              HOLDS
phantom-kind separation at direct-call args             DOES NOT HOLD
cross-module literal construction of a sealed carrier   HOLDS (probed)
only the declared sealed carrier reaches a consumer     DOES NOT HOLD
folds that re-establish their domain relation           HOLD, to their executing evidence

What this does and does not change in this PR. The attempt-graph admission stays strong — its fold actually checks work equality, roots, predecessors and cycles, so the executed fold is the evidence rather than the nominal type. Same for the repaired readback binder, which really compares all five subjects. What changes is the classification: possession of a generic sealed carrier is not authorization. A consumer must compare the subject against one derived from the desired run rather than treating possession of a TrainingRunSubject<P> as proof.

Consequence for the eventual actuation boundary, recorded now so it isn't discovered later: a TrainingCompletionCandidate<P> must not be treated as authorization to publish or promote, because another applied generic product could reach that parameter. The effect-facing path either consumes the compiler repair or projects into a concrete, non-generic realization authorization whose nominal head the current compiler does distinguish. I am explicitly not adding a runtime kind tag to FabricIdentity — that would mutate a live fabric authority to compensate for a language defect and create a second kind representation to keep synchronised with K.

Routed out of this lane, as it should be: work item adhoc-11c9b9ca-aa6, "Direct-call inhabitance admits distinct applied nominal product types", with the full seven-case repro population. The negative cases must require the expected diagnostic at the exact direct-call argument — "some blocking diagnostic occurred" would let a parse or unresolved-name error pass a negative test without the wall existing.

— sent from zesty-crane-477

Brian Searls and others added 2 commits August 28, 2026 13:13
…t admission, and the Attempt inert row its own dissolution condition retires

Seeing a checkpoint-like artifact establishes that something was written. It does not establish
that the thing written is a state training can continue from, and the gap between those two is
where the expensive failure lives: a resume from a PARTIALLY published checkpoint takes model
weights from step 500 beside an optimizer state from step 400, and the run does not crash. It
converges to a different model, slowly, and every downstream comparison then joins on a Work
identity describing a computation that never happened.

So admission is its own carrier and the observation cannot be widened into it by renaming. What
must hold is a CLOSED component roster rather than an ad hoc check, because the failure is
per-component: a missing optimizer state and a missing RNG state are both "incomplete", and a check
asking "are there components?" passes a checkpoint holding only weights. Each component carries its
own digest and its own materialization readback -- one digest over the whole checkpoint makes
"which part is missing" unanswerable, and a component recorded without a readback is a claim that
bytes exist somewhere, which is exactly the claim a resume is about to bet a run on.

Atomic publication is observed rather than assumed, and unobserved is its own arm: a writer that
published components one at a time leaves a checkpoint whose parts are individually valid and
jointly inconsistent, and "we did not observe the publication standing" is neither "incomplete" nor
"atomic" -- collapsing it either blocks a healthy resume or authorizes a torn one. The attempt must
be a member of the admitted run graph, without which a checkpoint from another run whose components
all read back correctly is admissible: every component honest, the publication genuinely atomic,
and the state belonging to a different computation.

Manifest agreement moves to resolution.dag beside the coordinate projection, as a POPULATION of
differing coordinates rather than a boolean or a first-difference. "The manifests differ" sends a
reader to twenty-three coordinates; naming only the first hides the rest until it is fixed. Both
are answers a hash could have given, which is the reason this reads the axis-keyed projection: a
hash answers same-or-different and can never answer WHICH, and WHICH is the entire purpose of the
effective-manifest axis.

CI REPAIR IN THE SAME CHANGE, and it is the roster working as designed rather than a collision. The
floor's inert-carrier lens went red with exactly one failure more than main, isolated by diffing
the failed sets rather than guessed: v2/test/lens_inert_carrier. The roster's Attempt row records a
carrier "referenced only by fabric_terminal_contract_witness_test so far", and its dissolution
condition reads "a live consumer reads the carrier; the stale-roster check then forces this row's
deletion". attempt_graph.dag is production code that reads Attempt, so the row is stale and the row
itself says the remedy is deletion. Attempt is the only rostered carrier this lane's production
code consumes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…on witnesses, and the one a torn publication would pass

The previous commit landed checkpoint admission with no witnesses. A compiling carrier is
specification without execution -- the failure this lane keeps naming in other people's work -- so
this is the evidence that should have shipped with it.

The witness that carries the class is a_checkpoint_holding_only_weights_is_refused_naming_every_
absent_component. A checkpoint holding only model weights is exactly what a torn publication leaves
behind, and it is the input a resume must never accept: the run continues with weights from this
step beside an optimizer state from an earlier one and DOES NOT CRASH. It converges to a different
model. A check asking "are there components?" passes that input, which is why the roster is closed;
the witness asserts all four absent components are named AND that model_weights is not reported
missing, so it fails in both directions -- if the roster stops being closed, and if the refusal
starts over-reporting.

The rest, each failing on something the others cannot see: incomplete and unobserved publication do
not read as each other, because one says the writer left a torn checkpoint and the other says
nobody looked, and their remedies are opposite; a checkpoint whose attempt is outside the admitted
run graph is refused even though every component reads back honestly, its publication is genuinely
atomic and its manifest agrees -- membership is the only thing separating it from an admissible
one; a diverged manifest refuses naming the COORDINATE and reports exactly one, which a hash
comparison could never have produced; and all independent defects are reported together, so a
checkpoint missing its RNG state AND diverging on gradient accumulation does not take two rounds to
learn about, with the second reason reading as a regression introduced by fixing the first.

The positive control is what makes every refusal above load-bearing: an admitter that refused
everything would satisfy all of them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Sixth slice: checkpoint admission — plus the CI repair, and a gap of my own I'm naming

The CI failure was mine, and the roster told me the remedy

required-witnesses-build passed; the two red checks were the floor plus the aggregator gating on it. I isolated it by diffing my failed set against main's rather than reading counters — planned +31, passed +30, failed +1, and the single extra was v2/test/lens_inert_carrier.

Cause: the inert-carrier roster's Attempt row records a carrier "referenced only by fabric_terminal_contract_witness_test so far", and its own dissolution condition reads "a live consumer reads the carrier; the stale-roster check then forces this row's deletion." attempt_graph.dag is production code that reads Attempt. The row was stale by construction and the roster names the fix. Deleted — Attempt is the only rostered carrier this lane's production code consumes.

A gap I left and then closed

The previous push landed checkpoint.dag with no witnesses. A compiling carrier is specification without execution — the exact failure I keep naming in review — so this push carries the six that should have shipped with it.

Why admission is a separate carrier from observation

Seeing a checkpoint-like artifact establishes that something was written, not that it is a state training can continue from. The gap between those is where the expensive failure lives: a resume from a partially published checkpoint takes model weights from step 500 beside an optimizer state from step 400, and the run does not crash. It converges to a different model, slowly, and every downstream comparison then joins on a Work identity describing a computation that never happened.

So: a closed component roster (a check asking "are there components?" passes a checkpoint holding only weights); per-component digest and materialization readback (one digest over the whole checkpoint makes "which part is missing" unanswerable; a component without a readback is a claim that bytes exist somewhere, which is what the resume is about to bet a run on); atomic publication observed, with Unobserved as its own arm; and membership in the admitted attempt graph.

Six witnesses, all green by execution

The one carrying the class is a_checkpoint_holding_only_weights_is_refused_naming_every_absent_component — it asserts all four absent components are named and that model_weights is not reported missing, so it fails in both directions: if the roster stops being closed, and if the refusal starts over-reporting.

The others each fail on something the rest cannot see: incomplete vs unobserved publication do not read as each other (one says the writer left a torn checkpoint, the other says nobody looked — opposite remedies); a foreign-run checkpoint is refused even though every component reads back honestly, the publication is genuinely atomic, and the manifest agrees — membership is the only thing separating it from an admissible one; a diverged manifest refuses naming the coordinate and reports exactly one, which a hash comparison could never produce; independent defects are all reported together. And the positive control, without which an admitter that refused everything would satisfy every refusal witness above.

Also landed

training_manifest_agreement in resolution.dag, beside the coordinate projection — a population of differing coordinates rather than a boolean or a first-difference. "The manifests differ" sends a reader to twenty-three coordinates; naming only the first hides the rest until it's fixed.

Still not here: reconciliation and actuation. Per the design ruling, the ordered effect sequence belongs in the Spark realization with non-parameterized outer types (the generic stage ladder cannot be a wall under the routed compiler defect), and wet actuation must not sit behind a generic authorization alone.

— sent from zesty-crane-477

…evidence composition, and reconciliation at per-attempt grain

Reconciliation is a pure fold that draws a conclusion and does nothing; actuation consumes the
conclusion. A fold that could also act would decide and do in one step, leaving no representable
state in between for anything to disagree with.

CONFLICTS ARE A PER-ATTEMPT FACT, AND AN EARLIER ATTEMPT AT THIS MODULE GOT THAT WRONG AT THE GRAIN
AND WAS DISCARDED WHOLE. Retry, capability escalation and requested re-execution create NEW attempts
rather than mutating an earlier one, so across attempts a failure then a success is the ordinary
local-model-to-Opus escalation history this programme exists to record; a terminal beside a later
running process is normal continuation; and two attempts producing two digests is two attempts. The
real contradictions all live within ONE attempt. Reading any of them at run grain refuses exactly
the evidence the escalation model is built to keep, which is why the witnesses come in pairs that
are identical one attempt identity apart and must return opposite verdicts.

THE HOLE THIS CHANGE CLOSES WAS IN CODE ALREADY PUSHED. The observation cut established that SOME
sweep enumerated the axes in order, and the readback carried populations each stamped with the
enumeration receipt that produced it -- and nothing related the two. A well-formed, same-subject cut
from a DIFFERENT sweep could therefore order populations it never observed: every half honest, the
relation between them invented. That is the third instance of one defect this lane has removed --
a manifest accepted beside evidence it could disagree with, a contract accepted beside a manifest
it could disagree with, and now a cut accepted beside populations it never saw. Reconciliation
taking graph, readback and cut as three independent arguments would have been the fourth.

So TrainingRunEvidenceComposition is admitted once, per axis, by receipt equality, and
reconciliation consumes only the composition. A cut naming another sweep's receipts is refused per
axis with every mismatch retained. A cut covering an axis nobody enumerated gets its own refusal
rather than a receipt mismatch, because that is a producer reporting work it did not do.

AN EMPTY BLOCKER POPULATION IS NECESSARY AND NOT SUFFICIENT FOR CONVERGENCE. Five successfully
enumerated empty populations contain no contradiction anywhere and are plainly not a converged run
-- they are a run nobody started. Convergence is therefore reached from POSITIVE evidence, exactly
one completion candidate, and the candidate is mintable only downstream of the graph and the cut:
without an ordered sweep, an output population read before the terminal is indistinguishable from a
finished run whose artifact is missing, and those have opposite remedies.

A GUARD REMOVED RATHER THAN SHIPPED. An earlier revision threaded an `ordered` boolean through the
cross-axis arms. Once composition became the only door, that boolean could not be false for any
admissible input, and a guard whose red is unreachable is a decoration that gets cited as coverage.
The requirement did not disappear; it moved to the door.

Ten witnesses, all green by execution, including the positive control without which a fold that
blocked unconditionally would satisfy every refusal above.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Seventh and eighth slices: evidence composition + reconciliation at per-attempt grain

This completes the observation spine: resolution → readback → attempt graph → observation cut → checkpoint admission → evidence composition → reconciliation. Ten witnesses, all green by execution.

The grain, and the version I discarded

Retry, capability escalation and requested re-execution create new attempts rather than mutating an earlier one. So across attempts:

  • E1 failed, E2 succeeded — the ordinary local-model-to-Opus escalation history this programme exists to record
  • E1 terminal, E2 running — normal continuation
  • E1 → digest A, E2 → digest B — two attempts, two artifacts

The real contradictions all live within one attempt. An earlier draft of this module keyed them at run grain, and I discarded it whole rather than land it — it would have refused exactly the evidence the escalation model is built to keep. The witnesses therefore come in pairs that are identical one attempt identity apart and must return opposite verdicts:

witness verdict
a_failure_then_a_success_across_two_attempts_is_history_not_a_conflict true
one_attempt_reporting_success_and_failure_is_a_terminal_conflict true
different_attempts_with_different_digests_is_not_an_output_conflict true
one_attempt_with_two_digests_is_an_output_conflict true

A hole in code I had already pushed

The cut established that some sweep enumerated the axes in order; the readback carried populations each stamped with its enumeration receipt. Nothing related the two. A well-formed, same-subject cut from a different sweep could order populations it never observed — every half honest, the relation between them invented.

That is the third instance of one defect this lane has removed: a manifest accepted beside evidence it could disagree with; a contract accepted beside a manifest it could disagree with; now a cut accepted beside populations it never saw. Reconciliation taking graph/readback/cut as three independent arguments would have been the fourth.

TrainingRunEvidenceComposition is admitted once, per axis, by receipt equality, and reconciliation consumes only the composition. A cut naming another sweep's receipts is refused per axis with every mismatch retained; a cut covering an axis nobody enumerated gets its own refusal rather than a receipt mismatch, because that is a producer reporting work it did not do.

Convergence needs positive evidence

no_blockers_over_empty_populations_requires_execution_rather_than_converging → true. Five successfully enumerated empty populations contain no contradiction anywhere and are plainly not a converged run — they are a run nobody started. So convergence is reached from exactly one completion candidate, and a candidate is mintable only downstream of the graph and the cut: without an ordered sweep, an output population read before the terminal is indistinguishable from a finished run whose artifact is missing, and those have opposite remedies.

A guard removed rather than shipped

An earlier revision threaded an ordered boolean through the cross-axis arms. Once composition became the only door, that boolean could not be false for any admissible input — and a guard whose red is unreachable is a decoration that gets cited as coverage. It's gone; the requirement moved to the door.

Not here

Actuation. Per the design ruling it must not sit behind a generic authorization while the routed compiler defect stands (bold-bear-763) — it needs the Spark realization's concrete, non-generic fence, which is its own lane.

— sent from zesty-crane-477

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Correction: the compiler defect I reported is not a generics defect

bold-bear-763 built the repair and measured it, and the framing in my earlier comments is wrong in a way worth correcting on the record rather than leaving to be inherited.

What I claimed: distinct parameterized types are silently admitted at a direct-call argument, while "the same mismatch on non-generic types refuses" — with the non-generic case cited as the control proving nominal comparison exists.

What is actually true: a non-generic Alpha at a Beta parameter is also silently admitted, whenever the actual is a call rather than a record literal (measured, 0 blocking). My control refused because the actual was a record literal, not because it was non-generic. The only producer comparing product heads at that position was structured_application_site_type_mismatch, which fires solely on a record-literal actual; kernel_value_declared_type_mismatch bails at its first gate for a non-kernel actual, and coproduct_payload_where_parent_required bails unless the formal's declaration is a coproduct.

So the class is which producer sees the pair, and it is wider than generics. My four-case matrix was a real measurement that supported a wrong generalisation — the discriminating variable was sitting in the fixtures the whole time and I read it as "generic vs non-generic" because that was the axis I had set out to test.

Root-cause count: one. The caution I recorded — two failing surfaces, root-cause count not established — was right, and the Wrapper<KindB> probe settled it. One arm in v1.compiler.infer declared_type_inhabitance closes all of them, consuming v1.compiler.type_head_exposure rather than deriving a second head view, with every guard failing open.

Measured after the repair, each fixture its own entry compile, all refusals DeclaredTypeNotInhabited at the exact direct-call argument: Alpha<String> at Beta<String> 0→1; Wrapper<KindB> at Wrapper<KindA> 0→1; the same with the actual a variable rather than a call 0→1; the record-literal case 1→2 (pre-existing mismatch plus the new arm); bare string at Beta<String> 1→1 unchanged; matching applied type 0→0 unchanged. Corpus false-positive census on src/v2/compiler/00_compile.dag: 0 blocking / 2167 advisory with the arm on, identical to the same binary with the arm disabled by env var — a one-variable A/B rather than two builds.

What does not change for this PR. The consequence I recorded still stands and is if anything broader: possession of a sealed carrier is not authorization, FabricIdentity<_, WorkKey> reaching a DemandKey parameter is admitted, and fabric_identity_eq cannot recover the lost K — it confirms the false match on equal principal+key. The attempt-graph and readback folds remain strong because their executed folds are the evidence, not the nominal types.

— sent from zesty-crane-477

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Floor red at `c1db6c9` is main's, not this branch's — measured, not inferred.

Compared this PR's floor job (run 33182227955) against the latest main floor run (33145062452, `3a8344b5`):

main #9574
planned 12949 12996
passed 12615 12662
failed 47 47
stale_quarantine 1 1
known_red_now_passing 1 1

comm -23 over the two failing-module sets (26 modules each) is empty — this branch introduces no failing site. planned and passed both rise by exactly 47, which is the number of witness sites this branch adds, so every added site executed and passed.

The witnesses aggregator red is downstream of the floor lane by construction and carries no independent signal.

Not pushing a speculative fix: there is nothing on this branch to repair, and re-running would replay the same main-owned population.

… the execution claim commits before the trainer starts

An attempt must be durably claimed BEFORE a trainer process exists, and the claim is
committed by a control-plane transaction rather than by the actuator. The actuator only
realizes an already-committed claim, so a controller that dies between commitment and
launch leaves a claim that can be resumed rather than a run that gets started twice.

THE EXCLUSION KEY IS THE TRANSITION, NOT THE ATTEMPT IDENTITY, and that is the whole
content of the module. A uniqueness constraint on the attempt identity excludes nothing:
two convergence passes that both read "execution required" choose attempt-A and attempt-B,
the identities differ, and both commit. What must be unique is the SEMANTIC TRANSITION --
this demand, this work, this cause -- so the second pass compare-and-sets an occupied slot
and receives the first pass's claim instead of minting a rival one. The witness pair is
written so this is checked rather than assumed: the race witness asserts one committed
attempt, and a separate control asserts the two candidate identities DIFFER while the
transition slots are EQUAL. Without that control the race witness is satisfied by any key
at all, including the one that does not work.

ALREADY-COMMITTED IS A SUCCESS, NOT A REFUSAL. The losing pass observed a real state and
lost a compare-and-set; the correct answer is the winner's claim so it can dispatch the
SAME occurrence. Returning a refusal would make a benign race look like a defect and
invite a retry into a second mint. Snapshot-stale is deliberately NOT folded into it: the
ledger moved under the caller, so what the caller believes is unreliable and the remedy is
to re-observe, not to proceed with either claim.

DISPATCH IS RECORDED ON A COMMITTED CLAIM AND HAS NO OTHER ROUTE. TrainingExecutionClaim
is sole_constructor with admit_callers limited to admit_start_claim and
record_claim_dispatch, so "dispatched" cannot be asserted about an occurrence that was
never durably claimed. The ordering is a property of the constructor surface rather than
an invariant someone remembers to preserve.

CONTROL STATE IS COMPOSED, NOT SUPPLIED BESIDE THE EVIDENCE. Passing a claim or grant list
into reconciliation would have been the FOURTH instance of one defect this lane has
removed: a manifest beside evidence it could disagree with, a contract beside a manifest,
a cut beside populations it never observed, and now a control record beside a graph it
never described. TrainingRunConvergenceInput joins the two admitted compositions on one
subject and reconcile_training_run consumes that and nothing else.

Reconciliation moved with it. A graph attempt with no execution claim is now
TrainingAttemptWithoutExecutionClaim -- a control-state defect, not a reason to launch. It
is exactly the state a retrospective writer produces, and answering it with "execution
required" is an instruction to start another trainer. ExecutionRequired is correspondingly
narrow: a committed undispatched claim is TrainingRunLaunchDispatchRequired and a
dispatched one awaiting a process is TrainingRunLaunchPending, because the two carry
different instructions -- one needs an actuation, the other needs only an observer.

BOTH LAUNCH ARMS CARRY A POPULATION, NOT ONE CLAIM. Two active claims on two lawful
transitions are both awaiting their launch, and reporting only the first would send a
caller to dispatch one and read the run as handled. That is the first-wins defect this
lane already repaired in the readback binder; it was reintroduced here in the first cut and
is fixed with its own discriminating control asserting the reported population is 2.

One existing witness went red on purpose and is rewritten rather than deleted:
no_blockers_over_empty_populations_requires_execution_rather_than_converging asserted
execution-required over the ordinary two-attempt fixture, which was true only while the
fold could not see what had been claimed. Over that fixture it would now be asserting that
a run with two live claims should have a third trainer started, so it is re-authored at the
grain the narrowed arm actually means: no attempts, no claims, empty populations.

Green by execution: 12 execution-control witnesses and 16 reconciliation witnesses, 0 red.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@briansrls
briansrls merged commit 823dd8f into main Aug 28, 2026
1 of 2 checks passed
@briansrls
briansrls deleted the session/zesty-crane-477 branch August 28, 2026 18:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant