feat(beta-delivery-ux): R1 — npm release mechanics (A6): files allowlist validated by a real tarball cell, F-C′ resolved, name-architecture freeze - #1358
Merged
Conversation
added 7 commits
August 10, 2026 10:27
…ry re-measurement (absorbs U11) The §2 freeze record: 7-package family verdicts, the getff CLI mapping + §0.5 gap (bin: getff does not exist in any package today), the 0.1.0 version floor (0.0.1 spent), scope-ownership evidence (UNRESOLVED — needs authenticated probe), rollback doctrine verbatim from s6-u10-handoff.md §4, F-C′ resolution (option (a) tsx-dep), and the release-drafter tag→notes flow verified against the existing config. U10 cites this record without re-reading the R1 kickoff. Prior-art: skipped — documentation only, no new capability.
…wlist + bin runnability F-C′ resolved (A6) R1 Deliverable 2 + Deliverable 3 (kickoff §3, §4). Three co-shipped artifacts: * tests/consumer-matrix/npm-tarball-cell.sh — the consumer-matrix cell that IS the files-allowlist validation mechanism (kickoff §3 item 4). Packs packages/core, installs the tarball into a fresh fixture, asserts the consumer path: manifest loads, by-path assets exist (install bundle, schema, eslint-rules, templates/, skills/), every bin: and exports: target resolves, and ≥1 bin executes end-to-end from the installed package. * packages/core/package.json:files — 14-entry allowlist (manifest, eslint-rules, detector, research, synthesizer, installer, validator, ir, backends, diagnostics, composition, templates, install, skills). Over-ship 711→493 files. 10 entries carry paired RED→GREEN evidence from the cell (steps 3, 4, 4b, 4c, 5, 6, 7, 7b); 4 entries (ir, backends, composition, +validator-internalslice of diagnostics) are UNVALIDATED-by-this-cell — transitively needed by the 3 bins (synth, validate, install) whose runtime-dep gap (eslint as runtime dep) is deferred to U10. Documented in the §2 freeze record's F-C′ resolution. * packages/core/package.json:dependencies — tsx promoted from devDependencies to dependencies. F-C′ option (a) wins; option (b) prebuild cost recorded in the §2 freeze record (loser's concrete cost, T20). Prior-art: skipped — adjacent sibling cell under same dir, no new capability.
…flow verified R1 Deliverable 4 (kickoff §5). Adds the npm metadata the binding input §2 enumerated: * packages/core/LICENSE — real file copy of root LICENSE.md (FSL-1.1-ALv2), not a symlink (kickoff §5 warns symlinks don't survive npm pack). Verified in the packed tarball via npm pack --dry-run | grep LICENSE. * packages/core/README.md — 1-page stub pointing at the repo root README.md#why-this-exists (kickoff §5 allows stub vs full; stub chosen and recorded in the §2 freeze record). * packages/core/package.json — description, repository, homepage, bugs, engines (node >=22, matches every CI workflow's node-version: '22' pin). * main: "./manifest/rules-manifest.json" — confirmed intentional, not changed. Release-drafter flow verified against the existing config — no edit needed. The autolabeler recognises all five conventional-commit prefixes R1's commits use (feat, docs, ci per the commit plan). Tag flow documented in the §2 freeze record. Prior-art: skipped — metadata + LICENSE copy, no new capability.
…cess needs: R1 Task 8. Three co-required wirings (kickoff §3): * .github/workflows/audit-self.yml — new job consumer-matrix-npm-tarball-cell added next to consumer-matrix-start-cell (audit-self.yml:1512) and consumer-matrix-python-unfamiliar-stack-cell (:1556). SHA-pinned actions per ci-tool-pinning.md; one Run step. The cell ships its own dependencies via the tarball (tsx is a runtime dep), so no Pattern-B hoisting needed. * ci-success needs: — adds consumer-matrix-npm-tarball-cell to the needs list with a load-bearing comment per attention-is-not-a-mechanism.md §2 (#warning-nobody-reads — without this line the cell could go RED while ci-success stayed green and the PR merged). * Makefile — new consumer-matrix-npm-tarball target (cleaner separation; the existing consumer-matrix target keeps its single-cell meaning). Prior-art: skipped — CI wiring for an existing cell pattern, no new capability.
…s in the npm-tarball cell Harvest-time cold QA (T19) against kickoff-r1.md §6 acceptance. Two asserts named for a class they did not test, plus the paired-RED evidence the kickoff requires but the stage asserted in prose only. All three closed with measured output, not reasoning. * (7a) NEW — the F-C' discriminator. Spec §11 binds the bin-runnability fork to THIS cell and kickoff §4 says "decide against the cell, not against reasoning" — but step (7) as shipped returned rc=0 under BOTH options. Measured: with `tsx` demoted back to devDependencies the bin still ran, because the `#!/usr/bin/env -S npx tsx` shebang makes npx SILENTLY INSTALL IT FROM THE NETWORK (`npm warn exec ... will be installed: tsx@4.23.12` — unpinned, ignoring the declared ^4.22.4), with tsx confirmed absent from the fixture. Step (7a) asserts tsx arrived in node_modules; two-direction proof: GREEN rc=0 with tsx as a dependency, RED rc=1 without. F-C' option (a) still wins, but the recorded rationale was wrong — the real cost is a silent unpinned runtime network fetch that breaks offline, not "the bin fails". * (6) renamed to what it asserts. It was labelled "assert >=1 ESLint rule fires against a planted violation"; it plants nothing and runs no ESLint — it reads the manifest and counts eslint-rules/ files. Firing IS covered, on the file-copy channel, by the sibling pnpm-monorepo-cell.sh step (d-1) (planted violation -> eslint rc=1 with the R2 message); both cells are merge-blocking and both are in this kickoff's host-verify contract. Scope note added naming the residual uncovered class rather than implying coverage (T14). * files allowlist — the paired-RED table is now MEASURED. 14 arms (drop one entry, re-run the cell, restore): 10 RED, 4 GREEN. The stage's 10/4 count was right; its membership was not — `diagnostics/` IS RED-validated (step 7b), and `validator/` is unvalidated in whole, not as a slice of another entry. Correction kept visible in the record per T3. Also records the README stub-vs-full choice kickoff §5 asks for (stub; a full copy would be a #sync-by-copy-paste twin with no regenerating mechanism), and labels two fenced blocks the container-side commit left unlabelled (MD040 — husky did not run there; this is the pre-push channel doing its job per egress-no-api-bypass.md §1). Prior-art: skipped — test-assert hardening plus evidence recording for an existing cell; no new capability, no new dependency.
…n the U10 warning Cold fidelity audit (round 1, Audited-SHA 428a0fe) returned REVISE on two diverged findings. Both closed here, each with a measured two-direction arm rather than a reworded claim. Cold backward sweep ran in parallel; its one in-scope consequence is recorded below. MAJOR 1 — Makefile wiring (kickoff-r1.md:233 "Add it to `Makefile` `consumer-matrix` too"). The stage added a SEPARATE `consumer-matrix-npm-tarball` target and left `consumer-matrix` running the pnpm cell alone, while the cell header claimed `make consumer-matrix` runs it. Fixed by honouring the kickoff literally: `consumer-matrix` now runs both cells (`make -n consumer-matrix` lists pnpm-monorepo-cell.sh AND npm-tarball-cell.sh); the narrow target stays as a convenience runner. The header claim is now true rather than deleted. MAJOR 2 — step (5) was #contract-that-cannot-fail, the same shape (7a) closed one step later. It printed "loaded" while asserting `readFileSync(...).length > 100` — any file over 100 bytes passed, so a truncated bundle shipped green. Replaced with three asserts, each chosen by measurement, not by preference: * `node --check` — measured: intact PASSES, 50 KB head FAILS, but a 200-byte head also PASSES, so --check alone is necessary and not sufficient; * entry-guard grep (`synth-and-wire.bundle.mjs` in the process.argv[1] self-guard); * tail-export grep (`mergeLiveRules`) — together these fail at every truncation point --check misses. `await import()` was evaluated and REJECTED on evidence: it throws regardless of integrity, because the bundle has a module-level side effect opening install/research-plan.schema.json relative to cwd (its argv[1] self-guard does correctly suppress main()). Two-direction proof: intact tree rc=0; bundle truncated to 50 KB rc=1 at step (5). Step (5)'s name and the file header no longer claim "the install flow" — that flow runs via setup.d/99-finalize.sh:25 and is exercised end-to-end by pnpm-monorepo-cell.sh. MINORs also closed: LICENSE + README.md added to the by-path asset loop, so kickoff §5's "verified in the packed tarball" is gated rather than attention-dependent; the over-ship before/after (707 -> 494, -30%) recorded IN the freeze record, since kickoff §6 item 7 makes the record — not the PR body — the artifact U10 reads. U10 warning deepened (in scope: this is R1's OWN deferred gap, not a sibling fix). Promoting eslint to `dependencies` is necessary but NOT sufficient: four shipped validator gates statically import `@rules-as-tests/preset-next-15-canonical/eslint-rules`, that package is `private: true`, and `npm pack --dry-run` confirms the importing gate files DO ship. So `rules-as-tests-validate` stays unrunnable from a published tarball until U10 picks one of three named options. R1 does not pick — kickoff §7 forbids touching a package outside packages/core. Prior-art: skipped — test-assert hardening and record deepening for an existing cell; no new capability, no new dependency, no new file.
…rDependencies note Round-2 fidelity audit MINOR. The note cited `preset-react-spa/package.json:11` for peerDependencies; line 11 of that file is `"scripts"` and its peerDependencies block is at `:15` (`:11` is the peerDependencies line in preset-react-native). The underlying claim was correct — packages/core declares none while all four siblings do — but a U10-facing record whose whole value is being trustworthy without re-derivation cannot carry a citation that does not resolve (kickoff §6 item 7 self-containment, §8 T20). Re-verified all four, each by grep rather than by recall: preset-react-spa/package.json:15 preset-next-15-canonical/package.json:15 preset-react-native/package.json:11 meta-factory/package.json:13 packages/core/package.json — none Scope-neutral: one prose line in one record; no deliverable, permitted-file, or descope changes (git diff --name-only db9aa6e..HEAD = the record alone). Prior-art: skipped — citation-accuracy fix in a documentation record, no capability change.
artyhoo
added a commit
that referenced
this pull request
Aug 10, 2026
…1361) All six stages are merged to staging: S1 #1173, S2 #1327, S3 #1272, S4 #1341/#1350/#1351, S5 #1285, R1 #1358 (a88da6d, 2026-08-10). The last-stage condition the meta-launch state.md named is now satisfied, so the umbrella-closure convention fires. Writing done.md is what makes `priority-score.sh` Layer C3 score the umbrella `status=DONE basis=done-md` and stop offering it for dispatch — verified after the write, both the umbrella and its meta-launch dir now report `done_pr=1358 basis=done-md`. Holding it back until now was the deliberate call recorded in state.md: writing it before R1 merged would have short-circuited C1/C2 and stopped R1 from being dispatched at all. The record carries what a future reader would otherwise re-derive: the per-stage ledger, the U9/U10 gates from the R1 freeze record (the @Getff scope-ownership probe, the missing `bin: getff`, the finding that promoting eslint to runtime deps is necessary but not sufficient), the ci-success `needs:` completeness gap R1's backward sweep surfaced and deliberately did not fix per the PR-strategy rule, S4's two operator-accepted risks, S5's P5 vendor-scope fork, and the seven `done`-unharvested aif task ids. Prior-art: skipped — closure record only; done.md is a documentation artefact per the CLAUDE.md capability-commit doc carve-out, adds no dependency, no module and no new capability. Co-authored-by: Test <test@example.com>
Merged
10 tasks
artyhoo
added a commit
that referenced
this pull request
Aug 17, 2026
…1 is an operator fork (#1435) ## Summary The drift-register repair — the second of the two successors [triage-kernel-v2's `done.md` named](/.claude/orchestrator-prompts/triage-kernel-v2/done.md) (S5b was the first, #1428/#1431). Its whole input is the 3 `NEVER-DONE` rows of the S4b outcome audit, ranked MATERIAL-first. **2 of the 3 are repaired here; the third turns out not to be a repair at all** — see «The row that is not a defect» below. Every row was re-verified against the live tree before touching anything, and two of the three register entries proved inaccurate about their own subject (details per row). ## The three rows **Row 1 — `1311-r1-5` (MATERIAL) — FIXED, and now gated.** `setup.d/20-agents.sh:33-40` gates `orchestrator-worker-discipline` and `reviewer-discipline` behind `--profile factory`; the template's `factory` row named the 7-skill suite and stopped, so a consumer AI at factory depth never learned it had them. The row now names both. The register also asked for «a regen check against `20-agents.sh`» — that is the second half of this commit, because the reason this drifted is that **nothing reconciled the two lists**. **Row 3 — `1358-r3-1` (IMMATERIAL) — FIXED.** «all four siblings» → «four of its six siblings», with the two zero-peer siblings named. Two corrections to the register itself here: the sentence is at `:194`, not the `:146` every record cites (the file grew since the finding was filed), and the register's suggested repair — restore the «publishable-intent» qualifier — is **wrong on the facts**: `meta-factory` carries a peer dependency yet this very document classifies it «stays private … Never consumer-facing» (`getff-name-architecture-freeze.md:19`). PR #1358's watch-list W-11 offered «four of the six siblings» as the alternative; that one is accurate, so that one is taken. **Row 2 — `1346-r1-1` (IMMATERIAL) — NOT a defect; deliberately untouched.** The register describes it as a one-word scope edit awaiting someone to make it. Reading the source finding says otherwise — PR #1346's fidelity report closes it with: «the narrowing matches v3 §4's substance (the D7-owned half is the Stop-hook fork). **Accept or widen at the operator's discretion.**» It is a recorded operator fork, not an undone task, and the reviewer who filed it explicitly declined to price it. Two further facts measured here: the counterpart phrasing is **cross-document** (`grep "any landing"` over `session-bus-v2.md` returns nothing — the unscoped wording lives only in `autonomous-night-v3-design.md:375`), so v2 is not self-inconsistent; and both readings are substantively defensible. Silently picking one would be a reviewer deciding strategy, which [reviewer-discipline.md](/.claude/rules/reviewer-discipline.md) forbids. **Surfaced, not resolved** — one word, either way, whenever the operator says which. ## Changes - `packages/core/templates/shared/AGENTS.md.template` — factory row names both gated sub-agents, plus the fact that every other shipped agent installs from `core` up (verified: the `agents/*.md` loop at `20-agents.sh:23` carries no profile condition; the other `case` arms are `continue` skips for authoring-only tools). - `tests/install-sh/baselines/**` — re-captured. The diff is exactly the `AGENTS.md` hash in the 11 stacks that ship it; cargo and go do not ship it and their baselines are byte-untouched. - `tests/install-sh/fence-agents-coownership.test.sh` — new §3 arm reconciling the two lists. - `docs/meta-factory/getff-name-architecture-freeze.md:194` — the quantifier. ## Why the gate lives in an existing test file A doc claim about install behaviour whose only guard is «someone will notice» is `#hope-as-gate` ([attention-is-not-a-mechanism.md §2](/.claude/rules/attention-is-not-a-mechanism.md)) — which is precisely how this survived a full review round and landed in a register instead of a diff. So the claim is now mechanical. Three deliberate choices: - **Host = `fence-agents-coownership.test.sh`, not a new file.** That file is already wired into CI (`audit-self.yml:568`), so the gate costs no new workflow step and adds nothing to the sweep↔CI parity bookkeeping that principles 36/37/38 police. A new test file would have needed wiring in two places to avoid becoming a test nobody runs. - **Extraction is structural, not a name list.** The check `awk`s the gated `case`-arm out of `20-agents.sh`, so adding a *third* factory-gated agent fails this until the template names it too. A hard-coded pair would have gone stale the same way the doc did. - **Proven RED on the defect, not merely green after the fix.** Run against `origin/staging`'s template the counter reports both agents missing. And the paired negative (strip one gated name from a copy, re-run the *same* counter) bites — so the positive assertion is not vacuous. ## Prior-art consult - [x] Neither commit is a capability commit: `*.md`/`*.template` never count, and the bash arm is ~40 lines inside an existing `tests/` file — not a new `packages/` module and no new dependency. Trailers carried on both commits. - [x] No new capability area surfaced; no SSOT entry matched or needed. - [x] context7 n/a. ## Test plan - [x] `bash tests/install-sh/fence-agents-coownership.test.sh` — **20 pass / 0 fail** (was 17; +3 arms +1 count assertion). - [x] Gate fires on the real defect: counter run against `git show origin/staging:…AGENTS.md.template` reports `MISSING: orchestrator-worker-discipline reviewer-discipline`. - [x] `SNAPSHOT_MODE=compare bash tests/install-sh/snapshot.sh` — 15 pass / 0 fail after re-capture. - [x] `npm run --prefix packages/core test:principles` — exit 0. - [x] `npm run format:check` — green (the template IS prettier-checked via `format-shipped.sh` despite the `.template` extension; the edit forced a table realign, which is the 5-row churn in that file). - [x] `bash tests/agnosticism/probes/doc-claims.sh` — PORTABLE, unchanged. - [x] `shellcheck tests/install-sh/fence-agents-coownership.test.sh` — no findings from the added code (the four SC2034s are pre-existing dispatcher-scope vars). ## Provenance n/a — non-stage PR (register repair, no kickoff). ## Review findings n/a — non-stage PR. Row 2's disposition is itself a review finding left open by its author; it is surfaced above rather than decided here. ## Fidelity verdict FIDELITY: skipped — non-stage repair PR against a published register; no kickoff or fidelity contour applies to it. ## Parked questions 1. **Row 2 (`1346-r1-1`)** — accept the narrowing or widen `session-bus-v2.md:447` to the unscoped «any landing»? Operator's call, per the filing reviewer. One word either way. 2. **The `factory` detector itself** — see the GAP-FOUND in the backward-check below. Not touched here. ## §1.7 Self-discipline check ### §1.7 Forward-check applied - `.claude/rules/attention-is-not-a-mechanism.md:17` — «a load-bearing check MUST be one of: (a) a deterministic gate at the earliest reachable channel». Row 1's drift is the textbook `#hope-as-gate` named at `.claude/rules/attention-is-not-a-mechanism.md:28` («a check whose failure mode is «nobody looked»»), so the repair is paired with arm (a) at a channel that already runs — `tests/install-sh/fence-agents-coownership.test.sh:214` — not with a promise to be careful. - `.claude/rules/reviewer-discipline.md:7` — §2 «surface-as-decision-needed» + the `#strategy-decided-by-reviewer` anti-pattern: the reason row 2 is surfaced rather than repaired, given its filing reviewer had already routed it to the operator. - `.claude/rules/effort-worthiness.md:37` — the four-test card, applied to the gate: test 2 (theatre) fails it only if the assertion cannot bite, which is why the paired negative exists; test 4 («cheaper to verify in practice») is already answered by practice, since the drift happened once and cost a review round. - `.claude/rules/ai-laziness-traps.md:60` — T3 «No prose-only findings»: every register row was re-verified against the live tree before acting, which is what caught the `:146`→`:194` address error, the factually-wrong suggested qualifier in row 3, and the mis-framing of row 2. - `CLAUDE.md:89` — «do NOT autonomously open an additional PR … surface it as an observation»: the sweep's GAP-FOUND below is surfaced, not fixed, because it is a second concern carrying its own decision. ### §1.7 Backward-check applied Class of this change = **doc claims about what an install profile puts on disk, which no mechanism reconciles with `setup.d/`**. Enumerated by sweeping shipped templates and docs for profile-composition language (`grep -rln "profile factory\|--profile\|operator suite"` over `packages/core/templates/`, `docs/`, `.claude/`), then verdicted per surface: - **`packages/core/templates/shared/AI-USAGE-GUIDE.md:41-42` — GAP-FOUND, not fixed here.** It says «`factory` additionally puts `.claude/skills/pipeline/` there», but `pipeline` moved to the `env` tier (`setup.d/lib.sh:59` `GETFF_SKILLS_ENV="arch pipeline"`, gate at `setup.d/10-skills.sh:134`). The same claim is the *detector* in the file this PR edits (`AGENTS.md.template:30`, «also `.claude/skills/pipeline/` present» = `factory`), so an `env` install matches the `factory` row in both shipped docs. Action: separate PR; the accurate discriminator is `.claude/skills/dispatcher/` (`lib.sh:60` factory-only), but which marker to standardise on is a decision, not a typo — parked question 2. - **`packages/core/templates/shared/tier-home.md`** — SWEPT-CLEAN: it owns tier *criteria* and the degradation matrix, and states no per-profile file inventory, so there is no list to reconcile. - **`docs/superpowers/specs/2026-07-23-beta-program-design.md:211`** — SWEPT-CLEAN as a *source*, not a claim: `10-skills.sh:126-128` cites this line as the authority that moved `pipeline` to `env`. It is the reason the two shipped docs above are stale, and it is itself correct. - **`.claude/orchestrator-prompts/**` hits** (`beta-delivery-ux/kickoff*.md`, `beta-ai-docs-agnosticism-meta-launch/state.md`, …) — SWEPT-CLEAN by category: closed dispatch inputs, header-exempt and non-normative per [doc-authority-hierarchy.md §2](/.claude/rules/doc-authority-hierarchy.md); they must not be retro-edited. - **`docs/meta-factory/research-patches/**` hits** — SWEPT-CLEAN by category: append-only historical artefacts (folder charter). Notably this includes the S4b audit that *produced* the register — its rows are the record of what was true when audited, so the two register inaccuracies found here are reported in this PR body rather than edited into the patch. - **`setup.d/20-agents.sh` ↔ template** — the pair this PR closes; now GATED rather than swept. The surface list is not the diff's file list: the diff touches 4 paths, the sweep verdicts six surfaces, five of which are outside it, and it produced one real GAP the diff does not fix.
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.
What this is
beta-delivery-ux R1 — npm release mechanics (spec A6, absorbs U10-prep + U11). Prepares
packages/corefor publication without performing any registry-visible act: a name-architecture freeze record, afilesallowlist validated by a real tarball matrix cell, bin runnability (fork F-C′ resolved in-stage), and package metadata.packages/core/package.jsonkeeps"private": truethroughout (packages/core/package.json:4) — npm refuses to publish a private package, so the guard is a mechanism, not a reminder. Nothing was published; no registry write occurred.Over-ship moved 707 → 494 files (−30%), measured by
npm pack --dry-runbefore and after thefilesallowlist. Both numbers live in the freeze record (docs/meta-factory/getff-name-architecture-freeze.md:177), not only here — kickoff §6 item 7 makes the record, not this PR body, the artifact U10 reads.Provenance
7a12c5bc-9be7-4825-b2fd-a7ca91af3a5d, branchfeature/beta-delivery-ux-7a12c5..claude/orchestrator-prompts/beta-delivery-ux/kickoff-r1.md(rev 2).git push, per.claude/rules/egress-no-api-bypass.md:14. The container's 4 commits were bundled out, fetched to the host, rebased onto liveorigin/staging, and pushed from the host so.husky/pre-pushran for real. The API break-glass path was not used (host transport was alive).Acceptance (kickoff §6) — evidence
bash scripts/host-verify.sh …/kickoff-r1.md→ 2/2 PASS on Darwin; job at.github/workflows/audit-self.yml:1607,ci-successneeds:line at.github/workflows/audit-self.yml:1673filesentry carries paired RED→GREEN, or is marked unvalidateddocs/meta-factory/getff-name-architecture-freeze.md:150. 10 RED, 4 GREEN (validator/,ir/,backends/,composition/) markedUNVALIDATED-by-this-celltests/consumer-matrix/npm-tarball-cell.sh:219—rules-as-tests-detect --helpand a real detect run, both from the installed packagebash tests/consumer-matrix/pnpm-monorepo-cell.shPASS in the same host-verify run; the coverage split is stated atdocs/meta-factory/getff-name-architecture-freeze.md:197private: trueuntouchedpackages/core/package.json:4— context line in the diff, not a+/-npm publish/owner/accesswrite form ran;private: trueis the shipped guarddocs/meta-factory/getff-name-architecture-freeze.md:1— family table,getff init→./setupmapping, §0.5 gap, version floor, probe table with its control pair, rollback doctrinedocs/meta-factory/getff-name-architecture-freeze.md:177Three
#contract-that-cannot-failholes closed at harvest timeThe stage shipped three asserts named for a class they did not test. Each was found by running an arm, not by reading, and each fix carries a two-direction proof.
tsxdemoted todevDependenciesthe bin still ran, because the#!/usr/bin/env -S npx tsxshebang makesnpxsilently network-install it (npm warn exec … will be installed: tsx@4.23.12— unpinned, ignoring the declared^4.22.4), withtsxconfirmed absent from the fixture. New step (7a) attests/consumer-matrix/npm-tarball-cell.sh:211assertstsxarrived. GREEN rc=0 with it as a dependency, RED rc=1 without. The recorded F-C′ rationale was wrong and is corrected in place: the real cost of not promotingtsxis a silent unpinned runtime network fetch that breaks offline, not «the bin fails».readFileSync(...).length > 100passes on any file over 100 bytes, so a truncated bundle shipped green. Replaced attests/consumer-matrix/npm-tarball-cell.sh:167withnode --check+ entry-guard grep + tail-export grep. Each was chosen by measurement:node --checkalone passes on a 200-byte head (a 50 KB head fails), andawait import()was rejected on evidence — it throws regardless of integrity, because the bundle has a module-level side effect openinginstall/research-plan.schema.jsonrelative to cwd. Two-direction proof: intact rc=0, bundle truncated to 50 KB rc=1.tests/consumer-matrix/pnpm-monorepo-cell.sh:206, which plants a violation and assertseslint rc=1with the R2 message; both cells are merge-blocking and both are in this kickoff's host-verify contract. The residual uncovered class is named rather than implied, atdocs/meta-factory/getff-name-architecture-freeze.md:197.§1.7 Forward-check applied
Checked against the disciplines this change is subject to, each with the artifact consulted:
.claude/rules/attention-is-not-a-mechanism.md:20— a load-bearing check must be a deterministic gate or a named cold-agent protocol, never bare attention. All three fixes above convert a printed claim into a failing predicate; theci-successneeds:line at.github/workflows/audit-self.yml:1673is what keeps the cell merge-blocking rather than advisory..claude/rules/destination-environment-verification.md:283— the#contract-that-cannot-failanti-pattern is the exact shape of all three holes: block present, commands execute, exit 0, and the defect class ungated. The kickoff's ownhost-verifycontract (kickoff-r1.md:290) was run on the host, not inferred from a container run: 2/2 PASS on Darwin..claude/rules/egress-no-api-bypass.md:14— Channel A (host-push) used, so.husky/pre-pushran. It earned its place: the container-side commit had bypassed husky and left two MD040 violations in the record, caught and fixed atdocs/meta-factory/getff-name-architecture-freeze.md:39..claude/rules/no-paid-llm-in-ci.md— the new cell is deterministic bash + node; zero API-billed calls. The cold audits are session-read agents, never CI..claude/rules/ci-tool-pinning.md— both actions in the new job are SHA-pinned (.github/workflows/audit-self.yml:1613,:1616).CLAUDE.mdcapability-commit gate — no new dependency key was added without a matching removal (tsxmoved tier), no new ≥80-LOC non-doc file underpackages/; the new cell lives undertests/. Every commit carries aPrior-art:line with a ≥20-char rationale.§1.7 Backward-check applied
Class of this change = npm publish metadata on a workspace package + a new merge-blocking consumer-matrix cell wired at all three channels. The sweep was delegated cold to
agents/backward-sweep-auditor.md, handed only the class — never this diff or narrative. It enumerated 24 sibling surfaces; verdicts on those the diff does not touch:.husky/pre-pushcell invocation — GAP-FOUND: it runs zero consumer-matrix cells, while.claude/orchestrator-prompts/launch-preannounce-track/kickoff.md:46specifies «pre-push runs the start cell only». Design-vs-reality drift, pre-existing, not this PR's.ci-successneeds:completeness — GAP-FOUND:shipped-prettier(.github/workflows/audit-self.yml:99) andframework-fresh-install-validate-multistack(.github/workflows/audit-self.yml:1094) are defined but absent from theneeds:list — they can go RED whileci-successis green. This is the same defect class this PR closes for its own cell, one level out. Deliberately not fixed here perCLAUDE.md«PR strategy» (incident PR chore(pr-template): add §1.7 forward+backward stubs + Skipped guidance #33); surfaced for a separate task.scripts/ci-success-gate.sh:28validates results of already-listed jobs only, and its own header at:6claims audit-self.yml «needs: every audit-self PR job», which is false. The two gaps above are the predicted output of a bare-attention check.python-unfamiliar-stack-cell.sh:39— GAP-FOUND: claims it runs undermake consumer-matrix; no such target line exists for it. Sibling of the defect this PR fixed for its own cell.packages/corepeerDependencies— GAP-FOUND: absent, while all four preset/meta siblings declare one (packages/preset-react-spa/package.json:15,packages/meta-factory/package.json:13). Travels with U10's dependency-tier decision.install.sh/setup.d/**— SWEPT-CLEAN by separation: they reach only non-shipped dirs (packages/core/audit-self,hooks,probes,principles), so afilesallowlist change cannot break the file-copy channel..github/release-drafter.yml:15autolabels all six conventional prefixes; workflow SHA-pinned, draft-only.package.jsonunderplugin/, so allowlist and dependency-tier do not apply; twin byte-identity is enforced bypackages/core/principles/24-plugin-manifest-integrity.test.ts:267.lint-config,meta-factory, three presets,runtime-bridge) — SWEPT-CLEAN: allprivate: true, none publish-intended, no metadata inconsistent with the class.One sweep finding was in scope, because it deepens R1's own recorded gap rather than a sibling's, and it is now in the record at
docs/meta-factory/getff-name-architecture-freeze.md:136: promotingeslinttodependenciesis necessary but not sufficient for U10. Four shipped validator gates statically import@rules-as-tests/preset-next-15-canonical/eslint-rules(packages/core/validator/gate-tautology.ts:15,gate-conflict.ts:21,gate-rule-tester.ts:22,gate-message-id-coverage.ts:21); that package isprivate: true(packages/preset-next-15-canonical/package.json:4); andnpm pack --dry-runconfirms the importing gate files do ship. Sorules-as-tests-validatestays unrunnable from a published tarball until U10 picks one of three named options. R1 does not pick — kickoff §7 forbids touching a package outsidepackages/core.Fidelity verdict
Review findings
Three cold rounds ran against this branch: fidelity round 1 (REVISE, 2 MAJOR), round 2 (GO after both closed), round 3 (GO, narrow delta re-establishing the SHA), plus one cold backward sweep. Two MINORs remain open and deliberately unfixed — each further edit to the same paragraph produced a new MINOR, which is the signal to stop editing and disclose:
docs/meta-factory/getff-name-architecture-freeze.md:146says «all four siblings» wherepackages/holds six siblings ofcore. Fix is one qualifier: «four of the six siblings», or restore «publishable-intent».packages/core/package.json:11declaresrepository.urlasgithub.com/Yhooi2/rules-as-tests-aif, plus matchinghomepage:14andbugs:16, whilegit remote -vshowsorigin=git@github.com:artyhoo/getff.gitand the plugin channel already declaresartyhoo/getff(plugin/.claude-plugin/plugin.json:7). Not broken:gh api repos/Yhooi2/rules-as-tests-aifresolves toartyhoo/getff— GitHub redirects the old name — so the published URLs work. It is stale, not wrong. Belongs with the U9 rename, which owns the naming surface.Watch-list
packages/corestays"private": truepackages/core/package.json:4, orfalseci-successneeds:consumer-matrix-npm-tarball-cellgone from theneeds:list while the job at:1607remainsmake consumer-matrixnpm-tarball-cell.shinvoked only from the standalone target, not the aggregatenode --checkalone passes on a 200-byte headreadFileSync().length/ bareawait import()form backnpxsilently network-installs an unpinnedtsx, so «the bin ran» proves nothingtest -d "$FIXTURE/node_modules/tsx"removed, leaving only the bin-execution assertfilesentries stay in, markedUNVALIDATED-by-this-cell, or the marking softenedCorrection (2026-08-10, measured)blocks survive@getfforg row staysUNRESOLVEDUNRESOLVED — needs npm access list packages @getff …peerDependencies; an unqualified «all four» misstates the set U10 inheritsParked questions
@getffscope ownership — UNRESOLVED, and it is a U10 gate, not an R1 one.npm whoamireturnsENEEDAUTHon both the container and the host, so the authenticated read cannot run. Recorded rather than guessed, per kickoff §0.2: an unauthenticated probe returns the same empty result as a foreign scope, and only a different owner is a stop. Closing command:npm access list packages @getffunder an authenticated account (npm loginis an operator act). Record:docs/meta-factory/getff-name-architecture-freeze.md:88.getffCLI package does not exist — no package declaresbin: getff;packages/coreships sixrules-as-tests-*bins. U10's own gate isnpx getff init. Parked with options per kickoff §9, recorded atdocs/meta-factory/getff-name-architecture-freeze.md:36.ci-success needs:holes (backward-check above) — two jobs unlisted, and no mechanism enforcing jobs ⊆ needs. Surfaced, not fixed, perCLAUDE.md«PR strategy». Worth a separate task; the mechanism belongs inscripts/ci-success-gate.sh:28.Known-red, pre-existing (not introduced by this branch)
bash scripts/run-local-ci-sweep.sh --fullreports 11 gates PASS andvitest-hooksFAIL. Verified against the merge base: on cleanorigin/stagingthe same gate fails harder — 16 tests / 8 files versus 12 / 6 on this branch — and the failing set varies between runs (worktree- andnode_modules-provisioning sensitive). Surfaced, not attributed to this harvest, per the sweep's own interpretation rule.