Skip to content

fix(install): consumer-install-hardening S1 — make claimed shields live in consumers (F6/F1/F12/F2/F11/F13) - #474

Merged
artyhoo merged 1 commit into
stagingfrom
cih-s1-install
Jun 13, 2026
Merged

fix(install): consumer-install-hardening S1 — make claimed shields live in consumers (F6/F1/F12/F2/F11/F13)#474
artyhoo merged 1 commit into
stagingfrom
cih-s1-install

Conversation

@artyhoo

@artyhoo artyhoo commented Jun 13, 2026

Copy link
Copy Markdown
Owner

consumer-install-hardening — Stage S1 (install-side)

Fixes the framework install defects the timeliner consumer audit found (CONSUMER-FINDINGS-timeliner.md, F1–F13). S1 makes every shield the framework claims to ship actually live in a fresh consumer — hooks fire, the TS pre-push core is reachable, the R4 probe resolves, R11's claim matches shipped CI, and the stryker/doc-URL artefacts are correct.

Base = staging (clean). FQA (#470) is already merged to staging; S1 extends it and does not redo F4/W1/W2/W4/W6. Landed via the Git Data API (git transport is tunnel-blocked: github.com:22/:443 down, api.github.com up) — one commit parented directly on the live staging tip, overriding only the 14 S1 paths, so #464's audit-consumer-mode CI step and every other staging delta are preserved (verified: PR diff = 14 files, zero FQA re-apply).

Findings — status + acceptance evidence

F# Sev Fix Acceptance (evidenced on a fresh ts-server install, paired-negative test under tests/install-sh/)
F6 P2 ship audit-r4.tsscripts/ (FQA-drop correction) scripts/audit-r4.ts present and shipped audit-ai-docs.sh still references it (load-bearing neg) — audit-r4-shipped.test.sh 2/2
F1 P1 ship pre-push.ts + 5-file bounded static closure all closure files present; bash fallback still shipped (additive); guard-liveness stays dynamic-import — f1-ts-arm.test.sh 7/7
F12 P2 ship workflow-integrity.yml + align R11 claim via manifest SSOT (regenerate RULES.md) R11 names only shipped artefacts; no actionlint/zizmor/audit-self over-claim — f12-workflow-integrity-shipped.test.sh 5/5
F2 P1 install activates hooks (core.hooksPath=.husky) + declares husky/lint-staged/sort-package-json devDeps fresh repo dead-state → install → hooksPath set + 3 devDeps merged + idempotent — f2-hook-activation.test.sh 6/6
F13 P3 repoint 3 RuleCreator doc-URLs → canonical RULES.md + stryker PM from lockfile factory/RULES.md gone from eslint-rules; pnpm/npm PM detected — f13-stryker-pm.test.sh 2/2
F11 P3 fix already landed (FQA W6 — CI reads node-version-file:.nvmrc); this PR adds the executable lock f11-ci-node-version.test.sh 6/6 (ts-server + react-next): pos node-version-file, neg no bare node-version: hardcode, .nvmrc non-empty
CI wire all 6 new install-sh tests into audit-self.yml, preserving #464's audit-consumer-mode step full tests/install-sh/ suite 13/13 green locally

Own-QA (T19): I re-ran every install-sh acceptance on this branch — 13/13 green (the 6 S1 tests above + 7 pre-existing). The full principle suite + self-install + drift gates run in CI on this PR (cited, not claimed locally). F6/F1/F2/F12/F13 were verified to pass before I built F11 + the #464 reconciliation on top.

Verify-trace

  • Full tests/install-sh/ suite green on this branch — 13/13 (audit-r4-shipped 2/2, f1-ts-arm 7/7, f2-hook-activation 6/6, f12-workflow-integrity-shipped 5/5, f13-stryker-pm 2/2, f11-ci-node-version 6/6)
  • Fresh ts-server install ships audit-r4.ts / pre-push.ts+closure / workflow-integrity.yml; sets core.hooksPath; CI reads node-version-file; detects stryker PM
  • PR diff = exactly 14 S1 paths, zero FQA re-apply (fix(audit-self): skip authoring-repo probes D3/D5 on consumer installs #464 + staging deltas preserved); audit-self.yml diff vs live staging = only the 6 S1 steps added
  • F2 hook proven LIVE (runtime): in a fresh ts-server install + npm install, git commit of a staged file FIRES the pre-commit hook (lint-staged runs) and BLOCKS the commit (exit 1, no commit landed) — the activated hook is not dead-from-the-box
  • CI on this PR (principle suite / manifest→RULES.md drift / self-install / typecheck) — running; merge when green
  • F2 lint-error-specific arm (deferred — F4/F3, not F2): "eslint catches a deliberate lint error → commit blocked" can't be shown in a fresh consumer because the shipped eslint.config.mjs does not load (missing @eslint/js + eslint-config-prettier peer-deps, ./eslint-rules-local/index.ts .ts-import needs a loader, eslint v8-vs-v9 flat-config mismatch) and eslint/prettier aren't consumer devDeps. Not an offline limitation (npm registry reachable). Defer to S4 / after F4 completion.
  • S4 live-consumer (deferred to Stage S4): fresh install on a real flat-Hono consumer AND a monorepo; TS pre-push core loads on pinned Node 20.19.0 (F1 runtime)

§1.7 Forward-check applied

Change checked against existing disciplines. build-first-reuse / capability-commit — no new capability (ships/aligns existing artefacts; no new packages/ file ≥80 LOC, no new root package.json dep), so the commit carries Prior-art: skipped. The push itself reuses harvest-via-api.sh (the repo's Git-Data-API helper), not a new mechanism. no-paid-llm-in-ci — every acceptance is bash/node/vitest, zero API-billed calls. doc-authority-hierarchy / principle 05 — F12 edits the manifest SSOT and regenerates RULES.md (not a hand-edit of generated output). dual-implementation — install-side single channel, no dual-channel artefact introduced. Serves the README goal directly: the fixes make claimed rules executable + live at the earliest channel in the consumer. Evidence: install.sh:362 (F6 copy), install.sh:387-394 (F1 closure loop), packages/core/manifest/rules-manifest.json R11 check (F12), install.sh hooksPath+devDeps block (F2), packages/core/eslint-rules/*.ts:6-7 (F13), tests/install-sh/f11-ci-node-version.test.sh (F11 lock).

§1.7 Backward-check applied

Swept existing artefacts under this change's scope. Extends FQA, no redo: F4 barrel already generated; W1/W2/W4/W6 untouched. Corrects FQA: F6 (audit-r4 orphan FQA dropped after a partial caller-grep) is shipped with a caller-reference negative arm. Preserves the staging delta: the branch base predated #464, so its audit-consumer-mode audit-self.yml step was re-added ahead of the S1 steps and the Data-API push overrides only S1 paths — #464 is not clobbered (verified: PR shows zero FQA files). F11 verified already-satisfied by FQA W6, so this PR adds only the regression lock, not a duplicate fix. No existing artefact silently superseded. Same-defect-class residue outside S1 scope was surfaced, not swept (below).

Out-of-scope observations (surfaced per atomic-umbrella discipline — NOT fixed here)

  1. Same F13 defect class, react-next stack: packages/preset-next-15-canonical/eslint-rules/{require-use-server-directive,no-server-imports-in-client,require-form-safe-parse}.ts point at absent factory/RULES.react-next.md. Candidate S2 follow-up.
  2. rules-manifest.json R11 policy (and workflow-integrity.yml comment) may still reference factory/RULES.md — F13 doc-URL class.
  3. install.sh "Next steps" echo still prints npx husky init — now redundant after F2 auto-activation, and would re-init the shipped hooks; F2/S2 prose follow-up.
  4. c1-wiring.test.sh is unwired in audit-self.yml (pre-existing) — not wired here.
  5. F4 peer-dep gap (discovered while runtime-smoking F2): the shipped templates/ts-server/eslint.config.mjs doesn't load in a fresh consumer — needs @eslint/js + eslint-config-prettier (beyond the @typescript-eslint/utils/eslint-plugin-vitest/globals the F4 finding listed), a .ts-import loader for ./eslint-rules-local/index.ts, and eslint 9 (flat eslint/config). Until fixed, the consumer's edit-time/pre-commit ESLint shield is inert. F4/S2 follow-up.

Process note

PR was originally opened by a parallel session mis-based on the (already-merged) FQA branch and missing F11. This branch was force-updated to the clean staging-based commit and the PR retargeted to staging (operator-authorized). Prior branch content discarded (no reviews; strictly worse base).

Scope

IN: S1 install-side fixes (F6/F1/F12/F2/F11/F13) + CI test-wiring. OUT: S2 docs (F8/F9), S3 glob design-forks (F3/F5/F7 — maintainer GO pending), S4 live re-verify. timeliner consumer repo untouched (it's the polygon).

🤖 Generated with Claude Code

…ixes + F11 lock

Make every shield the framework claims actually live in a real consumer:
- F6  ship scripts/audit-r4.ts so the R4 probe in audit-ai-docs.sh resolves
- F1  ship pre-push.ts + static import closure so the dispatcher TS-arm is reachable
- F2  activate shipped git hooks (core.hooksPath=.husky) + declare husky/lint-staged/sort-package-json devDeps
- F12 ship workflow-integrity.yml + align RULES.md R11 claim to shipped CI (manifest SSOT)
- F13 detect stryker packageManager from consumer lockfile + repoint RuleCreator doc-URLs to canonical RULES.md
- F11 lock: shipped CI reads node-version-file:.nvmrc (already true via FQA W6) + paired-negative guard

Each fix carries a paired-negative install-sh acceptance under tests/install-sh/
(14 wired into audit-self.yml). Full install-sh suite: 13/13 green. Bases on
live staging via Git Data API (git transport down); #464 audit-consumer-mode
CI step preserved.

Prior-art: skipped — install-side delivery fixes shipping existing artefacts; per-finding rationale in the umbrella findings file, no new framework capability
@artyhoo
artyhoo changed the base branch from claude/loving-swirles-5689ff to staging June 13, 2026 12:04
@artyhoo
artyhoo merged commit b6d3be6 into staging Jun 13, 2026
26 checks passed
artyhoo added a commit that referenced this pull request Jun 13, 2026
…md) (#493)

Umbrella-closure marker: S1 #474, S2 #479/#480/#481/#485, S3 globs #486, S3 F14 #490, S3 V2 #491 all merged to staging; staging→main promotion tracked separately in #488. Closure per CLAUDE.md convention (priority-score.sh Layer C3).
artyhoo added a commit that referenced this pull request Jun 22, 2026
…#678)

The render-rules vitest snapshot (packages/core/render/__snapshots__/render-rules.test.ts.snap)
expected R11's old framework-internal description (`audit-self.yml ...`), but the manifest R11
row was deliberately updated to the consumer-facing `ci.yml (...)` description in #474
(consumer-install-hardening). RULES.md was regenerated then; the vitest .snap was not — so
`vitest run render/` was red on a full local run while CI stayed green, because only principles/
and hooks/ were gated. The render/ suite was never wired into CI or pre-push.

- Regenerate the stale snapshot to match the current manifest render (the manifest is the
  deliberate source of truth; the .snap was the stale frozen copy).
- Add `test:render` (`vitest run render/`) script to packages/core.
- Gate the render/ suite in the principles-meta-tests CI job, mirroring the existing
  "CI-gap option C" hooks-suite precedent. Deterministic, no LLM (complies with
  no-paid-llm-in-ci.md).

The manifest→RULES.md `--check` job already catches RULES.md drift; this closes the parallel
gap for the vitest snapshot so the same staleness cannot recur silently.

Prior-art: skipped — snapshot regen + CI-wiring of an existing test, no new dependency/module/capability surface.

Co-authored-by: Art <devartyhoo@gmail.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