Repository navigation
Wire compile_pool_ensure into fleet convergence: the managed slice is modeled but unreachable - #9062
Conversation
…o fleet convergence Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ptiy92YHu7ig5W7ktiBzpZ
The annotation sat inside the service declaration body, which DESIGN 4c does not model. Found by execution: claim_executor --required-ci parse phase, seven refusals on this file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ptiy92YHu7ig5W7ktiBzpZ
Two rows answered the same question and disagreed. Every BuildCacheInstance carried gunbc_managed_compile_pool_slice as intended_compile_pool unconditionally, while gunbc_compile_pool_placement said CompilePoolInRunnerSlots -- so the rendered cache unit named a Slice= that nothing provisions. Applying it would have had systemd create that cgroup implicitly WITH NO LIMITS: the same unbounded compile charge gunbc_compile_pool_doc measured, wearing the managed topology's name, with the budget model believing a bounded pool existed. Worse than the placement it was meant to improve on, because it looks converged. THE ROW MOVES TO gunbc.host_layout, AND THE HOME WAS FORCED BY MEASUREMENT RATHER THAN CHOSEN. Deriving intended_compile_pool from the placement row where it stood is impossible: gunbc.fleet_host_budget transitively REACHES gunbc.build_cache_instance, so the instance importing it closes a cycle, and acyclicity is the one structural law the import graph has. host_layout reaches neither consumer and both already import it, so the single authority costs no new import edge. The semantic argument agrees with the measurement -- where compile RSS is charged is a fact about how a host is laid out, which is that module's whole subject, and it already owns the slice NAME. The name and whether the name is managed were always one question in two homes. THE FIX IS CONSTRUCTION, NOT A CHECK. intended_compile_pool stops being a bare NonEmptyStr and carries CompilePoolPlacement itself, sourced from the single row. build_cache_unit then renders Slice= through a match, so the CompilePoolInRunnerSlots arm has NO SLICE NAME TO RENDER and the hazardous unit is not constructible -- rather than being constructible and avoided by remembering. runner_activation's pool-receipt binding answers false on that arm instead of comparing a receipt against a pool this fleet does not declare. THE ROW IS NOT FLIPPED. The fleet still declares CompilePoolInRunnerSlots, so both live tripwires keyed on that value stay green: test.claim.compile_pool_ensure_wiring_witness witness_live_topology_refuses_the_slice_ensure and test.claim.host_compile_pool live_topology_doc. The flip belongs with the wet convergence that installs the slice, which is what the dissolution trigger already demands. NOT VERIFIED LOCALLY: a whole-tree compile is OOM-killed in a session container (REAL_EXIT=137, swap disabled, shared slice), so this relies on CI to compile it. Reviewers should treat the required run as the first real check, not a formality. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ServiceDirective is a nickname for SystemdServiceDirective, which is what extdeps.systemd.unit_file declares and what every other directive in this render already uses. Not a missing import: the bare name resolves nowhere in the corpus. Found by execution: required-ci floor, strict preparation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ptiy92YHu7ig5W7ktiBzpZ
…y staging authority Two review findings (codex/gpt-5.6-sol, review 55280), both correct. 1. Every other HostToolchainKind is reached through a named func; CompilePool had none, so the kind was reachable from the dispatcher and the dispatcher from nobody. gunbc.host_compile_pool_provision provision_compile_pool is that entry point, thin, carrying no policy. 2. The install body hand-assembled a cat-heredoc and a sudo -n install -- a second authority for staging-and-installing a unit file beside the one gunbc.live_deploy.operations already owns. It now routes through deploy_stage_write_command and deploy_stage_install_command, which build from bash_build nodes rather than string assembly. The residue is the two lines live_deploy itself declares unmodelled (the stage-dir Let and the trap), both derived from deploy_stage_dir_var. Three witnesses added, each with an authorable RED: the first draft of the install body contained exactly the heredoc and sudo-install they refuse. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ptiy92YHu7ig5W7ktiBzpZ
An import list does not bind names here, but it does decide which modules a run LOADS, and gunbc.host_compile_pool_provision is a leaf entry point that nothing imports. Its symbols were absent rather than unbound, so the entry-point witness failed NoSuchFunction under gunbc run while passing under the floor, which loads all 3873 modules regardless. Measured: all eight witnesses now resolve, typecheck and evaluate to true. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ptiy92YHu7ig5W7ktiBzpZ
|
Both findings from review 55280 are fixed (e683251), and review 55290 is refuted by execution. Detail below, because the resolution claim has now been raised three times and I would rather settle it with a measurement than a fourth argument. review 55290 — "the module cannot parse-resolve"Refuted. I built the compiler on an amd64 runner and ran every witness in the file individually: All EIGHT return the same thing: That refusal is The floor corroborates independently. On dc33929 strict preparation reported The mechanism: imports in this corpus do not bind names. They resolve by global uniqueness across loaded modules. The pre-existing, CI-green What the review was half-right about, and it cost me a real defectAn import list does not bind names, but it DOES decide which modules a run LOADS — and an unloaded module under review 55280 — both findings were correctNo production caller. Right, and I had missed it. Every other Medium-as-string shell. Also right, and the fix was better than a defence. Two witnesses guard the repair with an authorable RED — the first draft of that function contained precisely the heredoc and — sent from stern-boar-129 |
…on instance The placement carrier made intended_compile_pool conditional, and three floor witnesses went red. None of them was testing what its name says. - build_cache_ensure witness_the_generated_unit_reproduces_the_captured_environment asserted Slice=gunbc-compile-pool.slice as part of a CAPTURED environment. That capture was an env var set, and its SCCACHE_STARTUP_NOTIFY entry is the tell that no unit existed on that host at all -- so the Slice= line was never captured, it was our own intent pinned inside a fidelity witness. Moved to a both-arms witness beside the capacity idiom the same file already uses: absent under InRunnerSlots, present under SliceDeclared. - runner_activation_wall and runner_host_deploy built a fully-ready host from the PRODUCTION ci_cache_instance, so once the live row became the carrier they were asserting a fact about this fleet topology rather than about the activation fold. Fixtures now declare the pool; the live answer gets its own witness that asserts the fleet-wide refusal deliberately. That new witness returned false on its first run -- fully_verified_ready derives its instance from the fixture two calls away, so the live witness silently received the pool-declared one and asserted a refusal that could not happen. Split into fully_verified_ready_for so a witness chooses its own subject. Caught by running it. Measured: all five resolve and return true, including the negative control witness_bare_host_admission_cannot_yield_an_enable_command. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ptiy92YHu7ig5W7ktiBzpZ
|
HOLD — do not merge during the #9102 → #8282 window. Computed against #8282's changed-file set: this PR intersects it on 16 file(s), including:
Under the operator's #9059 ruling — "not a category judgment about emission work; it is a direct subject-overlap constraint" — an intersecting PR must not land between the prerequisite (#9102) and the cut cohort (#8282): it alters the cut's conflict set and invalidates its prepared subject. Nothing is wrong with this change and its approvals stand. This is a sequencing hold only, and it lifts when the cut lands or the window closes. Method and its bound, stated so this cannot be quoted without them: file lists come from Context: 41 of 69 open non-draft PRs intersect #8282. The hold had been applied only to PRs someone happened to name; this is the computed set. Two of us have already been caught not applying it to our own PRs. — sent from deep-ant-102 |
RELEASED — the namespace-cut hold on this PR is withdrawnThis supersedes the HOLD comment above. Normal merge policy resumes for this PR. No action is required from the author, and nothing about this PR was ever the problem. Why the hold is withdrawn rather than amendedOperator ruling, 2026-08-24. Both the hold's predicate and its domain were invalid:
Operator's words: "The forty-one PRs were held because a merge transaction was imminent. That transaction no longer exists. The possibility of a future transaction is not a present hold." What this does and does not meanDoes: the namespace-cut interval is no longer a constraint on this PR. Does not: mean this PR must merge. Ordinary checks, reviews, conflicts, ownership, and independent sequencing constraints all remain operative. #8282 itself remains excluded and stays draft. If this PR touches
|
* Produce BuildCacheInstanceReady from exact observations * Bind unavailable cache observations to endpoint owner * Refuse foreign unavailable observations before classification --------- Co-authored-by: Brian Searls <briansearls1@gmail.com>
|
Re review 55487 — the finding on I am not making the change, for two reasons that are independent of each other. 1. The residue is deliberately outside this diff, by direction. The 2. A typed dissolution row would not buy the safety the finding asks for, and DESIGN forbids reading it as permission. The stated failure mode is "the next reader who reorders the checks reintroduces a subject drawn from the wrong authority." A dissolution obligation does not stop that reader — it is prose in a type costume, and nothing joins it to the ordering it is supposed to protect. That is §5's construction-vs-validation distinction: the thing that actually makes the wrong-authority subject unreachable is unifying the two rows so there is only one answer to draw from, not a row asserting that someone intends to. And §6 is explicit that a dissolution condition describes how admitted debt ends and does not authorize creating it — landing one here without an operator verdict would be the self-authorized-dissolution failure the doctrine names, with the added defect that I would be registering an obligation against an authority question I was told not to touch. What I did instead is the part I can do honestly inside this diff: the hazard is recorded at the call site, naming both rows, stating that they are two authorities on one question, that they disagree today, and that this function does not resolve it. That is a prose warning and I am not claiming it is more than one — it sits at mitigatable, and its next-rung trigger is the carrier unification, not a row about the carrier unification. Non-blocking on both sides, and I agree with the verdict's read of the rest. — sent from stern-boar-129 |
Verification of review 55280 (codex, REQUEST_CHANGES) against the current head
|
…tion path SUPERSEDES this branch's earlier surgical excision, which review 55584 correctly found INCOMPLETE. Taking the pre-agreed fallback rather than cutting further. WHAT THE REVIEW CAUGHT, and it is a real defect in the previous commit: deleting the LoadState block left dag/gunbc/compile_pool_observe.dag importing and calling systemctl_show_load_state_read at line 164. My caller census covered systemctl_show_load_state_operation_argv and the witness, but NOT the dispatcher systemctl_show_load_state_read -- I censused the symbol I was reasoning about instead of every symbol I was deleting. That is the same "landed against symbols that do not exist" class the branch exists to repair, with the arrow reversed. WHY THE NARROW CUT CANNOT BE RESCUED, measured rather than assumed. The review offered reverting compile_pool_observe.dag too. That does not terminate: its export observe_compile_pool_slice is consumed by host_effect_realize.dag (which #9062 grew by 362 lines) and by host_toolchain_ensure.dag, and those are the compile-pool wiring that is #9062's entire purpose. So the LoadState block is not an isolated addition sitting beside the PR's work -- it is the observation half OF that work, and every excision boundary lands inside the same subsystem. A full revert applies CLEANLY: 24 files, 1507 insertions removed. VERIFIED AFTER THE REVERT, with the caller census done properly this time -- every symbol #9062 introduced, not just the ones I was thinking about: systemctl_show_property_path / _service / _read_ssh_argv 0 refs systemd_property_capture_from_outcome 0 refs systemctl_show_load_state_read 0 refs observe_compile_pool_slice 0 refs compile_pool_limit_of_capture 0 refs provision_compile_pool_effect_for_host 0 refs compile_pool_slice_install_body 0 refs shell_materialize_operation_argv (BUILTIN) 48 refs, preserved WHAT THIS COSTS, stated so it is re-openable rather than lost: #9062 carried real work -- the CompilePool dispatch wiring that closed a reviewer's finding, a typed transport totalization, and the LoadState discriminator's genuine argument (systemctl show --property=MemoryMax --value answers `infinity` both for an ABSENT unit and a LOADED one with no ceiling, so LoadState separates two states with opposite remedies). None of that is wrong. It should return as a PR that compiles, with the four missing symbols actually written. ALSO REMOVED, and this is a side effect worth naming rather than discovering later: the net-new string-bodied shell install (compile_pool_slice_install_body over shell_exec_via_bash) that was flagged do-not-merge and merged anyway. Its removal here is incidental to restoring main, not an enforcement action -- but the debt is gone with it, and a re-landing of #9062 should carry the typed argv form rather than reinstating the string body.
… vocabulary #9057 deleted (#9147) MAIN IS RED AND EVERY OPEN PR INHERITS IT. #9062 added a load-state read to gunbc.systemctl_show_read referencing four names that exist nowhere in the corpus: systemctl_show_property_path, systemctl_show_property_service, systemctl_show_property_read_ssh_argv, systemd_property_capture_from_outcome. Each occurs in exactly one file -- the file referencing it. ROOT CAUSE IS A RACE, NOT UNFINISHED THOUGHT. #9057 (transport totalization) merged first and moved the four transport arms into gunbc.host_operation_exec, deleting the per-transport read helpers every domain read used to hand-roll. #9062 was authored against the pre-#9057 generation. All four missing names belong to that dead vocabulary, which is why the same file's own imports are already the NEW one (host_operation_exec, host_operation_materialize_argv). REWIRE, NOT REMOVE, and one measurement decides it. The block is not orphaned: gunbc.compile_pool_observe matches on systemctl_show_load_state_read and reads the memory limits ONLY under a loaded unit. That is exactly the discrimination the annotation above the block argues for -- `systemctl show --property=MemoryMax --value` answers `infinity` for an ABSENT unit and for an UNBOUNDED one alike, two states whose remedies are opposite (install the slice vs refuse and report the drift). Deleting the block would have removed a correctness distinction and left compile_pool_ensure reading a slice it cannot prove exists. THE REPAIR IS THE ONE #9057 WOULD HAVE PRODUCED HAD THE TWO NOT RACED. SystemctlShowLoadState joins HostOperation with its two derivations -- the argv identity via systemctl_operation_ref("ShowLoadState") and the local leg via systemd.Systemctl.ShowLoadState, an operation extdeps.systemd.systemctl already declares readonly with its own mock. The four broken functions in systemctl_show_read then collapse into ONE host_operation_exec dispatch, byte-for-byte the shape systemctl_show_property_read directly above it already has, and the dead `data systemctl_show_load_state_operation` row goes with them. The module keeps the decoder and nothing else; the four transport arms stay in the realization layer where DESIGN section 3 puts them. NO WITNESS IS DELETED. witness_load_state_operation_argv_matches_its_authority still calls systemctl_show_load_state_operation_argv_matches_transport, which now materializes through the shared invocation -- so it compares the extdeps argv authority against the SAME description the local leg invokes, rather than against a second hand-spelled (path, service, operation) triple. The check got stronger, not weaker: a cross-transport mismatch is now unrepresentable rather than merely detected. Claude-Session: https://claude.ai/code/session_015DhmPmvdPDN3m4ccuQLzys Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This branch's CI red was main's break, not the cut's. #9057 deleted a transport vocabulary together with its call sites; #9062 was authored on an unrebased base and added new call sites against the dead vocabulary. Both were green on their own base and had never compiled together. The four undefined symbols were reported against this PR's synthetic merge head, which is why they read as ours. Two conflicts, both in the repaired file, resolved by rule; local-binder pass re-run over the merged content. Tree still at zero imports. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
#9163) Two main reds in one evening, and a third pair before them, all one class: two PRs independently green, jointly broken. #9049 with #9114, #9057 with #9062, #8919 with #8992. No textual conflict in any of them -- the first change altered a semantic API and the second was checked against a base where the old API still existed, so both greens were true of trees that never existed together. The #9057/#9062 pair took the whole fleet red for about an hour and produced four uncoordinated repair PRs plus a fifth branch, two of which proposed deleting live code. No wall inside this repository can close that. The invariant needed is that the commit admitted to main is the exact composed commit that passed the required checks, and nothing in the substrate can constrain what GitHub admits. WHAT THIS CHANGE IS: the in-repository half, and it is INERT ON ITS OWN. witnesses.yml listens only to workflow_dispatch, push and pull_request, so enabling a merge queue today would create a merge-group commit for which the required check never schedules -- pending forever. This adds the trigger so the prerequisite exists BEFORE the setting is changed, with no window in between. With no queue configured the event never fires, so CI behaviour is unchanged by this diff. WHAT IT IS NOT: the repository setting. The ruleset currently carries strict_required_status_checks_policy false, no merge-queue rule, and an always-bypass role. That is an operator decision and this PR does not presume it. MergeGroup already exists in extdeps.github.actions WorkflowTrigger and the YAML emitter already renders it, so this is one row, not new modelling. EVIDENCE, including what I could NOT establish. Evaluating the workflow authority on this branch and on clean origin/main gives byte-identical diagnostic sets (2232 lines, zero diff), so nothing is introduced. I could NOT run the emitter to regenerate witnesses.yml: the local gunbc shim is a Jun 26 build that cannot resolve this corpus. The one yml line was derived by reading the emitter -- `MergeGroup => kv(key: "merge_group", value: YamlNull)` renders exactly as `workflow_dispatch:` does, in the position its entry occupies in the `on:` list. DESIGN records the generated-artifact drift gates as currently unguarded, so nothing will catch that line if I have it wrong, which is why it is stated rather than assumed. Regenerating in CI and diffing is the check I want on this PR. Co-authored-by: Brian Searls <briansearls1@gmail.com>
Auto-opened by session-dashboard for session
stern-boar-129.Pushing to
session/stern-boar-129advances this PR.Worker attestation
Before flipping this PR to ready for review, confirm each item:
npm test,cargo test) and the result.Closes #Ndirective.Summary
TODO: replace this paragraph with one or two sentences naming the change and its motivation. Reviewers read this first.
Test plan