Hedronite Lesson · Polyglot-Dev / Nix · Fri 2026-10-02 · T7

The POSIX floor gate inside nix flake check — Floor Shebang · Pack Seat · Check Wire · Graduate Gate

Why the gate is /bin/sh. When a shell gate must graduate to a cargo script.

Lesson Class: Asr (Nix T7 Env & CI · Rust roads)
Focus: Floor Shebang · Pack Seat · Check Wire · Graduate Gate
Done-criteria: why /bin/sh (no rustc on floor); when shell gate graduates to cargo script
Grounding: bend-gate.sh · rust-tops-laws.nix · checks.law-catalog · NAMES 53 verified
Note: Not Duha Beat B · not Schema Read remake · Bend spine exhausted #9 · Phase 2 waits a teammate
Floor Shebang
#!/bin/sh asserts NAMES↔LAWS/PROOF parity without rustc or Bend.
Pack Seat
rust-tops-laws.nix copies laws/ via stdenvNoCC; not the gate.
Check Wire
law-catalog forces BEND_GATE_NAMES_ONLY=1 inside runCommand.
Name the shebang. Name the names-only export. Leave the keyboard.

<!-- hal:authoritative:yaml -->

*Why the gate is /bin/sh. When a shell gate must graduate to a cargo script.*

§I — Frame

Asr session 20. Topic T7 Env & CI. Fifth and final fire of the Nix Rust-roads block (#16 to #20). Home: . Cite: rust-tops scripts/bend-gate.sh + nix/rust-tops-laws.nix + flake checks.law-catalog. Vault mirror: foundry/rust-tops/repo/rust-tops/. Live: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake-check.html.

Session 19 named Schema Read, Shell Seat, and Check Seat. Today the unmarked row asks the floor question under law-catalog: why is the gate a POSIX shell script, what does the laws-pack derivation carry, and when must a shell gate graduate to a cargo script instead of staying on /bin/sh.

Verified on this Mac before drafting:

ProbeResult
bend-gate.sh shebang#!/bin/sh
NAMES line count / ^law in LAWS.bend53 / 53
BEND_GATE_NAMES_ONLY=1 ./scripts/bend-gate.shbend-gate: 53 laws named · exit 0
bend on PATHabsent · soft names-only exit 0
checks.aarch64-darwin attrNamescargo-tops, law-catalog, rust-tops-laws

Today's Duha Nix packaging shell (lesson_class: duha, patterns crate) packages Beat A. It does not consume this Asr cursor.

Done-criteria from the syllabus: say why the gate is /bin/sh (no rustc on the floor) and when a shell gate must graduate to a cargo script.

Not a remake of session 19 Schema Read. Not Bend regenerate body (s07). Bend Asr spine has no unmarked row after #9.

§II — Floor Shebang (named technique)

Floor Shebang: the gate starts with #!/bin/sh on purpose.

Open scripts/bend-gate.sh. The first line is not bash-for-comfort and not a Rust binary. It is POSIX sh. The script then:

  1. Resolves repo root and RUST_TOPS_LAWS (default laws/).
  2. Refuses missing LAWS.bend / PROOF.bend / NAMES (exit 2).
  3. Counts NAMES lines vs ^law statements in LAWS.bend.
  4. For each name, asserts the law line exists in LAWS.bend and the name appears in PROOF.bend.
  5. If BEND_GATE_NAMES_ONLY=1, prints the count and exits 0.
  6. If bend is missing on PATH, soft names-only: print and exit 0.
  7. Else exec bend PROOF.bend.

Yagyu: Floor Shebang means CI can assert catalog parity with grep and sh, without rustc, without Bend, without compiling gen-laws.rs.

Musashi: the floor answers "are the harvested names stated?" It does not answer "did Bend prove every stated law on this host?"

§III — Pack Seat (named technique)

Pack Seat: nix/rust-tops-laws.nix is the laws tree as a store package, not the gate.

stdenvNoCC.mkDerivation {
  pname = "rust-tops-laws";
  # ...
  src = ../laws;
  dontConfigure = true;
  dontBuild = true;
  installPhase = ''
    mkdir -p $out/share/rust-tops/laws
    cp -R . $out/share/rust-tops/laws/
  '';
}

stdenvNoCC is the tell: no C compiler seat, no Rust seat. The derivation copies the pack. Flake checks.rust-tops-laws is "this package builds." Flake checks.law-catalog is "the gate script passes names-only against ./laws."

Do not confuse Pack Seat with Floor Shebang. One ships files. One asserts name parity inside nix flake check.

§IV — Check Wire (named technique)

Check Wire: how law-catalog pins the floor inside the sandbox.

From flake.nix:

law-catalog = pkgs.runCommand "rust-tops-law-catalog" { } ''
  set -eu
  export BEND_GATE_NAMES_ONLY=1
  export RUST_TOPS_LAWS=${./laws}
  bash ${./scripts/bend-gate.sh}
  echo ok >"$out"
'';

Read the contracts:

WireMeaning
BEND_GATE_NAMES_ONLY=1sandbox never asks for Bend
RUST_TOPS_LAWS=${./laws}gate reads the flake-local laws tree
bash ${./scripts/bend-gate.sh}run the script; script itself stays /bin/sh
no gen-laws.rsregenerate is host work, not check work

nix flake check builds every checks attr. If name parity fails, the flake fails. That is the CI noun for Topics #20.

Chozanshi: if the sandbox has no Bend and no rustc for the generator, then names-only sh must still fail closed on a missing law name; thus regen stays a separate host step (Bend s07 Catalog Emit).

§V — Graduate Gate (named technique)

Graduate Gate (T7 floor version): keep shell until the check must compile or interpret Rust.

SeatToolWhen it belongs
Floor gate/bin/sh + grep (bend-gate.sh)assert name/statement parity; no deps; CI sandbox
Cargo scriptgen-laws.rs (cargo +nightly -Zscript)regenerate the triad on a maintainer host
Crate / writerbuildRustPackage / writeRust*locked deps, store package, or PATH binary

Graduate the shell gate to a cargo script when parity-by-grep is no longer enough: you need typed parsing, crate deps, or a binary that must exist in $out. Do not graduate just because Rust is nearby. gen-laws.rs already owns regen; bend-gate.sh owns the floor. Session 17 Graduate Gate sorted writer vs script vs crate. Session 20 adds the floor rule: **CI parity stays /bin/sh until the assertion itself needs a Rust program.**

Corpus honesty: rust-tops has not replaced bend-gate.sh with a Rust checker. That absence is truth. Do not invent a store Rust gate from class.

§VI — Why this road

Asr Nix seats T7 so Rust packaging ends the #16–#20 block with a floor you can name: shebang, pack, check wire, graduation. After crate, writers, musl, and flake schema, the last road move is "what runs when nix flake check hits the laws."

Keep the Duha/Asr split clear: Duha Beat B may package today's lesson crate under lesson_class: duha. Asr advances NIX-SYLLABUS under lesson_class: asr and topic: T7.

§VII — Done-criteria check

Say aloud without looking:

  1. Floor Shebang: gate is #!/bin/sh so CI needs no rustc and no Bend for name parity.
  2. Pack Seat: rust-tops-laws.nix copies laws/ with stdenvNoCC; it is not the gate.
  3. Check Wire: law-catalog forces BEND_GATE_NAMES_ONLY=1 inside runCommand.
  4. Graduate Gate: leave shell until the assertion itself needs a Rust program; regen stays cargo-script on host.

§VIII — Common mistakes

  1. Treating today's Duha Nix packaging shell as this Asr Topics #20 ship.
  2. Claiming nix flake check runs full bend PROOF.bend when law-catalog is names-only.
  3. Putting gen-laws.rs compile into the flake check "to be thorough."
  4. Confusing checks.rust-tops-laws (pack build) with checks.law-catalog (gate).
  5. Replacing /bin/sh with a Rust binary from class without a real assertion need.
  6. Inventing a Bend Phase 2 lesson row because the duo peer spine is exhausted.

§IX — Boundaries

§X — Close

Session 19 mapped the flake surface. Session 20 maps Floor Shebang, Pack Seat, Check Wire, and Graduate Gate against bend-gate.sh, rust-tops-laws.nix, and checks.law-catalog. NIX-SYLLABUS Topics #16 to #20 (Rust roads) are now complete; Phase 2 waits on a teammate.

Related:

Name the shebang. Name the names-only export. Leave the keyboard.