Skip to content

fix(repo-init): the non-interactive mint completes and mints correctly; standards re-pin - #237

Merged
hyperpolymath merged 7 commits into
mainfrom
claude/zealous-wozniak-2nherb
Oct 14, 2026
Merged

hyperpolymath merged 7 commits into
mainfrom
claude/zealous-wozniak-2nherb

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

Root-cause fixes for the estate checks that were red on resource-algebra#4. That repo was created with GitHub's "use this template" from df09a6c and never minted. Minting it (resource-algebra#6) exposed defects in this template's mint recipe, and showed that every child inherits a broken standards pin from here. These are fixed at source so new repos don't inherit them.

Changes

  • fix(repo-init): six recipe defects, each exercised by real mints.
    • RSR_NON_INTERACTIVE stubbed read for the whole recipe. Unanswered prompts then died under set -u, and the substitution loops never ended. Prompts now go through ask, which reads the environment. Service name, port and registry now honour their environment variables too.
    • The token pass rewrote just's own interpolation of project in Justfile and *.just. just files are now skipped by that pass.
    • CLAUDE.md and the repository map were left describing the template. Both are now regenerated from the child's deed and tree.
    • The self-name pass rewrote the deed's reject-if-contains detector into the child's own name.
    • A blank OpenSSF id deleted a table cell in TEMPLATE-STANDARDS-AUDIT.adoc, breaking the render gate.
    • identity.deed.in gains :pipeline-position and :chain as UNASSIGNED.
  • test(repo-init): tests/workflows/non_interactive_mint_test.sh, wired into Estate Rules with a checksum-verified just 1.43.0. No workflow ran repo-init before; tests/e2e runs nowhere in CI.
  • docs: four documents told agents never to use RSR_NON_INTERACTIVE. They now describe the working environment-variable path. The guide's prompt table gains the missing ORCID row and a variable column.
  • docs(arrival-pack): the owner's "Asking the owner" rule joins the estate-common block, per the owner's ruling of 2026-10-14.
  • fix(ci): the six standards reusables re-pinned from da2c748 to standards main ae36881, with actions.lock re-keyed and closed. At da2c748 the governance reusable installs gh-actions-lock unpinned, and v0.2.0 fails every caller on sha-as-ref. Standards main pins v0.1.6 and treats sha-as-ref as advisory.
  • fix(archetypes): the julia-library lock fragment moves to format v0.0.3. #236 moved the spine lock to v0.0.3, so archetype_lock_merge_test.sh fails on main and Julia mints stop at the merge.
  • docs(changelog).

RSR Quality Checklist

Required

  • Tests pass: every Estate Rules step and the key gates run locally on this tree (below)
  • No banned language patterns
  • SPDX license headers present on all new files
  • No secrets, credentials, or .env files included

As Applicable

  • Documentation updated
  • CHANGELOG updated under [Unreleased] / Fixed

Testing

  • Template mode. All Estate Rules steps pass on this tree, including the new test. archetype_lock_merge_test.sh fails on main without the fragment fix; it was reproduced on e2c87e6. Placeholders, root shape, render, lock sync (repo and standards main) and the arrival-pack check all pass.
  • The new test, watched failing. On the old recipe it fails twice over: the read() shim, and "PROJECT_NAME: unbound variable". It passes on the new recipe with just 1.43.0.
  • A full non-interactive mint of this tree with only the five required answers (mint-check) exits 0. The minted child passes placeholders, root shape, render (158 files), arrival pack and map freshness. It has no underscored names in just files and keeps its detector.
  • resource-algebra was minted with the same recipe. There, all 18 Estate Rules steps and all 26 Central Estate Audit gates (cicd-suite 0da816c) pass locally.

Not verifiable locally: the governance reusable's gh actions-lock --verify-local half. CI is the evidence for it.

Not fixed here

  • scripts/gen-repo-map.sh breaks on an apostrophe in a root-allow.txt comment (xargs: unmatched single quote).
  • docs/AI_INSTALLATION_GUIDE.adoc and the README tail are written for the template, and a minted child keeps them verbatim.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LiQzWJdcPfRU6YMDGRG8Xi


Generated by Claude Code

…ectly

Found by minting hyperpolymath/resource-algebra, which had been created
with GitHub's "use this template" from df09a6c and never minted
(resource-algebra#6). Each fix was exercised by a real mint there and by
a mint of this tree (`mint-check`), both with only the five required
answers in the environment.

1. RSR_NON_INTERACTIVE never worked. It shadowed `read` with a no-op for
   the whole recipe: an unanswered prompt left its variable unset, so
   `set -u` killed the mint at OPENSSF_BP_ID after docs/ was already
   overwritten, and every `while read -r` loop inherited the no-op and
   spun forever. Prompts now go through `ask`, which keeps the
   environment's value (or empty) and leaves the builtin alone. The
   service name, port and registry now also fall back to SERVICE_NAME,
   PORT and REGISTRY like every other answer, and their prompts show
   the effective default.
2. The token pass rewrote just's own interpolation. In Justfile and
   *.just every double-brace expression is a just variable; the
   lowercase project token is spelled like just's `project`
   interpolation, so 7 Justfile lines, the contractile copy and
   container.just's image tag froze into the identifier form. just files
   are skipped by the token pass; the self-name pass still rewrites them.
3. CLAUDE.md and the repository map were left describing the template:
   the pack named the child the estate's `foundation` with the template's
   uuid and clade, and the map kept archetypes/, so Estate Rules'
   map-freshness step failed in every child. Both are regenerated once
   the deed is final; a generator that cannot run stops the mint.
4. The self-name pass rewrote the deed's
   `:reject-if-contains ("rsr-template-repo")` detector into the child's
   own slug, rejecting every legitimate state file. Such lines are now
   protected like provenance lines.
5. A blank OpenSSF id deleted a table cell of
   docs/governance/TEMPLATE-STANDARDS-AUDIT.adoc, which then failed the
   render gate in every child. That document names the README's tokens,
   so it now spells them as plain names and the recipe leaves it alone.
6. identity.deed.in carries `:pipeline-position` and `:chain` as
   UNASSIGNED, so the arrival pack says so instead of rendering an empty
   `pipeline position ****`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LiQzWJdcPfRU6YMDGRG8Xi
No workflow exercised `just repo-init` at all: tests/e2e runs nowhere in
CI (only the inactive e2e.yml.template names it), which is how the
non-interactive mint could ship broken. tests/workflows/
non_interactive_mint_test.sh answers every prompt from the environment up
to "Proceed?" and declines, so it writes nothing and takes seconds:

- no `read()` function may shadow the builtin the substitution loops use;
- with only the five required answers, every prompt resolves without
  stdin and the declined mint aborts cleanly;
- a missing PROJECT_NAME fails by name, not as an unbound variable;
- the tree is as the test found it.

Watched it fail on the old recipe for two independent reasons (the shim;
"PROJECT_NAME: unbound variable") and pass on the new one. The loops'
hang lies past "Proceed?", so the full mints recorded in the previous
commit are the evidence for it, not this test.

Estate Rules installs just 1.43.0 from its release, checked against the
release's published sha256, the same way it installs Nickel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LiQzWJdcPfRU6YMDGRG8Xi
Four documents (README "The one trap", AI_INSTALLATION_GUIDE.adoc, the
user warm-up and the AI-install snippet) told agents never to set
RSR_NON_INTERACTIVE=1, because it stubbed `read` and hung, and to pipe
answers to stdin instead. The previous commits fix the cause, so the
documents now describe the working path: set RSR_NON_INTERACTIVE=1 and
pass the answers as environment variables (five required).

The guide's prompt table was also stale: it omitted the ORCID prompt,
so piping answers in its order shifted every later answer by one. It now
lists all 19 prompts, each with the environment variable it reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LiQzWJdcPfRU6YMDGRG8Xi
Owner ruling 2026-10-14: the rule that every question needing the
owner's decision goes through the AskUserQuestion selector belongs in
the estate arrival pack, not hand-appended to one repository's CLAUDE.md
(it arrived that way in resource-algebra#4 and was flagged out of scope).
It joins the estate-common block of arrival-pack.ncl, wording unchanged;
this repository's CLAUDE.md is regenerated, and verify.sh reports it in
sync. Every repo minted or re-synced from here receives it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LiQzWJdcPfRU6YMDGRG8Xi
At the pinned standards commit da2c748, governance-reusable.yml installs
github/gh-actions-lock unpinned, so a new release (cli v0.2.0) changed
the verdict for every caller: the Actions lockfile verify job fails on
`sha-as-ref` warnings it used to accept. Standards main carries both
cures (standards#1120 pins the tool to v0.1.6; sha-as-ref is advisory).
Every repo minted from this template inherits the template's pin, so the
cure has to land here as well as in each child.

- The six standards reusable calls pin ae36881 (standards main,
  2026-10-14), rewritten by standards' scripts/propagate-workflow-pins.sh.
- actions.lock follows, as check-lock-sync.sh prescribes for job-level
  refs: workflow entries re-keyed; the standards record rebuilt with the
  actions its reusables use at ae36881; three records it newly needs
  copied verbatim from standards' own lock; three records only da2c748
  used pruned; generator key order kept. Zero dangling edges; this
  repo's and standards main's check-lock-sync.sh both pass.
- The same rewrite on resource-algebra reproduces its hand-verified lock
  byte for byte.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LiQzWJdcPfRU6YMDGRG8Xi
The actions bump in #236 regenerated the spine lock as format v0.0.3.
The julia-library fragment stayed at v0.0.2, and merge-actions-lock
refuses a version mismatch, so tests/workflows/archetype_lock_merge_test.sh
fails on main (reproduced on e2c87e6 unmodified) and every
`just repo-init julia-library` would stop at the merge. Between the two
formats the only other change in #236's diff is lower-cased owner keys,
and this fragment has none, so its version line moves to v0.0.3. The
test passes, its clobber and missing-record mutants still fail, and
conflicts are still refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LiQzWJdcPfRU6YMDGRG8Xi
@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: Repository: hyperpolymath/rsr-template-repo/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c45c5ffc-be79-423e-b7b4-fcaad6b6c961
📥 Commits

Reviewing files that changed from the base of the PR and between e2c87e6 and 52e9e7d.

⛔ Files ignored due to path filters: 2
  • .github/workflows/actions.lock is excluded by !**/*.lock
  • archetypes/julia-library/actions.lock is excluded by !**/*.lock
📒 Files selected for processing: 18
  • .github/workflows/estate-rules.yml
  • .github/workflows/governance.yml
  • .github/workflows/hypatia-scan.yml
  • .github/workflows/mirror.yml
  • .github/workflows/rust-ci.yml
  • .github/workflows/scorecard.yml
  • .github/workflows/secret-scanner.yml
  • .machine_readable/arrival-pack/arrival-pack.ncl
  • CHANGELOG.adoc
  • CLAUDE.md
  • README.adoc
  • build/just/repo-init.just
  • build/templates/identity.deed.in
  • docs/AI-INSTALL-README-SECTION.adoc
  • docs/AI_INSTALLATION_GUIDE.adoc
  • docs/governance/TEMPLATE-STANDARDS-AUDIT.adoc
  • docs/onboarding/llm-warmup-user.adoc
  • tests/workflows/non_interactive_mint_test.sh
 _______________________________________________
< CodeRabbit: Because Jarvis was already taken. >
 -----------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@sonarqubecloud

Copy link
Copy Markdown

@hyperpolymath
hyperpolymath marked this pull request as ready for review October 14, 2026 11:06
@hyperpolymath
hyperpolymath merged commit 0afa6c9 into main Oct 14, 2026
65 of 67 checks passed
@hyperpolymath
hyperpolymath deleted the claude/zealous-wozniak-2nherb branch October 14, 2026 11:06
hyperpolymath added a commit to hyperpolymath/standards that referenced this pull request Oct 14, 2026
…n bumpers (#1254)

## Why

`scripts/apply-workflow-pins-remote.sh`, the scheduled pin applier,
fetches and commits only `*.yml`. The local `propagate-workflow-pins.sh`
has the same gap. Both re-point `uses: hyperpolymath/standards/...@SHA`
and leave `actions.lock` keyed to the old commit. `check-lock-sync.sh`
rejects that state, and its own header records GitHub refusing such runs
at startup.

The ledger census in `apply-workflow-pins.yml` counts 200 of 368
governance callers with an `actions.lock`. A fix-mode run would
therefore have opened PRs that stop those repos' reusable-calling
workflows.

This came up while fixing a stale `da2c748` pin, whose unpinned
`gh-actions-lock` fails Actions lockfile verify. That fix landed in
[resource-algebra#6](hyperpolymath/resource-algebra#6)
and
[rsr-template-repo#237](hyperpolymath/rsr-template-repo#237),
and both needed this relock done by hand.

## What

- **`scripts/relock-standards-pin.sh`** (new) moves a consumer's lock to
the target standards commit:
  - re-keys the per-workflow entries;
- rebuilds the standards dependency record from what the reusables
called with a full pin use at the target;
  - copies the records those need verbatim from standards' own lock;
  - prunes only records the old standards record alone kept alive;
  - keeps `gh-actions-lock`'s record order.
- **Short pins.** A short pin of 7 or more hex that prefixes the target
is current. This matches the applier, which counts it FRESH and leaves
it as written. It keeps its own short-keyed record, untouched.
- **It is fail-closed.** It leaves the lock untouched and exits 1 when:
  - a workflow pins another standards commit, or a pin under 7 hex;
  - a reusable is absent at the target;
  - the old record is missing;
  - a needed record is in neither lock;
- a workflow's standards entries would not name exactly the refs it
pins.
- **The applier** fetches `actions.lock` with the workflows and relocks
it in the same verified commit. A repo whose lock can't follow is
reported `LOCK-REFUSED` and not landed. In fix mode it fetches the
target commit if the CI checkout lacks it, and a new known-answer
control fails the run if the relock is missing.
- **The propagator** relocks before staging and reports `RELOCKED` /
`LOCK-REFUSED`. On a refusal it restores the workflows it rewrote,
uncommitted edits included, stages nothing, and leaves the branch alone.
Any refusal makes it exit 1.
- **Ported:** the frozen job-name fix that #1255 and #1256 also carry.
Self Test is red on main without it.

## Evidence

- **Known answers.** On resource-algebra and rsr-template-repo,
re-pinned from `da2c748` to `ae36881`, the relock reproduces byte for
byte the locks verified by hand there. Both pass `check-lock-sync.sh`.
resource-algebra's lock relocked to `934b879` passes the governance
gate's own `update-actions-lock.sh --verify-local` with gh-actions-lock
v0.2.0.
- **`scripts/tests/relock-standards-pin-test.sh`**, offline, 16 checks:
  - the known answer, and idempotence;
  - eight refusals that leave the lock byte-identical;
  - the no-lock no-op;
  - short pins at 7, 12 and 39 hex, each passing `check-lock-sync.sh`.
- **`scripts/tests/propagate-workflow-pins-test.sh`**: 29 of 29.
- **Mutants**, all killed:
- from the first round: no iteration, no pruning, no record copying, no
stale-pin refusal, over-pruning, no sorting;
- from the review round: exact-match only, every pin feeding the record,
no 7-hex minimum, no consistency guard, no restore, no early return.
- **Existing suites.** `check-lock-sync-test.sh` 13 of 13, and the
applier's `--self-test`.

The review round built on CodeRabbit's autofix commits (`cccec83`,
`5fd1373`) and kept their tests.

Not exercised: a live fix-mode applier run. It needs the dedicated App
credential, and it is the owner's dispatch.

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

https://claude.ai/code/session_01LiQzWJdcPfRU6YMDGRG8Xi

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
hyperpolymath added a commit that referenced this pull request Oct 14, 2026
…fs through the mint (#238)

## Summary

Follow-up to
[#237](#237).
After #237 merged, main still failed two governance jobs, the same two
its child
[resource-algebra#8](hyperpolymath/resource-algebra#8)
fixes. Minting resource-algebra also exposed one more defect in the mint
recipe.

| Check / defect | Cause | Fix |
|---|---|---|
| governance / Actions lockfile verify | standards `ae36881` installs
gh-actions-lock v0.1.6, which refuses lock format v0.0.3 | re-pin to
standards `6a92510`, which installs v0.2.0; relocked |
| governance / UUID v7 conformance | the strict v8 gate rejected the
uuid5 hex in `CLAUDE.md` and in the deed comment, and the Julia
`[extras]` registry UUIDs in `Project.toml.in` | print the deed's typed
`#u5"…"` literal and drop the hex from the comment; `6a92510` includes
[standards#1258](hyperpolymath/standards#1258),
which scans `Project.toml.in` as `Project.toml` |
| self-name pass | rewrote `rsr-template-repo#N` (the template's own
issues) into `<child>#N` | keep issue references as they are, with a
test |

## Changes

- **`fix(repo-init)`**: the self-name pass keeps `rsr-template-repo#N`.
  - The rewrite program moves into `SELF_NAME_SED`.
- The new `tests/workflows/self_name_pass_test.sh` runs that program, as
the recipe defines it, on fixtures. Estate Rules runs the test.
- **`fix(arrival-pack)`**: `extract.sh` prints `:repo-uuid` as the
deed's typed literal.
  - A deed whose uuid isn't typed stops generation with exit 2.
- CLAUDE.md is regenerated, and the deed comment no longer spells out
the hex.
- Per review, the literal is read at any indentation and spacing. A
space inside the literal is still refused: the deed ABNF defines
`%s"#u5" string`, with no space allowed between them.
- **`fix(ci)`**: the six standards reusables are pinned to `6a92510`.
`actions.lock` was relocked by standards' `propagate-workflow-pins.sh`
([standards#1254](hyperpolymath/standards#1254)).
- **`docs(changelog)`**.

## RSR Quality Checklist

### Required

- [x] Tests pass (below)
- [x] No banned language patterns
- [x] SPDX license headers present on all new files
- [x] No secrets, credentials, or `.env` files included

### As Applicable

- [x] Documentation updated (CLAUDE.md regenerated)
- [x] `CHANGELOG` updated under [Unreleased] / Fixed

## Testing

Run locally on this tree:
- `check-uuid-v8.sh --strict .`, using standards main's scanner: exit 0.
- The lock gates all pass:
  - `check-lock-sync.sh`, both the repo's copy and standards main's;
- the governance gate's `update-actions-lock.sh --verify-local`, run
with the checksum-verified gh-actions-lock v0.2.0 and mikefarah yq v4.
- `self_name_pass_test.sh`: 8 of 8. With the old program, 3 of the 8
cases fail.
- Also passing:
  - `archetype_lock_merge_test.sh` and `non_interactive_mint_test.sh`;
  - placeholders, root shape and the render check (160 files);
  - repository-map freshness and determinism;
  - `deed_clause_test.sh` and the arrival-pack `verify.sh`.

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

https://claude.ai/code/session_01LiQzWJdcPfRU6YMDGRG8Xi

---------

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

2 participants