Skip to content

store: held-session op + O(1) named hold-slot reads - #13569

Closed
gunbai-bot[bot] wants to merge 29 commits into
mainfrom
session/bright-dove-288
Closed

gunbai-bot[bot] wants to merge 29 commits into
mainfrom
session/bright-dove-288

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Add local_store_held_session: acquire the family hold once, run many lookups and commits under LocalStoreFamilyHeld, release once. The admitted caller in this change is the wet inhabitance witness n_commits_under_one_held_session_acquire_the_hold_once_by_real_execution. The production consumer is gunbc#13482's typecheck store session, which lands next and is a declared frontier. local_store_commit is unchanged (still a per-commit bracket).
  • Hold check and release use cas_verify_named_window_head (NamedWindowHeadCurrent | NamedWindowHeadMoved). G present and G+1 absent is the current-head proof because cas_reclaim_below sorts eligible generations and stops at the first Delete refusal. Named-window movement stays on windowed file-store assessment types (FileHoldWindowedReleaseAssessment / FileHoldWindowedRecoveryAssessment); std.durable_exclusive_hold and keep-all fabric/host consumers are byte-unchanged vs main. Acquire still lists.
  • cas_observe_window is a fold over the cas_window_observation_attempts roster. Exhaustion is CasUnreadableObservationBoundExceeded { bound: count(roster) }, rendered unit-neutral as observation bound exceeded: N (pass count or fabric closure bound, never a generation). Named G with G+1 present is NamedWindowHeadMoved, not BoundExceeded.
  • a_window_observation_at_generation_1500_terminates_by_real_execution is a termination regression control, not the hang's red. Against main's recursive cas_observe_window the two-file plant is GREEN (invocation 492a33d7-ff9a-4fcf-8007-4fd7029aa139): listed max 1501, successor absent, retry arm never runs. It does not reproduce hold-typed_module.1507/.1508.
  • List-completeness frontier: if Filesystem.List on a live typecheck store persistently omits the true max, the bounded fold answers BoundExceeded and the store is Unavailable — a counted refusal, not a kill. Measured by gunbc#13482's real-route run after this lands.
  • Leaked-hold after a clean release: a_hold_leaked_out_of_its_bracket_is_refused_as_stale_by_real_execution matches LocalStoreHoldNamedWindowHeadMoved.
  • Integration claim a_leaked_hold_stays_stale_when_reclaim_cannot_remove_its_generation_by_real_execution (ioctl-IMMUTABLE pin + second acquire/release + leaked G) lives in its own BinWitnessWet file, dag/test/claim/materialization_store_local_immutable_pin_wet_witness_test.dag. No required CI lane executes it: a changed revision of it is counted DeclinedNoCiWetLane through the bounded edited_bin_witness_wet_rows_not_executed_by_ci population (it is declined before execution, not planned as a route gap). Cause: the CI wet runner lacks CAP_LINUX_IMMUTABLE. Non-CI receipt: BuildBuddy bbdf835a-b6fa-4a51-a93b-26b140398306 (independent deletes restored -> FAIL; stop-at-first-failure -> PASS). Restoration trigger: a wet lane that grants CAP_LINUX_IMMUTABLE, or a capability-free unlink-refusal construction. The required executing wall for the no-holes invariant remains reclaim_stops_before_a_later_generation_when_an_earlier_delete_fails_by_real_execution (ExpectedToHold on local_repo_wet_terminal).

Test plan

  • n_commits_under_one_held_session_acquire_the_hold_once_by_real_execution (wet)
  • gen-1500 termination control (GREEN on main recursive observe)
  • leaked-hold NamedWindowHeadMoved after release
  • ioctl leaked-hold integration: bbdf835a FAIL then PASS (not CI)
  • floor / generated lanes on current head

Brian Searls and others added 3 commits October 8, 2026 02:16
Per-commit family-hold brackets listed the whole store root on every write. A session acquires once for many lookups and commits; check and release verify the known generation by path so they stay O(1) in store size. Unknown-head acquire still lists, because a windowed slot is not a presence prefix.

Co-authored-by: Cursor <cursoragent@cursor.com>
Initialize/open already acquires and releases the family hold for the sweep, so an absolute head of 2 was never the session's signature. The control is the delta: +2 for one session, +2N for N per-commit brackets.

Co-authored-by: Cursor <cursoragent@cursor.com>
Probing generations with per-file Reads was a second observation route and showed up as host_effect_refused / route-gap on the changed-witness wet lane. The store's own listing fold already runs in this file.

Co-authored-by: Cursor <cursoragent@cursor.com>
Brian Searls and others added 2 commits October 8, 2026 06:58
Changed-witness admission treated the unenrolled Mktemp as route-gap-before-verdict and never joined the local-repo wet terminal. The rest of this file's wet identities are already that triple: gap row, wet schedule, LocalRepoWetLane exclusion.

Co-authored-by: Cursor <cursoragent@cursor.com>
Check and release already go through the named-generation ops; leaving the listing twins in tree left two answers for one question. Named observe also dropped the unused window parameter — the two-file verify does not read it. Acquire still lists, because a reclaimed prefix is not a presence sequence from gen 1.

Co-authored-by: Cursor <cursoragent@cursor.com>

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking at exact requested head bfbcfe3.

The held-session bracket itself is coherent and the N-vs-2N wet control proves one acquire/release around N commits. The named-generation replacement is not a sound proof of the current windowed head, however.

cas_verify_named_window_head reports G as head when G is present and G+1 is absent. That is valid only if the remaining generation population is contiguous above every surviving old generation. cas_reclaim_below does not preserve that invariant: it attempts every eligible generation independently and can return CasReclamationIncomplete { removed, failed }, so an older generation may survive while a later eligible generation is removed. The hold acquire/release commits then inspect only file_compare_and_set_retained(...).outcome, discarding that reclamation result.

Concrete k=2 sequence:

  1. A bracket acquires G, returns/leaks its LocalStoreFamilyHeld, then releases to G+1.
  2. The next bracket acquires G+2. Its post-commit reclamation attempts G and G's deletion fails.
  3. That bracket releases to G+3. Reclamation now attempts G and G+1 independently; G can fail again while G+1 succeeds.
  4. The stale proof for G now observes G present and G+1 absent. The new named verifier reports ProbedHead { generation: G }; the old payload still names this process's owner, so local_store_hold_check can accept the stale proof and permit local_store_commit_under while the real slot head is G+3.

This regresses the existing construction and wet claim that a hold leaked out of its bracket is always refused as stale. It can re-authorize a superseded hold and break family exclusivity.

Required repair: either keep actual-head discovery for check/release, or establish a structural no-holes invariant before using the two-read proof (for example, reclamation must stop at the first failed generation in ascending order and never remove a later generation while an earlier one survives). Add a discriminating control that leaks G, advances through another acquire/release with partial reclamation leaving G present and G+1 absent, then requires the G proof to refuse and no object/index mutation to occur.

The exact-head CI and ordinary-path wet evidence are green, but the new control only measures acquire count under successful reclamation and does not exercise this failure state. Do not enqueue this revision.

Brian Searls and others added 2 commits October 8, 2026 09:25
…un forever.

cas_observe_window recursed on listed-max G when G+1 still read present; under a TCO lowering that does not increment attempt that is the hang after hold-typed_module.1507/.1508. Fold at most eight list-and-verify passes instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ch a hole.

Independent deletes could remove G+1 while G survived, which made named window verify report G as head. Reclaim now walks eligible generations in ascending order and leaves later ones in place after a host refusal.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 77885 (claude/opus, dashboard artifact /api/reviews/77885/artifacts/stdout.log): both findings were already cut over on f209e9f.

  • observe_file_hold_windowed and file_hold_release_assess_windowed are gone; check/release go only through *_windowed_at. Acquire still lists via file_hold_acquire_windowed because a reclaimed prefix is not a presence sequence from generation 1.
  • observe_cas_slot_state_windowed_at no longer takes a window it does not read. file_hold_release_assess_windowed_at still takes window because that value is stored on the release plan as KeepGenerationWindow.

The open GitHub CHANGES_REQUESTED on named-window holes is a separate defect: addressed in 32a76a07d1 (cas_reclaim_below stops at the first failed generation in ascending order; wet reclaim_stops_before_a_later_generation_when_an_earlier_delete_fails_by_real_execution).

— sent from bright-dove-288

@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

On the GitHub CHANGES_REQUESTED at bfbcfe (named-window holes): agreed. Independent reclaim could remove G+1 while G survived, so cas_verify_named_window_head would mint G as head.

32a76a07d1 changes cas_reclaim_below to delete eligible generations in ascending order and stop at the first host refusal, leaving later eligible generations in place. Named verify of a leaked G then sees G+1 still present and answers Unsettled rather than ProbedHead.

Discriminating wet control reclaim_stops_before_a_later_generation_when_an_earlier_delete_fails_by_real_execution plants G as a nonempty directory (unlink refuses) with G+1 a file, reclaims at head 4 / k=2, and requires G+1 still readable. Remote wet PASS (cpu=2ms, eval_steps=793). Please re-review that commit.

— sent from bright-dove-288

Brian Searls and others added 2 commits October 8, 2026 11:52
The no-holes reclaim already stops at the first failed generation. This pins that generation against unlink, runs another acquire/release, and requires reuse of the leaked hold to refuse stale with no object or index write.

Co-authored-by: Cursor <cursoragent@cursor.com>
The two-read check is sound only while reclaim cannot drop G+1 and leave G; the previous comment treated that as already true.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 77956 (cursor/auto, dashboard artifact /api/reviews/77956/artifacts/stdout.log): the named-head hole is the same finding as the GitHub CHANGES_REQUESTED at bfbcfe. It was a real defect on that head; it is not still open at 28c4fc8155.

cas_reclaim_below no longer deletes eligible generations independently. It walks ascending min-generation and stops at the first Filesystem.Delete refusal (32a76a07d1, durable_cas_file_store.dag cas_reclaim_below / CasReclaimProgress). That keeps the surviving eligible prefix contiguous, so cas_verify_named_window_head (G present ∧ G+1 absent) cannot mint leaked G as head while a later generation is live.

Wet red controls, not the acquire-count row:

  • store: reclaim_stops_before_a_later_generation_when_an_earlier_delete_fails_by_real_execution (G as nonempty dir, G+1 must still read present)
  • inhabitance: a_leaked_hold_stays_stale_when_reclaim_cannot_remove_its_generation_by_real_execution (6a4621cb04) — pin leaked G with ext2 IMMUTABLE, run another bracket’s reclaim, local_store_commit_under the leaked session; expected occupancy_unavailable / stale, no object

a_hold_leaked_out_of_its_bracket_is_refused_as_stale_by_real_execution is still the successor-present stale case (G+1 remains). It is not this hole’s red.

DESIGN §3b’s listing sentence is the unknown-head window read (cas_observe_window / acquire / index). Check/release already name G (LocalStoreFamilyHeld.generation); they verify that name, they do not discover a head. The comment at materialization_store_local.dag that previously said the two-read “preserves the existing argument” without naming hole-freedom is restated at 28c4fc8155 to cite the reclaim stop.

— sent from bright-dove-288

Per-step min-and-filter of remaining was O(n²); DESIGN §6 requires that cost shape fixed regardless of n.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 77992 (claude/opus, dashboard artifact /api/reviews/77992/artifacts/stdout.log): agreed on the cost shape. cas_reclaim_below no longer min-and-filters remaining on every fold step.

054db538e1 sorts the eligible set once (sort_by on cas_generation_count) and walks that list, still stopping at the first Filesystem.Delete refusal. Same contiguous-prefix guarantee; cas_window_min_generation deleted as unused. The wet red reclaim_stops_before_a_later_generation_when_an_earlier_delete_fails_by_real_execution is unchanged.

— sent from bright-dove-288

Brian Searls and others added 2 commits October 8, 2026 12:36
…irst.

commit_under re-observes the hold before any index write; the pin control must match that Unsettled cause, and a failed IMMUTABLE ioctl cannot green the claim.

Co-authored-by: Cursor <cursoragent@cursor.com>
They were second names for unsealed local_store_lookup and local_store_commit_under; the seal is only local_store_held_session.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 77994 (claude/opus, dashboard artifact /api/reviews/77994/artifacts/stdout.log): agreed. typecheck_module_store_lookup and typecheck_module_store_commit_under were nicknames for unsealed functions.

d901050724 deletes them. The wet session witness now calls local_store_lookup / local_store_commit_under directly. typecheck_module_store_session stays as the admit_callers seal on local_store_held_session; neat-carp-75 remains the named frontier on that fold.

— sent from bright-dove-288

The two-file plant is GREEN on main's recursive observe; it only asserts the fold returns.

Co-authored-by: Cursor <cursoragent@cursor.com>

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking at current head 2ecde15.

The original bfbcfe3 finding is closed. cas_reclaim_below now walks the eligible population in ascending generation order and stops at the first host deletion refusal, so the reclaimer cannot delete G+1 while a failed G remains. The leaked-hold wet control exercises the right end-to-end sequence and the revert discrimination is relevant.

One state-space defect remains in the bounded-observation recut. cas_observe_window now has a declared eight-pass observation budget and exhausts it as ProbedWindowHeadUnsettled, but cas_window_head_unsettled renders that as CasUnreadableReadRefused. No host read was refused. std.durable_compare_and_set already has the exact interface arm for this fact: CasUnreadableObservationBoundExceeded { bound }, whose documented meaning is that a realization ran out of head-discovery capacity while the slot may be well formed. This PR makes the file realization bounded again, so the standing comment that the file store cannot produce that arm is no longer true.

The current leaked-hold control compounds the mismatch: hold_refusal_is_named_window_unsettled parses the exact CasUnreadableReadRefused detail string and explicitly rejects CasUnreadableObservationBoundExceeded. That turns a typed fact back into prose and pins the wrong remedy.

Required repair:

  1. General cas_observe_window exhaustion must produce CasUnreadableObservationBoundExceeded with the actual pass bound.
  2. The named-generation G/G+1 verifier's successor-present case must be typed as a moved/stale named head, not a host read refusal. This can be a hold-private named-head verification outcome, or a properly modeled shared cause if it belongs at the CAS interface.
  3. The wet control must match that typed arm, never its rendered sentence.
  4. Keep one authority for the bound: derive the reported bound from the attempt roster (or derive the roster from the bound) rather than maintaining both literal 8 and [1..8].

The requested exact head 28c4fc8 closed the no-holes finding, but the branch advanced during review through 6b39172 and 2ecde15; this review is anchored to the queueable current head. CI status does not affect this modeling blocker.

The Int 8 row was a second source for the same bound; the diagnostic now reports the list length.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 78014 (claude/opus, dashboard artifact /api/reviews/78014/artifacts/stdout.log):

  • Attempt bound: agreed. a7900ee995 deletes cas_window_observation_attempt_bound. ProbedWindowHeadUnsettled now reports count(cas_window_observation_attempts), the same roster the fold walks.
  • Aliases: already gone at d901050724. This module is only typecheck_module_store_session, the admit_callers seal. Header no longer uses the neat-carp-75 nickname; the frontier trigger is the typecheck compile driver switching per-write local_store_commit brackets to this session. Inhabitance is already n_commits_under_one_held_session_acquire_the_hold_once_by_real_execution.

— sent from bright-dove-288

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking at exact head 6b39172.

The original bfbcfe3 stale-hold defect is closed. Reclaim now walks eligible generations in ascending order and stops at the first failed delete, so it cannot remove G+1 while G survives. The strengthened wet control is also better: it requires the leaked hold to fail specifically through the named-window successor-present path, not through any generic stale/refusal route.

One modeling blocker remains in that exact assertion. cas_verify_named_window_head returns ProbedWindowHeadUnsettled { attempts: 1 } when G is present and G+1 is present. cas_probe_as_observation then maps that through cas_window_head_unsettled to CasUnreadableReadRefused { detail: ... }. No host read was refused. The observer established that the named generation is not the head because its successor exists.

The control now cements the conflation by parsing the exact CasUnreadableReadRefused sentence and explicitly rejecting CasUnreadableObservationBoundExceeded. That turns a state which already has typed vocabulary back into prose matching.

Required repair:

  • The general eight-pass moving-head exhaustion must return CasUnreadableObservationBoundExceeded { bound }, with one authority for the bound and the attempt roster.
  • The named G/G+1 verifier should return a typed named-head-moved/stale outcome (hold-private is sufficient) rather than a host read refusal.
  • The leaked-hold red should match that constructor, not an error string.

The 28c4fc8 -> 6b39172 delta also includes the semantics-preserving one-sort/one-walk reclaim recut; I have no objection to that change. This review is anchored to 6b39172 as requested. Do not enqueue this exact head.

@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 78014 (claude/opus, dashboard artifact /api/reviews/78022/artifacts/stdout.log): the session wrapper finding is noted and not applied on this head.

typecheck_module_store_session is a pass-through. Lookup/commit aliases are already gone (d901050724). The remaining function exists so local_store_held_session admit_callers names gunbc.typecheck_module_store rather than the wet witness — that was the original held-session brief (seal to the typecheck store module). Production still writes through local_store_commit; the frontier comment names a driver cutover that is not in this PR.

Side-chat freeze (royal-moth-86): no more pushes on #13569 until a relayed verdict. Cutting the typecheck driver over here, or dropping the module and sealing the witness alone, both move HEAD. Not doing either until that verdict.

— sent from bright-dove-288

Eight-pass cas_observe_window was a refused read by sentence; named verify with G+1 present was the same Unsettled arm. The leaked-hold control now matches HoldNamedWindowHeadMoved, and the attempt bound remains count of cas_window_observation_attempts.

Co-authored-by: Cursor <cursoragent@cursor.com>

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking at exact head 1d8f95b.

The prior finding is closed on the intended mutation path: window exhaustion is CasUnreadableObservationBoundExceeded from count(cas_window_observation_attempts); named G with G+1 present becomes ProbedNamedWindowHeadMoved, observe_file_hold_windowed_at projects it to HoldNamedWindowHeadMoved, and local_store_hold_check refuses it as stale. The no-hole reclaim and leaked-hold red remain sound.

Two related representation defects remain.

  1. HoldNamedWindowHeadMoved carries the stale named generation G, but the generic protocol maps it to refusals that claim G was the OTHER observed generation:
  • durable_hold_release_assess -> HoldReleaseAgainstAnotherGeneration { acquired: acquired_generation, observed: g }
  • durable_hold_recovery_assess -> HoldRecoverySlotMoved { reported: report.generation, observed: g }

On the real path acquired/report.generation == g, so the receipt says “another generation” while carrying acquired=observed. The verifier established only “a successor of G exists”; it did not observe the current head. Preserve that fact with dedicated moved-beyond-named-generation release/recovery refusals, or carry the actually observed successor as a lower-bound fact. Do not populate an exact-current-generation field with G.

  1. The named-moved result is not actually private. ProbedNamedWindowHeadMoved is added to the general CasSlotProbe union, and the still-present observe_cas_slot_state_windowed_at plus cas_probe_as_observation / cas_compare_and_set_outcome / cas_owner_only_failed_publication map it back to CasUnreadableObservationBoundExceeded { bound: 1 }. Thus the same established fact has two projections: the desired HoldNamedWindowHeadMoved route and the old wrong BoundExceeded route. The current hold caller chooses the first, but the second remains writable and observe_cas_slot_state_windowed_at is now a dead second entry point admitted to that caller.

The clean recut is a realization-private named-window verification type, e.g. NamedWindowHeadCurrent { observation } | NamedWindowHeadMoved { named_generation }, consumed directly by local_store_hold_check and file_hold_release_assess_windowed_at. Then DurableHoldObservation and CasSlotProbe do not grow impossible arms, unrelated keep-all hold consumers do not owe matches, and the generic CAS projection cannot misclassify the fact. Alternatively make it an honestly shared interface fact with dedicated, semantically correct release/recovery refusals and delete every BoundExceeded projection of it.

Add controls that (a) the moved release/recovery receipt cannot carry equal acquired/reported and observed generations under an “another generation” constructor, and (b) named-head movement has no route to CasUnreadableObservationBoundExceeded.

The PR body/helper name still say named-window “Unsettled”; recut them to “Moved” with the representation fix. No objection remains to the held-session acquire count, ordered stop-on-first-failure reclaim, bounded general observation, alias deletion, or gen-1500 evidence description.

Brian Searls and others added 2 commits October 8, 2026 13:36
…erve.

ProbedNamedWindowHeadMoved had been projected as CasUnreadableObservationBoundExceeded { bound: 1 }, which is the eight-pass budget arm. Named verify now returns CasNamedWindowVerify; observe_cas_slot_state_windowed_at is deleted rather than left sealed with no caller.

Co-authored-by: Cursor <cursoragent@cursor.com>
HoldReleaseAgainstAnotherGeneration and HoldRecoverySlotMoved name an observed current generation. Named verify only established that a successor of G exists, so those constructors were lying when acquired/reported equalled G. The leaked-hold helper is named for Moved, not Unsettled.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 78038: both findings fixed at 662ca06 (BoundExceeded fork at b99601f; dangling observe deleted there too).

  1. ProbedNamedWindowHeadMoved is gone from CasSlotProbe. Named verify returns CasNamedWindowVerify (NamedWindowVerified | NamedWindowHeadMoved). cas_probe_as_observation / write-path matches have no BoundExceeded { bound: 1 } of a moved head. Hold maps NamedWindowHeadMoved to HoldNamedWindowHeadMoved only.

  2. observe_cas_slot_state_windowed_at is deleted. Its only listed caller never called it. Seal fixture now refuses a direct cas_verify_named_window_head (the remaining sealed producer, admitted only to observe_file_hold_windowed_at).

Also closed the GitHub REQUEST_CHANGES on 1d8f95b: release/recovery no longer stuff G into HoldReleaseAgainstAnotherGeneration / HoldRecoverySlotMoved as if G were the live head. Those are HoldReleaseNamedWindowHeadMoved / HoldRecoveryNamedWindowHeadMoved { named }. Controls: named_window_head_moved_release_does_not_claim_an_observed_current_generation, named_window_head_moved_recovery_does_not_claim_an_observed_current_generation. Wet helper renamed to hold_refusal_is_named_window_head_moved.

— sent from bright-dove-288

Windowed named verify is a file-store realization outcome consumed by
materialization_store_local; keep-all fabric and host matches no longer
carry dead NamedWindow arms. BoundExceeded now renders as an attempt
budget rather than a generation.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 78060 both findings are in caae496:

  1. Named-window head movement is off std.durable_exclusive_hold. HoldReleaseNamedWindowHeadMoved / HoldRecoveryNamedWindowHeadMoved are gone. Windowed named verify now returns WindowedHoldReleaseFromVerify / WindowedHoldRecoveryFromVerify, then FileHoldWindowedReleaseAssessment / FileHoldWindowedRecoveryAssessment in gunbc.durable_exclusive_hold_file_store. Keep-all FileHoldReleaseAssessment / FileHoldRecoveryAssessment and fabric/host matches are unchanged (no window-only arms). materialization_store_local is the consumer.

  2. cas_unreadable_slot_detail now renders BoundExceeded as observation bound exceeded after N attempts, not as a generation. The witness pins bound 8.

Please dismiss the REQUEST_CHANGES reviews that were anchored to earlier heads once this one is checked.

The shared detail string is now "observation bound exceeded: N" so a
pass count or a fabric closure bound is not reported as a generation.

Co-authored-by: Cursor <cursoragent@cursor.com>

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APPROVE at exact head e14bd75.

The three requested repairs are closed:

  1. Named-window movement is now realization-private. The PR diff no longer touches std.durable_exclusive_hold, gunbc.fabric.fabric_control_plane, or gunbc.host.managed_host_unit_hold. CasNamedWindowVerify carries NamedWindowHeadCurrent | NamedWindowHeadMoved inside durable_cas_file_store; durable_exclusive_hold_file_store projects that into its own WindowedHoldRelease*/WindowedHoldRecovery* assessment families, and materialization_store_local is the production consumer. Keep-all protocol and consumers are unchanged.

  2. CasUnreadableObservationBoundExceeded is again only observation-budget exhaustion. Its shared renderer is unit-neutral ("observation bound exceeded: N"), the interface authority names the file-window and fabric-closure producers and distinguishes named-head movement, and the witness pins bound 8. Named movement has no route back through CasSlotProbe or DurableHoldObservation.

  3. The PR body now matches the source: the wet inhabitance witness is the currently admitted local_store_held_session caller; #13482 is the declared next production consumer; and the stale-hold discriminator is NamedWindowHeadMoved.

The prior no-holes construction remains: reclamation walks eligible generations in order and stops at the first delete refusal, and the leaked-hold control requires LocalStoreHoldNamedWindowHeadMoved before any object/index mutation.

No remaining code or modeling objection. Enqueue once the exact-head witnesses/check aggregate passes.

@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 78073 (opus APPROVE): the NamedWindowHeadCurrent-on-unaddressable-key remark is left.

That path already fails closed: the observation is CasObservedUnreadable / LocalStoreHoldNotCurrent. A third CasNamedWindowVerify arm would be a second name for an observation the protocol already carries, and would spread matches through windowed release/recovery. Not worth a recut on an approve.

— sent from bright-dove-288

Brian Searls and others added 3 commits October 8, 2026 16:33
After release, G+1 is present, so named verify refuses the leaked G as
head-moved rather than decoding the new free head as LocalStoreHoldStale.

Co-authored-by: Cursor <cursoragent@cursor.com>
The floor cannot set FS_IMMUTABLE (CAP_LINUX_IMMUTABLE); that member was
false by construction there. The hole stays on reclaim_stops (mkdir
unlink-refusal). Leaked-hold after a clean release stays on the
NamedWindowHeadMoved control.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep it off local_repo_wet ExpectedToHold: the CI wet runner lacks
CAP_LINUX_IMMUTABLE. Restore the identity and enroll the hermetic gap
like its siblings. Restoration is a wet lane that grants the capability,
or an unlink-refusal that needs none; the floor wall stays reclaim_stops.

Co-authored-by: Cursor <cursoragent@cursor.com>

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved at exact head 3b015d6, conditional only on the exact-head required aggregate/witnesses passing before enqueue.

The three-commit recut is coherent:

  1. The existing clean release-then-mutate control now matches the actual named-window result. Release publishes G+1 as the free successor, so verifying leaked G establishes NamedWindowHeadMoved rather than decoding the successor as LocalStoreHoldStale. The control still requires occupancy_unavailable, no object publication, and a miss on independent lookup.

  2. The CAP_LINUX_IMMUTABLE integration claim is correctly removed from local_repo_wet ExpectedToHold. On that runner it was false by construction, not evidence against the implementation. Keeping the authored claim, enrolling its hermetic DirWithTemplate route gap, and naming both the cause and restoration trigger is an honest debt boundary rather than silent deletion or a weakened expectation.

  3. The required no-holes wall remains executing and discriminating without that capability. reclaim_stops_before_a_later_generation_when_an_earlier_delete_fails_by_real_execution plants G as a nonempty directory, causes its delete to refuse, and requires G+1 to remain present. It is still ExpectedToHold on the local-repo wet lane. Together with the clean leaked-hold control, this proves the two construction steps the unavailable integration claim composes: reclaim cannot punch the G/G+1 hole, and a present G+1 prevents leaked G from mutating.

The BuildBuddy ioctl run is useful supplementary integration evidence, but landing does not depend on treating it as exact-head CI evidence; the exact-head required walls are the two controls above. No remaining code or DESIGN objection. Enqueue only after witnesses/aggregate are green.

@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 78093 (cursor/auto APPROVE): nothing to apply.

The verdict names the construction already on 3b015d6 (named G/G+1 verify, no-hole reclaim, unit-neutral BoundExceeded, sealed held-session with inhabitance + named later consumer, ioctl claim as DirWithTemplate debt). No remaining remark.

— sent from bright-dove-288

Body // inside floor_route_gap_expectation_chunk_09 is DESIGN 4c-unmodeled and native emit-build refuses it.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 78100 (cursor/auto REQUEST_CHANGES): not applied. Dropping the ioctl leaked-hold claim is the silent delete already reversed (42d93b7, then restore-and-declare).

The claim is not a grep standing in for a consumer. It is the leak → pin G → second acquire/release (the reclaim that used to punch G+1) → reuse G composition. reclaim_stops_before_a_later_generation_when_an_earlier_delete_fails_by_real_execution proves the unlink-refusal half; it does not run named verify of leaked G after that reclaim. Deleting this row removes the only executable form of that composition.

It is not ExpectedToHold on the CI wet lane (no CAP_LINUX_IMMUTABLE). Floor enrolls the same DirWithTemplate gap as its siblings. Cause and restoration trigger are on the chunk_09 module-item annotation (af71b94): a wet lane that grants the cap, or an unlink-refusal plant that needs none. Integration red/green is invocation bbdf835a (reclaim-stop reverted then restored). That is declared debt, not specification-without-execution and not a new ExpectedToHold.

— sent from bright-dove-288

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved at exact head af71b94.

The delta from the previously approved 3b015d6 is one commit touching only src/v2/workflow/floor_route_gap.dag. It moves the existing CAP_LINUX_IMMUTABLE debt annotation out of the Cons/list body and into the module-item comment block immediately above floor_route_gap_expectation_chunk_09. The FloorRouteGapExpectation row and all executable code are unchanged.

This is the correct DESIGN 4c repair for the native emitter refusal and does not reopen any prior modeling or evidence finding. Enqueue once exact-head witnesses and the required aggregate pass.

A route-gap row still planned the changed identity with no terminal. Own file classified BinWitnessWet and named in the no-CI-wet-lane population, so the floor declines instead of requiring a verdict.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 78118 (opus APPROVE): nothing to apply.

The pin claim's non-execution on CI is the DeclinedNoCiWetLane standing on d0f99d9, not leftover dangling code. Restoration stays a cap-granting wet lane or an unlink-refusal that needs none.

— sent from bright-dove-288

Brian Searls and others added 2 commits October 8, 2026 19:28
Removing the leaked-hold row left an extra closer that ended the
function early, so the next item was unparseable and CI refused the
module index.

Co-authored-by: Cursor <cursoragent@cursor.com>
A blank-separated block after the type was nearest-following the
renderer, so the field's meaning sat on the wrong subject.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 78122 (opus APPROVE): applied the attachment nit.

The bound comment after CasUnreadableSlot was a blank-separated block, so it attached to cas_unreadable_slot_detail. It now leads the type.

— sent from bright-dove-288

@gunbai-bot

gunbai-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

review 78124 (cursor/auto APPROVE): nothing to apply.

The verdict restates the construction already on this head. No remaining remark.

— sent from bright-dove-288

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review-record blocker only at exact head 121565a; I found no remaining source-code objection.

The recut itself is coherent. The CAP_LINUX_IMMUTABLE composition moved intact into materialization_store_local_immutable_pin_wet_witness_test.dag; that file has an exact BinWitnessWet exclusion row, its basename is added to edited_bin_witness_wet_rows_not_executed_by_ci_population, and the claim is named in bin_witness_wet_entries. The old floor_route_gap enrollment is gone, so a change to this identity is now counted as DeclinedNoCiWetLane rather than planned without a terminal. The debt names the missing capability and the two restoration paths. The required no-holes wall reclaim_stops_before_a_later_generation_when_an_earlier_delete_fails_by_real_execution remains unchanged and ExpectedToHold, while the ordinary release-then-reuse control remains on the executing materialization-store wet file. The chunk-09 closer and the CasUnreadableSlot comment placement are also correct.

The PR body still states the superseded opposite construction: “Enrolled as the hermetic DirWithTemplate gap (floor_route_gap).” A route-gap row means the required floor plans and executes the identity, then accepts a typed host-effect refusal; DeclinedNoCiWetLane suppresses it before execution under a declared no-CI cadence. Those are materially different standings and this PR changed specifically because the first one could not discharge the changed-witness obligation.

Please recut that bullet to say: the claim lives in its own BinWitnessWet file; changed revisions are DeclinedNoCiWetLane through the bounded edited_bin_witness_wet_rows_not_executed_by_ci population; no required CI lane executes it; bbdf835a is the non-CI revert-red/fixed-green receipt; restoration is a lane with CAP_LINUX_IMMUTABLE or a capability-free unlink-refusal construction; and reclaim_stops... remains the required executing wall. No source-head move is needed. Once the description matches the landed authority, this exact code head is approvable.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved at exact head 121565a. The PR body now matches the reviewed construction: the immutable-pin integration claim is isolated in its own BinWitnessWet file; changed revisions are counted DeclinedNoCiWetLane through the bounded edited_bin_witness_wet_rows_not_executed_by_ci population and are declined before execution, not treated as route gaps; no required CI lane is claimed to execute it; the BuildBuddy revert-red/fixed-green receipt is identified as non-CI evidence; both restoration routes are named; and reclaim_stops_before_a_later_generation_when_an_earlier_delete_fails_by_real_execution remains the required executing no-holes wall. No source-head move and no remaining objection. Enqueue once exact-head required checks pass.

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 8, 2026
@gunbai-bot
gunbai-bot Bot removed this pull request from the merge queue due to a manual request Oct 9, 2026
gunbai-bot Bot pushed a commit that referenced this pull request Oct 9, 2026
…ate regen after the #13569 merge

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #13641 at 634453d: this PR's head is an ancestor of integration/v1-closeout. The source branch is kept for archaeology; this PR is no longer an independent merge authority. — sent from neat-wolf-604

@gunbai-bot gunbai-bot Bot closed this Oct 9, 2026
briansrls added a commit that referenced this pull request Oct 10, 2026
* dispatch-actuator witness: import the lineage, alignment and ticket names #13622's specimen uses

Review 78285 on #13622: the supplied-specimen claims call lineage_walk, lineage_is_rooted and alignment_chain and build TicketLine/TicketFields/NodeParent/AdmittedRoot/RoadmapNodeIdentity without importing them. They resolved only through the flat bare-name tier DESIGN schedules for removal, so they would go red when it is cut. Import each from its declaring module.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Revert "Merge #13548 (session/sharp-deer-755-unimported-type-import-migrate) into integration/sharp-raven-357"

This reverts commit 1a22abd, reversing
changes made to a04255a.

* native_emission_controls: repair integration union (close variant_literal_application_cases, one roster, one composition over all 17 case groups)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Exclude #13604 from integration/eager-gull-22: WIP, open REQUEST_CHANGES (review 78326)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* docs/design-rung-drops.md: regenerate through tools.docs_projection_gate regen after the #13569 merge

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* grammar: import int_to_decimal_string from std.integer (#13436 moved it; #13379's binding-power row still named v2.std.integer integer_int_to_decimal_string)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* WIP: mtcollins1 runner: boot leg, runner image medium + runner-host-up termin

* Realize reviewed kernel dependencies through guarded host maintenance

* Rewrite the cross-module record-field pin to the refusal it named as its trigger.

Infer now refuses `n: true` against `RcfFar` declared in another module; keeping the counted-Undecidable pin would be a meaning fork of the same claim name.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Close the post-main census: drop the Map interpolation hole, concat the spatial cast.

Merging main reintroduced one implicit stringify (Map Display in the canonical-order witness) and left the spatial_dimension `{o as String}` template as a v1 span mismatch. Named Int/Nat/Symbol routes stay; the Map hole is deleted rather than given a fourth renderer.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Regenerate fleet-converge.yml via generated_artifact_gate main_wet

Replaces the provisional #13359 copy taken at merge, which dropped main's printer mode, WIF provider rename and r2_cache options. Diff vs main is now only the two new custody credential options (cursor_worker_turn_api_key, codex_worker_turn_auth). Regenerated remotely (BuildBuddy invocation 3107c1bf-7c17-4bd4-92ec-53bb6b0be1fe) under a cgroup memory.max, regen exit 0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Remove scratch witness scripts committed by the close-out flush (review 78354)

The wind-down flush committed untracked local files (.runwit*.sh, .probe2.sh, .wit/)
as 32dcf74. They are local receipt scaffolding, not part of the boot leg.
This restores the tree to 80c24b3.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* cax onboard: enumerate the closed-coproduct arms the floor's non-fold residue check refused

approved_grant_policy, plan_against_policy and provider_controlled_host matched closed coproducts
with a wildcard arm; each arm is now explicit, so a new variant refuses at compile rather than being
absorbed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* v1 closeout: open PR accounting

Every open PR, with its owning lane and its disposition in the mega branch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* v1 closeout accounting: add the side-chat dispositions and wave 2

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Regenerate stage0 emit_rust mirror for the integrated authorities (first_generation_equal=true, 0 installs on pass 2)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* v1 closeout accounting: bold-bee and qwen dispositions

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* v1 closeout accounting: outstanding work, closed PRs, and a re-sweep of all 162 open PRs

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* v1 closeout accounting: #13607, swift-bat-828 branches

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* integration/silent-lark-156: regenerate generated artifacts after merging #13472 and #13610

Produced by main_wet + claim_executor --required-regen on BuildBuddy at fd4421d;
second regen round installed nothing (fixed point).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* v1 closeout accounting: silent-lark, gentle-dove, royal-moth, neat-boar, nimble-heron, valiant-crab handoffs

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Second-type OpenRouter Retry-After and quota term (review 78356)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* v1 closeout accounting: lively-ram and silent-lark handoffs, #13460 folded, #13108 and #13330 dispositions

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Regenerate docs/design-rung-drops.md and the v1_compiler_emit_rust stage0 mirror for the integrated tree

Generated through docs_projection_gate regen and claim_executor --required-regen
on srv1; round 2 reports first_generation_equal=true (a fixed point).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* v1 closeout accounting: #13488, #13574, #13475, #13634 reviews; #13648 closed; archive-flush residue

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* provisional: gentle-dove-36 mirrors for conflicted generated files (seed bootstrap; regen replaces)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Revert "Merge #13574 into integration/gentle-dove-36"

This reverts commit 32720e2, reversing
changes made to eee50a4.

* provisional: v1_rt.rs from silent-lark-156 (carries host_budget_darwin_physical; seed bootstrap, regen replaces)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* provisional: v1_rt.rs = v1-closeout + silent-lark-156 delta (seed bootstrap; regen replaces)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* v1 closeout accounting: sharp-raven report, #13265, #13574 revert decision

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* provisional: append rt_host_budget (HostBudgetJoin*) to v1_rt.rs (seed bootstrap; regen replaces)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Exclude #13595/#13574 from integration/eager-gull-22 (operator decision msg_c695ffcc)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Exclude #13595/#13574 from integration/eager-gull-22 (operator decision msg_c695ffcc)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Fix stderr-capture tests so they hit real routes, not decoys.

Delete the rustc program that returned Err before spawn without compiling
emit_shell_stderr_policy_binding; absent policy is already refused at the
emit diagnostic wall. Drive Complete limits from the live host-budget join
and keep drain specimens on the emit_rust authority strings.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fabric_quota: re-attach the window-start comment to quota_window_start (review 78371)

checked_second had been inserted between the comment and the function it documents.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Required CI: withdraw the four v1-judged lanes; the gate is emit-build alone (operator ruling 2026-10-09)

The operator's v1 withdrawal: v1 is no longer a validation authority, and
the one use left to the seed is emitting v2. gunbc.compiler_gate_workflow
drops `floor`, `generated`, `rust-unit-tests` and `seed`; the `witnesses`
aggregate reads the one remaining lane, `emit-build`, through the same
folded roster (one row). The GateArmSkippedOnPullRequest arm leaves with
its only inhabitant.

The loss is one declared drop, gunbc.rung_drop v1_required_lanes_withdrawn,
stated member by member (witnesses, stage0 mirrors and every generated
artifact, lint, v1 unit tests, module resolution outside the two emitted
closures, the downstream consumers), with a trigger that names the
capability: a binary built from an emission of v2 judging that population
on the required path. rust_unit_tests_off_pull_requests is Superseded (its
lane runs nowhere; trigger did not fire; the new row holds the loss).

gunbc.required_ci_contract_epoch moves to 2026-10-09.1: the name `witnesses`
now carries a materially different contract.

Consumers repaired rather than left dangling: the lane-resolution census
roster (the census now does not hold by design and is the instrument that
re-derives the drop's module population), DESIGN section 3's typed
required-gate reference (gunbc.documentary_refs, now
emitted_subject_build_rows), the Building & checks rows, the onboarding
path's run-witnesses step, five recurring_failure_mode evidence rows that
cited deleted declarations, and the two gate witness files (the blocking
set is asserted as exactly emit-build; a new RED asserts the four
withdrawn variables reach neither gate surface).

Projections regenerated by tools.generated_artifact_gate main_wet (the run
peaked at 15.8 GB RSS, against the 7.55 GiB that module's own note cites
for 2026-08-31): witnesses.yml, DESIGN.md, docs/design-rung-drops.md,
docs/onboarding.md; every other rostered artifact came out byte-identical.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Drop process-global budget env from stderr-capture tests.

review 78373: planting Complete limits through GUNBC_MEMORY_BUDGET_BYTES
leaked into parallel tests and did not inhabit the emit bind. Claim the
drain strings only; leave the host-budget join uncovered.

Co-authored-by: Cursor <cursoragent@cursor.com>

* regen round 0: stage0 mirrors from claim_executor --required-regen (supersedes provisional splices)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* provisional: re-append rt_host_budget to v1_rt.rs (round-0 regen emitted v1_rt.rs without it; seed bootstrap)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* regen round 2: stage0 mirrors (v1_rt.rs now emitted with rt_host_budget; hand-appended lines gone)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Regenerate generated artifacts for integration/eager-gull-22

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* required_ci_phase_roster: import std.optional (v2.std.optional moved by #13388; stale import from #13225)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* v1 closeout accounting: all lanes reported; remaining merge plan; closed auto-opened PRs

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Revert #13123 (admit_callers enforcement: mega's AdmitCallersEdge is the one enforcer)

* v1 closeout accounting: #13516 folded, #13212 dispositioned; every lane reported

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Drop #13545 transcribed-count red chunk (counts derive from ci_runner_sudo_binaries); retarget caller-admission real-route evidence to exact counts

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* v1 closeout accounting: eager-gull review outcomes, #13608 newer head, updated plan

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Drop the seed-growth citation of the deleted absent-policy decoy.

review 78381: hand_authored_declarations still named
emitted_absent_policy_refuses_before_spawn after that test was removed.
Absent policy stays cited as
capture_channels_without_stderr_capture_input_refuse_the_union.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Revert #13586 (receipt-only, excluded by operator review)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Revert #13453 (base-compiler/floor protocol; excluded by operator review): seed Rust, workflow steps and the script-row refusal API go with it

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* WIP: one required job, fresh products, memory envelope, heal-publish deletion (pre-merge, projections not yet regenerated)

* stage0 mirrors: restore generated mirrors to the mega branch's coherent set pending one regen round

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* floor_route_gap: give the belt exit-drain expectations their own chunk_43

Two folded PRs (#13442's seeded_filler rows and #13125's belt exit-drain rows) each
added floor_route_gap_expectation_chunk_42. The second silently replaced the first and
the native emitter refused (duplicate declaration). The exit-drain chunk becomes
chunk_43 and joins the roster, so both expectation sets are read.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* live_deploy: reconcile #13599 with #13583's directory authority

#13583 made owned directories the single directory authority (directory demands; host_directories)
and removed the directory kinds from the ensured steps and the instance parameter from
deployment_ensured_steps. #13599, folded alongside it, still called deployment_ensured_steps(instance:, target:)
and its witness matched on the deleted step kinds. The call passes target only, and the
lab-vs-production fabric-store claim now counts fabric_storage_store_directories demands in
deployment_directory_demands. Same claim, read through the surviving authority.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* roadmap_task_record: JSON codec for a runtime RoadmapNode (piece 1, uncompiled draft)

* roadmap_task_record witness

* roadmap_task_store: chain-partition roster over the fabric state binding, with wet witness (draft)

* roadmap_task_record: parent and centering required on the wire; drop nested optionals

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* managed_host: a superseded rung drop is not a standing citation

drop_is_standing_citation matched RungDropStanding with Retired and Standing only. Superseded has
existed since the 2026-10-06 supersession, and the closeout's seed refuses the non-exhaustive match,
which reaches every closure through managed_host (generated_artifact_gate included). A superseded
drop no longer stands, so it is not a citation, the same as Retired. (Found by smart-gull-336.)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* WIP: federation retired-path row below imports; floor_demand pinned envelope rows; managed_host Superseded arm (pre-regen)

* Headless Claude dispatch: print argv, systemd unit, stream-json projection.

When the harness has no spark, ExecutorDefault can admit Claude if custody is present; events stay in the belt's Codex envelope. Credential converge on srv1 remains an operator decision.

Co-authored-by: Cursor <cursoragent@cursor.com>

* closeout: complete the #13453 revert -- gunbc.fleet_desired_admission_workflow no longer imports the deleted script-row refusal API

6ee1d21 (integration/v1-closeout) removed fleet_desired_candidate_fetch_script_row and candidate_scripts_refusal from gunbc.fleet_desired_candidate but left their consumer, so every entry whose closure reaches the generated-artifact registry refused to resolve (regen, verify, five gate witnesses). This is origin/main's shape of the file: the admission workflow emits its YAML directly again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* closeout: complete the #13453 revert -- gunbc.fleet_desired_admission_workflow no longer imports the deleted script-row refusal API

6ee1d21 (integration/v1-closeout) removed fleet_desired_candidate_fetch_script_row and candidate_scripts_refusal from gunbc.fleet_desired_candidate but left their consumer, so every entry whose closure reaches the generated-artifact registry refused to resolve (regen, verify, five gate witnesses). This is origin/main's shape of the file: the admission workflow emits its YAML directly again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 94464b1)

* roadmap_task_record: balance ticket decode braces

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Address review 78387: one Claude event mapping, explicit executor, transmit effort.

parse_codex_jsonl now classifies bounded Claude stream-json via claude_code_line_codex_kind; jq only bounds those lines. ExecutorDefault stays a harness refusal. Print argv carries --effort.

Co-authored-by: Cursor <cursoragent@cursor.com>

* v2 compiler: reconcile #13438's precedence climbing with #13582 and #12942

Two merge-born references to deleted code, found by emit-build on #13641:
- 02_parse: #13438's infix stamp still wrote ParseProvenanceState.frame / FrameMinted, which
  #13582 deleted with the packrat memo. The write goes; the sibling stamps already carry none.
- body_lowering_fold: #12942's sealed body_lower_fold_raw kept the pre-#13438 pipe-tower test
  (body_lower_is_pipe_tower_root / body_lower_tower_pipes_into_fold), which #13438 deleted. It now
  uses #13438's replacement predicate, body_lower_application_pipes_into_fold, and keeps
  #12942's sealed outcome.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fleet_converge_workflow: drop MtCollins1UiBundleObserve from the mode list

#13503 removed the UI-bundle-observe mode (AMI-bundle-derived MegaRAC content) from
FleetConvergeWorkflowMode but left it in fleet_converge_workflow_modes. Every name in the list
now resolves to a declared variant. (Found by smart-gull-336.)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* WIP: trip is a ByteSize derived from the slot envelope (review 78388 item 3); witness claim the_trip_sits_inside_the_slot_envelope

* Address review 78389: emit tmux event pipe only for tmux containers.

Claude and harness systemd spawn no longer derive readiness from tee/pipe emission or refuse as tmux-event-pipe-emit.

Co-authored-by: Cursor <cursoragent@cursor.com>

* closeout: two stale references from folded deletions

- first_element_of_a_list_has_three_spellings cited v2.std.optional Optional; the module is
  std.optional (#13388's move).
- authorization_pattern_selection_witness imported PastedOperatorToken, which #13568 removed
  with the pasted-token refusal; the import was unused.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Regenerated projections for the one-job gate, on the merged closeout tree

One main_wet of tools.generated_artifact_gate over this branch merged with
integration/v1-closeout a925452 (regen 632 s, verify 693 s, both exit 0,
on srv1 under capped MemorySwapMax=0 scopes), nine artifacts:

- witnesses.yml: both subject steps carry GUNBC_BIND_MEMORY_CGROUP_BYTES
  (the derived trip, 20 GiB) and the failure notice carries the envelope
  lines (what 137 means, no larger runner and no retry, the MEMORY RECEIPT).
- DESIGN.md, docs/design-rung-drops.md: the CI row and the drop roster.
- .gitattributes: the deleted heal-publish.yml leaves the generated-artifact
  merge list.
- fleet-converge.yml: the closeout's authority fix projected.
- tools/fabric_ci_fci1_bounded_execution_context.env: the fci1 context
  follows the slot (22/21 GiB).
- provisioning/srv{1,3,4}/gunbc-ghrunner.sudoers: a 22 GiB slot fits more
  slots per host than a 26 GiB one, so the derived rosters grow (srv1 gains
  srv1-10 and srv1-11). Desired state; applying it is the converge effect.

The witness batch on the same tree: 16 files, green except the two latent
reds already recorded in the PR (fci1_bounded_execution_context: a stale
envelope-basis expectation; heal_publication_boundary: 23/34).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Enrol roadmap_task_store wet witness on the local-repo wet lane, as the allocation seam witness is

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Land the v2 cutover program as designed roadmap entries: 11 nodes, native_obligation_population plan, edges, RED acceptance witnesses

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* chore: regenerate drifted generated artifacts (ci auto-heal)


Ledger-Repair-Judged: docs/design-rung-drops.md
Ledger-Rows-Repaired: docs/design-rung-drops.md belt_liveness_publication_answers_unconsumed
Ledger-Rows-Repaired: docs/design-rung-drops.md bmc_secure_apply_converge_new_witness_eval_step_cost
Ledger-Rows-Repaired: docs/design-rung-drops.md edited_bin_witness_wet_rows_not_executed_by_ci
Ledger-Rows-Repaired: docs/design-rung-drops.md fixture_closure_union_unmodeled_stderr_capture
Ledger-Rows-Repaired: docs/design-rung-drops.md handoff_observer_is_sol_not_kvm_viewer
Ledger-Rows-Repaired: docs/design-rung-drops.md kvm_observer_protocol_wet_witnesses_deleted_with_the_observer
Ledger-Rows-Repaired: docs/design-rung-drops.md mtcollins1_boot_matrix_enrolment_dead_band_observed_only
Ledger-Rows-Repaired: docs/design-rung-drops.md mtcollins1_boot_matrix_new_witness_eval_step_cost
Heal-Candidate-Run: 38000315997

* closeout: regenerate stage0 mirrors and workflows from the folded tree

One emission round (operator ruling 2026-10-04) on srv1 at a925452:
claim_executor --required-regen, then generated_artifact_gate main_wet. Then on the
regenerated tree: seed build OK, gunbc test //gunbc/instruments:v2-native-cli exit 0,
//gunbc/instruments:self-host exit 0. Settles the files the folds left provisional
(fleet-converge.yml, the std_* and v1_compiler_* mirrors). docs/design-rung-drops.md was
already regenerated by CI auto-heal (17a309c).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* WIP: option B -- subject steps require the slot envelope; per-step trip withheld by the declared drop native_step_trip_awaits_fleet_job_cgroup; slot-grain receipt in gunbc test; seed-growth receipt (pre-regen)

* Enrol roadmap_task_store wet witness in floor_route_gap and the local-repo wet terminal, as the allocation seam witness is

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Regenerate ROADMAP.md, docs/plans and .gitattributes for the cutover rows; repair updated(...) wrapping

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Describe the envelope as slot-grain (option B) in witnesses-one-required-job; regenerate projections on the merged head

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Type the cutover receipt readings (closed kinds, ByteSize) and make the peak-above-trip control compare against the slot trip

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Subject steps require the slot envelope; the per-step trip waits on a fleet fact; the envelope decision is a .dag fold the seed mirrors

The first required run that passed GUNBC_BIND_MEMORY_CGROUP_BYTES
(38002497388 on a4b8f78) refused in four seconds: MemoryCgroupBindRefused,
the cgroup2 tree is not writable. memory_governor apply_memory_cgroup_bind
creates its leaf at the cgroup ROOT (a container-root design; the bind had
never been requested on the fleet) and a fleet job runs as the setpriv'd
job user under a root unit, so no job process can create the bound. The
operator approved the slot-grain arm (escalation 2026-10-09).

gunbc.memory_envelope (new) owns the decision and the verdict as folds over
supplied inputs -- the sibling of gunbc.memory_cgroup_binding -- and
test.claim.memory_envelope_witness_test reaches every arm by supplied value,
including the RED an inline decision could not: a slot requirement over a
process no numeric memory.max binds REFUSES (MemoryEnvelopeAbsent) rather
than running as bounded. The seed mirrors it arm for arm with unit tests;
the shells resolve the bounding cgroup through binding_cap_cgroup_dir (never
the peak locator), read memory.swap.max/.current/.peak (modeled in
extdeps.linux.cgroup_v2_memory) before and after the producer, print a
slot-grain MEMORY RECEIPT with event deltas and the peak labelled by whether
it rose, and refuse the run on any OOM kill or swap.

gunbc.emitted_subject_build_gate carries two envelope inputs and ONE
decision over them, native_step_memory_inputs(ownership): every subject step
REQUIRES the slot envelope (GUNBC_MEMORY_ENVELOPE_REQUIRED=slot, the
projection of EnvelopeSlotRequired) and the bind input at the derived trip
is withheld while gunbc.runner_slot_desired gunbc_runner_slot_job_cgroup_ownership
is JobOwnsNoBoundedCgroup. That is a fleet fact, not a rung drop -- nothing
on the required path ever held the trip -- so the climb is rostered as
gunbc.guarantee_stall native_step_trip_awaits_fleet_job_cgroup_stall
(grounding: unit delegation with DelegateSubgroup=, a per-job cgroup staged
by the root JIT wrapper, the governor's already-bound arm). The workflow and
the failure notice consume the fact; the witness exercises both arms by
supplied value, reads the live row, and asserts the bind KEY is absent.

The slot wall follows the ruling too: gunbc.runner_slot_allocation
gunbc_runner_slot_allocation_wall_holds drops its three floor conjuncts (a
slot sized to a tenant that no longer runs in it) and requires
MemorySwapMax == 0 instead of a swap above the maximum; the floor-fit drop
slot_row_pinned_below_demonstrated_demand_unrefused is Superseded with
v1_required_lanes_withdrawn as its loss holder; the slot witness re-pins the
row to 22/21/0 and its width alarms to the smaller slot's derivation
(srv1 12, srv3/srv4 21). The slot's demand oracle from here is the first
cold required run's MEMORY RECEIPT, a declared frontier.

The trip stays a ByteSize derived from the slot (review 78388 item 3). The
seed growth is receipted as gunbc.memory_envelope_receipt_seed_growth
(review 78391). The design document's CI row and the slot row's note say
the same.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* emit_rust: locate module via ModuleIndex.by_name; is_known_variant reads carried variant_to_enum (port of #13608 23f2d08, 8ff94ca; mirrors pending regen)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* decimal_digit_of_units: construct the units digit via the successor table; no D9 default for out-of-range Int

* closeout: bind variant_to_enum correctly at three #13665 call sites

import_variant_parent_for_name has no emit_info parameter; emit_specific_import_use_lines has no variant_to_enum binding.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Regenerate ROADMAP.md on the merged head; re-cite the envelope fact and stall

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Take sold Group B (srv9-srv12) out of everything that reaches hardware; declare fixture residue as a rung drop

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Supply sold Group B (srv9-srv12) as in-witness fixture population; production rosters stay empty

Chain: the scoped cut emptied dgx_spark_reserved_identities and the router bindings, so witnesses that
discriminated on the Group B population (commitment standings, admissibility, rail rows, topology
membership, reach labels) read nothing. spark_host_commitment_witness now folds the production
placement, claim and reservation rows over a local four-host fixture, with one inhabitance claim that
the production roster is empty; the topology, reach and site-locale witnesses are re-derived to the
emptied rosters. Under rung drop serving_fixtures_name_sold_group_b_hosts.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Regenerate std_integer stage0 mirror (remote required-regen candidate)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* closeout: revert #13662's fold (operator decision 2026-10-10)

#13662 (headless Claude worker) stays outside the closeout. A child re-lands it into main after #13641, with its review findings resolved.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Recut to five durable outcomes: cold-run envelope receipt rename, acceptance-receipt framing, derived-universe denominator, stable frontier subject; six chores moved to runtime tasks; no red witnesses

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* roadmap: split the event carrier's directory demand into a leaf module

gunbc.roadmap.dashboard_instance_directories imported gunbc.roadmap.roadmap_event_carrier for one
directory function, and through it the dispatch actuator. With #13625's host_standup -> host_effect
import (c390a49), that closed a 13-module cycle (materialized_secret -> host_phase_status ->
host_standup -> host_effect -> live_deploy.spec -> dashboard_instance_directories ->
roadmap_event_carrier -> roadmap_dispatch_actuator -> cursor_harness_credential -> ...), and main_wet
refused to resolve. The demand moves unchanged to gunbc.roadmap.roadmap_event_carrier_directory;
the carrier, the directory list and the owned-directory witness import it from there.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address review 78405: delete the never-red frontier-count decoration; eligibility and disjointness controls run over supplied members

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* closeout: five merge-born refusals that main_wet found

- managed_host: HostnameAllocation no longer carries canonical_hostname; read it through
  allocated_canonical_hostname (hostname_allocation's name scheme, #13625).
- host_control_route: handle ManagedHostFoundUnderDeclaredDrop the way managed_host's own
  account lookup does: the standing still decides the BMC route.
- mtjade1_arrival_federation_provision: DedicatedFederation's principal_set became
  impersonation: FederationImpersonation; the arrival pool is a standing-pool impersonation.
- fleet_workflow_steps: ci_fleet_wif_auth_step_when passed if_condition twice (a merge of
  #13607 and #13625).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Make fleet-converge branch-agnostic and parseable.

GitHub refused the workflow on every push after the mode input description crossed ~10k characters. Shorten that description to an authority citation, pin WIF to the workflow file on any heads ref plus workflow_dispatch (not pull_request), and admit a deploy from the current branch when --candidate-branch is empty. expected_revision stays a check when supplied and otherwise is the dispatched sha.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Name the branch-dispatch ruling; type malformed expected_revision.

Comments no longer claim reviewed-main file trust. Absent vs malformed expected_revision are separate arms so admit_optional cannot parse prose.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Declare the named-revision and deploy-branch drop.

Those two refusals are a different subject from the WIF main pin; §4b(3) needs its own population and trigger.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Recut #13660: restore privileged WIF to reviewed-main equality.

A rung drop does not substitute for the trust boundary. Privileged fleet-converge federations pin workflow_ref and ref at main again; session-branch admission lives only on the development pin list, which is not bound to fleet-cloud-convergence.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Drop leftover census conflict markers and project the named-revision drop.

The recut commit had kept rebase markers in gcp_iam_approval_enforced_in_reviewed_code; the projection now carries fleet_converge_named_revision_and_branch against closeout.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix OidcClaimPin inhabitance and the privileged-pin wording fork.

branch_dispatch_claim_pins now constructs event_name via oidc_equals. Privileged jobs are described as reviewed-main equality; the development pin list is named as a frontier, not a live federation.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Split presented OIDC claims from pins; printer session-branch is a red.

Privileged printer pins equal reviewed main, so a concatenated session-branch workflow_ref must refuse. Admission now takes OidcPresentedClaim (name and value only); relation lives only on the pin.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Regenerate fleet-converge.yml (21 inputs) and pin dashboard-deploy to main.

GitHub refused the hand-edited 30-input file; emission from fleet_converge_dispatch_inputs is the repair. dashboard-deploy now requires refs/heads/main and environment srv1-production so a branch dispatch cannot wet-deploy production.

Co-authored-by: Cursor <cursoragent@cursor.com>

* closeout: revert #13663's fold (operator ruling: #13662 and #13663 stay outside the closeout)

deep-cat-540 recuts it onto main after #13641.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Omit Spark dispatch when the administrator roster is empty.

Review 78408: regeneration had folded a sold-out Spark roster into target options: [] while spark_* modes stayed selectable. Restoring srv5-srv12 would invent enrolled hosts. Emission now drops the target input and spark_* mode options, and refuses any remaining empty InputChoice.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Treat srv1-production environment protection as the root-mutation boundary.

A branch dispatch runs that branch's YAML, so a github.ref if is not a trust boundary. dashboard-deploy, approval-broker-dark-install and microvm-controller-install now name srv1-production; the required GitHub setting (main-only deployment branches, required reviewers) is modeled with an unobserved readback. Checkout is the event sha.

Co-authored-by: Cursor <cursoragent@cursor.com>

* closeout: stage0 mirrors and projections regenerated at a fixed point on 5c0d9d5

The composed closeout tip (the #13663 revert and #13664's fixed head folded) could not regenerate itself: claim_executor --required-regen refused with Stage0EmittedEdgesNotCovered (62 emitted edge endpoints with no stage0 crate) and the committed mirrors did not build a seed. Two generation-1 facts explain both, and both are repaired in this set rather than worked around.

First, the regen's coverage check reads the host-shell roster from the TREE's src/v1/stage0/src/lib.rs (required_regen_host: closure_modules(lib.rs)), not from the seed. The integration-side regen from the d9368e8 seed, an emitter predating the crate planner (#13597), rewrote lib.rs without the three pub mod lines #13597's head 3674580 carried for gunbc_crate_partition, gunbc_emitted_crate_workspace and v1_compiler_emitted_workspace, while their mirrors and .dag sources stayed. Restoring the three declarations lets the regen run; the regenerated lib.rs then lists them canonically, which is the only change this set makes to lib.rs.

Second, --required-regen renders v1_rt.rs from the SEED's compiled-in runtime rows, so a boot seed older than the tree's runtime_rust.dag emits a candidate without the host-budget join that the tree's memory_governor mirror consumes, and generation 1 does not build (the closeout history records the same provisional step at 42954d2). The committed v1_rt.rs is kept for generation 1; generation 2, whose seed carries the tip's rows, emits it identically, so v1_rt.rs is unchanged here.

Recipe, on a shallow clone of 5c0d9d5 on srv1, each step under systemd-run --user --scope -p MemoryMax=80G -p MemorySwapMax=0: boot seed built from 3674580; main_wet; lib.rs roster repair; required-regen with the boot seed (first_generation_equal=false, 244-file candidate); install; v1_rt.rs restored; then the tip's own seed: build, main_wet, required-regen (generation 1: divergent, candidate installed; generation 2: first_generation_equal=true). No .dag file changes. The projections are main_wet's output over the composed tree: fleet-converge.yml regenerated from its 21-row authority (the committed 30-input file was drift), ROADMAP.md and docs/plans/native-obligation-population.md for #13664's recut, docs/design-rung-drops.md for the supersession, .gitattributes for the plan projection's merge driver.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fleet-converge: omit the Spark target input and spark_* modes while the administrator roster is empty; refuse an empty choice at emission (port of ffe8a90)

The fixed-point regeneration on 5c0d9d5 faithfully emitted .github/workflows/fleet-converge.yml with `target: type: choice, options: []`, because gunbc.spark.credential_workflow spark_administrator_credential_roster has been empty since 2026-10-10 (every Spark sold) and gunbc.fleet_converge_workflow had no wall for an empty closed choice. GitHub rejects a choice input without options, so the regenerated workflow would have been undispatchable in every mode, not only the seven spark_* modes that read inputs.target; the previously committed file was drift the other way (hand-kept srv5..srv12 options for hosts no longer enrolled). Review 78408 on gunbc#13660 found this, and snappy-stag-26 fixed the authority there at ffe8a90; that PR is ruled outside the closeout at its WIF scope, so this commit ports exactly the empty-roster hunk and nothing of the WIF or environment changes.

What changes in the authority: fleet_converge_spark_target_modes names the seven modes that consume the target; fleet_converge_dispatchable_modes() drops them while fleet_converge_spark_target_options is empty, and fleet_converge_mode_options is derived from it; the dispatch inputs are now fleet_converge_dispatch_input_rows filtered by fleet_converge_dispatch_inputs, which omits `target` while the roster is empty; fleet_converge_empty_choice_input_names() enumerates every InputChoice with no options over the four DispatchInputType variants, and expected_fleet_converge_yml() refuses emission with those names before the input-count check (DESIGN section 5: refuse, do not emit options: []). The witness every_dispatch_option_is_a_wire_value_of_the_vocabulary joins the options to the dispatchable modes, and empty_spark_roster_does_not_emit_an_empty_choice_or_spark_dispatch_modes pins the current roster state. The fleet_workflow_steps.dag hunk of ffe8a90 is not needed here: the closeout's ci_fleet_wif_auth_step_when already passes if_condition by name.

The regenerated fleet-converge.yml is main_wet's output over this authority with the fixed-point seed; the stage0 mirrors are unchanged (the module is not in the emitted population) and required-regen stays at first_generation_equal=true.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* closeout: delete the accounting doc; the terminal ledger lives in #13641's body (review 5474794145)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* closeout: revert the #13664 fold (5c0d9d5) per the operator's review 5477471759: close #13664 without folding, branch preserved; projections regenerated next

* deployment environments: model the branch policy as GitHub returns it (name + branch-or-tag rules), so the srv1-production standing can be discharged by a faithful GET (review 78420)

Review 78420 on gunbc#13660 (folded here at 60c9457) found that extdeps.github.deployment_environments modeled the deployment-branch policy as SelectedRefs { refs: ["refs/heads/main"] }, while the API carries no refs: the environment object's deployment_branch_policy is null or { protected_branches, custom_branch_policies }, and the custom rules live at GET /repos/{owner}/{repo}/environments/{name}/deployment-branch-policies as branch_policies rows { name, type } with type "branch" or "tag". A reading of the real API can therefore never match the modeled refs, so gunbc.auth.github_deployment_environment's standing could never move from Unobserved to Holds (DESIGN section 3: model what the API actually returns; section 5: a check that cannot be discharged is not a boundary).

The model now carries DeploymentBranchPolicyRule { name, ref_type: PolicyRefBranch | PolicyRefTag } under SelectedBranchesAndTags { rules }, the srv1-production requirement is the single branch rule named main with required reviewers, the restriction predicate requires exactly one rule that is a branch named main, and the read obligation names both GETs and the shapes they return. The witness gains a supplied-value control: a tag rule named main and a two-rule policy are not the main-branch boundary, the single branch rule is. Standing stays Unobserved until the operator applies the setting and its readback lands; that flip is the first follow-up on main.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* closeout: regenerate at the fixed point on composition A (revert of #13664, fold of #13660)

Same recipe as f8c3fa4, on a shallow clone of dbdc9d2 with the previous fixed-point seed as the boot seed (srv1, logs8): main_wet exit 0; required-regen generation 0 drifted gunbc_cli_dispatch_surface.rs (gunbc.cli_dispatch_surface is touched by #13660), generation 1 drifted gunbc_cli_dispatch_generated.rs, generation 2 first_generation_equal=true planned=169 executed=169 adjudicated=169 declared_divergent=1 [main.rs]; verify (dry main) exit 0; rebuild; gunbc test //gunbc/instruments:v2-native-cli exit 0 (emit and build exit_status=0 warning_count=0 wall_s=611, discriminating red on v2_cli_compile_cli) and //gunbc/instruments:self-host exit 0 (wall_s=716, red on v2_compiler_compile). The projections resolved toward #13660's side in the merge (ROADMAP.md, fleet-converge.yml, docs/design-rung-drops.md) were byte-identical to main_wet's output, so only .gitattributes and the two cli_dispatch mirrors change here.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: gunbc-ci-auto-heal <briansrls@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: x <x@x>
Co-authored-by: gunbai-bot[bot] <289086189+gunbai-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant