Skip to content

feat(provisioning): estate Provisioning Standard + launcher v0.5 provisioning modes - #1112

Merged
hyperpolymath merged 2 commits into
mainfrom
feat/provisioning-canon-signed
Oct 1, 2026
Merged

hyperpolymath merged 2 commits into
mainfrom
feat/provisioning-canon-signed

Conversation

@hyperpolymath

@hyperpolymath hyperpolymath commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

Supersedes #1096. The content is identical, rebuilt on current main as one signed commit.

Why a replacement

Delta vs #1096: Hypatia eval_in_shell false positives

#1096's Hypatia code-scanning check and governance / Validate Hypatia Baseline were red on 4 content_patterns/eval_in_shell findings (provision-check.sh:23, provision-lib.sh:867,868,944). The rule is a bare \beval\b, and every hit is the word: the eval verb name, or the .eval/ directory. None is the shell builtin.

The fix is an inline # hypatia:ignore eval_in_shell -- <reason> pragma on each line, not baseline entries:

  • HYPATIA-BASELINE-FORMAT.adoc lists "single new findings on freshly-introduced code" as a bad baseline entry, and the baseline is a ratcheted exemption ledger.
  • These files are templates minted into other repos. The pragma travels with them; a standards-only baseline entry would not.
  • 3 comment lines that newer hypatia (4065424) also flags are pragma'd too, so a scanner bump does not turn this red again.

Control: local hypatia@4065424 scan over the two files reports 7 eval_in_shell findings on #1096's version and 0 on this branch. bash -n is clean for both scripts. Upstream rule precision is tracked upstream in hyperpolymath/hypatia#892 (eval_in_shell matches the word, not the builtin in command position).

CodeRabbit's last CHANGES_REQUESTED (the launcher.sh.tmpl header saying modes delegate to the Justfile) is already addressed in this content: l.25–29 say provisioning modes call build/just/provision-lib.sh directly.


Original description (#1096)

What

Phase 1 of the estate provisioning campaign. This PR is the canon every repository will be minted from, so that nobody who clones a repo has to search for how to install, configure, run, test, bench, diagnose or repair it.

New: 3-practice/provisioning/

  • PROVISIONING-STANDARD.adoc (v1.0.0) and provisioning-standard_praxis.deed (lints OK)
  • Engine, identical estate-wide:
    • provision.just: the provision:: module with every verb
    • provision-lib.sh: bash only, shellcheck clean
    • provision-modes.sh: the launcher dispatch
    • provision-check.sh: the offline conformance checker, covering §8 items 1–5
  • Minted templates:
    • launcher.sh.tmpl
    • mise.toml (latest plus mise.lock)
    • Guix: a cargo-build-system package for Rust, a copy-build-system source package for everything else, plus manifest.scm and a pinned channels.scm
    • docs/SETUP.adoc, the manual route, with a doctor-code troubleshooting table
    • docs/AI_INSTALLATION_GUIDE.adoc
    • llm-warmup-{user,dev,maintainer}.adoc
    • the README [[ai-install]] "Just say it" fragment (the neurophone pattern)
    • the per-repo provisioning_praxis.deed

Launcher standard 0.6.0 (launcher-standard.adoc and launcher-standard_praxis.deed)

  • Every repository carries a launcher.sh, profiled by archetype. Only app has runtime modes; the others print N/A and exit 0.
  • --setup, --doctor, --heal and --ai-setup call the engine directly (build/just/provision-lib.sh), so a repo's own root doctor/setup/heal recipe cannot shadow the canon.
  • Repo-specific checks live in the doctor-local, setup-local and heal-local recipes. A failing doctor-local is FAIL PV-E50.

guix.scm: the licence field was a malformed ad-hoc licence object pointing at palimpsest-license. It is now mpl2.0 from (guix licenses), which is the licence the file's own SPDX header already declares. No licence changes.

Verified

  • deed_lint.py:
    • OK on launcher-standard_praxis.deed and provisioning-standard_praxis.deed
    • OK on a filled instance of the per-repo deed template
  • Shellcheck is clean on the engine scripts.
  • provision-check.sh fixture:
    • The positive control gives rc=0.
    • 9 mutants each fail on exactly their own check: launcher not executable, root verb missing, module verb missing, banned python, banned aqua:denoland/deno, no mise.lock, guix stub, mechanical slot residue, README SPEC residue.
    • --dev downgrades SPEC residue to a WARN.
  • doctor-local, in a scratch repo:
    • A failing doctor-local gives PV-E50 and rc=1 via both ./launcher.sh --doctor and just doctor.
    • A root doctor that prints fake green is not executed by --doctor.
  • just floor 1.42.0, measured: a root recipe depending on a module recipe fails on 1.31, 1.36, 1.40 and 1.41.
  • Guix, via podman with metacall/guix at ae77aeb: the Rust source package derivation builds (guix build -d, rc=0). The non-Rust derivation and the real build were still running when this PR was opened.

Known, not introduced here

  • The standards-map gate (Gate D) is already red on main, with 5 unmapped top-level entries: arena-session-787, patches, ULTRAPLAN-2026-09-24.adoc, ULTRAPLAN-2026-09-29.adoc and ziz-drop. This PR adds no top-level entry, because 3-practice is already mapped.
  • Dogfooding mod provision in this repo's own Justfile is deferred to the pilot phase.

Update: review round (head b234caf)

Commits since opening

  • 206eb6c — one placement resolver.

    • Each Guix template resolves the repository root from its own location, so a repo can keep the files at the root or under build/. This resolves the CodeRabbit placement thread.
    • Zig is detected up to 3 directories down.
  • 39b790f — no faked zig/bun tests.

    • A language with no test command prints an honest N/A.
    • There is now one AI-install sentence, read from the README by ai-setup.
  • eaf3a89 — new fmt-check verb, the check-only twin of fmt.

    • Per language: cargo fmt --check, zig fmt --check, mix format --check-formatted, gleam format --check, dune build @fmt, and bun's fmt-check script.
    • quality now depends on this verb. Before, it silently ran lint.
  • b234caf — the remaining review findings.

    • doctor-local.sh now runs sourced in a subshell. An exit or a tripped set -e is FAIL PV-E51, and the checks it completed still count.
    • hp_provision_or_return replaces && exit $?, which reported success for a failing mode.
    • The ai-warmup argument is now quoted.
    • trivy is pinned in mise only where a recipe calls it.
    • The launcher currency constant is now 0.5.0 (0.6.0 after 094fd79, below).
  • 7e6f3db — toolchain-refresh regenerates build/guix/crates.scm.

    • guix.scm.cargo.tmpl already promised this, but nothing implemented it. The new lib verb crates-scm runs guix import crate --lockfile. GUIX may name a container wrapper.
    • The file is written whole or not at all. Output is accepted only when it defines one origin per registry crate in Cargo.lock, because a containerised guix loses its exit status. Otherwise the run fails with the new code PV-E41 and the old file stays. PV-E41 is in the deed, the lib and the SETUP table: all three hold the same 28 codes.
    • Measured on launch-scaffolder's Cargo.lock:
      • 151/151 origins;
      • guix repl gives (length %crate-inputs) = 151 and origin? = #t;
      • regeneration is byte-identical.
    • Mutants killed:
      • truncated importer output (10/151): rc 1, PV-E41, file sha256 unchanged;
      • a failing importer (0/151): rc 1, PV-E41, file sha256 unchanged.
  • 094fd79 — merge main; the provisioning modes are launcher standard 0.6.0.

    • main took 0.5.0 for the (js-runtime) clause (D224, feat(launcher-standard): add the (js-runtime) bun/bunx launch route, v0.5.0 (D224) #1100). That number is published with that meaning, so the archetype and provisioning obligations move to 0.6.0 (2026-10-01). Updated together: the deed, the .adoc, the currency gate's CURRENT_VERSION, the launcher template and provision-modes.sh.
    • A consumer still citing 0.5.0 gets the non-blocking stale-version warning (standards#991), not a failure.
    • Checks:
      • currency test 19/19;
      • the gate on this tree: clean at v0.6.0;
      • --self-test: 4 mutants seeded, all detected.

Measured on rsr-template-repo (the first consumer; that PR follows)

  • doctor-hook cases:

    hook PASS / WARN / FAIL
    normal 19 / 1 / 0
    exit 3 19 / 0 / 1 + PV-E51
    set -e; false 19 / 0 / 1 + PV-E51
    fail 18 / 0 / 1
  • ./launcher.sh --doctor: rc 0 when clean, rc 1 with a failing hook.

  • just doctor 18/0/0, just validate pass, provision-check --dev 0 FAIL / 0 WARN, shellcheck clean.

  • fmt-check: rc 0 on clean code; a mis-formatted mutant gives rc 1.

  • Guix, via metacall/guix at ae77aeb:

    • guix build -f guix.scm: rc 0.
    • guix shell -m manifest.scm --dry-run: rc 0.
    • channels.scm evaluates to the same pinned commit.
  • just registry-check OK. check-launcher-standard-currency OK.

Red checks: none is a required check. Classified:

Placement labels (elegance arm)

  • The engine is vendored byte-identical into each repo, and provision-set --check will prove it is equal to canon. This is the elegant long-term arm.
  • Departure considered and rejected: fetching the engine at run time. That would break offline and Guix-hermetic use and add a supply-chain hop.
  • channels.scm is minted, not engine (departure, labelled). toolchain-refresh re-pins it per repo by design, so a byte-compare would go red after every weekly refresh. Instead it is checked for a 40-hex commit pin.

Update: one banned list, backends and bare names (heads b01a245, bf7c97a)

Found by the 8-repo pilot (launch-scaffolder#67).

  • b01a245:
    • The deed's :banned-tools and the engine's BANNED_TOOLS had diverged. They are now one 20-item list, plus a new :banned-backends ("npm" "pipx" "pip" "go"). launch-scaffolder tests that the deed and the engine agree.
    • PV-W23 now reads mise.toml, .mise.toml and .tool-versions.
    • A tool behind a banned backend is flagged whatever its name (npm:prettier).
    • Controls: .tool-versions python + .mise.toml "npm:prettier" → [python npm:prettier] rc=1; clean → [] rc=0.
  • bf7c97a: a bare name whose only registry backends are banned is flagged too. prettier resolves only to npm:prettier.
    • The lookup uses mise registry, which works offline.
    • Shells with no mise and names mise doesn't know are never flagged on a guess.
    • Controls: prettier → [prettier] rc=1; shfmt/zig/an unknown jest → [] rc=0.
    • shellcheck is clean, and docstring coverage is 100%.
  • Pilot gaps that are canon work but not fixed here are filed as Provisioning canon: four gaps found by the 8-repo pilot (doctor provenance, toolchain floors, per-user artefacts, offline mint) #1107.

Next

  • the rsr-template-repo canon fix
  • the provision-set generator and the provisioning-check.yml gate
  • a pilot of about 8 repos, then fan-out in SET batches

🤖 Generated with Claude Code

https://claude.ai/code/session_01DAKujx2PXHcVSA7vncTNH1

Re-signed rebuild of #1096 (head 18dcefa) on current main. Two coderabbitai[bot]
commits on that branch were unsigned, which required_signatures refuses even under
squash. The tree equals 18dcefa apart from main's later #1087/#1098 files, plus:

- hypatia:ignore eval_in_shell pragmas on 7 lines of provision-check.sh and
  provision-lib.sh. Each hit is the word "eval" (a verb name or the .eval/
  directory), never the shell builtin. Inline pragmas, not baseline entries:
  the templates are minted into other repos, where the pragma travels with them.
  Control: hypatia@4065424 reports 7 findings before and 0 after.

Original commits (feat/provisioning-canon):
  fd0658c feat(provisioning): estate provisioning standard + launcher v0.5 modes
  e7b134e fix(provisioning): detect ABI/FFI layout; launcher is generated
  40010ef fix(provisioning): no curl|sh install hint; regenerate registry
  206eb6c feat(provisioning): one placement resolver; zig found 3 dirs down
  39b790f fix(provisioning): no faked zig/bun tests; one ai-install sentence
  eaf3a89 feat(provisioning): fmt-check verb, the check-only twin of fmt
  b234caf fix(provisioning): #1096 review — hook isolation, dispatch rc, quoting
  89c1d32 fix(provisioning): one set of predicates for doctor and the CI gate
  93342bf docs(provisioning): banned-tool mise.toml is replaced; app launchers
  7e6f3db feat(provisioning): toolchain-refresh regenerates build/guix/crates.scm
  9b57453 fix(provisioning): mise.lock checksums are checked per platform table
  7475b18 docs(provisioning): document the awk helper in mise_lock_gaps
  e323e0a docs(provisioning): escape the [[ai-install]] anchor in prose
  42b66c3 fix(provisioning): guix-only re-pin, tally-last doctor, artefact kinds
  b01a245 fix(provisioning): PV-W23 reads every mise config and backend
  bf7c97a fix(provisioning): a bare mise name with only npm backends is banned
  a00fcf3 Update 3-practice/provisioning/templates/launcher.sh.tmpl
  71cad01 docs(provisioning): document shell template functions
  18dcefa docs(provisioning): clarify template function behavior and exit statuses

Co-Authored-By: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DAKujx2PXHcVSA7vncTNH1
@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 12 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 5a4a5783-bea4-4db6-a7d2-45715daa3325

📥 Commits

Reviewing files that changed from the base of the PR and between 7de6a8a and 45186c9.

📒 Files selected for processing (24)
  • 3-practice/provisioning/PROVISIONING-STANDARD.adoc
  • 3-practice/provisioning/provisioning-standard_praxis.deed
  • 3-practice/provisioning/templates/.machine_readable/descriptiles/provisioning_praxis.deed.tmpl
  • 3-practice/provisioning/templates/Justfile.tmpl
  • 3-practice/provisioning/templates/README-ai-install.adoc.tmpl
  • 3-practice/provisioning/templates/build/just/provision-check.sh
  • 3-practice/provisioning/templates/build/just/provision-lib.sh
  • 3-practice/provisioning/templates/build/just/provision-modes.sh
  • 3-practice/provisioning/templates/build/just/provision.just
  • 3-practice/provisioning/templates/docs/AI_INSTALLATION_GUIDE.adoc.tmpl
  • 3-practice/provisioning/templates/docs/SETUP.adoc.tmpl
  • 3-practice/provisioning/templates/guix/channels.scm
  • 3-practice/provisioning/templates/guix/guix.scm.cargo.tmpl
  • 3-practice/provisioning/templates/guix/guix.scm.source.tmpl
  • 3-practice/provisioning/templates/guix/manifest.scm.tmpl
  • 3-practice/provisioning/templates/launcher.sh.tmpl
  • 3-practice/provisioning/templates/llm-warmup-dev.adoc.tmpl
  • 3-practice/provisioning/templates/llm-warmup-maintainer.adoc.tmpl
  • 3-practice/provisioning/templates/llm-warmup-user.adoc.tmpl
  • 3-practice/provisioning/templates/mise.toml.tmpl
  • docs/UX-standards/launcher-standard.adoc
  • guix.scm
  • launcher/launcher-standard_praxis.deed
  • scripts/check-launcher-standard-currency.sh
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@hyperpolymath
hyperpolymath merged commit 2c06ddf into main Oct 1, 2026
50 checks passed
@hyperpolymath
hyperpolymath deleted the feat/provisioning-canon-signed branch October 1, 2026 15:18
hyperpolymath added a commit that referenced this pull request Oct 1, 2026
…1106 onto main) (#1113)

**Re-land of #1106 onto `main`.** #1106 merged at 15:32Z into its
stacked base `feat/provisioning-canon`, but #1096 (that base) was closed
unmerged. Its content reached `main` as #1112 instead, so the gate never
reached `main`. `.github/workflows/provisioning-check-reusable.yml` is
absent on `main` at `1b6e19ea`.

This is #1106's single commit replayed onto `main` (signed). The
workflow and `canon.lock` are byte-identical to #1106's merged head
`a6649bca`. The only conflict was `.github/workflows/actions.lock`:
#1084 added `harden-runner` under `propagate-hooks.yml` next to where
this PR adds its section, and both are kept. `gh actions-lock --no-fix`
passes 56 of 57 workflows. The one failure is the
`signed-push-smoke.yml` local-action error, which #1084 records as
already failing before this change.

A diff of the `3-practice/provisioning` tree between
`feat/provisioning-canon` and `main` shows that only this gate was
stranded. The template differences there are newer `hypatia:ignore`
annotations that `main` has and the dead base lacks.

KYAML for this workflow follows in a separate PR. That PR first moves
the grep-reading workflow gates (lock-selfcheck, validate-actions-lock,
governance permissions check, duplicate-keys) to `yq` (YAML-POLICY Y-1),
because each of them would falsely fail a flow-style file.

## What

`.github/workflows/provisioning-check-reusable.yml`, the CI gate from
`3-practice/provisioning`. It checks the caller against the canon at the
workflow's own commit (`job.workflow_sha`), in two steps that report
separately:

| Step | Fails when |
|---|---|
| Engine files match the canon | any
`build/just/{provision.just,provision-lib.sh,provision-modes.sh,provision-check.sh}`
is missing or differs byte-for-byte |
| Provisioning set conforms | the **canon** `provision-check.sh`, run
without `--dev`, reports FAIL. It loads `provision-lib.sh` from its own
directory, so a drifted caller copy cannot vouch for itself |

- `channels.scm` is deliberately not compared byte-for-byte:
`toolchain-refresh` re-pins it per repository. `provision-check.sh`
checks its pin instead.
- `just` 1.56.0 comes from the release tarball, pinned by sha256 (the
same pin as launch-scaffolder#67). No new `uses:` is added.
- `actions.lock` gains the section by hand (checkout only). `canon.lock`
lists the reusable as `provisioning` under `[canon.workflows]`.

## Evidence (local dry run of both steps; the CI proof follows on a
throwaway caller)

| Case | cmp step | provision-check |
|---|---|---|
| rsr-template-repo #213 head (control) | pass | pass |
| mutant: `fmt-check` recipe removed | pass | **FAIL** |
| mutant: `python` added to `mise.toml` | pass | **FAIL** (banned tool +
unpinned) |
| mutant: `provision-lib.sh` changed | **FAIL** | pass |
| mutant reverted | pass | pass |

The third mutant is why there are two steps: an engine edit that leaves
conformance intact is caught only by the byte comparison.

## Known, not new

- actionlint does not know the `job.workflow_sha` context. It reports
the same thing 4 times on `allowlist-preflight-reusable.yml`.
- `gh actions-lock` gives this file the same `sha-as-ref` advisory that
every SHA-pinned workflow here carries (94 on the base, 95 with this
one).




🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01W5CoaksP2Bg21HpDCgFgwS

Co-authored-by: Claude Opus 5.5 <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