Skip to content

Omega: runner-capacity lane consolidated (5 of 6 constituents) - #8016

Merged
briansrls merged 66 commits into
mainfrom
omega-runner-capacity
Aug 8, 2026
Merged

briansrls merged 66 commits into
mainfrom
omega-runner-capacity

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Consolidation of the deep-badger-594 runner-capacity lane into one PR, per operator request.

What merged cleanly (5 constituents)

PR branch state when folded
#7938 session/jolly-swift-846 2/2, ci=success
#7947 session/still-ram-738-pr-c 2/2, ci=success
#7940 session/vivid-otter-718 2/2, ci=success
#7931 session/still-ram-738 2/2, ci=failure (own witness)
#7957 session/quick-bear-899 2/2, ci=failure (known flake)

Branched from origin/main at 08887c6e913 and merged each constituent (merge commits, no rebase, no cherry-pick). 91 files, +10582/-220. No conflict markers in the tree.

Cost paid to build this, stated plainly: #7938, #7940 and #7947 were each 2/2 with ci=success on frozen heads at the moment of folding. This PR starts at 0/2 and needs a fresh CI round. That was an accepted trade to get a single artifact to reason about.

What did NOT merge — #7939, and this is the remaining work

#7939 (session/vivid-eagle-131) conflicts on 9 files, of which 5 are add/add:

add/add   dag/gunbc/apply.dag
add/add   dag/gunbc/fleet_runner_connectivity.dag
add/add   dag/gunbc/runner_capacity_plan.dag
add/add   dag/test/claim/fleet_runner_connectivity_witness_test.dag
add/add   dag/test/claim/runner_capacity_plan_witness_test.dag
content   dag/extdeps/github/ci_runner.dag
content   dag/gunbc/non_fold_residue.dag
content   dag/gunbc/runner_host_deploy.dag
content   dag/gunbc/runner_slot_allocation.dag

An add/add conflict means two lanes independently authored the same carrier. That is the §3 dual-representation violation, and resolving it is a modeling decision — pick the single authority and delete the fork — not a textual merge. Taking either side by convenience would land two representations of runner capacity in one tree, which is the exact failure the design doc says gets consolidated later at higher cost.

So the residual work in this lane is one question, not nine: which lane owns runner_capacity_plan, fleet_runner_connectivity, and apply?

What this PR does NOT do

  • Provisions nothing. All nine runner_lifecycle_realize_* arms return NotConverged as declared scaffolds with a named dissolution trigger (runner_lifecycle_realize_wet_transport_dissolve_on). The fleet stays at 20 runners.
  • The activation-first vs install-pipeline-primary question was never ruled on and is carried on the constituents rather than guessed. Live evidence gathered this session says activation-first: srv3-06/07 are complete runner installs with units disabled+inactive, and a stale .runner is harmless (its mtime tracks unit ActiveEnterTimestamp to the second, so it is rewritten every incarnation).
  • srv4 remains unobservable after four access paths failed. Its slots must not inherit srv3's evidence grade.

Known reds among constituents

Superseded and already closed: #7946 (contained in #7947, verified by path comparison), #7930 (control law rejected as circular).

— sent from deep-badger-594

gunbc-ci-auto-heal and others added 30 commits August 6, 2026 20:49
…ed replacement classification

Split MemberAction's collapsed upsert into four arms per operator ruling:
MemberAdded{to} | MemberChanged{from,to} | MemberRemoved{from} |
MemberRemovalRefused{from, cause}.

The discarded `from` was the load-bearing loss. Every safe realization of a
change consumes the prior value: an SCM ref update is a compare-and-swap that
names the expected prior (git update-ref <ref> <new> <old>), and a host resource
whose address moved needs the prior endpoint to retire. With only `to` in hand
the sole reachable realization is the unconditional write. MemberEffect splits
the same way (EffectAdd/EffectReplace{from,to}/EffectRemove) so the apply grain
can retire a prior realization instead of overwriting it blind.

gunbc.host_resource: identity is allocator-minted at declaration, never derived
from unit/path/content. HostResourceIdentity{host, occurrence} +
HostResource<R,V>{identity, role, value}, role a type parameter so a new role is
an instantiation rather than a widened central enum. This is the closed-system
answer to renames: git does not track them, it INFERS them from content
similarity, and DESIGN 4 rules a heuristic never necessary in a closed system --
a content-derived key_of is that inference wearing a bundle. Distinct carrier
from std.occurrence_identity (source-occurrence specific; one shared Int space
would let occurrence_id_eq answer true on a numeric coincidence -- the
cross-family comparison the ContentHash grounding closed). The subject-
parameterized extraction is registered as a trigger, not built under a
load-bearing module with stage0 work in flight.

gunbc.change_realization: the classification table. SCM ref -> atomic CAS;
source declaration move -> atomic SCM tree transformation; same runtime address
-> in-place update; changed host address -> staged replacement with declared
intermediates. Kills a live conflation: a .dag module re-home is an SCM tree
transformation, NOT a host migration. StagedIntermediates is head+tail so an
empty intermediate plan has no constructor, and an undeclared one refuses
(typed, located) rather than degrading to an overwrite -- the srv4 lesson (its
build-cache server died with its cgroup, never unlinked its socket, ran uncached
for weeks) made unwritable rather than warned about in prose.

A change-refusal arm was built during this work and WITHDRAWN: gunbc.ownership
defines Ensured as "requires present but does NOT own (never torn down)", a
constraint on removal, not update. It broke tool_readiness and
repo_local_git_config (whose job is re-installing drifted pins/bindings) and was
unreachable elsewhere. Per DESIGN 4c a carrier note is not evidence, so the
withdrawal is enrolled as w_ensured_member_converges_but_refuses_removal.

All three new guards verified DISCRIMINATING by planting their exact
regressions: reintroducing the change-refusal arm reds the Ensured control
alone; reintroducing the collapse reds the both-sides rows; turning the
staged-replacement refusal into an InPlaceUpdate fallback reds the srv4 row.

Caught during migration: repo_local_git_config's apply fold has a `_ => acc`
wildcard for its construction-unreachable removal arms, and MemberChanged would
have fallen into it -- silently dropping the drift that module exists to
converge. Both write arms are now explicit. live_deploy's EffectReplace is
structurally unreachable at both degenerate poles and emits a loud typed poison
per that module's discipline; its 44 byte-identity goldens pass unchanged.

Witnesses green by execution: membership_reconcile 10/10, change_realization
8/8, live_deploy 44/44, plus tool_readiness, repo_local_git_config,
workflow_reconcile, srv3, host_phase_status, roadmap_belt, host_axis_caps.
Corpus compile carries the same 10 pre-existing diagnostics as main, none mine.

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

Introduce typed RunnerConnectivityAction with incarnation replace, canary-first
fleet breaker, verified postcondition, and per-host reach refusal so wedged
acquire-job slots plan repair without watchdog fanout.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ions webhook incident)

The PR opened during the Actions backend incident and no workflow runs were
created at all -- absent, not queued. ci.yml triggers on pull_request
[opened, synchronize, reopened, ready_for_review], so this empty commit fires
a synchronize to get the affected-set run executed against the branch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Project RunnerIncarnationReplace into a four-step observe-replace-observe
sequence with scaffold binds to still-ram-738's HostEffect variants; witnesses
green for replace and noop paths.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ivate, verify

Split from parked #7931 joint-solver PR per operator ruling (deep-badger-594):
this lane owns HostEffect arms, runner_lifecycle ADD sequence, slot
provision, disk observation, srv4 width-7 at allocation with apply-time
disk preflight, and fleet observation producer scaffolding.

Not included here: host_capacity_solve joint enumeration (stays on #7931).

Judgement calls in this PR body:
- runner_host_deploy / runner_slot_allocation: provisioning materialization
  target (runner_count=7, disk gate at apply).
- fleet_shell_transport_observation, build_cache_endpoint_observation,
  host_swap_backing, session_residency shell gate: interim observation
  producers gated on transport; unsure → delivery PR.
- host_converge_slice1: under-count is postcondition for provision ADD,
  not pre-refuse (count equality after RunnerSlotProvision).

Local verification: claim_batch on runner_lifecycle, runner_slot_provision,
runner_slot_allocation, host_allocation_conservation, runner_host_deploy
witnesses (pull_request checks absent repo-wide since 2026-08-06T19:36:59Z).

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

Parked off capacity-delivery critical path per operator ruling — NOT
presented as progress toward gunbc apply / seven runners. Lifecycle,
HostEffect arms, and provisioning live on session/still-ram-738-pr-b.

This PR contains only host_capacity_solve + witness and the jobserver
helper split needed for per-token pool sizing in the enumeration.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep producer-Unobserved as Unobserved with dated receipts as provenance
only, not authoritative ReachRefused. Refuse fabricated Owned on observed
slot dirs until systemd drop-in provenance lands (ownership_of Absent).

Co-authored-by: Cursor <cursoragent@cursor.com>
Connects gunbc.apply mode=apply to runner_capacity_plan + disk
preflight + ADD dispatch seam (depends on #7939 plan, #7946 effects).

Witnesses: two additions not count-refusal, disk unobservable refuses
(not width-5 fallback), replay no-op when observed satisfies request.
Local claim_batch: 3/3 PASS on runner_capacity_realize_witness_test.

Co-authored-by: Cursor <cursoragent@cursor.com>
Import hardware_thread_count_value so the tokens-cap refusal witness resolves;
author srv3_non_compile_residency_observed as a scaffold producer so the dissolve
DeclarationRef cites a live symbol; ground slice_unit via host_layout.gunbc_managed_compile_pool_slice_unit.

Co-authored-by: Cursor <cursoragent@cursor.com>
Only SessionsObservedAbsent maps to CapacityEvidenceObserved; observed
session presence caps at candidate-only with an explicit reason. Add
srv1_session_present_live_capacity_is_candidate_only witness.

Co-authored-by: Cursor <cursoragent@cursor.com>
Models the conjunction predicate (remote offline + broker silence + no worker + grace elapsed), evidence grades, re-read refusal, and derived 10-minute bound with discriminating witnesses wired into runner_connectivity_recovery.

Co-authored-by: Cursor <cursoragent@cursor.com>
The floor's extdeps scope placement gate refused PR C: dag/extdeps/github/
actions_runner.dag landed as a new extdeps module enrolled in neither
scope_carrier_paths nor the machinery exemption, and the frozen legacy
manifest is not a landing state for anything added after the freeze.

Subject is actions_runner_release_2_334_0 — the cited upstream release row,
which is what GitHub actually publishes and what this module exists to pin.
Appended to the carrier roster rather than re-sorted; re-sorting that list
produced a pointless merge conflict on #7891 earlier today.

carriers_declare_scope_on_disk, frontier_rosters_are_disjoint,
roster_paths_resolve_on_disk and preflight_rows_counted green by execution.
The other diagnostics in that run were the floor refusing to spend budget
once batch 1 went red, not separate defects.
Add missing HostEffect match arms in fleet_converge_cli, fix lifecycle
witness construction (no bare _ values), and model post-convergence width
via converged-seven roster fixture so a second apply plans zero additions
and succeeds without disk preflight when nothing remains to materialize.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add fleet plan builder with per-host replacement cap, five-step repair choreography (observe before mutate), SIGPIPE diagnostic-read refusal, and reobservation witnesses.

Co-authored-by: Cursor <cursoragent@cursor.com>
'release' is a reserved word; using it as a match binder made
runner_lifecycle_witness_test.dag unparseable, which killed regen and
heal before they did any work and left ci reporting FloorUpstreamAlreadyRed.
All three red jobs had this one cause.

Underneath it, witness_runner_lifecycle_host_effects_declared constructed
each HostEffect variant and matched it straight back. That establishes only
that the constructor typechecks -- already the typechecker's guarantee -- and
cannot go red on any behavioral defect. The compiler refused each single-arm
match as non-exhaustive over the 31-variant coproduct; answering that with
thirty '=> false' arms would make the tautology compile without making it a
check. Deleted, with its now-dead imports. fleet_converge_cli already carries
the claim by execution: it matches HostEffect exhaustively and fails to
compile if an arm goes missing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ReplaceRunnerIncarnation now carries LocalRunnerSlotIncarnation plus
RunnerReplacementCause so repair plans can refuse stale incarnations and
name why replacement fired; witness binding renamed from release to cited
to avoid the reserved keyword that broke regen.

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

Auto-heal correctly removed witness_runner_lifecycle_host_effects_declared
(parse error + no behavioral oracle). ReplaceRunnerIncarnation grounding on
LocalRunnerSlotIncarnation and RunnerReplacementCause remains in host_effect.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add runner_lifecycle_realize_wet_transport_dissolve_on (srv3/srv4 SSH
reach + HostEffectTransport) and cite it from every NotConverged arm;
update runner_capacity_realize authority note to state apply does not
provision until the scaffold retires.

Co-authored-by: Cursor <cursoragent@cursor.com>
Move LocalRunnerSlotIncarnation to gunbc.runner_incarnation, add ReplaceRunnerIncarnation seam witnesses, and model in-band ADD admission (LocalShell + derived execution target; Step E void). Capture operator constraints: workflow-only application, srv1 row-6 control, unit/process width authority, imperative caps, and ctrl installer read-before-realize.

Co-authored-by: Cursor <cursoragent@cursor.com>
srv1 probe shows complete dormant install trees without .runner until JIT start. Add three-state installation carrier and witnesses; correct width notes. srv3/srv4 slot-06/07 state still unobserved from this session.

Co-authored-by: Cursor <cursoragent@cursor.com>
Collapse materialized-never-activated and materialized-previously-activated into SlotMaterializedNotActive; unit_active drives readiness. Record srv3 06/07/08 probe, srv3 reach via srv2 jump, and width-8 vs intent-7 ceiling.

Co-authored-by: Cursor <cursoragent@cursor.com>
RunnerSlotInstallationObservation separates observed states from Unobserved/ReachRefused so srv4 never defaults to SlotAbsent. Pin srv3 01-08 mapping from sibling probe; witnesses enforce srv4 blocks add without extract routing.

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

Restore srv3 shell transport session receipt for producer-unobserved authority, pin incident desired_width at 22, pass roster into connectivity repair planning, and enroll connectivity verdict predicates in the non-fold-residue roster.

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

Wire vivid-eagle srv3 shell transport as producer-observed success while srv4 stays unobserved with dated receipt provenance; derive incident desired_width=22 from srv4's five-slot outage pin instead of a naked literal.

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

Introduces medium-neutral CiExecutionPlan carriers from ci_spec (not ci.yml), a poll-first ci_control_plane daemon with durable queue and lease reclaim, GitHub Checks create/update, and /ci serve routes for run receipts.

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

Load repo/stages/floor plan from gunbc.owned_ci_seed via eval; persist ledger before check create; mark CheckPublicationPending on API failure without duplicate enqueue; document seed REST transport as dissolve-on scaffold.

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

Ground lease duration on std.measure.Second and queue expiry on NumericDate;
load state root and lease seconds from gunbc.owned_ci_seed in the Rust bin;
fix unpublished-completed conclusion mapping and UpdateRun wire encoding;
dissolve ci_subject_is_fork_refused Bool predicate into direct coproduct match.

Co-authored-by: Cursor <cursoragent@cursor.com>
Drop dead failed/completed ternary on queue move (always completed dir);
remove tautological Rust unit tests — decision procedure stays in .dag witnesses.

Co-authored-by: Cursor <cursoragent@cursor.com>
Propagate system-clock errors from now_unix instead of fabricating 0;
persist fork PR refusals to index/run ledger so the /ci UI can observe them.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace Bool lease expiry with typed reclaim/validity decisions that
carry LeaseClockRefused for fractional NumericDate arms; witness the refusal.

Co-authored-by: Cursor <cursoragent@cursor.com>
Brian Searls and others added 6 commits August 7, 2026 18:59
…amilies.

NFR rows would stale the roster — these helpers are exhaustive matches without top-level wildcard arms (unlike connectivity_verdict_is_*). Document predicate-dissolution at authoring via explicit Terminal disposition rows.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review August 7, 2026 21:00
gunbc-ci-auto-heal and others added 2 commits August 7, 2026 21:06
Three conflicts, all resolved additively — no side's facts dropped:

- host_effect.dag: both import sets kept (runner-incarnation carriers from
  this lane, CandidateRelease from main).
- non_fold_residue.dag: both frontier roster rows kept; the two lanes
  appended independent subjects to one list.
- ci_deploy_target_host_witness_test.dag: took main's side. Its rename
  deploy_runner_labels_contain -> deploy_runner_label_list_contains repairs a
  real homonym collision against gunbc.design.component's byte-identical
  declaration; this branch carried only the older colliding name and no other
  content in that file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gunbc-ci-auto-heal and others added 2 commits August 7, 2026 21:32
Two conflicts:

- extdeps_scope_frontier.dag: additive roster on both sides, union kept
  (actions_runner.dag from this lane; claude_sdk.dag + codex_app_server.dag
  from main). Neither side's carriers dropped.

- DESIGN.md: the generated-artifact driver refused, correctly — both sides
  changed this projection since the merge base. The regenerator could not be
  run to resolve it: `generated_artifact_gate main_wet` was OOM-killed at
  "resolved 605 sources" on three attempts, twice locally and once through
  ctrl-build --remote. The kill is not this session's cgroup cap
  (memory.events.local `max 0`, `oom 0`; only `oom_kill` incremented, which
  counts processes that died, not the cap that decided).

  Resolved structurally instead of by picking a side, and the structure is
  checkable: base, ours and theirs have identical line counts; ours changed
  exactly line 148 and theirs exactly line 152, disjoint. The authority
  (design_document.dag) auto-merged with BOTH edits. Each side's line was
  then verified to appear verbatim in the merged authority's li(text:) rows
  under the source escapes (\{ and \"), so the union of the two disjoint line
  replacements IS the projection of the merged authority, not a chosen side.

  This is asserted from structure, not from an executed regeneration. The
  drift gate in CI is the independent check and has not yet run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The type is referenced twice in this module and was resolving only by pool
coincidence — the Class B binding failure the corpus already tracks. Picked up
from session/still-ram-738-pr-c commit 5df7f02, which fixed the same review
finding on the now-superseded branch.

That commit's other half — a stray brace in non_fold_residue_frontier — does
not apply here: it came from that branch's own conflict resolution, and this
branch's roster resolution did not produce one (checked, the list closes clean).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gunbc-ci-auto-heal and others added 3 commits August 7, 2026 22:59
…urface.

CI ci job red: 'Refused' not found in module 'gunbc.membership_reconcile'
(imported by 'gunbc.runner_slot_provision'), 3 occurrences. A genuine fold
defect, not a flake and not memory (floor peak 9.85 GB against memory.max
17179869184 = 57%, so the cap was not reached).

CAUSE: runner_slot_provision came from #7947 and was written against the
pre-rework membership_reconcile surface (MemberUpsert / MemberTeardown /
MemberTeardownRefused / membership_upsert_count). The fold also brought in
#7938's MemberChanged{from,to} rework of that module, which splits the old
fused upsert into distinct MemberAdded and MemberChanged arms. Neither PR
was wrong alone; consolidating them created the mismatch.

NOT A MECHANICAL RENAME. The old MemberUpsert fused add and change, and the
operator's Decision 1 split them deliberately, so each site is a decision:

- MemberAdded -> emit the slot extract script. This is the add path.
- MemberChanged -> []. Decision 2 says apply may execute RunnerSlotAdd only
  and must refuse Change/Remove/IncarnationReplace; emitting an extract
  script for a changed member would materialize a change the apply path is
  required to refuse.
- MemberRemoved / MemberRemovalRefused -> [], unchanged in meaning.
- membership_upsert_count -> membership_added_count, NOT the derived
  membership_write_count (= adds + changes). The consumer is
  runner_slot_provision_has_width_increase: a width INCREASE is adds; counting
  changes would overcount. membership_write_count exists for consumers that
  want both, and this is not one.

The witness carried the same stale vocabulary and is migrated with it; its
assertion is preserved exactly (7 desired - 2 observed = 5, and the 2 observed
match desired so they are Unchanged, not Changed).

VERIFICATION, stated at its real strength. A local single-entry run does NOT
verify this: a stashed-fix control returns the IDENTICAL 2000 errors and zero
'Refused' reports on the pre-fix tree, so that instrument never surfaces this
defect class -- it dies at parse before resolution, and 2000 is a truncation
cap rather than a count. Verified instead at symbol grain: all 7 symbols
imported from membership_reconcile resolve to declarations, with a positive
control confirming the query reports the two removed names as MISSING. CI's ci
job is the instrument that found this and is the one that settles it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
REQUEST_CHANGES verified against current code rather than taken on trust, and
the finding is correct: gunbc.owned_ci check_publication_reports_github_success
and check_publication_is_pending_honest are coproduct is_*/reports_* predicates
carrying no disposition, while this same diff already dispositions two sibling
families — extdeps.github.ci_runner github_runner_registration_predicate_family_disposition
(review 50232) and gunbc.runner_incarnation runner_slot_installation_predicate_family_disposition.
Inconsistent within one PR is the reviewer's point and it stands.

Adds check_publication_predicate_family_disposition = Terminal, matching the
runner_incarnation precedent's shape and reason.

TOTALITY CHECKED, NOT ASSERTED. The row claims both matches are total, so that
claim is measured: CheckPublicationState has six variants (NotStarted, Queued,
InProgress, Completed, Pending, Failed) and both fns carry an explicit arm for
all six with zero top-level wildcard arms. Positive control: the same query
reports a fictitious variant as missing, so an all-present result is a real
negative rather than a blind read. (First pass counted the type name itself as
a seventh variant and reported a false miss — the query was wrong, the code was
not.)

Terminal rather than NFR enrollment is the right arm for the same reason the
precedent gives: these dissolve at authoring, so an NFR row would stale the
roster. fleet_runner_connectivity connectivity_verdict_is_* is the contrasting
case — wildcard false arms, correctly enrolled in non_fold_residue_frontier.

Scope checked: exactly two Bool fns in gunbc.owned_ci match over a coproduct,
and both are fixed. owned_ci_run_id_char_is_digit / _is_hex take String, not a
coproduct. check_conclusion_is_success lives in extdeps.github.checks, outside
this diff.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ogy authority.

OPERATOR DIAGNOSIS, and it corrects mine. I had read the double count as a
property of the current topology and concluded the arithmetic had merely drifted
under a stable defect. Wrong on the load-bearing point: main ALREADY carries the
correct rule, and #7931 reintroduced the defect locally.

THE DEFECT IS A DUAL REPRESENTATION OF ONE SEMANTIC FACT — where compile RSS
lives in the host's resource topology.

  Representation 1, the authority (gunbc.fleet_host_budget):
      CompilePoolInRunnerSlots  => CompilePoolDerived { bytes: byte_size(0) }
      CompilePoolSliceDeclared  => resolve_compile_pool(...)
    Compile memory is CONTAINED in runner-slot accounting under the current
    topology, so it is not a second claim on host RAM.

  Representation 2, the parked solver (gunbc.host_capacity_solve):
      per_slot_runner_pool_charge(CompilePoolInRunnerSlots) = full MemoryMax
      compile_pool = jobserver_build_pool_bytes_for_tokens(...)   [EVERY placement]
      host_allocation_conserves(runner_pool: .., compile_pool: .., ..)
    Two additive SIBLING charges. The placement argument steers the runner-side
    charge but never gates whether the compile charge is added at all.

A containment relation (compile RSS subset-of runner-slot RSS) flattened into a
partition of disjoint siblings. The solver imports the placement and then
reimplements its accounting meaning, which makes the solver a second authority
over a fact fleet_host_budget already owns.

WHY THE WITNESS FAILED NOW. joint_solve_double_counted_topology_refuses_seven_slots_at_derived_tokens
asserts best.runner_slots < 7 — a NUMERIC CONSEQUENCE, not the invariant its name
claims. At 16GiB slots, 7 x 16 = 112GiB against 125GiB usable, so the doubled
charge pushed 7 over and the witness passed. At 14GiB (#7891's measured ruling,
already on main) 7 x 14 = 98GiB leaves ~27GiB, so the same broken model now fits.
The modeling error is unchanged; only its numerical shadow moved. Flipping the
assertion to >= 7 would have been a tree-copied measurement — a change detector,
which DESIGN section 5 forbids as an oracle.

WHY REMOVAL RATHER THAN REPAIR. #7931 is parked, non-delivery content, and main's
capacity authority already carries the correct placement-dependent decomposition,
so deleting the fork restores single authority with no capability lost. Repairing
in place would mean routing candidate accounting through one placement-aware
charge and replacing the numeric witness with structural placement/charge
controls — real work that belongs to the capacity lane, not to a consolidation.

REVERTED TO MAIN, all four paths #7931's merge touched:
  D dag/gunbc/host_capacity_solve.dag              (absent on main)
  D dag/test/claim/host_capacity_solve_witness_test.dag  (absent on main)
  M dag/extdeps/jobserver.dag       -> main (the _for_tokens split served only the solver)
  M dag/gunbc/host_layout.dag       -> main (gunbc_managed_compile_pool_slice_unit had
                                      exactly one consumer, the solver; keeping it would
                                      strand an unconsumed carrier)
Checked: zero dangling references to host_capacity_solve,
jobserver_build_pool_bytes_for_tokens, or gunbc_managed_compile_pool_slice_unit
remain in the corpus, and per_slot_runner_pool_charge is gone entirely.

NOT CONFLATED WITH THIS: the live jobserver admits 128 tokens where the declared
formula derives 62. That is an over-admission pointing the opposite way (too
permissive) from the double count (too conservative). Untouched here.

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

gunbai-bot Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

Re: review 50446 (REQUEST_CHANGES) — verified against the current tree, and not fixing, because the finding's premise does not hold. Detail below so it is checkable rather than asserted.

Both files are pre-existing on main, not added by this PR.

git cat-file -e origin/main:dag/extdeps/github/checks.dag     -> present
git cat-file -e origin/main:dag/extdeps/github/ci_runner.dag  -> present
git cat-file -e origin/main:dag/extdeps/github/actions_runner.dag -> ABSENT (this is the new one)

The review calls each a "New extdeps module". Neither is. This PR modifies them; it does not add them.

Both are already enrolled — as rows of the frozen legacy manifest.

extdeps_scope_frontier_law states every dag/extdeps/**/*.dag is exactly one of three things: scope_carrier_paths, scope_machinery_exempt_paths, or a row of the frozen legacy manifest at legacy_extdeps_scope_frontier_manifest_path. That manifest is a separate artifact, dag/gunbc/legacy_extdeps_scope_frontier.tsv (401 rows) — not a list inside extdeps_scope_frontier.dag, which is where a grep of the module would look and find nothing.

grep -cxF dag/extdeps/github/checks.dag     dag/gunbc/legacy_extdeps_scope_frontier.tsv  -> 1
grep -cxF dag/extdeps/github/ci_runner.dag  dag/gunbc/legacy_extdeps_scope_frontier.tsv  -> 1
positive control  dag/extdeps/access/aws_iam.dag                                         -> 1
negative control  dag/extdeps/github/nonexistent.dag                                     -> 0

So they occupy the third permitted state. There is no gap.

The placement gate will not refuse them. Per the law, tools.extdeps_scope_placement_gate refuses dag/extdeps files added by this change over origin/main...HEAD. These are not in that set. The cited RED control red_scope_placement_refuses_unrostered_added_extdeps_file is likewise about added files — and about unrostered ones, which these are not.

The genuinely new file was handled exactly as the review asks. dag/extdeps/github/actions_runner.dag is new, declares extdeps_model_scope, and is enrolled in scope_carrier_paths. That is the pattern the review points at, and this PR already follows it for the one file the law binds.

Why I am not making the change anyway. Adding extdeps_model_scope to these two and enrolling them in scope_carrier_paths without deleting their manifest rows would put them in two rosters at once, and the law requires the three to stay disjoint — that is a per-PR merge-gated check, so the suggested edit would red the gate it is meant to satisfy. The correct migration is add-scope + move-to-carriers + delete-the-manifest-row in one change, which is a legitimate piece of work but is the frontier's drain-down, not this consolidation's scope, and it is explicitly the mechanism the law describes for retiring manifest rows.

Happy to be shown wrong if the gate reds on either path — that would be the instrument disagreeing with this reading, and I would take the instrument.

— sent from deep-badger-594

@briansrls
briansrls merged commit 155718e into main Aug 8, 2026
9 of 10 checks passed
@briansrls
briansrls deleted the omega-runner-capacity branch August 8, 2026 05:30
briansrls pushed a commit that referenced this pull request Aug 18, 2026
* Delete the owned-CI control plane at the root

The control plane was built once (#8016), never deployed, and never ran: it
is in no release-bin roster, no systemd unit, no converge membership, and no
.gunbc state exists anywhere. Its only live surface was a /ci route that
answered a permanent 503 by construction. It therefore holds no boundary,
which makes this the cleanest form of the DESIGN 3 delete-first cut: nothing
depended on it, so nothing regresses.

What it was: 1754 lines of hand-written Rust implementing semantics the
substrate already models -- a poll loop, a filesystem queue, a lease, HTTP to
GitHub, and JSON state -- under a declared scaffold whose three dissolve-on
items were all still open. Per DESIGN 7 the seed shrinks toward zero, and
this was the seed growing instead.

Two forks die with it. QueueLease was a nickname for std.temporal_effect
HeldLease, which already carries lease_key, resource_fingerprint,
owner_fingerprint, generation, and a five-armed observed state, and whose
decision_for_held_lease_verdict already yields stale-lease reclaim and
foreign-holder refusal. CiExecutionSubject fused demand and work into one
identity, so a retry had nowhere to live.

Deleted whole rather than migrated, per the standing rule that a replacement
cuts at the root: both Rust files and the bin registration, gunbc.owned_ci,
owned_ci_seed (which existed only to feed the Rust seed), owned_ci_serve,
owned_ci_page, gunbc.ci_execution_plan, the witness module, and the design
doc whose sequencing was the old shape's gravity. Git history keeps all of it
as quarry.

The witnesses are retired rather than re-enrolled, with a receipt: their
subject is the fused subject/run model, and evidence whose only subject is a
rejected shape must not be left standing (DESIGN 4b). The lease obligations
they covered are already witnessed against HeldLease in
temporal_effect_spine_witness_test.

The generated crate-layout artifacts are edited mechanically here rather than
regenerated locally; the drift gate is the oracle for them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GJgwfCsHvvRLD5EAErgP7F

* Drop the /ci route assertions from the roadmap_serve witness

review 52992 (cursor): roadmap_serve_witness_test still imported
CiRunsPageHandler, CiRunDetailPageHandler and CiRunsJsonHandler and asserted
that /ci, /ci/runs.json and /ci/run/{run_id} select them. Those variants,
routes and dispatch arms are deleted by this cut, so the enrolled witness
would not resolve against the updated module. Correct and confirmed by
reading the file; fixed rather than argued.

Why the first sweep missed it: the residual grep searched for the deleted
MODULE names (owned_ci, ci_execution_plan, ci_control_plane). These three
symbols contain none of those strings -- they are symbols removed from a
SURVIVING module. A deletion has two reference surfaces, not one, and only
the first was swept.

The re-sweep covers both: every symbol removed from a surviving module, every
exported symbol of each deleted module, and the route literals. All clean
across dag/, src/ and .github/. No route-count assertion exists that the
three removals would falsify.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GJgwfCsHvvRLD5EAErgP7F

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Aug 19, 2026
… not the emission (#8476)

* Delete the owned-CI control plane at the root

The control plane was built once (#8016), never deployed, and never ran: it
is in no release-bin roster, no systemd unit, no converge membership, and no
.gunbc state exists anywhere. Its only live surface was a /ci route that
answered a permanent 503 by construction. It therefore holds no boundary,
which makes this the cleanest form of the DESIGN 3 delete-first cut: nothing
depended on it, so nothing regresses.

What it was: 1754 lines of hand-written Rust implementing semantics the
substrate already models -- a poll loop, a filesystem queue, a lease, HTTP to
GitHub, and JSON state -- under a declared scaffold whose three dissolve-on
items were all still open. Per DESIGN 7 the seed shrinks toward zero, and
this was the seed growing instead.

Two forks die with it. QueueLease was a nickname for std.temporal_effect
HeldLease, which already carries lease_key, resource_fingerprint,
owner_fingerprint, generation, and a five-armed observed state, and whose
decision_for_held_lease_verdict already yields stale-lease reclaim and
foreign-holder refusal. CiExecutionSubject fused demand and work into one
identity, so a retry had nowhere to live.

Deleted whole rather than migrated, per the standing rule that a replacement
cuts at the root: both Rust files and the bin registration, gunbc.owned_ci,
owned_ci_seed (which existed only to feed the Rust seed), owned_ci_serve,
owned_ci_page, gunbc.ci_execution_plan, the witness module, and the design
doc whose sequencing was the old shape's gravity. Git history keeps all of it
as quarry.

The witnesses are retired rather than re-enrolled, with a receipt: their
subject is the fused subject/run model, and evidence whose only subject is a
rejected shape must not be left standing (DESIGN 4b). The lease obligations
they covered are already witnessed against HeldLease in
temporal_effect_spine_witness_test.

The generated crate-layout artifacts are edited mechanically here rather than
regenerated locally; the drift gate is the oracle for them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GJgwfCsHvvRLD5EAErgP7F

* Drop the /ci route assertions from the roadmap_serve witness

review 52992 (cursor): roadmap_serve_witness_test still imported
CiRunsPageHandler, CiRunDetailPageHandler and CiRunsJsonHandler and asserted
that /ci, /ci/runs.json and /ci/run/{run_id} select them. Those variants,
routes and dispatch arms are deleted by this cut, so the enrolled witness
would not resolve against the updated module. Correct and confirmed by
reading the file; fixed rather than argued.

Why the first sweep missed it: the residual grep searched for the deleted
MODULE names (owned_ci, ci_execution_plan, ci_control_plane). These three
symbols contain none of those strings -- they are symbols removed from a
SURVIVING module. A deletion has two reference surfaces, not one, and only
the first was swept.

The re-sweep covers both: every symbol removed from a surviving module, every
exported symbol of each deleted module, and the route literals. All clean
across dag/, src/ and .github/. No route-count assertion exists that the
three removals would falsify.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GJgwfCsHvvRLD5EAErgP7F

* DESIGN.md is a first-principles doc: cut it 68%, and catalogue the patterns that would have caught the forks

Open threads had become the parallel ledger §6 forbids: 15,336 words across
40 rows, 53% of the file, against ~6,800 words for the reasoning the document
exists for. The file had already diagnosed this once, in one row -- the
five-minute-CI-gate paragraph records its own six-step copy going stale after
the roadmap authority was recut. This generalizes that fix.

Deleted (operator ruling, overriding the enumerate-before-deleting rule):
the whole Open threads section. Four lanes went outright -- SCM economics,
gunb.ai site subsumption, srvN build-cache, srv4 subsumption -- each verified
first against the test that matters: every module it named resolves and its
plan doc exists, so the row was a summary of live carriers and removing it
loses nothing.

Re-homed the nine rows that had no plan doc, bodies verbatim with provenance:
cross-platform-instrument-motion, witness-cost-derives-from-purpose,
secret-version-lifecycle, determinism-boundary-relative,
disk-tier-repeat-resolve-closeout, content-hash-family-grounding, and
parked-questions for the three too small to warrant a document.

Extracted two doctrines that were principle-shaped only from a distance:
replacement-migration (4,405w, 77% of §3 and 31% of the whole file) and
scaffold-admission (792w from §5). Each leaves a statement of the principle
and a link; the procedure, carve-outs, disposition census, terminal receipt
and dated receipts live in the doc. §3 is 5,729 -> 1,257, §5 2,344 -> 1,755.

Added "The recurring patterns": realization, materialization, leasing and
fencing, reconcile, allocation, authorization, identity and keying, evidence
and claims, observation-to-verdict, dissolution. Each carries its authority
and a fork test, because that is the part that does work -- a census of one
lane found eleven forked carriers, and every one was introduced by an author
who did not know the pattern already had an owner. "If you are writing a
record with a generation in it, you are re-declaring leasing" would have
caught LeaseIdentity before it dropped owner_fingerprint and left the receipt
fence with no owner to compare.

Also lands three new design notes from the fabric/CI-minutes work:
fabric-concept-reconciliation (the authority census), ci-minutes-product-design,
floor-semantic-artifact-design.

29,084 -> 9,340 words. No section over 1,800. Three links, all resolving.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012q31BK3okLA8vG4kdTWtBf

* Revert the DESIGN.md hand-edit: it is a generated artifact, and I edited the emission instead of the model

DESIGN.md carries `merge=generated-artifact` in .gitattributes and is emitted
from dag/gunbc/design_document.dag via expected_design_md, consumed by
gunbc.generated_artifact_emit. The previous commit hand-edited the emitted
file, which is out-of-band actuation -- hand-applying an actuator with a
commit wrapped around it -- and left live model/emission drift: the model
still carried every Open threads row the emission had lost, so the next regen
would have silently reverted the whole cut.

Caught by checking .gitattributes before flipping the PR to ready. It should
have been the first check, not the last.

This restores DESIGN.md to the model's current output. The eleven new
docs/plans/*.md files are unaffected -- they are hand-authored and were never
generated -- so the re-homed lanes and the two extracted doctrines stand. The
cut itself is re-applied in dag/gunbc/design_document.dag, where it belongs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012q31BK3okLA8vG4kdTWtBf

* DESIGN.md: cut to first principles, at the model rather than the emission

Operator ruling: DESIGN.md is a first-principles document; per-lane status
in it is a dual representation. 27,516 -> 9,279 words. Every edit is to
dag/gunbc/design_document.dag; DESIGN.md is regenerated from it, so the
committed bytes are a fixed point of the model rather than a hand-patched
file that happens to match.

Deleted: the Open threads section, 37 per-lane status rows. Ten lanes that
named no design document were re-homed to docs/plans/ first (the other 27
already cited one), so nothing was dropped without a home.

Compressed to principle, with the operative detail moved out rather than
deleted: the section 3 replacement-migration rule (why leaf-upward editing
creates authority before removing any; the attractor and its A3 grounding;
delete-first with the deletion as the census; the two carve-outs; what
"atomic" means) now cites docs/plans/replacement-migration-doctrine.md for
the loop, the disposition census, the cut search and the receipts. The
section 5 scaffold ruling keeps the rule -- a dissolution condition is a
lifecycle fact, not a permit; the default landing state is the final
construction -- and cites docs/plans/scaffold-admission-doctrine.md for the
verdict vocabulary and the out-of-band-actuation case. Section 3's opening
paragraph keeps interface/realization/policy as three facts and drops the
worked extdeps detail.

Four documentary citations retired with the paragraph that cited them
(three body-lowering refs, the five-minute-CI-gate ref); their DeclarationRef
declarations survive in doc_graph_roots where other consumers use them.

Evidence, all green by execution on this tree:
  - documentary_refs_generated_document_renders_the_rows: true
  - documentary_refs_population_is_the_union: true
  - documentary_refs_renamed_system_refuses: true
  - documentary_refs_ambiguous_system_refuses: true
  - doc_graph_bind_identities_unique / works_refs_carry_symbols /
    production_doc_binds_all_carry_a_retirement /
    hand_authored_slugs_not_registered: true
  - compile-clean gate (3 roots, primary-precedence): 0 blocking errors

The two perturbation controls were RED for one edit before this landed:
their specimen was a body-lowering symbol the document no longer cites, so
they were retargeted onto the surviving citation. That red is the receipt
that they still discriminate.

Orphan wall: the ten re-homed documents are registered as HandAuthoredDocBind
rows, each naming a verified carrier symbol and a retirement condition. That
moves doc_graph_orphan_count 16 -> 4. The residual 4 orphans and all 5
dangling links predate this branch (docs/plans/ci-selection-vs-scheduling.md
is deleted but still linked from ROADMAP.md and four plans); not fixed here,
and reported rather than absorbed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012q31BK3okLA8vG4kdTWtBf

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.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