Skip to content

CI shell→dag audit: census the missed sites + generalize the invariant (config is a language too) - #7159

Merged
briansrls merged 2 commits into
mainfrom
session/shell-to-dag-ci-census-additions
Jul 24, 2026
Merged

briansrls merged 2 commits into
mainfrom
session/shell-to-dag-ci-census-additions

Conversation

@briansrls

Copy link
Copy Markdown
Contributor

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.I

The census is grounded at #78f43c38; five CI run: shell sites landed after that and were tracked only at the site (rich in-code notes), never rolled up into §4/§5:

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, the toolchain-unresolved cache-poison slug, the CARGO_BUILD_JOBS=1 fleet-pressure mask), each owed a modeled outcome. Keyed on file+symbol per the §4 convention.

2. shell-intent-emit-realization-design.md — generalize the invariant

The 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."

  • the config forks (toolchain isolation, GHA cache key, action version, permissions) — a fact a model owns (ToolchainEnvIsolation, gha_actions_cache_facts, std.effect_grant), hand-copied into the emitter;
  • the litmus "opaque to emission" — if the emitter special-cases a concept (an "isolate this job" branch), the concept is forked emitter logic, not a projectable 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 — the target is a parameter;
  • the wall generalized: a lens that reds config hand-written where a model exists.

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

Brian Searls and others added 2 commits July 24, 2026 03:19
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>
@cursor

cursor Bot commented Jul 24, 2026

Copy link
Copy Markdown

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.

@briansrls
briansrls merged commit 773d53d into main Jul 24, 2026
5 checks passed
@briansrls
briansrls deleted the session/shell-to-dag-ci-census-additions branch July 24, 2026 15:15
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>
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