From 6bcb5c13ca2079a8bdc85fd6fdda74d7b063844b Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 16 Sep 2026 15:54:01 +0000 Subject: [PATCH 1/2] =?UTF-8?q?docs(audits):=20gate=20census=202026-09=20?= =?UTF-8?q?=E2=80=94=20227=20rows,=20one=20table,=20report-only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every scripts/**/check-*.mjs and packages/*/scripts/check-*.mjs (182), every root check:* that is not a thin alias (26), every .claude/hooks/* (12) and every required context on main (7) on one six-column table, with the retirement list, the report-only list and the method + limits. Real catches sampled over the last 30 days of failed PR runs (1,230 runs, 1,287 failed jobs, step-level attribution with self-PR exclusion). No gate is removed, disabled or edited. Claude-Session: https://claude.ai/code/session_01Wj1HUjzyeiBQ8atRf1ZhaL Co-authored-by: Claude --- docs/audits/gate-census-2026-09.md | 400 +++++++++++++++++++++++++++++ 1 file changed, 400 insertions(+) create mode 100644 docs/audits/gate-census-2026-09.md diff --git a/docs/audits/gate-census-2026-09.md b/docs/audits/gate-census-2026-09.md new file mode 100644 index 00000000000..72408a7c9ca --- /dev/null +++ b/docs/audits/gate-census-2026-09.md @@ -0,0 +1,400 @@ +# Audit: gate census 2026-09 — every `check-*.mjs`, `check:*` script, hook and required context on one table + +**Date**: 2026-09-16 · **Tree**: `origin/main` at `85c6d76e` (worktree `objectstack-issue-18472`, shallow floor 2026-09-09) · **Card**: #18472 · +**Ruling**: maintainer ruling **F**, verbatim 「F」, on 「现在有各种门禁的开发在浪费我的各种时间,我们的项目是不是门禁用的太重了。有这个必要吗?」 · +**Report-only**: this audit removes, disables and edits **no** gate. The retirement batch follows as its own card(s) after the maintainer's one-word 「认可」 on the table. + +Zod validation inside `packages/spec` and the runtime is the **product**, not a gate — it is out of scope here and has no row. + +## The numbers + +| inventory | definition | count | +|:--|:--|--:| +| ① check files | every `scripts/**/check-*.mjs` (178) and `packages/*/scripts/check-*.mjs` (4) | **182** | +| ② root `check:*` scripts that are not a thin alias | 164 root `check:*` scripts; 138 run only inventory-① file(s) (thin alias, collapsed onto the file row); **26** run something else (a composite of helper self-tests, a `.sh`/`.mjs` outside ①, or a `--check` of a generator) | **26** | +| ③ hooks | every file under `.claude/hooks/` — 6 PreToolUse guards + their 6 `*.selftest.sh` | **12** | +| ④ required contexts | `GET /repos/objectstack-ai/objectstack/rules/branches/main` → `required_status_checks` (ruleset 12119582, `strict=false`) | **7** | +| **union = rows** | the four sets are disjoint by construction (paths, script names, hook paths, job names) | **227** = 182 + 26 + 12 + 7 | + +| verdict | rows | +|:--|--:| +| `keep` | 133 | +| `retire` | 58 | +| `report-only` | 16 | +| `keep (session hook; see Method)` | 6 | +| `keep (with its hook)` | 6 | +| `keep (too new)` | 5 | +| `keep (ruled)` | 2 | +| `retire (ruled)` | 1 | +| **retire (all spellings)** | **59** | +| **keep (all spellings)** | **152** | +| **report-only** | **16** | + +| class | rows | +|:--|--:| +| `process` | 117 | +| `contract` | 60 | +| `correctness` | 50 | + +**Sample window for column 5**: PR CI runs created 2026-08-17..2026-09-16 (30 days): 1,480 failed `pull_request` runs repo-wide; the 1,230 in the eight PR-triggered workflows that host gates were read job-by-job and step-by-step (1,287 failed jobs, 1,287 annotation reads, 9 job-log reads). Attribution is by the failed **step** (lint.yml step names map 1:1 to a gate for all but four shared steps), split by annotation tag or a sampled log where a step hosts several gates, and counted as **distinct PRs**, excluding any PR whose file list contains the gate's own file. + +**Top three by blast radius (PRs turned red in the window, gate rows only)**: `check-changeset-no-major.mjs` **74 PRs** (Clause-② level rule, `Check Changeset` job — advisory job, but the PM loop treats a red check as a stop) · `check-partof-closing-keyword.mjs` **31 PRs** (advisory guard workflow) · `check-system-context-census.mjs` **21 PRs** (required, whole-repo). Next: `check-type-check-coverage.mjs` 20 · `check:merge-driver` 20 (two landed reds riding `main`) · `check-adr-0087-registration.mjs` 16 · `pm/check-dispatch-gates.mjs` 15 · `@objectstack/client check:exported-any-returns` 15 (one stale ledger entry riding `main` for two days). Not a row but the largest single source of PR red: the inline **`Require a changeset (or the skip-changeset label)`** step of `pr-automation.yml` — **107 PRs**. + +**Carrier counts (job-level red, distinct PRs)**: Lint & Repo Gates 164 · Test Core 101 · TypeScript Type Check 78 · Dogfood 26 · Temporal 9 · Build Core 7 · Governed Surface Queue Guard 0 (1 cancelled run) · Check Changeset (advisory) 198 · Part-of guard (advisory) 31. + +## Verdict rule, as applied + +- `keep` — class `contract` or `correctness`; or class `process` with ≥ 1 real catch in the window; or a standing ruling (`keep (ruled)`). Spellings: `keep (too new)` = landed after 2026-09-09, under 7 days of window coverage, so a zero would be a guess; `keep (session hook; see Method)` / `keep (with its hook)` = the hooks, which never run in CI (Method §hooks). +- `report-only` — advisory today, no fail-closed role: the gate proper runs only in a workflow outside the required set, runs `--advisory`, is a report-only sweeper/metric, or is run by no workflow at all. Catches are still recorded (one of them fires often — see the list). +- `retire` — class `process`, zero real catches in the window (a measured zero: the gate ran on every PR in the sample and never failed on a PR that did not edit it) or `unmeasured` for a reason that means it could not have judged a PR, **and** guards no published contract. `retire (ruled)` = objectstack#18095 ruling E. +- Column 3 carries two facts: the published contract the gate validates (or `none`) and its origin card; the acceptance criterion `guards = none` is read on the contract half — every script names an incident, so reading it on the card number would make nothing retirable. +- Straddles: a static ratchet over **runtime source** enforcing an ADR invariant (tenant chokepoint, durability log level, init-service, settings bind-window, kernel-hook pairs, wildcard fall-through, …) is filed `correctness` — the invariant is runtime behaviour a test could also pin; the process half (a ratchet, not a test) is named in column 3. Changeset/commit-shape checks are `process` per the card, whatever they catch. Release-lane gates (`release.yml` / `cut-rc.yml`) are `contract` (the published npm/docs surface). + +## The table + +| name | class | guards (contract or none · origin · landed) | required + blast radius | real catches since landing (window 2026-08-17..09-16) | verdict | +|:--|:--|:--|:--|:--|:--| +| **Build Core** (required context) | correctness | turbo build of every package + published-artefact gates (dts-closure, cjs loads, sourcemaps, lean entry) | required · path-scoped (ci.yml `filter`) — main ruleset 12119582, strict=false | 7 PRs red at job level in window (every gate the job hosts, self included — a carrier count, not a catch count) | `keep` | +| **Dogfood Regression Gate** (required context) | correctness | boots example apps and drives real user flows, 3 shards + verify CLI | required · path-scoped (ci.yml `filter`) — main ruleset 12119582, strict=false | 26 PRs red at job level in window (every gate the job hosts, self included — a carrier count, not a catch count) | `keep` | +| **Governed Surface Queue Guard** (required context) | process | the maintainer's approval mechanism (PD#14) — runs check-governed-queue-guard.mjs | required · whole-repo — main ruleset 12119582, strict=false | 0 in window (1 failed run, conclusion `cancelled`, no failed step) | `keep (ruled)` | +| **Lint & Repo Gates** (required context) | process | carrier job (lint.yml `lint`): 180 steps, 5 family-scoped, the rest whole-repo — hosts most `check:*` gates | required · whole-repo — main ruleset 12119582, strict=false | 164 PRs red at job level in window (every gate the job hosts, self included — a carrier count, not a catch count) | `keep` | +| **Temporal Conformance (live PG + MySQL)** (required context) | correctness | driver-sql temporal suite against live PG + MySQL | required · path-scoped (ci.yml `filter`) — main ruleset 12119582, strict=false | 9 PRs red at job level in window (every gate the job hosts, self included — a carrier count, not a catch count) | `keep` | +| **Test Core** (required context) | correctness | vitest over the affected package set, 6 shards + attestation | required · path-scoped (ci.yml `filter`) — main ruleset 12119582, strict=false | 101 PRs red at job level in window (every gate the job hosts, self included — a carrier count, not a catch count) | `keep` | +| **TypeScript Type Check** (required context) | correctness | aggregator of four lanes (source gates · workspace · debt ledger · consumer gates): tsc over every package + the spec generated-artefact gates | required · whole-repo — main ruleset 12119582, strict=false | 78 PRs red at job level (lanes: source 25 · workspace 9 · debt 24 · consumer 26) | `keep` | +| `packages/cli/scripts/check-app-nav-i18n.mjs` | contract | platform-app navigation translated in every locale (ADR-0029) · origin #5750 · landed 2026-08-08 | required · whole-repo (TypeScript Type Check ← consumer lane) | 0 in window | `keep` | +| `packages/lint/scripts/check-doc-formula-expressions.mjs` | contract | docs formula examples are valid CEL against the spec formula grammar · origin #5026 · landed 2026-08-04 | required · whole-repo (TypeScript Type Check ← consumer lane) | 0 in window | `keep` | +| `packages/lint/scripts/check-doc-security-posture.mjs` | contract | docs object examples pass `os validate` security posture · origin #10581 · landed 2026-08-21 | required · whole-repo (TypeScript Type Check ← consumer lane) | 0 in window | `keep` | +| `packages/lint/scripts/check-reference-carrier-shape.mjs` | contract | relationship carriers spelled as the string the spec declares · ruled retire: #18095 E · origin #13053 · landed 2026-08-29 | required · whole-repo (Lint & Repo Gates) | 2 PRs / 2 days (2026-08-30..2026-09-13) | `retire (ruled)` | +| `scripts/check-adr-0087-registration.mjs` | process | none (changeset-shape check; reads the ADR-0087 registry to grade a declared-breaking changeset) · origin #6011 · landed 2026-08-07 | required · whole-repo (Lint & Repo Gates); advisory (Check Changeset); advisory (Cut an rc from one sna) | 16 PRs / 11 days (2026-08-27..2026-09-16) | `keep` | +| `scripts/check-adr-anchors.mjs` | process | none (docs/adr anchors resolve into code; ADR-0001 corollary) · origin #3723 · landed 2026-08-02 | required · whole-repo (Lint & Repo Gates) | 6 PRs / 3 days (2026-08-27..2026-09-03) | `keep` | +| `scripts/check-adr-links.mjs` | process | none (relative links inside docs/adr resolve) · origin #6028 · landed 2026-08-08 | advisory (Check Documentation Li) | 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | `report-only` | +| `scripts/check-adr-symbol-anchors.mjs` | process | none (docs/adr symbol anchors resolve; ADR-0113) · origin #13556 · landed 2026-09-03 | required · whole-repo (Lint & Repo Gates) | 1 PRs / 2 days (2026-09-03..2026-09-04) | `keep` | +| `scripts/check-agent-model-declared.mjs` | process | none (.claude/agents/*.md declare a model) · PM loop · origin #6566 · landed 2026-08-09 | required · whole-repo (TypeScript Type Check ← source lane) | 0 in window | `retire` | +| `scripts/check-agent-test-spelling.mjs` | process | none (no committed command forwards vitest args through a bare `--`) · origin #10166 · landed 2026-08-24 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-aggregator-roster.mjs` | process | none — CI integrity: an aggregate job `needs:` every lane it vouches for · CI-integrity group · origin #4690 · landed 2026-08-21 | required · whole-repo (Lint & Repo Gates); required · whole-repo (TypeScript Type Check) | 0 in window (its own `Aggregator roster gate` step never failed; the typecheck aggregator step that mentions it in a comment failed on 71 PRs = lane failures) | `retire` | +| `scripts/check-auth-mount-ledger.mjs` | contract | published REST auth route surface (mount vs ledger) · origin #9941 · landed 2026-08-22 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-bash32-floor.mjs` | process | none (shell scripts stay bash-3.2 compatible) · origin #12221 · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-changeset-fixed.mjs` | contract | npm publish: every publishable package is in the Changesets `fixed` group · origin #11510 · landed 2026-05-25 | advisory (Cut an rc from one sna); advisory (Publish ${{ needs.rele); advisory (Validate Package Depen); advisory (Version PR maintenance) | 0 in window | `keep` | +| `scripts/check-changeset-no-major.mjs` | process | none (changeset level rule: no `major`; Clause-② yes ⇒ ≥ minor — maintainer ruling 2026-09-04) · origin #6129 · landed 2026-07-10 | required · whole-repo (Lint & Repo Gates); advisory (Check Changeset); advisory (Cut an rc from one sna) | 74 PRs / 11 days (2026-09-06..09-16; log-sampled ×2: Clause-② level rule — `yes` graded `patch`, or no `Clause-②:` line) | `keep` | +| `scripts/check-ci-filter-parity.mjs` | correctness | test-input parity between turbo affected-set and cross-package readers (Layer C) · origin #7802 · landed 2026-08-21 | required · whole-repo (Lint & Repo Gates) | 0 in window (3 failure(s) only on PRs editing this file, excluded) | `keep` | +| `scripts/check-cli-command-ids.mjs` | contract | published CLI command registry (string-literal ids resolve) · origin #11535 · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 1 PRs / 1 days (2026-09-13..2026-09-13) | `keep` | +| `scripts/check-cli-examples-parity.mjs` | contract | published CLI examples vs the documented block · origin #15390 · landed 2026-09-05 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-cli-test-child-env.mjs` | correctness | CLI test child-process env hygiene · origin #11267 · landed 2026-08-24 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-closing-keyword-parity.mjs` | process | none (PM closing-keyword parser parity across scripts) · PM loop · origin #456 · landed 2026-08-20 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-closing-target-claim.mjs` | process | none (a PR may close only a card whose Claim: names its branch) · PM loop · origin no card in header · landed 2026-09-12 | advisory (Closing-Target Claim Guard workflow, PR + merge_group); Lint & Repo Gates runs only its `--self-test` | unmeasured (landed 2026-09-12; Closing-Target Claim Guard: 0 failed runs in the sample); lint runs only its self-test | `report-only` | +| `scripts/check-comment-mask-adoption.mjs` | process | none (scripts/** route comment-stripping through one module) · scripts hygiene · origin no card in header · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-comment-mask-corpus.mjs` | process | none (comment mask agrees with a real parser over the corpus) · scripts hygiene · origin #10427 · landed 2026-08-21 | required · family-scoped (Lint & Repo Gates, `select-gate-families`) | 0 in window | `retire` | +| `scripts/check-commit-card-trailers.mjs` | process | none (commit trailers carry no card relation / model id; pre-push refusal) · PM loop · origin no card in header · landed 2026-09-12 | required · whole-repo (Lint & Repo Gates, self-test) + local pre-push | unmeasured (landed 2026-09-12; <7 days of window coverage) | `keep (too new)` | +| `scripts/check-console-injection.mjs` | contract | published Console bundle carries this tree's spec (objectui pin) · origin #9667 · landed 2026-08-18 | advisory (Console Pin Gate); advisory (Publish ${{ needs.rele) | 0 in window | `keep` | +| `scripts/check-console-intercept-disarm.mjs` | correctness | vitest console-intercept disarmed in every test-running package · origin #10293 · landed 2026-08-30 | required · whole-repo (Lint & Repo Gates) | 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | `keep` | +| `scripts/check-console-sha.mjs` | contract | published Console dist stamp equals `.objectui-sha` · origin no card in header · landed 2026-07-01 | advisory (Console Pin Gate); advisory (Cut an rc from one sna); advisory (Publish ${{ needs.rele); advisory (Showcase nav-surface s) | 0 in window | `keep` | +| `scripts/check-corpus-claim-drift.mjs` | process | none (lexical anti-drift ratchet over the teaching corpus) · docs ratchet · origin #13539 · landed 2026-08-31 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-cross-package-test-inputs.mjs` | correctness | CI test-input completeness (a test reading outside its package is declared) · origin #7769 · landed 2026-08-12 | required · whole-repo (Lint & Repo Gates) | 2 PRs / 2 days (2026-09-12..2026-09-14) | `keep` | +| `scripts/check-cross-repo-closer-outcome.mjs` | process | none (outcome contract of the cross-repo issue-closer automation) · PM loop · origin #9575 · landed 2026-08-18 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-declaration-mirrors.mjs` | process | none (hand-written `.d.mts` mirrors stay equal to their `.mjs`) · scripts hygiene · origin #5475 · landed 2026-08-21 | required · whole-repo (Lint & Repo Gates) | 1 PRs / 1 days (2026-09-04..2026-09-04) | `keep` | +| `scripts/check-declared-population-live.mjs` | process | none (a gate family that declares a path population reaches the tree) · meta-gate · origin #13519 · landed 2026-09-01 | required · whole-repo (Lint & Repo Gates) | 1 PRs / 1 days (2026-09-14..2026-09-14) | `keep` | +| `scripts/check-dev-prereqs.mjs` | correctness | `pnpm dev` refuses a stale packages/spec/dist (build freshness) · origin #5726 · landed 2026-08-06 | required · whole-repo (TypeScript Type Check ← source lane) | 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | `keep` | +| `scripts/check-dispatcher-error-vocabulary.mjs` | contract | ADR-0112 error-code vocabulary (packages/spec/src/shared error maps) · origin #8087 · landed 2026-08-16 | required · whole-repo (Lint & Repo Gates) | 2 PRs / 2 days (2026-08-21..2026-08-28) | `keep` | +| `scripts/check-doc-anchors.mjs` | process | none (`#fragment` links in content/docs resolve to real headings) · docs · origin #7465 · landed 2026-08-11 | required · whole-repo (Lint & Repo Gates) | unmeasured (shares its lint step with the system-context census: 25 step failures, 22 tagged census by annotation, 2 unresolved, 1 log-sampled = census) | `keep` | +| `scripts/check-doc-authoring.mjs` | process | none (docs/skills corpus authoring guard: bare identifiers, ADR-0010/0059 spellings) · docs · origin #2035 · landed 2026-06-21 | required · whole-repo (Lint & Repo Gates) | 10 PRs / 7 days (2026-09-06..2026-09-14) | `keep` | +| `scripts/check-doc-frontmatter.mjs` | process | none (every docs page's frontmatter parses) · docs · origin #10493 · landed 2026-08-21 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-doc-route-spelling.mjs` | process | none (route spellings in prose match the ledgers) — runs `--advisory` · docs · origin #4916 · landed 2026-08-24 | required · whole-repo (Lint & Repo Gates) | 0 in window | `report-only` | +| `scripts/check-docs-image-tag.mjs` | contract | published docs pin the CLI version the release ships (release lane: release.yml/cut-rc.yml) · origin #8911 · landed 2026-08-16 | required · whole-repo (Lint & Repo Gates); advisory (Cut an rc from one sna); advisory (Version PR maintenance) | 0 in window | `keep` | +| `scripts/check-docs-locale-catch-all.mjs` | process | none (apps/docs locale catch-all + OG-card URL invariant) · docs · origin no card in header · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-docs-nav-label.mjs` | process | none (docs `navTitle` stays out of title surfaces) · docs · origin no card in header · landed 2026-09-01 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-docs-redirects.mjs` | process | none (docs redirect destinations resolve, no chains) · docs · origin #8948 · landed 2026-08-16 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-docs-section-name.mjs` | contract | docs form-section examples satisfy the spec `section.name` requirement · origin #10709 · landed 2026-08-24 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-docs-single-h1.mjs` | process | none (one h1 per docs page) · docs · origin #12236 · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-docs-spec-enumerations.mjs` | contract | hand-written `@objectstack/spec` enumerations equal the exports map · origin #16325 · landed 2026-09-10 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-10; <7 days of window coverage) | `keep` | +| `scripts/check-driver-conformance.mjs` | correctness | every driver runs the shared conformance suite (ADR-0053) · origin #3106 · landed 2026-07-31 | required · whole-repo (TypeScript Type Check ← source lane) | 0 in window | `keep` | +| `scripts/check-driver-memory-census.mjs` | correctness | test-double census of `@objectstack/driver-memory` declarations · origin #5499 · landed 2026-08-08 | required · whole-repo (Lint & Repo Gates) | 4 PRs / 4 days (2026-08-22..2026-09-04) | `keep` | +| `scripts/check-dts-closure.mjs` | contract | published `.d.ts` closure resolves (no vanished declarations) · origin #12078 · landed 2026-09-05 | required · path-scoped (Build Core; ci.yml `filter.core`); required · whole-repo (TypeScript Type Check ← consumer lane); required · whole-repo (TypeScript Type Check ← debt lane) | 0 in window | `keep` | +| `scripts/check-dts-emitted.mjs` | correctness | a package build emits every declaration file its manifest promises (runs inside 8 packages' `build`) · origin #11907 · landed 2026-08-25 | required · path-scoped (inside 8 packages' `build` → Build Core / Type Check lanes) | unmeasured (not run by any PR workflow or hook) | `keep` | +| `scripts/check-dual-build-cjs-loads.mjs` | contract | every published `require` entry point loads (ADR-0093) · origin #12843 · landed 2026-08-28 | required · path-scoped (Build Core; ci.yml `filter.core`) | 0 in window | `keep` | +| `scripts/check-durability-degradation-log-level.mjs` | correctness | runtime invariant ratchet: durability degradation logs at `error` / read-seam invention (AGENTS.md section) · static ratchet over runtime source · origin #4420 · landed 2026-08-03 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-empty-changeset.mjs` | process | none (no empty-frontmatter changeset; changeset-shape check) · origin #5471 · landed 2026-08-07 | required · whole-repo (Lint & Repo Gates); advisory (Check Changeset); advisory (Cut an rc from one sna) | 4 PRs / 5 days (2026-09-03..2026-09-16) | `keep` | +| `scripts/check-engine-double-contract.mjs` | correctness | fake ObjectQL engines honour the engine write-verb contract · origin #4434 · landed 2026-08-03 | required · whole-repo (Lint & Repo Gates) | 5 PRs / 5 days (2026-08-22..2026-09-10) | `keep` | +| `scripts/check-engine-split-ratio.mjs` | process | none (ADR-0076 D7 metric: cross-package commit ratio) — report-only metric · metric · origin #2462 · landed 2026-07-16 | required · whole-repo (Lint & Repo Gates); advisory (Engine cross-package c) | 0 in window (its shared lint step failed on 10 PRs on 2026-08-21; log-sampled failure = `git-history.mjs --self-test`, not this file) | `report-only` | +| `scripts/check-entry-guard.mjs` | process | none (scripts/** entry guards go through one predicate) · scripts hygiene · origin no card in header · landed 2026-08-20 | required · whole-repo (Lint & Repo Gates) | 1 PRs / 1 days (2026-08-21..2026-08-21) | `keep` | +| `scripts/check-error-code-casing.mjs` | contract | ADR-0112 error-code casing (SCREAMING_SNAKE) over the runtime · origin #4003 · landed 2026-07-30 | required · whole-repo (Lint & Repo Gates) | 4 PRs / 4 days (2026-08-18..2026-09-06) | `keep` | +| `scripts/check-error-status-conformance.mjs` | contract | published HTTP status in docs equals the status the runtime emits · origin no card in header · landed 2026-08-16 | required · whole-repo (Lint & Repo Gates) | 2 PRs / 2 days (2026-08-25..2026-09-05); 1 self excluded | `keep` | +| `scripts/check-examples-live-imports.mjs` | correctness | inventory of packages/** tests that import examples/** stays declared · origin #8231 · landed 2026-08-16 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-filter-alias-parity.mjs` | contract | packages/spec filter-slot wire aliases vs the runtime · origin #7390 · landed 2026-08-12 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-i18n-bundles.mjs` | contract | generated translation bundles derived from the spec schemas (nine packages) · origin #3370 · landed 2026-07-28 | required · whole-repo (TypeScript Type Check ← consumer lane) | 4 PRs / 3 days (2026-09-02..2026-09-05) | `keep` | +| `scripts/check-i18n-coverage.mjs` | contract | ratchet over untranslated spec-declared labels (ADR-0029) · origin #3370 · landed 2026-07-28 | required · whole-repo (TypeScript Type Check ← consumer lane) | 0 in window | `keep` | +| `scripts/check-i18n-stale-fill.mjs` | contract | stale translation fills vs the spec-declared source · origin #8543 · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-i18n-walk-parity.mjs` | contract | every translation group `@objectstack/spec` declares is walked by the extractor · origin no card in header · landed 2026-09-04 | required · whole-repo (TypeScript Type Check ← consumer lane) | 0 in window (1 failure(s) only on PRs editing this file, excluded) | `keep` | +| `scripts/check-init-service-contract.mjs` | correctness | runtime invariant: ADR-0116 init-service declarations · static ratchet over runtime source · origin #4085 · landed 2026-08-02 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-issue-citations.mjs` | process | none (issue-number citations resolve against the board) — no workflow runs it · PM loop · origin #16099 · landed 2026-09-14 | not in PR CI (root `check:*` exists; no workflow or hook runs it) | unmeasured (not run by any PR workflow or hook) | `report-only` | +| `scripts/check-kernel-hook-pairs.mjs` | correctness | paired kernel-hook pin (runtime) · static ratchet over runtime source · origin #5170 · landed 2026-08-08 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-keyed-text-bounds.mjs` | contract | spec text-family columns declare their DDL bound (ADR-0029) · origin #11374 · landed 2026-08-28 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-lean-entry-closure.mjs` | contract | published lean engine entry loads nothing forbidden (ADR-0076) · origin #9803 · landed 2026-09-08 | required · path-scoped (Build Core; ci.yml `filter.core`) | 0 in window | `keep` | +| `scripts/check-live-db-isolation.mjs` | correctness | no live suite reuses a shared database · origin #9350 · landed 2026-08-21 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-lockstep-package-count.mjs` | process | none (prose restatements of the lockstep package count) · docs · origin #16919 · landed 2026-09-09 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-logger-receiver-detach.mjs` | correctness | runtime invariant: receiver-sensitive log channels detach · static ratchet over runtime source · origin #12773 · landed 2026-08-29 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-manifest-repository-directory.mjs` | contract | publishable manifests carry `repository.directory` · origin #15991 · landed 2026-09-07 | required · whole-repo (Lint & Repo Gates) | 0 in window (1 failure(s) only on PRs editing this file, excluded) | `keep` | +| `scripts/check-merge-queue-triage-outcome.mjs` | process | none (outcome contract of the merge-queue-triage automation) · PM loop · origin #10128 · landed 2026-08-20 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-merged-branch-reaper-outcome.mjs` | process | none (classifier contract of the merged-branch reaper) · PM loop · origin #13503 · landed 2026-09-04 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-merged-result.mjs` | process | none (probe tool: run a gate on the merged result) — no workflow runs it · PM loop · origin #15379 · landed 2026-09-16 | not in PR CI (root `check:*` exists; no workflow or hook runs it) | unmeasured (not run by any PR workflow or hook) | `report-only` | +| `scripts/check-meta-type-normalized.mjs` | contract | metadata type names normalized at the `:type` route param (spec MetadataTypeSchema) · origin #3984 · landed 2026-08-07 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-node-version.mjs` | process | none — CI integrity: workflows run the `.nvmrc` Node · CI-integrity group · origin #3812 · landed 2026-07-28 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-nul-bytes.mjs` | process | none (no raw control bytes in text files) · origin #4890 · landed 2026-07-17 | required · whole-repo (Lint & Repo Gates); advisory (Cut an rc from one sna); advisory (Version PR maintenance) | 1 PRs / 1 days (2026-09-12..2026-09-12) | `keep` | +| `scripts/check-object-def-param-keys.mjs` | contract | object-definition parameters declare the spec keys they are (ADR-0057) · origin #4311 · landed 2026-09-08 | required · whole-repo (TypeScript Type Check ← source lane) | 0 in window | `keep` | +| `scripts/check-objectql-double-limit.mjs` | correctness | in-memory ObjectQL `find` doubles honour `limit` · origin #7620 · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 4 PRs / 4 days (2026-08-25..2026-09-11) | `keep` | +| `scripts/check-optional-error-sink-contract.mjs` | correctness | runtime invariant: optional `error` sink contract · static ratchet over runtime source · origin #4632 · landed 2026-08-21 | required · whole-repo (Lint & Repo Gates) | 2 PRs / 2 days (2026-08-28..2026-09-03) | `keep` | +| `scripts/check-org-identifier.mjs` | process | none (author-facing reference code uses the blessed org identifier) · docs · origin #3280 · landed 2026-07-19 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-osv-exemptions.mjs` | process | none (OSV exemption ledger carries expiry + reason) · deps · origin #4965 · landed 2026-08-04 | advisory (Validate Package Depen) | 0 in window | `report-only` | +| `scripts/check-overlay-whitelist-table.mjs` | contract | docs overlay-whitelist table derived from the spec metadata type registry (ADR-0005) · origin #6283 · landed 2026-08-24 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-override-consistency.mjs` | contract | pnpm overrides reflected in published manifests · origin #5825 · landed 2026-07-17 | advisory (Validate Package Depen) | 2 PRs / 1 days (2026-08-31..2026-08-31) | `keep` | +| `scripts/check-page-declaration-shape.mjs` | contract | kernel-reaching pages declare the spec page shape · origin #11255 · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-parse-guard.mjs` | process | none (scripts/** TypeScript parses go through one module) · scripts hygiene · origin no card in header · landed 2026-08-21 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-partof-closing-keyword.mjs` | process | none (a Part-of PR body carries no closing keyword for its card) · PM loop · origin #8131 · landed 2026-08-13 | advisory (Part-of Closing-Keyword Guard workflow); Lint & Repo Gates runs only its `--self-test` | 31 PRs / 13 days (job-level: the guard workflow's only gate; 0 self excluded) — advisory workflow, reds the check, does not block | `report-only` | +| `scripts/check-platform-checklist-watchdog.mjs` | process | none (static pin over the platform-checklist watchdog workflow) · QA · origin #11730 · landed 2026-09-06 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-platform-checklist.mjs` | process | none (platform test checklist shape) — schedule/advisory workflow · QA · origin #3358 · landed 2026-08-08 | advisory (Platform checklist gat) | 0 in window | `report-only` | +| `scripts/check-platform-object-tenancy-census.mjs` | process | none (docs tenancy census page equals the tree) · docs census · origin #14957 · landed 2026-09-04 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-plugin-teardown-shape.mjs` | correctness | runtime plugin teardown shape (kernel contract) · static ratchet over runtime source · origin #9371 · landed 2026-08-21 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-pnpm-acquisition.mjs` | process | none — CI integrity: every job that runs pnpm acquires it first · CI-integrity group · origin no card in header · landed 2026-08-24 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-pnpm-filter-targets.mjs` | correctness | every committed `pnpm --filter` names a real package (a zero-match filter exits 0 running nothing) · origin #10853 · landed 2026-08-22 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-position-name-fold-loaders.mjs` | process | none (the vendored name-fold fixture has no non-test loader) · fixture · origin #13419 · landed 2026-08-31 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-prerelease-pin-watch.mjs` | process | none (watch: has upstream shipped a stable release for a prerelease pin) — advisory · deps · origin #3002 · landed 2026-08-05 | advisory (Stable release watch f) | 0 in window | `report-only` | +| `scripts/check-published-files.mjs` | contract | npm `files[]` whitelist of every publishable package · origin #3786 · landed 2026-07-31 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-published-list-mirrors.mjs` | process | none (a list a document publishes equals the gate that prints it — AGENTS.md block) · governed prose · origin #8995 · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-published-readme-exports.mjs` | contract | symbols a published README names exist on the entry · origin #9517 · landed 2026-08-18 | required · whole-repo (TypeScript Type Check ← consumer lane) | 0 in window | `keep` | +| `scripts/check-published-readme-links.mjs` | contract | outbound links in published READMEs are followable · origin #9589 · landed 2026-08-18 | required · whole-repo (Lint & Repo Gates); advisory (Version PR maintenance) | 0 in window | `keep` | +| `scripts/check-query-options-erasure-ratchet.mjs` | correctness | engine invariant ratchet: query-options erasure (#4918) · static ratchet over runtime source · origin #4251 · landed 2026-08-05 | required · family-scoped (Lint & Repo Gates, `select-gate-families`) | 4 PRs / 4 days (2026-08-18..2026-09-01) | `keep` | +| `scripts/check-quick-reference-counts.mjs` | process | none (docs quick-reference section counts match their tables) · docs · origin #6319 · landed 2026-08-07 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-ratchet-remedy-authority.mjs` | process | none (every ratchet's remedy text names its authority — gate-farm convention) · meta-gate · origin #8435 · landed 2026-08-13 | required · whole-repo (TypeScript Type Check ← source lane) | 0 in window (4 failure(s) only on PRs editing this file, excluded) | `retire` | +| `scripts/check-react-page-adapter-contract.mjs` | contract | React pages honour the `useAdapter()` query/result contract (spec ↔ objectui) · origin #10288 · landed 2026-08-24 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-refd-timer-probe.mjs` | correctness | process-global ref'd-timer probe stays reachable in tests · origin #4813 · landed 2026-08-22 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-regen-pending.mjs` | process | none (merge=os-regen deferral is discharged before commit/push; local pre-commit + pre-push) · merge driver · origin #4675 · landed 2026-08-02 | required · whole-repo (Lint & Repo Gates, self-test) + local pre-commit/pre-push | part of 20 PRs / 3 days on `check:merge-driver` (2 clusters; log-sampled: 2026-09-01 = git-merge-regen ledger drift, 2026-09-05 = this file's self-test cases) — not split further | `keep` | +| `scripts/check-registry-log-declared.mjs` | correctness | vitest-running packages declare the registry log level · origin #13517 · landed 2026-09-04 | required · whole-repo (Lint & Repo Gates) | 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | `keep` | +| `scripts/check-release-notes.mjs` | contract | published release pages track the released version (release lane) · origin #3423 · landed 2026-07-11 | required · whole-repo (Lint & Repo Gates); advisory (Version PR maintenance) | 0 in window | `keep` | +| `scripts/check-release-page-status.mjs` | contract | a GA'd major's release page says it is released (release lane) · origin no card in header · landed 2026-08-16 | required · whole-repo (Lint & Repo Gates); advisory (Version PR maintenance) | 0 in window | `keep` | +| `scripts/check-release-section-coverage.mjs` | contract | a published minor appears on its major's release page (release lane) · origin #8882 · landed 2026-08-21 | required · whole-repo (Lint & Repo Gates); advisory (Release section-covera); advisory (Version PR maintenance) | 0 in window | `keep` | +| `scripts/check-required-contexts.mjs` | process | none — CI integrity: the seven required-context job names are pinned · CI-integrity group · origin #5584 · landed 2026-08-09 | required · whole-repo (Lint & Repo Gates); advisory (Live required-set swee) | 0 in window (1 failure(s) only on PRs editing this file, excluded) | `retire` | +| `scripts/check-rest-log-declared.mjs` | correctness | the package owning the REST fault-log level declares it · origin #4886 · landed 2026-09-12 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-12; <7 days of window coverage) | `keep` | +| `scripts/check-rest-log-spy-declared.mjs` | correctness | tests observing the REST fault log declare it · origin #128 · landed 2026-09-14 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-14; <7 days of window coverage) | `keep` | +| `scripts/check-resume-authority-declared.mjs` | contract | pausing action descriptors declare resume authority (spec, ADR-0044) · origin #3801 · landed 2026-08-06 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-role-word.mjs` | process | none (ADR-0090 D3 vocabulary ratchet over hand-written docs) · docs ratchet · origin #2697 · landed 2026-07-10 | required · whole-repo (Lint & Repo Gates) | 2 PRs / 2 days (2026-08-19..2026-09-02); 1 self excluded | `keep` | +| `scripts/check-route-envelope.mjs` | contract | ADR-0112 response envelope over the REST route modules · origin #3563 · landed 2026-07-30 | required · whole-repo (Lint & Repo Gates) | 0 in window (1 failure(s) only on PRs editing this file, excluded) | `keep` | +| `scripts/check-route-ledger-census.mjs` | process | none (generated route-ledger census sentence in docs equals the ledger) · docs census · origin #16758 · landed 2026-09-09 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-runner-env-posture.mjs` | correctness | product source reads no test-runner env · origin no card in header · landed 2026-08-23 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-runtime-services-index.mjs` | process | none (runtime-services docs indexes enumerate the chapter's real pages) · docs · origin #9588 · landed 2026-08-18 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-scripts-symbol-anchors.mjs` | process | none (scripts/** symbol anchors in docs resolve) · docs · origin #13556 · landed 2026-09-05 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-sdui-lockstep.mjs` | contract | `sdui-parser` stays in lockstep with objectui's copy · origin #12719 · landed 2026-08-30 | required · whole-repo (Lint & Repo Gates) | 1 PRs / 1 days (2026-09-02..2026-09-02) | `keep` | +| `scripts/check-sdui-manifest.mjs` | contract | repo-root `sdui.manifest.json` present, intact, fresh at the objectui pin (ADR-0082 D4 input) · origin #12924 · landed 2026-08-30 | required · whole-repo (Lint & Repo Gates) | 2 PRs / 2 days (2026-09-01..2026-09-02) | `keep` | +| `scripts/check-section-landing-index.mjs` | process | none (docs section landing pages enumerate their meta.json pages) · docs · origin #9604 · landed 2026-08-23 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-self-test-wired.mjs` | process | none (every `--self-test` is wired into a workflow) · meta-gate · origin #11150 · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-self-test-workflow-commands.mjs` | process | none (self-test output never emits a runner workflow command) · meta-gate · origin #11886 · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-service-providers.mjs` | contract | `CORE_SERVICE_PROVIDER` (packages/spec/src/system/core-services.zod.ts) remedy guard · origin #4093 · landed 2026-07-30 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-settings-bind-window.mjs` | correctness | runtime invariant: settings bind window (ADR-0116) · static ratchet over runtime source · origin #4471 · landed 2026-08-24 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-shard-attestation.mjs` | correctness | Test Core / Dogfood aggregate counts positive shard attestations · origin #4928 · landed 2026-08-07 | required · path-scoped (Dogfood Regression Gate); required · whole-repo (Lint & Repo Gates); required · path-scoped (Test Core); advisory (Dogfood Regression Gat); advisory (Dogfood Verify CLI); advisory (Test Core (${{ matrix.) | unmeasured (its `--verify` step fails whenever a shard fails — 101 Test Core / 26 Dogfood PRs — an attestation-specific catch is not separable in step data) | `keep` | +| `scripts/check-single-authz-resolver.mjs` | correctness | single request-authorization resolver (ADR-0090 security invariant) · static ratchet over runtime source · origin #4916 · landed 2026-06-26 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-single-claim-paths.mjs` | process | none (at most one open PR modifies a declared single-writer path) · PM loop · origin no card in header · landed 2026-08-18 | advisory (Single-Claim Path Guard workflow); Lint & Repo Gates runs only its `--self-test` | 0 in window (Single-Claim Path Guard: 0 failed runs in the sample); lint runs only its self-test | `report-only` | +| `scripts/check-skill-compatibility-version.mjs` | contract | published SKILL.md `compatibility:` lines match the workspace versions · origin #4690 · landed 2026-08-07 | required · whole-repo (TypeScript Type Check ← source lane) | 0 in window | `keep` | +| `scripts/check-skill-frame-freshness.mjs` | process | none (working-tree copy of the escalation frame is current) — only its self-test runs in CI · PM loop · origin #4936 · landed 2026-08-07 | required · whole-repo (TypeScript Type Check ← source lane) | 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | `retire` | +| `scripts/check-skill-frame-sync.mjs` | process | none (the escalation decision frame is identical across its four copies) · PM loop · origin #5130 · landed 2026-08-06 | required · whole-repo (TypeScript Type Check ← source lane) | 0 in window | `retire` | +| `scripts/check-skill-identifier-liveness.mjs` | contract | identifiers taught by published skills resolve into the spec (ADR-0049) · origin #13678 · landed 2026-08-31 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-skills-token-ratchet.mjs` | process | none (published-skills token/line budget ratchet) · ratchet · origin #10402 · landed 2026-08-21 | required · whole-repo (TypeScript Type Check ← source lane) | 0 in window (3 failure(s) only on PRs editing this file, excluded) | `retire` | +| `scripts/check-slot-lookup-ratchet.mjs` | correctness | engine invariant ratchet: slot lookup (#4251) · static ratchet over runtime source · origin #4127 · landed 2026-07-31 | required · family-scoped (Lint & Repo Gates, `select-gate-families`) | 3 PRs / 3 days (2026-08-18..2026-09-15) | `keep` | +| `scripts/check-sourcemap-no-sources-content.mjs` | contract | published source maps embed no source text · origin #15905 · landed 2026-09-07 | required · path-scoped (Build Core; ci.yml `filter.core`) | 0 in window | `keep` | +| `scripts/check-spec-docblock-symbol-anchors.mjs` | process | none (packages/spec/src doc-block symbol anchors resolve) · docs · origin #13003 · landed 2026-09-09 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-spec-parsed-alias.mjs` | contract | ADR-0122 spec type-alias convention (bare name = author state, `XParsed`) · origin #5551 · landed 2026-08-07 | required · whole-repo (Lint & Repo Gates) | 1 PRs / 1 days (2026-08-25..2026-08-25) | `keep` | +| `scripts/check-stack-collection-maps.mjs` | contract | every enumeration of the stack-collection set answers to `stack.zod.ts` · origin #6242 · landed 2026-08-09 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-stall-guard-budget.mjs` | correctness | CI stall guard speaks before its own budget · origin #11916 · landed 2026-08-28 | required · whole-repo (TypeScript Type Check ← source lane) | 0 in window | `keep` | +| `scripts/check-startup-registry-verdict.mjs` | correctness | runtime invariant: no recorded verdict from a still-filling registry (AGENTS.md section) · static ratchet over runtime source · origin #4769 · landed 2026-08-03 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-step-collectors.mjs` | process | none (a lint step running several self-tests cannot mask one) · meta-gate · origin #4690 · landed 2026-08-21 | required · whole-repo (Lint & Repo Gates) | 1 PRs / 1 days (2026-09-01..2026-09-01) | `keep` | +| `scripts/check-system-context-census.mjs` | process | none (docs system-context page anchors and counts equal the source census) · docs census · origin #15921 · landed 2026-08-30 | required · whole-repo (Lint & Repo Gates) | 21 PRs / 9 days (2026-08-30..09-10; annotation-tagged `[anchor-is-not-a-read-site]`/`[declared-count]`; +2 unresolved on the shared step) | `keep` | +| `scripts/check-tenant-audit-census.mjs` | process | none (docs tenant-audit census page equals the tree) · docs census · origin no card in header · landed 2026-08-31 | required · whole-repo (Lint & Repo Gates) | 4 PRs / 3 days (2026-09-02..2026-09-10); 1 self excluded | `keep` | +| `scripts/check-tenant-chokepoint.mjs` | correctness | read-side tenant chokepoint (ADR-0105 security invariant) · static ratchet over runtime source · origin #2734 · landed 2026-08-09 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-test-completeness.mjs` | correctness | a `turbo run test` log ran every package it should · origin #3812 · landed 2026-07-28 | advisory (Dogfood Regression Gat); advisory (Nightly tiers (${{ mat); advisory (Test Core (${{ matrix.) | unmeasured (runs inside Test Core / Dogfood / Nightly; 1 failing step in window on a Test Core shard, not separable from the test failure it reported) | `keep` | +| `scripts/check-test-source-alias.mjs` | correctness | unit tests are a verdict about source (vitest alias hygiene) · origin #4757 · landed 2026-08-12 | required · whole-repo (Lint & Repo Gates) | 3 PRs / 3 days (2026-08-19..2026-09-16) | `keep` | +| `scripts/check-tier-file-adoption.mjs` | correctness | a package adopting a nightly tier reads the tier file · origin no card in header · landed 2026-09-10 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-10; <7 days of window coverage) | `keep` | +| `scripts/check-turbo-task-graph.mjs` | correctness | turbo.json package tasks name real packages and scripts · origin #12046 · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-type-check-coverage.mjs` | correctness | every package is type-check covered or in the shrink-only DEBT ledger · origin #4311 · landed 2026-07-31 | required · whole-repo (TypeScript Type Check ← debt lane); required · whole-repo (TypeScript Type Check ← source lane) | 20 PRs / 11 days (2026-08-21..09-03; `--re-measure` debt-ledger lane) | `keep` | +| `scripts/check-type-source-resolution.mjs` | correctness | a package's types resolve from source, not stale dist · origin #7849 · landed 2026-08-12 | required · whole-repo (Lint & Repo Gates) | 3 PRs / 3 days (2026-08-20..2026-09-16); 1 self excluded | `keep` | +| `scripts/check-undeclared-dep-imports.mjs` | contract | published `src/**` imports only declared workspace deps · origin #10062 · landed 2026-08-28 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-vendor-export-contract.mjs` | contract | a consumer-resolved vendor version exports what we import · origin #10909 · landed 2026-09-07 | required · whole-repo (Lint & Repo Gates); advisory (Validate Package Depen) | 0 in window | `keep` | +| `scripts/check-vendor-version-stamps.mjs` | process | none (prose version stamps about a pinned vendor stay equal to the pin) · docs · origin #10073 · landed 2026-08-31 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-verify-stand-in-erasure.mjs` | correctness | ESLint guard on `@objectstack/verify` stand-in erasure · origin #4984 · landed 2026-08-08 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-watch-hint-literal.mjs` | process | none (`ROOT_DIR_WATCH_HINTS` declarations are literals) · meta-gate · origin no card in header · landed 2026-08-28 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-where-matcher-conformance.mjs` | correctness | in-memory WHERE matchers in tests conform to the engine · origin #7619 · landed 2026-08-13 | required · whole-repo (Lint & Repo Gates) | 7 PRs / 7 days (2026-08-22..2026-09-13) | `keep` | +| `scripts/check-whole-set-label-write.mjs` | process | none (nothing issues a whole-set label PUT) · PM loop · origin #10698 · landed 2026-08-24 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-widget-option-census.mjs` | contract | `CONSUMED_WIDGET_OPTION_KEYS` derived from the spec, not pinned · origin #12810 · landed 2026-08-29 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/check-wildcard-fallthrough.mjs` | correctness | permission namespace wildcard fall-through (ADR-0069 runtime invariant) · static ratchet over runtime source · origin #923 · landed 2026-07-30 | required · whole-repo (Lint & Repo Gates) | 0 in window (1 failure(s) only on PRs editing this file, excluded) | `keep` | +| `scripts/check-workflow-status-functions.mjs` | process | none — CI integrity: job-level `if:` status functions are spelled safely · CI-integrity group · origin #4900 · landed 2026-08-05 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/check-workflow-step-name-quoting.mjs` | process | none — CI integrity: unquoted step names do not truncate at " #" · CI-integrity group · origin #13419 · landed 2026-09-10 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-10; <7 days of window coverage) | `keep (too new)` | +| `scripts/check-workspace-manifest-cycles.mjs` | correctness | workspace manifest dependency graph has no cycle · origin #13513 · landed 2026-09-02 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `scripts/docs-audit/check-affected-docs.mjs` | process | none (change → affected-docs mapper; feeds the advisory docs-drift comment) · docs · origin #9187 · landed 2026-08-17 | advisory (Flag docs affected by) | 1 PRs / 1 days (2026-09-05..2026-09-05); 1 self excluded | `report-only` | +| `scripts/docs-audit/check-audit-scope.mjs` | process | none (docs-accuracy-audit scope list is derived, not hand-kept) · docs · origin #4920 · landed 2026-08-03 | required · whole-repo (Lint & Repo Gates) | 1 PRs / 1 days (2026-09-09..2026-09-09) | `keep` | +| `scripts/docs-audit/check-docs-transcript-drift.mjs` | contract | CLI transcripts in published docs match the CLI registry · origin #15369 · landed 2026-09-05 | required · whole-repo (TypeScript Type Check ← workspace lane) | 0 in window | `keep` | +| `scripts/docs-audit/check-drift-comment.mjs` | process | none (pins the advisory docs-drift comment headline) · docs · origin #11180 · landed 2026-08-24 | advisory (Flag docs affected by) | 0 in window | `report-only` | +| `scripts/pm/check-clause2-carriers.mjs` | process | none (Clause-② enqueue-gate limbs legible) — only its self-test runs in CI · PM loop · origin #12409 · landed 2026-08-31 | required · whole-repo (Lint & Repo Gates) | 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | `retire` | +| `scripts/pm/check-dispatch-gates.mjs` | process | none (CI gate for the dispatch-gates tool: its battery reads the live tree) · PM loop · origin #8162 · landed 2026-08-13 | required · family-scoped (Lint & Repo Gates, `select-gate-families`) | 15 PRs / 11 days (2026-08-25..09-16; battery reads the live tree, so sibling PRs trip it; log-sampled ×1) | `keep` | +| `scripts/pm/check-expected-skips.mjs` | process | none (enqueue bar's SKIP half legible) — only its self-test runs in CI · PM loop · origin #18298 · landed 2026-09-16 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-16; <7 days of window coverage) | `keep (too new)` | +| `scripts/pm/check-governed-merges.mjs` | process | none (report-only post-merge audit of governed-surface merges) · governed audit · origin #4690 · landed 2026-08-18 | required · whole-repo (Lint & Repo Gates) | 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | `report-only` | +| `scripts/pm/check-governed-prose.mjs` | process | none (AGENTS.md PD#14 surface list equals `GOVERNED_SURFACES`) · governed prose · origin #9395 · landed 2026-08-19 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/pm/check-governed-queue-guard.mjs` | process | none — the maintainer's approval mechanism for governed surfaces (PD#14) · ruled keep · origin #9319 · landed 2026-08-25 | required · whole-repo (Governed Surface Queue Guard) | 0 in window | `keep (ruled)` | +| `scripts/pm/check-half-states.mjs` | process | none (report-only enumeration of PM half-states) — only its self-test runs in lint · PM loop · origin #7341 · landed 2026-08-10 | required · whole-repo (Lint & Repo Gates); advisory (Live half-state sweep) | 0 in window | `report-only` | +| `scripts/pm/check-harness-current.mjs` | process | none (harness-loaded files on origin/main are in the running harness) — only its self-test runs in CI · PM loop · origin #18327 · landed 2026-09-14 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-14; the shared step's 10 failures on 2026-08-21 predate it) | `keep` | +| `scripts/pm/check-label-desc-cap.mjs` | process | none (label descriptions in the pm vocabulary fit the cap) · PM loop · origin no card in header · landed 2026-08-20 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/pm/check-prior-rulings.mjs` | process | none (mechanical half of the governing-text step) — only its self-test runs in CI · PM loop · origin #15929 · landed 2026-09-13 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-13; <7 days of window coverage) | `keep (too new)` | +| `scripts/pm/check-settings-deny-roster.mjs` | process | none (`.claude/settings.json` deny list pinned) · PM loop · origin #18218 · landed 2026-09-15 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-15; <7 days of window coverage) | `keep (too new)` | +| `scripts/pm/check-skill-id-lint.mjs` | process | none (operative agent-protocol text cites no issue numbers) · PM loop · origin no card in header · landed 2026-08-12 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `scripts/pm/check-skill-line-ratchet.mjs` | process | none (per-file line budget over the PM instruction surface) · PM loop · origin #5925 · landed 2026-08-10 | required · whole-repo (Lint & Repo Gates) | 0 in window (7 failure(s) only on PRs editing this file, excluded) | `retire` | +| `scripts/pm/check-widening-tells.mjs` | process | none (mechanical half of the directional Clause-② read) — only its self-test runs in CI · PM loop · origin #16349 · landed 2026-09-07 | required · whole-repo (Lint & Repo Gates) | 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | `retire` | +| `check:adr-symbol-anchors` | process | none (symbol-anchors module self-test + check-adr-symbol-anchors) · composite · `node scripts/symbol-anchors.mjs --self-test && node scripts/check-adr-symbol-anchors.mjs -…` | not in PR CI | 1 PR / 2 days (check-adr-symbol-anchors leg) | `keep` | +| `check:docs-audit-scope` | process | none (affected-docs self-test + check-audit-scope) · composite · `node scripts/docs-audit/affected-docs.mjs --self-test && node scripts/docs-audit/check-aud…` | required · whole-repo (Lint & Repo Gates) | 1 PR / 1 day (check-audit-scope leg) | `keep` | +| `check:docs-image-tag-sync` | contract | release lane: self-test of the docs image-tag version-time rewriter (run by release.yml version-pr) · `node scripts/sync-docs-image-tags.mjs --self-test` | required · whole-repo (Lint & Repo Gates); advisory (Version PR maintenance) | 0 in window — self-test only; cannot judge a PR | `keep` | +| `check:merge-driver` | process | none (merge-driver wiring: git-env, git-merge-regen and check-regen-pending self-tests) · composite of three self-tests · `node scripts/git-env.mjs --self-test && node scripts/git-merge-regen.mjs --self-test && no…` | required · whole-repo (Lint & Repo Gates) | 20 PRs / 3 days (2026-09-01..09-05; 2 clusters riding main; log-sampled: git-merge-regen ledger drift, check-regen-pending self-test) | `keep` | +| `check:objectui-bump` | contract | objectui pin write-ordering self-test (console pin tooling) · `bash scripts/bump-objectui.selftest.sh` | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `check:objectui-changeset` | contract | objectui pin-changeset digest + range self-tests (console pin tooling) · `node scripts/objectui-changeset-digest.mjs --self-test && node scripts/objectui-range.mjs …` | required · whole-repo (Lint & Repo Gates) | 2 PRs / 2 days | `keep` | +| `check:platform-checklist` | process | none (checklist-select self-test + check-platform-checklist) — advisory watchdog workflow · QA · `node scripts/checklist-select.mjs --self-test && node scripts/check-platform-checklist.mjs…` | advisory (Platform checklist gate sweep) | unmeasured (advisory watchdog workflow; 0 failed runs of it in the window sample — schedule + PR) | `report-only` | +| `check:pm-board-snapshot` | process | none (self-test of the board-snapshot archiver) · PM tool self-test only · `node scripts/pm/board-snapshot.mjs --self-test` | required · whole-repo (Lint & Repo Gates) | 0 in window — self-test only; cannot judge a PR | `retire` | +| `check:pm-changeset-deadline-census` | process | none (self-test of the changeset-deadline census) · PM tool self-test only · `node scripts/pm/changeset-deadline-census.mjs --self-test` | required · whole-repo (Lint & Repo Gates) | 0 in window — self-test only; cannot judge a PR | `retire` | +| `check:pm-closed-card-sweep` | process | none (self-test of the closed-card sweeper tool) · PM tool self-test only · `node scripts/pm/sweep-closed-cards.mjs --self-test` | not in PR CI | 0 in window — self-test only; cannot judge a PR | `retire` | +| `check:pm-label-write` | process | none (self-test of the label-write helper) · PM tool self-test only · `node scripts/pm/label-write.mjs --self-test` | required · whole-repo (Lint & Repo Gates) | 0 in window — self-test only; cannot judge a PR | `retire` | +| `check:pm-post-stamped` | process | none (self-test of the stamped-post helper) · PM tool self-test only · `node scripts/pm/post-stamped.mjs --self-test` | required · whole-repo (Lint & Repo Gates) | 0 in window — self-test only; cannot judge a PR | `retire` | +| `check:pm-stale-finding` | process | none (self-test of the stale-finding sweeper tool) · PM tool self-test only · `node scripts/pm/sweep-stale-finding.mjs --self-test` | required · whole-repo (Lint & Repo Gates) | 0 in window — self-test only; cannot judge a PR | `retire` | +| `check:pnpm-filter-targets` | correctness | every committed `pnpm --filter` names a real package (pnpm-filter-targets + checker self-tests) · `node scripts/pnpm-filter-targets.mjs --self-test && node scripts/check-pnpm-filter-targets…` | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `check:publish-smoke-pin` | contract | publish lane: self-test of the publish-smoke pack pin set · `node scripts/publish-smoke-pack.mjs --self-test` | required · whole-repo (Lint & Repo Gates) | 0 in window — self-test only; cannot judge a PR | `keep` | +| `check:release-body` | contract | release lane: GitHub Release body limit self-test · `node scripts/release-github-releases.mjs --self-test` | required · whole-repo (Lint & Repo Gates) | 0 in window — self-test only; cannot judge a PR | `keep` | +| `check:release-index-currency-sync` | contract | release lane: self-test of the release-index currency rewriter (release.yml version-pr) · `node scripts/sync-release-index-currency.mjs --self-test` | required · whole-repo (Lint & Repo Gates); advisory (Version PR maintenance) | 0 in window — self-test only; cannot judge a PR | `keep` | +| `check:scaffold-emission-policy` | contract | generated scaffold emission policy in the create-objectstack on-ramp is current · `node scripts/sync-scaffold-emission-policy.mjs --self-test && node scripts/sync-scaffold-e…` | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | +| `check:scripts-symbol-anchors` | process | none (symbol-anchors module self-test + check-scripts-symbol-anchors) · composite · `node scripts/symbol-anchors.mjs --self-test && node scripts/check-scripts-symbol-anchors.m…` | not in PR CI | 0 in window | `retire` | +| `check:select-gate-families` | process | none — CI integrity: gate-family selection self-test · CI-integrity group · `bash scripts/ci/select-gate-families.selftest.sh` | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `check:select-shard-packages` | process | none — CI integrity: Test Core package selection self-test · CI-integrity group · `bash scripts/ci/select-shard-packages.selftest.sh` | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | +| `check:spec-docblock-symbol-anchors` | process | none (symbol-anchors module self-test + check-spec-docblock-symbol-anchors) · composite · `node scripts/symbol-anchors.mjs --self-test && node scripts/check-spec-docblock-symbol-anc…` | not in PR CI | 0 in window | `retire` | +| `check:stall-guard` | correctness | CI stall guard self-test · `node scripts/run-with-stall-guard.mjs --self-test` | required · whole-repo (TypeScript Type Check ← source gates lane) | 0 in window — self-test only; cannot judge a PR | `keep` | +| `check:stall-guard-headroom` | correctness | CI stall-guard headroom self-test · `node scripts/measure-stall-guard-headroom.mjs --self-test` | required · whole-repo (TypeScript Type Check ← source gates lane) | 0 in window — self-test only; cannot judge a PR | `keep` | +| `check:swallow-census-controls` | process | none (control families of the durability swallow census) · measurement controls · `node scripts/measure-durability-swallow-family.mjs --self-test=gated` | required · whole-repo (TypeScript Type Check ← source gates lane) | 1 PR / 1 day | `keep` | +| `check:template-version-sync` | contract | release lane: self-test of the template version-time rewriter (release.yml version-pr) · `node scripts/sync-template-versions.mjs --self-test` | required · whole-repo (Lint & Repo Gates); advisory (Version PR maintenance) | 0 in window — self-test only; cannot judge a PR | `keep` | +| `.claude/hooks/guard-governed-enqueue.selftest.sh` | process | self-test of `guard-governed-enqueue.sh` (counted as what it serves) · landed 2026-09-01 | required · whole-repo (Lint & Repo Gates, `Claude hook guard self-tests` step discovers every `*.selftest.sh`) | 0 in window (that step never failed in the sample) | `keep (with its hook)` | +| `.claude/hooks/guard-governed-enqueue.sh` | process | AGENTS.md PD#14 — session-side half of the governed queue guard (blocks enqueue/merge tools on a governed PR) · origin no card in header · landed 2026-09-01 | not a CI gate — PreToolUse hook in `.claude/settings.json`; blocks the tool call in every agent session | unmeasured (a PreToolUse block leaves no repo-visible record) | `keep (session hook; see Method)` | +| `.claude/hooks/guard-main-checkout-bash.selftest.sh` | process | self-test of `guard-main-checkout-bash.sh` (counted as what it serves) · landed 2026-08-06 | required · whole-repo (Lint & Repo Gates, `Claude hook guard self-tests` step discovers every `*.selftest.sh`) | 0 in window (that step never failed in the sample) | `keep (with its hook)` | +| `.claude/hooks/guard-main-checkout-bash.sh` | process | AGENTS.md PD#11 worktree-first, Bash-side (redirection, sed -i, cp/mv/rm on the shared checkout) · origin #3435 · landed 2026-08-06 | not a CI gate — PreToolUse hook in `.claude/settings.json`; blocks the tool call in every agent session | unmeasured (a PreToolUse block leaves no repo-visible record) | `keep (session hook; see Method)` | +| `.claude/hooks/guard-main-checkout.selftest.sh` | process | self-test of `guard-main-checkout.sh` (counted as what it serves) · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates, `Claude hook guard self-tests` step discovers every `*.selftest.sh`) | 0 in window (that step never failed in the sample) | `keep (with its hook)` | +| `.claude/hooks/guard-main-checkout.sh` | process | AGENTS.md PD#11 worktree-first (blocks Edit/Write on the shared checkout) · origin no card in header · landed 2026-06-14 | not a CI gate — PreToolUse hook in `.claude/settings.json`; blocks the tool call in every agent session | unmeasured (a PreToolUse block leaves no repo-visible record) | `keep (session hook; see Method)` | +| `.claude/hooks/guard-process-kill.selftest.sh` | process | self-test of `guard-process-kill.sh` (counted as what it serves) · landed 2026-09-08 | required · whole-repo (Lint & Repo Gates, `Claude hook guard self-tests` step discovers every `*.selftest.sh`) | 0 in window (that step never failed in the sample) | `keep (with its hook)` | +| `.claude/hooks/guard-process-kill.sh` | process | AGENTS.md Multi-agent §8 — kill only a recorded PID, never a name · origin #16120 · landed 2026-09-08 | not a CI gate — PreToolUse hook in `.claude/settings.json`; blocks the tool call in every agent session | unmeasured (a PreToolUse block leaves no repo-visible record) | `keep (session hook; see Method)` | +| `.claude/hooks/guard-shared-stash.selftest.sh` | process | self-test of `guard-shared-stash.sh` (counted as what it serves) · landed 2026-08-08 | required · whole-repo (Lint & Repo Gates, `Claude hook guard self-tests` step discovers every `*.selftest.sh`) | 0 in window (that step never failed in the sample) | `keep (with its hook)` | +| `.claude/hooks/guard-shared-stash.sh` | process | AGENTS.md Multi-agent discipline — the shared stash stack is never mutated · origin #3430 · landed 2026-08-08 | not a CI gate — PreToolUse hook in `.claude/settings.json`; blocks the tool call in every agent session | unmeasured (a PreToolUse block leaves no repo-visible record) | `keep (session hook; see Method)` | +| `.claude/hooks/guard-tree-enum.selftest.sh` | process | self-test of `guard-tree-enum.sh` (counted as what it serves) · landed 2026-08-30 | required · whole-repo (Lint & Repo Gates, `Claude hook guard self-tests` step discovers every `*.selftest.sh`) | 0 in window (that step never failed in the sample) | `keep (with its hook)` | +| `.claude/hooks/guard-tree-enum.sh` | process | origin/main reading rule covers file enumeration (guard header #13305) · origin #13305 · landed 2026-08-30 | not a CI gate — PreToolUse hook in `.claude/settings.json`; blocks the tool call in every agent session | unmeasured (a PreToolUse block leaves no repo-visible record) | `keep (session hook; see Method)` | + +Row count: **227** (7 contexts · 182 files · 26 scripts · 12 hooks). + +## Retirement list + +**59 rows** (49 files · 10 root scripts whose every leg is a helper self-test). Every row: `catches` is a measured zero (or `unmeasured` for a stated reason) and the contract half of `guards` is `none`. ⛔ Nothing here is removed by this PR; the list is the input to the retirement batch. + +Deletion footprint per row: the file(s) to delete, the root `package.json` script(s) to drop, the workflow lines to remove (`file:line`, taken at `85c6d76e`), and how many other tracked files outside `scripts/**` still name it (AGENTS.md, `.claude/**`, `docs/**`, `.github/**` — prose to fix in the same PR). No retire row has a `.d.mts` mirror or an `scripts/adr-anchors/` entry. Rosters that derive from the tree at runtime need no edit: `dispatch-gates.mjs` families, `check-self-test-wired.mjs`, `check-step-collectors.mjs` (it parses lint.yml), `check-declared-population-live.mjs`. Deleting a `--self-test` leg also removes it from the `Self-test wiring gate` population automatically. + +### CI-integrity sub-group (rule says retire; presented as a set) + +These nine guard the CI farm's own wiring — the required-context names, aggregator `needs:` rosters, Node/pnpm acquisition, `if:` status functions, self-test wiring, shard/family selectors. Each has a measured zero and no published contract, so the rule retires them; their value is deterrence over the workflow files, which this window did not exercise (every failure on them was on a PR editing the gate itself). The director can present them as one keep-or-retire decision rather than nine. + +| row | delete | drop from `package.json` | workflow lines | other refs | +|:--|:--|:--|:--|--:| +| `scripts/check-aggregator-roster.mjs` | `scripts/check-aggregator-roster.mjs` | — | lint.yml:3796, lint.yml:3797, lint.yml:6549 | 3 | +| `scripts/check-node-version.mjs` | `scripts/check-node-version.mjs` | `check:node-version` | lint.yml:3429 | 5 | +| `scripts/check-pnpm-acquisition.mjs` | `scripts/check-pnpm-acquisition.mjs` | `check:pnpm-acquisition` | lint.yml:3453 | 2 | +| `scripts/check-required-contexts.mjs` | `scripts/check-required-contexts.mjs` | `check:required-contexts` | lint.yml:3828, required-set-patrol.yml:104, required-set-patrol.yml:151 | 9 | +| `scripts/check-self-test-wired.mjs` | `scripts/check-self-test-wired.mjs` | — | lint.yml:1597, lint.yml:1598 | 3 | +| `scripts/check-self-test-workflow-commands.mjs` | `scripts/check-self-test-workflow-commands.mjs` | — | lint.yml:1640, lint.yml:1641 | 2 | +| `scripts/check-workflow-status-functions.mjs` | `scripts/check-workflow-status-functions.mjs` | `check:workflow-status-functions` | lint.yml:3474 | 3 | +| `check:select-gate-families` | `scripts/ci/select-gate-families.selftest.sh (only if no other user; check before deleting)` | `check:select-gate-families` | lint.yml:3769 | 0 | +| `check:select-shard-packages` | `scripts/ci/select-shard-packages.selftest.sh (only if no other user; check before deleting)` | `check:select-shard-packages` | lint.yml:3725 | 0 | + +### Everything else on the list + +| row | class · why it is on the list | delete | drop from `package.json` | workflow lines | other refs | +|:--|:--|:--|:--|:--|--:| +| `packages/lint/scripts/check-reference-carrier-shape.mjs` | contract · objectstack#18095 ruling E — its one real defect class moves to the reader's fail-loud | `packages/lint/scripts/check-reference-carrier-shape.mjs` | — | lint.yml:4662, lint.yml:4663 | 2 | +| `scripts/check-agent-model-declared.mjs` | process · 0 in window | `scripts/check-agent-model-declared.mjs` | `check:agent-model-declared` | lint.yml:5366 | 3 | +| `scripts/check-agent-test-spelling.mjs` | process · 0 in window | `scripts/check-agent-test-spelling.mjs` | `check:agent-test-spelling` | lint.yml:4561 | 2 | +| `scripts/check-bash32-floor.mjs` | process · 0 in window | `scripts/check-bash32-floor.mjs` | `check:bash32-floor` | lint.yml:678 | 3 | +| `scripts/check-closing-keyword-parity.mjs` | process · 0 in window | `scripts/check-closing-keyword-parity.mjs` | — | lint.yml:3610, lint.yml:3611, cross-repo-issue-closer.yml:214 | 3 | +| `scripts/check-comment-mask-adoption.mjs` | process · 0 in window | `scripts/check-comment-mask-adoption.mjs` | — | lint.yml:598, lint.yml:599 | 2 | +| `scripts/check-comment-mask-corpus.mjs` | process · 0 in window | `scripts/check-comment-mask-corpus.mjs` | — | lint.yml:723 | 3 | +| `scripts/check-corpus-claim-drift.mjs` | process · 0 in window | `scripts/check-corpus-claim-drift.mjs` | `check:corpus-claim-drift` | lint.yml:2520 | 4 | +| `scripts/check-cross-repo-closer-outcome.mjs` | process · 0 in window | `scripts/check-cross-repo-closer-outcome.mjs` | — | lint.yml:3584, lint.yml:3585 | 2 | +| `scripts/check-doc-frontmatter.mjs` | process · 0 in window | `scripts/check-doc-frontmatter.mjs` | — | lint.yml:1912, lint.yml:1913 | 4 | +| `scripts/check-docs-locale-catch-all.mjs` | process · 0 in window | `scripts/check-docs-locale-catch-all.mjs` | `check:docs-locale-catch-all` | lint.yml:2142 | 2 | +| `scripts/check-docs-nav-label.mjs` | process · 0 in window | `scripts/check-docs-nav-label.mjs` | — | lint.yml:1943, lint.yml:1944 | 6 | +| `scripts/check-docs-redirects.mjs` | process · 0 in window | `scripts/check-docs-redirects.mjs` | `check:docs-redirects` | lint.yml:2110 | 2 | +| `scripts/check-docs-single-h1.mjs` | process · 0 in window | `scripts/check-docs-single-h1.mjs` | `check:docs-single-h1` | lint.yml:2070 | 5 | +| `scripts/check-lockstep-package-count.mjs` | process · 0 in window | `scripts/check-lockstep-package-count.mjs` | `check:lockstep-package-count` | lint.yml:3313 | 1 | +| `scripts/check-merge-queue-triage-outcome.mjs` | process · 0 in window | `scripts/check-merge-queue-triage-outcome.mjs` | — | lint.yml:3654, lint.yml:3655 | 2 | +| `scripts/check-merged-branch-reaper-outcome.mjs` | process · 0 in window | `scripts/check-merged-branch-reaper-outcome.mjs` | — | lint.yml:3690, lint.yml:3691 | 3 | +| `scripts/check-org-identifier.mjs` | process · 0 in window | `scripts/check-org-identifier.mjs` | `check:org-identifier` | lint.yml:2836 | 5 | +| `scripts/check-parse-guard.mjs` | process · 0 in window | `scripts/check-parse-guard.mjs` | `check:parse-guard` | lint.yml:563 | 2 | +| `scripts/check-platform-checklist-watchdog.mjs` | process · 0 in window | `scripts/check-platform-checklist-watchdog.mjs` | — | lint.yml:2825, lint.yml:2826 | 2 | +| `scripts/check-platform-object-tenancy-census.mjs` | process · 0 in window | `scripts/check-platform-object-tenancy-census.mjs` | `check:platform-object-tenancy-census` | lint.yml:2043, lint.yml:2044 | 5 | +| `scripts/check-position-name-fold-loaders.mjs` | process · 0 in window | `scripts/check-position-name-fold-loaders.mjs` | — | lint.yml:755, lint.yml:756 | 2 | +| `scripts/check-published-list-mirrors.mjs` | process · 0 in window | `scripts/check-published-list-mirrors.mjs` | — | lint.yml:4077, lint.yml:4078 | 2 | +| `scripts/check-quick-reference-counts.mjs` | process · 0 in window | `scripts/check-quick-reference-counts.mjs` | `check:quick-reference-counts` | lint.yml:2580 | 2 | +| `scripts/check-ratchet-remedy-authority.mjs` | process · 0 in window (4 failure(s) only on PRs editing this file, excluded) | `scripts/check-ratchet-remedy-authority.mjs` | `check:ratchet-remedy-authority` | lint.yml:5387 | 2 | +| `scripts/check-route-ledger-census.mjs` | process · 0 in window | `scripts/check-route-ledger-census.mjs` | `check:route-ledger-census` | lint.yml:3328 | 2 | +| `scripts/check-runtime-services-index.mjs` | process · 0 in window | `scripts/check-runtime-services-index.mjs` | `check:runtime-services-index` | lint.yml:2651 | 4 | +| `scripts/check-scripts-symbol-anchors.mjs` | process · 0 in window | `scripts/check-scripts-symbol-anchors.mjs` | `check:scripts-symbol-anchors` | lint.yml:2760, lint.yml:2778 | 2 | +| `scripts/check-section-landing-index.mjs` | process · 0 in window | `scripts/check-section-landing-index.mjs` | — | lint.yml:2699, lint.yml:2700 | 4 | +| `scripts/check-skill-frame-freshness.mjs` | process · 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | `scripts/check-skill-frame-freshness.mjs` | `check:skill-frame-freshness` | lint.yml:5318 | 3 | +| `scripts/check-skill-frame-sync.mjs` | process · 0 in window | `scripts/check-skill-frame-sync.mjs` | `check:skill-frame-sync` | lint.yml:5282 | 2 | +| `scripts/check-skills-token-ratchet.mjs` | process · 0 in window (3 failure(s) only on PRs editing this file, excluded) | `scripts/check-skills-token-ratchet.mjs` | — | lint.yml:5411, lint.yml:5412 | 2 | +| `scripts/check-spec-docblock-symbol-anchors.mjs` | process · 0 in window | `scripts/check-spec-docblock-symbol-anchors.mjs` | `check:spec-docblock-symbol-anchors` | lint.yml:2761, lint.yml:2792 | 2 | +| `scripts/check-vendor-version-stamps.mjs` | process · 0 in window | `scripts/check-vendor-version-stamps.mjs` | `check:vendor-version-stamps` | lint.yml:2910 | 2 | +| `scripts/check-watch-hint-literal.mjs` | process · 0 in window | `scripts/check-watch-hint-literal.mjs` | `check:watch-hint-literal` | lint.yml:926 | 3 | +| `scripts/check-whole-set-label-write.mjs` | process · 0 in window | `scripts/check-whole-set-label-write.mjs` | — | lint.yml:3533, lint.yml:3534 | 2 | +| `scripts/pm/check-clause2-carriers.mjs` | process · 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | `scripts/pm/check-clause2-carriers.mjs` | `check:pm-clause2-carriers` | lint.yml:1140 | 4 | +| `scripts/pm/check-governed-prose.mjs` | process · 0 in window | `scripts/pm/check-governed-prose.mjs` | `check:pm-governed-prose` | lint.yml:1353 | 2 | +| `scripts/pm/check-label-desc-cap.mjs` | process · 0 in window | `scripts/pm/check-label-desc-cap.mjs` | `check:pm-label-desc-cap` | lint.yml:838 | 2 | +| `scripts/pm/check-skill-id-lint.mjs` | process · 0 in window | `scripts/pm/check-skill-id-lint.mjs` | `check:pm-skill-id-lint` | lint.yml:825 | 3 | +| `scripts/pm/check-skill-line-ratchet.mjs` | process · 0 in window (7 failure(s) only on PRs editing this file, excluded) | `scripts/pm/check-skill-line-ratchet.mjs` | `check:pm-skill-ratchet` | lint.yml:817 | 3 | +| `scripts/pm/check-widening-tells.mjs` | process · 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | `scripts/pm/check-widening-tells.mjs` | `check:pm-widening-tells` | lint.yml:1153 | 2 | +| `check:pm-board-snapshot` | process · 0 in window — self-test only; cannot judge a PR | `scripts/pm/board-snapshot.mjs (only if no other user; check before deleting)` | `check:pm-board-snapshot` | lint.yml:1259 | 0 | +| `check:pm-changeset-deadline-census` | process · 0 in window — self-test only; cannot judge a PR | `scripts/pm/changeset-deadline-census.mjs (only if no other user; check before deleting)` | `check:pm-changeset-deadline-census` | lint.yml:1313 | 0 | +| `check:pm-closed-card-sweep` | process · 0 in window — self-test only; cannot judge a PR | `scripts/pm/sweep-closed-cards.mjs (only if no other user; check before deleting)` | `check:pm-closed-card-sweep` | — | 0 | +| `check:pm-label-write` | process · 0 in window — self-test only; cannot judge a PR | `scripts/pm/label-write.mjs (only if no other user; check before deleting)` | `check:pm-label-write` | lint.yml:1238 | 0 | +| `check:pm-post-stamped` | process · 0 in window — self-test only; cannot judge a PR | `scripts/pm/post-stamped.mjs (only if no other user; check before deleting)` | `check:pm-post-stamped` | lint.yml:1212 | 0 | +| `check:pm-stale-finding` | process · 0 in window — self-test only; cannot judge a PR | `scripts/pm/sweep-stale-finding.mjs (only if no other user; check before deleting)` | `check:pm-stale-finding` | lint.yml:1291 | 0 | +| `check:scripts-symbol-anchors` | process · 0 in window | `scripts/symbol-anchors.mjs (only if no other user; check before deleting)`, `scripts/check-scripts-symbol-anchors.mjs (only if no other user; check before deleting)`, `scripts/check-scripts-symbol-anchors.mjs (only if no other user; check before deleting)` | `check:scripts-symbol-anchors` | — | 0 | +| `check:spec-docblock-symbol-anchors` | process · 0 in window | `scripts/symbol-anchors.mjs (only if no other user; check before deleting)`, `scripts/check-spec-docblock-symbol-anchors.mjs (only if no other user; check before deleting)`, `scripts/check-spec-docblock-symbol-anchors.mjs (only if no other user; check before deleting)` | `check:spec-docblock-symbol-anchors` | — | 0 | + +## Report-only list + +**16 rows** — advisory today, no fail-closed role. They cost a run per PR (or per schedule) and can red a check the PM loop reads, but none blocks the merge queue. + +| row | where it runs | catches in window | note | +|:--|:--|:--|:--| +| `scripts/check-adr-links.mjs` | advisory (Check Documentation Li) | 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | runs in `Check Links` (not required); its self-test is not in lint | +| `scripts/check-closing-target-claim.mjs` | advisory (Closing-Target Claim Guard workflow, PR + merge_group); Lint & Repo Gates runs only its `--self-test` | unmeasured (landed 2026-09-12; Closing-Target Claim Guard: 0 failed runs in the sample); lint runs only its self-test | `Closing-Target Claim Guard` workflow (PR + merge_group, not required); lint runs only its self-test | +| `scripts/check-doc-route-spelling.mjs` | required · whole-repo (Lint & Repo Gates) | 0 in window | invoked with `--advisory` in lint.yml | +| `scripts/check-engine-split-ratio.mjs` | required · whole-repo (Lint & Repo Gates); advisory (Engine cross-package c) | 0 in window (its shared lint step failed on 10 PRs on 2026-08-21; log-sampled failure = `git-history.mjs --self-test`, not this file) | ADR-0076 D7 metric; the lint step only runs its self-test | +| `scripts/check-issue-citations.mjs` | not in PR CI (root `check:*` exists; no workflow or hook runs it) | unmeasured (not run by any PR workflow or hook) | root `check:issue-citations` exists (self-test only) but no workflow or hook runs it — a tool, not a gate | +| `scripts/check-merged-result.mjs` | not in PR CI (root `check:*` exists; no workflow or hook runs it) | unmeasured (not run by any PR workflow or hook) | root `check:merged-result` exists (self-test only) but no workflow runs it — a probe tool | +| `scripts/check-osv-exemptions.mjs` | advisory (Validate Package Depen) | 0 in window | runs in `Validate Dependencies` (not required) | +| `scripts/check-partof-closing-keyword.mjs` | advisory (Part-of Closing-Keyword Guard workflow); Lint & Repo Gates runs only its `--self-test` | 31 PRs / 13 days (job-level: the guard workflow's only gate; 0 self excluded) — advisory workflow, reds the check, does not block | the one report-only gate that fires — 31 PRs; promote into a required context or retire, not both | +| `scripts/check-platform-checklist.mjs` | advisory (Platform checklist gat) | 0 in window | checklist shape; `Platform-Checklist Watchdog` (schedule + PR, not required) | +| `scripts/check-prerelease-pin-watch.mjs` | advisory (Stable release watch f) | 0 in window | a watch — npm probe on schedule/PR | +| `scripts/check-single-claim-paths.mjs` | advisory (Single-Claim Path Guard workflow); Lint & Repo Gates runs only its `--self-test` | 0 in window (Single-Claim Path Guard: 0 failed runs in the sample); lint runs only its self-test | `Single-Claim Path Guard` workflow (not required); lint runs only its self-test | +| `scripts/docs-audit/check-affected-docs.mjs` | advisory (Flag docs affected by) | 1 PRs / 1 days (2026-09-05..2026-09-05); 1 self excluded | feeds the advisory docs-drift PR comment | +| `scripts/docs-audit/check-drift-comment.mjs` | advisory (Flag docs affected by) | 0 in window | pins the advisory docs-drift comment headline | +| `scripts/pm/check-governed-merges.mjs` | required · whole-repo (Lint & Repo Gates) | 0 in window — only its `--self-test` runs in CI; the gate proper never judges a PR here | post-merge audit by design; the lint step only runs its self-test | +| `scripts/pm/check-half-states.mjs` | required · whole-repo (Lint & Repo Gates); advisory (Live half-state sweep) | 0 in window | live sweep is schedule/PR advisory; the lint step only runs its self-test | +| `check:platform-checklist` | advisory (Platform checklist gate sweep) | unmeasured (advisory watchdog workflow; 0 failed runs of it in the window sample — schedule + PR) | composite root script of the row above plus `checklist-select.mjs --self-test` | + +## Method + limits + +**Inventories.** ① `find scripts -name "check-*.mjs"` (178) + `find packages -path "*/scripts/check-*.mjs"` (4). ② root `package.json` `check:*` (164), each command's targets resolved (including `pnpm --filter PKG run check:X` through that package's `package.json`); a script whose every target is an ① file is a thin alias and is not a row. ③ `find .claude/hooks -type f` (12). ④ the branch-rules read named in the card, 2026-09-16. The union is disjoint by construction, so rows = 182 + 26 + 12 + 7 = 227. + +**Not rows, by the card's definition, but gates all the same**: 70 per-package `check:*` scripts (31 in `packages/spec`, 3 `packages/lint`, 2 `packages/cli`, 2 `packages/client`, 32 singletons — all `check:test-typecheck`) run by the `TypeScript Type Check` lanes; every one is `contract` or `correctness` (the spec generated-artefact set, exported-any, test typecheck) and would read `keep`. 31 workflow-direct steps run a script that is not a `check-*` file (`scripts/pm/bare-root-worklist.mjs --self-test`, `git-history.mjs --self-test`, `ts-parse.mjs`, `invoked-as.mjs`, `js-comment-mask.mjs`, `import-prerequisite.mjs`, `symbol-anchors.mjs`, `pr-labels.mjs`, `run-with-stall-guard.mjs`, …); three of them failed PRs in the window (`git-history.mjs --self-test` 10 PRs on one day, `bare-root-worklist.mjs --self-test` 5 PRs, `git-merge-regen.mjs --self-test` inside `check:merge-driver`). Two inline workflow gates with no script: `Require a changeset (or the skip-changeset label)` (107 PRs red — the largest single source) and the typecheck aggregator's `verify-lanes` heredoc. A follow-up census could take these as ⑤; this one names them so the union stays honest. + +**Column 5 method.** Runs: `GET /actions/workflows/ID/runs?event=pull_request&status=failure&created=>=2026-08-17` for the eight PR-triggered gate workflows (lint 338, ci 189, pr-automation 449, partof 99, validate-deps 55, check-links 49, docs-drift 50, governed 1 = 1,230; the repo-wide total is 1,480 — the other 250 are workflows with no gate rows: CodeQL, Duplicate Fix Guard, …). Jobs: `GET /actions/runs/ID/jobs?filter=latest` per run, reading each failed job's failed **steps**. Attribution: a lint.yml/ci.yml step name maps to exactly one gate except four shared steps (`Docs anchors…` = doc-anchors + system-context-census; `Shallow-history guard self-tests` = 4 self-tests; `Merge-driver wiring gate` = 3 self-tests; `Symbol-anchor gate self-tests` = 4); those were split by annotation tag (`GET /check-runs/ID/annotations`, 1,287 reads — most annotations say only `Process completed with exit code 1`, so tags exist only where the gate prints `::error::`) and by nine sampled job logs through the MCP read tool (`get_job_logs`, `tail_lines=60`; the REST log endpoint 302-redirects to a blob host the egress proxy refuses with 403). PR identity: the run's `pull_requests[]` when present (349 runs), else `GET /pulls?head=objectstack-ai:BRANCH&state=all` (491 branches resolved, 9 with no PR — counted by branch). Self exclusion: `GET /pulls/N/files` (paged) — a PR whose file list contains the gate's own file is not a catch. The aggregate steps `Verify test shard results`, `Verify dogfood shard results` and `Verify every type-check lane succeeded` fail whenever a shard or lane fails, so they are counted for the job, never for `check-shard-attestation.mjs` / `check-aggregator-roster.mjs`. 330 of the 1,230 failed runs had no job in `failure`/`timed_out`/`cancelled` at their latest attempt (a re-run that passed keeps the run's original conclusion) and contribute nothing. A `0 in window` is therefore a measurement: the gate ran on every PR in the sample and never failed on a PR that did not edit it. Clustering is stated where the dates show one landed red riding `main` into many PRs (`exported-any-returns` 15 PRs / 2 days; `check:merge-driver` 20 PRs / 3 days; `git-history` 10 PRs / 1 day). + +**Landing dates.** The clone is shallow (floor 2026-09-09, 599 commits), so `git log --diff-filter=A` cannot reach most landings; each file's first commit was read instead from `GET /commits?path=FILE` paged to the oldest page (194 reads, none failed). Distribution: 2026-05 ×1, 2026-06 ×3, 2026-07 ×20, 2026-08 ×131, 2026-09 ×39 — 170 of the 194 files are under ten weeks old, and 13 landed inside the window's last week (`keep (too new)` / `unmeasured`). + +**Hooks.** A PreToolUse block happens inside an agent session and leaves nothing this census can read, so column 5 is `unmeasured` by construction. The literal rule (process + unmeasured + no contract) would retire all six; they are filed `keep (session hook)` because four are the enforcement AGENTS.md names for Prime Directive #11 and the stash/process-kill rules, one is the session-side half of the ruled-keep governed queue guard, and one (`guard-tree-enum.sh`) guards the `origin/main` reading rule — the maintainer can overrule any row. Their `*.selftest.sh` files run in `Lint & Repo Gates` (`Claude hook guard self-tests`) and never failed in the window. + +**Limits.** (1) One 30-day window; a gate that fires once a quarter reads as zero. (2) Distinct PRs, not distinct root causes — a landed red counts every PR it rode into; the clusters are named where visible, not everywhere. (3) Step-level attribution cannot see a gate that fails inside a step it shares unless the gate tags its output; two of the 25 `Docs anchors` failures stay unresolved. (4) Self-test-only rows: a failing self-test is a regression of the tool or of the tree it reads, which is a real catch for that row but never a judgement of the PR's diff — the card's "cannot judge a diff" reading; 29 root `check:*` scripts are self-test-only. (5) The four `Type Check` lanes are counted under their aggregator context; a lane is not a required context by itself. (6) `check-partof-closing-keyword.mjs` is counted job-level because the step name in the workflow at `85c6d76e` differs from the two spellings the API returned for older runs. (7) Exclusion uses the PR's file list at read time, not at run time — a PR that touched the gate after the failure is still excluded. (8) Nothing here was re-run locally; the readings are GitHub's. + From bf4d0c18283b7df1cecaaa52b3118165c05f8f4a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 16 Sep 2026 16:04:36 +0000 Subject: [PATCH 2/2] =?UTF-8?q?docs(audits):=20re-derive=20the=20gate=20ce?= =?UTF-8?q?nsus=20on=20the=20merged=20tree=20=E2=80=94=20225=20rows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit origin/main moved seven commits before the PR opened; one of them removed the client-side enqueue guard hook and its self-test, so the hook inventory is 10 and the union 225. Adds a Drift paragraph naming what moved and re-reads the five changed scripts/pm gates from the merged tree. Claude-Session: https://claude.ai/code/session_01Wj1HUjzyeiBQ8atRf1ZhaL Co-authored-by: Claude --- docs/audits/gate-census-2026-09.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/audits/gate-census-2026-09.md b/docs/audits/gate-census-2026-09.md index 72408a7c9ca..fc5978f2193 100644 --- a/docs/audits/gate-census-2026-09.md +++ b/docs/audits/gate-census-2026-09.md @@ -1,6 +1,6 @@ # Audit: gate census 2026-09 — every `check-*.mjs`, `check:*` script, hook and required context on one table -**Date**: 2026-09-16 · **Tree**: `origin/main` at `85c6d76e` (worktree `objectstack-issue-18472`, shallow floor 2026-09-09) · **Card**: #18472 · +**Date**: 2026-09-16 · **Tree**: base `origin/main` at `85c6d76e`, re-derived on the branch after merging `origin/main` at `bf61f0a1` (merge `a22464ae`; worktree `objectstack-issue-18472`, shallow floor 2026-09-09) · **Card**: #18472 · **Ruling**: maintainer ruling **F**, verbatim 「F」, on 「现在有各种门禁的开发在浪费我的各种时间,我们的项目是不是门禁用的太重了。有这个必要吗?」 · **Report-only**: this audit removes, disables and edits **no** gate. The retirement batch follows as its own card(s) after the maintainer's one-word 「认可」 on the table. @@ -12,27 +12,27 @@ Zod validation inside `packages/spec` and the runtime is the **product**, not a |:--|:--|--:| | ① check files | every `scripts/**/check-*.mjs` (178) and `packages/*/scripts/check-*.mjs` (4) | **182** | | ② root `check:*` scripts that are not a thin alias | 164 root `check:*` scripts; 138 run only inventory-① file(s) (thin alias, collapsed onto the file row); **26** run something else (a composite of helper self-tests, a `.sh`/`.mjs` outside ①, or a `--check` of a generator) | **26** | -| ③ hooks | every file under `.claude/hooks/` — 6 PreToolUse guards + their 6 `*.selftest.sh` | **12** | +| ③ hooks | every file under `.claude/hooks/` — 5 PreToolUse guards + their 5 `*.selftest.sh` (the base tree had 6 + 6; #18478 removed `guard-governed-enqueue.sh` and its self-test on `main` after the base, so the merged tree is counted) | **10** | | ④ required contexts | `GET /repos/objectstack-ai/objectstack/rules/branches/main` → `required_status_checks` (ruleset 12119582, `strict=false`) | **7** | -| **union = rows** | the four sets are disjoint by construction (paths, script names, hook paths, job names) | **227** = 182 + 26 + 12 + 7 | +| **union = rows** | the four sets are disjoint by construction (paths, script names, hook paths, job names) | **225** = 182 + 26 + 10 + 7 | | verdict | rows | |:--|--:| | `keep` | 133 | | `retire` | 58 | | `report-only` | 16 | -| `keep (session hook; see Method)` | 6 | -| `keep (with its hook)` | 6 | +| `keep (session hook; see Method)` | 5 | | `keep (too new)` | 5 | +| `keep (with its hook)` | 5 | | `keep (ruled)` | 2 | | `retire (ruled)` | 1 | | **retire (all spellings)** | **59** | -| **keep (all spellings)** | **152** | +| **keep (all spellings)** | **150** | | **report-only** | **16** | | class | rows | |:--|--:| -| `process` | 117 | +| `process` | 115 | | `contract` | 60 | | `correctness` | 50 | @@ -71,7 +71,7 @@ Zod validation inside `packages/spec` and the runtime is the **product**, not a | `scripts/check-adr-symbol-anchors.mjs` | process | none (docs/adr symbol anchors resolve; ADR-0113) · origin #13556 · landed 2026-09-03 | required · whole-repo (Lint & Repo Gates) | 1 PRs / 2 days (2026-09-03..2026-09-04) | `keep` | | `scripts/check-agent-model-declared.mjs` | process | none (.claude/agents/*.md declare a model) · PM loop · origin #6566 · landed 2026-08-09 | required · whole-repo (TypeScript Type Check ← source lane) | 0 in window | `retire` | | `scripts/check-agent-test-spelling.mjs` | process | none (no committed command forwards vitest args through a bare `--`) · origin #10166 · landed 2026-08-24 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | -| `scripts/check-aggregator-roster.mjs` | process | none — CI integrity: an aggregate job `needs:` every lane it vouches for · CI-integrity group · origin #4690 · landed 2026-08-21 | required · whole-repo (Lint & Repo Gates); required · whole-repo (TypeScript Type Check) | 0 in window (its own `Aggregator roster gate` step never failed; the typecheck aggregator step that mentions it in a comment failed on 71 PRs = lane failures) | `retire` | +| `scripts/check-aggregator-roster.mjs` | process | none — CI integrity: an aggregate job `needs:` every lane it vouches for · CI-integrity group · origin #4690 · landed 2026-08-21 | required · whole-repo (Lint & Repo Gates) | 0 in window (its own `Aggregator roster gate` step never failed; the typecheck aggregator step that mentions it in a comment failed on 71 PRs = lane failures) | `retire` | | `scripts/check-auth-mount-ledger.mjs` | contract | published REST auth route surface (mount vs ledger) · origin #9941 · landed 2026-08-22 | required · whole-repo (Lint & Repo Gates) | 0 in window | `keep` | | `scripts/check-bash32-floor.mjs` | process | none (shell scripts stay bash-3.2 compatible) · origin #12221 · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | | `scripts/check-changeset-fixed.mjs` | contract | npm publish: every publishable package is in the Changesets `fixed` group · origin #11510 · landed 2026-05-25 | advisory (Cut an rc from one sna); advisory (Publish ${{ needs.rele); advisory (Validate Package Depen); advisory (Version PR maintenance) | 0 in window | `keep` | @@ -236,7 +236,7 @@ Zod validation inside `packages/spec` and the runtime is the **product**, not a | `scripts/pm/check-governed-prose.mjs` | process | none (AGENTS.md PD#14 surface list equals `GOVERNED_SURFACES`) · governed prose · origin #9395 · landed 2026-08-19 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | | `scripts/pm/check-governed-queue-guard.mjs` | process | none — the maintainer's approval mechanism for governed surfaces (PD#14) · ruled keep · origin #9319 · landed 2026-08-25 | required · whole-repo (Governed Surface Queue Guard) | 0 in window | `keep (ruled)` | | `scripts/pm/check-half-states.mjs` | process | none (report-only enumeration of PM half-states) — only its self-test runs in lint · PM loop · origin #7341 · landed 2026-08-10 | required · whole-repo (Lint & Repo Gates); advisory (Live half-state sweep) | 0 in window | `report-only` | -| `scripts/pm/check-harness-current.mjs` | process | none (harness-loaded files on origin/main are in the running harness) — only its self-test runs in CI · PM loop · origin #18327 · landed 2026-09-14 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-14; the shared step's 10 failures on 2026-08-21 predate it) | `keep` | +| `scripts/pm/check-harness-current.mjs` | process | none (harness-loaded files on origin/main are in the running harness) — only its self-test runs in CI · PM loop · origin #18330 · landed 2026-09-14 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-14; the shared step's 10 failures on 2026-08-21 predate it) | `keep` | | `scripts/pm/check-label-desc-cap.mjs` | process | none (label descriptions in the pm vocabulary fit the cap) · PM loop · origin no card in header · landed 2026-08-20 | required · whole-repo (Lint & Repo Gates) | 0 in window | `retire` | | `scripts/pm/check-prior-rulings.mjs` | process | none (mechanical half of the governing-text step) — only its self-test runs in CI · PM loop · origin #15929 · landed 2026-09-13 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-13; <7 days of window coverage) | `keep (too new)` | | `scripts/pm/check-settings-deny-roster.mjs` | process | none (`.claude/settings.json` deny list pinned) · PM loop · origin #18218 · landed 2026-09-15 | required · whole-repo (Lint & Repo Gates) | unmeasured (landed 2026-09-15; <7 days of window coverage) | `keep (too new)` | @@ -269,8 +269,6 @@ Zod validation inside `packages/spec` and the runtime is the **product**, not a | `check:stall-guard-headroom` | correctness | CI stall-guard headroom self-test · `node scripts/measure-stall-guard-headroom.mjs --self-test` | required · whole-repo (TypeScript Type Check ← source gates lane) | 0 in window — self-test only; cannot judge a PR | `keep` | | `check:swallow-census-controls` | process | none (control families of the durability swallow census) · measurement controls · `node scripts/measure-durability-swallow-family.mjs --self-test=gated` | required · whole-repo (TypeScript Type Check ← source gates lane) | 1 PR / 1 day | `keep` | | `check:template-version-sync` | contract | release lane: self-test of the template version-time rewriter (release.yml version-pr) · `node scripts/sync-template-versions.mjs --self-test` | required · whole-repo (Lint & Repo Gates); advisory (Version PR maintenance) | 0 in window — self-test only; cannot judge a PR | `keep` | -| `.claude/hooks/guard-governed-enqueue.selftest.sh` | process | self-test of `guard-governed-enqueue.sh` (counted as what it serves) · landed 2026-09-01 | required · whole-repo (Lint & Repo Gates, `Claude hook guard self-tests` step discovers every `*.selftest.sh`) | 0 in window (that step never failed in the sample) | `keep (with its hook)` | -| `.claude/hooks/guard-governed-enqueue.sh` | process | AGENTS.md PD#14 — session-side half of the governed queue guard (blocks enqueue/merge tools on a governed PR) · origin no card in header · landed 2026-09-01 | not a CI gate — PreToolUse hook in `.claude/settings.json`; blocks the tool call in every agent session | unmeasured (a PreToolUse block leaves no repo-visible record) | `keep (session hook; see Method)` | | `.claude/hooks/guard-main-checkout-bash.selftest.sh` | process | self-test of `guard-main-checkout-bash.sh` (counted as what it serves) · landed 2026-08-06 | required · whole-repo (Lint & Repo Gates, `Claude hook guard self-tests` step discovers every `*.selftest.sh`) | 0 in window (that step never failed in the sample) | `keep (with its hook)` | | `.claude/hooks/guard-main-checkout-bash.sh` | process | AGENTS.md PD#11 worktree-first, Bash-side (redirection, sed -i, cp/mv/rm on the shared checkout) · origin #3435 · landed 2026-08-06 | not a CI gate — PreToolUse hook in `.claude/settings.json`; blocks the tool call in every agent session | unmeasured (a PreToolUse block leaves no repo-visible record) | `keep (session hook; see Method)` | | `.claude/hooks/guard-main-checkout.selftest.sh` | process | self-test of `guard-main-checkout.sh` (counted as what it serves) · landed 2026-08-25 | required · whole-repo (Lint & Repo Gates, `Claude hook guard self-tests` step discovers every `*.selftest.sh`) | 0 in window (that step never failed in the sample) | `keep (with its hook)` | @@ -282,7 +280,7 @@ Zod validation inside `packages/spec` and the runtime is the **product**, not a | `.claude/hooks/guard-tree-enum.selftest.sh` | process | self-test of `guard-tree-enum.sh` (counted as what it serves) · landed 2026-08-30 | required · whole-repo (Lint & Repo Gates, `Claude hook guard self-tests` step discovers every `*.selftest.sh`) | 0 in window (that step never failed in the sample) | `keep (with its hook)` | | `.claude/hooks/guard-tree-enum.sh` | process | origin/main reading rule covers file enumeration (guard header #13305) · origin #13305 · landed 2026-08-30 | not a CI gate — PreToolUse hook in `.claude/settings.json`; blocks the tool call in every agent session | unmeasured (a PreToolUse block leaves no repo-visible record) | `keep (session hook; see Method)` | -Row count: **227** (7 contexts · 182 files · 26 scripts · 12 hooks). +Row count: **225** (7 contexts · 182 files · 26 scripts · 10 hooks). ## Retirement list @@ -386,15 +384,17 @@ These nine guard the CI farm's own wiring — the required-context names, aggreg ## Method + limits -**Inventories.** ① `find scripts -name "check-*.mjs"` (178) + `find packages -path "*/scripts/check-*.mjs"` (4). ② root `package.json` `check:*` (164), each command's targets resolved (including `pnpm --filter PKG run check:X` through that package's `package.json`); a script whose every target is an ① file is a thin alias and is not a row. ③ `find .claude/hooks -type f` (12). ④ the branch-rules read named in the card, 2026-09-16. The union is disjoint by construction, so rows = 182 + 26 + 12 + 7 = 227. +**Inventories.** ① `find scripts -name "check-*.mjs"` (178) + `find packages -path "*/scripts/check-*.mjs"` (4). ② root `package.json` `check:*` (164), each command's targets resolved (including `pnpm --filter PKG run check:X` through that package's `package.json`); a script whose every target is an ① file is a thin alias and is not a row. ③ `find .claude/hooks -type f` (10 on the merged tree; 12 at the base — see Drift). ④ the branch-rules read named in the card, 2026-09-16. The union is disjoint by construction, so rows = 182 + 26 + 10 + 7 = 225. **Not rows, by the card's definition, but gates all the same**: 70 per-package `check:*` scripts (31 in `packages/spec`, 3 `packages/lint`, 2 `packages/cli`, 2 `packages/client`, 32 singletons — all `check:test-typecheck`) run by the `TypeScript Type Check` lanes; every one is `contract` or `correctness` (the spec generated-artefact set, exported-any, test typecheck) and would read `keep`. 31 workflow-direct steps run a script that is not a `check-*` file (`scripts/pm/bare-root-worklist.mjs --self-test`, `git-history.mjs --self-test`, `ts-parse.mjs`, `invoked-as.mjs`, `js-comment-mask.mjs`, `import-prerequisite.mjs`, `symbol-anchors.mjs`, `pr-labels.mjs`, `run-with-stall-guard.mjs`, …); three of them failed PRs in the window (`git-history.mjs --self-test` 10 PRs on one day, `bare-root-worklist.mjs --self-test` 5 PRs, `git-merge-regen.mjs --self-test` inside `check:merge-driver`). Two inline workflow gates with no script: `Require a changeset (or the skip-changeset label)` (107 PRs red — the largest single source) and the typecheck aggregator's `verify-lanes` heredoc. A follow-up census could take these as ⑤; this one names them so the union stays honest. **Column 5 method.** Runs: `GET /actions/workflows/ID/runs?event=pull_request&status=failure&created=>=2026-08-17` for the eight PR-triggered gate workflows (lint 338, ci 189, pr-automation 449, partof 99, validate-deps 55, check-links 49, docs-drift 50, governed 1 = 1,230; the repo-wide total is 1,480 — the other 250 are workflows with no gate rows: CodeQL, Duplicate Fix Guard, …). Jobs: `GET /actions/runs/ID/jobs?filter=latest` per run, reading each failed job's failed **steps**. Attribution: a lint.yml/ci.yml step name maps to exactly one gate except four shared steps (`Docs anchors…` = doc-anchors + system-context-census; `Shallow-history guard self-tests` = 4 self-tests; `Merge-driver wiring gate` = 3 self-tests; `Symbol-anchor gate self-tests` = 4); those were split by annotation tag (`GET /check-runs/ID/annotations`, 1,287 reads — most annotations say only `Process completed with exit code 1`, so tags exist only where the gate prints `::error::`) and by nine sampled job logs through the MCP read tool (`get_job_logs`, `tail_lines=60`; the REST log endpoint 302-redirects to a blob host the egress proxy refuses with 403). PR identity: the run's `pull_requests[]` when present (349 runs), else `GET /pulls?head=objectstack-ai:BRANCH&state=all` (491 branches resolved, 9 with no PR — counted by branch). Self exclusion: `GET /pulls/N/files` (paged) — a PR whose file list contains the gate's own file is not a catch. The aggregate steps `Verify test shard results`, `Verify dogfood shard results` and `Verify every type-check lane succeeded` fail whenever a shard or lane fails, so they are counted for the job, never for `check-shard-attestation.mjs` / `check-aggregator-roster.mjs`. 330 of the 1,230 failed runs had no job in `failure`/`timed_out`/`cancelled` at their latest attempt (a re-run that passed keeps the run's original conclusion) and contribute nothing. A `0 in window` is therefore a measurement: the gate ran on every PR in the sample and never failed on a PR that did not edit it. Clustering is stated where the dates show one landed red riding `main` into many PRs (`exported-any-returns` 15 PRs / 2 days; `check:merge-driver` 20 PRs / 3 days; `git-history` 10 PRs / 1 day). -**Landing dates.** The clone is shallow (floor 2026-09-09, 599 commits), so `git log --diff-filter=A` cannot reach most landings; each file's first commit was read instead from `GET /commits?path=FILE` paged to the oldest page (194 reads, none failed). Distribution: 2026-05 ×1, 2026-06 ×3, 2026-07 ×20, 2026-08 ×131, 2026-09 ×39 — 170 of the 194 files are under ten weeks old, and 13 landed inside the window's last week (`keep (too new)` / `unmeasured`). +**Landing dates.** The clone is shallow (floor 2026-09-09, 599 commits), so `git log --diff-filter=A` cannot reach most landings; each file's first commit was read instead from `GET /commits?path=FILE` paged to the oldest page (194 reads at the base tree, none failed; the two removed hook files are dropped). Distribution over the 192 rows that are files: 2026-05 ×1, 2026-06 ×3, 2026-07 ×20, 2026-08 ×129, 2026-09 ×39 — 168 of the 192 are under ten weeks old, and 13 landed inside the window's last week (`keep (too new)` / `unmeasured`). -**Hooks.** A PreToolUse block happens inside an agent session and leaves nothing this census can read, so column 5 is `unmeasured` by construction. The literal rule (process + unmeasured + no contract) would retire all six; they are filed `keep (session hook)` because four are the enforcement AGENTS.md names for Prime Directive #11 and the stash/process-kill rules, one is the session-side half of the ruled-keep governed queue guard, and one (`guard-tree-enum.sh`) guards the `origin/main` reading rule — the maintainer can overrule any row. Their `*.selftest.sh` files run in `Lint & Repo Gates` (`Claude hook guard self-tests`) and never failed in the window. +**Hooks.** A PreToolUse block happens inside an agent session and leaves nothing this census can read, so column 5 is `unmeasured` by construction. The literal rule (process + unmeasured + no contract) would retire all five; they are filed `keep (session hook)` because four are the enforcement AGENTS.md names for Prime Directive #11 and the stash/process-kill rules, and one (`guard-tree-enum.sh`) guards the `origin/main` reading rule — the maintainer can overrule any row. The sixth guard at the base, `guard-governed-enqueue.sh`, was removed on `main` by #18478 (「the merge_group queue guard is the line」) before this PR opened and has no row. Their `*.selftest.sh` files run in `Lint & Repo Gates` (`Claude hook guard self-tests`) and never failed in the window. + +**Drift between base and PR.** The census was first derived at `85c6d76e`; `origin/main` moved seven commits before the PR opened and the branch merged it (`bf61f0a1` → merge `a22464ae`). What moved among the rows: #18478 deleted `.claude/hooks/guard-governed-enqueue.sh` + its self-test (12 → 10 hook rows, union 227 → 225); #18481 flipped the gate asymmetry in the PM skill (adding a required gate/hook/ratchet joins the human floor; a census-marked retirement becomes class-1) — the protocol half of ruling F; five `scripts/pm/check-*.mjs` changed content (`check-governed-merges`, `check-governed-queue-guard`, `check-harness-current`, `check-settings-deny-roster`, `check-widening-tells`) — their wiring and origin cards were re-read from the merged tree, and their verdicts did not change. The catches sample is unaffected (it is GitHub's record, keyed by step name). **Limits.** (1) One 30-day window; a gate that fires once a quarter reads as zero. (2) Distinct PRs, not distinct root causes — a landed red counts every PR it rode into; the clusters are named where visible, not everywhere. (3) Step-level attribution cannot see a gate that fails inside a step it shares unless the gate tags its output; two of the 25 `Docs anchors` failures stay unresolved. (4) Self-test-only rows: a failing self-test is a regression of the tool or of the tree it reads, which is a real catch for that row but never a judgement of the PR's diff — the card's "cannot judge a diff" reading; 29 root `check:*` scripts are self-test-only. (5) The four `Type Check` lanes are counted under their aggregator context; a lane is not a required context by itself. (6) `check-partof-closing-keyword.mjs` is counted job-level because the step name in the workflow at `85c6d76e` differs from the two spellings the API returned for older runs. (7) Exclusion uses the PR's file list at read time, not at run time — a PR that touched the gate after the failure is still excluded. (8) Nothing here was re-run locally; the readings are GitHub's.