Repository navigation
RLM-2a: typed fleet plan/apply + dashboard deploy receipts, RoadmapLaunchDeploymentReceipt (total verdict), root-tree OID readback, BeltTickReceipt v4, systemd unit standing, live observers, run/artifact bindings, content-addressed persistence, generated receipt mode - #9761
Conversation
…unchDeploymentReceipt, root-tree OID readback, BeltTickReceipt v4, systemd unit standing, live observers, run/artifact bindings, content-addressed persistence, generated receipt mode Red controls and models land together in this first commit; the generated fleet-converge.yml regeneration follows in the next commit once the remote regen dispatch reports (the local gunbc binary is stale and cannot check this tree). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…h SystemdServiceDirective; hoist a body annotation to item grain Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…h the emitted ": " separator Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…; remaining ListHeadResult arms Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…r reverse loses the element type) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…nnotation form; new note rows become §4c annotations Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…low_file_path (a bare nullary artifact variant is an undefined variable in the floor frame) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…low (rlm_launch_deployment_receipt mode, receipt uploads, shared host-mutation concurrency) Regenerated via generated_artifact_gate main_wet on this tree; only the fleet-converge artifact changed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
briansrls
left a comment
There was a problem hiding this comment.
REQUEST_CHANGES — exact head 06c2e317430b80593a4d4a0e07957d447f3fedb0 reviewed.
I accept the execution evidence on this head: CI run 33331924621 is head-bound and green; the floor reports 3202 planned / 3202 executed / 0 failed; and the 82 changed witness identities, including the 42 floor-only identities, have terminal planned-and-passed evidence. I also confirm that this is substantial modeling rather than a shell wrapper: the 18-member total completion fold, sole-constructor DeploymentCompleteProof, same-locus G7 root-tree readback, BeltTickReceipt v4, shared host-mutation concurrency, and content-addressed persistence are real.
The head is nevertheless not safe to merge. These are production-boundary defects, not missing corroboration:
-
P0 — fleet apply can mutate srv1 at a revision other than R.
fleet_converge_apply_stepdoes not passRLM_EXPECTED_REVISION, andfleet_converge_apply_wetnever callsread_expected_revision/admit_run_revisionbeforerun_shell_commandsreachesfleet_converge_locked_apply_script. It proves only that the plan and apply receipts name the same SHA. A plan and apply both run at Q can therefore agree and actuate while the operator selected R; the final receipt would discover the wrong SHA only after mutation. Pass the independent expected R into apply (and bind every run as ruled), refuse before the locked actuator, carry the admission in the typed receipt, and add a RED-first control proving Q/Q with expected R cannot reach apply. -
P0 —
PartiallyAppliedcan be certified as a successful fleet apply. The existing fleet model deliberately distinguishesFullyAppliedfromPartiallyAppliedand deliberately does not change the shell exit code for sibling-axis refusals. The new apply receipt carries onlylocked_apply_exit_code; the completion fold admits exit code 0. Thus a refused axis plus an exit-0 partial application can reachDeploymentComplete. Carry the typed apply terminal and the relevant apply/generation admissions inFleetConvergeApplyReceipt(or an exact equivalent), requireFullyApplied, and add the discriminating exit-0/PartiallyAppliedRED. -
P1 — timer cadence is not matched to R's emitted unit.
TimerUnitExpectationcontains only the target unit;judge_belt_timermerely checks thatTimersMonotoniccontains the two directive names. Any values pass, andAccuracySecis not checked. Separately, tick freshness authors another literal 60 seconds while claiming derivation from emission. The ruling requires effective cadence matching R. Add a normalized systemd duration/effective-timer model, derive unit expectations and freshness from the same emitted authority, compare at least OnBootSec, OnUnitInactiveSec, and AccuracySec (or their exact effective equivalents), and add a wrong-cadence-beside-fresh-tick RED. A declared residue does not amend this acceptance bar. -
P1 — the four-run provenance chain is incomplete. The final receipt run verifies its SHA but does not prove its own
GITHUB_WORKFLOW_REFnames the generated workflow; its subject adoptsrun.repositoryas the expected repository and writes the expected path without comparing the current run to either. No run conclusion is carried or verified. Dashboard provenance names plan/apply run IDs and the plan hash, but not the exact predecessor plan/apply receipt identities. Bind the canonical repository, current receipt workflow path, successful conclusions, and predecessor receipt identities for all four runs, with wrong-repository/path/conclusion/predecessor RED controls. -
P1 — the plan receipt truncates the ruled lease epoch.
LeaseEpochis{lease_key, resource_fingerprint, owner_fingerprint, generation};FleetConvergePlanReceiptserializes onlylease_keyplus generation projections. The frozen RLM-2 join therefore cannot name the actual held epoch. Carry the whole typed epoch (or an injective exact equivalent) in the receipt identity and wire form, and add member-substitution/tamper controls. -
P1 — the HTTP evidence bypasses the production route. All three observers construct
http://127.0.0.1:<port>/.... That proves the local process, not that the deployed production/Tailscale route serves the release and active instance. A broken or misdirected route can coexist with a healthy localhost and still reach Complete. Derive the routed endpoint from the existing deployment/network authority, observe/healthz,/instance.json, and/workflow.jsonthrough it, and add a local-healthy/routed-wrong RED. -
P1 — the durable receipt does not serialize the claimed machine-readable fact population. Both verdict arms emit
factsas an array of rendered strings, and the receipt identity hashes delimiter-joined presentation text. The PR's own wet template addresses.facts.tick_standing,.facts.unit_standing, and.facts.observation_window; none of those paths exists. Serialize a structured fact object preserving typed arms and load-bearing payloads, derive identity from that canonical structure, and keep any prose lines as a separate presentation projection.
Also correct the wet template before merge: R is selected after RLM-2a merges and may be a later admitted main descendant; it is not definitionally this PR's merge commit. Do not discover run IDs with an uncorrelated gh run list --limit 1 race.
Ruling: no approval on this head; do not merge. RLM-2b remains blocked and no production dispatch is authorized. Bring a new exact head with RED-first evidence for the new discriminators, regenerated YAML from gunbc.fleet_converge_workflow, and exact-identity floor execution for every affected witness. A dashboard review does not discharge these findings.
…unit blocker matches recover WHICH unit refused; verdict matched at its one consumer); Scaffold+DissolutionCondition pair for gunbc_ci_fleet_key_agent_script with the marker on the emitted runner; regenerate fleet-converge.yml Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
|
Both findings of review 57664 addressed at 7382d27:
fleet-converge.yml regenerated via generated_artifact_gate main_wet on this tree. — sent from crisp-newt-85 |
…5; mode options union; regenerate fleet-converge.yml Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…y, required FullyApplied terminal, normalized timer cadence values from the emitted unit, four-run provenance, whole LeaseEpoch on the plan receipt, routed observers, structured facts serialization Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh # Conflicts: # dag/gunbc/fleet/fleet_converge_plan_cli.dag
|
Rework for review 5061891290 (REQUEST_CHANGES on 06c2e31) is on head
Both wet-template corrections adopted in the PR body: R is the operator-selected admitted main revision after merge (not definitionally this PR's merge commit), and predecessor run ids come from receipt-bound artifacts, never |
…nd tick freshness, three named timer-directive readers replace the string-tag selector, symbol citation replaces the line-range citation Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
|
Response to review 57708 (dashboard artifact /api/reviews/57708/artifacts/stdout.log), addressed on head
— sent from crisp-newt-85 |
|
Final verification chain for head
Discrimination evidence for the rework controls: each control substitutes exactly one member of the otherwise-Complete fixture population and asserts the typed Incomplete verdict naming that member as first_blocker (e.g. PartiallyApplied under exit 0 → — sent from crisp-newt-85 |
briansrls
left a comment
There was a problem hiding this comment.
REQUEST_CHANGES — exact head 4683c48b4b0b148e3722189360af8bf006f42701 re-reviewed.
I accept the head-bound execution evidence: run 33349151228 has five successful jobs on this SHA, including required build, required floor, Rust unit tests, witnesses, and fabric evidence. I also accept that the following prior findings are substantively repaired in code: expected-R admission now dominates plan/apply and the locked actuator; exit-zero PartiallyApplied is rejected by the completion fold; timer values are normalized and compared against the emitted unit; the full LeaseEpoch is identity-bearing; and dashboard provenance now binds the exact downloaded plan/apply receipt identities.
The head is still not mergeable. Three of the seven prior findings are only partially repaired, the wet procedure remains contradictory, and the required temporal falsification evidence is still absent.
-
P1 — routed
/healthzis still not the release/tree binding, and the observation window remains local. Inrlm_launch_deployment_receipt_bound, bothhealthz = observe_healthz(port)andhealthz_routedare read, butdeployed_release_binding(observation: tree, identity: ...)consumes the LOCAL health identity. The routed result feeds onlyReadinessFact, whose blocker compares revision but discards surface. Thus a routed endpoint serving R under the wrong surface can pass while localhost supplies the expected surface/tree join. The opening and closingwindow_snapshotlikewise call localrunning_release_hex(port)andactive_instance_text(port), so a route change during capture is invisible. Make routed health the load-bearingDeployedReleaseBindinginput, require its expected surface, and make the window's running-release/active-instance members routed. Keep localhost only as a separately named complementary observation. Add the previously required local-healthy/routed-wrong RED and a routed-state-changed-during-window RED. -
P1 — current receipt-run provenance still does not prove the canonical repository, and “four conclusions carried” overclaims the implementation. The three predecessor runs are API-read and checked well. The current run is represented only by
receipt_workflow_ref_names_path.run_binding_names_workflow_filebuilds its prefix from the binding's OWN repository, sofork-owner/gunbc/.github/workflows/fleet-converge.yml@...passes; no blocker comparesrun.repositorywithgunbc_repository.full_name. Carry or admit the current run binding against canonical repository + workflow path + R before capture, with a wrong-current-repository RED. The receipt run cannot observe its own terminal conclusion from inside itself; that is acceptable only as an explicit RLM-2b manager verification after the run completes, not as a claim thatRunProvenanceFactcarries all four conclusions. Correct the model/body/evidence template to state the split precisely, or add a post-run attestation mechanism. -
P1 —
factsis structured overall, but tick freshness is still presentation text.facts_jsonserializestick_standing.freshnessasjson_string(tick_freshness_text(fr)); it does not preserve theTickFresh | TickStale | TickBeforeDeploy | TickInstantUnparseable | TickCadenceUnnormalizablearm or the age/bound payloads. The machine-readable witness checks execution revision/mode but not freshness. Serialize freshness as a typed-arm object with its load-bearing fields, and extend the round-trip/navigation witness to recover the observed age and cadence-derived bound without parsing prose. -
P1 — the PR body's executable wet procedure still contradicts its appended correction. The retained command block says
R=<merge sha of this PR>, omitsexpected_revision=$Rfrom both plan and apply even though those modes now require it, and still discovers PLAN/APPLY/DASH/RCPT through uncorrelatedgh run list --limit 1. The later prose saying the opposite does not repair executable instructions. Replace or delete the stale block. Supply a genuinely correlation-safe run-ID mechanism; “read the run ID from the receipt-bound artifact” is circular because downloading that artifact already requires its run ID. A transaction nonce carried in workflow input/run identity/receipt is one sound shape. Also remove the now-false timer-cadence residue text in the PR body andunit_standing.dag; values are no longer structural-only. -
The temporal RED-first bar remains outstanding. Exact-head substitution witnesses are valuable and I accept their current green discrimination, but they do not establish that the newly added tests failed without the repairs. The old temporal reds exercised the original control population, not these seven new discriminators. Before approval, run mutation falsification against temporary refs/trees (never production): one mutant per repaired defect family is sufficient, not one per witness. At minimum prove failure when (a) the pre-actuation expected-R admission is removed, (b)
PartiallyAppliedis admitted, (c) timer value comparison is relaxed, (d) current/predecessor provenance or receipt-identity binding is relaxed, (e) one LeaseEpoch member is dropped, (f) localhost is substituted for routed authority, and (g) typed freshness is collapsed to prose. Record mutant SHA/tree, exact failing witness identities, and then the final-head green executions. These mutation runs may occur after the repair commit; they are the accepted equivalent of having landed each RED first.
Ruling: no approval on 4683c48b4b0b148e3722189360af8bf006f42701; do not merge. RLM-2b remains blocked and no production dispatch is authorized. Bring a new exact head with the three completion seams closed, the actual wet block corrected, generated YAML regenerated, exact-identity floor green, and the mutation-falsification receipts. Dashboard approval does not discharge these findings.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh # Conflicts: # .github/workflows/fleet-converge.yml # dag/gunbc/fleet/fleet_converge_workflow.dag
…ed via systemd_duration_usec since review 5061891290 P1-3 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
briansrls
left a comment
There was a problem hiding this comment.
REQUEST_CHANGES — exact head 9b89da837cea4ac932fb7f3ae4e2c5d17b4bbe72 re-reviewed. This supersedes the head anchor of my review on 4683c48b4b0b148e3722189360af8bf006f42701 without changing its substantive ruling.
I verified the update. The branch-local RLM delta is the merge of current main, including the allocation-store and organization-actions changes with regenerated fleet-converge.yml, followed by an annotation-only commit deleting the superseded timer-cadence residue. I accept that timer-values-have-no-model prose as closed. I also accept the new head-bound execution evidence: workflow run 33354805028 contains five successful jobs on this exact SHA, and the reported floor/changed-witness evidence re-establishes the prior final-head green population.
My verdict on 4683c48b was CHANGES_REQUESTED, not APPROVE. None of the remaining completion seams is changed by this head update:
-
Routed observation is still not the load-bearing release/tree binding, and the observation window remains local.
rlm_launch_deployment_receipt_boundreads both localhost and routed health, butdeployed_release_bindingstill consumes the localhost health identity. Routed health supplies onlyReadinessFact; that blocker compares revision while discarding the routed surface. The opening and closingwindow_snapshotlikewise obtain running release and active instance through localhost. A healthy local process can therefore supply the expected surface/tree join while the production route serves R under a wrong surface, and a route change during capture is not a window change. Make routed health the binding input, require its expected surface, make the window's running-release and active-instance observations routed, keep localhost as a separately named complementary fact, and add local-healthy/routed-wrong plus routed-window-change controls. -
The current receipt run is still not admitted against the canonical repository, and the claimed four-conclusion chain remains overstated. The three predecessor API records are checked well. For the current run, however,
RunProvenanceFactcarries onlyreceipt_workflow_ref_names_path;run_binding_names_workflow_filederives its prefix from the binding's own repository. A fork repository using the same workflow path can satisfy it, and no blocker compares the currentrun.repositorywithgunbc_repository.full_name. Admit/carry the current binding against canonical repository, workflow path, run id, and R before capture, with a wrong-current-repository control. The current run's own terminal conclusion cannot be known inside that run; model the split honestly and require a post-run manager attestation/check, or add a later attestation mechanism. -
Tick freshness is still presentation text inside the otherwise structured facts object.
facts_jsonserializestick_standing.freshnessthroughtick_freshness_text(fr)as a JSON string. It does not preserve theTickFresh | TickStale | TickBeforeDeploy | TickInstantUnparseable | TickCadenceUnnormalizablearm or the age/bound payloads. Serialize freshness as a typed-arm object with unit-bearing load-bearing fields, and extend the machine-readable navigation/round-trip witness to recover the freshness arm, age, and cadence-derived bound without parsing prose. -
The executable wet procedure in the PR body is still contradictory and correlation-unsafe. The retained block still says
R=<merge sha of this PR>, omitsexpected_revision=$Rfrom plan and apply despite both modes requiring it, and assigns PLAN/APPLY/DASH/RCPT with uncorrelatedgh run list --limit 1. The appended correction prose does not repair executable commands. Replace or delete that block and use a genuinely correlation-safe identity, such as a transaction nonce carried from dispatch input through API-visible run identity and typed receipts. Reading a run id from its artifact is circular because the run id is already needed to download the artifact. -
The temporal RED-first bar remains outstanding. I accept the exact-head substitution witnesses as valuable identity-grain discrimination, but they do not show that the newly added controls failed without the repaired mechanisms. Execute the offered non-production mutation runs before approval. One mutant per defect family is sufficient: expected-R dominance,
PartiallyApplied, timer-value equality, provenance/receipt identity, one LeaseEpoch member, routed-versus-local authority, and structured freshness. Record mutant commit/tree, exact failing witness identities, and the restored final-head green executions.
Ruling: no approval on 9b89da837cea4ac932fb7f3ae4e2c5d17b4bbe72; do not merge. RLM-2b remains blocked and no production dispatch is authorized. Bring a new exact head closing the three semantic seams, replacing the wet block, regenerating YAML, re-establishing exact-identity floor green, and carrying the mutation-falsification receipts. Dashboard approval does not discharge these findings.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…window reads routed state; current receipt-run admitted against the canonical repository (receipt_repository on RunProvenanceFact); typed freshness arms in the structured facts; transaction_nonce input + run-name for dispatch-correlated run ids Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…del — RunProvenanceFact carries no current-run conclusion; that is a post-run manager verification Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…le-document witnesses: the two-document form was budget-refused at the floor's 500ms CPU line (run 33358233304) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
|
Mutation-falsification record for review 5062738052 / 5063097188 (temporal-RED ruling): one mutant per repaired defect family, executed post-repair on UNCOMMITTED trees over the named base head — never committed, never pushed. Each mutant removes exactly one repaired mechanism and the named discriminating witness goes RED (claim_batch rc=1, FAIL line quoted); the restore is verified byte-clean (0 residual changes). Families a–f ran on base e49dd85; family g was re-executed on the final head 05e93e1 after its witness was split for the floor's 500ms CPU line. The final-head green executions are the local per-file claim_batch baseline (17+6+13+13+44 witnesses, rc=0 each) and the head's CI floor run. — sent from crisp-newt-85 |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…e main_wet output) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
…ReceiptWorkflowRefStanding replaces the Bool discriminator (foreign arm carries the observed ref), iso8601 epoch instants carried as Second Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
|
Response to review 57760 (dashboard artifact /api/reviews/57760/artifacts/stdout.log), addressed on head
— sent from crisp-newt-85 |
|
Response to review 57765 (dashboard artifact /api/reviews/57765/artifacts/stdout.log), per finding — dispositions, on head
The two P0-class review lines (5061891290, 5062738052/5063097188) are fully repaired on this head with mutation-falsification receipts; the findings above are ladder climbs on shapes consistent with current in-tree conventions, so they are dispositioned as named follow-ups rather than silently absorbed. If the lane manager rules any of them in-scope for RLM-2a, they land here. — sent from crisp-newt-85 |
…re label reaches the typed LiveDeployApplyReceiptUnreadable arm (review 57765 rebuttal condition, lane-manager ruling) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
|
Addendum to the review 57765 response, per the lane manager's ruling on scope: (1) the four ladder climbs are now durably tracked in the PR body section "Follow-up climbs from dashboard review 57765" with named triggers; (2) the absorbing-fallback rebuttal now carries EXECUTING evidence on head — sent from crisp-newt-85 |
…apsing wrapper, unconstructable WindowUnobserved deleted, dead receipt-path row deleted, Gregorian day-in-month validation (Feb 30 / Apr 31 refuse; Feb 29 leap-year positive control) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VuaG6CT3EScsM13jQCbQoh
|
Response to review 57773 (dashboard artifact /api/reviews/57773/artifacts/stdout.log), on head
— sent from crisp-newt-85 |
briansrls
left a comment
There was a problem hiding this comment.
APPROVE — exact head f474d96575066e4227c9a49089c8ca8138e8f827 reviewed.
This approval supersedes my REQUEST_CHANGES review 5063097188 and closes RLM-2a at this exact head.
I independently verified the controlling completion bar:
-
Routed authority is load-bearing. Routed
/healthznow suppliesDeployedReleaseBinding, which requires the admitted revision and expected surface; the opening and closing observation-window snapshots read routed running-release and active-instance state. Localhost is retained only as a separately named complementary observation. The mixed-locus and routed-window-change discriminators are enrolled and execute green. -
The current receipt run is admitted against canonical identity. Before capture, its binding is judged against
gunbc_repository.full_name, the generated workflow path, its run id, and R.RunProvenanceFactcorrectly carries no impossible self-observation of the current run's terminal conclusion; predecessor conclusions remain API-observed and the current conclusion is an explicit post-run manager verification. -
Freshness is machine-readable rather than presentation text.
tick_standing.freshnessserializes the typed arm and unit-bearing age/bound payload. The split fresh/stale witnesses recover kind, age, and bound from one receipt document without parsingfacts_text. -
The wet procedure is singular and correlation-safe. The contradictory
R=<merge sha>/ arrival-order block is gone. The authoritative sequence selects R after merge, passesexpected_revision=$Ron every dispatch, carries a transaction nonce into the API-visible run title, selects exactly one run by nonce, verifies the downloaded receipt'srun_id, and performs the post-run conclusion check. -
Temporal falsification is discharged. The PR comment records all seven required non-production mutation families with mutant commit/tree identity, the exact relaxed mechanism, exact failing witness identities and terminals, restoration, and final-head green execution: expected-R dominance,
PartiallyApplied, timer-value equality, provenance/receipt identity, LeaseEpoch membership, routed-versus-local authority, and structured freshness.
Run 33368298684 is bound to this exact head and all five jobs succeeded. Its required floor reports 3251 planned / 3251 executed / 0 failed, FloorClean, and 107 changed witnesses planned-and-passed with zero blocking changed witnesses.
Ruling:
- RLM-2a: APPROVED and CLOSED at this exact head.
- PR #9761 merge: AUTHORIZED.
- RLM-3: remains CLOSED.
- RLM-2b: may advance after merge only through the R-selection/evidence gate. Bring the exact selected main revision R and its admission evidence for acceptance before any production plan, apply, dashboard, or receipt dispatch. This review does not authorize production dispatch.
extdeps.systemd SystemdUnitProperty carried two identical SubState arms and two identical wire arms. One name, two declarations in one coproduct, on main since #9761/#10443 -- a section 3 single-authority defect that stayed invisible because variant lookup took the first exact match and never asked whether a second existed. The refusal arm in this branch's find_variant_child_keyed is what surfaced it: both children key equal, so lookup refuses, and the required floor and the heal job both red with ChangedWitnessObservationFailed naming this line. The corpus population is measured, not assumed -- an arm-level scan of every coproduct declaration under dag/ and src/ finds exactly one declaration with a duplicated leaf key, this one. The duplicate declaration arm and its duplicate wire arm are deleted. Behaviour is unchanged: SubState still maps to "SubState", and the seven witnesses of test.claim.systemd_property_directive_overlap pass. This edit is outside the v1 seed scope of this PR and is admitted only as a forced consequence of a correct refusal, with a measured population of one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xa46zVYGRz2PUMouekjznP
One name, two declarations in a single type. Lookup by exact authored name takes the first match and never asks whether a second exists, so the duplicate is not merely tolerated -- it is unobservable, and no consumer can report it because none can distinguish the two. The receipt is live rather than constructed: extdeps.systemd SystemdUnitProperty carried two identical SubState arms since #9761/#10443 and passed every required run in that window, surfacing only when this branch began keying variant lookup and refusing on more than one match. Rung found at is recorded as mechanically preventable BY ACCIDENT, which is the honest grain: the refusal that caught it is a lookup-time consequence of keying for an unrelated repair, not a wall built for this class, and on any route that does not key the class stays silent. The ceiling is structural impossibility -- a duplicate leaf has no constructor once the declaration fold refuses it -- and the trigger names that capability, not an artifact. A lookup-side refusal does not retire the row. Filed on swift-bat-902's ruling that the declaration-time wall is a ledger obligation rather than gunbc#11301's scope, so the repair that surfaced the class is not mistaken for the wall against it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xa46zVYGRz2PUMouekjznP
RLM-2a — the MODELING half of RLM-2 (docs/plans/roadmap-launch-mvp-plan.md §3 RLM-2). Binds the RLM-1 join: main
0beef8a2c1a035f4f1f0507e77075bdeaba74cba, tree79d55f2e63af52c96a51a08dac969ff10fa30194,launch_admission_contract_digest_hex=8b884d701d7a356e(frozen asgunbc.roadmap_launch_deployment_cli rlm1_contract_digest_frozen; the receipt producer refuses at R if the live digest drifts from it). No production actuation: RLM-2b is the manager/operator's wet transaction and changes no source.The 10 deliverables → module.symbol
gunbc.fleet_converge_receiptFleetConvergePlanReceipt/FleetConvergeApplyReceipt(+ JSON wire, identity hex,admit_apply_plan_bindingwith four distinct refusals), minted insidegunbc.fleet_converge_plan_cli fleet_converge_plan_wet/fleet_converge_apply_wetbefore the ProcessExit projection (plan receipt lives in the plan artifact dir so the existing upload/download carries it; apply receipt has its own artifact).gunbc.live_deploy.apply_receiptLiveDeployApplyReceipt(expected revision, candidate revision + surface + root-tree OID, target decision, apply outcome, one independent post-apply readiness read, fleet provenance,completed_at), minted by the newgunbc.live_deploy.apply live_deploy_apply_srv1_transaction_wetaround the unchanged fold; the plain operator entry is untouched.gunbc.roadmap_launch_deployment_receiptRoadmapLaunchDeploymentSubject,RoadmapLaunchDeploymentFacts(18 members, each a typed standing with its own refusal arms),roadmap_launch_deployment_blockers(every member consulted, blockers accumulated),RoadmapLaunchDeploymentVerdict = DeploymentComplete { subject, facts, proof } | DeploymentIncomplete { subject, facts, first_blocker, further_blockers }.DeploymentCompleteProofissole_constructor: no module other than the join can write it, and the join writes it in exactly one place (roadmap_launch_deployment_verdict, empty blocker list). Both arms serialize (roadmap_launch_deployment_receipt_document).gunbc.live_deploy.deployed_tree_observationdeployed_tree_root_tree_argv(git rev-parse HEAD:— the colon form is the one spelling the portability wall admits;^{tree}is refused byportable_remote_word_char_allowed), one more leg on the sameDeployedTreeLocus/run_typed_argv_transport;DeployedTreeObservedgainstree: GitObjectId;deployed_root_tree_standingrequires OID equality ANDDeployedScopeMatchesCommit. Candidate side:gunbc.live_deploy.apply_receipt observe_candidate_root_tree_oid(same colon form on the deploying checkout).gunbc.roadmap_belt_actuateschemaroadmap-belt-tick-receipt/v4,BeltTickExecutionStanding = TickExecuted { instance_id, deployed_revision, spawn_mode } | TickExecutionWithheld { refusal },receipt_identityderived (belt_tick_receipt_identity_hex), written on the wire and verified on decode; minted atbelt_run_once_cli_inviabelt_tick_execution_standing_for_instance(the instance'sfleet_revision_standing+roadmap_belt_production_spawn_mode). A v3 document refuses the decoder (witness_v3_tick_receipt_refuses_the_v4_decoder). Freshness:gunbc.roadmap_launch_deployment_observe belt_tick_freshness(aftercompleted_atof the dashboard receipt, within 3 × the emitted 60s cadence).gunbc.live_deploy.unit_standing:extdeps.systemd.systemd SystemdUnitPropertywidened (LoadState, UnitFileState, SubState, Result, ExecMainStatus, ExecStart, User, WorkingDirectory, Unit, NextElapseUSecMonotonic, TimersMonotonic) and read through the existingsystemd.Systemctl.ShowProperty; expectations DERIVED from R's emitted units (gunbc.live_deploy.emit live_deploy_serve_unit_file/live_deploy_belt_service_unit_file/live_deploy_belt_timer_unit_file, factored out of the doc producers); three judgements modeled on what the units are: dashboardsimple(loaded/enabled/active + exact ExecStart/User/WorkingDirectory), belt timer (loaded/enabled/active-waiting, exactUnit=target, OnBootUSec + OnUnitInactiveUSec entries present), belt oneshot (static, lastResult=success,ExecMainStatus=0, exact ExecStart/User/WorkingDirectory, inactive between ticks accepted). Timer cadence VALUES (OnBootUSec, OnUnitInactiveUSec, AccuracyUSec) are normalized throughextdeps.systemd systemd_duration_usec(systemd.time(7),std.measure Microsecond) and compared against expectations derived from R's emitted timer unit — the former structural-only residue is dissolved;60sand1minare one value./healthz,/instance.json,/workflow.jsonobservers + decoders —gunbc.roadmap_launch_deployment_observe(observe_healthz→observe_running_release_identity;dashboard_instance_document_decode;roadmap_workflow_document_decodewith the embeddedbelt_tickdecoded by the receipt's own decoder — 200 is not sufficient, absent/unreadable tick refuses). Renderers are no longer cited as evidence anywhere on the receipt path.hostinput (FLEET_CONVERGE_EXPECTED_HOST), records the observed host; the join requires plan/apply observed host ==srv1and the receipt run's own hostname ==srv1; effective principal viaextdeps.access.posix_effective_principal(whoami) must equal the emitted beltServiceUser; footprint / provider (dispatch_actuator_selection→belt_provider_preflight_for_instance) /dispatch_preflight_for_instanceall run in that same process and bind to the active instance.gunbc.actions_run_binding(GITHUB_REPOSITORY,GITHUB_WORKFLOW_REF,GITHUB_RUN_ID,GITHUB_SHA— the last two variable names added toextdeps.github.actions_environment),RLM_EXPECTED_REVISIONas the independent operator input,admit_run_revision,run_binding_names_workflow_file; every receipt carries its binding and the join checks repository / workflow file / run id / revision per run. One per-host mutation domain:gunbc.fleet_workflow_steps fleet_host_mutation_concurrency_group_expression(gunbc-host-mutation-${{ inputs.host }}) now on the fleet-converge job, the dashboard-deploy job and the receipt job (replaces the dashboard-only literal group). Observation window opened and closed (WindowSnapshot: main, desired, deployed revision + tree, running release, transition, active instance) →WindowChangedblocker.gunbc.roadmap_launch_deployment_cli persist_receipt: canonical bytes staged attarget/rlm-launch-deployment-receipt/receipt.json, SHA-256 bysha256sum, written withFilesystem.WriteOwnerOnly(O_EXCL) to<instance_receipts_dir>/launch-deployment/<sha256>.json, digest read back and compared (a differing pre-existing file at the address refuses); the staged copy is uploaded as run artifactrlm-launch-deployment-receiptwithalways()and 90-day retention. Incomplete receipts persist too; exit 0 only for a persisted Complete.gunbc.fleet_converge_workflow: moderlm_launch_deployment_receipt, inputsexpected_revision,apply_workflow_run_id,dashboard_workflow_run_id, new jobfleet_converge_rlm_launch_deployment_receipt_job(host-pinned runner, WIF + fleet key agent for the FleetSsh tree readback, downloads the three predecessor receipts by run id, uploads its own), apply-receipt upload on the apply mode, dashboard mode switched to the receipted entry with env;.github/workflows/fleet-converge.ymlregenerated viagenerated_artifact_gate.dag --function main_wet, never hand-edited. CI targets enrolled ingunbc.ci.ci_spec gunbc_run_step_targets.Red controls (all hermetic; RED committed first, each replaces one member of an otherwise Complete population)
dag/test/claim/roadmap/roadmap_launch_deployment_receipt_witness_test.dag— positive controlwitness_complete_population_is_complete, then one witness per ruling row: plan/apply/dashboard run at another SHA; plan run-id substitution; apply bound to another plan; dashboard bound to another R; input srv1 vs observed host srv2 (plan) and receipt-run host srv2; candidate/deployed root-tree mismatch; v3 / stale / wrong-instance / wrong-revision / AutomaticReady tick; disabled timer beside a fresh tick; inactive-successful oneshot positive control (the Complete fixture itself) + active-mid-tick positive control; wrong principal; observation window changed; and the four destructive falsifiers run synthetically — transition marker (ActuationInhibited), unwritable root (FootprintRefused), missing provider credential (ProviderPreflightRefused), unobservable attempt ledger / absent tick on/workflow.json; desired ref behind R. Totality: two substitutions retain both blockers; Incomplete document carries its blockers; receipt identity stable and discriminating.Supporting witnesses:
fleet/fleet_converge_receipt_witness_test.dag(round trips, tamper → identity refusal, four plan-binding refusals, run-binding predicates),live_deploy/apply_receipt_witness_test.dag,live_deploy/unit_standing_witness_test.dag(ExecStart parse, disabled timer RED, inactive-successful oneshot GREEN, wrong user RED, expectations derived from the srv1 spec),roadmap/roadmap_launch_deployment_observe_witness_test.dag(ISO-8601 epoch oracle values, four freshness arms,/instance.jsonand/workflow.jsondecoders incl. embedded v3 → Unreadable, v4 tamper refusal, root-tree argv admitted by the portability wall, root-tree standing mismatch).Rework for review 5061891290 (REQUEST_CHANGES on 06c2e31) — all seven findings
gunbc.fleet_converge_plan_cli: bothfleet_converge_plan_wetandfleet_converge_apply_wetreadRLM_EXPECTED_REVISION(gunbc.actions_run_binding read_expected_revision) and refuse viaadmit_run_revision— a typed comparison of two origins — BEFORE any actuation (fleet_converge_locked_apply_scriptis unreachable when Q≠R). The admitted revision is carried on the apply receipt (expected_revision_admitted, in identity + wire). Workflow env regenerated:RLM_EXPECTED_REVISION: ${{ github.event.inputs.expected_revision }}on the plan and apply steps. RED:witness_apply_admitted_against_q_is_incomplete_at_apply_receipt.gunbc.fleet_converge_plan FleetConvergeApplyTerminal(FullyApplied | PartiallyApplied { refused_axis_count, detail }) with wire spelling + decoder; carried on the plan artifact and BOTH fleet receipts; the join'sapply_outcome_blockersrequiresFullyAppliedandexpected_revision_admitted == subject.revision. RED:witness_partially_applied_exit_zero_is_incomplete_at_apply_receipt(fixture is PartiallyApplied under a green exit; first_blocker=apply_receipt).extdeps.systemd systemd_duration_usecmodels systemd.time(7) span normalization (usec→hours spellings, microsecond result, malformed part ⇒ Absent — never a partial sum).TimerUnitExpectationgainson_boot_usec/on_unit_inactive_usec/accuracy_usecDERIVED from R's emitted timer unit (timer_directive_duration_usecover the same directives; one authority —gunbc.roadmap_launch_deployment_observe belt_tick_cadence_seconds_derivednow derives the freshness bound from the same emittedbelt_tick_cadence, deleting the hand-typed 60).judge_belt_timercompares normalized OnBootUSec/OnUnitInactiveUSec (TimersMonotonic) and AccuracyUSec against those values; each mismatch is a typedBeltTimerRefusednaming the property in decimal usec. REDs:witness_timer_with_wrong_cadence_value_refuses(wrong cadence beside an otherwise-clean timer),witness_systemd_duration_normalizes_equal_spellings,witness_derived_timer_expectation_carries_the_emitted_cadence.repositoryis nowgunbc.repository gunbc_repository.full_name(canonical authority, not restated from the observed run).RunProvenanceFacton the facts: each predecessor (plan/apply/dashboard) read back through the runs API (extdeps.github.workflow_runs GetRun, which now carriespath) and required to beconclusion=success,head_sha == R,path == subject.workflow_path,run_idexactly the bound input; the receipt run's ownGITHUB_WORKFLOW_REFmust name the generated workflow file (run_binding_names_workflow_file). Dashboard provenance carries the exact predecessor receipt IDENTITIES (plan_receipt_identity/apply_receipt_identityonLiveDeployFleetProvenance, populated inlive_deploy_apply_srv1_transaction_wetfrom the two downloaded receipts — the workflow's dashboard job now downloads both) and the join recomputes both identities from the receipts it read. REDs: the six*_is_incomplete_at_run_provenancewitnesses +witness_dashboard_citing_another_plan_receipt_is_incomplete_at_dashboard_receipt+witness_dashboard_receipt_with_tampered_plan_receipt_identity_refuses.FleetConvergePlanReceiptgainslease_resource_fingerprint,lease_owner_fingerprint,lease_generationbesidelease_key(identity + wire + decoder). REDs: three per-member tamper witnesses.rlm_routed_base_url()derives the production endpoint from the deployment authority (deployment_tailnet_url(spec: deployment_spec_srv1()));/healthz,/instance.json,/workflow.jsonare observed THROUGH that routed base (extdeps.http GetBounded,observe_*_routed); readiness and the workflow/instance facts come from the routed reads; the localhost read remains only as the complementary release-binding probe. An underivable route is a typedHealthzRefused, never a localhost fallback.roadmap_launch_deployment_receipt facts_jsonserializes ALL facts members as a typed-arm JSON object (each member{arm, …payload}, embedded receipts as their full receipt JSON); the receipt identity is derived fromsubject_identity_text + serialize_json(facts_json(f)), and the document carriesfacts(structured) besidefacts_text(presentation lines, no longer identity-bearing). RED:witness_receipt_document_facts_are_machine_readablerecovers frozen-join members from the JSON document without parsing prose.Wet-template corrections (review findings a+b): R is the exact admitted MAIN revision selected AFTER this PR merges (possibly a later descendant chosen by the operator) — not definitionally this PR's merge commit; and predecessor run ids are captured from the receipt-bound artifacts of the runs the operator actually dispatched (each receipt names its own
run_id), never discovered via an uncorrelatedgh run list --limit 1.Verification status — FINAL, on head
f474d96575066e4227c9a49089c8ca8138e8f827CI (the evidence of record): run 33368298684, headSha
f474d96575066e4227c9a49089c8ca8138e8f827— all 5 checks SUCCESS;required-floor: verdict=FloorClean unexpected_failures=0 verdict_incomplete=0 non_verdict_unenrolled=0 stale_non_verdict=0; changed-witness sublane 107/107 identitiesstanding=planned-and-passed, zero in any other standing — including both BuildBuddy-OOM files, all 19 review-5061891290 rework witnesses, the B1/B2/B3 controls, the decode-refusal witness, and the calendar-validation arms. Local corroboration: per-fileclaim_batchgreen on every touched file on this tree (7+13+44 on the last delta; full 5-file baselines green at each prior station).fleet-converge.ymlregenerated only viagenerated_artifact_gate.dag --function main_wet.Head lineage since the controlling review: B1–B4 repairs +
transaction_nonce/run-name(e49dd85) → freshness witness split for the floor's 500ms CPU line (05e93e1) → main merges througha6d6c68d4d(785cc03) → review 57760 measure/coproduct fixes (f14021d) → decode-refusal executing witness per the lane-manager ruling (e5e9967, CI run 33365472053 SUCCESS on that head) → review 57773 fail-closed fixes: class-preserving member reads,WindowUnobserveddeleted as unconstructable, dead path row deleted, Gregorian day-in-month validation (f474d96). The 7-family mutation-falsification record is in the PR comment "Mutation-falsification record…"; every mutant anchors on mechanisms byte-identical on this head.Rework for review 5062738052 / 5063097188 (REQUEST_CHANGES) — B1–B4 + mutation evidence
deployed_release_bindingnow consumes the ROUTED/healthzidentity (revision AND surface;ReleaseSurfaceMixedblocks), and the observation window'srunning_release_hex/active_instancemembers read through the routed base (running_release_hex_routed/active_instance_text_routed); no localhost read remains on the receipt path — the local observers stay ingunbc.roadmap_launch_deployment_observeas separately named complementary diagnostics. REDs:witness_routed_surface_mixed_is_incomplete_at_release_binding,witness_route_change_during_window_is_incomplete_at_observation_window.gunbc_repository.full_nameAND the generated workflow file AND R;RunProvenanceObservedcarriesreceipt_repositoryand the join blocks on it. The split is stated AT THE MODEL (annotation onRunProvenanceFact): three predecessor conclusions are API-read; the current run's terminal conclusion is structurally unobservable from inside itself and is an explicit POST-RUN manager verification (RLM-2b final step) — never an internal claim. RED:witness_receipt_run_in_another_repository_is_incomplete_at_run_provenance.facts_jsonserializes freshness as its own typed-arm object (fresh{age_seconds} | stale{age_seconds,bound_seconds} | before_deploy | instant_unparseable | cadence_unnormalizable, seconds viastd.measure second_count); the round-trip witnesses recover age and bound by JSON navigation, never prose:witness_receipt_document_fresh_age_is_machine_readable,witness_receipt_document_stale_age_and_bound_are_machine_readable(split into one document each after the two-document form was budget-refused at the floor's 500ms CPU line on run 33358233304).expected_revision=$Ron every dispatch and nonce-based run-id correlation:transaction_nonceis a generated workflow input echoed intorun-name(regenerated YAML), each run id selected by its nonce indisplayTitle, and the downloaded receipt's ownrun_idmust equal the selected id. Stale structural-cadence claims removed from the deliverable map andunit_standing.dag.Verification status — superseded record, head
9b89da837cea4ac932fb7f3ae4e2c5d17b4bbe72Current head = the 4683c48 state below + merge of main through
bfa440b66d(org-actions mode #9778, unioned infleet_converge_workflow.dag, YAML regenerated) + dissolution of the stale cadence-residue note inunit_standing.dag(annotation-only). On THIS head: workflow run 33354805028 — all 5 checks SUCCESS;required-floor: verdict=FloorClean unexpected_failures=0 verdict_incomplete=0 non_verdict_unenrolled=0 stale_non_verdict=0; changed-witness sublane 101/101 identitiesstanding=planned-and-passed; local per-fileclaim_batch88/88 rc=0 on the merged tree; mergeable CLEAN; dashboard approvals on the head lineage (reviews 57713, 57731, 57734).Verification status — rework record, head
4683c48b4b0b148e3722189360af8bf006f42701Head = seven-finding rework for review 5061891290 (
a2a43a139e) + merge of main through0a6d177619(e7d171b017) + review 57708 fixes (4683c48b4b:Microsecond/Secondmeasure carriers, three named timer-directive readers replacing the string-tag selector, symbol citation).CI (the evidence of record): workflow run 33349151228, headSha
4683c48b4b0b148e3722189360af8bf006f42701— all 5 checks SUCCESS;required-floor: verdict=FloorClean unexpected_failures=0 verdict_incomplete=0 non_verdict_unenrolled=0 stale_non_verdict=0. The changed-witness sublane executed 101 identities, every onestanding=planned-and-passed outcome=passed, at these per-file counts: fleet_converge_receipt_witness 17, apply_receipt_witness 6, unit_standing_witness 13, roadmap_launch_deployment_observe_witness 13, roadmap_launch_deployment_receipt_witness 39, roadmap_belt_actuate_witness 7, deployed_tree_observation_witness 4, roadmap_launch_admission_witness 1, release_binding_witness 1. That roster includes both files BuildBuddy cannot hold (observe 13, receipt 39) and all 19 rework witnesses by exact identity. Chain: reviewed head → run 33349151228 (headSha = reviewed head) → changed-witness roster → 101 exact identities → executed terminal PASS each.Local corroboration on the same tree: per-file
claim_batch(31 GiB container): 17+6+13+13+39 = 88 witnesses, rc=0 each;fleet-converge.ymlregenerated bygenerated_artifact_gate.dag --function main_wetwith only that artifact changing.Rework red controls (added to the roster; RED is executed by fixture discrimination inside the same witnesses)
witness_partially_applied_exit_zero_is_incomplete_at_apply_receiptapply_receiptwitness_apply_admitted_against_q_is_incomplete_at_apply_receiptapply_receiptwitness_predecessor_non_success_conclusion_is_incomplete_at_run_provenancerun_provenancewitness_predecessor_at_another_sha_is_incomplete_at_run_provenancerun_provenancewitness_predecessor_on_another_workflow_is_incomplete_at_run_provenancerun_provenancewitness_predecessor_run_id_substitution_is_incomplete_at_run_provenancerun_provenancewitness_receipt_workflow_ref_not_named_is_incomplete_at_run_provenancerun_provenancewitness_provenance_unobserved_is_incomplete_at_run_provenancerun_provenancewitness_dashboard_citing_another_plan_receipt_is_incomplete_at_dashboard_receiptdashboard_receiptwitness_receipt_document_facts_are_machine_readablewitness_plan_receipt_with_tampered_lease_resource_fingerprint_refuseswitness_plan_receipt_with_tampered_lease_owner_fingerprint_refuseswitness_plan_receipt_with_tampered_lease_generation_refuseswitness_apply_receipt_partially_applied_round_tripswitness_apply_receipt_with_unknown_terminal_wire_refuseswitness_dashboard_receipt_with_tampered_plan_receipt_identity_refuseswitness_systemd_duration_normalizes_equal_spellingswitness_timer_with_wrong_cadence_value_refuseswitness_derived_timer_expectation_carries_the_emitted_cadenceVerification status — pre-rework record, head
06c2e317430b80593a4d4a0e07957d447f3fedb0CI (the evidence of record): workflow run 33331924621 on head
06c2e317430b80593a4d4a0e07957d447f3fedb0— all checks SUCCESS;required-floor: planned=3202 executed=3202 failed=0 … verdict=FloorClean. The changed-witness sublane prints one identity line per touched witness; all 82 readstanding=planned-and-passed, at these counts: fleet_converge_receipt_witness 12, apply_receipt_witness 5, unit_standing_witness 10, roadmap_launch_deployment_observe_witness 13, roadmap_launch_deployment_receipt_witness 29, roadmap_belt_actuate_witness 7, deployed_tree_observation_witness 4, roadmap_launch_admission_witness 1, release_binding_witness 1. Chain per the reviewer bar: reviewed head → run 33331924621 (headSha = reviewed head) → changed-witness roster → 82 exact identities → executed terminal PASS each. No independent-dispatch gap remains, so no file split is needed.BuildBuddy per-file
claim_batchcorroboration (one VM per file; a multi-file batch OOMs the 7.5 GB guest): fleet_converge_receipt 12/12, apply_receipt 5/5, unit_standing 10/10, each with[resolve-summary] … N witness(es)footers. The observe (13) and receipt (29) files exceed the guest at every budget; their executing route is the CI floor above.RED-first evidence (executed red before green, each on a real run): the tamper controls asserting the unspaced JSON separator ran RED on BuildBuddy (
FAIL witness_plan_receipt_with_tampered_host_refuses,FAIL witness_dashboard_receipt_with_tampered_candidate_refuses); the two document witnesses ran RED on floor run 33329794671 (returned Bool(false)); the 29 receipt witnesses ran RED on floor run 33327970268 (undefined variable: FleetConvergeYamlArtifact) — then green on 33331924621 after the named fixes. The committed controls discriminate by execution, not by construction order alone.Generated-source provenance:
.github/workflows/fleet-converge.ymlregenerated bygenerated_artifact_gate.dag --function main_weton this tree (local 31 GiB container; BuildBuddy cannot hold the resolve — finding 9); the regen changed only that artifact (+174/−6) and the drift gate class stands as the declared §4b rung drop.Red-control roster (each substitutes ONE member of the otherwise-Complete population)
witness_complete_population_is_complete-witness_complete_receipt_document_names_its_verdict_and_identity-witness_plan_run_at_another_sha_is_incomplete_at_plan_receiptplan_receiptwitness_apply_run_at_another_sha_is_incomplete_at_apply_receiptapply_receiptwitness_dashboard_run_at_another_sha_is_incomplete_at_dashboard_receiptdashboard_receiptwitness_plan_run_id_substitution_is_incomplete_at_plan_receiptplan_receiptwitness_apply_bound_to_another_plan_is_incomplete_at_apply_receiptapply_receiptwitness_dashboard_bound_to_another_r_is_incomplete_at_dashboard_receiptdashboard_receiptwitness_plan_observed_on_another_host_is_incomplete_at_plan_receiptplan_receiptwitness_receipt_run_on_another_host_is_incomplete_at_observed_hostobserved_hostwitness_deployed_tree_mismatch_is_incomplete_at_deployed_treedeployed_treewitness_stale_tick_is_incomplete_at_tick_standingtick_standingwitness_wrong_instance_tick_is_incomplete_at_tick_standingtick_standingwitness_wrong_revision_tick_is_incomplete_at_tick_standingtick_standingwitness_automatic_ready_tick_is_incomplete_at_tick_standingtick_standingwitness_v3_tick_on_disk_is_incomplete_at_tick_standingtick_standingwitness_disabled_timer_beside_fresh_tick_is_incomplete_at_unit_standingunit_standingwitness_active_oneshot_mid_tick_is_still_complete-witness_wrong_principal_is_incomplete_at_principalprincipalwitness_window_change_is_incomplete_at_observation_windowobservation_windowwitness_transition_marker_is_incomplete_at_transitiontransitionwitness_unwritable_root_is_incomplete_at_footprintfootprintwitness_missing_provider_credential_is_incomplete_at_provider_preflightprovider_preflightwitness_unobservable_attempt_ledger_is_incomplete_at_workflow_endpointworkflow_endpointwitness_workflow_json_without_a_tick_is_incomplete_at_workflow_endpointworkflow_endpointwitness_desired_ref_behind_r_is_incomplete_at_desired_revisiondesired_revisionwitness_two_substitutions_retain_both_blockers-witness_incomplete_receipt_document_carries_its_blockers-witness_receipt_identity_is_stable_and_discriminating-RLM-2b — the wet transaction (NOT run by this PR; manager/operator only)
The executable sequence lives in ONE place — "Authorized RLM-2b sequence (manager/operator only; corrected per review 5062738052 B4)" below — with the nonce-based run-id correlation and
expected_revision=$Ron every dispatch. The earlier command block that stood here (R defined as this PR's merge sha; run ids viagh run list --limit 1) is deleted as contradictory to its own correction note.Follow-up climbs from dashboard review 57765 (ruled OUT of RLM-2a scope by the lane manager; tracked here per the ruling's condition 1)
Each is a real guarantee-ladder climb on shapes consistent with current in-tree conventions; each opens a model layer ahead of its consumers, so it lands as its own change with its own witnesses. None is half-adopted in this PR — the only 57765-adjacent change here is the executing witness for the target_decision decode refusal (
witness_unknown_target_decision_label_is_unreadable_not_absorbed).extdeps.systemdcoproducts + wire contracts for LoadState / UnitFileState / SubState / Result (ActiveState's already exist), thenServiceUnitObserved/TimerUnitObservedparse at the boundary and the judges match arms instead of wire literals; same change internalizes the systemd.time(7) unit-spelling table as a closedSystemdTimeUnitcoproduct (review 57773)systemctl showrendering parse placementexec_start_argv_of_show_value/show_rendered_duration_usecbeside the ShowProperty operation inextdeps.systemd.systemctl, where the rendering format is citedGitObjectId/CommitShaconstructed at the env/API boundaries (actions_run_binding.run_revision, receiptcandidate_revision/candidate_tree_oid) with the four receipt codecs' identity witnesses regenerated in the same changecompleted_atstd.types Timestamp = Stringaliases dissolve into — model lands before the receipt consumers adopt itWhere the ruling could NOT be satisfied by the existing model (findings, not patches)
systemctl show TimersMonotonicrendersOnBootUSec=2min; there is no systemd duration model inextdeps.systemdto ground an equality with the emitted2min/1min. The judgement requires both entries present and the exactUnit=target. Trigger: aSystemdDurationmodel inextdeps.systemdwith a decoder overshowoutput.principalmember compares the receipt process's effective principal (whoami) with the emittedUser=; the host-pinned runner runs as the same account today, but nothing in the workflow model asserts asudo -u— if the runner account ever differs, the member blocks (correctly) and the fix is a modeled principal switch, not a relaxation.GITHUB_WORKFLOW_REF(repo/path@ref), not agh run viewfield — the run API exposes nopath. The predicate is a prefix match on<repo>/<workflow file>@.Unsized(dispatch_actuator_selection(node_sizing: Unsized)) because the receipt has no work item to size; it proves the credential + provider binding of the production selection path, not a specific sizing arm.live_deploy_apply_srv1_wetentry is retained beside the transaction entry for the operator's manual route; only the transaction entry is wired into the generated workflow.EXPECTED_HASHprelude on the apply job remains the pre-existing untyped shell guard; the typedadmit_apply_plan_bindingrefusal is now the authority behind it, and the prelude is a redundancy candidate for a follow-up removal once the typed gate has one wet green.workflow_path: artifact_path(a: FleetConvergeYamlArtifact)in a bare-name witness errored at runtime for all 29 receipt witnesses; routing it throughrlm_workflow_file_path()in the CLI module (where the import lives) resolved it. Same family: a freesplit(s:, delimiter:)call resolved on one line of a function and not five lines below inside a match-arm block (function 'split' not found in scope), andlist_head(reverse(parts))inferredPrimitive(T), erasing the method surface — the parse now uses the corpus'sfoldidiom.main_wetresolve exceeds the 7.5 GB guest at everyGUNBC_MEMORY_BUDGET_BYTES(12 GB → 600 MB, three kills). Regenerated locally (31 GiB container) with the freshly built binary; the drift gate (declared §4b rung drop) guards the artifact at CI.Controlling ruling
===== SUPERSEDING RLM-2 RULING (reviewer, verbatim) =====
Ruling
The two-phase architecture is accepted, but the draft is not dispatchable verbatim. Treat the amendments below as the superseding RLM-2 gate brief.
The operational shape is one modeling PR plus one wet execution transaction, not two PRs. RLM-2b changes no source and therefore has no PR of its own.
Your central decisions are right:
ManualReadyobservation; it cannot be the RLM-1 merge.The controlling plan requires an exact plan/apply transaction, dashboard deployment of the same revision, independent release/tree/readiness/transition/service/timer/preflight observations, and one joined
RoadmapLaunchDeploymentReceipt. fileciteturn55file01. R is selected after RLM-2a merges, then held fixed
Do not define R in advance as “the RLM-2a merge commit.” Define it as:
It may happen to be the RLM-2a merge commit. If another unrelated main commit lands before the wet window, R is that later descendant or the transaction waits for a new selection.
This matters immediately: main had already advanced from the RLM-1 merge to
d21370bd9526db6eac8f62fcb0af6ca04a81e1f6during this review. fileciteturn107file0L1-L2Once R is selected:
main == R.refs/fleet/desired == R.--ref R.GITHUB_SHA == R.FleetDesiredAcceptedRevisionproves that one required-CI/default-branch event was admissible; by itself it does not prove that main and the desired ref still equal that revision at final readback. fileciteturn99file02. The plan/apply and dashboard transactions need typed receipts
This is the largest missing seam in the draft.
Fleet apply
The existing plan artifact is a strong authority: it carries the host/scope/member-set subject, prior generation, held lease, observed baseline, plan body, apply body, and bundle hash. fileciteturn101file0
However,
fleet_converge_plan_wetandfleet_converge_apply_wetcurrently flatten their results toProcessExit. The workflow’s apply job binds a prior plan run and artifact hash, but there is no durable typed apply receipt exported from that transaction. fileciteturn63file0 fileciteturn106file0The existing
ConvergeCliReceiptis not that receipt. It belongs to the separate periodic/legacygunbc convergepath and carries only:It does not bind the reviewed plan hash, plan subject, baseline, lease generation, plan run, apply run, or executing revision. fileciteturn105file0
RLM-2a therefore adds, or factors out, exact equivalents of:
The apply receipt must be produced inside the typed apply composition before its CLI projection becomes
ProcessExit.Dashboard deployment
dashboard_deployis currently an independent workflow job invokinglive_deploy_apply_srv1_wet. It takes neither an expected revision nor the selected plan/apply transaction, and it emits no typed transaction receipt. fileciteturn64file0RLM-2a must add an exact equivalent of:
The plan hash does not become a second eligibility authority for live deploy. R is the shared safety key. The plan/apply identity and hash ride on the dashboard receipt as provenance, so the final join cannot combine an arbitrary fleet transaction with an arbitrary dashboard transaction.
3. Correct the final receipt shape
The proposed
Complete | Incomplete{first blocking member}is too lossy. It would discard valid sibling observations after the first refusal and make diagnosis depend on evaluation order.Use this shape, or an exact typed equivalent:
The complete arm has one private/sole production constructor that explicitly matches every positive arm and verifies all revision, host, instance, run, and identity equalities. There is no public record literal that can author
DeploymentComplete.Every independent read should still run.
first_blockeris an ordered presentation projection over a nonempty blocker population, not the only retained evidence.Both Complete and Incomplete results are serialized and persisted. The workflow exits successfully only for Complete.
4. Add the missing deployed-tree identity member
Your G1 says every member already has an existing type, but the controlling plan’s deployed tree digest does not.
The current deployed-tree authority carries:
It does not carry a root-tree object identity. fileciteturn85file0
Add G7 within the existing
DeployedTreeLocusand transport:HEAD^{tree}through the same sealed srv1 locus;DeployedScopeMatchesCommit.This is an additional argv on the existing typed observer, not a second remote-revision transport.
deployed_tree_report_ci_wetremains only a renderer/CLI edge. The deployment receipt consumes the typed observation and standing directly; it must never parse the report text. fileciteturn77file05. Health and workflow evidence must be actual live HTTP observations
Two entries in the authority map currently name renderers as though they were observers:
healthz_body_with_release_identityconstructs the expected body; it is not evidence that the routed service returned it.serve_workflow_response_for_instanceconstructs the route response; calling it in the receipt process would not prove the deployed public route served those bytes.The final receipt mode must execute live GETs against the production endpoint and type the results:
The running-release parser validates both revision and surface identity, and
DeployedReleaseBindingindependently joins the process announcement to the deployed tree. fileciteturn82file0 fileciteturn79file0The
/workflow.jsonparser must not treat HTTP 200 as sufficient. The current wire can return a valid workflow document while its nestedbelt_tickis absent or unreadable; those states must refuse RLM-2 rather than become “Idle.” The route currently embeds the persisted tick receipt as a typed Present/Absent/Unreadable standing. fileciteturn92file0 fileciteturn97file0Also observe
/instance.jsonor its exact existing typed equivalent. The active routed instance must equal the instance named by the tick, unit standing, footprint, provider preflight, and receipt path.6. G2 becomes a bound and fresh tick receipt, not only
spawn_modeBumping the current tick receipt with one string field is insufficient. The current v3 receipt contains
observed_at, launch identities, and four pass outcomes, but no instance, mode, deployed revision, or receipt identity. fileciteturn92file0RLM-2a should bump the schema and add a typed execution standing:
For RLM-2 Complete:
An old v3 receipt refuses. A v4 receipt from another instance, revision, mode, or pre-deployment timestamp refuses.
/workflow.jsonprojects this exact receipt and identity. It does not derive mode fromroadmap_belt_production_spawn_mode.The wet procedure waits for a natural timer-triggered tick after dashboard deployment. Manually invoking
belt_run_oncewould prove that the service can run, not that the timer is active.7. Q2: G4 is mandatory, but model the correct systemd states
G4 remains in scope. Readiness plus a fresh tick cannot prove the timer is enabled now: a service can be invoked manually, write one fresh receipt, and sit behind a disabled timer.
The controlling plan independently requires service/timer state. fileciteturn55file0
Do not model “service and timer are both enabled and active,” because the emitted units deliberately have different semantics:
Type=simple;Type=oneshot;timers.target, targeting the oneshot service, withOnBootSec=2min,OnUnitInactiveSec=60s, andAccuracySec=5s. fileciteturn75file0The positive unit standing is therefore:
Add the smallest typed
systemctl show/ system-scopeis-enabledobserver needed. The extdeps surface currently modelsIsActive, while its own note says there is no modeled system-scopeIsEnabledoperation. fileciteturn72file0The discriminating positive control is important: a correctly completed inactive oneshot must remain green.
8. Bind every ambient preflight to srv1 and the service principal
The current workflow’s plan/apply jobs run on generic
[self-hosted, ARM64]. Thehost=srv1input does not itself select srv1;fleet_converge_plan_wetobserves the local kernel hostname and constructs the plan subject from that host. fileciteturn62file0 fileciteturn106file0RLM-2a must make one of these true:
In either case, the typed plan receipt records the observed host and refuses unless it is srv1. Artifact naming from the workflow input is not host evidence.
The same applies to footprint and provider observations.
belt_footprint_admission_for_instancedeliberately states that writability must be tested as the effective principal that will perform dispatch, not as a privileged deploy or runner account. fileciteturn92file0The receipt must therefore prove:
Then run:
belt_footprint_admission_for_instance;belt_provider_preflight_for_instancefor the exact provider selected by production;dispatch_preflight_for_instance.DispatchPreflightReportremains complementary: its source explicitly says provider authentication is not one of its axes. It cannot substitute forBeltProviderPreflight. fileciteturn95file09. Bind the four workflow runs and prevent mixed snapshots
The frozen transaction has four, not two, workflow runs:
The desired-admission workflow run is additional provenance.
Every run/artifact binding must verify:
The current apply job already downloads one exact plan run and checks the bundle hash; preserve that mechanism and add source-revision and typed-receipt binding. fileciteturn63file0
Apply, dashboard deploy, and final readback must share one srv1 production mutation/convergence concurrency domain, or an equivalent modeled host lease. Today plan/apply and dashboard deploy have separate concurrency groups and may overlap. fileciteturn62file0 fileciteturn64file0
The final readback additionally observes at both the beginning and end:
A change during capture produces
DeploymentIncomplete { blocker: ObservationWindowChanged }, not a self-consistent join assembled from two production moments.10. Q1: persist exact bytes on the host and as a workflow artifact; do not commit them
Artifact-only with 30-day retention plus a manager-recorded identity is insufficient. The current workflow’s plan artifact retention is 30 days. fileciteturn62file0
Do not commit the wet receipt to main. That would create a new main revision after R and immediately invalidate the exact equality the receipt is supposed to freeze. A production observation is also not source authority.
Required durability:
The existing per-instance receipt root is already modeled by
instance_receipts_dir; add a dedicated content-addressed deployment-receipt path below it. fileciteturn104file0Incomplete receipts are persisted too. A refusal is evidence, not discarded output.
11. Q3: the RLM manager/operator dispatches RLM-2b
gh workflow runis an acceptable transport. There is no requirement to use the GitHub web UI.The implementation worker for RLM-2a may prepare the exact commands and evidence template, but it may not autonomously actuate production. After RLM-2a merges and R is selected, the RLM manager under the operator’s authority dispatches the serial transaction.
A delegated worker dispatch would require a separate one-shot authorization naming:
Absent that exact grant, dispatch remains manager/operator-only.
Superseding RLM-2a acceptance bar
The RLM-2a work item may now be created with these required deliverables:
RoadmapLaunchDeploymentSubject, complete fact population, and total verdict./healthz,/instance.json, and/workflow.jsonobservers and decoders.rlm_launch_deployment_receiptmode emitted fromgunbc.fleet_converge_workflow; generated YAML is regenerated, never hand-edited.The red controls land first and exercise the exact production completion fold. In addition to your seven controls, include:
srv1while observed runner host is not srv1;The destructive falsifiers—tree mutation, unwritable root, credential removal, and transition marker—run synthetically, hermetically, or against a disposable locus. Do not poison srv1 to demonstrate them.
Existing member witnesses are supporting evidence. The new load-bearing controls each replace one member in an otherwise Complete fact population and prove the deployment join becomes Incomplete with that member named.
Authorized RLM-2b sequence (manager/operator only; corrected per review 5062738052 B4)
R is the exact admitted MAIN revision the operator selects AFTER this PR merges — possibly a later descendant of the merge commit, whatever main revision the operator rules the transaction installs and proves. Every dispatch carries
expected_revision=$R; every run of the transaction refuses unless it checked out exactly R. Run-id correlation uses a transaction NONCE: the operator mints one, passes it as thetransaction_nonceinput, the workflow echoes it intorun-name, and each run id is then selected by matching the nonce in the run'sdisplayTitle— never bygh run list --limit 1. The downloaded receipt's ownrun_idmust equal the selected run id, closing the loop.Provenance split, stated precisely (review 5062738052 B2): inside the receipt run,
RunProvenanceFactcarries the three PREDECESSOR runs' API-read conclusions/head_sha/path plus the CURRENT run's binding admitted against the canonical repository, the generated workflow path, and R — the current run's own terminal conclusion is structurally unobservable from inside itself, and is verified by the manager in step 5 after completion. The receipt does NOT claim four conclusions.Frozen RLM-2 join
The final join expands to:
RLM-3 remains closed until that exact tuple is accepted.