Skip to content

Commit f328453

Browse files
Remove CI inbox hook surface
1 parent 52430c6 commit f328453

36 files changed

Lines changed: 1149 additions & 1678 deletions

.claude/hooks/guards/bash-policy-checks.mjs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const readCommands = new Set([
1212
"head",
1313
"less",
1414
"more",
15+
"nl",
1516
"rg",
1617
"sed",
1718
"tail",
@@ -30,6 +31,10 @@ const safeEnvTemplates = new Set([
3031
".env.sample",
3132
".env.template",
3233
]);
34+
35+
export function isReadCommandName(name) {
36+
return readCommands.has(name);
37+
}
3338
export function evaluateBashPolicy(input, env = process.env) {
3439
if (!isBashPayload(input)) {
3540
return allowResult();
@@ -131,7 +136,7 @@ function checkSecretEnvFileRead(command) {
131136
const matches = [];
132137
for (const tokens of commandSegments(stripHeredocs(command))) {
133138
const start = commandStart(tokens);
134-
if (!readCommands.has(tokens[start] ?? "")) {
139+
if (!isReadCommandName(tokens[start] ?? "")) {
135140
continue;
136141
}
137142
for (const token of tokens.slice(start + 1)) {
@@ -313,7 +318,8 @@ function nestedShellCommand(tokens) {
313318
const args = commandArgs(tokens);
314319
for (let index = 0; index < args.length - 1; index += 1) {
315320
if (shellCommandOption(args[index] ?? "")) {
316-
return args[index + 1];
321+
const commandIndex = nestedShellCommandIndex(args, index + 1);
322+
return args[commandIndex];
317323
}
318324
}
319325
}
@@ -322,6 +328,14 @@ function shellCommandOption(value) {
322328
return value.startsWith("-") && value.slice(1).includes("c");
323329
}
324330

331+
function nestedShellCommandIndex(args, start) {
332+
let index = start;
333+
while (args[index] === "--") {
334+
index += 1;
335+
}
336+
return index;
337+
}
338+
325339
function parseShellAst(command) {
326340
const segments = [];
327341
let current = [];

.claude/hooks/sync-llm-on-claude-surface-change.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function editTargets(payload, projectDir) {
6464
function editTargetsForTool(toolPayload, projectDir) {
6565
const toolName = toolNameOf(toolPayload);
6666
const input = toolInputOf(toolPayload);
67-
if (toolName === "apply_patch") {
67+
if (toolName === "apply_patch" || toolName === "functions.apply_patch") {
6868
return patchTargets(patchTextFromInput(input), projectDir);
6969
}
7070
if (typeof input.file_path === "string" && input.file_path.length > 0) {

.claude/rules/09-ci-cd-efficiency-governance.md

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ This repo is a single-package npm TypeScript CLI/library with private local Pyth
2828

2929
## Workflow map
3030

31-
The complete public CI surface is the seven tracked workflows under `.github/workflows/`:
31+
The complete public CI surface is the six tracked workflows under `.github/workflows/`:
3232

3333
- `ci.yml` — the pull-request and `main`-push gate. Three jobs:
3434
- `quality` (matrix `node-version: [22, 24]`, no database): `npm ci`, `npm audit signatures`, `npm run build`, `npm run lint:ci` (Biome `biome ci .`), `npm run typecheck`, `npm run guard`, `npm run check:schema`, `npm run check:package`, then packs the tarball and smoke-tests `npx supaschema --version|diff|check`. On Node 22 only, CI prepares the alternate consumer package managers required by Rule 13, runs `npm run package:smoke`, and runs the shipped `examples/` render+check plus `npm run test:examples`.
@@ -39,14 +39,13 @@ The complete public CI surface is the seven tracked workflows under `.github/wor
3939
- `codeql.yml` — CodeQL static analysis matrix (`actions`, `javascript-typescript`) with the `security-and-quality` query suite and explicit no-build mode, on push/PR to `main` and a weekly schedule. These lanes have no dependency install.
4040
- `scorecard.yml` — OpenSSF Scorecard on `main` push + weekly schedule, uploading SARIF.
4141
- `docs.yml` — path-filtered (`docs/**`, `package.json`, `package-lock.json`, the workflow itself) Mintlify validation via `npm run docs:check`.
42-
- `ci-failure-report.yml` — pull-request DX reporter. It runs after every completed `workflow_run` for `CI`, `Docs`, `CodeQL`, and `Dependency Review` when the source event was `pull_request`. Failed source workflows write or update one trusted PR marker comment for local Claude/Codex inbox hooks to read, including workflow-level failures when failed job details are unavailable. Successful and other non-failure source workflows clear only the matching current-head workflow marker so unrelated failures remain visible.
4342

4443
## Hard rules
4544

4645
- Every workflow declares a top-level least-privilege `permissions:` block, defaulting to `contents: read` (or `read-all`). A job elevates only the exact scopes it needs: `release.yml`'s `publish` job adds `contents: write` for GitHub Release/tag creation plus `id-token: write` and `attestations: write` for trusted publishing/provenance; `codeql.yml`/`scorecard.yml` add `security-events: write` (+ `id-token: write` for Scorecard). Never grant write at the top level.
4746
- All `uses:` refs are pinned to full-length commit SHAs with an adjacent version comment (for example `# v6.0.3`) for Dependabot readability. The executable ref must be immutable — never a tag or branch. This is the OpenSSF Scorecard "Pinned-Dependencies" check and a STOP condition if violated.
48-
- `actions/checkout` uses `persist-credentials: false` on every tracked workflow's checkout (`ci.yml`, `dependency-review.yml`, `scorecard.yml`, `release.yml`, `codeql.yml`, `docs.yml`, `ci-failure-report.yml`); release re-supplies an explicit `GH_TOKEN`/`registry-url` only where a step needs it.
49-
- Every job declares a `timeout-minutes` ceiling so no lane can hang at the 360-minute default — least of all the privileged `release.yml` `publish` job (`ci.yml` 20/30/20, `dependency-review.yml` 10, `release.yml` 30, `codeql.yml`/`scorecard.yml` 20, `docs.yml` 15, `ci-failure-report.yml` 10).
47+
- `actions/checkout` uses `persist-credentials: false` on every tracked workflow's checkout (`ci.yml`, `dependency-review.yml`, `scorecard.yml`, `release.yml`, `codeql.yml`, `docs.yml`); release re-supplies an explicit `GH_TOKEN`/`registry-url` only where a step needs it.
48+
- Every job declares a `timeout-minutes` ceiling so no lane can hang at the 360-minute default — least of all the privileged `release.yml` `publish` job (`ci.yml` 20/30/20, `dependency-review.yml` 10, `release.yml` 30, `codeql.yml`/`scorecard.yml` 20, `docs.yml` 15).
5049
- The privileged `release.yml` `publish` job runs `step-security/harden-runner` for egress monitoring. It ships in `egress-policy: audit` with the candidate `allowed-endpoints` list commented inline; tightening to `egress-policy: block` happens only after reviewing a real run's network insights. Do not remove harden-runner from the OIDC-holding job.
5150
- Releases publish through npm OIDC trusted publishing, not a stored npm token: the job runs on a GitHub-hosted runner with Node 24, asserts `npm >= 11.5.1`, sets `registry-url: https://registry.npmjs.org`, disables package-manager caching on the privileged publish path, and runs `npm publish "$SUPASCHEMA_TARBALL" --access public --provenance`. npm trusted publishing already generates provenance; `--provenance` remains explicit repo policy. Tarball provenance is attested with `actions/attest@v4`. Do not reintroduce a long-lived `NPM_TOKEN`/`NODE_AUTH_TOKEN` secret.
5251
- `main` is the npm and GitHub release source. `release.yml` must not publish from GitHub Release events or `workflow_run` because release must not wait on the full CI workflow. It publishes from direct `push` to `main`, with manual dispatch limited to `refs/heads/main`. The preflight script must fail closed when `package.json`, `package-lock.json`, the lockfile root package version, or the top `CHANGELOG.md` release entry disagree; when a GitHub Release exists but npm is missing; or when an existing GitHub tag points away from the release commit. Same-version reruns are idempotent: if npm exists and the GitHub Release exists, the workflow exits cleanly; if npm exists and the GitHub Release is missing, the workflow repairs the GitHub Release from `CHANGELOG.md` without republishing npm.
@@ -58,7 +57,6 @@ The complete public CI surface is the seven tracked workflows under `.github/wor
5857
- Each `supaschema diff --out` render in a workflow writes to its own output subdirectory. supaschema treats the `--out` file's parent directory as the migrations dir for the lineage chain gate, so two renders sharing one directory — for example the `quality` lane's tarball smoke and examples smoke both writing into `$RUNNER_TEMP` — make the first render look like a pending migration the second must continue, a false `SUPA_DIFF_LINEAGE_BROKEN`. Give each render an isolated `--out` directory (supaschema auto-creates the parent).
5958
- Concurrency is declared in each PR-facing workflow (`ci.yml`, `dependency-review.yml`) as `group: "${{ github.workflow }}-${{ github.ref }}"` with `cancel-in-progress: true`, so superseded PR runs are cancelled. `release.yml` is not cancel-on-new; it uses `group: release-npm` with `queue: max` and must never set `cancel-in-progress: true` on the publish path.
6059
- Path-filtered workflows (`docs.yml`) gate on their owned trees plus their own workflow file and the lockfile inputs that affect them. These are independent advisory workflows, not required checks short-circuited by `paths-ignore`; do not convert a required gate (`ci.yml`) into a path-skipped check.
61-
- `ci-failure-report.yml` is a reporter, not a required gate. It MUST keep top-level read-only permissions, elevate only its report job to `actions: read`, `checks: read`, `contents: read`, `pull-requests: read`, and `issues: write`, and MUST NOT checkout, build, test, or execute pull-request code. It may only run `scripts/github/report-ci-failure.mjs` from the default-branch checkout to update the single `<!-- supaschema:ci-failure-report -->` PR comment.
6260
- CI/docs Node lanes use `actions/setup-node` with npm caching where appropriate; the privileged release job disables package-manager caching to avoid unnecessary package-manager side effects on the OIDC publish path. There is no external/remote build cache in this repo.
6361
- CodeQL MUST cover `actions` and `javascript-typescript`, use `queries: security-and-quality`, and use no-build analysis for these interpreted/action languages. Do not use the deprecated CodeQL dependency installer input.
6462
- Supply-chain scanning is layered and must stay wired: `npm audit signatures` (registry signature check) in `quality` and `release`, `actions/dependency-review-action` on PRs, CodeQL static analysis, and OpenSSF Scorecard. Do not remove a public scanner to make a run green.
@@ -69,13 +67,13 @@ The complete public CI surface is the seven tracked workflows under `.github/wor
6967
## Enforced by
7068

7169
- `npm run guard` (`scripts/guards/check-all.mjs`) — repository invariants (tooling stack, canonical surfaces, agent surfaces, dependency catalog, Code Atlas, LSP coverage), run inside `ci.yml`'s `quality` job. Public guard scans over agents, skills, rules, and policy files MUST derive their file lists from `git ls-files --cached`, not raw filesystem directory walks, so ignored local DX cannot satisfy or break CI-only requirements. It MUST run a second targeted public-checkout pass for local-only maintainer surfaces with `SUPASCHEMA_PUBLIC_CHECKOUT=1` and emit `PUBLIC_CHECKOUT_GUARDS_OK`, so ignored local files cannot mask clean GitHub checkout failures.
72-
- `npm run guard:ci` (`scripts/guards/check-ci-governance.mjs`, part of `npm run guard`) — parses every tracked `.github/workflows/*.yml` with the `yaml` dependency (AST/structured walk, Rule 07) and asserts this rule's STOP invariants deterministically: top-level least-privilege permissions, full-SHA action pins, `actions/checkout` `persist-credentials: false`, no stored npm token, the release workflow's direct `push` trigger on `main`, no `workflow_run` release dependency, main-scoped manual dispatch, queued non-canceling publish concurrency, GitHub-hosted Ubuntu Node 24 trusted-publishing lane, harden-runner + OIDC `id-token: write` + `npm publish "$SUPASCHEMA_TARBALL" --access public --provenance`, `actions/attest@v4`, GitHub Release/tag creation from `scripts/release/changelog-notes.mjs` with `--notes-file`, exact `github.sha` checkout, release preflight, no database service or benchmark on the publish job, no benchmark gate in `ci.yml`, the Node/Postgres/OS matrix lanes, the single-owner examples lane, matrix-focused test scripts, the CodeQL `actions`/`javascript-typescript` matrix, the `ci-failure-report.yml` completed-PR reporter shape that can clear current-head markers after non-failure reruns, and the requirement that `python.yml` stay private with the FastMCP service.
70+
- `npm run guard:ci` (`scripts/guards/check-ci-governance.mjs`, part of `npm run guard`) — parses every tracked `.github/workflows/*.yml` with the `yaml` dependency (AST/structured walk, Rule 07) and asserts this rule's STOP invariants deterministically: top-level least-privilege permissions, full-SHA action pins, `actions/checkout` `persist-credentials: false`, no stored npm token, the release workflow's direct `push` trigger on `main`, no `workflow_run` release dependency, main-scoped manual dispatch, queued non-canceling publish concurrency, GitHub-hosted Ubuntu Node 24 trusted-publishing lane, harden-runner + OIDC `id-token: write` + `npm publish "$SUPASCHEMA_TARBALL" --access public --provenance`, `actions/attest@v4`, GitHub Release/tag creation from `scripts/release/changelog-notes.mjs` with `--notes-file`, exact `github.sha` checkout, release preflight, no database service or benchmark on the publish job, no benchmark gate in `ci.yml`, the Node/Postgres/OS matrix lanes, the single-owner examples lane, matrix-focused test scripts, the CodeQL `actions`/`javascript-typescript` matrix, and the requirement that `python.yml` stay private with the FastMCP service.
7371
- `npm run lint:ci` (Biome `biome ci .`), `npm run typecheck`, `npm run build`, `npm run check:schema`, `npm run check:package`, and `npm run package:smoke` — the static and packaging gates the `quality` matrix runs (lint/format ownership is Rule 08; toolchain is Rule 06; the npm package boundary is Rule 13).
7472
- `npm run test:matrix`, `npm run test:matrix:coverage`, `npm run fixture:verify`, and `npm run corpus:check` — the database-backed replay-safety proofs the `check` matrix runs.
75-
- The seven workflow files themselves under `.github/workflows/`, plus `.github/dependabot.yml`.
73+
- The six workflow files themselves under `.github/workflows/`, plus `.github/dependabot.yml`.
7674
- `lefthook.yml` for local pre-commit hooks that mirror the lint/format gates before code reaches CI.
7775

78-
STOP if a tracked workflow grants top-level write permissions, unpins an action from its full-length commit SHA, drops `persist-credentials: false` on a job that does not need persisted credentials, removes harden-runner from the OIDC publish job, replaces OIDC trusted publishing with a stored npm token, moves the publish job off GitHub-hosted Ubuntu/Node 24 or drops the npm `>=11.5.1` assertion, drops `actions/attest@v4`, publishes from GitHub Release events or waits for `workflow_run`, lets a non-main manual dispatch publish, drops the release version preflight, publishes anything other than the smoked tarball, drops GitHub Release/tag creation, creates a GitHub Release with auto-generated notes instead of the extracted `CHANGELOG.md` entry, uploads extra GitHub Release artifacts, runs benchmarks in a required CI/release workflow, removes a supported Node/Postgres/OS matrix lane, drops a public CodeQL language lane (`actions`, `javascript-typescript`), makes `python.yml` public while `services/agent-mcp` stays private, moves database-backed proofs out of the `postgres`-service `check` job, duplicates examples tests across DB or OS matrix axes, removes concurrency cancellation from a PR-facing workflow, disables a public supply-chain scanner (`npm audit signatures`, dependency-review, CodeQL, or Scorecard), makes `ci-failure-report.yml` run on non-PR source events, execute PR code, or grant permissions beyond the reporter scopes, moves a bash-only construct into a step or npm script the `check-os` (Windows/macOS) lane runs, or shares one `--out` directory across multiple `supaschema diff` renders in a workflow.
76+
STOP if a tracked workflow grants top-level write permissions, unpins an action from its full-length commit SHA, drops `persist-credentials: false` on a job that does not need persisted credentials, removes harden-runner from the OIDC publish job, replaces OIDC trusted publishing with a stored npm token, moves the publish job off GitHub-hosted Ubuntu/Node 24 or drops the npm `>=11.5.1` assertion, drops `actions/attest@v4`, publishes from GitHub Release events or waits for `workflow_run`, lets a non-main manual dispatch publish, drops the release version preflight, publishes anything other than the smoked tarball, drops GitHub Release/tag creation, creates a GitHub Release with auto-generated notes instead of the extracted `CHANGELOG.md` entry, uploads extra GitHub Release artifacts, runs benchmarks in a required CI/release workflow, removes a supported Node/Postgres/OS matrix lane, drops a public CodeQL language lane (`actions`, `javascript-typescript`), makes `python.yml` public while `services/agent-mcp` stays private, moves database-backed proofs out of the `postgres`-service `check` job, duplicates examples tests across DB or OS matrix axes, removes concurrency cancellation from a PR-facing workflow, disables a public supply-chain scanner (`npm audit signatures`, dependency-review, CodeQL, or Scorecard), moves a bash-only construct into a step or npm script the `check-os` (Windows/macOS) lane runs, or shares one `--out` directory across multiple `supaschema diff` renders in a workflow.
7977

8078
STOP if anyone reintroduces Turborepo / remote-cache / `--affected` / maintainer pnpm/Yarn/Bun install workflows / Vercel / Render deploy machinery into the CI surface or into this rule. The isolated package-smoke lane is the only CI exception for alternate package managers.
8179

0 commit comments

Comments
 (0)