Repository navigation
CI shell→dag audit: census the missed sites + generalize the invariant (config is a language too) - #7159
Merged
Conversation
A 2026-07-24 three-facet CI audit found five CI `run:` shell sites that landed
after the census's #78f43c38 grounding and are tracked only at the site (rich
in-code notes) but never rolled up into §4/§5:
ci_spec.dag · ci_fmt_gate_line (→ cargo.Build.Fmt, §5.B call-the-op)
ci_spec.dag · gunbc_ci_deploy_invoke (E-emit)
ci_spec.dag · gunbc_ci_heal_regen_invoke (E-emit)
ci_spec.dag · ci_heal_git_add_lines + commit/push (E-emit → typed git.Core.*)
ci_materialization.dag · ci_sccache_provider_shell_injection
(E-emit + a §5 ABSORBING-FALLBACK: the `if sccache --show-stats` guard
silently skips caching when the daemon is down — dissolves to a mandatory
provisioning-ensure, the sibling of the level-2 `-u RUSTC_WRAPPER` fallback
removed on #7138)
Also records the §5 absorbing-fallbacks INSIDE the CI scripts that the census
tracked the scripts but not the widens for (git rev-parse … || pwd ×17;
git fetch … || true; the toolchain-unresolved cache-poison slug; the
CARGO_BUILD_JOBS=1 fleet-pressure mask), each owed a modeled outcome on migration.
And cross-references the ADJACENT (not shell-string) model↔realization forks the
same audit found — toolchain isolation (ToolchainEnvIsolation modeled but the
workflow hand-spells per-job isolation → the rustup ETXTBSY race in a prose note),
GHA cache key, artifact upload/download, permissions — which belong to the
model↔realization-fork thread / roadmap 2-emit-partition, noted here only so they
aren't lost across the seam.
Keyed on file+symbol per the §4 convention; no code changes, doc-only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The doc's thesis is "the intent names no language" (shell strings). The 2026-07-24 CI-workflow audit found the same §3/§4 violation in a second sink that isn't a string — hand-spelled CONFIG (toolchain isolation, GHA cache key, action version/components, permissions) whose modeled authority already exists (ToolchainEnvIsolation, gha_actions_cache_facts, ToolchainCapability, std.effect_grant) but which the workflow emit hand-picks instead of deriving. Adds a principle-only section that sharpens the invariant to "the EMITTER names no concept": - the second sink (config, not strings) — same disease, one sink over; - the litmus "opaque to emission" — if the emitter special-cases a concept (it has an "isolate this job" branch), the concept is forked emitter logic, not a fact; - the bespoke ci_workflow/ci_yaml_emit is itself the fork — there should be ONE emit(intent, target); a second workflow emitter is the N×M trap at workflow scale (roadmap 2-emit-partition already targets the general-emit end-state); - config-opacity + the multi-target Python litmus are the same property (target is a parameter); - the wall generalized: a lens that reds config hand-written where a model exists. Respects the doc's no-second-census discipline — states the principle, references census §4.I for the sites. Doc-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
gunbai-bot Bot
pushed a commit
that referenced
this pull request
Jul 24, 2026
…ovisioning path
The srvN subsumption spine had TWO authorities for "install sccache on a fleet
host", firing on the same host in sequence:
P1:runner-deploy-slot -> extdeps.cache.sccache.sccache_install_script
pinned v0.15.0 tarball, per-arch sha256 verified,
lands at /usr/local/bin/sccache
P1b:build-cache-provision -> hand-rolled `sudo -n apt-get install -y sccache`
unpinned, unverified, plus a systemd user unit whose
ExecStart=/usr/bin/sccache
So the unit pointed at a path the modeled install never creates: the daemon could
not start, the read-back refused, and the fail-closed wall was correctly refusing
a state the EMITTER had created by forking the concept (the "emitter names no
concept" shape recorded in the shell->dag census 4.I / #7159).
- sccache_installed_binary_path is now the single authority for where the cited
release lands; both the install script and the unit ExecStart read it.
- The ensure arm calls sccache_install_script; the apt fork is deleted.
- Arch is DERIVED from the effect target's own ComputeHost CpuFacts.architecture.
sccache_release_arch_token / sccache_release_digest are partial over the
Architecture coproduct, so an arch the cited release does not publish yields a
typed NotConverged. No default arch (5: never fabricate a plausible binary).
- The misconfigured-fragment classifier is a FOLD over the cited roster
sccache_misconfigured_log_fragments instead of three unrolled if/elif branches,
so citing a fourth fragment costs zero emitter edits.
- NEW path-authority guard: CI consumes the cache as bare `sccache` on PATH
(RUSTC_WRAPPER=sccache), so provisioning the modeled binary is not sufficient —
a healthy sccache earlier in PATH is the two-authority state itself and is
invisible to an absolute-path read-back. It now REFUSES, typed and located.
- loginctl enable-linger: a systemd --user manager dies with the provisioning ssh
session, so the read-back would green on a daemon already gone. Does NOT settle
open question 1 (user vs system scope) — that stays operator-open.
- The refusal is LOCATED: build-cache failures reported themselves as
OsInstallActuatorToolchainEnsure because they reused a fold that hardcoded the
effect name in its header. The header is now a parameter.
- ci_sccache_provider_shell_injection's bare `if` gained an else emitting a
counted CiSccacheProviderReceipt naming the host. Deliberately LOUD, NOT a
refusal: STEP 2's fail-closed flip is operator-sequenced after a live T4
read-back, and refusing first would red the fleet.
- ci.yml + falsifier.yml regenerated from the model (main_wet), 3 lines each.
Green by execution:
PASS host_build_cache_provision_design_witnesses (claim_batch, 396 modules /
7232 items in closure) — 8 new assertions incl. the emitted script contains the
cited release URL and NEITHER apt-get NOR /usr/bin/sccache; ExecStart equals the
install-path authority; the classifier covers every cited fragment AND contains
no elif (re-unrolling reds); arch token/digest Absent for Riscv64/Wasm32; a host
with no readable CPU refuses realization; srv1's real row still resolves aarch64
so the refusal path is not trivially always-on.
Direct bash execution: emitted script syntax-valid; classifier fold classifies
all three cited fragments and falls through on a fourth input; path guard
refuses a shadowing binary (exit 1) and passes when nothing is on PATH.
The two new wet witnesses are enrolled in bin_witness_wet_entries — that roster is
keyed per test fn, so they would otherwise have been orphans (enrolled, zero
executions).
NOT done here, and not claimed: the live leg. This container reaches srv1/srv2/srv4
on :22 but holds no fleet ssh key and no ADC, so P1b has NOT been run against a
real host — that is gap A2 (reach-secrets) in fleet_subsumption_manual_gaps. This
lands at T1/T2; T3/T4 receipts need an operator-supplied credential.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
briansrls
added a commit
that referenced
this pull request
Jul 25, 2026
…ovisioning path (#7170) * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * srvN build-cache: de-fork the sccache install authority on the P1b provisioning path The srvN subsumption spine had TWO authorities for "install sccache on a fleet host", firing on the same host in sequence: P1:runner-deploy-slot -> extdeps.cache.sccache.sccache_install_script pinned v0.15.0 tarball, per-arch sha256 verified, lands at /usr/local/bin/sccache P1b:build-cache-provision -> hand-rolled `sudo -n apt-get install -y sccache` unpinned, unverified, plus a systemd user unit whose ExecStart=/usr/bin/sccache So the unit pointed at a path the modeled install never creates: the daemon could not start, the read-back refused, and the fail-closed wall was correctly refusing a state the EMITTER had created by forking the concept (the "emitter names no concept" shape recorded in the shell->dag census 4.I / #7159). - sccache_installed_binary_path is now the single authority for where the cited release lands; both the install script and the unit ExecStart read it. - The ensure arm calls sccache_install_script; the apt fork is deleted. - Arch is DERIVED from the effect target's own ComputeHost CpuFacts.architecture. sccache_release_arch_token / sccache_release_digest are partial over the Architecture coproduct, so an arch the cited release does not publish yields a typed NotConverged. No default arch (5: never fabricate a plausible binary). - The misconfigured-fragment classifier is a FOLD over the cited roster sccache_misconfigured_log_fragments instead of three unrolled if/elif branches, so citing a fourth fragment costs zero emitter edits. - NEW path-authority guard: CI consumes the cache as bare `sccache` on PATH (RUSTC_WRAPPER=sccache), so provisioning the modeled binary is not sufficient — a healthy sccache earlier in PATH is the two-authority state itself and is invisible to an absolute-path read-back. It now REFUSES, typed and located. - loginctl enable-linger: a systemd --user manager dies with the provisioning ssh session, so the read-back would green on a daemon already gone. Does NOT settle open question 1 (user vs system scope) — that stays operator-open. - The refusal is LOCATED: build-cache failures reported themselves as OsInstallActuatorToolchainEnsure because they reused a fold that hardcoded the effect name in its header. The header is now a parameter. - ci_sccache_provider_shell_injection's bare `if` gained an else emitting a counted CiSccacheProviderReceipt naming the host. Deliberately LOUD, NOT a refusal: STEP 2's fail-closed flip is operator-sequenced after a live T4 read-back, and refusing first would red the fleet. - ci.yml + falsifier.yml regenerated from the model (main_wet), 3 lines each. Green by execution: PASS host_build_cache_provision_design_witnesses (claim_batch, 396 modules / 7232 items in closure) — 8 new assertions incl. the emitted script contains the cited release URL and NEITHER apt-get NOR /usr/bin/sccache; ExecStart equals the install-path authority; the classifier covers every cited fragment AND contains no elif (re-unrolling reds); arch token/digest Absent for Riscv64/Wasm32; a host with no readable CPU refuses realization; srv1's real row still resolves aarch64 so the refusal path is not trivially always-on. Direct bash execution: emitted script syntax-valid; classifier fold classifies all three cited fragments and falls through on a fourth input; path guard refuses a shadowing binary (exit 1) and passes when nothing is on PATH. The two new wet witnesses are enrolled in bin_witness_wet_entries — that roster is keyed per test fn, so they would otherwise have been orphans (enrolled, zero executions). NOT done here, and not claimed: the live leg. This container reaches srv1/srv2/srv4 on :22 but holds no fleet ssh key and no ADC, so P1b has NOT been run against a real host — that is gap A2 (reach-secrets) in fleet_subsumption_manual_gaps. This lands at T1/T2; T3/T4 receipts need an operator-supplied credential. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * WIP: srvN subsumption * Relocate the PATH-shadow judgement into the model; shrink the script back to 6 builders Operator review: this module is a DECLARED SCAFFOLD whose dissolution trigger says it should be going away, and the shell->dag census keys it as an A5 `decompose` row (host_effect_realize.ProvisionBuildCache), deferred 2026-07-22 — real debt, NOT done. The previous commit added a 7th `build_cache_*_body` to it. That is exactly the failure the census predicts in prose: "while a raw-shell builder exists in the tree, LLMs copy it — one anemic concat(\"sudo -n \", …) becomes ten ... assume anything left behind is duplicated/triplicated" The finding (a healthy sccache earlier in PATH is the two-authority state, and no absolute-path read-back can see it) is real and kept. Only its LOCATION was wrong. Model now owns the judgement (gunbc.host_build_cache_provision): - DaemonPathShadowed { resolved, expected } on BuildCacheDaemonObservation — carries BOTH paths so the refusal is located, not merely typed. - RefusalPathShadowed on BuildCacheProvisionRefusal. - verdict fold refuses fail-closed; the gate accepts only that refusal. - the widen sketch fabricates Converged on shadow, so the RED control has a real forbidden behaviour to reject rather than asserting a tautology. Script only OBSERVES, and SHRANK: - build_cache_path_authority_guard_body DELETED. - the observation became build_cache_path_authority_lines() -> List<String>, appended into the two bodies that already existed (observe + read_back), so both checkpoints survive with no new builder. - builder count 7 -> 6, matching the census row exactly. Routing (why shell was the wrong home at all): this site is RUNTIME-PRESENT — it realizes through host_effect_apply_gated on LocalShell/SshShell — so per the census routing decision its end state is a typed effect-plan with NO bash emitted. The deploy-preflight precedent is the target shape: a typed predicate over captured values (Not{StrEq}, never a minted StrNeq). There is no `command -v` typed op in extdeps/os today; that is a §5.A new-op row, and §5.E's TransportScript construction wall — the thing that would have made my 7th builder a type error — is still awaiting the operator's wall-first-vs-migrate-now decision. Census standing recorded ON THE CARRIER (host_build_cache_provision_script_census_ row_note), not in a PR description that evaporates: A5 decompose, deferred, runtime-present, and the standing constraint that this module may SHRINK but must not GROW — a new *_body here is a census regression even when the behaviour it adds is correct. Green by execution (claim_batch): PASS host_build_cache_provision_design_witnesses — adds path-shadow fail-closed refusal (reason names both paths), the widen-rejected RED control, and a check that the path-authority observation lives in the two existing bodies rather than a separate builder. PASS provision_read_back_failure_not_converged_by_real_execution PASS provision_path_authority_refuses_healthy_shadowing_sccache PASS provision_path_authority_passes_when_no_sccache_on_path (--wet; the read-back witness's fake binary moved OFF PATH so it exercises the read-back arm rather than short-circuiting on the shadow check, and asserts path_authority=SHADOWED is ABSENT.) No ci.yml impact — the provisioning script is not part of the emitted workflow. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * Fix compile-clean whole-tree failure: bare `Owned` variant is ambiguous The new host_authorized_keys_reconcile witness constructed a bare `Owned` value in its RED-control helper. `Owned` is defined in TWO modules (gunbc.ownership and extdeps.languages.rust.types), so it resolves under scoped claim_batch (small pool) but is undefined/ambiguous under the whole-tree compile-clean gate (--dependency-pool-index primary-precedence), which the PR triggered by touching ci.yml (outside the selectable universe -> whole-tree baseline). Derive the "always Owned" lie from authorized_key_ownership(macbook) instead of naming the ambiguous variant. Both symbols are unique. Verified: the exact gate compile now has zero hard diagnostics; all 6 witnesses still PASS including the lying-ownership RED control. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * Ground the IP address + network-host leaves (step a, reach lane) Continues the transport decomposition's leaf-grounding, toward reach.dag. - extdeps/network/ipv6.dag: structured Ipv6Address (eight Int-where-range(0,65535) groups, the Port bound idiom; RFC 4291/5952 cited). Type + constructor grounded; the RFC 5952 string codec is STAGED with a dissolution trigger (reuses base16, zero fleet v6 consumers — §6, don't build for a host that doesn't diverge). - extdeps/network/address.dag: IpAddress = IpV4 | IpV6, the honestly-closed coproduct. render_ip_address is fail-closed on v6 (returns Absent, never a fabricated v6 string, §5). - extdeps/network/endpoint.dag: NetworkHost = HostByName | HostByAddress (reuses the already-grounded HostName + IpAddress — this is the leaf ssh_host grounds onto), SocketAddress reusing std.types.Port verbatim. - network_address_host_witness_test: 7 witnesses green, incl. the v6-render-refuses fail-closed control. All new names unique; whole-tree compile-clean. Next: reach.dag (OpenSSH ProxyJump cited; srv3 = ProxyJump via srv2 interim). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * srv3 network reach: model the srv2 ProxyJump interim, grounded live; census-note honesty srv3 is a fabric-only target; the operator-sanctioned interim is a ProxyJump through srv2 (reachable) standing in for the not-yet-working fabric. New gunbc.fleet_reach models this on the extdeps.network.reach model built earlier in this lane: - srv3_reach = ProxyJump{jumps:[srv2], target:srv3}, grounded on extdeps.network.ipv4 (grounded srv2/srv3 Ipv4Address rows — the convergence target the fleet_intent_network bare-string endpoint residual dissolves onto, cross-linked both ways so the transitional dual representation is marked debt toward one authority, not a fork). - srv3_reach_fabric_intended = FabricTunnel{srv3} — the dissolution target made a real value that HONESTLY refuses realization today (the §5 control). - GROUNDED LIVE 2026-07-25: from srv2, an ssh handshake to srv3:22 returns Permission-denied for every probed user — a refused AUTH, not a network failure, which PROVES the network reach via srv2 is realizable while the shell/auth transport is fail-closed (srv2's key trusted by no srv3 user — the A1/B2 credential gap). That is exactly the operator's reach-independent-of- shell split, proven by execution: reach realizable, shell gated, held separate. - host_identity_srv3_access note wires the split: SshShell realizes OVER srv3_reach; encoding the jump INTO the transport (SshShell carries a Reach) is step b, coordinated with the shell->dag transport-wall lane. Witness (fleet_reach_witness_test): single-hop proxy, network realizable, target is srv3's grounded .221, jump is srv2, fabric-intended refuses (RED control). Also addresses review 42401's census-note finding: the "must not GROW the shell surface" pledge is restated precisely — new shell must be a deduction or a cited de-fork swap; the sccache de-fork's apt->cited-install swap and the genuinely-new `loginctl enable-linger` leaf (bounded, required for the user-scope handler) are both acknowledged rather than hidden behind a blanket no-growth claim. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * WIP: srvN subsumption * WIP: srvN subsumption * WIP: srvN subsumption * Consolidate 6 new witness files → 2 to fix floor batch-3 over-budget The floor's batch-3 discovery corpus went over its 28-min wall budget (twice, by 21s then 59s) because this PR added 6 new witness files and the floor pays a full whole-tree closure resolve (~80s) per entry. Three of the six pull the large gunbc closure. Per §6 (bare-minimum cost; a proven cost-shape defect is always fixed) and the batch-wall-budget rule (a refusal, never a widen — do NOT raise the budget), consolidate into 2 entries by shared closure: - test.claim.srv3_subsumption = fleet_reach + host_authorized_keys_reconcile + host_toolchain_reach_pairing (gunbc closure) — 17 witnesses. - test.claim.network_grounding = ipv4_address + network_address_host + network_reach (extdeps.network closure) — 19 witnesses. All 36 witnesses preserved and green by execution; removes 4 whole-tree closure resolves from the batch. No coverage lost — the merges are by shared closure and lane, not unrelated concerns; original witness notes preserved verbatim. Also folds in two live-run grounding corrections to srv3_reach_note: - realization is nested exec (ssh srv2 'ssh srv3'), not a -J tunnel: srv2 sets AllowTcpForwarding no, so -J returns 'administratively prohibited'; the reach realizes via the ProxyCommand-family handler (reach abstraction is agnostic). - fleet-automation was ADDED to ubuntu@srv3 live 2026-07-25 (the reconcile srv3 upsert executed over the hop, R5-safe, backup taken) — srv3 now trusts the fleet identity; the "not yet on srv3" claim is corrected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Doc-only. Writes a 2026-07-24 three-facet CI-workflow audit into the existing shell→dag threads (extend, don't spawn a plan). Two edits:
1.
shell-to-dag-residual-census-and-arc-completion.md— new §4.IThe census is grounded at
#78f43c38; five CIrun:shell sites landed after that and were tracked only at the site (rich in-code notes), never rolled up into §4/§5:ci_fmt_gate_line(→cargo.Build.Fmt)gunbc_ci_deploy_invoke,gunbc_ci_heal_regen_invokeci_heal_git_add_lines+ commit/push (76-line git transport → typedgit.Core.*)ci_sccache_provider_shell_injection— theif sccache --show-statsguard, also a §5 absorbing-fallback (silently skips caching when the daemon's down; the sibling of the-u RUSTC_WRAPPERone removed on BMC redfish fails closed on HTTP status + argv-anemia dissolution plan + srv4 sccache access #7138)Plus a table of the §5 absorbing-fallbacks inside the CI scripts the census tracked the scripts but not the widens for (
git rev-parse … || pwd×17,git fetch … || true, thetoolchain-unresolvedcache-poison slug, theCARGO_BUILD_JOBS=1fleet-pressure mask), each owed a modeled outcome. Keyed on file+symbol per the §4 convention.2.
shell-intent-emit-realization-design.md— generalize the invariantThe doc's thesis is "the intent names no language" (shell strings). The audit found the same §3/§4 violation in a second sink that isn't a string — hand-spelled config. New principle-only section: "the emitter names no concept."
ToolchainEnvIsolation,gha_actions_cache_facts,std.effect_grant), hand-copied into the emitter;ci_workflow/ci_yaml_emitis itself the fork — there should be oneemit(intent, target); a second workflow emitter is the N×M trap at workflow scale (roadmap2-emit-partitionalready targets the general-emit end-state);Respects each doc's discipline — the census owns the sites, the design doc owns the principle and references the census (no parallel ledger).
What this does not do
No code. The actual dissolution (derive config from
env_isolation, the missing lens, the shell-site migrations) is the roadmap's ongoing shell-emission / model↔realization-fork lane — this PR just makes the CI audit's findings tracked in the right homes so no site or fork is invisible.🤖 Generated with Claude Code