diff --git a/.agents/roles/standards-enforcer.md b/.agents/roles/standards-enforcer.md index 270fbc1eb..6ee73af64 100644 --- a/.agents/roles/standards-enforcer.md +++ b/.agents/roles/standards-enforcer.md @@ -3,7 +3,7 @@ title: Standards Enforcer Role status: active owner: eng canonical: true -last_verified: 2026-07-22 +last_verified: 2026-09-02 doc_type: role scope: repo-wide review_interval_days: 90 @@ -18,7 +18,9 @@ Check changed files against repo instructions and context standards before PR re 1. Read `docs/context-standards.md`. 2. Identify applicable `AGENTS.md` files from repo root down to each changed file. -3. Identify applicable checklists from `docs/pr-checklists/` and `pnpm agent:quality-gate --dry-run`. +3. Identify applicable checklists from `docs/pr-checklists/`, scoped + instructions, and the author-check table in step 3 of the + [operating card](../../docs/notes/pr-operating-card.md). 4. Run `pnpm agent:context-check`. 5. Review for canonical/non-canonical confusion, missing scoped instructions, duplicated instructions, missing metadata, and root policy that belongs in nested AGENTS. diff --git a/.agents/roles/verifier.md b/.agents/roles/verifier.md index 58d42faac..9e0c4fe04 100644 --- a/.agents/roles/verifier.md +++ b/.agents/roles/verifier.md @@ -3,7 +3,7 @@ title: Verifier Role status: active owner: eng canonical: true -last_verified: 2026-08-26 +last_verified: 2026-09-02 doc_type: role scope: repo-wide review_interval_days: 90 @@ -16,25 +16,16 @@ Run diff-scoped verification and report only actionable results. ## Procedure -1. Inspect the branch diff against `origin/main`. -2. Run `pnpm agent:quality-gate --dry-run` and confirm mapped commands/checklists match changed surfaces. -3. Unless the requester asked for dry verification only, run the gate as a - background task. A local setup runs `pnpm agent:quality-gate --run` against - the resolved PR base. In a hosted setup, run the resolved-base gate first - when the resolved base tracking ref is not `origin/main`. This includes fork - and stacked PRs. Then fetch `origin/main` and warm the hook with - `./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main`. If - the resolved base is `origin/main`, this hook warm is also the resolved-base - gate. - Before invoking it, ensure - that no direct validation, dashboard server, or browser suite outside the - coordinator is active on the same machine. Concurrent `--run` gates from - other worktrees can continue through the coordinator. They share weighted - machine capacity. From invocation until this gate exits, do not start - uncoordinated work there. Use same-machine spare workers only for read-only - work. Run validation outside the coordinator from a fully hydrated checkout - on another machine. -4. Report every failed or skipped command, the relevant output, and the +1. Inspect the branch diff against the resolved pull request base. Use the + resolved PR base, not a fixed `origin/main`, for every diff-based author + check, including stacked PRs. +2. Read the scoped instructions and checklists for the changed surfaces. +3. Select the applicable direct author checks from step 3 of + [`pr-operating-card.md`](../../docs/notes/pr-operating-card.md). Unless the + requester asked for dry verification only, run those checks directly and + record each result as the card requires. Do not substitute the legacy + diagnostic gate for the author-check table. +4. Report every failed or not-run command, the relevant output, and the smallest next fix. ## Output diff --git a/.agents/skills/backlog-sweep/SKILL.md b/.agents/skills/backlog-sweep/SKILL.md index fea412244..6cb394c3a 100644 --- a/.agents/skills/backlog-sweep/SKILL.md +++ b/.agents/skills/backlog-sweep/SKILL.md @@ -20,11 +20,11 @@ larger batch — and reads the report afterwards. Default batch size is 2. The session that runs this skill is an **orchestrator**. It ranks, picks, claims, hands each issue to a dedicated worker subagent, and grooms the queue -for the next run. It runs no gate, edits no source file, and opens no PR. Those -three prohibitions keep concurrent workers out of each other's trees, so they -bind only while separate workers exist: on a runtime with no way to spawn one, -the session works the batch sequentially and takes both roles itself, one issue -at a time. +for the next run. It runs no author check, edits no source file, and opens no +PR. Those three prohibitions keep concurrent workers out of each other's trees, +so they bind only while separate workers exist: on a runtime with no way to +spawn one, the session works the batch sequentially and takes both roles +itself, one issue at a time. **It merges nothing, in either shape.** That boundary is unconditional — it has nothing to do with tree isolation or with how many actors are running, and the @@ -46,14 +46,13 @@ worker works ## Preflight -Every check here fails cheaply. Skipping one fails late, after issues are -already claimed and a worker is mid-gate. +Every check here fails cheaply. Skipping one fails late, after issues are already claimed and a worker is mid-validation. ```bash -git fetch origin main -git status --porcelain # must print nothing -gh auth status # must report an authenticated account -git remote get-url --push origin # must serve mento-protocol/monitoring-monorepo +gh auth status # must report an authenticated account +git remote -v # origin fetch and push must serve mento-protocol/monitoring-monorepo +git status --porcelain # must print nothing +git fetch origin main # only after both origin URLs pass ``` **A fork checkout is a stop, before anything is claimed.** The operating card @@ -62,29 +61,21 @@ first-publish, because a cross-repository PR is one that workflow can never drive to ready ([`pr-operating-card.md`](../../../docs/notes/pr-operating-card.md)). Workers inherit this checkout's remote, so a sweep started from a fork would claim -upstream issues, implement and gate all of them, and only then discover that -none of them can open a PR. Check the push URL here, where it costs one +upstream issues, implement and validate all of them, and only then discover that +none of them can open a PR. Check both effective URLs here, where they cost one command. A dirty session worktree is a stop, not a warning. The orchestrator does not commit, so nothing it does would clear those changes, and a sweep that runs beside unfinished work makes the two indistinguishable in the report. -**Do not probe the gate's lock, and never stop on it.** Gate `--run` requests -share a transient machine-wide coordinator that admits independent work from -different worktrees under a weighted capacity, so a new gate **joins** a -compatible coordinator rather than queueing behind it -([`agent-quality-gate-mechanics.md`](../../../docs/notes/agent-quality-gate-mechanics.md)). -The coordinator adopts the legacy `run.lock` while scheduled or recovery work -exists, which makes `run.lock/owner` name a live pid for as long as anyone on -the machine is gating — hours, routinely, during ordinary parallel work. A -sweep that read that record as a busy signal would refuse to start in the -normal case. Local workers wait with `--lock-wait 3600`. Hosted workers use the -hook's exact 1,800-second default. Both cover scheduler admission, a command -lease, a coalesced result, and an older legacy holder. Never pass `--no-lock` -and never delete the lock directory: the gate owns its own reclaim rules, and a -record that looks stale from outside is routinely a live holder inside a long -browser suite. +**Do not probe or change the legacy gate's lock.** Workers run the direct author +checks from operating-card step 3 in isolated checkouts. The batch cap remains +the CPU and memory bound. Run no more than three ordinary command-heavy check +sets at once. Run dashboard coverage or scoped related tests, browser work, +production builds, and size-limit work alone. Other workers can keep editing. +A browser check that finds its fixed port in use must fail and report the +conflict. It must not wait for, stop, or reuse another process. **State the usage reality before starting.** One shipped PR costs roughly 3% of the weekly usage window, and every push to it triggers another Codex review, @@ -190,9 +181,9 @@ Take the top N — default 2 — that satisfy **all** of: That label is the repo's own ownership area, so it settles "same subsystem" by lookup rather than per-batch judgement. Two workers editing one package produce PRs whose diffs conflict and whose reviewers see a base moving under - them, and the second PR then pays for a merge, a re-gate, and a fresh review - round it did not need. `pkg:tooling` gets a path test instead of the label - test, below. + them, and the second PR then pays for a merge, repeated author checks, and a + fresh review round it did not need. `pkg:tooling` gets a path test instead of + the label test, below. - **Outside its own grooming veto window.** A candidate whose newest _trusted_ `sweep-groomed:` marker comment is less than 12 hours old waits for the next run, whatever version that marker carries — the window asks whether a @@ -451,10 +442,10 @@ Then spawn one worker subagent per issue. Give each a brief containing: **`$dir` is the working directory for every later command, not just the clone.** `git clone` does not move the shell, and a worker can inherit the - orchestrator's directory, so setup, the branch, the edits, the gate, and the - push would all run in the orchestrator's checkout — the one tree this whole - scheme exists to keep workers out of, and the one the preflight requires to - stay clean. A shell that does not persist between calls does not make this + orchestrator's directory, so setup, the branch, the edits, the author checks, + and the push would all run in the orchestrator's checkout — the one tree this + whole scheme exists to keep workers out of, and the one the preflight requires + to stay clean. A shell that does not persist between calls does not make this optional: every fresh shell re-enters `$dir` first, and no worker command is ever issued from an unstated directory. @@ -462,7 +453,7 @@ Then spawn one worker subagent per issue. Give each a brief containing: fixed once and passed to every worker beside `sweep_id`. Take the **push** URL specifically: `git clone` copies no remote config, `pushurl` included, so where a checkout's fetch and push URLs differ a worker cloned from the fetch - URL gates cleanly and then pushes somewhere nobody is watching. `--push` + URL passes its checks and then pushes somewhere nobody is watching. `--push` returns `pushurl` when one is set and the fetch URL otherwise, so it is right either way. Do not hard-code the public HTTPS URL. A worker must push, not merely clone, and the transport that @@ -470,7 +461,7 @@ Then spawn one worker subagent per issue. Give each a brief containing: using — often SSH, while `gh auth status` says nothing about git's credential helper. Cloning over a transport nobody has credentials for succeeds on a public repository and then fails at the push, after the whole issue has been - implemented and gated. + implemented and validated. `worker_dir` is set only on a respawn, to the path the orchestrator recorded for this worker. Use it verbatim; do not re-derive. A worker displaced to a @@ -504,29 +495,18 @@ Then spawn one worker subagent per issue. Give each a brief containing: name, and `mkdir` is the atomic claim that makes the loser take the next suffix instead. - In Claude Code, subagents inherit the parent session's Bash worktree pin, so - git in a sibling worktree under `.claude/worktrees/` is refused for them, and - a tmp clone is the only checkout those workers can use. The general rule - outlives that specific block: every worker gets an isolated checkout — a - clone or a worktree — that its own runtime can actually write to, because two - workers in one checkout is the failure this is preventing. Then run - `./scripts/setup.sh` unsandboxed in **every** new clone, not conditionally. - It is what sets `core.hooksPath` to `.trunk/hooks`, so a checkout that only - ran `pnpm install` has no pre-push hook — and a worker there could push - without the gate the boundaries below forbid bypassing. Run it on **resumed** - checkouts too, not just fresh ones: the marker is written straight after the - clone, so an interruption between the two leaves an owned checkout with no - hooks, and a resume that trusted the marker would push from it. Rerunning is - free — the script owns codegen and the browser dependencies and skips its own - work when the inputs are unchanged — which is why this is a blanket rule - rather than a condition to evaluate. - - Before spawning workers, read the orchestrator checkout's - `agent.qualityGate.cloudPrePushRequireFresh` value and pass one hosted/local - boolean to every worker. After `./scripts/setup.sh` in each fresh or resumed - clone, set `agent.qualityGate.cloudPrePushRequireFresh=true` when that boolean - is hosted. Unset the key when it is local. A clone does not inherit local git - config, so never infer its setup type from the clone before this propagation. + Claude subagents cannot use sibling worktrees, so each uses an isolated tmp + clone. Before resumed setup, use the operating-card preflight to resolve and + fetch the pull request base, or verified `origin/main` without a pull request. + Set `BASE_REMOTE` and `baseRefName` for that base. Inspect `git status --short`, + `git diff "$BASE_REMOTE/$baseRefName"...HEAD`, `git diff --cached`, `git diff`, + and untracked files. Inspect lifecycle and install effects for changed manifests, + lockfiles, pnpm configuration, or patches; stop if the change set is unclear. + + Run `./scripts/setup.sh` in every resumed clone only after that inspection. In + a fresh clone, fetch and run `git switch --detach origin/main` before setup. + Setup prepares the staged formatter, dependencies, codegen, and browser tools; + its markers make unchanged reruns cheap. Branch as **the exact name the orchestrator passed to `issue:claim --branch`**, from `origin/main`. That name is already in the Project `Branch` @@ -541,8 +521,8 @@ Then spawn one worker subagent per issue. Give each a brief containing: issue that was released and later re-selected. Resume it only on proof it is this sweep's own, which is what the `sweep-owner` comparison above decides. Keep the marker inside `.git/` — a file at the clone root would be untracked - in every worker checkout, where a clean-worktree check can refuse the gate or - the push and broad staging can commit the marker into the PR. Remote and + in every worker checkout, where a clean-worktree check can refuse shipping or + broad staging can commit the marker into the PR. Remote and branch are not proof — a second sweep of the same issue reproduces both, so that test also accepts a checkout a live worker is committing from, and two workers would then push from one tree. Anything else gets a @@ -554,69 +534,21 @@ Then spawn one worker subagent per issue. Give each a brief containing: steps 2-7, end to end. Implement surgically — touch only what the issue needs, and read the scoped `AGENTS.md` for the package first. - **Formatting before the commit:** `./tools/trunk fmt `. The - gate does not run it, and the required Code Quality check does. -- **The gate**, unsandboxed, backgrounded, and polled inside the turn: - - ```bash - pnpm agent:quality-gate # inspect first - ./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main # hosted - pnpm agent:quality-gate --run --lock-wait 3600 # local - ``` - - Run only the command for the current setup. Before a hosted run, fetch - `origin/main`. A hosted setup has - `agent.qualityGate.cloudPrePushRequireFresh=true` in local git config. Its - launcher, base, and parallelism must match the pre-push hook. - - Inspect before running, as the operating card's step 3 requires: the bare - form prints the mapped commands **and the checklists to apply**, and the - checklists are the half that `--run` never surfaces. - - Invoke the script directly. The `pnpm agent:quality-gate -- --run` spelling - mangles the arguments on the way through the package manager. Every worker - gate goes through the machine's gate coordinator and counts against its - capacity — 3 by default, `AGENT_QUALITY_GATE_CAPACITY`. Gates from different - worktrees run together under that capacity. Local sweeps keep the hour-long - `--lock-wait`. Hosted sweeps use the hook's exact 1,800-second default so the - push can reuse their stamp. Both budgets span scheduler admission, a command - lease, a coalesced result, and an older legacy holder. - - **A package-manifest change needs the gate's acknowledgement, not a - hand-off.** When the issue touches a package manifest, `pnpm-lock.yaml`, pnpm - configuration, or `patches/**`, that invocation exits 2 before running any - check: `Refusing to run because package manifests, patches, or lockfile -changed.` Review the lifecycle and install scripts in the diff first, then - record the acknowledgement in local git config and re-run: - - ```bash - git config agent.qualityGate.allowPackageScriptChanges true - ./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main # hosted - pnpm agent:quality-gate --run --lock-wait 3600 # local - ``` - - Run only the command for the current setup. - - The **config**, not the `--allow-package-script-changes` flag, is what lets - the push through. The pre-push hook runs the gate without that flag - (`.trunk/trunk.yaml`), and on a package-risk push the acknowledgement is part - of the freshness key — so a run acknowledged only on the command line cannot - be reused by the hook, which then refuses the push with the same message. - Local git config is read by both the manual run and the hook - ([`agent-quality-gate-mechanics.md`](../../../docs/notes/agent-quality-gate-mechanics.md)). - This is the gate's own designed path for that change class, so it is not the - blocked-control hand-off in the boundaries below: the acknowledgement records - a diff the worker has read, and setting it without reading one is the - dishonest version. Without this step a `risk:low` issue that edits a manifest - can never finish — it gates, then cannot push, and `--no-verify` is forbidden. - - **Background it with the runtime's own mechanism, then poll within the - turn.** The command above is written foreground; do not run it that way for a - full gate. Start it the way the runtime backgrounds work — in Claude Code the - Bash tool's background mode, not a trailing `&` — and poll it to completion - inside the same turn. Judge the run by its exit status, never by the tail of - its log. A worker that instead ends its turn to wait never wakes: subagents - die at turn end, and a backgrounded process they were waiting on has no one - left to notice it finished. + retained pre-commit hook formats staged files, and the required Code Quality + check enforces formatting in CI. +- **The author checks:** Apply step 3 of the + [operating card](../../../docs/notes/pr-operating-card.md). Inspect any + manifest, lockfile, pnpm configuration, or patch change before the first + package-manager command. Run the selected direct commands in the order that + step defines. Record every result as `passed`, `failed`, or `not run` with its + reason. The legacy quality gate is diagnostic and is not the normal worker + path. + + Start a long author check with the runtime's background mechanism and poll it + to completion inside the same turn. Judge the command by its exit status, + never by the tail of its log. A worker that ends its turn while a check is + still running has no one left to record the result. A failed required check + blocks the ready handoff as the operating card specifies. - **The closeout**, chosen by the runtime the worker is in. Outside an active Codex session, bare `pnpm agent:autoreview`; when the codex engine is @@ -657,11 +589,11 @@ changed.` Review the lifecycle and install scripts in the diff first, then These duties belong to the orchestrator. They are the reason this skill has an orchestrator at all. -**Re-invoke a worker that has gone quiet.** Each worker polls its own gate and -push inside its turn, so the orchestrator holds no timers and watches no pids — -it never learns their pids in the first place. What it owns is the case -in-turn polling cannot reach: a worker whose task notification shows it parked -at a turn end, or whose last report has gone stale while its siblings advance. +**Re-invoke a worker that has gone quiet.** Each worker polls its own author +checks and push inside its turn, so the orchestrator holds no timers and watches +no pids. It owns the case in-turn polling cannot reach: a worker whose task +notification shows it parked at a turn end, or whose last report has gone stale +while its siblings advance. Send that worker a message naming where it stopped and what to do next. Nothing else re-invokes a subagent that has already ended its turn. @@ -673,17 +605,13 @@ as it arrives. A worker that finished without one is not done: ask it for the missing facts before writing the report, because nothing on disk reconstructs them afterwards. -**Keep concurrent gates within the coordinator's capacity.** The coordinator -schedules gate work across worktrees under a weighted capacity, 3 by default, -so a batch of 4 runs at most three gates at once — hold the fourth worker at -its gate step until one finishes rather than letting all four queue. The -non-gate part of a worker's turn stays outside the coordinator, and that is -sound on the axis the operating card warns about: each worker owns its own tmp -clone, so no package-manager process can recreate or invalidate another's -`node_modules`. It is not free on CPU and memory, which is why the batch cap -and the coordinator's capacity both stay small. The card's read-only rule for -spare same-machine workers governs _uncoordinated_ validation; every validation -a worker runs here goes through the coordinator instead. +**Keep concurrent author checks within the local resource bound.** A batch of +four runs at most three ordinary command-heavy check sets at once. Hold the +fourth until one finishes. Run dashboard coverage or scoped related tests, browser work, +production builds, and size-limit work without another command-heavy check set. +Other workers can keep editing while that set runs. This is a sweep schedule, +not a global gate lock. Each worker owns its own clone, so no package-manager +process can recreate or invalidate another's `node_modules`. **Serialize the instructions so two workers never share a checkout.** Each worker owns exactly one clone and one branch, and no instruction ever names @@ -692,8 +620,8 @@ wrong branch, and the worker that owns it will not notice. **Resume workers after a usage-limit interruption; never restart them.** The worker's clone still holds its branch, its claim, and often an open PR. A -restart re-claims an issue that is already `agent-active`, re-runs a gate that -already passed, and can open a second PR for the same branch. Wait for the +restart re-claims an issue that is already `agent-active`, repeats completed +author checks, and can open a second PR for the same branch. Wait for the limit to reset, then wake the existing worker where it stopped. **Record each worker's allocated path, and pass it back as `worker_dir` on any @@ -739,13 +667,10 @@ The full procedure is git rev-parse "$oid:" # one blob or tree id; non-zero when absent ``` - Fetch the validated push URL, not the remote name. Preflight grades - `git remote get-url --push origin`, and a remote carrying a `pushurl` - fetches from a different URL than it pushes to, so `git fetch origin main` - would resolve every path in this pass against a URL no check ever read. - Naming that URL here binds the read to the repository Preflight approved and - leaves Preflight one check on one URL, which is the check the fork stop - needs. + Fetch the validated push URL, not the remote name. Preflight verifies both + effective `origin` URLs. A remote carrying a `pushurl` fetches from a + different URL than it pushes to, so naming the validated push URL here binds + this later tree read to the canonical repository the sweep publishes to. Pin `FETCH_HEAD`, not `origin/main`: a fetch by URL updates no remote-tracking ref at all, and a clone made with `--single-branch` on @@ -896,12 +821,12 @@ crossed without anyone watching. - **MUST NOT weaken or widen a control that blocks the run.** Root [`AGENTS.md`](../../../AGENTS.md) states it: never weaken a control that blocks your own work, because an agent that can widen its own gate has no - gate. A gate refusal, a failing hook, a denied permission, or a sandbox block - is reported and handed to an independent session — never edited away by the - worker it is blocking. Reclassifying the blocking change as a separate task - does not qualify. -- **MUST NOT bypass hooks.** No `--no-verify`, no hook-skipping environment - variable, no direct push that dodges the pre-push gate. + gate. A required author-check or CI failure, a failing hook, a denied + permission, or a sandbox block is reported and handed to an independent + session — never edited away by the worker it is blocking. Reclassifying the + blocking change as a separate task does not qualify. +- **MUST NOT bypass retained hooks.** No `--no-verify` or hook-skipping + environment variable. - **MUST release a bad pick honestly.** An issue that turns out misgroomed, or a worker that stalls with no path forward, releases the issue rather than leaving it parked in `agent-active`: diff --git a/.agents/skills/doc-garden/SKILL.md b/.agents/skills/doc-garden/SKILL.md index 1a69d47c8..cc816101d 100644 --- a/.agents/skills/doc-garden/SKILL.md +++ b/.agents/skills/doc-garden/SKILL.md @@ -5,7 +5,7 @@ title: Documentation Garden Skill status: active owner: eng canonical: true -last_verified: 2026-07-22 +last_verified: 2026-09-02 doc_type: skill scope: repo-wide review_interval_days: 90 @@ -89,9 +89,9 @@ pnpm agent:context-check pnpm agent:context-budget --strict ``` -Run the quality gate through step 3 of the operating card. Hosted sessions use -the exact direct warm command from that step. Local sessions use -`pnpm agent:quality-gate --run`. +Apply the direct author checks from step 3 of the +[operating card](../../../docs/notes/pr-operating-card.md). Record each +applicable result in the PR validation section as that step requires. Summarize the disposition and evidence for every packet file in the PR body. Open a normal ready-for-review PR, use `Closes #` only when the entire diff --git a/.agents/skills/monorepo-import/SKILL.md b/.agents/skills/monorepo-import/SKILL.md index 9a808cfcf..10a5688f2 100644 --- a/.agents/skills/monorepo-import/SKILL.md +++ b/.agents/skills/monorepo-import/SKILL.md @@ -5,7 +5,7 @@ title: Monorepo Import Skill status: active owner: eng canonical: true -last_verified: 2026-07-23 +last_verified: 2026-09-02 doc_type: skill scope: repo-wide review_interval_days: 90 @@ -83,16 +83,17 @@ patterns and update them in the same PR. ## Phase 4: Verify In Layers -Run the narrow local checks for the imported subsystem first, then the repo's -agent gate: +Run the narrow local checks for the imported subsystem first. Then apply the +repo-wide checks for its changed surfaces: - package build/typecheck/test/lint for imported TypeScript packages - `forge test` for imported Foundry helpers/contracts - Terraform fmt/init/validate/plan for touched Terraform roots; never apply without explicit user approval - workflow syntax and path/filter review for new CI/deploy workflows -- the quality gate from operating-card step 3 before opening or updating the - PR; hosted sessions use its exact direct warm command +- the applicable direct author checks from step 3 of the + [operating card](../../../docs/notes/pr-operating-card.md) before the ready + handoff If registry/network access is unavailable, do not pretend lockfile or install work is verified. Surface the blocked command and rerun with network access when diff --git a/.agents/skills/ship/SKILL.md b/.agents/skills/ship/SKILL.md index 5518ea4b9..f60d38a08 100644 --- a/.agents/skills/ship/SKILL.md +++ b/.agents/skills/ship/SKILL.md @@ -1,11 +1,11 @@ --- name: ship -description: '[repo-skill] Ship monitoring-monorepo changes through the repo''s Codex-compatible workflow: preflight, quality gate, closeout review, commit, push, PR create/update, readiness babysitting, and required production closeout. Use when the user says "ship it", "/ship", "push this", "open a PR", "create a PR", "publish this", or "send it" in this repo.' +description: '[repo-skill] Ship monitoring-monorepo changes through the repo''s Codex-compatible workflow: preflight, direct author checks, closeout review, commit, push, PR create/update, readiness babysitting, and required production closeout. Use when the user says "ship it", "/ship", "push this", "open a PR", "create a PR", "publish this", or "send it" in this repo.' title: Ship Skill status: active owner: eng canonical: true -last_verified: 2026-08-22 +last_verified: 2026-09-02 doc_type: skill scope: repo-wide review_interval_days: 90 @@ -20,40 +20,40 @@ loads the user-global `ship` skill instead of this file ([`codex-agent-skills.md`](../../../docs/notes/codex-agent-skills.md#claude-global-store-shadowing)), so a rule written here and nowhere else would reach Codex only. -Work [`pr-operating-card.md`](../../../docs/notes/pr-operating-card.md) from -step 2 through step 9. It owns the PR description shape, the ready-for-review -default, `Closes` vs `Refs`, the babysit and ready-state contracts, merge -hygiene, and production closeout. +After bootstrap, work +[`pr-operating-card.md`](../../../docs/notes/pr-operating-card.md) steps 2-9. +Run its preflight before agent-invoked repository code. It does not attest +bootstrap; setup has a separate [trust boundary](../../../docs/notes/worktree-and-web-setup.md#bootstrap-trust-boundary). -| Decision | Authority | -| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | -| Gate mapping, autoreview engine, bundle preparation and verification | [`agent-quality-gate-mechanics.md`](../../../docs/notes/agent-quality-gate-mechanics.md) | -| Readiness and feedback projections | [`pr-ready-state.md`](../../../docs/notes/pr-ready-state.md) | -| Surface detection, gh capability gate, gh→MCP mapping | [`github-tooling-surfaces.md`](../../../docs/notes/github-tooling-surfaces.md) | -| UI browser verification and the `## Visual comparison` section | [`dashboard-verification.md`](../../../docs/notes/dashboard-verification.md) | -| Claim, deferrals, issue lifecycle | [`agent-issue-workflow.md`](../../../docs/notes/agent-issue-workflow.md) | -| Production closeout | [`../../../docs/deployment.md`](../../../docs/deployment.md) and the owning package runbook | +| Decision | Authority | +| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| Author-check triggers and result records | [`pr-operating-card.md`](../../../docs/notes/pr-operating-card.md#the-loop) | +| Autoreview engine, bundle preparation and verification | [`agent-quality-gate-mechanics.md`](../../../docs/notes/agent-quality-gate-mechanics.md) | +| Readiness and feedback projections | [`pr-ready-state.md`](../../../docs/notes/pr-ready-state.md) | +| Surface detection, gh capability gate, gh→MCP mapping | [`github-tooling-surfaces.md`](../../../docs/notes/github-tooling-surfaces.md) | +| UI browser verification and the `## Visual comparison` section | [`dashboard-verification.md`](../../../docs/notes/dashboard-verification.md) | +| Claim, deferrals, issue lifecycle | [`agent-issue-workflow.md`](../../../docs/notes/agent-issue-workflow.md) | +| Production closeout | [`../../../docs/deployment.md`](../../../docs/deployment.md) and the owning package runbook | ## What this repo adds -- **Gate before publish**: Follow card step 3 and validate against the resolved - PR base. A local setup runs `pnpm agent:quality-gate --run` against that base. - In a hosted setup, run the resolved-base gate first when the resolved base - tracking ref is not `origin/main`. This includes fork and stacked PRs. Then - fetch `origin/main` and warm the hook with - `./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main`. If the - resolved base is `origin/main`, this hook warm is also the resolved-base - gate. Then run the closeout review - for non-trivial behavioural, workflow, security, data-flow, infrastructure, - or UI changes. **Which closeout depends on the surface**, and a bare +- **Repository identity before agent-invoked code**: Resolve `CURRENT_REPO`, + `BASE_REPO`, PR, remotes, and base after bootstrap. Stop fork and + cross-repository heads before agent code. Bind PR probes to `BASE_REPO`; a + failed query does not prove that no PR exists. Use the resolved PR base, not + a fixed `origin/main`, for every diff-based author check, including stacked + PRs. +- **Author checks before ready publication**: Apply every matching row in card + step 3. Format every intended changed file before those checks. Record each + result in `## Validation`. Reapply affected rows after a material fix, base + integration, or formatter change during commit. Pre-push runs no repository + verification. + Then run the closeout review for non-trivial behavioural, workflow, security, + data-flow, infrastructure, or UI changes. **Which closeout depends on the surface**, and a bare `pnpm agent:autoreview` is not always it: inside an active Codex session that silently selects the local deterministic engine, so the prepared-bundle fresh-context flow is required instead. Card step 4 owns the choice — follow it rather than the bare command. -- **Resolve the base repo from evidence.** A fork checkout uses its parent as - `BASE_REPO`; never substitute a fork's `origin` for its parent. Bind every - `gh pr view`, feedback-state, and ready-state call with `--repo `. - A failed GitHub query is not evidence that no PR exists. - **PRs open ready for review.** Drafts suppress the automated AI reviews this workflow depends on. - **`scripts/pr/check-pr-description.mjs` enforces `## The Problem` then @@ -63,8 +63,8 @@ hygiene, and production closeout. - **Never post routine or duplicate `@codex review` requests**, and never tag `chatgpt-codex-connector` directly. - **Deep security scan** (`claude-security`) is developer-installed and Claude - Code only. This repo does not declare it. Where unavailable, aim the gate and - closeout review at the sensitive surfaces and record + Code only. This repo does not declare it. Where unavailable, aim the direct + author checks and closeout review at the sensitive surfaces and record `Claude Security scan: skipped ()` in the final summary. - **Done is not merge when Done means includes live behaviour.** Card step 9 owns the closeout. diff --git a/.claude/commands/autoreview.md b/.claude/commands/autoreview.md index e40c314ec..18e8e5a41 100644 --- a/.claude/commands/autoreview.md +++ b/.claude/commands/autoreview.md @@ -24,7 +24,8 @@ checks and autoreview for that batch. Do not pause solely for cycle count before five review-triggered patch cycles are complete; pause for scope reclassification before starting a sixth. A clean source review is not test, browser, generated-artifact, CLI/API, or runtime proof, so retain every -applicable gate. +applicable author check from step 3 of the +[operating card](../../docs/notes/pr-operating-card.md). If an autoreview runtime change triggers the owning adapter's self-review refusal, keep it intact and follow the trusted pre-change sequence in the owner note. diff --git a/.claude/hooks/session-start.sh b/.claude/hooks/session-start.sh index 36a1f55b7..0d9323982 100644 --- a/.claude/hooks/session-start.sh +++ b/.claude/hooks/session-start.sh @@ -28,13 +28,6 @@ fi REPO_ROOT="${CLAUDE_PROJECT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}" SETUP_SCRIPT="$REPO_ROOT/scripts/bootstrap/claude-code-web-setup.sh" -# Cached remote sessions can resume after this hook updates but before the -# heavy startup setup runs again. Apply the lightweight hosted pre-push policy -# on every remote source before the resume/compact early exit. -if git -C "$REPO_ROOT" rev-parse --git-dir >/dev/null 2>&1; then - git -C "$REPO_ROOT" config agent.qualityGate.cloudPrePushRequireFresh true -fi - # Inspect SessionStart payload on stdin (best-effort: if stdin is not present # or the payload is unparsable, default to running the bootstrap rather than # silently skipping). Only `startup` triggers the heavy install/codegen path. diff --git a/.claude/skills/backlog-sweep/SKILL.md b/.claude/skills/backlog-sweep/SKILL.md index fea412244..6cb394c3a 100644 --- a/.claude/skills/backlog-sweep/SKILL.md +++ b/.claude/skills/backlog-sweep/SKILL.md @@ -20,11 +20,11 @@ larger batch — and reads the report afterwards. Default batch size is 2. The session that runs this skill is an **orchestrator**. It ranks, picks, claims, hands each issue to a dedicated worker subagent, and grooms the queue -for the next run. It runs no gate, edits no source file, and opens no PR. Those -three prohibitions keep concurrent workers out of each other's trees, so they -bind only while separate workers exist: on a runtime with no way to spawn one, -the session works the batch sequentially and takes both roles itself, one issue -at a time. +for the next run. It runs no author check, edits no source file, and opens no +PR. Those three prohibitions keep concurrent workers out of each other's trees, +so they bind only while separate workers exist: on a runtime with no way to +spawn one, the session works the batch sequentially and takes both roles +itself, one issue at a time. **It merges nothing, in either shape.** That boundary is unconditional — it has nothing to do with tree isolation or with how many actors are running, and the @@ -46,14 +46,13 @@ worker works ## Preflight -Every check here fails cheaply. Skipping one fails late, after issues are -already claimed and a worker is mid-gate. +Every check here fails cheaply. Skipping one fails late, after issues are already claimed and a worker is mid-validation. ```bash -git fetch origin main -git status --porcelain # must print nothing -gh auth status # must report an authenticated account -git remote get-url --push origin # must serve mento-protocol/monitoring-monorepo +gh auth status # must report an authenticated account +git remote -v # origin fetch and push must serve mento-protocol/monitoring-monorepo +git status --porcelain # must print nothing +git fetch origin main # only after both origin URLs pass ``` **A fork checkout is a stop, before anything is claimed.** The operating card @@ -62,29 +61,21 @@ first-publish, because a cross-repository PR is one that workflow can never drive to ready ([`pr-operating-card.md`](../../../docs/notes/pr-operating-card.md)). Workers inherit this checkout's remote, so a sweep started from a fork would claim -upstream issues, implement and gate all of them, and only then discover that -none of them can open a PR. Check the push URL here, where it costs one +upstream issues, implement and validate all of them, and only then discover that +none of them can open a PR. Check both effective URLs here, where they cost one command. A dirty session worktree is a stop, not a warning. The orchestrator does not commit, so nothing it does would clear those changes, and a sweep that runs beside unfinished work makes the two indistinguishable in the report. -**Do not probe the gate's lock, and never stop on it.** Gate `--run` requests -share a transient machine-wide coordinator that admits independent work from -different worktrees under a weighted capacity, so a new gate **joins** a -compatible coordinator rather than queueing behind it -([`agent-quality-gate-mechanics.md`](../../../docs/notes/agent-quality-gate-mechanics.md)). -The coordinator adopts the legacy `run.lock` while scheduled or recovery work -exists, which makes `run.lock/owner` name a live pid for as long as anyone on -the machine is gating — hours, routinely, during ordinary parallel work. A -sweep that read that record as a busy signal would refuse to start in the -normal case. Local workers wait with `--lock-wait 3600`. Hosted workers use the -hook's exact 1,800-second default. Both cover scheduler admission, a command -lease, a coalesced result, and an older legacy holder. Never pass `--no-lock` -and never delete the lock directory: the gate owns its own reclaim rules, and a -record that looks stale from outside is routinely a live holder inside a long -browser suite. +**Do not probe or change the legacy gate's lock.** Workers run the direct author +checks from operating-card step 3 in isolated checkouts. The batch cap remains +the CPU and memory bound. Run no more than three ordinary command-heavy check +sets at once. Run dashboard coverage or scoped related tests, browser work, +production builds, and size-limit work alone. Other workers can keep editing. +A browser check that finds its fixed port in use must fail and report the +conflict. It must not wait for, stop, or reuse another process. **State the usage reality before starting.** One shipped PR costs roughly 3% of the weekly usage window, and every push to it triggers another Codex review, @@ -190,9 +181,9 @@ Take the top N — default 2 — that satisfy **all** of: That label is the repo's own ownership area, so it settles "same subsystem" by lookup rather than per-batch judgement. Two workers editing one package produce PRs whose diffs conflict and whose reviewers see a base moving under - them, and the second PR then pays for a merge, a re-gate, and a fresh review - round it did not need. `pkg:tooling` gets a path test instead of the label - test, below. + them, and the second PR then pays for a merge, repeated author checks, and a + fresh review round it did not need. `pkg:tooling` gets a path test instead of + the label test, below. - **Outside its own grooming veto window.** A candidate whose newest _trusted_ `sweep-groomed:` marker comment is less than 12 hours old waits for the next run, whatever version that marker carries — the window asks whether a @@ -451,10 +442,10 @@ Then spawn one worker subagent per issue. Give each a brief containing: **`$dir` is the working directory for every later command, not just the clone.** `git clone` does not move the shell, and a worker can inherit the - orchestrator's directory, so setup, the branch, the edits, the gate, and the - push would all run in the orchestrator's checkout — the one tree this whole - scheme exists to keep workers out of, and the one the preflight requires to - stay clean. A shell that does not persist between calls does not make this + orchestrator's directory, so setup, the branch, the edits, the author checks, + and the push would all run in the orchestrator's checkout — the one tree this + whole scheme exists to keep workers out of, and the one the preflight requires + to stay clean. A shell that does not persist between calls does not make this optional: every fresh shell re-enters `$dir` first, and no worker command is ever issued from an unstated directory. @@ -462,7 +453,7 @@ Then spawn one worker subagent per issue. Give each a brief containing: fixed once and passed to every worker beside `sweep_id`. Take the **push** URL specifically: `git clone` copies no remote config, `pushurl` included, so where a checkout's fetch and push URLs differ a worker cloned from the fetch - URL gates cleanly and then pushes somewhere nobody is watching. `--push` + URL passes its checks and then pushes somewhere nobody is watching. `--push` returns `pushurl` when one is set and the fetch URL otherwise, so it is right either way. Do not hard-code the public HTTPS URL. A worker must push, not merely clone, and the transport that @@ -470,7 +461,7 @@ Then spawn one worker subagent per issue. Give each a brief containing: using — often SSH, while `gh auth status` says nothing about git's credential helper. Cloning over a transport nobody has credentials for succeeds on a public repository and then fails at the push, after the whole issue has been - implemented and gated. + implemented and validated. `worker_dir` is set only on a respawn, to the path the orchestrator recorded for this worker. Use it verbatim; do not re-derive. A worker displaced to a @@ -504,29 +495,18 @@ Then spawn one worker subagent per issue. Give each a brief containing: name, and `mkdir` is the atomic claim that makes the loser take the next suffix instead. - In Claude Code, subagents inherit the parent session's Bash worktree pin, so - git in a sibling worktree under `.claude/worktrees/` is refused for them, and - a tmp clone is the only checkout those workers can use. The general rule - outlives that specific block: every worker gets an isolated checkout — a - clone or a worktree — that its own runtime can actually write to, because two - workers in one checkout is the failure this is preventing. Then run - `./scripts/setup.sh` unsandboxed in **every** new clone, not conditionally. - It is what sets `core.hooksPath` to `.trunk/hooks`, so a checkout that only - ran `pnpm install` has no pre-push hook — and a worker there could push - without the gate the boundaries below forbid bypassing. Run it on **resumed** - checkouts too, not just fresh ones: the marker is written straight after the - clone, so an interruption between the two leaves an owned checkout with no - hooks, and a resume that trusted the marker would push from it. Rerunning is - free — the script owns codegen and the browser dependencies and skips its own - work when the inputs are unchanged — which is why this is a blanket rule - rather than a condition to evaluate. - - Before spawning workers, read the orchestrator checkout's - `agent.qualityGate.cloudPrePushRequireFresh` value and pass one hosted/local - boolean to every worker. After `./scripts/setup.sh` in each fresh or resumed - clone, set `agent.qualityGate.cloudPrePushRequireFresh=true` when that boolean - is hosted. Unset the key when it is local. A clone does not inherit local git - config, so never infer its setup type from the clone before this propagation. + Claude subagents cannot use sibling worktrees, so each uses an isolated tmp + clone. Before resumed setup, use the operating-card preflight to resolve and + fetch the pull request base, or verified `origin/main` without a pull request. + Set `BASE_REMOTE` and `baseRefName` for that base. Inspect `git status --short`, + `git diff "$BASE_REMOTE/$baseRefName"...HEAD`, `git diff --cached`, `git diff`, + and untracked files. Inspect lifecycle and install effects for changed manifests, + lockfiles, pnpm configuration, or patches; stop if the change set is unclear. + + Run `./scripts/setup.sh` in every resumed clone only after that inspection. In + a fresh clone, fetch and run `git switch --detach origin/main` before setup. + Setup prepares the staged formatter, dependencies, codegen, and browser tools; + its markers make unchanged reruns cheap. Branch as **the exact name the orchestrator passed to `issue:claim --branch`**, from `origin/main`. That name is already in the Project `Branch` @@ -541,8 +521,8 @@ Then spawn one worker subagent per issue. Give each a brief containing: issue that was released and later re-selected. Resume it only on proof it is this sweep's own, which is what the `sweep-owner` comparison above decides. Keep the marker inside `.git/` — a file at the clone root would be untracked - in every worker checkout, where a clean-worktree check can refuse the gate or - the push and broad staging can commit the marker into the PR. Remote and + in every worker checkout, where a clean-worktree check can refuse shipping or + broad staging can commit the marker into the PR. Remote and branch are not proof — a second sweep of the same issue reproduces both, so that test also accepts a checkout a live worker is committing from, and two workers would then push from one tree. Anything else gets a @@ -554,69 +534,21 @@ Then spawn one worker subagent per issue. Give each a brief containing: steps 2-7, end to end. Implement surgically — touch only what the issue needs, and read the scoped `AGENTS.md` for the package first. - **Formatting before the commit:** `./tools/trunk fmt `. The - gate does not run it, and the required Code Quality check does. -- **The gate**, unsandboxed, backgrounded, and polled inside the turn: - - ```bash - pnpm agent:quality-gate # inspect first - ./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main # hosted - pnpm agent:quality-gate --run --lock-wait 3600 # local - ``` - - Run only the command for the current setup. Before a hosted run, fetch - `origin/main`. A hosted setup has - `agent.qualityGate.cloudPrePushRequireFresh=true` in local git config. Its - launcher, base, and parallelism must match the pre-push hook. - - Inspect before running, as the operating card's step 3 requires: the bare - form prints the mapped commands **and the checklists to apply**, and the - checklists are the half that `--run` never surfaces. - - Invoke the script directly. The `pnpm agent:quality-gate -- --run` spelling - mangles the arguments on the way through the package manager. Every worker - gate goes through the machine's gate coordinator and counts against its - capacity — 3 by default, `AGENT_QUALITY_GATE_CAPACITY`. Gates from different - worktrees run together under that capacity. Local sweeps keep the hour-long - `--lock-wait`. Hosted sweeps use the hook's exact 1,800-second default so the - push can reuse their stamp. Both budgets span scheduler admission, a command - lease, a coalesced result, and an older legacy holder. - - **A package-manifest change needs the gate's acknowledgement, not a - hand-off.** When the issue touches a package manifest, `pnpm-lock.yaml`, pnpm - configuration, or `patches/**`, that invocation exits 2 before running any - check: `Refusing to run because package manifests, patches, or lockfile -changed.` Review the lifecycle and install scripts in the diff first, then - record the acknowledgement in local git config and re-run: - - ```bash - git config agent.qualityGate.allowPackageScriptChanges true - ./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main # hosted - pnpm agent:quality-gate --run --lock-wait 3600 # local - ``` - - Run only the command for the current setup. - - The **config**, not the `--allow-package-script-changes` flag, is what lets - the push through. The pre-push hook runs the gate without that flag - (`.trunk/trunk.yaml`), and on a package-risk push the acknowledgement is part - of the freshness key — so a run acknowledged only on the command line cannot - be reused by the hook, which then refuses the push with the same message. - Local git config is read by both the manual run and the hook - ([`agent-quality-gate-mechanics.md`](../../../docs/notes/agent-quality-gate-mechanics.md)). - This is the gate's own designed path for that change class, so it is not the - blocked-control hand-off in the boundaries below: the acknowledgement records - a diff the worker has read, and setting it without reading one is the - dishonest version. Without this step a `risk:low` issue that edits a manifest - can never finish — it gates, then cannot push, and `--no-verify` is forbidden. - - **Background it with the runtime's own mechanism, then poll within the - turn.** The command above is written foreground; do not run it that way for a - full gate. Start it the way the runtime backgrounds work — in Claude Code the - Bash tool's background mode, not a trailing `&` — and poll it to completion - inside the same turn. Judge the run by its exit status, never by the tail of - its log. A worker that instead ends its turn to wait never wakes: subagents - die at turn end, and a backgrounded process they were waiting on has no one - left to notice it finished. + retained pre-commit hook formats staged files, and the required Code Quality + check enforces formatting in CI. +- **The author checks:** Apply step 3 of the + [operating card](../../../docs/notes/pr-operating-card.md). Inspect any + manifest, lockfile, pnpm configuration, or patch change before the first + package-manager command. Run the selected direct commands in the order that + step defines. Record every result as `passed`, `failed`, or `not run` with its + reason. The legacy quality gate is diagnostic and is not the normal worker + path. + + Start a long author check with the runtime's background mechanism and poll it + to completion inside the same turn. Judge the command by its exit status, + never by the tail of its log. A worker that ends its turn while a check is + still running has no one left to record the result. A failed required check + blocks the ready handoff as the operating card specifies. - **The closeout**, chosen by the runtime the worker is in. Outside an active Codex session, bare `pnpm agent:autoreview`; when the codex engine is @@ -657,11 +589,11 @@ changed.` Review the lifecycle and install scripts in the diff first, then These duties belong to the orchestrator. They are the reason this skill has an orchestrator at all. -**Re-invoke a worker that has gone quiet.** Each worker polls its own gate and -push inside its turn, so the orchestrator holds no timers and watches no pids — -it never learns their pids in the first place. What it owns is the case -in-turn polling cannot reach: a worker whose task notification shows it parked -at a turn end, or whose last report has gone stale while its siblings advance. +**Re-invoke a worker that has gone quiet.** Each worker polls its own author +checks and push inside its turn, so the orchestrator holds no timers and watches +no pids. It owns the case in-turn polling cannot reach: a worker whose task +notification shows it parked at a turn end, or whose last report has gone stale +while its siblings advance. Send that worker a message naming where it stopped and what to do next. Nothing else re-invokes a subagent that has already ended its turn. @@ -673,17 +605,13 @@ as it arrives. A worker that finished without one is not done: ask it for the missing facts before writing the report, because nothing on disk reconstructs them afterwards. -**Keep concurrent gates within the coordinator's capacity.** The coordinator -schedules gate work across worktrees under a weighted capacity, 3 by default, -so a batch of 4 runs at most three gates at once — hold the fourth worker at -its gate step until one finishes rather than letting all four queue. The -non-gate part of a worker's turn stays outside the coordinator, and that is -sound on the axis the operating card warns about: each worker owns its own tmp -clone, so no package-manager process can recreate or invalidate another's -`node_modules`. It is not free on CPU and memory, which is why the batch cap -and the coordinator's capacity both stay small. The card's read-only rule for -spare same-machine workers governs _uncoordinated_ validation; every validation -a worker runs here goes through the coordinator instead. +**Keep concurrent author checks within the local resource bound.** A batch of +four runs at most three ordinary command-heavy check sets at once. Hold the +fourth until one finishes. Run dashboard coverage or scoped related tests, browser work, +production builds, and size-limit work without another command-heavy check set. +Other workers can keep editing while that set runs. This is a sweep schedule, +not a global gate lock. Each worker owns its own clone, so no package-manager +process can recreate or invalidate another's `node_modules`. **Serialize the instructions so two workers never share a checkout.** Each worker owns exactly one clone and one branch, and no instruction ever names @@ -692,8 +620,8 @@ wrong branch, and the worker that owns it will not notice. **Resume workers after a usage-limit interruption; never restart them.** The worker's clone still holds its branch, its claim, and often an open PR. A -restart re-claims an issue that is already `agent-active`, re-runs a gate that -already passed, and can open a second PR for the same branch. Wait for the +restart re-claims an issue that is already `agent-active`, repeats completed +author checks, and can open a second PR for the same branch. Wait for the limit to reset, then wake the existing worker where it stopped. **Record each worker's allocated path, and pass it back as `worker_dir` on any @@ -739,13 +667,10 @@ The full procedure is git rev-parse "$oid:" # one blob or tree id; non-zero when absent ``` - Fetch the validated push URL, not the remote name. Preflight grades - `git remote get-url --push origin`, and a remote carrying a `pushurl` - fetches from a different URL than it pushes to, so `git fetch origin main` - would resolve every path in this pass against a URL no check ever read. - Naming that URL here binds the read to the repository Preflight approved and - leaves Preflight one check on one URL, which is the check the fork stop - needs. + Fetch the validated push URL, not the remote name. Preflight verifies both + effective `origin` URLs. A remote carrying a `pushurl` fetches from a + different URL than it pushes to, so naming the validated push URL here binds + this later tree read to the canonical repository the sweep publishes to. Pin `FETCH_HEAD`, not `origin/main`: a fetch by URL updates no remote-tracking ref at all, and a clone made with `--single-branch` on @@ -896,12 +821,12 @@ crossed without anyone watching. - **MUST NOT weaken or widen a control that blocks the run.** Root [`AGENTS.md`](../../../AGENTS.md) states it: never weaken a control that blocks your own work, because an agent that can widen its own gate has no - gate. A gate refusal, a failing hook, a denied permission, or a sandbox block - is reported and handed to an independent session — never edited away by the - worker it is blocking. Reclassifying the blocking change as a separate task - does not qualify. -- **MUST NOT bypass hooks.** No `--no-verify`, no hook-skipping environment - variable, no direct push that dodges the pre-push gate. + gate. A required author-check or CI failure, a failing hook, a denied + permission, or a sandbox block is reported and handed to an independent + session — never edited away by the worker it is blocking. Reclassifying the + blocking change as a separate task does not qualify. +- **MUST NOT bypass retained hooks.** No `--no-verify` or hook-skipping + environment variable. - **MUST release a bad pick honestly.** An issue that turns out misgroomed, or a worker that stalls with no path forward, releases the issue rather than leaving it parked in `agent-active`: diff --git a/.claude/skills/doc-garden/SKILL.md b/.claude/skills/doc-garden/SKILL.md index 1a69d47c8..cc816101d 100644 --- a/.claude/skills/doc-garden/SKILL.md +++ b/.claude/skills/doc-garden/SKILL.md @@ -5,7 +5,7 @@ title: Documentation Garden Skill status: active owner: eng canonical: true -last_verified: 2026-07-22 +last_verified: 2026-09-02 doc_type: skill scope: repo-wide review_interval_days: 90 @@ -89,9 +89,9 @@ pnpm agent:context-check pnpm agent:context-budget --strict ``` -Run the quality gate through step 3 of the operating card. Hosted sessions use -the exact direct warm command from that step. Local sessions use -`pnpm agent:quality-gate --run`. +Apply the direct author checks from step 3 of the +[operating card](../../../docs/notes/pr-operating-card.md). Record each +applicable result in the PR validation section as that step requires. Summarize the disposition and evidence for every packet file in the PR body. Open a normal ready-for-review PR, use `Closes #` only when the entire diff --git a/.claude/skills/monorepo-import/SKILL.md b/.claude/skills/monorepo-import/SKILL.md index 9a808cfcf..10a5688f2 100644 --- a/.claude/skills/monorepo-import/SKILL.md +++ b/.claude/skills/monorepo-import/SKILL.md @@ -5,7 +5,7 @@ title: Monorepo Import Skill status: active owner: eng canonical: true -last_verified: 2026-07-23 +last_verified: 2026-09-02 doc_type: skill scope: repo-wide review_interval_days: 90 @@ -83,16 +83,17 @@ patterns and update them in the same PR. ## Phase 4: Verify In Layers -Run the narrow local checks for the imported subsystem first, then the repo's -agent gate: +Run the narrow local checks for the imported subsystem first. Then apply the +repo-wide checks for its changed surfaces: - package build/typecheck/test/lint for imported TypeScript packages - `forge test` for imported Foundry helpers/contracts - Terraform fmt/init/validate/plan for touched Terraform roots; never apply without explicit user approval - workflow syntax and path/filter review for new CI/deploy workflows -- the quality gate from operating-card step 3 before opening or updating the - PR; hosted sessions use its exact direct warm command +- the applicable direct author checks from step 3 of the + [operating card](../../../docs/notes/pr-operating-card.md) before the ready + handoff If registry/network access is unavailable, do not pretend lockfile or install work is verified. Surface the blocked command and rerun with network access when diff --git a/.claude/skills/ship/SKILL.md b/.claude/skills/ship/SKILL.md index 5518ea4b9..f60d38a08 100644 --- a/.claude/skills/ship/SKILL.md +++ b/.claude/skills/ship/SKILL.md @@ -1,11 +1,11 @@ --- name: ship -description: '[repo-skill] Ship monitoring-monorepo changes through the repo''s Codex-compatible workflow: preflight, quality gate, closeout review, commit, push, PR create/update, readiness babysitting, and required production closeout. Use when the user says "ship it", "/ship", "push this", "open a PR", "create a PR", "publish this", or "send it" in this repo.' +description: '[repo-skill] Ship monitoring-monorepo changes through the repo''s Codex-compatible workflow: preflight, direct author checks, closeout review, commit, push, PR create/update, readiness babysitting, and required production closeout. Use when the user says "ship it", "/ship", "push this", "open a PR", "create a PR", "publish this", or "send it" in this repo.' title: Ship Skill status: active owner: eng canonical: true -last_verified: 2026-08-22 +last_verified: 2026-09-02 doc_type: skill scope: repo-wide review_interval_days: 90 @@ -20,40 +20,40 @@ loads the user-global `ship` skill instead of this file ([`codex-agent-skills.md`](../../../docs/notes/codex-agent-skills.md#claude-global-store-shadowing)), so a rule written here and nowhere else would reach Codex only. -Work [`pr-operating-card.md`](../../../docs/notes/pr-operating-card.md) from -step 2 through step 9. It owns the PR description shape, the ready-for-review -default, `Closes` vs `Refs`, the babysit and ready-state contracts, merge -hygiene, and production closeout. +After bootstrap, work +[`pr-operating-card.md`](../../../docs/notes/pr-operating-card.md) steps 2-9. +Run its preflight before agent-invoked repository code. It does not attest +bootstrap; setup has a separate [trust boundary](../../../docs/notes/worktree-and-web-setup.md#bootstrap-trust-boundary). -| Decision | Authority | -| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | -| Gate mapping, autoreview engine, bundle preparation and verification | [`agent-quality-gate-mechanics.md`](../../../docs/notes/agent-quality-gate-mechanics.md) | -| Readiness and feedback projections | [`pr-ready-state.md`](../../../docs/notes/pr-ready-state.md) | -| Surface detection, gh capability gate, gh→MCP mapping | [`github-tooling-surfaces.md`](../../../docs/notes/github-tooling-surfaces.md) | -| UI browser verification and the `## Visual comparison` section | [`dashboard-verification.md`](../../../docs/notes/dashboard-verification.md) | -| Claim, deferrals, issue lifecycle | [`agent-issue-workflow.md`](../../../docs/notes/agent-issue-workflow.md) | -| Production closeout | [`../../../docs/deployment.md`](../../../docs/deployment.md) and the owning package runbook | +| Decision | Authority | +| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| Author-check triggers and result records | [`pr-operating-card.md`](../../../docs/notes/pr-operating-card.md#the-loop) | +| Autoreview engine, bundle preparation and verification | [`agent-quality-gate-mechanics.md`](../../../docs/notes/agent-quality-gate-mechanics.md) | +| Readiness and feedback projections | [`pr-ready-state.md`](../../../docs/notes/pr-ready-state.md) | +| Surface detection, gh capability gate, gh→MCP mapping | [`github-tooling-surfaces.md`](../../../docs/notes/github-tooling-surfaces.md) | +| UI browser verification and the `## Visual comparison` section | [`dashboard-verification.md`](../../../docs/notes/dashboard-verification.md) | +| Claim, deferrals, issue lifecycle | [`agent-issue-workflow.md`](../../../docs/notes/agent-issue-workflow.md) | +| Production closeout | [`../../../docs/deployment.md`](../../../docs/deployment.md) and the owning package runbook | ## What this repo adds -- **Gate before publish**: Follow card step 3 and validate against the resolved - PR base. A local setup runs `pnpm agent:quality-gate --run` against that base. - In a hosted setup, run the resolved-base gate first when the resolved base - tracking ref is not `origin/main`. This includes fork and stacked PRs. Then - fetch `origin/main` and warm the hook with - `./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main`. If the - resolved base is `origin/main`, this hook warm is also the resolved-base - gate. Then run the closeout review - for non-trivial behavioural, workflow, security, data-flow, infrastructure, - or UI changes. **Which closeout depends on the surface**, and a bare +- **Repository identity before agent-invoked code**: Resolve `CURRENT_REPO`, + `BASE_REPO`, PR, remotes, and base after bootstrap. Stop fork and + cross-repository heads before agent code. Bind PR probes to `BASE_REPO`; a + failed query does not prove that no PR exists. Use the resolved PR base, not + a fixed `origin/main`, for every diff-based author check, including stacked + PRs. +- **Author checks before ready publication**: Apply every matching row in card + step 3. Format every intended changed file before those checks. Record each + result in `## Validation`. Reapply affected rows after a material fix, base + integration, or formatter change during commit. Pre-push runs no repository + verification. + Then run the closeout review for non-trivial behavioural, workflow, security, + data-flow, infrastructure, or UI changes. **Which closeout depends on the surface**, and a bare `pnpm agent:autoreview` is not always it: inside an active Codex session that silently selects the local deterministic engine, so the prepared-bundle fresh-context flow is required instead. Card step 4 owns the choice — follow it rather than the bare command. -- **Resolve the base repo from evidence.** A fork checkout uses its parent as - `BASE_REPO`; never substitute a fork's `origin` for its parent. Bind every - `gh pr view`, feedback-state, and ready-state call with `--repo `. - A failed GitHub query is not evidence that no PR exists. - **PRs open ready for review.** Drafts suppress the automated AI reviews this workflow depends on. - **`scripts/pr/check-pr-description.mjs` enforces `## The Problem` then @@ -63,8 +63,8 @@ hygiene, and production closeout. - **Never post routine or duplicate `@codex review` requests**, and never tag `chatgpt-codex-connector` directly. - **Deep security scan** (`claude-security`) is developer-installed and Claude - Code only. This repo does not declare it. Where unavailable, aim the gate and - closeout review at the sensitive surfaces and record + Code only. This repo does not declare it. Where unavailable, aim the direct + author checks and closeout review at the sensitive surfaces and record `Claude Security scan: skipped ()` in the final summary. - **Done is not merge when Done means includes live behaviour.** Card step 9 owns the closeout. diff --git a/.github/ISSUE_TEMPLATE/agent-task.yml b/.github/ISSUE_TEMPLATE/agent-task.yml index 0b4469d07..6e6de2b15 100644 --- a/.github/ISSUE_TEMPLATE/agent-task.yml +++ b/.github/ISSUE_TEMPLATE/agent-task.yml @@ -48,9 +48,7 @@ body: label: Verification commands description: Commands or checks the agent should run before opening/updating a PR. placeholder: | - # Follow docs/notes/pr-operating-card.md step 3. - pnpm agent:quality-gate --run # local - ./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main # hosted hook warm + # Apply the direct author checks in docs/notes/pr-operating-card.md step 3. pnpm --filter @mento-protocol/... test validations: required: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 482f46ebc..2bdb2ac5f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -763,8 +763,9 @@ jobs: # separate from the legacy routing parity suite below. run: node --test scripts/agent-autoreview-indexer-invariant-contract.test.mjs - name: Legacy indexer routing parity suite - # This remaining suite checks only the legacy local gate's table and - # checklist router. The no-skip audit measures retained commands. + # This remaining suite checks only the optional legacy diagnostic's + # table and checklist router. The no-skip audit measures retained + # commands. if: ${{ !inputs.no_skip_audit }} run: node --test scripts/gate/routing-table/indexer-invariant-parity.test.mjs - name: Test with coverage @@ -1220,8 +1221,8 @@ jobs: # suites); the pin validator keeps that trust safe by rejecting a # drifted command (e.g. an appended `&& `) before it executes. # check-sentry-suites-in-ci.test.mjs pins this ordering, because the - # `sentry:*` aliases the local quality gate trusts are pinned by the - # same validator. + # `sentry:*` aliases the optional legacy diagnostic trusts are pinned + # by the same validator. run: node scripts/check-agent-quality-gate-package-scripts.mjs # GitHub resolves $/ from the running commit; actionlint lacks support. # trunk-ignore(actionlint/action) @@ -1252,8 +1253,7 @@ jobs: # extracted from the legacy Bash gate suite. run: bash scripts/bootstrap/agent-setup-contract.test.sh - name: Agent quality-gate routing regression suite - # Keep the mandatory legacy gate safe during the shadow period. The - # no-skip audit measures only commands retained after gate retirement. + # Optional legacy diagnostic regression; no-skip measures required CI. if: ${{ !inputs.no_skip_audit }} run: pnpm agent:quality-gate:test - name: Gate routing-table suite @@ -1263,9 +1263,8 @@ jobs: # pairing lint, the path staleness check, the /bin/bash oracle for the # pattern compiler, the closed verb set against the engine, and the # `implementation_signature()` pin that keeps the freshness stamp honest. - # It belongs in the required `ci` sentinel path for the same reason the - # routing regression suite above does: the local pre-push gate is the - # thing a contributor can bypass, and a broken table fails nowhere else. + # Required CI is authoritative and must reject a broken diagnostic + # table even when no author invokes the optional local diagnostic. # It is not part of the retained no-skip target command set. if: ${{ !inputs.no_skip_audit }} run: pnpm gate:routing-table:test @@ -1275,8 +1274,8 @@ jobs: # findings now feed the pr:feedback-state ledger. The pin asserts the # committed config exactly equals the canonical object in the suite, so # weakening it fails required CI until the pin is edited in the same PR. - # This runs in CI, not only in the local pre-push gate, because the - # local gate is the thing a config-weakening PR would skip. + # Required CI is authoritative because any local author procedure can + # be skipped. run: pnpm coderabbit:config:test - name: Terraform source-format target regression suite # Proves ignored operator tfvars stay outside the explicit format target @@ -1427,8 +1426,9 @@ jobs: # credential-shaped fixtures still scan clean as whole text under # scripts/agent-autoreview-core.mjs, and that none of the four paths has # vanished. It is NOT a `sentry-*.test.mjs`, so the `sentry-suites` gate - # neither enumerates nor runs it; this step and the local quality gate - # are its two routes. The `rootScripts` filter is `scripts/**`, so the + # neither enumerates nor runs it; required CI is its authoritative + # route, and the optional legacy diagnostic is a second route. The + # `rootScripts` filter is `scripts/**`, so the # scanner, the four suites and the canary itself all admit this job — # the same recursive entry every other scripts/ suite here relies on, # rather than a new enumerated list to keep in sync. @@ -1694,8 +1694,8 @@ jobs: # The gate above proves the suites ran; it cannot prove its own job still # exists, is unconditional, and still reaches the required `ci` context — # so this pins that, re-proves the one suite the gate does not run - # (sentry-provider-contract, via `pnpm tf:test`), and holds the local - # gate's `sentry:*` allowlist to its pins. It ran in the path-gated + # (sentry-provider-contract, via `pnpm tf:test`), and holds the optional + # diagnostic's `sentry:*` allowlist to its pins. It ran in the path-gated # `scripts` job until this PR, where a dashboard-only, indexer-only or # non-Markdown doc-asset diff skipped it entirely. run: node scripts/sentry/ci-wiring/check-sentry-suites-in-ci.test.mjs diff --git a/.trunk/hooks/pre-push b/.trunk/hooks/pre-push deleted file mode 100755 index cd3c7f6f0..000000000 --- a/.trunk/hooks/pre-push +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash -# Shim: delegates to trunk's git-hook callback from the correct repo root. -# Lives in .trunk/hooks/ so core.hooksPath can point here and work from any -# machine (server, Mac, CI) regardless of where trunk's cache dir is. -set -euo pipefail - -REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -TRUNK="${REPO_ROOT}/tools/trunk" - -if [[ ! -x "${TRUNK}" ]]; then - echo "trunk not found at ${TRUNK} — skipping pre-push hooks" >&2 - exit 0 -fi - -# The trunk launcher self-downloads the pinned CLI from trunk.io on first use. -# In a restricted-network sandbox (e.g. Claude Code on the web, where trunk.io -# is not in the default egress allowlist) that download 403s and the launcher -# exits non-zero, which would otherwise block every push. Probe provisioning -# first and, when trunk cannot be obtained, skip with a warning — same posture -# as the "trunk not found" branch above. The hook is fast-feedback convenience; -# CI still enforces trunk on the PR. Allowlist trunk.io (+ *.trunk.io) to enable -# it; set TRUNK_HOOK_REQUIRE=1 to hard-fail instead of skipping. -if ! TRUNK_LAUNCHER_QUIET=true "${TRUNK}" --version >/dev/null 2>&1; then - if [[ "${TRUNK_HOOK_REQUIRE:-0}" == "1" ]]; then - echo "trunk could not be provisioned and TRUNK_HOOK_REQUIRE=1 — failing pre-push." >&2 - exit 1 - fi - echo "warning: trunk CLI could not be provisioned (download blocked? allowlist trunk.io) — skipping pre-push hooks." >&2 - exit 0 -fi - -# Feed stdin to trunk (branch/sha pairs from git) -TRUNK_LAUNCHER_QUIET=true "${TRUNK}" git-hooks callback pre-push -- "$@" diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 0f0998f40..ed714ac1b 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -139,18 +139,6 @@ lint: actions: disabled: - trunk-announce - - trunk-check-pre-push # Use custom pre-push below - definitions: - - id: agent-quality-gate-pre-push - display_name: Agent Quality Gate Pre-Push - description: > - Runs the path-aware agent quality gate before push. The gate maps the - branch diff to the required local checks instead of always running the - full monorepo pre-push suite. - run: git fetch --quiet origin main && ./scripts/agent-quality-gate.sh --run --parallel 3 --skip-if-fresh --pre-push --base origin/main - triggers: - - git_hooks: [pre-push] enabled: - trunk-fmt-pre-commit - - agent-quality-gate-pre-push - trunk-upgrade-available diff --git a/AGENTS.md b/AGENTS.md index d5d920bc9..7c423c2ba 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,7 +3,7 @@ title: Monitoring Monorepo Instructions status: active owner: eng canonical: true -last_verified: 2026-08-13 +last_verified: 2026-09-02 doc_type: agent-instructions scope: repo-wide review_interval_days: 90 @@ -17,7 +17,7 @@ live in [`SPEC.md`](SPEC.md). ## Operating Rule (read this before opening PRs) -The full claim → implement → gate → autoreview → ship → babysit → ready-state → +The full claim → implement → author checks → autoreview → ship → babysit → ready-state → merge loop, plus production closeout when required, is one card: [`docs/notes/pr-operating-card.md`](docs/notes/pr-operating-card.md). Read it first; open the authority docs it names only when a step needs their depth. @@ -153,7 +153,7 @@ Codex routing and skill ownership are in [`docs/notes/codex-agent-skills.md`](docs/notes/codex-agent-skills.md); Claude commands live under `.claude/commands/`. -Run `./scripts/setup.sh` in a new clone or worktree. Hosted setup and Worktrunk -hooks are in +Run `./scripts/setup.sh` only from a trusted canonical branch. Hosted setup, +Worktrunk hooks, and the trust boundary are in [`docs/notes/worktree-and-web-setup.md`](docs/notes/worktree-and-web-setup.md); service prerequisites stay in package READMEs. diff --git a/README.md b/README.md index a1b2621d6..1b23f09b2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Real-time monitoring infrastructure for Mento v3 on-chain pools — a multichain [Envio HyperIndex](https://docs.envio.dev/) indexer paired with a Next.js 16 + Plotly.js dashboard. - + **Live dashboard:** [monitoring.mento.org](https://monitoring.mento.org) @@ -81,14 +81,14 @@ production-cutover matrix is - [pnpm](https://pnpm.io/) 11.x - Docker (for local indexer dev — runs Postgres + Hasura) - On macOS, the Xcode Command Line Tools. Install them with - `xcode-select --install`. The quality gate uses their selected macOS SDK and - Clang toolchain for exact Darwin process identity. + `xcode-select --install`. The optional legacy gate uses their selected macOS + SDK and Clang toolchain for exact Darwin process identity. ### Install -For a fresh clone or manually-created worktree, prefer the setup script so -workspace deps, postinstall hooks, Playwright Chromium, and Envio codegen are -handled in one place: +From a trusted canonical clone or worktree, use the setup script for workspace +dependencies, lifecycle hooks, Playwright, and Envio codegen. See the +[bootstrap trust boundary](./docs/notes/worktree-and-web-setup.md#bootstrap-trust-boundary). ```bash ./scripts/setup.sh @@ -117,8 +117,9 @@ local `~/.agents` directory, so the repo vendors its required autoreview helper. The helper trust boundary, prepared-bundle workflow, external-runtime procedure, and fail-closed checks live in [`docs/notes/agent-quality-gate-mechanics.md`](./docs/notes/agent-quality-gate-mechanics.md). -Autoreview remains source review, so the quality gate and applicable browser or -runtime verification are still required. +Autoreview remains source review. Apply the direct author checks in step 3 of +the [PR operating card](./docs/notes/pr-operating-card.md), plus applicable +browser or runtime verification. The maintenance path runs after Codex checks out the task branch in a cached container; it refreshes `origin/main`, verifies the autoreview helper, syncs @@ -204,8 +205,8 @@ pnpm --filter @mento-protocol/ui-dashboard test:browser The browser suite starts the Next.js app with a local GraphQL fixture server so it can exercise routing, focus, hydration, and degraded query states without -hitting hosted Hasura/Envio. The agent quality gate installs Playwright -Chromium before running it; for direct fresh-checkout runs, install it once with +hitting hosted Hasura/Envio. The setup script attempts to install Playwright +Chromium. If a fresh checkout still lacks it, install it once with `pnpm --filter @mento-protocol/ui-dashboard exec playwright install chromium`. ### Targeted Mutation Baseline diff --git a/alerts/AGENTS.md b/alerts/AGENTS.md index a859862ef..810280327 100644 --- a/alerts/AGENTS.md +++ b/alerts/AGENTS.md @@ -3,7 +3,7 @@ title: Alerts Instructions status: active owner: eng canonical: true -last_verified: 2026-07-23 +last_verified: 2026-09-02 doc_type: agent-instructions scope: alerts review_interval_days: 90 @@ -57,6 +57,7 @@ routing. - `pnpm --filter @mento-protocol/alerts-oncall-announcer typecheck` and `test:coverage` — green on on-call announcer changes. Lint/knip are wired too. - `pnpm alerts:watcher:test` — required on `alerts/infra/sentry-ingest-watcher/` changes. - `bash alerts/infra/scripts/fix-webhook-state.test.sh` — required when changing the shared QuickNode state-ID parser, repair tool, or listener replacement provisioner. -- `pnpm agent:quality-gate` for any combined edit — path-aware routing. +- For a combined edit, apply every matching direct author check in step 3 of + the [PR operating card](../docs/notes/pr-operating-card.md). For Cloud Function deploy verification, follow `docs/pr-checklists/terraform-cloudrun.md`. diff --git a/docs/PLAN-progressive-verification-graph.html b/docs/PLAN-progressive-verification-graph.html index d6f168084..986af01e8 100644 --- a/docs/PLAN-progressive-verification-graph.html +++ b/docs/PLAN-progressive-verification-graph.html @@ -575,12 +575,12 @@
-

Monitoring monorepo · Phase 1 trust hardening

+

Monitoring monorepo · M5 early local cutover

Remove the queue. Keep the quality bar.

- Replace the mandatory local gate with direct package feedback and - hardened existing CI. Add no app, cloud project, scheduler, task - graph, or verdict store. + M5 removes the mandatory local gate from the push path. Direct package + feedback and hardened existing CI keep the quality bar. The design + adds no app, cloud project, scheduler, task graph, or verdict store.

@@ -730,7 +730,8 @@

Format staged files

Check affected packages

Run direct lint, typecheck, test, codegen, React Doctor, build, - and browser checks when their named trigger applies. + and browser checks when their named trigger applies. Inspect + install changes first, then install the frozen candidate graph.

@@ -748,9 +749,9 @@

Example: a dashboard page with indexer changes

  • Regenerate contractsRun indexer codegen when schema, config, ABI, entry point, or - reachability changes. Run dashboard codegen for query - consumers.After any required frozen install, run indexer codegen when + schema, config, ABI, entry point, or reachability changes. Run + dashboard codegen for query consumers.
  • @@ -764,7 +765,7 @@

    Example: a dashboard page with indexer changes

  • Check the pageRun dashboard:react-doctor:diff, build the + >Run React Doctor against the resolved PR base, build the route, and verify route, console, interaction, and auth states in a browser. @@ -894,7 +895,7 @@

    Immutable no-skip audit

    command.
  • - Shadow spend is approved: allow at most 45 + Canary spend is capped: allow at most 45 runner-minutes per no-skip run and 450 cumulative runner-minutes. Stop after a run exceeds 45 minutes. Do not start another run when it could exceed the cumulative ceiling. The first cold proof on PR @@ -904,14 +905,14 @@

    Immutable no-skip audit

    credit. The repair extracts the retained setup, package-policy, and autoreview assertions into two focused suites. It excludes only the four legacy selector steps. Retained generated-output and workflow - safeguards still run in fixed CI. The repaired cohort starts after - this change reaches protected main. Audit-eligible pull + safeguards still run in fixed CI. The post-cutover canary starts + after M5 reaches protected main. Audit-eligible pull requests use ordinary CI plus no-skip for the same immutable head. Package, dependency, and toolchain pull requests use ordinary CI only when the protected filter selects the full fixed job set and every retained job succeeds. Evidence-instrument changes cannot - count. At least 10 pull requests over at least 7 calendar days must - pass these rules. The no-skip ceiling has 43.48 of 450 + count. At least 10 merged pull requests over at least 7 calendar + days must pass these rules. The no-skip ceiling has 43.48 of 450 runner-minutes recorded.
    @@ -952,7 +953,10 @@

    Six layers keep the quality claim honest.

    No-skip auditDetect selection omissions before and after cutover. + >Detect selection omissions during the post-cutover + canary.
    Review and consentSix layers keep the quality claim honest.

    Evidence earns each deletion.

    - The gate stays mandatory until shadow evidence passes and a human - approves a separate cutover. + The M5 early local cutover is active. Ten merged PRs over seven + days must pass the post-cutover canary before deletion.

    @@ -1029,25 +1033,24 @@

    Category detail stays separate

    >
  • - No-skip and shadow · #2126No-skip audit · #2126Repair the retained target. Compare at least 10 distinct PRs - over 7 days through same-head audit or ordinary force-all - evidence within approved spend.Implement the protected manual audit and archive its incident + evidence. The cohort moved to #2128.
  • Cut over · #2127Extend the after-manifest generator, then use human approval to - remove pre-push verification. Keep the diagnostic runtime.Use the recorded human approval to remove pre-push + verification. Keep the diagnostic runtime and required CI.
  • Soak and delete · #2128After another 10 merged PRs over 7 days, retire only proved - gate-only code.Observe at least 10 merged PRs over 7 days, then retire only + proved gate-only code with separate approval.
  • @@ -1066,7 +1069,7 @@

    Category detail stays separate

  • - 10 PRsminimum shadow sample + 10 PRsminimum post-cutover canary
    7 daysminimum calendar window @@ -1077,7 +1080,7 @@

    Category detail stays separate

    2 approvalscutover and later deletion + >recorded cutover and separate deletion

    @@ -1090,8 +1093,9 @@

    Category detail stays separate

    Rollback before deletion

    - Stop merges, restore the recorded ruleset, then revert the - cutover commit. The retained runtime resumes the hook. + On a confirmed author-check mapping omission, stop merge + handoffs and revert the cutover commit. Keep required CI and + strict current-base protection.

    diff --git a/docs/PLAN-progressive-verification-graph.md b/docs/PLAN-progressive-verification-graph.md index 8151141bc..47247b4a7 100644 --- a/docs/PLAN-progressive-verification-graph.md +++ b/docs/PLAN-progressive-verification-graph.md @@ -3,7 +3,7 @@ title: Simple Verification System Plan status: active owner: eng canonical: false -last_verified: 2026-09-01 +last_verified: 2026-09-03 doc_type: plan scope: repo-wide review_interval_days: 180 @@ -275,8 +275,11 @@ command would need base resolution, cross-package routing, generated-file rules, timeouts, and cloud fallbacks. That design would recreate the current gate. A draft push must remain a fast way to start CI. -Use this fixed trigger table. Invoke the commands directly. Do not add a -repository-wide selector or quick wrapper. +The complete current trigger table is in +[step 3 of the PR operating card](notes/pr-operating-card.md#the-loop). The +table below is a non-normative summary of common package and UI triggers. +Invoke commands directly. Do not add a repository-wide selector or quick +wrapper. | Change trigger | Required local checkpoint | | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -284,9 +287,15 @@ repository-wide selector or quick wrapper. | Typed source in a package | Run that package's `typecheck` command at the same checkpoint. | | Behavior change in a package | Run focused tests while editing as useful. Run that package's normal `test` command once before review handoff. | | Generated input or consumer | Run the owning code generator as soon as the schema, configuration, ABI, query, entry point, or handler reachability is coherent. Check the generated diff. | -| Dashboard React or client source | Run `pnpm dashboard:react-doctor:diff` after the changed UI is coherent and before review handoff. | +| Dashboard React or client source | Run `REACT_DOCTOR_BASE_REF= pnpm --filter @mento-protocol/ui-dashboard react-doctor:diff` after the changed UI is coherent and before review handoff. | | New or changed UI interaction or route | Run the documented build when the route, server, or build boundary changes. Verify the changed route in a browser. Check the console and exercise the changed interaction. | +Inspect install-affecting changes before any package-manager command. When +they change, install the candidate graph with +`CI=true pnpm install --frozen-lockfile` before code generation and package +checks. Keep the small exact trust-configuration contract rows in the operating +card. + Use the package's CI-aligned local test command. Do not assume that every package's generic `test` alias is unattended. For Governance Watchdog behavior changes, run `pnpm --filter @mento-protocol/governance-watchdog test:unit`. @@ -313,8 +322,9 @@ sequence: `pnpm --filter @mento-protocol/ui-dashboard typecheck`, and `pnpm --filter @mento-protocol/ui-dashboard test`. 5. When the page is feature-complete, run - `pnpm dashboard:react-doctor:diff` against the resolved current pull request - base. Run `pnpm dashboard:build` for the new route with the documented + `REACT_DOCTOR_BASE_REF= pnpm --filter +@mento-protocol/ui-dashboard react-doctor:diff`. Run `pnpm dashboard:build` + for the new route with the documented non-secret build environment. Follow the dashboard browser runbook for the changed route, console, interaction, and applicable auth states. 6. Push at any point when shared CI feedback is useful. Complete all applicable @@ -709,9 +719,9 @@ measured work. Do not make a full CI rewrite a prerequisite for local relief. ## Migration -Each phase is independently reversible. The mandatory local gate remains -enforced until a separately approved cutover. Required CI remains the merge -authority throughout the migration. +Each phase is independently reversible. The operator approved the M5 early +local cutover on 2026-09-02. Required CI remains the merge authority throughout +the migration. ### Phase 0: Inventory and measure @@ -822,7 +832,7 @@ scheduler tests to the replacement for a scheduler that will be deleted. The second implementation pull request stops here. Issue #2125 does not add or run the no-skip audit. It changes no hook, ruleset, or local gate behavior. -### Phase 3: Add the no-skip audit and shadow (#2126) +### Phase 3: Add the no-skip audit (#2126) Add an opt-in protected-default-branch no-skip workflow with a distinct run and display name. Keep its run ID and immutable inputs as operational evidence. Do @@ -865,9 +875,10 @@ The approved execution ceiling is 45 runner-minutes for one run and 450 runner-minutes for the initial sample. Stop after a run exceeds 45 minutes. Do not start another run when it could exceed the cumulative ceiling. -Record at least 10 distinct pull requests over at least 7 calendar days, -subject to the approved spend ceiling. Multiple heads from one pull request do -not increase the pull-request count. Use one of these evidence forms: +After M5 cutover, issue #2128 records at least 10 distinct merged pull requests +over at least 7 calendar days, subject to the approved spend ceiling. Multiple +heads from one pull request do not increase the pull-request count. Use one of +these evidence forms: - For a pull request without package-execution or evidence-instrument drift, record ordinary CI and the distinct no-skip audit for the same immutable @@ -896,47 +907,48 @@ For every head, record: observed numerator and cohort denominator. - Any product failure, flake, cancellation, or infrastructure failure. -Record a local gate result when it is available for the same SHA. Do not make -cutover depend on collecting ignored per-worktree state from every PR. +Record a legacy diagnostic result only when it is deliberately available for +the same SHA. The post-cutover canary does not depend on ignored per-worktree +state. Use the existing historical routing corpus to test every remaining conditional filter. Add negative fixtures for workflow weakening, deleted files, renamed files, unknown paths, skipped jobs, cancelled jobs, and missing aggregate inputs. -Issue #2126 owns both the no-skip implementation and this evidence window. Its -implementation pull request uses `Refs`, and the issue stays open until the -10-PR, 7-day receipt passes. +Issue #2126 owns the no-skip implementation and its archived incident evidence. +Issue #2128 owns the post-cutover 10-PR, 7-day canary. ### Phase 4: Human-approved cutover (#2127) Use a separate change and explicit human approval because this phase removes a -control that blocks the acting agent. +control that blocks the acting agent. The operator granted that approval on +2026-09-02 and moved the observation window after cutover. Before changing the local contract: -1. Verify that the existing `CI / ci` and all other live required contexts stay - required. -2. Prove the required results on the exact current head. -3. Record the current ruleset JSON and the exact cutover revert commit. Apply - only the current-base requirement that this plan needs. -4. Verify a canary pull request for normal code, control-plane code, a renamed - file, an unknown path, a failed job, a cancelled job, and a stale head. -5. Verify two close `main` commits without cross-cancellation. -6. Before producing the after manifest, extend the Phase 0 manifest generator +1. Merge the M4 graph-pin repair and require green protected-main CI for its + exact merge commit. +2. Verify that the existing `CI / ci` and all other live required contexts stay + required. Enable current-base protection without changing those contexts. +3. Record the current ruleset JSON and the exact cutover revert commit. +4. Before producing the after manifest, extend the Phase 0 manifest generator to count replacement-owned checker and test files, verification aliases, and every changed control-plane block. Accept a Trunk configuration with both legacy gate markers absent after full action removal. Continue to reject a partial or malformed legacy block. Add fixtures for the present, fully removed, and partial or malformed states. +Issue #2128 observes normal code, control-plane code, renamed and unknown paths, +failed and cancelled jobs, stale heads, and close `main` commits after cutover. + Then remove the mandatory full gate from the local push path. Keep the staged formatter on pre-commit. Add no pre-push verification command. Add the fixed trigger table and required author checkpoints to the operating card and publication workflow. Invoke existing package commands directly. Update the -quick commands, setup, Worktrunk hooks, Trunk hook, ship and babysit skills, -package scripts, and all stale gate instructions in the same change. Keep the -old command available as a diagnostic during the observation period. +quick commands, setup, Worktrunk hooks, Trunk hook, ship and babysit skills, and +all stale gate instructions in the same change. Keep the package aliases and +old command available as diagnostics during the observation period. The retained diagnostic keeps its coordinator, process drains, and legacy lock. Inventory active worktrees before deletion. Update setup and worktree entry @@ -986,10 +998,9 @@ a separate plan and evidence that the current filters cannot meet the target. ## Acceptance Evidence -Do not cut over until every unlabelled pre-cutover requirement passes. Evaluate -requirements marked **Post-cutover soak** during the #2127 and #2128 soak. -Evaluate requirements marked **Deletion gate** immediately before the separate -Issue #2128 deletion approval. +The M5 early local cutover is active. Evaluate **Post-cutover soak** requirements +during the #2128 canary. Evaluate **Deletion gate** requirements immediately +before the separate issue #2128 deletion approval. ### Coverage @@ -1002,9 +1013,9 @@ Issue #2128 deletion approval. `needs`, conditional jobs, and allowed skips. - The aggregate fails for failed, cancelled, missing, and disallowed skipped jobs. -- No shadow head has a product failure found only by no-skip CI because +- No canary head has a product failure found only by no-skip CI because path-gated CI omitted the failing job. -- The shadow sample covers all pull-request risk classes. +- The canary sample covers all pull-request risk classes. ### Trust and merge behavior @@ -1024,8 +1035,9 @@ Issue #2128 deletion approval. ### Speed and reliability -Use the same shadow sample of at least 10 distinct pull requests over at least 7 -calendar days for head-level measures unless a larger denominator is stated. +Use the same #2128 post-cutover sample of at least 10 distinct merged pull +requests over at least 7 calendar days for head-level measures unless a larger +denominator is stated. - **Post-cutover soak:** shared local gate queue time is zero seconds. The staged formatter and selected author commands still have their own measured runtime. @@ -1071,20 +1083,21 @@ calendar days for head-level measures unless a larger denominator is stated. The rollback uses repository history and the existing ruleset. It needs no service recovery. -If the static CI aggregate is wrong before cutover, keep the current gate and -fix the CI workflow. +Roll back M5 on the first confirmed author-check mapping omission. Confirmation +requires all of these facts: `/ship` handled the PR; its changed surface matched +a table trigger; the PR validation record omitted that check or marked it +inapplicable; required CI ran the corresponding safeguard; and the safeguard +failed deterministically because of the PR. A CI-only safeguard failure is not +automatically a mapping omission. -If a false success appears after cutover but before legacy deletion: +For a confirmed omission: -1. Stop merges through the normal ruleset administration path. -2. Verify or restore the prior required-check configuration from the recorded - ruleset JSON. The record must include `CI / ci`, Code Quality, all Sentry - suite requirements, Vercel, and Vercel Preview Comments. -3. Revert the recorded cutover commit to restore the mandatory gate hook and - its legacy implementation. -4. Add a regression fixture for the missed safeguard. -5. Correct the inventory or static job. -6. Repeat the shadow acceptance period for the affected risk class. +1. Stop merge handoffs. +2. Revert the recorded M5 cutover commit to restore pre-push verification. +3. Keep required CI and strict current-base protection. +4. Add the missed case to the author table. +5. Resume the #2128 canary only after the repair reaches green protected + `main`. If the legacy implementation was already deleted: @@ -1096,7 +1109,7 @@ If the legacy implementation was already deleted: 4. Restore the prior ruleset configuration. 5. Revert the cutover commit to re-enable the mandatory hook only after the runtime is available. -6. Add the regression fixture and repeat the affected shadow period. +6. Add the regression fixture and restart the affected canary window. Never restore a hook before its runtime. Never clear live coordinator state during rollback. diff --git a/docs/adr/0007-agent-quality-gate-and-merge-oracle.md b/docs/adr/0007-agent-quality-gate-and-merge-oracle.md index a2a46926b..8140e7dc5 100644 --- a/docs/adr/0007-agent-quality-gate-and-merge-oracle.md +++ b/docs/adr/0007-agent-quality-gate-and-merge-oracle.md @@ -3,7 +3,7 @@ title: Local agent quality gate plus two-projection PR all-clear and Codex gate status: active owner: eng canonical: true -last_verified: 2026-08-31 +last_verified: 2026-09-02 scope: ci/process date: 2026-05 doc_type: adr @@ -13,11 +13,11 @@ garden_lane: adrs-architecture # ADR 0007 — Local agent quality gate + two-projection PR all-clear + Codex approval gate -**Status:** Accepted (Apr–Jun 2026), in force during the staged transition. +**Status:** Accepted (Apr–Jun 2026), amended by the M5 cutover on 2026-09-02. [ADR 0078](0078-staged-verification-redesign.md) supersedes the mandatory local -gate as the target state. The current gate remains mandatory until the approved -cutover. The hosted two-projection all-clear and Codex approval gate remain in -force. +gate. The gate remains a callable diagnostic and a required-CI regression +suite. The direct `/ship` author checks replace it in normal local delivery. +The hosted two-projection all-clear and Codex approval gate remain in force. **Scope:** ci/process ## Context @@ -29,7 +29,7 @@ definition of "ready to merge". ## Decision -Two layers: +The original decision had two layers: - **Local agent quality gate** (`pnpm agent:quality-gate`) maps changed paths to the exact package checks + checklists and runs them locally before push. It is @@ -43,6 +43,11 @@ Two layers: blocks through the feedback ledger, and any aggregate `CHANGES_REQUESTED` review verdict blocks readiness. +The M5 amendment retires the first layer as a mandatory local control. Step 3 +of the [PR operating card](../notes/pr-operating-card.md) now owns bounded +direct author checks. Pre-push runs no repository verification. Required CI +remains merge authority. + ## Alternatives considered - **Trust the GitHub checks UI by eye** — rejected: advisory bots trail the status diff --git a/docs/adr/0033-adr-process-and-gate.md b/docs/adr/0033-adr-process-and-gate.md index 05922051a..ad5cd0d56 100644 --- a/docs/adr/0033-adr-process-and-gate.md +++ b/docs/adr/0033-adr-process-and-gate.md @@ -3,7 +3,7 @@ title: Architectural decisions are recorded as ADRs, enforced by a reminder gate status: active owner: eng canonical: true -last_verified: 2026-08-11 +last_verified: 2026-09-02 scope: ci/process date: 2026-07 doc_type: adr @@ -13,7 +13,9 @@ garden_lane: adrs-architecture # ADR 0033 — Architectural decisions are recorded as ADRs, enforced by a reminder gate -**Status:** Accepted (Jul 2026), in force. +**Status:** Accepted (Jul 2026), amended by M3 and M5 in 2026-09. The reminder +now runs in the existing required root-scripts CI job. Direct author checks +also route control-plane changes to the focused contract. **Scope:** ci/process ## Context @@ -32,11 +34,12 @@ is enforced, not just documented: - **When** to write one is defined by a three-part test and a trigger-surface list in [`docs/pr-checklists/architecture-decisions.md`](../pr-checklists/architecture-decisions.md). -- **A reminder gate** — `scripts/pr/check-adr-reminder.mjs` (`pnpm adr:check`) — +- **A reminder check** — `scripts/pr/check-adr-reminder.mjs` (`pnpm adr:check`) — detects high-signal architectural changes (new package/service, new Terraform stack, new CI/deploy workflow) that ship without an ADR and prints a reminder. - The agent quality gate runs it on those surfaces, so a normal pre-push flow - surfaces it automatically. + The required `Lint + test root scripts` CI job runs it and its tests. The + operating card requires it for the same high-signal surfaces during author + checks. - **The PR template** asks "Architecture decision?" so authors consciously answer yes (link the ADR) or no (why). @@ -53,10 +56,9 @@ for a trigger without an accompanying ADR. PRs are threshold tweaks or reorders, not decisions; false positives would train everyone to ignore the gate. Advisory + self-suppressing keeps the signal credible, with `--strict` available when a team opts in. -- **A dedicated CI required check** — deferred: required checks carry no `paths:` - filters here (ADR 0010) and hard-gating on "did you decide something?" is - false-positive-prone; the local gate + PR-template prompt is the right altitude - for now. +- **A dedicated CI context** — rejected: the existing required root-scripts job + runs the reminder without adding another required context. The PR-template + prompt retains the explicit author decision. ## Consequences diff --git a/docs/adr/0064-scripts-module-directories.md b/docs/adr/0064-scripts-module-directories.md index a430b4140..e19511ff7 100644 --- a/docs/adr/0064-scripts-module-directories.md +++ b/docs/adr/0064-scripts-module-directories.md @@ -3,7 +3,7 @@ title: scripts/ may use module subdirectories; basenames and pinned paths are th status: active owner: eng canonical: true -last_verified: 2026-08-23 +last_verified: 2026-09-02 scope: ci/process date: 2026-08 doc_type: adr @@ -257,7 +257,7 @@ routing, not procedure. boundary admits `scripts/**`; `tf-stacks.test.mjs` proves it subsumes every stack pattern. A stale stack entry still stops that stack reacting to its own tooling. -5. `.trunk/trunk.yaml` pre-push hook, and `.gitattributes`. +5. `.trunk/trunk.yaml`, `.trunk/hooks/pre-commit`, and `.gitattributes`. 6. `.claude/settings.json`, `.codex/hooks.json`, `.claude/hooks/session-start.sh`, and the verbatim copies and invocation regexes in `context/check-settings-contract.mjs`, which @@ -298,10 +298,11 @@ routing, not procedure. `implementation_signature()`. Repoint every occurrence. `$script_source_dir` is the required anchor: the gate runs against stub fixture repositories where `$repo_root` is a temp directory with no `scripts/` tree, so a repo-root - anchor misses the helper on every fixture run. No CI job runs the gate for - real, so `agent-quality-gate.test.sh` is the only place any of them is - exercised outside a developer's pre-push. P11 moved `lockfile-scope.mjs` into - `gate/`, added it to `implementation_signature()` (issue 1905), and made a + anchor misses the helper on every fixture run. Required CI runs the + regression suites. Before M5, `agent-quality-gate.test.sh` was the only + exercise for these helpers outside a developer's pre-push; it remains their + CI exercise. P11 moved `lockfile-scope.mjs` into `gate/`, added it to + `implementation_signature()` (issue 1905), and made a helper the gate cannot find exit 2 instead of falling toward the full suite — its caller reads a nonzero exit as "cannot narrow", so the old behaviour silently widened every lockfile change and the run read as slow, not broken. diff --git a/docs/adr/0069-gate-routing-table-as-data.md b/docs/adr/0069-gate-routing-table-as-data.md index 620a4bd24..ad11d7b51 100644 --- a/docs/adr/0069-gate-routing-table-as-data.md +++ b/docs/adr/0069-gate-routing-table-as-data.md @@ -3,7 +3,7 @@ title: The quality gate's routing table is data, compiled by the repo's own bash status: active owner: eng canonical: true -last_verified: 2026-08-24 +last_verified: 2026-09-02 scope: ci/process date: 2026-08 doc_type: adr @@ -13,15 +13,13 @@ garden_lane: adrs-architecture # ADR 0069 — the quality gate's routing table is data, compiled by the repo's own bash-`case` translator -**Status:** Active (Aug 2026), complete. Implemented across four PRs of -[issue 1877](https://github.com/mento-protocol/monitoring-monorepo/issues/1877)'s -deferred D5 track: D5a made the table data, D5b landed the Node mapping engine -and proved it at parity, D5b part 2 made it the routing behind an in-production -parity guard, and D5c retired the bash arms, that guard and the parity harness -once the soak was clean -([issue 2020](https://github.com/mento-protocol/monitoring-monorepo/issues/2020)). -Sections 3 and 4 below describe the transitional machinery and are kept for the -record; what is live is the table, the engine, and the checks in section 5. +**Status:** Active (Aug 2026), complete. The four D5 PRs in +[issue 1877](https://github.com/mento-protocol/monitoring-monorepo/issues/1877) +made the table data, added the engine and parity guard, then retired the bash +arms after [issue 2020](https://github.com/mento-protocol/monitoring-monorepo/issues/2020)'s +clean soak. Sections 3 and 4 are historical. The table, engine, and section 5 +checks remain live. M5 retained the gate as an optional diagnostic; required CI +is authoritative. **Scope:** ci/process @@ -123,7 +121,7 @@ to tell a considered exception from a silenced check. One routing family has an external data source. The indexer handler-invariant classifier stays in the attested `scripts/agent-autoreview-core.mjs` runtime so -autoreview and the local gate do not grow separate owner lists. The core exports +autoreview and the optional diagnostic do not grow separate owner lists. The core exports a detached, deeply frozen family view and consumes that same view for its `{path, route, owner}` decisions. It validates the family schema before export: unknown fields, invalid types, overlapping exact owners, and Bash-unsafe literal @@ -164,8 +162,8 @@ A focused parity test covers all current JS, JSON, and TypeScript module paths below `src/` and `test/`, every current file below `abis/` and `config/`, every current root `config*.yaml` file, Vitest input, indexer test wrapper, Stryker configuration, `schema.graphql`, exact owners, exclusions, and synthetic future -extensions. The local indexer route runs it for these 25 inventory patterns, -and the indexer CI job runs it for every indexer change. A new module below +extensions. The optional diagnostic's indexer route runs it for these 25 +inventory patterns, and the indexer CI job runs it for every indexer change. A new module below `src/` or `test/`, root config YAML, root Vitest input, indexer test wrapper, ABI, or config file must gain an explicit owner in the PR that adds it. @@ -177,7 +175,7 @@ used. A prepared runtime keeps its existing prepared-runtime trust contract. When a candidate changes `scripts/agent-autoreview-core.mjs`, that protected classifier cannot see a new owner or a false-to-true reclassification in the candidate revision. The core path therefore selects the handler-invariant -checklist in both autoreview and the local gate. This source trigger +checklist in both autoreview and the optional diagnostic. This source trigger intentionally routes unrelated core edits. Executing the candidate classifier would break the protected-main trust boundary. @@ -199,7 +197,8 @@ So the matcher is a hand-written translator, and its test uses `/bin/bash` itsel as the oracle over every pattern in the table crossed with every literal path in the table, every tracked repo path, one synthetic matching path per glob, and a set of near misses per glob. The oracle runs on every bash the machine has, not -only the first on `PATH`, because 3.2 is what the pre-push hook runs on a Mac. +only the first on `PATH`. Before M5, Bash 3.2 was the version that the pre-push +hook ran on a Mac. The machinery to run bash from Node already exists in `scripts/sentry/ci-wiring/check-sentry-suites-in-ci-gate-extract.mjs` (`runProbeShell`, `probeDirs`). @@ -208,68 +207,13 @@ The near misses are checked twice: the shell must agree that the synthetic match matches and that at least one near miss does not. A control the shell rejects controls nothing. -### 3. TRANSITIONAL (D5a–D5b): the bash arms stay, and an equality test holds the two together - -**Retired at D5c.** `gate-equality.test.mjs` and the `gate-arms.mjs` parser it -rested on are deleted; the table is the only copy of the routing now, so there is -nothing left to compare it against. The routing-table suite kept every check that -was about the DATA — the schema, the pairing lint, staleness, the bash pattern -oracle — and gained the closed verb set, measured against -`scripts/gate/mapping/route.mjs` instead of against the gate's bash helpers. - -Until the arms are retired, the table is a second copy of a routing authority, -and a second copy nobody compares is a copy that drifts. `gate-equality.test.mjs` -parses the gate's own routing region and asserts the two describe the same -routing — patterns, verbs, arguments, guards and order, with comments dropped on -both sides because rewording one is not a routing change. - -The parser is narrow and **fails closed**: it recognises exactly the constructs -the routing region uses today and raises on anything else, naming the line. A -parser that skipped what it did not understand would report equality over the -subset it happened to read. - -Because the arms are the code that runs, the equality test is also what makes a -`scripts/` move complete: it fails if only one side moved. - -That is only true if it RUNS in both directions, so it is routed from both. A -change under `scripts/gate/routing-table/` schedules it, and so does a change to -`scripts/agent-quality-gate.sh` itself — the commoner drift, where somebody adds -or reorders an arm and does not touch the data. It also runs in the required -`ci` job, beside the routing regression suite and for the same stated reason: -the local pre-push gate is the thing a contributor can bypass, and a table that -has drifted from the arms fails nowhere at all. - -### 4. D5b part 2: the engine becomes the routing, behind a guard that runs in production - -**The guard is retired; the first paragraph is what stands.** The gate runs -`scripts/gate/mapping.mjs` once and executes its plan, and every refusal in the -paragraph beginning "Every failure around the seam" is still live. What went at -D5c is the arms, `plan_records_from_bash`, and the byte comparison between them. - -The gate no longer builds its plan from the `case` arms. It runs -`scripts/gate/mapping.mjs` once per run, reads the plan back as the TSV -`write_command_plan` already emits, and uses that. The arms still execute, and -the gate **refuses the whole run if the two plans differ by one byte** — every -record, in order, including the two run-scoped flags the routing sets. - -That guard is the point of the split. The parity harness proved agreement over -a corpus; this proves it over whatever a contributor actually changed, on every -run, on every machine. It is also what makes the step reversible without a -revert: a divergence stops the run rather than silently picking a winner, and -the arms are still sitting there. - -Every failure around the seam is a refusal, because the failure mode this whole -track exists to remove is a plan that came out smaller and still exited 0: a -mapper that cannot be found, exits non-zero, emits nothing, emits a record the -gate cannot parse, or names a bucket that does not exist. Measured, each of -those refuses with exit 2 (evidence below). - -**Why the arms stayed for a soak rather than going in the same PR.** The engine's -plan is hashed into the freshness stamp and executed. The arms cost nothing but -wall-clock, and while they ran, every gate invocation anyone made was another -parity sample on a path set nobody thought to put in a corpus. D5c deletes the -arms, the comparison, and the harness together, once the soak has produced no -refusal. +### 3–4. Historical D5 transition + +D5a–D5b kept the Bash arms and required exact parity with the data table and +Node plan. D5c removed the arms, parser, equality suite, and in-run parity guard +after the clean soak in section 5. `scripts/gate/mapping.mjs` is now the only +routing authority. A missing mapper, non-zero exit, empty or malformed plan, or +unknown bucket stops the diagnostic with exit 2. ### 5. D5c: what the soak produced, and what routing correctness rests on now @@ -331,8 +275,9 @@ Six pins land with the table: — the same treatment `scripts/agent-quality-gate.test.sh` and `scripts/terraform/terraform-fmt-check.test.mjs` already get, since a suite is part of what the gate proves about itself. An entry it cannot - `stat` hashes as `__missing__`, which **freezes** the signature, so - `--skip-if-fresh` reuses a stale stamp and skips real pre-push work + `stat` hashes as `__missing__`, which **freezes** the signature. Before M5, + `--skip-if-fresh` then skipped mandatory pre-push work; it now affects only + an operator-invoked diagnostic (`docs/adr/0064-scripts-module-directories.md:273-275`). This is the one that must not be forgotten, and `routing-table.test.mjs` asserts it per module. Runtime modules hash from the gate's `$script_source_dir`; suites and the @@ -364,8 +309,9 @@ comments would drift within one phase. It also cannot express the templated commands without an eval, and nothing in the repo lints JSON. **YAML.** Holds comments. Rejected: it puts a YAML parser on the gate's hot -path, which runs on every pre-push, and the repo has already learned here that a -parse failure must fail closed rather than widen (`scripts/gate/lockfile-scope.mjs` +path. Before M5, that path ran on every pre-push; it now serves the optional +diagnostic. A parse failure must fail closed rather than widen +(`scripts/gate/lockfile-scope.mjs` and `docs/notes/agent-quality-gate-mechanics.md:148-157`). A hand-checked module has no parser to fail. diff --git a/docs/adr/0073-guardrail-prose-pinned-in-ci.md b/docs/adr/0073-guardrail-prose-pinned-in-ci.md index e15953623..750c4372d 100644 --- a/docs/adr/0073-guardrail-prose-pinned-in-ci.md +++ b/docs/adr/0073-guardrail-prose-pinned-in-ci.md @@ -3,7 +3,7 @@ title: Normative guardrail sentences are pinned in CI, and scripts are not status: active owner: eng canonical: true -last_verified: 2026-08-26 +last_verified: 2026-09-02 scope: ci/process date: 2026-08 doc_type: adr @@ -134,10 +134,11 @@ edit is not the working model here. **Run the check only in the local pre-push gate.** The gate already routes it from both directions — an edit to the checker or the pin list, and an edit to -any protected prose file, `CLAUDE.md` included. Rejected as the only route: the local gate is -skippable by anything that does not run it, including a web session or an edit -landed through the GitHub UI, and the pins are worth exactly what the weakest -route enforces. It stays as the fast local signal; CI is the binding one. +any protected prose file, `CLAUDE.md` included. Rejected as the only route: the +local gate is skippable by anything that does not run it, including a web +session or an edit landed through the GitHub UI, and the pins are worth exactly +what the weakest route enforces. M5 retired that local route. Required CI is +the binding route. ## Consequences diff --git a/docs/adr/0076-fair-quality-gate-coordinator.md b/docs/adr/0076-fair-quality-gate-coordinator.md index f8e942202..1d8d95a30 100644 --- a/docs/adr/0076-fair-quality-gate-coordinator.md +++ b/docs/adr/0076-fair-quality-gate-coordinator.md @@ -3,7 +3,7 @@ title: Fair local quality-gate coordination across worktrees status: active owner: eng canonical: true -last_verified: 2026-08-30 +last_verified: 2026-09-02 scope: ci/process date: 2026-08 doc_type: adr @@ -13,14 +13,17 @@ garden_lane: adrs-architecture # ADR 0076 — Fair local quality-gate coordination across worktrees -**Status:** Accepted (Aug 2026). In force on branches that contain this change. +**Status:** Accepted (Aug 2026), narrowed by the M5 cutover on 2026-09-02. The +coordinator remains in force for the callable legacy diagnostic and rollback +compatibility. Normal `/ship` author checks do not use it. Pre-push starts no +repository verification, lock, or wait. **Scope:** ci/process ## Context [ADR 0007](0007-agent-quality-gate-and-merge-oracle.md) established the local -agent quality gate. Several agents and pre-push hooks now run that gate from -linked worktrees on one machine. +agent quality gate. Before M5, several agents and pre-push hooks ran that gate +from linked worktrees on one machine. Unrestricted overlap is unsafe. Issue [#1802](https://github.com/mento-protocol/monitoring-monorepo/issues/1802) @@ -1156,13 +1159,9 @@ its capacity and named resources until a token-scoped drainer acknowledges ## Consequences -- Independent gate-registered lint, typecheck, and unit-test work from different - worktrees can progress together within one machine budget. -- The same worktree still runs one full gate request at a time. This is required - for local outputs and result files. -- Dashboard coverage, browser, and build work still run without competing gate - commands. Their fair barrier can pause new admission while current work - drains. +- During optional diagnostic runs, independent lint, typecheck, and unit-test + work can progress within one machine budget. Each worktree remains + serialized. Dashboard coverage, browser, and build work retain their barrier. - Exact matching requests execute once. Their queue and execution results stay bound to one source, plan, environment, toolchain, and policy identity. - Older worktrees still observe the legacy lock during rollout. They do not @@ -1265,51 +1264,10 @@ They do not predict production gate duration. - Local `.tmp/agent-quality-gate/durations.jsonl` records captured on 2026-08-21 — 1,710 seconds total for 14 seconds of recorded execution, and 1,306 seconds total for about 64 seconds of recorded execution. -- Runtime files: `scripts/gate/quality-gate-coordinator.mjs`, - `quality-gate-coordinator.sh`, `quality-gate-coordinator-support.sh`, - `quality-gate-coordinator-policy.mjs`, - `quality-gate-coordinator-environment.mjs`, - `quality-gate-coordinator-client.mjs`, - `quality-gate-coordinator-lifecycle.mjs`, - `quality-gate-coordinator-core.mjs`, - `quality-gate-coordinator-primitives.mjs`, - `quality-gate-coordinator-requests.mjs`, - `quality-gate-coordinator-scheduler.mjs`, - `quality-gate-coordinator-server.mjs`, - `quality-gate-coordinator-startup-attestation.mjs`, - `quality-gate-coordinator-socket.mjs`, - `quality-gate-coordinator-state.mjs`, - `quality-gate-coordinator-legacy.mjs`, - `quality-gate-coordinator-journal.mjs`, - `quality-gate-coordinator-journal-fields.mjs`, - `quality-gate-coordinator-drain.mjs`, - `quality-gate-coordinator-result-record.mjs`, - `quality-gate-coordinator-results.mjs`, and - `quality-gate-coordinator-retention.mjs`. -- Darwin containment and service files: - `scripts/gate/darwin-broker-launch-preflight.mjs`, - `darwin-process-identity.c`, `darwin-process-identity-runtime.inc.c`, - `darwin-process-identity-helper.mjs`, - `darwin-process-lineage-model.mjs`, `darwin-process-lineage-state.mjs`, - `darwin-process-lineage.mjs`, - `darwin-process-lineage.sh`, - `mapped-command-process-identity.mjs`, and `trunk-check-once.sh`. -- Test and benchmark files: `scripts/agent-quality-gate.test.sh`, - `scripts/gate/quality-gate-coordinator.test.mjs`, - `quality-gate-coordinator-policy.test.mjs`, - `agent-quality-gate-scheduler.integration.test.mjs`, - `agent-quality-gate-scheduler-benchmark.mjs`, - `agent-quality-gate-scheduler-fixture.mjs`, - `agent-quality-gate-scheduler-fixture-support.mjs`, - `agent-quality-gate-fixture-processes.mjs`, and - `agent-quality-gate-scheduler-tool-fixture.mjs`. -- Focused containment tests: - `scripts/gate/darwin-broker-launch-preflight.test.mjs`, - `darwin-process-identity.test.mjs`, `darwin-process-lineage.test.mjs`, - `mapped-command-process-identity.test.mjs`, `trunk-check-once.test.sh`, - `scripts/agent-autoreview.test.sh`, - `scripts/sentry/broker/sentry-mcp-broker.test.mjs`, and - `scripts/sentry/ci-wiring/check-sentry-suites-in-ci-gate-extract.test.mjs`. +- Runtime, containment, test, fixture, and benchmark files under + `scripts/gate/`, plus the focused gate and Sentry tests that exercise those + files. - Integration entry point: `scripts/agent-quality-gate.sh`. -- Related decision: [ADR 0007](0007-agent-quality-gate-and-merge-oracle.md), - which owns why the local gate is required before push. +- Related decisions: [ADR 0007](0007-agent-quality-gate-and-merge-oracle.md) + records the pre-M5 gate; [ADR 0078](0078-staged-verification-redesign.md) + makes it optional and required CI authoritative. diff --git a/docs/adr/0077-operator-triggered-backlog-sweep.md b/docs/adr/0077-operator-triggered-backlog-sweep.md index 0e10466a0..251279649 100644 --- a/docs/adr/0077-operator-triggered-backlog-sweep.md +++ b/docs/adr/0077-operator-triggered-backlog-sweep.md @@ -13,7 +13,7 @@ garden_lane: adrs-architecture # ADR 0077 — Operator-triggered backlog sweep with isolated workers -**Status:** Accepted (Aug 2026). In force on branches that contain this change. +**Status:** Accepted (Aug 2026), amended by M5 in 2026-09. **Scope:** process ## Context @@ -30,17 +30,12 @@ Issue tracked stage 2. Its grooming decisions settled the trust model in favour of an operator-started run rather than a scheduled one. -Three constraints shaped the design. +Subagents cannot wait across turns. A worker polls each author check in-turn. +The orchestrator re-invokes a worker that goes quiet. -Subagents cannot wait across turns. A subagent that ends its turn to watch a -gate is never re-invoked, so an unattended batch that parks on a gate produces -nothing overnight. - -Gate runs are scheduled, not serialized. Since -[ADR 0076](0076-fair-quality-gate-coordinator.md) a transient machine-wide -coordinator admits independent work from different worktrees under a weighted -capacity, and a new gate joins a compatible coordinator instead of queueing -behind it. +M5 replaced worker gates. Each worker uses the direct author checks in step 3 of +the operating card. The legacy coordinator now serves only the diagnostic gate. +The sweep schedules direct checks by local CPU and memory use. Review rounds dominate cost. One shipped PR costs roughly 3% of the weekly usage window, and each push buys another bot review round whose findings cost @@ -53,8 +48,9 @@ claims each issue by number, and drives each through its own worker to a ready-for-review PR. It stops at READY and prints the PR links for the operator. - **The operator starts every run.** No schedule, no self-triggering. -- **The session is an orchestrator.** It runs no gate, edits no source file, and - opens no PR. It selects, claims, keeps workers moving, and writes the report. +- **The session is an orchestrator.** It runs no author check, edits no source + file, and opens no PR. It selects, claims, keeps workers moving, and writes the + report. - **One worker per issue, one isolated checkout per worker.** Each worker owns a clone it alone commits from, proven by a marker inside `.git/`. - **Claims use the issue-board transaction.** Each issue gets a stable Claim ID, @@ -69,9 +65,8 @@ ready-for-review PR. It stops at READY and prints the PR links for the operator. use the same-Claim-ID explicit rebind after it creates a PR branch. - **Workers poll their own long processes in-turn.** The orchestrator holds no timers; it re-invokes a worker that has gone quiet. -- **Concurrency is bounded by the gate coordinator's capacity.** Worker gates - are scheduled by it and count against it; the batch is capped at 4 and - defaults to 2. +- **Local resources bound author-check concurrency.** Run at most three ordinary + check sets at once. Run resource-heavy checks alone while other workers edit. - **The run stops at READY.** The sweep never merges. After a human merges a partial-stage sweep PR, the separate issue lifecycle can @@ -206,10 +201,9 @@ installs. Rejected: two workers committing from one tree push each other's work, and a repair applied through the wrong checkout lands on the wrong branch with nothing to notice it. Isolation is what makes a worker's branch its own. -**Machine-wide gate serialization, as the loop was first written.** Rejected -because it no longer describes the gate. Under the coordinator the adopted -`run.lock` names a live pid for as long as anyone on the machine is gating, so -treating that record as a busy signal refuses a sweep in the ordinary case. +**Machine-wide author-check scheduling.** Rejected for normal workers. Direct +checks run in isolated checkouts under the sweep's local resource bound. The +legacy coordinator remains only for the diagnostic gate. **Cron-triggered autonomy.** A sweep that starts itself needs answers this design does not have: what stops a run burning the usage window unattended, and @@ -235,9 +229,8 @@ Issues outside that set stay manual, which is the intended cost. The amendment above adds the pass that keeps that set from being empty, and bounds the delay it introduces at 12 hours per groomed issue. -Bounding concurrency at the coordinator's capacity means a batch of 4 runs at -most three gates at once. Throughput is capped by machine capacity rather than -by how many issues qualify. +A batch of 4 runs at most three ordinary check sets at once. Heavy checks run +alone while other workers edit. Required CI owns merge admission. Because the sweep stops at READY, merge approval remains a human step for every PR it opens. @@ -250,10 +243,8 @@ PR it opens. [#2071](https://github.com/mento-protocol/monitoring-monorepo/issues/2071), whose grooming decisions chose the operator-triggered form. - [`.agents/skills/backlog-sweep/SKILL.md`](../../.agents/skills/backlog-sweep/SKILL.md) - is the procedure that enforces the decision, mirrored byte-identically into - `.claude/skills/backlog-sweep/SKILL.md`. That mirror is enforced by - `scripts/repo-health/check-skills-mirror.mjs`, which the Agent Quality Gate - routes on any change to either tree. + and its byte-identical `.claude` mirror implement the decision. Operating-card + step 3 and required CI run the mirror checker and its tests. - [`docs/notes/backlog-sweep.md`](../notes/backlog-sweep.md) is the canonical contract the skill produces against — eligibility, boundaries, resilience duties, and the report. @@ -263,9 +254,8 @@ PR it opens. `pkg:tooling` path test, all documented in the two files above. Issues 2240, 2242, 2246, 2247, and 2256 carry the `sweep-groomed:v2` marker contract that followed from reviewing it. -- The concurrency bound is the gate coordinator's own capacity, default 3, - recorded in [ADR 0076](0076-fair-quality-gate-coordinator.md) and - [`docs/notes/agent-quality-gate-mechanics.md`](../notes/agent-quality-gate-mechanics.md). +- The skill and canonical backlog-sweep runbook enforce the sweep-local + resource bound. - The never-merge boundary rests on the operating card and [ADR 0084](0084-github-ui-operator-merge.md). The sweep stops at READY. A human can merge through the GitHub UI. @@ -278,5 +268,7 @@ PR it opens. receipt, and the exclusion ledger. - [`docs/notes/pr-operating-card.md`](../notes/pr-operating-card.md) — the PR loop every worker runs. -- [ADR 0076](0076-fair-quality-gate-coordinator.md) — the gate coordinator this - design's concurrency bound depends on. +- [ADR 0076](0076-fair-quality-gate-coordinator.md) — the legacy diagnostic + coordinator, narrowed by M5; normal workers do not use it. +- [ADR 0078](0078-staged-verification-redesign.md) — direct author checks and + required CI after M5. diff --git a/docs/adr/0078-staged-verification-redesign.md b/docs/adr/0078-staged-verification-redesign.md index 126e01200..e90642f34 100644 --- a/docs/adr/0078-staged-verification-redesign.md +++ b/docs/adr/0078-staged-verification-redesign.md @@ -3,7 +3,7 @@ title: Staged replacement of the mandatory local gate with existing CI status: active owner: eng canonical: true -last_verified: 2026-09-02 +last_verified: 2026-09-03 scope: ci/process date: 2026-08 doc_type: adr @@ -13,10 +13,10 @@ garden_lane: adrs-architecture # ADR 0078 — staged replacement of the mandatory local gate with existing CI -**Status:** Accepted (Aug 2026), amended 2026-09-02. The migration is in force. -The operator approved an early local cutover before the original pre-cutover -sample. The current gate stays mandatory until the approved cutover change -lands. +**Status:** Accepted (Aug 2026), amended 2026-09-03. The M5 early local cutover +is in force. The operator approved it before the original pre-cutover sample. +The legacy gate remains callable as a diagnostic and remains covered in +required CI. Issue #2128 owns the post-cutover canary and retirement evidence. [ADR 0007](0007-agent-quality-gate-and-merge-oracle.md) remains active for the hosted two-projection all-clear and Codex approval gate. This ADR supersedes only its mandatory-local-gate target state. [ADR @@ -187,6 +187,11 @@ reachability, and dashboard GraphQL consumer changes require their applicable code generation. Other workspace packages use their direct lint, typecheck, and test commands when those scripts exist. +Dashboard bundle inputs require a fresh shared-config build when applicable, a +fresh dashboard production build, and the bundle-size check. Peg-registry +authority inputs and shared thresholds require the existing integrity and +cross-package parity checks in the author-check table. + These local results shorten feedback. Required CI remains merge authority. A manual push can omit author checks, but it cannot omit required CI. @@ -286,9 +291,9 @@ cohort would prolong a local bottleneck that the operator already had to skip. It would also measure an intermediate local workflow that the approved cutover removes. -Issue #2127 may therefore remove repository verification from pre-push after -the graph-pin repair reaches protected `main`, protected-main CI passes, and -strict current-base checking is active. The cutover must keep staged formatting +Issue #2127 therefore removes repository verification from pre-push after the +graph-pin repair reaches protected `main`, protected-main CI passes, and strict +current-base checking is active. The cutover keeps staged formatting on pre-commit. It must add the fixed `/ship` author-check trigger table. It must also keep the full legacy gate available in required CI and as a diagnostic. Required CI remains merge authority. @@ -399,8 +404,9 @@ shadow evidence stays in GitHub runs and the later Markdown evidence record. ## Rollback -Before legacy deletion, restore the recorded ruleset first and revert the -cutover commit. The retained gate runtime then resumes the mandatory hook. +Before legacy deletion, keep required CI and strict current-base protection. +Revert the cutover commit. The retained gate runtime then resumes the mandatory +hook. After legacy deletion, first revert the retirement commit. Restore the gate runtime, coordinator, aliases, tests, and mixed-version lock behavior before diff --git a/docs/adr/0080-merge-base-freshness-stamp.md b/docs/adr/0080-merge-base-freshness-stamp.md index 144e54d5b..700c7b486 100644 --- a/docs/adr/0080-merge-base-freshness-stamp.md +++ b/docs/adr/0080-merge-base-freshness-stamp.md @@ -3,7 +3,7 @@ title: The gate's freshness stamp binds the merge-base status: active owner: eng canonical: true -last_verified: 2026-08-30 +last_verified: 2026-09-02 scope: ci/process date: 2026-08 doc_type: adr @@ -13,14 +13,16 @@ garden_lane: adrs-architecture # ADR 0080 — The freshness stamp binds the merge-base, not the base tip -**Status:** Accepted (Aug 2026), in force. +**Status:** Accepted (Aug 2026), narrowed by the M5 cutover on 2026-09-02. The +freshness stamp remains part of the callable legacy diagnostic and rollback +compatibility. No installed pre-push hook consumes it. **Scope:** ci/process ## Context `scripts/agent-quality-gate.sh --run` writes a whole-run freshness stamp so a later `--skip-if-fresh` run can exit without re-executing the mapped commands. -The pre-push hook in `.trunk/trunk.yaml` is the main consumer: it runs +Before M5, the pre-push hook in `.trunk/trunk.yaml` was the main consumer. It ran `git fetch --quiet origin main` and then the gate with `--skip-if-fresh --base origin/main`. diff --git a/docs/metrics/verification-redesign-control-plane-after.json b/docs/metrics/verification-redesign-control-plane-after.json new file mode 100644 index 000000000..6679e1d32 --- /dev/null +++ b/docs/metrics/verification-redesign-control-plane-after.json @@ -0,0 +1,1647 @@ +{ + "schema_version": 1, + "source_sha": "677ee1f63c278996228a280018efe42a22d40877", + "definitions": { + "whole_file": "Physical lines in the gate entry points, dedicated canonical gate documents, every scripts/gate/** file, the package-script pin checker, and the full pre-push hook. The gate-rooted set includes retained shared-consumer code.", + "matching_lines": "Unique fixed-pattern lines in other tracked files, full Turbo input filters that pin gate sources, and the full Trunk gate action block." + }, + "entries": [ + { + "path": ".agents/skills/babysit-pr/SKILL.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "81783a3719eeff081eda020055be96cfca413f155deac3d0e1a85afe50da1561" + }, + { + "path": ".agents/skills/backlog-sweep/SKILL.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "a13e2fe9261d97e2c1606e6c2e864c71be3edbd410bfe41df5bc9086cd2a2552" + }, + { + "path": ".agents/skills/ship/SKILL.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "074038c8aeecb4aa8984a327c684b665dd0baf607bc721c5d4dae1cd850fc6ce" + }, + { + "path": ".claude/babysit-pr.sh", + "surface": "shell-reference", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "d3c480e0895931bed7cbf87874c70abf3b6fba63aa92afb96a8b0e089e6c1f2b" + }, + { + "path": ".claude/commands/autoreview.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "4f4e8e29132190a939f67aeefaf19305c8d005401f463f40dd322874ebc41f81" + }, + { + "path": ".claude/settings.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 5, + "sha256": "e6474fc847975018a1fc2818febc5448395dee7fb52cd5ed59d35f5d7502ffc1" + }, + { + "path": ".claude/skills/babysit-pr/SKILL.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "81783a3719eeff081eda020055be96cfca413f155deac3d0e1a85afe50da1561" + }, + { + "path": ".claude/skills/backlog-sweep/SKILL.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "a13e2fe9261d97e2c1606e6c2e864c71be3edbd410bfe41df5bc9086cd2a2552" + }, + { + "path": ".claude/skills/ship/SKILL.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "074038c8aeecb4aa8984a327c684b665dd0baf607bc721c5d4dae1cd850fc6ce" + }, + { + "path": ".coderabbit.yaml", + "surface": "yaml-or-inline-shell", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "beba65e097060e21193f6fde6dc733af7a2fecf40f3480cd4c87d7931b26aa6b" + }, + { + "path": ".github/workflows/ci.yml", + "surface": "yaml-or-inline-shell", + "count_mode": "matching-lines", + "lines": 24, + "sha256": "f33008c54488ad61f005cc7be08fc225215cdbca014c06ab577673e5a758434d" + }, + { + "path": ".github/workflows/metrics-bridge.yml", + "surface": "yaml-or-inline-shell", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "e44656563aac997c99413b294847e004e3393e956cc7b7780e31f9f4971df799" + }, + { + "path": ".github/workflows/sentry-triage-agent.yml", + "surface": "yaml-or-inline-shell", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "f7dc2c765e72f4a382884789790694c68745c95d7447578ceb1ae7780c9a3379" + }, + { + "path": ".trunk/trunk.yaml", + "surface": "yaml-or-inline-shell", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "adf1390ee5f4a64f7ec714b0b0356c24348a5460fbd36d1fe7315651314d5a83" + }, + { + "path": "README.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "16df628cb187fe8f833d7417dab1383a2eb067b4111d6bab7be2f0e3934698c9" + }, + { + "path": "aegis/.gitignore", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "59697aa79114a3fd854e163245f693e6950688d2be96256d850bc8348f374701" + }, + { + "path": "aegis/terraform/.gitignore", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "7fd290c56c7b6dba2f9121a3b03cb93831c13bd20cef4b274c85d19f15259778" + }, + { + "path": "alerts/infra/.gitignore", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "2fb90408683344508e1527cc18f7e1ab5becedbfbe2ecd1a986e57fa5b4b57b2" + }, + { + "path": "alerts/peg-policy-publication/.gitignore", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "f482badb2523d45c8be652d77e042a0b6261a4a43588f67a6f5749d85abcee3c" + }, + { + "path": "alerts/rules/.gitignore", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "b3cb7c97cb0ccc9fa4aa044669d99b78ca7e7f0426193443101ede65ddb2889c" + }, + { + "path": "bootstrap-worktree.sh", + "surface": "shell-reference", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "8cc707e79ec22d19035cf691814576c9aa5eb3d46a3c0c265cd22ce44cf9b886" + }, + { + "path": "docs/PLAN-ai-review-process.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "b31ea8a8571166963ce05245865edfd7800d6bbb603f64b32a97d689bb5323ed" + }, + { + "path": "docs/PLAN-progressive-verification-graph.html", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "7ba568d96b454d5211bf149231b5157d665762f2fd35a8d6cbcc1a2999b1cf40" + }, + { + "path": "docs/PLAN-progressive-verification-graph.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 10, + "sha256": "d8e4935c9367c8b8054c5d93fc81e1b6c71854612e50b574269f6f87299d70ab" + }, + { + "path": "docs/PLAN-trove-history-page.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "bad460ec56b2758726d606136246fa79c7303c73ac2ddcc0ec9686968900fb38" + }, + { + "path": "docs/README.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 5, + "sha256": "f9a6641f9cdceb507421f4df1c48709ccf5fb20f07f618091733dc7ad96cee82" + }, + { + "path": "docs/adr/0007-agent-quality-gate-and-merge-oracle.md", + "surface": "instruction", + "count_mode": "whole-file", + "lines": 71, + "sha256": "48fcefe6020c20cefcae73dd7e23cd1ef0061520e864f732ef8bc8f467ee3f7f" + }, + { + "path": "docs/adr/0008-mandatory-hazard-checklists.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "761cd366028e82953425aace6b8d7ce5cf021e29bd131e9d9a7bcefad949d8a3" + }, + { + "path": "docs/adr/0024-plotly-basic-dist-bundle-budgets.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "e4d11d7838e250f7a378fd120720105b0c2e055680a44229edf0e61e7ae3a4ef" + }, + { + "path": "docs/adr/0025-fixture-browser-tests-react-doctor.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "d38643e65adaf862f567340fbf74f92691df7c0e9730228005615a5d9681547d" + }, + { + "path": "docs/adr/0031-governance-watchdog-standalone-root.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "68c8378af32164212c2a4ffcbb28176def7a22a2b5072226f85d91fa51e10e30" + }, + { + "path": "docs/adr/0033-adr-process-and-gate.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "38b6000ac669025db04c1ca7657e07f95a6281f09d63ff3abac6e29b710a2414" + }, + { + "path": "docs/adr/0043-peg-registry-service-local.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "3d8c15516820e3c757451a6199a39368e52f1cdb211d354f534b9528d14fec3e" + }, + { + "path": "docs/adr/0044-peg-thresholds-gated-rules-plane.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "5a5a99e370e3d7bbae99018f6e9538896d816f46538c2ef227933257f60ea710" + }, + { + "path": "docs/adr/0062-sentry-suites-self-run-gate.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "975559acf587d3bec76da82cf2609a4332ded009acf2569ac5a9dcf625d1fc14" + }, + { + "path": "docs/adr/0064-scripts-module-directories.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 17, + "sha256": "ce324c40f35ed3f7004497726bfa0d8e0c96c2ef3e1a0610b032eb9a1f822d33" + }, + { + "path": "docs/adr/0065-scripts-file-size-watchlist-scope.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "1ca1c7a93983d48e9d05b510489baa076d674fc7eaa275d30a3288c11e5bd38f" + }, + { + "path": "docs/adr/0068-sentry-fixture-authoring-policy.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "b1926d0b435e470d1c9fb56bf7bb6a557daaad5246f8609de1d242a4334c0beb" + }, + { + "path": "docs/adr/0069-gate-routing-table-as-data.md", + "surface": "instruction", + "count_mode": "whole-file", + "lines": 521, + "sha256": "c3cda5ee8f1aaf2d49f02d0f75743d805f9df0d8248df7d115e2363589dad0cd" + }, + { + "path": "docs/adr/0072-md-only-docs-checks-job.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 28, + "sha256": "4df7158a0d5e4a890b24c5828070bf468e62ad8c20b73362aaac321e2e4f232f" + }, + { + "path": "docs/adr/0073-guardrail-prose-pinned-in-ci.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "6370965ab35e4b0b8f96a3a36a00dcc1ea44b51a50011e068764132e8f8de5b9" + }, + { + "path": "docs/adr/0076-fair-quality-gate-coordinator.md", + "surface": "instruction", + "count_mode": "whole-file", + "lines": 1273, + "sha256": "9fe80fc11a4ea4d04c8aee3cb5eee3bfaa3d0ed23039b5b330f891dff2dd6de5" + }, + { + "path": "docs/adr/0077-operator-triggered-backlog-sweep.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "95c04959b110da40a0d290ff42b8185f1ea8f7b690e9cabaf540c848f2ec1bf2" + }, + { + "path": "docs/adr/0078-staged-verification-redesign.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 6, + "sha256": "6c4335e82473c8cbc9d758048ef43724adeb8ddb7b6440e7ab0c48cf6684a3d1" + }, + { + "path": "docs/adr/0079-sealed-exact-file-patch-secret-suppression.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "e1a27aa88335d024d71b5ed55ccbd6e92c5773d890e2a623da83764d2cdf12b7" + }, + { + "path": "docs/adr/0080-merge-base-freshness-stamp.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 7, + "sha256": "193f552a108821a4149aae0cc048e5c56bbb66d792f5e9fa454f823b02f9bb3f" + }, + { + "path": "docs/adr/0082-persistent-issue-board-mutation-mutex.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "304a15113ab10f51c1e97bc6bdcdff57eee874fc6270a629d5e46eec5b498a6f" + }, + { + "path": "docs/adr/README.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "349456402a68a06051f1cc0245768bb5e97ab0cf47ce574498bbe2e4e0a51b24" + }, + { + "path": "docs/claude-runtime-document-registry.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "8c5620a53f78d6fc3ed4cf0aadcdf0241cc8e25e118ea25e6070eed4762a13ea" + }, + { + "path": "docs/evals/documentation-navigation-2026-07-post-garden-alerts-escalation.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "8075dd829efc11834e9b75824ee433e1d686d1c70f47c6e8d55c10e5ab578770" + }, + { + "path": "docs/evals/documentation-navigation-2026-07-post-garden.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 7, + "sha256": "6de8163eaad0e2561e5cb7e9e83f680228c197f83f02544480f8df77bd89061d" + }, + { + "path": "docs/evals/documentation-navigation-2026-08-post-route.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 8, + "sha256": "b7d8aa801f244e82460fcb36a3aa7533c715f806abb6a508dca36d8dbf17be9a" + }, + { + "path": "docs/evals/documentation-navigation-baseline-fixtures.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "6e8199f615edfe9814abb18042bd6cbcd366a0b3474d65112166bb64d817c70e" + }, + { + "path": "docs/evals/documentation-navigation-baseline.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 9, + "sha256": "9730b8cb48dc22c29e5b1bb53972d60985315a29bbd146fdafc08c1b701b7777" + }, + { + "path": "docs/evals/documentation-navigation-fixtures.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "6f6a8c3305ceae1ad3a5e816646fcf6464805d3c324a2c1058a998953bf61011" + }, + { + "path": "docs/evals/documentation-navigation.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "09b9fb35d9497308669dd40ca6ffb98f0849da4025003d53db9378c561fba601" + }, + { + "path": "docs/evals/review-skill-finder-reports/pr-1995-draw1.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "b76442adf5ff04431735a2a134d9bf505b5f5127d6da5455b49ccbfaf4d59316" + }, + { + "path": "docs/evals/review-skill-finder-reports/pr-1995-draw2.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "7398c85b61f97d0eb5261f3402db2c35bc13bc7a1fc2874b4fd9797b5e55b879" + }, + { + "path": "docs/evals/review-skill-fixtures.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "7223888cc6bd15c9bdb3bf1f6929a516719dd497ee6d2f1bc577a6405e8202e9" + }, + { + "path": "docs/evals/review-skill-judge-calibration.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 19, + "sha256": "aa930bb14f90b5c747706771685eb0696100e1ce9e64ab8595440b55fde017dd" + }, + { + "path": "docs/evals/review-skill-runs/2026-08-28-76c7cde7-full-1afd9abd/calibration.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 7, + "sha256": "5e78b065d3ca37bb0e2f9e97a6b21923e032918f15ea9186a178234e1b226f8a" + }, + { + "path": "docs/evals/review-skill-runs/2026-08-28-76c7cde7-full-1afd9abd/result-1984-pipeline-1.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "a57d252b9edc91d662dcf673e3465989eaf056e8c9f6053c88539456dd4467f6" + }, + { + "path": "docs/evals/review-skill-runs/2026-08-28-76c7cde7-full-1afd9abd/result-1984-pipeline-2.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "c21f044b6ae3ff2b9adc86ace7a191dc40a546fb882313240739bfd2d7cbcf52" + }, + { + "path": "docs/evals/review-skill-runs/2026-08-28-76c7cde7-full-1afd9abd/result-1995-control-1.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 9, + "sha256": "401df3d5ff1444db9ac0e1eae34aceec262d81949e802b85e268a45783751b4e" + }, + { + "path": "docs/evals/review-skill-runs/2026-08-28-76c7cde7-full-1afd9abd/result-1995-pipeline-1.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 8, + "sha256": "8d8abc84c5c1a4e0b9bd633e5bd635539999bf5f6b120d10069516a4d1efc1dc" + }, + { + "path": "docs/evals/review-skill-runs/2026-08-28-76c7cde7-full-1afd9abd/result-1995-pipeline-2.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 9, + "sha256": "0fbca439e7d147978194a25584cef7a9edb4640f716a57688b7470f3be653e85" + }, + { + "path": "docs/evals/review-skill-runs/2026-08-28-76c7cde7-full-1afd9abd/result-1995-replay-1.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 12, + "sha256": "11f718be27418d88da4714b9373b15447990cbeeaea652b75af73469306e86f9" + }, + { + "path": "docs/evals/review-skill-runs/2026-08-28-76c7cde7-full-1afd9abd/result-1995-replay-2.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 9, + "sha256": "aa702668a236b50fe869ee45d8043e9fcc5e2e836705ae913ffb9aed73a846a3" + }, + { + "path": "docs/evals/review-skill-truth/pr-1984.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "b4962d6a8d66726541a482351c06f5397da4ee2658f1d64676790482f7e87766" + }, + { + "path": "docs/evals/review-skill-truth/pr-1995.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 13, + "sha256": "1493526f59e95669a6888f3e1bf77b3f7ad815bbf52959c505e02932be5ecbed" + }, + { + "path": "docs/evals/review-skill.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "ba82b6e3580497553bc90fdc50845c5dd4a46c1a1474fb2508019953fe862645" + }, + { + "path": "docs/metrics/verification-redesign-baseline.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 13, + "sha256": "121f1598b74c55a9a888de35408d9f14e37fd9108490b05c209acd2e03b411aa" + }, + { + "path": "docs/metrics/verification-redesign-control-plane-before.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 87, + "sha256": "2aeec153548a440101e96416112c1199ba55e835b94a20c21ddc2432433a0754" + }, + { + "path": "docs/metrics/verification-redesign-local-gate-source-bound-sample.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "ae64a703b4ee16338630b1ac0cd28c6cc305430d556ee98c8726b020c1b411c4" + }, + { + "path": "docs/metrics/verification-redesign-local-gate-source.patch", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 182, + "sha256": "1dce787ccb8c59709f9bd6a4650eba9c3a037e5dc88bb0dfaf4c16876f4a51a2" + }, + { + "path": "docs/metrics/verification-redesign-m2-complexity.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "1d45c7823660eb93f14642806c15f73a8e42bd3d083a791bdd44783edede9936" + }, + { + "path": "docs/metrics/verification-redesign-m3-complexity.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 4, + "sha256": "0b39cec3e00b90ece4437cad368cde2e5d1ba8571f563f42e2831ad6b193ccbb" + }, + { + "path": "docs/metrics/verification-redesign-m4-complexity.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 10, + "sha256": "a181366e46aeb4633916b1073205fa93ee8cf4b1e55eb87284f2811992b3f2ad" + }, + { + "path": "docs/metrics/verification-redesign-m4-shadow-evidence.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "c5eaade0bca9fef0c6febd06e2c11beae0e29a784d2dfbe37af2e69ae1d3cec4" + }, + { + "path": "docs/metrics/verification-redesign-safeguards.jsonl", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 20, + "sha256": "5615d15111e34fcb324ed0340bc5df7360b02c11f0f7a75f2574be46b6c6df4c" + }, + { + "path": "docs/notes/agent-issue-workflow.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "1235cfb641b4cf81550f5c001e38f2d684429a702bf2437157709c75bd6a4d28" + }, + { + "path": "docs/notes/agent-quality-gate-mechanics.md", + "surface": "instruction", + "count_mode": "whole-file", + "lines": 3269, + "sha256": "ec1d8400de671c78ce71951052ddf18819a99a8cd10fafeb85e45177d0f90d2a" + }, + { + "path": "docs/notes/autoreview-runtime-trust.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "9f6ee4e4adf9f0af128a6ea6cebfb05062a99559026945565a6ccc2efe970be8" + }, + { + "path": "docs/notes/backlog-sweep.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "fece55880ae885b5aea3925309b53b21a0156abe23c53f36de6a8e19a9bf16b7" + }, + { + "path": "docs/notes/codex-agent-skills.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "b0b1f665f9dbbed5ae4c609ed5c75909d80fc6024285cb3d3c11e7e0566567c5" + }, + { + "path": "docs/notes/codex-cloud-setup.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "0f85957b48bec8315ad843944400b68a36251ab9a3f449a8bc1832fca3fdce0a" + }, + { + "path": "docs/notes/file-size-watch.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 21, + "sha256": "22585f4478b266c62a1fc41b336a57922b77d0bd86e89436742b06642e15c43a" + }, + { + "path": "docs/notes/github-tooling-surfaces.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "0755db01f09b40f0814852d8887699128c51b1ef9ffb4079a91ca7d4d3856313" + }, + { + "path": "docs/notes/pr-operating-card.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "299b93b7c1801a0f053b7cc8b5bd74792d5a198ed83f532b526ab97bdb8bb159" + }, + { + "path": "docs/notes/pr-ready-state.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "ca4cfaa6b7483ec11ca990a144935756616447cccf23e49d14350747b5e0d5cc" + }, + { + "path": "docs/notes/quick-commands.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "d5dfa66129bcd4a9b108329030f52d61434e853f7874640db026590e4c1d25b8" + }, + { + "path": "docs/notes/sentry-triage-pipeline.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "547df8cfede7f1d6bbd330abc5f180e2aa39c13c3ab1217d368fc56b5d430af7" + }, + { + "path": "docs/notes/verification-redesign-phase-0-evidence.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 20, + "sha256": "0359bd3d5c0ae7d310f5a510105c6961c626733cd773298dc24189ba5f8d665a" + }, + { + "path": "docs/notes/worktree-and-web-setup.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "dc18fe1f9b4d6fa3c0b41be37801aabe28efa0d16d7bd725a45c9f101259e788" + }, + { + "path": "docs/pr-checklists/ci-workflow-gates.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "603412d3d377c0c9f9f71b4a7bf96488f212352e2ebc54610955dbdff583469c" + }, + { + "path": "docs/terraform.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "f04492b9bae1a82ab24996e6b8b69cbec309ed2ea62e5d68b58d9d4f561206b4" + }, + { + "path": "governance-watchdog/.gitignore", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "f49bd9afd3e34e59635fd42d9adf3f4630a8cc23b6e1be2ea970800bba72b932" + }, + { + "path": "indexer-envio/vitest.config.ts", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "8d4b91c66c0ef6fff1c2e079b05afbdb4372107083a650641a63f95d133a6413" + }, + { + "path": "package.json", + "surface": "alias", + "count_mode": "matching-lines", + "lines": 5, + "sha256": "81c0e41b345d746d2b938033e48694df56a043523b6c0b60f52ecab4dec150ac" + }, + { + "path": "scripts/AGENTS.md", + "surface": "instruction", + "count_mode": "matching-lines", + "lines": 8, + "sha256": "f12b0ade285223de171c37a768434310dc3be1e87984fba0da6af503357f701d" + }, + { + "path": "scripts/agent-autoreview-core.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "69b8ebe38c5534ec35aaf24af7d1ad66dfe3f31afb1be8e2d22a3977266a36b6" + }, + { + "path": "scripts/agent-autoreview.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 10, + "sha256": "69a78f21d4649b46dc1a6dcbbeee4e0a719a91c1aac4fac8ac3a5e7201b986a4" + }, + { + "path": "scripts/agent-autoreview.sh", + "surface": "shell-reference", + "count_mode": "matching-lines", + "lines": 67, + "sha256": "78c75660e1e7d17009dcf6a7be8990b633ba0d39e835af7b55ddc702da091399" + }, + { + "path": "scripts/agent-autoreview.test.sh", + "surface": "shell-reference", + "count_mode": "matching-lines", + "lines": 47, + "sha256": "759d1cf2b6da9e45c376583b799418db732c338490cb5e419c611ba94193c657" + }, + { + "path": "scripts/agent-quality-gate.sh", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 12352, + "sha256": "59c210448a46ab692bb9e2e7f836347bbc4e1783c7a8f5c0d592c70ca05b0798" + }, + { + "path": "scripts/agent-quality-gate.test.sh", + "surface": "test", + "count_mode": "whole-file", + "lines": 26167, + "sha256": "16b30091c88da5f51c49c18eb12d684724fae0ffd4038bbf39129f92ea90442a" + }, + { + "path": "scripts/bootstrap/agent-setup-contract.test.sh", + "surface": "shell-reference", + "count_mode": "matching-lines", + "lines": 9, + "sha256": "c3cb5cdf93196fc0d486b6620abb06026713096d67344e299bcf825ce61610e3" + }, + { + "path": "scripts/bootstrap/codex-cloud-setup.sh", + "surface": "shell-reference", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "da5afc596faa72cadb57238beebb0739b2bb885a6e219b7d51ba6ad57a1cf115" + }, + { + "path": "scripts/check-agent-quality-gate-package-scripts.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 155, + "sha256": "9b50d706520859312a5da8bb0bd707ae1df9f83e7cd556bfb9bb06ac96ce9535" + }, + { + "path": "scripts/coderabbit-config.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 12, + "sha256": "fcc761c687ff5f58f58a93e24e1f3419a462acf8b37d944c562da12eddd11087" + }, + { + "path": "scripts/context/check-agent-context.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "b407538f8862f89a2b16d6504d8e876ac6071a09d134325c5d7f3971d87a84f0" + }, + { + "path": "scripts/context/check-agent-context.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "9d9d5f8159a633d021eb0324dfefa6b7b8e20f2217f3125ba79da412c70f5faf" + }, + { + "path": "scripts/context/check-settings-contract.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 5, + "sha256": "48701c6c4c38e871dc9998c166dda143cb5fa6c1d7d9f3c083859fc677ff5952" + }, + { + "path": "scripts/context/check-settings-contract.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 8, + "sha256": "4a82a6e9b3e6048f6270d74254560cd53052d4af116ecf2b85ffe1edf6ff55b3" + }, + { + "path": "scripts/docs/check-verification-redesign-evidence.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 10, + "sha256": "b6fde6c6a4f3b136e602a5895638baa600bbe785abe845bee699dbce31093255" + }, + { + "path": "scripts/docs/check-verification-redesign-evidence.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 43, + "sha256": "89b092cc6430f1f8cb9df97baf10f6fb3781579cf92efabe7c38a4a250134eaf" + }, + { + "path": "scripts/docs/docs-garden-issue.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "09c951f900018a95e4341f629e50255a7cbfc6cc417b61886c2f0c649326242e" + }, + { + "path": "scripts/docs/docs-navigation-eval.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "5bf608380fe613bc9948af3ff624a19a11b41279152ec631657f17b49c063b3d" + }, + { + "path": "scripts/eslint-baseline-diff.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "4068085f47af1af25c46d2a4957fd0168ff95fb0a31c45d0c69d11440d34f08a" + }, + { + "path": "scripts/gate/agent-prewarm.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 457, + "sha256": "5a22486117833df6f9c8b74a703b020cb54777ded0d6586c1c434941eb6160ff" + }, + { + "path": "scripts/gate/agent-prewarm.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 227, + "sha256": "8b909d7ed22ec89fec347108b2d246a8b059ba6e0c796edc9796d35303e524e7" + }, + { + "path": "scripts/gate/agent-quality-gate-fixture-processes.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 298, + "sha256": "17ad0f58870df2ea9f13b510365ad3198998ed1b3c0d550d967f2b5bc4295e91" + }, + { + "path": "scripts/gate/agent-quality-gate-scheduler-benchmark.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 592, + "sha256": "ea7479e51e377136662656fdf171429aec43de29872fb513bb2aa5de3b26bb34" + }, + { + "path": "scripts/gate/agent-quality-gate-scheduler-fixture-support.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 54, + "sha256": "3e11175a3cd80df04eb908e3f50491bee279542177736460bba9c1eca8d16a07" + }, + { + "path": "scripts/gate/agent-quality-gate-scheduler-fixture.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 800, + "sha256": "cd62a7943791e580e36b246088e3e89ed65abe4e62d7eb461057ffdb9f369db5" + }, + { + "path": "scripts/gate/agent-quality-gate-scheduler-tool-fixture.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 89, + "sha256": "52f966b55d5db4800727f8db836250cceb381f1a80f0a8e919a57dd4187edd63" + }, + { + "path": "scripts/gate/agent-quality-gate-scheduler.integration.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 1645, + "sha256": "ddbb46a6ca71b0e6fbcff14bbc1b9afc0e290181deade6a5a9791b2820e17700" + }, + { + "path": "scripts/gate/darwin-broker-launch-preflight.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 2326, + "sha256": "e1d63122180a9b29e515aefa13c96cb06d7022b693c56b787c347e8fba50ac96" + }, + { + "path": "scripts/gate/darwin-broker-launch-preflight.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 1714, + "sha256": "b870bba633792c5c723f798771dcb5cd0864842f279d603292e14a50cf9c78e9" + }, + { + "path": "scripts/gate/darwin-process-identity-helper.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 1311, + "sha256": "daae20f43f84718a752f5e9fd31820ffb9da3e59e75d6983bf811cbe6edfd39b" + }, + { + "path": "scripts/gate/darwin-process-identity-runtime.inc.c", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 657, + "sha256": "3935539f4f6e84dad5c539a5a4e9028899f76f2a6956dd7b91dce818d890a3d1" + }, + { + "path": "scripts/gate/darwin-process-identity.c", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 785, + "sha256": "19bc5245b9a2c8013db4ce81aa427ce55cd1f62afd7aa4015b186ccea7b6ba05" + }, + { + "path": "scripts/gate/darwin-process-identity.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 1881, + "sha256": "c7beb05bbd1fe9902394fac8489de166347564682a85c78e613ea353890625a9" + }, + { + "path": "scripts/gate/darwin-process-lineage-model.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 793, + "sha256": "874f5017af320b11636db93755672fb19c12b241970b89ddcb6767e6939861fa" + }, + { + "path": "scripts/gate/darwin-process-lineage-state.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 1466, + "sha256": "002f4c2b7be827ade5529ec1c03aaf632f6f4fc73bb695fb908cb340a61577f1" + }, + { + "path": "scripts/gate/darwin-process-lineage.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 1712, + "sha256": "32bb1139cf405cd61529335d1b3c6186ed41d300fe36244083e7037f00d4eafc" + }, + { + "path": "scripts/gate/darwin-process-lineage.sh", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 776, + "sha256": "d58b14691e2ba82d098bb5211570d062d0857e4778a72567b28650fa07fa4b93" + }, + { + "path": "scripts/gate/darwin-process-lineage.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 3995, + "sha256": "82343f3c45f8b86d47180553f2ff401e9ffec43c4c77e211ebeeff9169ad9d63" + }, + { + "path": "scripts/gate/lockfile-scope.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 121, + "sha256": "7ae840852b3ea83e8ad7f7f0aafb5e9a7c74c15e2cc0e216289885ad2824efb3" + }, + { + "path": "scripts/gate/lockfile-scope.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 212, + "sha256": "452127e9b39ca1c3ba75309b70bcae0e29e3ccf6a52b16f980220b409583cba9" + }, + { + "path": "scripts/gate/mapped-command-process-identity.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 244, + "sha256": "5a3586a929a31581dc77bb0f5b5165e7218dc07bc0b17770c7ff090be5881a0b" + }, + { + "path": "scripts/gate/mapped-command-process-identity.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 598, + "sha256": "0a4be839e71c40c43d7a14c28a3818d30bdc273d4b4a51bb612f5acd2138653b" + }, + { + "path": "scripts/gate/mapping.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 480, + "sha256": "6ddbd8725ce38c06fa0ba4239f7689877d8112197383ff74e953953162f53293" + }, + { + "path": "scripts/gate/mapping/engine.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 1493, + "sha256": "5e69c52639c19c0e725229f978264f1f52c7a927a8ba430eddfd55a7754d33d4" + }, + { + "path": "scripts/gate/mapping/facts.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 492, + "sha256": "c48cfa31aeba850a49b63e6d034937e3018d1f8592275caaab27a3cd7668d28c" + }, + { + "path": "scripts/gate/mapping/plan.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 154, + "sha256": "8a5ceeb15eb044ca3426222132d5f9b2b763c4e0daf5ddfca3c8f6796fc32d83" + }, + { + "path": "scripts/gate/mapping/post-passes.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 554, + "sha256": "91bc27e2ab73d9beee84be3117a372d0d1cf3f2d7c32289384b31844058089c2" + }, + { + "path": "scripts/gate/mapping/route.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 241, + "sha256": "3ae78cb2664f3edbd09927abad6a9bd4a888f6b980d50d89a3d6cf6c959b4f33" + }, + { + "path": "scripts/gate/mapping/shell-quote.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 152, + "sha256": "a63629d9f5af30da86ba6f45a0022297505bc4e3593ffe8b241c4bfabd0a2b0d" + }, + { + "path": "scripts/gate/mapping/shell-quote.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 259, + "sha256": "3d80e1e6cdf1a7dbc1c67d8df2fc2393dfb851d319e17cda9e3e00b33b21f1bb" + }, + { + "path": "scripts/gate/mapping/verbs.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 387, + "sha256": "dff8f8e2a8cc90a5f567a9e3c7a8e598a3464ced03c0d039c94e40cbb7ada20f" + }, + { + "path": "scripts/gate/quality-gate-coordinator-client.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 290, + "sha256": "b210085e0a569e69fce5b1adf3cd613f41c0915a39975d5c5db9d445537b2b5b" + }, + { + "path": "scripts/gate/quality-gate-coordinator-core.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 649, + "sha256": "ca59c2def93efbc7fcaf6bf3ec94fa3b76021941936f1a7776ad07f092889667" + }, + { + "path": "scripts/gate/quality-gate-coordinator-drain.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 126, + "sha256": "697f69a0699804c4a67bbfe43f11ee5277871f57eb0966131a0bc9cafcddb3b1" + }, + { + "path": "scripts/gate/quality-gate-coordinator-environment.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 2507, + "sha256": "34b5ddad3088983cfbfc7bf32ae2af7b9a9610c23ac455a76e8fdd6794393ebd" + }, + { + "path": "scripts/gate/quality-gate-coordinator-journal-fields.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 171, + "sha256": "f865b74b5cefac6516c0af52977457094fcba77e1f2126d966ef6b7fa31fa6ba" + }, + { + "path": "scripts/gate/quality-gate-coordinator-journal.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 607, + "sha256": "a96b44b4abcdcac9606f085d06cc0f3c305ff90c35ff13616b4bcc7053816009" + }, + { + "path": "scripts/gate/quality-gate-coordinator-legacy.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 1793, + "sha256": "9a5a02ecb27b32aaac4606e29af3fe678696efff171cc1dc5c152e30bb564f57" + }, + { + "path": "scripts/gate/quality-gate-coordinator-lifecycle.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 92, + "sha256": "5d52f675c03c58236beeefa6d352fa9676d637cf7e290224d97bbade90f6d9b4" + }, + { + "path": "scripts/gate/quality-gate-coordinator-policy.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 218, + "sha256": "13547aff9563fe72f27e9eeb314aa19b8367c7846e545a9434352c74b0c9d458" + }, + { + "path": "scripts/gate/quality-gate-coordinator-policy.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 2305, + "sha256": "c044d48c51f5f67832ee618811500996a06c9728166ba3ba650e5880e3d4c8e2" + }, + { + "path": "scripts/gate/quality-gate-coordinator-primitives.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 207, + "sha256": "3632b84704f45ca6e50816bd96648d901fefcdf98d68e0e141978cdb8e053e92" + }, + { + "path": "scripts/gate/quality-gate-coordinator-requests.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 464, + "sha256": "25709b91e095f15e1314063cddf22f17cdaa96d135238d049471eef94e6ead5b" + }, + { + "path": "scripts/gate/quality-gate-coordinator-result-record.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 93, + "sha256": "2f5c5d1027ecd370052a40e683a2cfad4eadc86e9f2250b9a120e11bc04d78c1" + }, + { + "path": "scripts/gate/quality-gate-coordinator-results.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 363, + "sha256": "5e2f0326f16990d6130511611743341236cb0404abe45b7e6c35589d233ac526" + }, + { + "path": "scripts/gate/quality-gate-coordinator-retention.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 491, + "sha256": "0db8db8a078c1cfb8fb517c7300a06f8793eda031ee32b210513a63a5b004195" + }, + { + "path": "scripts/gate/quality-gate-coordinator-scheduler.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 243, + "sha256": "9632e41af02ea863f21ab9868a578e3ce3787699d5b62b033bfe268b814c3217" + }, + { + "path": "scripts/gate/quality-gate-coordinator-server.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 630, + "sha256": "e90e1dd80e1c7d8b30ac046b8946dceaa0b8d20a9f1e7d836e20211dbdda7ee3" + }, + { + "path": "scripts/gate/quality-gate-coordinator-socket.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 325, + "sha256": "abd40b82e48df054fb7a49d26470003514d8d37ea10424656b9473c66c3923f3" + }, + { + "path": "scripts/gate/quality-gate-coordinator-startup-attestation.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 363, + "sha256": "3497c731d1ecb1402979bbf142cf95c7749525440e12a6e69a815cb3ee74db6a" + }, + { + "path": "scripts/gate/quality-gate-coordinator-state.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 377, + "sha256": "247cb3fa6b533ecb56362096f69adef2d40df0edffeb4f5048dbf77ae7fe0598" + }, + { + "path": "scripts/gate/quality-gate-coordinator-submodule-state.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 361, + "sha256": "cdf873b3d3b89f935eefa22bd1fd66c4437494cadf90be757c964cef18a7ba7f" + }, + { + "path": "scripts/gate/quality-gate-coordinator-support.sh", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 997, + "sha256": "59498e6da2b9dd1e8e22fc5d8922caaf60e7d8e5cb7b04c082df8a23597414ba" + }, + { + "path": "scripts/gate/quality-gate-coordinator.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 610, + "sha256": "4b459380d17efe93a21869678d2a407925a61f829d71ca74b31246929df6fbbf" + }, + { + "path": "scripts/gate/quality-gate-coordinator.sh", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 814, + "sha256": "78eeb9b68dfb84616194e19810f22c6187b4a728742cd4369006802815fbe03c" + }, + { + "path": "scripts/gate/quality-gate-coordinator.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 8555, + "sha256": "3d4b13b7f7738693d42dfa6fbb2a529f61ad0e18ae4a4f097d4dabfe048352ff" + }, + { + "path": "scripts/gate/routing-table/arms-agent-modules.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 548, + "sha256": "8d08791888633b456116956819f50d17fa0c1e201524b3c8eb35233f60cef0fc" + }, + { + "path": "scripts/gate/routing-table/arms-alerts.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 170, + "sha256": "6ad94a4dc03afac932c45816d4c0d36b362c24e967434b69eaf656925ec1e0b1" + }, + { + "path": "scripts/gate/routing-table/arms-packages.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 546, + "sha256": "aa69a9cf75be15629261383491b4245e08bed2f8b437222b79c8d7b8c1e599bb" + }, + { + "path": "scripts/gate/routing-table/arms-script-modules.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 56, + "sha256": "a472a5574bf0bff1720522fb6b484937dc21ae5cf3785c453301f3c03742b217" + }, + { + "path": "scripts/gate/routing-table/arms-scripts.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 371, + "sha256": "b3d13d058ab4af46e9c3f38e4b023afc8aab910c57cf6547cd4c498d95e222c6" + }, + { + "path": "scripts/gate/routing-table/arms-sentry-modules.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 344, + "sha256": "19b6bf6899f67bfeb23ab99dc9b38ed448a6c3a7a41ee74a997645e2610c3309" + }, + { + "path": "scripts/gate/routing-table/arms-services.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 301, + "sha256": "b17e5fa108a25c1c5b156093233b7084c17f9f62a07864f819778980f45085ed" + }, + { + "path": "scripts/gate/routing-table/arms-tooling-modules.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 594, + "sha256": "09000181984d014148a2dca232e2cb95f2a0b2fdcef440453fc5dfe2aac33fee" + }, + { + "path": "scripts/gate/routing-table/arms-workflows.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 575, + "sha256": "4b67d7b663e7284ab7ef8881af597fc55efd87597a85b8499d40de09ad9180b1" + }, + { + "path": "scripts/gate/routing-table/checks.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 362, + "sha256": "0b0dfcc19f1425373745af1af2992dc03bdfa514b42588398c186a5439f5181f" + }, + { + "path": "scripts/gate/routing-table/groups-head.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 638, + "sha256": "ddb5103a26f13e5710df747f412414de7066dffe8351503439bfa5c5f7c8b435" + }, + { + "path": "scripts/gate/routing-table/groups-tail.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 407, + "sha256": "bba976c23b4db1ef50f5ddfebfeff67a50a0bb0e1be92422cebebe6114dd7073" + }, + { + "path": "scripts/gate/routing-table/index.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 125, + "sha256": "4202c1bd70dd2570fcdf5b411abb8e8324a732e2bf6b40df6cbaf45c8ec7dea6" + }, + { + "path": "scripts/gate/routing-table/indexer-invariant-parity.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 583, + "sha256": "547e0fe61e60bcbf0c31c46ba851a677ae71292ee11d835b17fa572fd7813b40" + }, + { + "path": "scripts/gate/routing-table/pattern-oracle.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 515, + "sha256": "ab0543ab31d498fb66d602f58a74ff5d46dbf82bc81d544fb30e827a21f9d67d" + }, + { + "path": "scripts/gate/routing-table/pattern.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 253, + "sha256": "13bfb0f339396d962c8ed1ac88439ff40d395bbdc523807e2304783b02207c05" + }, + { + "path": "scripts/gate/routing-table/pins.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 217, + "sha256": "ebc9a99ce102ca4a735da7ffccbe991c5cc2f5f1690eda698cb6667c8fb6100b" + }, + { + "path": "scripts/gate/routing-table/routing-table.test.mjs", + "surface": "test", + "count_mode": "whole-file", + "lines": 825, + "sha256": "8bb5dc2317da07fd3adf4c8103da535dad5315fb952e3f02ab6863f0a96f0063" + }, + { + "path": "scripts/gate/routing-table/schema.mjs", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 502, + "sha256": "a3be2a3684177f3754eaa1d8f2574f7cb7d29c7d55a19e67b3a15c55f5dc5cb9" + }, + { + "path": "scripts/gate/run-handles.sh", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 911, + "sha256": "e8549a1364dda172879a4d3ad1df35a6324f899be1f2e440d0bffd6e2ce155b9" + }, + { + "path": "scripts/gate/trunk-check-once.sh", + "surface": "implementation", + "count_mode": "whole-file", + "lines": 606, + "sha256": "a47889b36e6b5586d8f1ed95fd4602c41f0148ab788c09510d4e62507187e2ed" + }, + { + "path": "scripts/gate/trunk-check-once.test.sh", + "surface": "test", + "count_mode": "whole-file", + "lines": 632, + "sha256": "859b5fc3deac6265969f25964dcf2025c9fe13480841c6ea4ebe429acc591248" + }, + { + "path": "scripts/pr/check-adr-reminder.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 6, + "sha256": "0d7f69267c83209f122d4dcce4d5fa0016b44600dd2c217650e595147f087e8f" + }, + { + "path": "scripts/pr/pr-feedback-state.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 14, + "sha256": "fdf9a9ceaa8d8b22dc89ef52d0f4b2933e0046c6a21c237b49716f5512aacd2f" + }, + { + "path": "scripts/production-infra-identity-contract/routing.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 4, + "sha256": "b5f98f9dbaf07fc1c64d1b8ffc8d63e66f460a8cacb8d18d3ec8547a6ede78ea" + }, + { + "path": "scripts/repo-health/file-size-watchlist.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 15, + "sha256": "f91652d2819ad341802722de77fd942b740a947b93650b604217d0707cc4337a" + }, + { + "path": "scripts/repo-health/guardrail-prose.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "1318a9e848d0afd17eec2a32fe1913cbd9de36215ca637838e04c50223bf13e5" + }, + { + "path": "scripts/review/install-review-eval-launchd.sh", + "surface": "shell-reference", + "count_mode": "matching-lines", + "lines": 7, + "sha256": "c15a37879035ef1e97a68b5b6fd3b039b000883bb2cfc2c3112da89743c36789" + }, + { + "path": "scripts/review/install-review-eval-launchd.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 8, + "sha256": "fa77ec3fbbbd42a86fe9e82c44633fca6192931bbb73e334014cf6e1526e1ce8" + }, + { + "path": "scripts/review/testdata/review-eval-split-equivalence/contract.json.txt", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "7223888cc6bd15c9bdb3bf1f6929a516719dd497ee6d2f1bc577a6405e8202e9" + }, + { + "path": "scripts/sentry/autofix/sentry-autofix-family-handled.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "8b4fab8147b1b5d1142c3dd0f8bb04d0af66954dc6b93c70495292ec595ef2c5" + }, + { + "path": "scripts/sentry/broker/mapped-command-process-identity.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "58a8fbda2f0e122333858b0c0518d8f1e15b74d525e7ad1994446ec285896a38" + }, + { + "path": "scripts/sentry/broker/sentry-mcp-broker.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "e797a8e19d683ef46d89406538431b1ca8506edf5925f192d86832b4892461bf" + }, + { + "path": "scripts/sentry/broker/sentry-mcp-probe.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 4, + "sha256": "c59decc88b1f99b5c5cb924723e35bd53a80998ca8ba09b2f646df605243e3fc" + }, + { + "path": "scripts/sentry/ci-wiring/check-sentry-suites-in-ci-core.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "b305ccfbadd2c018c9bbe2b3129643ba41d75dc4bdfba3594362c11cc7c50892" + }, + { + "path": "scripts/sentry/ci-wiring/check-sentry-suites-in-ci-coverage.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 5, + "sha256": "f7a60550f26afc0bbbdd36bc33c62eb081697378833cf0d61ff8a5271fec8ffc" + }, + { + "path": "scripts/sentry/ci-wiring/check-sentry-suites-in-ci-gate-extract.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 3, + "sha256": "8149f0f217ee6ffcbcfe74cb4bf81fe2be309988abffa4f4ae07c8c05a7fdd39" + }, + { + "path": "scripts/sentry/ci-wiring/check-sentry-suites-in-ci-gate-extract.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 7, + "sha256": "70a207438c243046e90bc9fdf2656672d87ac06e6686b9fafb8e58b73d92089a" + }, + { + "path": "scripts/sentry/ci-wiring/check-sentry-suites-in-ci-gate-fixtures.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 6, + "sha256": "d807d8cbcc73f0eb1eb0cfad0b3cca13eb11d583c47f8a7070d64b783730293e" + }, + { + "path": "scripts/sentry/ci-wiring/check-sentry-suites-in-ci-gate-job.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "409ee3cd524e6b8b56c0fea51af98787ed13b7621d81be2ca5fdae7dda16eff2" + }, + { + "path": "scripts/sentry/ci-wiring/check-sentry-suites-in-ci-gate-probe.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 15, + "sha256": "317da3c86d9f13e7be19d7a8b8988d8e77f2c2f4a7152dac250f38c46226221b" + }, + { + "path": "scripts/sentry/ci-wiring/check-sentry-suites-in-ci-gate-probe.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 10, + "sha256": "ca8c95b079a2f3ec414f91e4b8fa3529d3b8b6f90b50a10b91fc6a41d863594f" + }, + { + "path": "scripts/sentry/ci-wiring/check-sentry-suites-in-ci-lifecycle.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 7, + "sha256": "dd131eb4e965188fff9e31dab17eb56614ef3ddaf18c3113ea627616f5de5673" + }, + { + "path": "scripts/sentry/ci-wiring/check-sentry-suites-in-ci-probes.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 10, + "sha256": "5a239333ee4d0e89c73d725f6a233dc805f90ec69f19dfbc6a27edf57d5a5732" + }, + { + "path": "scripts/sentry/ci-wiring/check-sentry-suites-in-ci.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "c816954306c0a255f9f2a15b81b7528fabb294b9dd33f294d11ea87fa949e445" + }, + { + "path": "scripts/sentry/fixture-scan-canary.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "4cad8293017b13a24a8ffc20438247103528aeda55ccf857714816bd30e550ba" + }, + { + "path": "scripts/sentry/gate/sentry-suite-manifest.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "57eb43731f7ca56af615a13e8ffcb61c4f707b582eca52b3aa71b8d098d25f3b" + }, + { + "path": "scripts/sentry/triage/sentry-triage-brief.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "18c47324d4f33d60b510433bb13d6efdc29da2a14accb9d3f456b0225f84bde1" + }, + { + "path": "scripts/setup.sh", + "surface": "shell-reference", + "count_mode": "matching-lines", + "lines": 4, + "sha256": "4f3f5a4559b32eb6d64cfea515cbf8eae0f47a69798ab02ad53e7b3fccb63be0" + }, + { + "path": "scripts/workflows/check-ci-contract.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "02dcbb5393dce7922d45fbda06f9ea3bd0366bdaec56d8eb9530f9e0e0ad9ad5" + }, + { + "path": "scripts/workflows/check-no-skip-audit.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 7, + "sha256": "d902e2817c73b6d8e5bc69991f8c5de86e6f157f0f78190bdcfb99ce161e6dd3" + }, + { + "path": "scripts/workflows/check-no-skip-audit.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 15, + "sha256": "ab37377fd0c899d596fe8a14e6bc073dca3947db5e0f059efa4e40bfcdad5235" + }, + { + "path": "scripts/workflows/check-pr-validation-boundary.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 2, + "sha256": "2096cb26cf8a32defa2582b1fe67fcba6a724fe37615076fdefd3c72159f5c3f" + }, + { + "path": "scripts/workflows/check-pr-validation-boundary.test.mjs", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 4, + "sha256": "21f008f45b9207eeb4ebc7de0c8d60ccb6671435c2e23e64a443f675ed66a930" + }, + { + "path": "terraform/.gitignore", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 1, + "sha256": "bbb6a4d2d552d4c12abb699fcf87284895de9da732a0469e48d324d844f8c8d7" + }, + { + "path": "turbo.json", + "surface": "configuration-reference", + "count_mode": "matching-lines", + "lines": 95, + "sha256": "226c1db28d1538a5a11a9d51fefcfb51f194b6e21b734e16500a3fe373b09c6e" + } + ], + "totals": { + "files": 232, + "counted_lines": 105684, + "by_surface": { + "alias": 5, + "configuration-reference": 810, + "implementation": 47187, + "instruction": 5326, + "shell-reference": 141, + "test": 52184, + "yaml-or-inline-shell": 31 + } + } +} diff --git a/docs/metrics/verification-redesign-m5-complexity.json b/docs/metrics/verification-redesign-m5-complexity.json new file mode 100644 index 000000000..93450769f --- /dev/null +++ b/docs/metrics/verification-redesign-m5-complexity.json @@ -0,0 +1,683 @@ +{ + "schemaVersion": 1, + "baseSha": "14ed775d936201e314008f812577e7a209afdb88", + "sourceSha": "677ee1f63c278996228a280018efe42a22d40877", + "sourceBoundaryCommit": "677ee1f63c278996228a280018efe42a22d40877", + "cutoverImplementationCommit": "bc58e096d3ea9a1bca48a7d7f70e83b43d8f1bc9", + "baseline": "M5 early-cutover complexity and control-plane receipt for issue #2127.", + "scope": "Every M5 path changed from baseSha through sourceSha, except this receipt and the generated after manifest. Both receipts bind to sourceSha and therefore self-exclude.", + "derivation": { + "method": "Use git diff --numstat from baseSha through sourceSha. Classify active agent instructions and operating runbooks as procedure; executable scripts as check; test files as test; hook and configuration files separately; architecture, plan, and evidence prose as doc.", + "trackedCommand": "git diff --numstat 14ed775d936201e314008f812577e7a209afdb88 677ee1f63c278996228a280018efe42a22d40877", + "receiptPath": "docs/metrics/verification-redesign-m5-complexity.json", + "afterManifestPath": "docs/metrics/verification-redesign-control-plane-after.json", + "receiptsSelfExcluded": true + }, + "beforeManifest": { + "path": "docs/metrics/verification-redesign-control-plane-before.json", + "sourceSha": "a5692c4570d7fe33255c2ce863d7f79264a9ddb0", + "sha256": "2aeec153548a440101e96416112c1199ba55e835b94a20c21ddc2432433a0754", + "totals": { + "files": 223, + "counted_lines": 101595, + "by_surface": { + "alias": 5, + "configuration-reference": 380, + "hook": 33, + "implementation": 46174, + "instruction": 5192, + "shell-reference": 126, + "test": 49641, + "yaml-or-inline-shell": 44 + } + } + }, + "afterManifest": { + "path": "docs/metrics/verification-redesign-control-plane-after.json", + "sourceSha": "677ee1f63c278996228a280018efe42a22d40877", + "sha256": "be9cac8230a2ba77d0f23a8ac6604790258731c7b48d0a24d3b83db7d5402a85", + "totals": { + "files": 232, + "counted_lines": 105684, + "by_surface": { + "alias": 5, + "configuration-reference": 810, + "implementation": 47187, + "instruction": 5326, + "shell-reference": 141, + "test": 52184, + "yaml-or-inline-shell": 31 + } + } + }, + "manifestComparison": { + "filesDelta": 9, + "countedLinesDelta": 4089, + "bySurface": { + "alias": { + "before": 5, + "after": 5, + "delta": 0 + }, + "configuration-reference": { + "before": 380, + "after": 810, + "delta": 430 + }, + "hook": { + "before": 33, + "after": 0, + "delta": -33 + }, + "implementation": { + "before": 46174, + "after": 47187, + "delta": 1013 + }, + "instruction": { + "before": 5192, + "after": 5326, + "delta": 134 + }, + "shell-reference": { + "before": 126, + "after": 141, + "delta": 15 + }, + "test": { + "before": 49641, + "after": 52184, + "delta": 2543 + }, + "yaml-or-inline-shell": { + "before": 44, + "after": 31, + "delta": -13 + } + }, + "interpretation": "The raw manifest keeps the complete legacy runtime and counts repository evolution since the pre-M1 baseline. It is a control-plane inventory. It is not the M5 phase diff or the final gate-specific deletion denominator." + }, + "files": [ + { + "path": ".agents/roles/standards-enforcer.md", + "category": "procedure", + "additions": 4, + "deletions": 2 + }, + { + "path": ".agents/roles/verifier.md", + "category": "procedure", + "additions": 11, + "deletions": 20 + }, + { + "path": ".agents/skills/backlog-sweep/SKILL.md", + "category": "procedure", + "additions": 81, + "deletions": 156 + }, + { + "path": ".agents/skills/doc-garden/SKILL.md", + "category": "procedure", + "additions": 4, + "deletions": 4 + }, + { + "path": ".agents/skills/monorepo-import/SKILL.md", + "category": "procedure", + "additions": 6, + "deletions": 5 + }, + { + "path": ".agents/skills/ship/SKILL.md", + "category": "procedure", + "additions": 30, + "deletions": 30 + }, + { + "path": ".claude/commands/autoreview.md", + "category": "procedure", + "additions": 2, + "deletions": 1 + }, + { + "path": ".claude/hooks/session-start.sh", + "category": "hook", + "additions": 0, + "deletions": 7 + }, + { + "path": ".claude/skills/backlog-sweep/SKILL.md", + "category": "procedure", + "additions": 81, + "deletions": 156 + }, + { + "path": ".claude/skills/doc-garden/SKILL.md", + "category": "procedure", + "additions": 4, + "deletions": 4 + }, + { + "path": ".claude/skills/monorepo-import/SKILL.md", + "category": "procedure", + "additions": 6, + "deletions": 5 + }, + { + "path": ".claude/skills/ship/SKILL.md", + "category": "procedure", + "additions": 30, + "deletions": 30 + }, + { + "path": ".github/ISSUE_TEMPLATE/agent-task.yml", + "category": "configuration", + "additions": 1, + "deletions": 3 + }, + { + "path": ".github/workflows/ci.yml", + "category": "configuration", + "additions": 15, + "deletions": 15 + }, + { + "path": ".trunk/hooks/pre-push", + "category": "hook", + "additions": 0, + "deletions": 33 + }, + { + "path": ".trunk/trunk.yaml", + "category": "configuration", + "additions": 0, + "deletions": 12 + }, + { + "path": "AGENTS.md", + "category": "procedure", + "additions": 4, + "deletions": 4 + }, + { + "path": "README.md", + "category": "procedure", + "additions": 11, + "deletions": 10 + }, + { + "path": "alerts/AGENTS.md", + "category": "procedure", + "additions": 3, + "deletions": 2 + }, + { + "path": "docs/PLAN-progressive-verification-graph.html", + "category": "doc", + "additions": 33, + "deletions": 29 + }, + { + "path": "docs/PLAN-progressive-verification-graph.md", + "category": "doc", + "additions": 65, + "deletions": 52 + }, + { + "path": "docs/adr/0007-agent-quality-gate-and-merge-oracle.md", + "category": "doc", + "additions": 11, + "deletions": 6 + }, + { + "path": "docs/adr/0033-adr-process-and-gate.md", + "category": "doc", + "additions": 11, + "deletions": 9 + }, + { + "path": "docs/adr/0064-scripts-module-directories.md", + "category": "doc", + "additions": 7, + "deletions": 6 + }, + { + "path": "docs/adr/0069-gate-routing-table-as-data.md", + "category": "doc", + "additions": 27, + "deletions": 81 + }, + { + "path": "docs/adr/0073-guardrail-prose-pinned-in-ci.md", + "category": "doc", + "additions": 6, + "deletions": 5 + }, + { + "path": "docs/adr/0076-fair-quality-gate-coordinator.md", + "category": "doc", + "additions": 16, + "deletions": 58 + }, + { + "path": "docs/adr/0077-operator-triggered-backlog-sweep.md", + "category": "doc", + "additions": 24, + "deletions": 32 + }, + { + "path": "docs/adr/0078-staged-verification-redesign.md", + "category": "doc", + "additions": 16, + "deletions": 10 + }, + { + "path": "docs/adr/0080-merge-base-freshness-stamp.md", + "category": "doc", + "additions": 5, + "deletions": 3 + }, + { + "path": "docs/metrics/verification-redesign-safeguards.jsonl", + "category": "doc", + "additions": 14, + "deletions": 13 + }, + { + "path": "docs/notes/agent-quality-gate-mechanics.md", + "category": "procedure", + "additions": 64, + "deletions": 52 + }, + { + "path": "docs/notes/backlog-sweep.md", + "category": "procedure", + "additions": 50, + "deletions": 61 + }, + { + "path": "docs/notes/codex-agent-skills.md", + "category": "procedure", + "additions": 11, + "deletions": 9 + }, + { + "path": "docs/notes/codex-cloud-setup.md", + "category": "procedure", + "additions": 3, + "deletions": 3 + }, + { + "path": "docs/notes/dashboard-verification.md", + "category": "procedure", + "additions": 15, + "deletions": 12 + }, + { + "path": "docs/notes/peg-monitoring.md", + "category": "procedure", + "additions": 2, + "deletions": 2 + }, + { + "path": "docs/notes/pr-operating-card.md", + "category": "procedure", + "additions": 102, + "deletions": 98 + }, + { + "path": "docs/notes/pr-ready-state.md", + "category": "procedure", + "additions": 9, + "deletions": 12 + }, + { + "path": "docs/notes/quick-commands.md", + "category": "procedure", + "additions": 8, + "deletions": 11 + }, + { + "path": "docs/notes/sentry-triage-pipeline.md", + "category": "procedure", + "additions": 10, + "deletions": 8 + }, + { + "path": "docs/notes/worktree-and-web-setup.md", + "category": "procedure", + "additions": 19, + "deletions": 13 + }, + { + "path": "docs/pr-checklists/architecture-decisions.md", + "category": "procedure", + "additions": 12, + "deletions": 9 + }, + { + "path": "docs/pr-checklists/ci-workflow-gates.md", + "category": "procedure", + "additions": 2, + "deletions": 2 + }, + { + "path": "docs/pr-checklists/code-health.md", + "category": "procedure", + "additions": 15, + "deletions": 17 + }, + { + "path": "docs/pr-checklists/indexer-handler-invariants.md", + "category": "procedure", + "additions": 3, + "deletions": 3 + }, + { + "path": "docs/pr-checklists/recurring-review-patterns.md", + "category": "procedure", + "additions": 18, + "deletions": 10 + }, + { + "path": "docs/pr-checklists/review-prompt-exclusions.md", + "category": "procedure", + "additions": 6, + "deletions": 5 + }, + { + "path": "docs/terraform.md", + "category": "procedure", + "additions": 4, + "deletions": 3 + }, + { + "path": "governance-watchdog/ADDING_EVENTS.md", + "category": "procedure", + "additions": 4, + "deletions": 2 + }, + { + "path": "indexer-envio/AGENTS.md", + "category": "procedure", + "additions": 8, + "deletions": 3 + }, + { + "path": "indexer-envio/README.md", + "category": "procedure", + "additions": 4, + "deletions": 3 + }, + { + "path": "scripts/AGENTS.md", + "category": "procedure", + "additions": 13, + "deletions": 14 + }, + { + "path": "scripts/agent-autoreview.mjs", + "category": "check", + "additions": 1, + "deletions": 1 + }, + { + "path": "scripts/agent-autoreview.test.sh", + "category": "test", + "additions": 1, + "deletions": 1 + }, + { + "path": "scripts/agent-quality-gate.sh", + "category": "check", + "additions": 48, + "deletions": 48 + }, + { + "path": "scripts/agent-quality-gate.test.sh", + "category": "test", + "additions": 35, + "deletions": 114 + }, + { + "path": "scripts/bootstrap/agent-setup-contract.test.sh", + "category": "test", + "additions": 37, + "deletions": 0 + }, + { + "path": "scripts/bootstrap/claude-code-web-setup.sh", + "category": "check", + "additions": 2, + "deletions": 3 + }, + { + "path": "scripts/bootstrap/codex-cloud-maintenance.sh", + "category": "check", + "additions": 0, + "deletions": 1 + }, + { + "path": "scripts/bootstrap/codex-cloud-setup.sh", + "category": "check", + "additions": 0, + "deletions": 1 + }, + { + "path": "scripts/docs/check-verification-redesign-evidence.mjs", + "category": "check", + "additions": 45, + "deletions": 5 + }, + { + "path": "scripts/docs/check-verification-redesign-evidence.test.mjs", + "category": "test", + "additions": 116, + "deletions": 1 + }, + { + "path": "scripts/docs/docs-garden-issue-helpers.mjs", + "category": "check", + "additions": 1, + "deletions": 3 + }, + { + "path": "scripts/docs/docs-garden-issue.test.mjs", + "category": "test", + "additions": 3, + "deletions": 2 + }, + { + "path": "scripts/gate/mapping/shell-quote.mjs", + "category": "check", + "additions": 3, + "deletions": 3 + }, + { + "path": "scripts/gate/routing-table/arms-scripts.mjs", + "category": "check", + "additions": 1, + "deletions": 1 + }, + { + "path": "scripts/gate/routing-table/index.mjs", + "category": "check", + "additions": 1, + "deletions": 1 + }, + { + "path": "scripts/pr/review-materiality.mjs", + "category": "check", + "additions": 4, + "deletions": 4 + }, + { + "path": "scripts/pr/review-materiality.test.mjs", + "category": "test", + "additions": 5, + "deletions": 1 + }, + { + "path": "scripts/repo-health/check-guardrail-prose.test.mjs", + "category": "test", + "additions": 5, + "deletions": 2 + }, + { + "path": "scripts/repo-health/guardrail-prose.json", + "category": "configuration", + "additions": 67, + "deletions": 1 + }, + { + "path": "scripts/setup.sh", + "category": "check", + "additions": 1, + "deletions": 10 + }, + { + "path": "scripts/workflows/check-no-skip-audit.test.mjs", + "category": "test", + "additions": 2, + "deletions": 2 + }, + { + "path": "shared-config/AGENTS.md", + "category": "procedure", + "additions": 7, + "deletions": 5 + } + ], + "totals": { + "procedure": { + "additions": 666, + "deletions": 786, + "net": -120 + }, + "check": { + "additions": 107, + "deletions": 81, + "net": 26 + }, + "configuration": { + "additions": 83, + "deletions": 31, + "net": 52 + }, + "hook": { + "additions": 0, + "deletions": 40, + "net": -40 + }, + "doc": { + "additions": 235, + "deletions": 304, + "net": -69 + }, + "test": { + "additions": 204, + "deletions": 123, + "net": 81 + }, + "all": { + "additions": 1295, + "deletions": 1365, + "net": -70 + } + }, + "replacementSpecific": { + "definition": "The M5 replacement is a direct author procedure plus focused static checks. Procedure, check, configuration, and hook additions count as implementation. Architecture, plan, and evidence prose count as documentation.", + "implementationAdditions": { + "procedure": 666, + "check": 107, + "configuration": 83, + "hook": 0, + "total": 856 + }, + "testAdditions": 204, + "documentationAdditions": 235, + "testToImplementationRatio": 0.2383, + "replacementControlPlaneNetDeletion": { + "definition": "Procedure, check, configuration, hook, and test lines. Architecture, plan, and evidence prose do not enter this result.", + "additions": 1060, + "deletions": 1061, + "net": -1, + "additionsBelowDeletions": true, + "statement": "The budgeted M5 replacement control plane deletes 1 more line than it adds." + }, + "phaseScopedNetDeletion": { + "additions": 1295, + "deletions": 1365, + "net": -70, + "additionsBelowDeletions": true, + "statement": "The M5 phase-scoped diff deletes 70 more lines than it adds." + }, + "limits": { + "newOrchestrationScripts": [], + "newServices": [], + "newReplacementImplementationFiles": [], + "newReplacementImplementationFilesOver500Lines": [], + "generatedReceiptPathsExcludedFromReplacementFileLimit": [ + "docs/metrics/verification-redesign-control-plane-after.json", + "docs/metrics/verification-redesign-m5-complexity.json" + ], + "twiceImplementationAdditions": 1712, + "testAdditionsUnderTwiceImplementationAdditions": true + } + }, + "removedLocalAutomation": { + "trackedPrePushHookRemoved": true, + "trunkPrePushActionRemoved": true, + "hostedSetupFreshnessRequirementRemoved": true, + "replacementPrePushAdded": false, + "stagedPreCommitFormattingRetained": true + }, + "forbiddenMechanisms": [], + "phaseClaim": { + "mode": "early-local-cutover", + "localCutoverActive": true, + "legacyGateRuntimeRetained": true, + "legacyRequiredCiRetained": true, + "claimsPostCutoverCanaryComplete": false, + "claimsFinalDeletionDenominator": false, + "claimsFinal80PercentDeletion": false, + "statement": "M5 removes mandatory repository verification from local push. The direct author-check table and required CI become the normal path. Issue #2128 owns the 10-PR, seven-day canary, source allocation, final denominator, and any later deletion approval." + }, + "evidence": { + "humanApproval": "https://github.com/mento-protocol/monitoring-monorepo/issues/2127#issuecomment-5507740185", + "rulesetBefore": "https://github.com/mento-protocol/monitoring-monorepo/issues/2127#issuecomment-5507910457", + "rulesetAfter": "https://github.com/mento-protocol/monitoring-monorepo/issues/2127#issuecomment-5507919323", + "prerequisiteReceipt": "https://github.com/mento-protocol/monitoring-monorepo/issues/2127#issuecomment-5511541326", + "graphPinPr": 2218, + "graphPinMergeSha": "3597a3f21ba52071544302d94c55a558064af4ee", + "protectedMainRun": 33637419758, + "protectedMainRunConclusion": "success", + "currentBaseProtection": { + "rulesetId": 13494367, + "strictRequiredStatusChecksPolicy": true, + "requiredContexts": [ + { + "context": "Vercel", + "integrationId": 8329 + }, + { + "context": "Vercel Preview Comments", + "integrationId": 8329 + }, + { + "context": "Code Quality", + "integrationId": 15368 + }, + { + "context": "ci", + "integrationId": 15368 + }, + { + "context": "Sentry suites", + "integrationId": 15368 + } + ] + } + } +} diff --git a/docs/metrics/verification-redesign-safeguards.jsonl b/docs/metrics/verification-redesign-safeguards.jsonl index 0eff303ee..2efedd73a 100644 --- a/docs/metrics/verification-redesign-safeguards.jsonl +++ b/docs/metrics/verification-redesign-safeguards.jsonl @@ -1,18 +1,19 @@ -{"kind":"metadata","schema_version":1,"reviewed_at":"2026-09-01","baseline_source_sha":"a5692c4570d7fe33255c2ce863d7f79264a9ddb0","owner":"eng","risk_classes":[1,2,3,4,5,6,7,8,9,10,11,12,13]} +{"kind":"metadata","schema_version":1,"reviewed_at":"2026-09-02","baseline_source_sha":"a5692c4570d7fe33255c2ce863d7f79264a9ddb0","owner":"eng","risk_classes":[1,2,3,4,5,6,7,8,9,10,11,12,13]} {"kind":"safeguard","id":"local.gate.entry","category":"gate-command","name":"Mapped local quality-gate entry point","sources":["scripts/agent-quality-gate.sh","package.json#agent:quality-gate"],"risk_classes":[1,2,3,4,5,6,7,8,9,12,13],"owner":"eng","disposition":"deferred-with-owner","follow_up":"#2127 keeps it diagnostic; #2128 decides deletion after soak"} {"kind":"safeguard","id":"local.gate.routing","category":"gate-command","name":"Changed-path routing table and mapping engine","sources":["scripts/gate/routing-table/**","scripts/gate/mapping.mjs","scripts/gate/mapping/**"],"risk_classes":[1,2,3,4,5,6,7,8,9,13],"owner":"eng","disposition":"deferred-with-owner","follow_up":"#2128 retires gate-only routing after #2125's fixed CI filter contract and the cutover evidence pass"} {"kind":"safeguard","id":"local.gate.executor","category":"gate-command","name":"Mapped command execution, timeout, and result handling","sources":["scripts/agent-quality-gate.sh","scripts/gate/run-handles.sh"],"risk_classes":[1,2,3,4,5,7,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"#2128 classifies by retained consumer before deletion"} {"kind":"safeguard","id":"local.gate.coordinator","category":"gate-command","name":"Weighted coordinator, worktree admission, and legacy run.lock","sources":["scripts/gate/quality-gate-coordinator*.mjs","scripts/gate/quality-gate-coordinator*.sh"],"risk_classes":[4,5,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"#2128 removes only after the mixed-worktree transition and post-cutover soak"} -{"kind":"safeguard","id":"local.gate.freshness","category":"gate-command","name":"Freshness stamps and exact-result reuse","sources":["scripts/agent-quality-gate.sh","scripts/gate/quality-gate-coordinator-results.mjs"],"risk_classes":[1,2,3,7,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"#2032 remains independent while the gate is mandatory; #2128 records final retirement evidence"} -{"kind":"safeguard","id":"local.gate.process-drain","category":"process-safety","name":"Process identity, descendant drain, and recovery evidence","sources":["scripts/agent-quality-gate.sh","scripts/gate/run-handles.sh","scripts/gate/quality-gate-coordinator-drain.mjs"],"risk_classes":[4,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"PR #2131 closed #2042 at terminal commit e0346ec4756f9577bcbb1e13e06566ccc507e9e4; PR #2134 advanced gate-specific drain recovery to pre-M1 source a5692c4570d7fe33255c2ce863d7f79264a9ddb0; #2127 and #2128 re-audit current code by consumer before cutover or deletion"} -{"kind":"safeguard","id":"local.gate.shared-resources","category":"shared-resource","name":"Browser port, Playwright store, Terraform cache, and all-capacity barriers","sources":["docs/adr/0076-fair-quality-gate-coordinator.md","scripts/gate/quality-gate-coordinator-policy.mjs"],"risk_classes":[4,5,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"#2127 removes automatic local consumers; #2128 deletes only unused coordination"} +{"kind":"safeguard","id":"local.gate.freshness","category":"gate-command","name":"Freshness stamps and exact-result reuse","sources":["scripts/agent-quality-gate.sh","scripts/gate/quality-gate-coordinator-results.mjs"],"risk_classes":[1,2,3,7,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"M5 removes every automatic consumer; #2128 records final diagnostic retirement evidence"} +{"kind":"safeguard","id":"local.gate.process-drain","category":"process-safety","name":"Process identity, descendant drain, and recovery evidence","sources":["scripts/agent-quality-gate.sh","scripts/gate/run-handles.sh","scripts/gate/quality-gate-coordinator-drain.mjs"],"risk_classes":[4,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"PR #2131 closed #2042 at terminal commit e0346ec4756f9577bcbb1e13e06566ccc507e9e4; PR #2134 advanced gate-specific drain recovery to pre-M1 source a5692c4570d7fe33255c2ce863d7f79264a9ddb0; M5 keeps this diagnostic-only family unchanged, and #2128 re-audits current code by consumer before deletion"} +{"kind":"safeguard","id":"local.gate.shared-resources","category":"shared-resource","name":"Browser port, Playwright store, Terraform cache, and all-capacity barriers","sources":["docs/adr/0076-fair-quality-gate-coordinator.md","scripts/gate/quality-gate-coordinator-policy.mjs"],"risk_classes":[4,5,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"M5 removes automatic local consumers; #2128 deletes only unused coordination"} {"kind":"safeguard","id":"local.gate.self-tests","category":"gate-test","name":"Gate, coordinator, mapping, and routing regression suites","sources":["scripts/agent-quality-gate.test.sh","scripts/gate/**/*.test.mjs","package.json#agent:quality-gate:test"],"risk_classes":[12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"#2128 deletes tests only with their retired subject and retains shared-consumer tests"} {"kind":"safeguard","id":"local.gate.prewarm","category":"gate-command","name":"Gate-plan prewarm consumer","sources":["scripts/gate/agent-prewarm.mjs","scripts/gate/agent-prewarm.test.mjs","package.json#agent:prewarm"],"risk_classes":[1,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"#2128 deletes it with the local selector unless an independent consumer is proved"} -{"kind":"safeguard","id":"local.hook.prepush","category":"hook","name":"Mandatory pre-push quality-gate hook","sources":[".trunk/trunk.yaml",".trunk/hooks/pre-push"],"risk_classes":[1,2,3,4,5,6,7,8,9,12,13],"owner":"eng","disposition":"deferred-with-owner","follow_up":"#2127 removes repository verification only after shadow evidence and human approval"} +{"kind":"safeguard","id":"local.hook.prepush","category":"hook","name":"Retired mandatory pre-push quality-gate hook","sources":[".trunk/trunk.yaml",".trunk/hooks/pre-push","docs/adr/0078-staged-verification-redesign.md"],"risk_classes":[1,2,3,4,5,6,7,8,9,12,13],"owner":"eng","disposition":"obsolete-with-evidence","evidence":"The operator approved M5 early cutover on #2127. M5 deletes the tracked hook and Trunk action after #2218 merge commit 3597a3f21ba52071544302d94c55a558064af4ee passed protected-main CI run 33637419758."} {"kind":"safeguard","id":"local.hook.precommit","category":"hook","name":"Staged-file Trunk formatter","sources":[".trunk/trunk.yaml",".trunk/hooks/pre-commit"],"risk_classes":[1],"owner":"eng","disposition":"retained-author-procedure","entry_point":"Trunk staged-file pre-commit formatter"} +{"kind":"safeguard","id":"local.author-checks","category":"author-procedure","name":"Bounded direct author-check trigger table","sources":["docs/notes/pr-operating-card.md",".agents/skills/ship/SKILL.md",".claude/skills/ship/SKILL.md","scripts/repo-health/guardrail-prose.json"],"risk_classes":[1,2,3,4,5,6,7,8,9,10,12,13],"owner":"eng","disposition":"retained-author-procedure","entry_point":"PR operating card step 3 through the /ship workflow"} {"kind":"safeguard","id":"local.package-script-pins","category":"package-policy","name":"Trusted aliases and lifecycle-hook validator","sources":["scripts/check-agent-quality-gate-package-scripts.mjs","scripts/bootstrap/agent-setup-contract.test.sh"],"risk_classes":[6,7],"owner":"eng","disposition":"retained-required-ci","entry_point":"CI scripts and docs-checks run the validator before install; CI scripts runs the focused policy contract"} {"kind":"safeguard","id":"workflow.adr-reminder","category":"documentation","name":"ADR reminder for new architectural surfaces","sources":["package.json#adr:check","package.json#adr:check:test","scripts/pr/check-adr-reminder.mjs","scripts/pr/check-adr-reminder.test.mjs","scripts/gate/mapping/facts.mjs","scripts/gate/mapping/verbs.mjs","scripts/gate/routing-table/arms-agent-modules.mjs",".github/workflows/ci.yml#scripts"],"risk_classes":[8,13],"owner":"eng","disposition":"retained-required-ci","entry_point":"CI / Lint + test root scripts runs pnpm adr:check and pnpm adr:check:test"} -{"kind":"safeguard","id":"local.worktree.setup","category":"author-procedure","name":"Worktree setup and core.hooksPath installation","sources":["scripts/setup.sh","scripts/bootstrap/codex-cloud-maintenance.sh","scripts/bootstrap/claude-code-web-setup.sh","scripts/bootstrap/agent-setup-contract.test.sh"],"risk_classes":[7,8,12],"owner":"eng","disposition":"retained-author-procedure","entry_point":"./scripts/setup.sh and hosted setup procedures; CI scripts runs the focused setup contract"} +{"kind":"safeguard","id":"local.worktree.setup","category":"author-procedure","name":"Worktree setup and pre-commit hooksPath installation","sources":["scripts/setup.sh","scripts/bootstrap/codex-cloud-maintenance.sh","scripts/bootstrap/claude-code-web-setup.sh","scripts/bootstrap/agent-setup-contract.test.sh"],"risk_classes":[7,8,12],"owner":"eng","disposition":"retained-author-procedure","entry_point":"./scripts/setup.sh and hosted setup procedures install staged formatting; CI scripts runs the focused setup contract"} {"kind":"safeguard","id":"review.autoreview","category":"review","name":"Fresh-context source review and runtime attestation","sources":["scripts/agent-autoreview.sh","scripts/agent-autoreview.mjs","scripts/agent-autoreview-core.mjs","scripts/agent-autoreview-indexer-invariant-contract.test.mjs","scripts/gate/darwin-process-identity.c","scripts/gate/darwin-process-identity-runtime.inc.c","scripts/gate/darwin-process-identity-helper.mjs","scripts/gate/darwin-process-lineage-model.mjs","scripts/gate/darwin-process-lineage-state.mjs","scripts/gate/darwin-process-lineage.mjs","scripts/gate/mapped-command-process-identity.mjs","docs/notes/pr-operating-card.md"],"risk_classes":[3,6,7,8,10,13],"owner":"eng","disposition":"retained-author-procedure","entry_point":"Ship closeout review and prepared-bundle verification; CI indexer runs the focused owner and schema contract"} {"kind":"safeguard","id":"ci.changes","category":"ci-job","name":"Pinned changed-path classifier","sources":[".github/workflows/ci.yml#changes"],"risk_classes":[1,2,3,4,5,6,7,8,9],"owner":"eng","disposition":"retained-required-ci","entry_point":"CI / Detect changes"} {"kind":"safeguard","id":"ci.shared","category":"ci-job","name":"shared-config type, lint, drift, Knip, and coverage","sources":[".github/workflows/ci.yml#shared"],"risk_classes":[1,2,3,9],"owner":"eng","disposition":"retained-required-ci","entry_point":"CI / Quality Checks (shared-config)"} @@ -39,7 +40,7 @@ {"kind":"safeguard","id":"external.trunk","category":"required-check","name":"Trunk Code Quality","sources":[".github/workflows/trunk.yml",".trunk/trunk.yaml"],"risk_classes":[1,6,7],"owner":"eng","disposition":"retained-required-ci","entry_point":"Required context Code Quality"} {"kind":"safeguard","id":"external.vercel","category":"required-check","name":"Vercel deployment check","sources":["GitHub ruleset 13494367","Vercel Git integration"],"risk_classes":[4,11],"owner":"eng","disposition":"retained-required-ci","entry_point":"Required context Vercel while the live ruleset names it"} {"kind":"safeguard","id":"external.vercel-comments","category":"required-check","name":"Vercel Preview Comments","sources":["GitHub ruleset 13494367","Vercel Git integration"],"risk_classes":[4,10],"owner":"eng","disposition":"retained-required-ci","entry_point":"Required context Vercel Preview Comments while the live ruleset names it"} -{"kind":"safeguard","id":"ruleset.main-structural-controls","category":"merge","name":"Protected-main deletion, non-fast-forward, linear-history, pull-request, and thread-resolution controls","sources":["GitHub ruleset 13494367","docs/metrics/verification-redesign-baseline.json#ruleset.other_rules"],"risk_classes":[6,10],"owner":"eng","disposition":"retained-author-procedure","entry_point":"GitHub protected-main and pull-request merge controls"} +{"kind":"safeguard","id":"ruleset.main-structural-controls","category":"merge","name":"Protected-main current-base, deletion, non-fast-forward, linear-history, pull-request, and thread-resolution controls","sources":["GitHub ruleset 13494367","docs/metrics/verification-redesign-baseline.json#ruleset.other_rules","docs/adr/0078-staged-verification-redesign.md"],"risk_classes":[6,10],"owner":"eng","disposition":"retained-author-procedure","entry_point":"GitHub protected-main and pull-request merge controls with strict required status checks"} {"kind":"safeguard","id":"ci.permission.checks-write","category":"ci-authority-exception","name":"Removed PR package-job checks:write authority","sources":[".github/workflows/ci.yml","scripts/workflows/check-pr-validation-boundary.mjs"],"risk_classes":[6],"owner":"eng","disposition":"obsolete-with-evidence","evidence":"M2 removes the unused grant from all 11 candidate package jobs and pins the absence structurally"} {"kind":"safeguard","id":"ci.secret.codecov","category":"ci-authority-exception","name":"Advisory Codecov token after candidate commands","sources":[".github/workflows/ci.yml","secrets.CODECOV_TOKEN","docs/adr/0078-staged-verification-redesign.md"],"risk_classes":[6,9],"owner":"eng","disposition":"deferred-with-owner","follow_up":"The human operator accepted this exact trusted-contributor exposure on 2026-08-30; later work is required only if the threat model changes"} {"kind":"safeguard","id":"ci.cache.setup-node","category":"ci-cache-exception","name":"Removed implicit setup-node cache saves in PR jobs","sources":[".github/actions/pnpm-install/action.yml",".trunk/setup-ci/action.yaml",".github/workflows/ci.yml",".github/workflows/pr-description.yml",".github/workflows/review-eval-freshness.yml",".github/workflows/supply-chain.yml","scripts/workflows/check-pr-validation-boundary.mjs"],"risk_classes":[6,7],"owner":"eng","disposition":"obsolete-with-evidence","evidence":"M2 disables setup-node caching on every PR-reachable step, including local reusable workflows, and pins the closed contract structurally"} @@ -82,11 +83,11 @@ {"kind":"safeguard","id":"workflow.sentry-triage-archive","category":"deployment","name":"Issue-driven Sentry triage archive operation","sources":[".github/workflows/sentry-triage-archive.yml"],"risk_classes":[6,10,11],"owner":"eng","disposition":"retained-after-merge","entry_point":"Trusted issue close and manual archive operation"} {"kind":"safeguard","id":"workflow.terraform-queue-watch","category":"scheduled-workflow","name":"Terraform deploy-queue expiry watch","sources":[".github/workflows/terraform-deploy-queue-watch.yml"],"risk_classes":[5,11],"owner":"eng","disposition":"scheduled","detection_interval":"daily at 7 6 * * *"} {"kind":"safeguard","id":"workflow.visual-snapshot-update","category":"author-procedure","name":"Explicit visual snapshot update workflow","sources":[".github/workflows/update-snapshots.yml"],"risk_classes":[4,6],"owner":"eng","disposition":"retained-author-procedure","entry_point":"Human-dispatched snapshot rebaseline after reviewed visual evidence"} -{"kind":"safeguard","id":"process.darwin-identity","category":"process-safety","name":"Retained Darwin process identity and coherent lineage","sources":["scripts/gate/darwin-process-identity.c","scripts/gate/darwin-process-identity-runtime.inc.c","scripts/gate/darwin-process-identity-helper.mjs","scripts/gate/darwin-process-identity.test.mjs","scripts/gate/darwin-process-lineage-model.mjs","scripts/gate/darwin-process-lineage-state.mjs","scripts/gate/darwin-process-lineage.mjs","scripts/gate/darwin-process-lineage.test.mjs","scripts/gate/mapped-command-process-identity.mjs","scripts/gate/mapped-command-process-identity.test.mjs"],"risk_classes":[6,12],"owner":"eng","disposition":"retained-required-ci","entry_point":"Autoreview runtime and Sentry process-identity consumers with their required CI suites; #2127 and #2128 re-audit each consumer before any relocation or deletion"} +{"kind":"safeguard","id":"process.darwin-identity","category":"process-safety","name":"Retained Darwin process identity and coherent lineage","sources":["scripts/gate/darwin-process-identity.c","scripts/gate/darwin-process-identity-runtime.inc.c","scripts/gate/darwin-process-identity-helper.mjs","scripts/gate/darwin-process-identity.test.mjs","scripts/gate/darwin-process-lineage-model.mjs","scripts/gate/darwin-process-lineage-state.mjs","scripts/gate/darwin-process-lineage.mjs","scripts/gate/darwin-process-lineage.test.mjs","scripts/gate/mapped-command-process-identity.mjs","scripts/gate/mapped-command-process-identity.test.mjs"],"risk_classes":[6,12],"owner":"eng","disposition":"retained-required-ci","entry_point":"Autoreview and Sentry process-identity consumers remain retained after M5 with their required CI suites; #2128 re-audits them before any relocation or gate-specific deletion"} {"kind":"safeguard","id":"process.autoreview-provenance","category":"process-safety","name":"Autoreview runtime and child provenance","sources":["scripts/agent-autoreview.sh","scripts/agent-autoreview.mjs","scripts/gate/darwin-process-identity.c","scripts/gate/darwin-process-identity-runtime.inc.c","scripts/gate/darwin-process-identity-helper.mjs","scripts/gate/darwin-process-lineage-model.mjs","scripts/gate/darwin-process-lineage-state.mjs","scripts/gate/darwin-process-lineage.mjs","scripts/gate/mapped-command-process-identity.mjs"],"risk_classes":[6,10,12],"owner":"eng","disposition":"retained-author-procedure","entry_point":"Prepared-bundle closeout review; required CI suites retain separate test coverage"} {"kind":"safeguard","id":"process.sentry-verified-leader","category":"process-safety","name":"Sentry detached-group verified-leader rule","sources":["scripts/sentry/broker/**","scripts/sentry/broker/mapped-command-process-identity.mjs","scripts/sentry/ci-wiring/check-sentry-suites-in-ci-gate-extract.mjs","scripts/gate/mapped-command-process-identity.mjs"],"risk_classes":[6,10,12],"owner":"eng","disposition":"retained-required-ci","entry_point":"Sentry broker and Sentry CI wiring suites"} -{"kind":"safeguard","id":"process.trunk-daemon","category":"process-safety","name":"Trunk daemon containment or bounded trusted-service contract","sources":["#2042","PR #2131 terminal commit e0346ec4756f9577bcbb1e13e06566ccc507e9e4",".trunk/trunk.yaml","tools/trunk"],"risk_classes":[1,6,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"Re-audit current pre-M1 source a5692c4570d7fe33255c2ce863d7f79264a9ddb0 for the Trunk consumer before cutover or deletion in #2127 or #2128"} -{"kind":"safeguard","id":"migration.issue-2006","category":"retirement-dependency","name":"Coordinator bottleneck residuals","sources":["#2006","docs/adr/0076-fair-quality-gate-coordinator.md"],"risk_classes":[12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"For #2006, re-audit current pre-M1 source a5692c4570d7fe33255c2ce863d7f79264a9ddb0 by consumer and retain the controlled macOS timeout disposition; do not change #2006 state in Phase 0"} -{"kind":"safeguard","id":"migration.issue-2032","category":"retirement-dependency","name":"Pre-push freshness mismatch","sources":["#2032"],"risk_classes":[1,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"May be fixed while mandatory; #2127 records supersession if cutover makes it obsolete"} -{"kind":"safeguard","id":"migration.issue-2042","category":"retirement-dependency","name":"Self-daemon and trusted-service containment","sources":["#2042","PR #2131 terminal commit e0346ec4756f9577bcbb1e13e06566ccc507e9e4","historical provisional snapshot 8e2965a6ffbd92bcc0c2793a6892754e4c674a6b"],"risk_classes":[6,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"#2127 and #2128 re-audit the terminal commit by consumer before cutover or deletion"} -{"kind":"safeguard","id":"migration.issue-2094","category":"retirement-dependency","name":"Cloud gate self-test support","sources":["#2094"],"risk_classes":[7,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"Still protects mandatory-gate delivery; #2128 records final obsolete evidence if unresolved"} +{"kind":"safeguard","id":"process.trunk-daemon","category":"process-safety","name":"Trunk daemon containment or bounded trusted-service contract","sources":["#2042","PR #2131 terminal commit e0346ec4756f9577bcbb1e13e06566ccc507e9e4",".trunk/trunk.yaml","tools/trunk"],"risk_classes":[1,6,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"M5 keeps the bounded Trunk-check consumer in the callable legacy diagnostic; #2128 re-audits it before deleting gate-specific containment"} +{"kind":"safeguard","id":"migration.issue-2006","category":"retirement-dependency","name":"Coordinator bottleneck residuals","sources":["#2006","docs/adr/0076-fair-quality-gate-coordinator.md"],"risk_classes":[12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"M5 keeps the coordinator for the callable diagnostic; #2128 owns residual retirement after the post-cutover soak and retains the controlled macOS timeout disposition"} +{"kind":"safeguard","id":"migration.issue-2032","category":"retirement-dependency","name":"Pre-push freshness mismatch","sources":["#2032","#2127"],"risk_classes":[1,12],"owner":"eng","disposition":"obsolete-with-evidence","evidence":"M5 removes the only automatic pre-push consumer. The retained diagnostic can still use freshness, but a mismatch no longer blocks a push."} +{"kind":"safeguard","id":"migration.issue-2042","category":"retirement-dependency","name":"Self-daemon and trusted-service containment","sources":["#2042","PR #2131 terminal commit e0346ec4756f9577bcbb1e13e06566ccc507e9e4","historical provisional snapshot 8e2965a6ffbd92bcc0c2793a6892754e4c674a6b"],"risk_classes":[6,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"#2128 re-audits the terminal commit by consumer before deletion"} +{"kind":"safeguard","id":"migration.issue-2094","category":"retirement-dependency","name":"Cloud gate self-test support","sources":["#2094"],"risk_classes":[7,12],"owner":"eng","disposition":"deferred-with-owner","follow_up":"M5 removed mandatory pre-push delivery; #2128 records whether this support has a retained diagnostic consumer or is obsolete at deletion"} diff --git a/docs/notes/agent-quality-gate-mechanics.md b/docs/notes/agent-quality-gate-mechanics.md index fcdf8d7f1..1dc0f92ac 100644 --- a/docs/notes/agent-quality-gate-mechanics.md +++ b/docs/notes/agent-quality-gate-mechanics.md @@ -3,7 +3,7 @@ title: Agent Quality Gate — Mechanics status: active owner: eng canonical: true -last_verified: 2026-09-01 +last_verified: 2026-09-02 doc_type: runbook scope: repo-wide review_interval_days: 90 @@ -12,25 +12,33 @@ garden_lane: operator-runbooks # Agent Quality Gate — Mechanics -This runbook owns gate invocation, path mapping, parallelism, caching, and the -package-script refusal guard. Root `AGENTS.md` routes here. +This runbook owns the retained legacy gate runtime, its path mapping, +parallelism, caching, and package-script refusal guard. Normal delivery uses +the direct author checks in +[`pr-operating-card.md`](pr-operating-card.md#the-loop) plus required CI. +Pre-push starts no repository verification. The complete gate remains callable +as a diagnostic and remains covered in required CI. Issue #2128 owns its +post-cutover observation and retirement receipt. Deletion needs separate human +approval. + +Any pre-push or hosted hook-warm behavior below describes the dormant retained +mode for diagnostic and rollback compatibility. No installed repository hook +invokes that mode after M5. ## Invocation contract -Before opening or updating an agent-authored PR: +For an optional legacy diagnostic: ```bash pnpm agent:quality-gate # inspect mapped commands and checklists pnpm agent:quality-gate --run # execute the safe local mapped commands -pnpm agent:autoreview # required for a non-trivial completed batch -pnpm agent:autoreview:test -- --jobs 1 # sequential full regression closeout for autoreview runtime changes ``` -The local-only gate never deploys or applies Terraform. Run it explicitly; -do not assume the pre-push hook exists. +The local-only diagnostic never deploys or applies Terraform. Run it only when +the retained mapping is useful for diagnosis. It is not an author checkpoint. -The package command and Trunk hook execute `./scripts/agent-quality-gate.sh` -directly. This preserves the script's Bash `-p` startup boundary; it does not +The package command executes `./scripts/agent-quality-gate.sh` directly. This +preserves the script's Bash `-p` startup boundary; it does not grant operating-system privileges. The prologue clears the remaining inherited Bash controls before it resolves a path or parses an argument. Do not invoke the gate as `bash scripts/agent-quality-gate.sh`; that bypasses the shebang boundary. @@ -65,8 +73,7 @@ eligible successes keep per-command stamps, so the later gate can avoid repeating them. Running a command directly proves it but records no per-command stamp. -For a manual full-repository reproduction of the server-side pre-push baseline, -including when hooks are absent or uncertain, use: +For a manual full-repository legacy diagnostic, use: ```bash git fetch origin main:refs/remotes/origin/main @@ -160,8 +167,9 @@ routing-sensitive source, the shared classifier adds the offline scheduled evaluation. Every tracked Markdown change runs `pnpm docs:index --check` and `pnpm docs:navigation-eval:test`. The second command enforces the navigation source budgets that the Markdown-only CI job checks. Review the -output. Then run the local or hosted gate command from step 3 of the -[PR operating card](pr-operating-card.md). +output. This mapping describes the optional retained diagnostic. Normal author +work follows the matching direct checks in step 3 of the +[PR operating card](pr-operating-card.md) and does not invoke the gate. Every non-empty candidate change set also runs the Terraform-stack suite. The gate spells it `pnpm tf:test`, unless a root-tooling `package.json` edit already @@ -2482,12 +2490,12 @@ live fixture. A new fixture whose liveness the suite asserts takes the same `$((RANDOM % 900 + 100))-$$` suffix the lock-race fixtures use, and every scan for it is scoped to that exact name. -The pre-push hook reaches neither bypass. It runs a fixed command line, and -Trunk strips these variables. If coordination fails, the hook exits non-zero. -After the reported recovery or compatibility blocker clears, fetch the hook's -base and warm the matching stamp with `git fetch --quiet origin main && +The dormant pre-push mode reaches neither bypass. It uses a fixed command line, +and Trunk strips these variables. If coordination fails, the mode exits +non-zero. After the reported recovery or compatibility blocker clears, fetch +the old hook base and warm the matching stamp with `git fetch --quiet origin main && ./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main`. A -verified matching success lets the hook's `--skip-if-fresh` path exit before it +verified matching success lets the dormant `--skip-if-fresh` path exit before it registers another request. Set `AGENT_QUALITY_GATE_DEBUG_STAMP=1` to print the active freshness-stamp @@ -2497,7 +2505,7 @@ the v4 `coordinatorContext`. The output therefore follows the active base binding instead of assuming whether it is a tip or merge-base. It prints only the stored identifiers and hashes. It does not print raw environment values. The switch does not change the stamp or stdout. To diagnose a miss, capture the -warm command and the hook's exact fetch-and-run command back to back. The first +warm command and the dormant hook's exact fetch-and-run command back to back. The first changed line names the input that prevented reuse. **Heavy suites form barriers.** Dashboard coverage, its scoped `vitest related` @@ -2569,21 +2577,22 @@ replacement provisioner map to `bash alerts/infra/scripts/fix-webhook-state.test.sh`; the handler test suite also executes that shell fixture in CI. -The [PR operating card](pr-operating-card.md#the-loop) owns ordinary gate and -closeout sequencing. A second `--run` request from another worktree joins the -coordinator. A request from the same worktree waits for that worktree lease. -Before a full gate starts, finish direct validation, dashboard servers, browser -suites, and package-manager work that runs outside the coordinator on the same -machine. Do not start uncoordinated work there until the gate exits. The -coordinator can schedule only registered gate work. An unregistered +The [PR operating card](pr-operating-card.md#the-loop) owns normal direct author +checks and closeout sequencing. When an operator explicitly runs a full legacy +diagnostic, a second `--run` request from another worktree joins the coordinator. +A request from the same worktree waits for that worktree lease. Before the +diagnostic starts, finish dashboard servers, browser suites, and package-manager +work that runs outside the coordinator on the same machine. Do not start +uncoordinated work there until the diagnostic exits. The coordinator can +schedule only registered gate work. An unregistered package-manager process in the same worktree can change `node_modules`. Unregistered validation from another worktree can still starve the scheduled workers. Browser tests and size-limit can rewrite `next-env.d.ts`. Use same-machine spare workers only for read-only work. Run concurrent validation -outside the coordinator only on another machine. Run focused checks first, then -let the gate own the mapped batch. For a non-trivial batch, freeze the card's -scope baseline and run autoreview after the gate. After accepted fixes, rerun -focused checks and autoreview. +outside the coordinator only on another machine. Complete normal direct checks +before an optional diagnostic. For a non-trivial batch, freeze the card's scope +baseline and run autoreview after the applicable direct checks. After accepted +fixes, rerun the affected direct checks and autoreview. **Stage timing and capture deadlines.** The wrapper and helper append best-effort stage JSONL to `.tmp/agent-autoreview/durations.jsonl`; override @@ -2758,8 +2767,9 @@ protected object. Otherwise the command fails closed with the separate-trusted-checkout instruction used for runtime-changing reviews; a wrapper nested anywhere inside the reviewed checkout is never treated as external. The old autoreview -`--parallel-tests` path is removed: the mapped quality gate owns test execution -and isolation. +`--parallel-tests` path is removed. Step 3 of the [PR operating +card](pr-operating-card.md) owns direct author checks; required CI owns merge +admission. The repo command itself is executable code from the active checkout. The committed/pre-change runtime comparisons protect review integrity when the @@ -2807,12 +2817,11 @@ git merge-base --is-ancestor "$base_oid" "$final_head" || exit 1 git merge-base --is-ancestor "$premerge_oid" "$final_head" || exit 1 ``` -Then run the mapped gate against **both** axes, not just the new base: - -```bash -pnpm agent:quality-gate --base "$base_oid" --head HEAD --run -pnpm agent:quality-gate --base "$premerge_oid" --head HEAD --run -``` +Then derive changed paths for both `base_oid..final_head` and +`premerge_oid..final_head`. Apply every direct author-check row selected by +either axis to `final_head`; do not invoke the legacy gate. Record each axis +that selected a check. Run a shared check once because both axes bind to the +same final tree. `base_oid..final_head` shows what the branch adds to the new base. `premerge_oid..final_head` shows what the merge changed about the branch — the axis that catches a resolution which @@ -2957,12 +2966,12 @@ checks, so an external helper must leave no background writer behind. Autoreview answers whether the source bundle contains review findings. It does not prove CLI/API behavior, generated artifacts, deployment/runtime behavior, -or a UI interaction. Keep the mapped quality gate and every applicable browser, -generation, integration, and runtime check in the validation record. The final -PR all-clear still comes from `pnpm pr:ready-state`, not autoreview. +or a UI interaction. Keep every applicable direct author, browser, generation, +integration, and runtime check in the validation record. The final PR all-clear +still comes from `pnpm pr:ready-state`, not autoreview. To classify review depth and likely context-update requirements before or after -the mapped gate, use: +the direct author checks, use: ```bash pnpm agent:review-materiality @@ -2971,9 +2980,9 @@ pnpm agent:review-materiality The command reports `trivial`, `standard`, or `full` materiality from changed path risk and diff size, plus whether the change likely needs AGENTS, README, runbook, checklist, or skill context updates. It is advisory and does not -replace the applicable gate command from step 3 of the -[PR operating card](pr-operating-card.md), -`pnpm agent:autoreview`, or `pnpm pr:ready-state`. +replace the applicable author checks from step 3 of the +[PR operating card](pr-operating-card.md), `pnpm agent:autoreview`, or +`pnpm pr:ready-state`. To warm Turbo's local cache for the Turbo-backed package tasks mapped by the same gate without running deploy, Terraform, mutation, codegen, or install @@ -2991,8 +3000,11 @@ Turbo commands with bounded parallelism too (`--parallel `, default `2`, or concurrent logs do not interleave. The same dashboard `.next` serialization rule applies to prewarm. -The Trunk pre-push hook delegates to this same path-aware gate with -`--parallel 3 --skip-if-fresh --pre-push`. Independent ordinary commands can run +## Dormant pre-push compatibility + +Before M5, the Trunk pre-push hook delegated to this path-aware gate with +`--parallel 3 --skip-if-fresh --pre-push`. The retained diagnostic mode keeps +the same behavior for rollback compatibility. Independent ordinary commands can run concurrently within the global capacity. An all-capacity command runs after the active pool drains. The hook reuses a recent successful manual gate run when the whole-run freshness key is unchanged and the recorded success is no older @@ -3009,8 +3021,8 @@ script/lifecycle diff first, then set both the manual warm run and the hook) so a just-passed acknowledged manual gate can satisfy the `--skip-if-fresh` check. -Hosted setup sets `agent.qualityGate.cloudPrePushRequireFresh=true` in the -repository git config. A hosted pre-push with a fresh exact stamp exits through +Before M5, hosted setup set `agent.qualityGate.cloudPrePushRequireFresh=true` in +the repository git config. A hosted pre-push with a fresh exact stamp exits through the normal freshness path. A cold or invalid stamp exits with status 2 before scheduler registration, lock acquisition, or mapped work. Fetch `origin/main`, run `./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main` as @@ -3019,8 +3031,8 @@ launcher, base, and parallelism match the hook's freshness key. A `pnpm` launcher adds material lifecycle environment values and cannot warm this exact hook stamp. This hook warm does not replace validation against the resolved PR base. A stacked PR must pass its resolved-base gate first, then warm the separate -`origin/main` hook stamp. Local setup leaves this option unset, so a cold local -pre-push still runs the mapped gate. +`origin/main` hook stamp. Before M5, local setup left this option unset, so a +cold local pre-push ran the mapped gate. Coordinator coalescing and retained-result reuse use the complete execution key described above, including HEAD. The leader recomputes it before execution and diff --git a/docs/notes/backlog-sweep.md b/docs/notes/backlog-sweep.md index 9c638af23..75de97fd5 100644 --- a/docs/notes/backlog-sweep.md +++ b/docs/notes/backlog-sweep.md @@ -114,8 +114,8 @@ place a human still reads the batch. ## Roles -**The orchestrator** is the session the operator invoked. It runs no quality -gate, edits no source file, and opens no PR — prohibitions that keep concurrent +**The orchestrator** is the session the operator invoked. It runs no author +check, edits no source file, and opens no PR — prohibitions that keep concurrent workers out of each other's trees, and so bind only while separate workers exist. A runtime that cannot spawn one works the batch sequentially, taking both roles, one issue at a time. Merging is not one of those prohibitions: that @@ -129,8 +129,8 @@ way to notice. Every worker command runs from inside its own clone. `git clone` does not move the shell and a worker can inherit the orchestrator's directory, so a brief -that only says which path to clone into would let setup, the branch, the -edits, and the gate run in the orchestrator's checkout — the tree the whole +that only says which path to clone into would let setup, the branch, the edits, +and the author checks run in the orchestrator's checkout — the tree the whole scheme exists to keep workers out of. A worker's clone path is derived from its issue number, so it is deterministic @@ -138,7 +138,7 @@ and can already exist — an interrupted run leaves one behind, and a released issue can be selected again later. An existing directory is resumed only on proof that it belongs to this sweep — a `.git/sweep-owner` file written immediately after the clone and holding the sweep id, kept inside `.git/` so it -never shows up as untracked state a gate or a push can trip over. The +never shows up as untracked state that blocks validation or shipping. The orchestrator fixes that id once, before the first claim, and gives it to every worker; a clone whose marker was never written cannot be resumed, only abandoned for a fresh path. Remote and branch are not that @@ -152,19 +152,19 @@ suffix. A checkout whose contents have not been established is never deleted; it can hold uncommitted work, and nothing available to the sweep tells that apart from litter. -Every checkout runs `./scripts/setup.sh`, fresh or resumed. That script sets -`core.hooksPath`, so a checkout that only ran `pnpm install` has no pre-push -hook — and a worker there could push without the gate these boundaries forbid -bypassing. The marker is written straight after the clone, so an interruption -between the two leaves an owned checkout with no hooks; rerunning is free, since -the script skips its own work when inputs are unchanged. +Every checkout runs `./scripts/setup.sh`. Before resuming one, inspect +`git status --short`, committed, staged, unstaged, and untracked changes. Review +lifecycle and install effects for any manifest, lockfile, pnpm configuration, +or patch change before setup. Stop if the change set is unclear. Before fresh +setup, fetch and run `git switch --detach origin/main`. Setup prepares the staged +formatter, dependencies, codegen, and browser tools; markers skip unchanged work. The split exists because subagents cannot wait across turns. A subagent that -ends its turn to wait for a gate stalls permanently — nothing re-invokes it, -and the background process it was waiting on has no one left to observe it. So -a worker polls its own gate and push inside the turn that started them, and the -orchestrator exists for the residue: re-invoking a worker that went quiet -anyway, and collecting the facts only workers can see. +ends its turn while an author check is running stalls permanently. Nothing +re-invokes it, and the background process has no one left to record its result. +A worker polls its author checks and push inside the turn that started them. +The orchestrator re-invokes a worker that went quiet and collects the facts +only workers can see. ## Eligibility @@ -219,8 +219,9 @@ An issue enters a batch only when all of the following hold: That label is the repo's existing ownership area ([`agent-issue-workflow.md`](agent-issue-workflow.md)), so "same subsystem" is a lookup rather than a per-batch judgement. Otherwise the second PR pays for - a merge, a re-gate, and a fresh review round caused only by its sibling. - `pkg:tooling` is the one area where a path test replaces that lookup, below. + a merge, repeated author checks, and a fresh review round caused only by its + sibling. `pkg:tooling` is the one area where a path test replaces that + lookup, below. - **Outside its own grooming veto window** — a candidate whose newest _trusted_ `sweep-groomed:` marker comment is less than 12 hours old waits for the next run, whatever version that marker carries, and the report names @@ -367,40 +368,32 @@ usage window. ## Preflight -The orchestrator verifies, before anything is claimed: `origin/main` fetched, a -clean session worktree, working `gh` auth, and that -`git remote get-url --push origin` serves `mento-protocol/monitoring-monorepo`. -It does **not** probe the gate's lock. +Before anything is claimed, the orchestrator verifies a clean session worktree, +working `gh` auth, and that both effective `origin` URLs serve +`mento-protocol/monitoring-monorepo`. It fetches `origin/main` only after these checks pass. +It does not probe or change the legacy gate's lock. A fork checkout is a stop. The operating card refuses every fork head and tells a fork to stop rather than first-publish, and workers inherit this checkout's -remote — so a sweep started from a fork would claim, implement, and gate a +remote — so a sweep started from a fork would claim, implement, and validate a whole batch that can never open a PR. That is the preflight's whole purpose: each check here costs one command, and skipping one fails late, with issues -already claimed and a worker mid-gate. - -That omission is deliberate. Gate `--run` requests share a transient -machine-wide coordinator that admits independent work from different worktrees -under a weighted capacity, and a new gate joins a compatible coordinator rather -than queueing behind it -([`agent-quality-gate-mechanics.md`](agent-quality-gate-mechanics.md)). The -coordinator adopts the legacy `run.lock` while scheduled or recovery work -exists, so `run.lock/owner` names a live pid for as long as anyone on the -machine is gating — hours at a time under ordinary parallel work. A sweep that -treated that record as a busy signal would refuse to start in the normal case. -Local workers wait with `--lock-wait 3600`. Hosted workers use the hook's exact -1,800-second default so the push can reuse the warm stamp. Both waits span -scheduler admission, a command lease, a coalesced result, and an older legacy -holder. No sweep passes `--no-lock` or deletes the lock directory: the gate owns -its reclaim rules, and a record that looks stale from outside is routinely a -live holder inside a long browser suite. +already claimed and a worker mid-validation. + +Workers apply the direct author checks from operating-card step 3 in isolated +checkouts. The batch cap remains the CPU and memory bound. Run no more than +three ordinary command-heavy check sets at once. Run dashboard coverage or +scoped related tests, browser work, production builds, and size-limit work +alone. Other workers can keep editing. A browser check that finds its fixed +port in use fails and reports the conflict. It never waits for, stops, or +reuses another process. ## Resilience duties These belong to the orchestrator, and they are what makes an unattended run survive the night: -- **Wake a quiet worker.** Workers poll their own gate and push in-turn, so the +- **Wake a quiet worker.** Workers poll their own author checks and push in-turn, so the orchestrator carries no timers and never learns a worker's pids. Its duty is the residue: a worker parked at a turn end, or silent while its siblings advance, gets a message naming where it stopped and what comes next. @@ -409,17 +402,16 @@ survive the night: operator-decision items, and any checkout conflict — exist only inside a worker's turn. The orchestrator records each closing message as it arrives and asks for what is missing before writing the report. -- **Gate concurrency within the coordinator's capacity.** Worker gates are - scheduled by the gate coordinator and count against its capacity, 3 by - default, so a batch of 4 runs at most three at once. Non-gate worker work - stays outside the coordinator, which is safe on the `node_modules` axis - because no two workers share a checkout, and bounded on CPU and memory only - by the batch cap and that capacity. +- **Author-check concurrency stays bounded.** A batch of four runs at most + three ordinary command-heavy check sets at once. Dashboard coverage or scoped + related tests, browser work, production builds, and size-limit work run alone. + Other workers can keep editing. Each worker owns its checkout, so no + package-manager process can recreate or invalidate another's `node_modules`. - **Serialized instructions.** One checkout per worker, and no instruction ever names another worker's path. - **Resume, never restart, after a usage-limit interruption.** The worker's clone still holds its branch, its claim, and often an open PR. A restart - re-claims an issue already `agent-active`, re-runs a passed gate, and can + re-claims an issue already `agent-active`, repeats completed author checks, and can open a second PR on the same branch. The orchestrator also records each worker's allocated clone path and hands it back on any respawn: a worker displaced to a suffixed path cannot recognise its own checkout from the @@ -468,13 +460,10 @@ oid="$(git rev-parse FETCH_HEAD)" # the commit this fetch just wrote git rev-parse "$oid:" # one blob or tree id; non-zero when absent ``` -Fetch the validated push URL, not the remote name. Preflight grades -`git remote get-url --push origin`, and a remote that carries a `pushurl` -fetches from a different URL than it pushes to, so `git fetch origin main` -would resolve every path in the pass against a URL no check ever read. Naming -the validated URL binds the read to the repository Preflight approved, and it -leaves Preflight one check on one URL — the check the fork stop needs — rather -than a second check whose only reader is this pass. +Fetch the validated push URL, not the remote name. Preflight verifies both +effective `origin` URLs. A remote that carries a `pushurl` fetches from a +different URL than it pushes to, so naming the validated push URL here binds +this later tree read to the canonical repository the sweep publishes to. Pin `FETCH_HEAD`, not `origin/main`. Every fetch writes the commit it fetched there, while a fetch by URL updates no remote-tracking ref at all and a clone @@ -750,12 +739,12 @@ while it runs: - **Never weaken or widen a control that blocks the run.** Root [`AGENTS.md`](../../AGENTS.md) states it, and the hand-off procedure and its one narrow exception are in the - [operating card](pr-operating-card.md). A gate refusal, a failing hook, a - denied permission, or a sandbox block is reported and handed to an independent - session. Reclassifying the blocking change as a separate task does not - qualify. -- **Never bypass hooks.** No `--no-verify`, no hook-skipping environment - variable, no push that dodges the pre-push gate. + [operating card](pr-operating-card.md). A required author-check or CI failure, + a failing hook, a denied permission, or a sandbox block is reported and + handed to an independent session. Reclassifying the blocking change as a + separate task does not qualify. +- **Never bypass retained hooks.** No `--no-verify` or hook-skipping environment + variable. - **Release a bad pick honestly.** A misgroomed issue, or a worker that stalls before opening a PR, runs `pnpm issue:release --issue --claim-id ` — add diff --git a/docs/notes/codex-agent-skills.md b/docs/notes/codex-agent-skills.md index f4b4806da..ede32b7ac 100644 --- a/docs/notes/codex-agent-skills.md +++ b/docs/notes/codex-agent-skills.md @@ -3,7 +3,7 @@ title: Codex Agent Skills status: active owner: eng canonical: true -last_verified: 2026-08-26 +last_verified: 2026-09-02 doc_type: runbook scope: repo-wide review_interval_days: 90 @@ -56,7 +56,8 @@ The target-selection, engine-isolation, sensitive-input, runtime-trust, prepared-bundle, and runtime-changing-PR contracts live in [`agent-quality-gate-mechanics.md`](agent-quality-gate-mechanics.md). Keep that note as their single owner instead of copying implementation details here. -Autoreview is source review only: mapped quality gates, browser checks, +Autoreview is source review only. The direct author checks selected by step 3 +of the [PR operating card](pr-operating-card.md), browser checks, generated-artifact checks, runtime verification, and final PR readiness remain separate. @@ -118,9 +119,9 @@ actual rule is not. ## Codex Cloud routing -Codex Cloud does not inherit a developer's local `~/.agents`, `~/.codex`, or -`~/.claude` directories. Configure the environment setup and optional -maintenance scripts as: +Codex Cloud does not inherit local agent directories. On a trusted canonical +branch under the [bootstrap boundary](worktree-and-web-setup.md#bootstrap-trust-boundary), +configure setup and optional maintenance as: ```bash ./scripts/bootstrap/codex-cloud-setup.sh @@ -136,8 +137,8 @@ and maintenance behavior live in The repo-local `ship` and `babysit-pr` skills under `.agents/skills/` have exact `.claude/skills/` mirrors. They preserve the familiar workflow names while -backing behavior with repo-visible commands such as `pnpm agent:quality-gate`, -`pnpm agent:autoreview`, and `pnpm pr:ready-state`. +backing behavior with the repo-visible PR operating card and commands such as +`pnpm agent:autoreview` and `pnpm pr:ready-state`. The `doc-garden` skill uses the same exact-mirror contract. It turns a generated bounded packet into evidence-backed dispositions, guarded semantic edits, @@ -165,8 +166,9 @@ report contract live in [`backlog-sweep.md`](backlog-sweep.md). The `.agents/skills/` ↔ `.claude/skills/` mirror is enforced, not just documented: `scripts/repo-health/check-skills-mirror.mjs` byte-compares the two -trees and fails on any drift, and the Agent Quality Gate runs it automatically -whenever either tree changes. Symlinking the trees was rejected — repo files +trees and fails on any drift. The optional legacy gate also selects it for +those changes. Symlinking the trees was +rejected — repo files pushed via the GitHub Contents API and hosted/web checkouts are not guaranteed to preserve symlinks, so a check script is the safer default. Run `node scripts/repo-health/check-skills-mirror.mjs` after editing either copy. diff --git a/docs/notes/codex-cloud-setup.md b/docs/notes/codex-cloud-setup.md index 54c7677f5..0ee35cb1f 100644 --- a/docs/notes/codex-cloud-setup.md +++ b/docs/notes/codex-cloud-setup.md @@ -12,9 +12,9 @@ garden_lane: operator-runbooks # Codex Cloud Setup and Maintenance -Codex Cloud does not inherit a developer's local `~/.agents`, `~/.codex`, or -`~/.claude` directories. Configure the environment setup script and optional -cached-container maintenance script as: +Codex Cloud does not inherit local agent directories. On a trusted canonical +branch under the [bootstrap boundary](worktree-and-web-setup.md#bootstrap-trust-boundary), +configure setup and optional cached-container maintenance as: ```bash ./scripts/bootstrap/codex-cloud-setup.sh diff --git a/docs/notes/dashboard-verification.md b/docs/notes/dashboard-verification.md index 3b30ecd6a..a5ab750a6 100644 --- a/docs/notes/dashboard-verification.md +++ b/docs/notes/dashboard-verification.md @@ -3,7 +3,7 @@ title: Dashboard Local and Browser Verification status: active owner: eng canonical: true -last_verified: 2026-08-25 +last_verified: 2026-09-02 doc_type: runbook scope: ui-dashboard review_interval_days: 90 @@ -173,9 +173,9 @@ For `pnpm build` plus `pnpm start`: - The persisted SWR build salt is derived from `VERCEL_DEPLOYMENT_ID ?? VERCEL_GIT_COMMIT_SHA ?? "dev"` and inlined as `NEXT_PUBLIC_SWR_CACHE_BUILD_SALT`. Do not configure the public mirror. The - agent quality gate supplies its own stable local deployment identity for the - build-backed size check, so operator-local Vercel placeholders are ignored on - that path. + optional legacy gate supplies its own stable local deployment identity for + its build-backed size check, so operator-local Vercel placeholders are + ignored on that diagnostic path. - `.next/cache/fetch-cache` survives `next start` restarts; remove it before a true cold-cache measurement. @@ -190,8 +190,8 @@ separately. Non-Sentry 429s and failed GraphQL/API calls are regressions. `.next-fixture`) via `next start`, alongside `tests/browser/fixtures/hasura-fixture-server.mjs`, then runs Playwright under `tests/browser/`. There is no `next dev` server: the build is produced at most -once per gate run (the turbo `test:browser` task `dependsOn` the cached -`fixture-build` task) and reused across re-runs. Direct callers compare the +once per browser-test invocation (the Turbo `test:browser` task `dependsOn` +the cached `fixture-build` task) and reused across re-runs. Direct callers compare the stored Turbo task hash with the current `fixture-build` hash and rebuild stale or unverifiable output. The fixture server publishes an identity over its local source closure, scenario, and response delay; the runner reuses port 3211 only @@ -200,10 +200,10 @@ process on mismatch. Use the package scripts, not a direct `playwright test`, so this preflight runs. The fixture server is the only GraphQL source for these tests; never point it at hosted Hasura/Envio. The app-level harness covers App Router navigation, URL state, hydration, CSP, SWR request -behavior, and real browser focus. On a fresh checkout, install Chromium once -with `pnpm exec playwright install chromium`; the quality gate does this -automatically. The fixture build snapshots and restores `next-env.d.ts` around -the `next build` that rewrites it. +behavior, and real browser focus. The setup script attempts to install +Chromium. On a fresh checkout that still lacks it, run +`pnpm exec playwright install chromium`. The fixture build snapshots and +restores `next-env.d.ts` around the `next build` that rewrites it. The fixture Hasura server listens on a fixed port (`3211`) baked into the build; the Next server port is OS-assigned at runtime. Only the fixture URL, not the @@ -247,8 +247,11 @@ normally be clean because the full-score floor is 100. Fix warnings or use a narrow `// react-doctor-disable-next-line ` with a one-line rationale when a finding is genuinely inapplicable. -Run `pnpm dashboard:react-doctor:diff` from the root for the CI-equivalent diff -scan, `pnpm react-doctor` inside the package for a full scan, and +Run `REACT_DOCTOR_BASE_REF=/ pnpm --filter +@mento-protocol/ui-dashboard react-doctor:diff` for the CI-equivalent scan +against the resolved PR base. The root `pnpm dashboard:react-doctor:diff` alias +hardcodes `origin/main`; use it only for a main-base PR after fetching that +ref. Run `pnpm react-doctor` inside the package for a full scan. Run `pnpm react-doctor:score` for the enforced 100/100 score. The standalone CLI and `react-doctor.config.json` are authoritative even where noisy rules are disabled in ESLint. diff --git a/docs/notes/peg-monitoring.md b/docs/notes/peg-monitoring.md index ffac0d0fd..60894ff5e 100644 --- a/docs/notes/peg-monitoring.md +++ b/docs/notes/peg-monitoring.md @@ -246,8 +246,8 @@ pnpm tf validate alerts-rules (cd alerts/rules && TF_DATA_DIR=.terraform-tf-wrapper terraform test -no-color) ``` -Then run the gate or gates from step 3 of the -[PR operating card](pr-operating-card.md). +Treat these commands as satisfied. Then apply every other matching direct +author check from step 3 of the [PR operating card](pr-operating-card.md). The linter parses map-comprehension `format()` expressions, requires every `mento_peg_*` selector to bind one approved policy version, cross-checks metric diff --git a/docs/notes/pr-operating-card.md b/docs/notes/pr-operating-card.md index d8748fa97..76d0a3de1 100644 --- a/docs/notes/pr-operating-card.md +++ b/docs/notes/pr-operating-card.md @@ -3,7 +3,7 @@ title: PR Operating Card status: active owner: eng canonical: true -last_verified: 2026-09-01 +last_verified: 2026-09-03 doc_type: runbook scope: repo-wide review_interval_days: 90 @@ -22,6 +22,22 @@ even when you never open an authority. ## The loop +**Run the repository preflight first.** Automatic setup can finish before agent +control under a [separate trust boundary](worktree-and-web-setup.md); this +preflight does not attest it. Before step 1 or any repository command, resolve +`CURRENT_REPO`, `BASE_REPO`, the target PR when one exists, `BASE_REMOTE`, +`HEAD_REMOTE`, and the PR base with the exact step 5 rules. Read +`headRepository`, `headRepositoryOwner`, and `isCrossRepository` for an +existing PR. With no PR, require a non-fork checkout whose `origin` serves +`CURRENT_REPO`. Stop on a fork checkout, a cross-repository head, an ambiguous +target, or a failed identity lookup before the agent executes repository code. +Fetch the base only after its repository and remote are bound. Keep these +values as the authority for author checks and publication, and re-read them +before each publication mutation in step 5. Before step 1, inspect resolved-base +and working-tree changes, including untracked files, for package manifests, +package-manager configuration, lockfiles, and patches. Review lifecycle and +install effects before any package-manager command, including the claim command. + 1. **Claim.** Before substantive edits, claim from the ready queue: ```bash @@ -50,84 +66,70 @@ even when you never open an authority. an architecture change that constrains future work records an ADR in the same PR. When a change adds or alters a command, script, env var, hook, or ordered runbook, audit every live entry point and runbook in the same PR. - Adding, renaming, or removing a doc needs `pnpm docs:index --write` in - the same PR, or the gate's `docs:index --check` fails. + After adding, renaming, or removing a doc, or changing its catalog metadata, + run `pnpm docs:index --write` in the same PR or `docs:index --check` fails. Before touching or moving docs, read [`../context-standards.md`](../context-standards.md). -3. **Gate.** Before opening or updating an agent-authored PR, inspect then run - the mapped local-only checks. **Resolve the target and remotes first** when - this run will reach step 5 — the repo-identity preflight in - [`agent-quality-gate-mechanics.md`](agent-quality-gate-mechanics.md) governs - any adapter call that trusts repository identity, and this gate is one. In a - Claude cloud session, where `origin` is a credential-proxy URL that can - never satisfy the canonical-origin requirement, the content-based cloud - binding in - [`github-tooling-surfaces.md`](github-tooling-surfaces.md) replaces that - preflight for every such call — gate, ship, and babysit alike. On a - branch with no PR yet and an unambiguous `origin`, the local checks below are - safe to run first; in a fork or ambiguous-remote checkout they are not, and - step 5's resolution comes before this step rather than after it: - - ```bash - pnpm agent:quality-gate # inspect mapped commands and checklists - pnpm agent:quality-gate --run # execute the safe local mapped commands - ``` - - `--run` maps changed paths to the safe local checks (lint, typecheck, tests, - browser suite) and stamps freshness so a later pre-push `--skip-if-fresh` - cache-hits. Every base ref below lives on the **resolved base remote** — - `BASE_REMOTE` from step 5's resolution when it ran first, plain `origin` - only in the non-fork single-remote case above; in a fork checkout `origin` - serves the fork, so an `origin/...` base diffs the wrong repository and - real changes skip their mapped checks. Fetch every base the gate will diff - against first — `git fetch main`, plus `` for a - stacked PR, whose tracking ref is otherwise stale or absent: an unfetched - base diffs against history the branch has already moved past, and the hook - fetches before it runs the gate in any case. The freshness stamp binds the - **merge-base**, not the base tip, so an advance of `main` that leaves the - merge-base alone keeps a warm stamp; a rebase moves the merge-base and - still costs a full re-run. That applies only to plans that never read the - base: a plan naming the base ref or its tip — `react-doctor:diff`, the ADR - reminder, and the peg registry check — keeps tip binding, so any base - advance re-runs it. A bare invocation - diffs against `origin/main`; a fork checkout must pass - `--base /main`, and a stacked PR (base not `main`) must - resolve `baseRefName` and pass `--base /` — a - child change that reverses a parent-introduced path can vanish from the - `main`-based diff, scheduling no checks for it. It does not run `trunk fmt` — run - `./tools/trunk fmt` (the checked-in launcher; a global `trunk` may not exist) - before committing so the required Code Quality CI stays green. The gate never - deploys and never applies Terraform. It **refuses package-script, - package-manager, or lockfile changes until their lifecycle risk is reviewed - and explicitly acknowledged** — do not bypass the refusal; review the surface - and pass `--allow-package-script-changes`. Before invoking a full gate, - ensure that no direct validation, dashboard server, or browser suite outside - the coordinator is active on the same machine. From invocation until the - gate exits, do not start uncoordinated work there. Use same-machine spare - workers only for read-only work. Run concurrent validation outside the - coordinator from a fully hydrated checkout on another machine. Concurrent - `--run` gates from different worktrees share weighted machine capacity. The - default capacity is 3. Evidence-backed heavy dashboard commands form fair - barriers and run alone. Requests from the same worktree remain serialized. - Exact matching requests share one exact terminal result. A Trunk-qualified - result reaches active followers but is never retained or - reused. Background the `--run` gate and the `git push`; a 600s foreground - kill discards the freshness stamp. Hosted setup requires this fresh stamp - before pre-push. A cold hosted pre-push exits before scheduler registration - or mapped work. Fetch `origin/main`, then run - `./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main` as an - observable background task. The launcher, base, and parallelism must match - the hook's freshness key. This hook warm does not replace validation against - the resolved PR base. When the resolved base tracking ref is not - `origin/main`, including fork and stacked PRs, run the required resolved-base - gate first. Then warm this separate `origin/main` stamp. Retry the push after - both gates pass. Local setup keeps the normal cold pre-push run. If the hosted - branch has package-script risk, review it first. Then set - `git config agent.qualityGate.allowPackageScriptChanges true` before the warm - run so the hook uses the same acknowledgement. - Authority: - [`agent-quality-gate-mechanics.md`](agent-quality-gate-mechanics.md). +3. **Author checks.** Apply every matching row below after the change is + coherent and before the first ready-for-review publication. Invoke the + existing commands directly. Do not add a selector or wrapper. First run + `./tools/trunk fmt ` on each intended changed file + that exists in the final tree. Use deleted paths and both sides of a rename + to select matching rows, but never pass a missing path to Trunk. Start the + checks only after formatting is complete. + + | Change trigger | Required direct author checks | + | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | Source in a workspace package | Run each script that exists for that package: `pnpm --filter lint`, `pnpm --filter typecheck`, and its normal unit-test command. Governance Watchdog uses `pnpm --filter @mento-protocol/governance-watchdog test:unit`; its generic `test` needs a local service. | + | Dashboard React or client source | Also run `REACT_DOCTOR_BASE_REF= pnpm --filter @mento-protocol/ui-dashboard react-doctor:diff`. | + | Dashboard UI or visual output, route or interaction, browser test, or frontend build/runtime path | Also run `pnpm dashboard:build`, then follow [`dashboard-verification.md`](dashboard-verification.md) for the changed UI or runtime path, console, interaction, breakpoints, and applicable auth states. | + | Dashboard bundle input listed in the `dashboard` path filter in `.github/workflows/size-limit.yml` | When `shared-config/**` changes, first run `pnpm --filter @mento-protocol/config build`. After any required install and shared-config build, run `pnpm dashboard:build`, then `pnpm dashboard:size-limit`. Run a command once if another row also selects it. | + | `metrics-bridge/peg-registry.json`, `shared-config/chain-metadata.json`, `shared-config/deployment-namespaces.json`, `shared-config/oracle-reporters.json`, `shared-config/src/chains.ts`, `shared-config/src/oracle-reporters.ts`, or `shared-config/src/tokens.ts` | Run `node scripts/alerts/check-peg-registry-integrity.mjs --base-ref `. | + | `shared-config/src/thresholds.ts` | Run `node scripts/alerts/check-deviation-threshold-drift.mjs` and `pnpm --filter @mento-protocol/indexer-envio exec vitest run deviationThresholdSharedConfigSync`. | + | Indexer schema, configuration, ABI, entry point, or handler reachability | Run each affected code-generation variant from [`../../indexer-envio/AGENTS.md`](../../indexer-envio/AGENTS.md). Run affected non-mainnet variants first and `pnpm indexer:codegen` last. Inspect the generated diff before indexer package checks. | + | Dashboard GraphQL query or schema consumer, `indexer-envio/schema.graphql`, or `scripts/envio-schema-stubs.graphql` | Run `pnpm dashboard:codegen` and inspect the generated diff. | + | Manifest, lockfile, pnpm configuration, or patch | Inspect lifecycle and install effects. Run `CI=true pnpm install --frozen-lockfile` from the repository root. When one of these inputs changes under `alerts/infra/onchain-event-handler`, `alerts/infra/oncall-announcer`, or `governance-watchdog`, also run `CI=true pnpm install --frozen-lockfile --ignore-scripts --lockfile-dir .` from that root. Complete the installs before code generation or the applicable package rows. | + | Package Vitest configuration or hermetic setup | Run `node scripts/repo-health/check-hermetic-vitest-setup.mjs`. | + | Trunk configuration or local Git hook | Run `./tools/trunk check --ci --all` and `node scripts/workflows/check-github-action-pins.mjs`. Also run `bash scripts/bootstrap/agent-setup-contract.test.sh` when hook or Trunk action behavior changes. | + | Shell file, hosted agent setup, or hook | Run `bash -n` on each surviving changed shell file. Run `bash scripts/bootstrap/agent-setup-contract.test.sh` when hosted setup or hook behavior changes. | + | Agent instruction, role, command, skill, runtime configuration, or catalog-visible document metadata | Run `pnpm agent:context-check`, `pnpm agent:context-budget:test`, and `pnpm agent:context-budget --strict`. Also run `pnpm docs:index --check` after adding, moving, or removing managed context, or changing catalog-visible metadata. | + | Mirrored agent skill content or mirror checker | Run `node scripts/repo-health/check-skills-mirror.mjs` and `node scripts/repo-health/check-skills-mirror.test.mjs`. | + | Guardrail prose pin list or pinned normative text | Run `node scripts/repo-health/check-guardrail-prose.mjs` and `node scripts/repo-health/check-guardrail-prose.test.mjs`. | + | GitHub Actions workflow or action, or protected PR admission boundary | Run `pnpm ci:contract:test`, `node scripts/workflows/check-github-action-pins.mjs`, and `node scripts/workflows/check-autofix-ci-trust.mjs`. | + | `.coderabbit.yaml` | Run `pnpm coderabbit:config:test`. | + | `.lighthouserc.cjs` | Run `node scripts/lighthouse-config.test.mjs`. | + | `.gitignore` | Run `pnpm review:eval:test`. | + | `.gitattributes`, `.codex/config.toml`, or `.codex/upstash-mcp.example.toml` | Run `node --test scripts/mcp/upstash-mcp-config.test.mjs`. | + | `terraform.stacks.json` | Run `pnpm tf:test`. | + | New top-level package/service root with `AGENTS.md` or `package.json`, new workspace package registration, new Terraform stack registration, or new GitHub Actions workflow file | Run `pnpm adr:check --base --include-untracked`. | + | Root tooling, control plane, or standalone service | Run the focused existing contract named by the nearest scoped `AGENTS.md`. Do not add a root selector. | + + Use the resolved PR base, not a fixed `origin/main`, for every diff-based + author check, including stacked PRs. Fetch it before the check. The root + React Doctor alias uses `origin/main`. Use the explicit table command for + any other base. + + Run mutable checks in this order: inspect package-manager changes; run the + frozen install when its row applies; run code generation; run package lint, + typecheck, tests, integrity, and parity checks; run React Doctor, build, + size-limit, and browser checks; then run step 4. Record each applicable + result in the PR's `## Validation` section as `passed`, `failed`, or + `not run: `. + A failed author check blocks the ready handoff. An unavailable tool can be + `not run`; a failed command cannot be relabeled. Required CI remains merge + authority. + + Apply only the rows affected by a material fix before publishing the new + head. Apply the table again after base integration because conflict + resolution creates a new tree. Do not run the table on every commit or + push. Pre-commit keeps staged formatting only. Pre-push starts no repository + check, fetch, lock, or wait. A manual push can omit author checks. It cannot + omit required CI. + + If pre-commit changes any file during commit, stop before push. Apply the + affected author-check rows and step 4 to the committed tree. Do not publish + formatter-changed bytes that the checks and reviewer did not inspect. 4. **Autoreview.** Freeze the scope baseline first — the initial request, target/owner, changed-file set, and non-test changed-line count — as the @@ -167,7 +169,7 @@ even when you never open an authority. post-review check above so bundle replacement or drift during review cannot go undetected. Autoreview reviews the complete branch-local target without truncation, but it is **source review only**: it runs no - tests and proves no behavior, so the mapped gate, browser, + tests and proves no behavior, so the direct author checks, browser, generated-artifact, and runtime checks still apply. One fresh-context reviewer must inspect every prepared-bundle pass, with manifest verification before and after review. Capture, bundle-integrity, @@ -197,7 +199,7 @@ even when you never open an authority. auto-review (`.coderabbit.yaml` keeps `reviews.auto_review.drafts` false) and the `pr-description.yml` CI check, which skips draft PRs; drafting is skipping review, not a staging step. A ship that updates an **existing draft** converts it to ready once - the gate passes — `pr:ready-state` holds draft state as a required blocker, + the author checks and closeout review pass — `pr:ready-state` holds draft state as a required blocker, so an unconverted draft never reaches all-clear. Use or keep draft only when the user asks or required validation is intentionally pending, and state that reason in the body. Link @@ -211,8 +213,9 @@ even when you never open an authority. old Branch. Do not pass `--branch` to review. Authority: [`agent-issue-workflow.md`](agent-issue-workflow.md). - **Resolve the repository identities first.** Before any PR lookup, resolve - the checkout repository and its upstream base — + **Re-read the repository identities.** The preflight before step 1 resolves + the checkout repository and its upstream base. Before any publication + lookup or mutation, resolve them again — `gh repo view --json nameWithOwner,parent` locally, the session-attached repository metadata in a Claude cloud session. `CURRENT_REPO` is the checkout's own repository; a fork checkout uses its parent as `BASE_REPO`, @@ -245,7 +248,8 @@ even when you never open an authority. scan is developer-installed and Claude Code only; this repo does not declare it. Where the diff touches authn/authz, secrets handling, injection surfaces, network-facing handlers, deploy/CI paths, or onchain code and the plugin is - unavailable, aim the gate and the closeout review at those surfaces instead, + unavailable, aim the direct author checks and closeout review at those + surfaces instead, and record `Claude Security scan: skipped ()` in the final summary so the deep pass can be run later from a session that has it. Never imitate or install it to fill the gap. @@ -277,8 +281,8 @@ even when you never open an authority. **Integrating the base produces a new, unvalidated head.** Steps 3-4 ran against the pre-merge tree, so either integrate the base before step 3 or - rerun the gate and the closeout review against the merged head before - pushing. A conflict resolution is exercised, not assumed. + rerun the applicable author checks and the closeout review against the + merged head before pushing. A conflict resolution is exercised, not assumed. Either way, re-read the PR after pushing and require its `headRefOid` to equal local `HEAD` before treating anything as published. A fork checkout @@ -290,9 +294,9 @@ even when you never open an authority. the target as step 5 defines: the target-PR precedence, `BASE_REPO`, both remotes, and `number,url,headRefName,headRefOid,baseRefName,headRepository,headRepositoryOwner,isCrossRepository`. - **Stop a fork head at that resolution, before the first repo-local probe, - gate, or fix** — the `.claude/babysit-pr.sh` refusal at gate time is the - backstop, not the first line. Sweep every feedback + **Stop a fork head at that resolution, before the first repo-local probe or + fix** — the `.claude/babysit-pr.sh` refusal is the backstop, not the first + line. Sweep every feedback surface: top-level comments, review bodies, inline comments and threads, annotations, and failing logs. **Reply before resolving**, on the correct surface, in @@ -324,6 +328,11 @@ even when you never open an authority. attributing it. Chasing an unrelated failure puts unrelated changes on the branch. + After a material fix, rerun the step 3 rows whose inputs or surface changed. + Run step 4 again when its materiality rule applies. Publish the new head only + after each applicable author check is `passed` or truthfully recorded as + `not run: `. + **A user correction updates the request baseline**: update the PR description before the next push, or current-head reviewers enforce the superseded criteria and re-raise findings you already resolved. This and @@ -488,7 +497,7 @@ These bind regardless of which step you are on: [Low-risk rule](agent-issue-workflow.md#low-risk-rule). An evidence-backed won't-fix is not a deferral. - **Never weaken a control that is blocking your own work.** Do not widen, - disable, or soften the quality gate, the sandbox or permission config, branch + disable, or soften the author-check contract, the sandbox or permission config, branch protection, or a safety-boundary rule to unblock the change you are making now — an agent that can widen its own gate has no gate. Stop and hand the control change to an independent session through a brief or an agent-ready @@ -504,19 +513,13 @@ These bind regardless of which step you are on: operator's explicit consent to the specific repair, recorded on the issue or PR, and the repair stays narrowly scoped to restoring the control. It is still reviewed: use the last independently reviewed pre-change runtime for - the gate, or an independent reviewer for the diff. Widening the control + an executable control, or an independent reviewer for the diff. Widening the control beyond the repair, or using this path for anything the control was correctly refusing, is the thing this rule exists to prevent. -- **Package-script, package-manager, and lockfile changes require explicit - acknowledgement** through the gate; never bypass the refusal. -- **Background long `--run` gates and pushes**; do not run them in a 600s - foreground that a kill would truncate, and do not start an uncoordinated - direct validation command, dashboard server, or browser suite alongside a - gate. Use same-machine spare workers only for read-only work. Run concurrent - validation outside the coordinator from another machine. Let the gate - coordinator schedule concurrent gate work. Do not use `--no-lock` to bypass - its capacity, worktree lease, or named resources. +- **Inspect package-script, package-manager, lockfile, and patch changes before + any package-manager command.** Record the applicable author-check results. + Never treat a failed or unavailable command as a pass. - **Secrets are IaC-owned and Terraform apply needs human approval** — plan first, never one-off `gh secret set` / `vercel env add` / `gcloud secrets versions add`. @@ -526,7 +529,8 @@ These bind regardless of which step you are on: | Step | Authority doc | | ------------------------ | -------------------------------------------------------------------------------------------------------------- | | Claim, defer, merge-sync | [`agent-issue-workflow.md`](agent-issue-workflow.md) | -| Gate, autoreview | [`agent-quality-gate-mechanics.md`](agent-quality-gate-mechanics.md) | +| Author checks | step 3 here | +| Autoreview | step 4 here and [`agent-quality-gate-mechanics.md`](agent-quality-gate-mechanics.md) | | Ready-state | [`pr-ready-state.md`](pr-ready-state.md) | | Docs and drift | [`../context-standards.md`](../context-standards.md) | | Ship | steps 2-9 here; entry points in [`codex-agent-skills.md`](codex-agent-skills.md#claude-global-store-shadowing) | diff --git a/docs/notes/pr-ready-state.md b/docs/notes/pr-ready-state.md index 174c447cd..37110c90f 100644 --- a/docs/notes/pr-ready-state.md +++ b/docs/notes/pr-ready-state.md @@ -495,21 +495,18 @@ Field expectations: cycle count before five review-triggered patch cycles are complete. Pause for reclassification before starting a sixth. -3. Before invoking the gate, ensure that no direct validation, dashboard server, - or browser suite outside the coordinator is active on the same machine. - Concurrent `--run` gates from other worktrees can continue through the - coordinator. They share weighted machine capacity. From invocation until - this gate exits, do not start uncoordinated work there. Use same-machine spare - workers only for read-only work. Run the gate or gates from operating-card - step 3. Local PRs and hosted non-fork PRs targeting `origin/main` run one - pass. Hosted fork and stacked PRs run the resolved-base pass and the separate - `origin/main` hook warm. Run validation outside the coordinator from a fully - hydrated checkout on another machine. +3. Apply the direct author-check table from step 3 of the + [operating card](pr-operating-card.md) before the ready handoff. Re-run each + applicable check after a material fix changes its surface. Record every + result in the validation record as the card requires. Do not substitute the + legacy diagnostic gate for these checks. + Use the resolved PR base, not a fixed `origin/main`, for every diff-based + author check, including stacked PRs. 4. For non-trivial behavioral, workflow, security, data-flow, or UI batches, run `pnpm agent:autoreview` as a structured source-review closeout at the batch boundary rather than as an inner loop. Verify accepted findings before - editing and rerun focused checks plus autoreview if those fixes change the - batch. The exact target, prepared-bundle, isolation, and trust contracts live + editing and rerun applicable author checks plus autoreview if those fixes + change the batch. The exact target, prepared-bundle, isolation, and trust contracts live in [`agent-quality-gate-mechanics.md`](agent-quality-gate-mechanics.md); keep behavioral and runtime verification in the validation record. 5. Run the suggested invocation pair above: `pnpm --silent pr:feedback-state` diff --git a/docs/notes/quick-commands.md b/docs/notes/quick-commands.md index b82a382a5..e1d159b31 100644 --- a/docs/notes/quick-commands.md +++ b/docs/notes/quick-commands.md @@ -3,7 +3,7 @@ title: Quick Commands status: active owner: eng canonical: true -last_verified: 2026-09-02 +last_verified: 2026-09-03 doc_type: runbook scope: repo-wide review_interval_days: 90 @@ -45,15 +45,12 @@ pnpm code-health:history # CodeScene-style git history → reports/cod pnpm code-health:duplication # jscpd duplication → reports/jscpd/; advisory, never blocks pnpm code-health:schema-diff # GraphQL breaking-change diff vs origin/main; advisory, never blocks pnpm code-health # Run knip + deps; exclude history + duplication -pnpm agent:quality-gate # Map changed paths to required local checks and PR checklists -pnpm agent:quality-gate --run # Local: run mapped checks; resolve non-main PR bases per operating-card step 3 -./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main # Hosted: warm the hook after resolved-base validation -# Package scripts, package-manager settings, and lockfiles can change install code. Review before acknowledgment: -pnpm agent:quality-gate --run --allow-package-script-changes # Local -git config agent.qualityGate.allowPackageScriptChanges true # Hosted, before the direct warm command +# Normal delivery uses the direct author checks in pr-operating-card step 3. +pnpm agent:quality-gate # Optional legacy diagnostic: inspect its retained mapping +pnpm agent:quality-gate --run # Optional legacy diagnostic: execute its retained mapping pnpm agent:context-check # Validate repo-visible agent instructions, links, and routing pnpm agent:review-materiality # Classify review depth + context-update signals for current diff -pnpm agent:autoreview # Isolated closeout; multi-pass uses --prepare-bundle-dir DIR + a fresh reviewer; gate owns tests +pnpm agent:autoreview # Isolated closeout; multi-pass uses --prepare-bundle-dir DIR + a fresh reviewer; author checks and CI stay separate pnpm agent:autoreview:test # Full regressions; defaults to up to 3 workers with progress + timings pnpm agent:autoreview:test -- --jobs 1 # Sequential full closeout for autoreview runtime changes pnpm agent:autoreview --verify-bundle-dir DIR # Pre-review rehash; retain the printed manifest digest @@ -72,12 +69,12 @@ pnpm docs:navigation-eval -- --validate # Recompute authority, ev pnpm ci:contract:test # Test fixed CI, protected no-skip admission and drift, cache, base, and aggregate contracts bash scripts/bootstrap/agent-setup-contract.test.sh # Test retained SessionEnd, setup-marker, and package-policy behavior node --test scripts/agent-autoreview-indexer-invariant-contract.test.mjs # Test retained indexer autoreview owners and schema -# After M4 reaches main and before each approved proof, read the current immutable inputs: -gh pr view --json number,state,headRefOid,baseRefName,baseRefOid,headRepositoryOwner +# For each approved #2128 post-cutover canary proof, read the current immutable inputs: +gh pr view --repo mento-protocol/monitoring-monorepo --json number,state,headRefOid,baseRefName,baseRefOid,headRepositoryOwner # The audit refuses a stale baseRefOid. Update or rebase the PR branch, then read fresh inputs. # Do not dispatch no-skip for package-execution or evidence-instrument drift. Package drift can use ordinary-force-all evidence. Instrument drift cannot count. # Stop after any run exceeds 45 runner-minutes. Do not exceed 450 cumulative runner-minutes. -gh workflow run no-skip-audit.yml --ref main -f pr_number= -f source_sha= -f base_sha= +gh workflow run no-skip-audit.yml --repo mento-protocol/monitoring-monorepo --ref main -f pr_number= -f source_sha= -f base_sha= pnpm verification:inventory:check # Validate Phase 0 inventory schema, unique IDs, and complete dispositions pnpm verification:manifest:write # Regenerate the terminal pre-M1 gate-rooted control-plane baseline manifest pnpm verification:manifest:check # Recompute and compare the terminal pre-M1 baseline manifest diff --git a/docs/notes/sentry-triage-pipeline.md b/docs/notes/sentry-triage-pipeline.md index 6606f0f2a..e6696a674 100644 --- a/docs/notes/sentry-triage-pipeline.md +++ b/docs/notes/sentry-triage-pipeline.md @@ -3,7 +3,7 @@ title: Sentry Triage Pipeline status: active owner: eng canonical: true -last_verified: 2026-09-01 +last_verified: 2026-09-02 scope: ci/process doc_type: runbook review_interval_days: 90 @@ -796,7 +796,8 @@ wrapper crossed the 600-line soft cap. The guard is part of the wrapper's runtime import closure, so the workflow stages it read-only with the rest — an unstaged guard would be loaded from the agent-writable checkout, which is the whole point of the staging step. It has no suite of its own: the wrapper's suite -covers it, and the quality gate routes the guard's path there. +covers it. Run `node scripts/sentry/triage/sentry-triage-agent-comment.test.mjs` +when the guard changes. The wrapper also **checks the broker process directly**, in the instant before it hands the body to `gh`, because a polled marker lags the death it reports and @@ -2021,14 +2022,15 @@ immediately before its child runs, and the shared checkout is swept afterwards, so a suite that writes there is named even though it can no longer change a verdict. -`scripts/sentry/ci-wiring/check-sentry-suites-in-ci.test.mjs` is the gate's static half and runs +`scripts/sentry/ci-wiring/check-sentry-suites-in-ci.test.mjs` is the Sentry +suite gate's static half and runs as the last step of the same job, after the install it needs for `js-yaml`. It -carries what the gate cannot see: that the gate job still exists, is +carries what the suite gate cannot see: that the gate job still exists, is unconditional, matches ADR 0062's canonical shape key for key, and reaches the required `ci` context; that the one suite the gate does not run (`sentry-provider-contract.test.mjs`, imported by `tf-stacks.test.mjs`) really is run by the unconditional `production-infra-contract` job; and that the local -quality gate's `sentry:*` allowlist stays pinned to exact commands. It parses +legacy gate's `sentry:*` allowlist stays pinned to exact commands. It parses ci.yml rather than searching it, and compares the job by exact equality, so an `if:`, a `continue-on-error:`, a `working-directory:`, an `env:`, a `|| true`, a reordered step or a key nobody has thought of all fail it by name. @@ -2050,9 +2052,9 @@ To run one suite on its own — the gate names the file it failed on — invoke by path, e.g. `node scripts/sentry/triage/sentry-triage-ingest.test.mjs` or `node --test scripts/sentry/broker/sentry-mcp-broker.test.mjs`. -The `pnpm sentry:*:test` aliases still run these suites for interactive use and -in the local pre-push gate; the CI gate is the backstop, and the pin validator -keeps the aliases the local gate trusts safe. +The `pnpm sentry:*:test` aliases run these suites for direct author checks. The +required CI Sentry suite gate is the backstop. The pin validator also keeps the +aliases used by the optional legacy gate safe. ```bash # Read-only previews that require local credentials: diff --git a/docs/notes/worktree-and-web-setup.md b/docs/notes/worktree-and-web-setup.md index 8f3679e5d..b17547b3d 100644 --- a/docs/notes/worktree-and-web-setup.md +++ b/docs/notes/worktree-and-web-setup.md @@ -3,7 +3,7 @@ title: New Worktree / Clone Setup and Claude Code on the Web Setup status: active owner: eng canonical: true -last_verified: 2026-08-28 +last_verified: 2026-09-02 doc_type: runbook scope: repo-wide review_interval_days: 90 @@ -12,13 +12,18 @@ garden_lane: operator-runbooks # New Worktree / Clone Setup and Claude Code on the Web Setup -The invocation pointer lives in the "Agent Tooling and Setup" section of root -`AGENTS.md`. This note holds the underlying mechanics. +## Bootstrap trust boundary + +Setup can run repository code before agent control. Disable automatic setup +before checking out an untrusted, fork, or cross-repository head. If a platform +cannot enforce this order, do not use automatic setup there. Inspect the diff +without execution and apply approved changes on a trusted canonical branch. +The later [repository preflight](pr-operating-card.md) does not attest bootstrap. ## New Worktree / Clone Setup macOS setup requires the Xcode Command Line Tools (`xcode-select --install`) -for the Darwin gate helper. Linux does not need them. +for the optional legacy gate's Darwin helper. Linux does not need them. After creating a new worktree manually or cloning the repo, run: @@ -26,9 +31,9 @@ After creating a new worktree manually or cloning the repo, run: ./scripts/setup.sh ``` -This configures the tracked git hooks, installs dependencies, builds -`shared-config`, and ensures Envio codegen has produced the generated type -facade required for `indexer-envio` TypeScript to compile. It also attempts to +This configures the tracked pre-commit formatting hook, installs dependencies, +builds `shared-config`, and ensures Envio codegen has produced the generated +type facade required for `indexer-envio` TypeScript to compile. It also attempts to install Playwright Chromium for dashboard browser tests. A blocked browser download warns and continues; run `pnpm --filter @mento-protocol/ui-dashboard exec playwright install --with-deps chromium` @@ -50,7 +55,7 @@ Playwright installer marker because `--with-deps` also provisions host libraries there. Fresh per-PR worktrees start warm because `setup.sh`, -`bootstrap-worktree.sh`, and the agent quality gate all point Turbo at one +`bootstrap-worktree.sh`, and the optional legacy gate all point Turbo at one shared local cache directory outside any worktree. The mechanics, the fallback when that directory is unset or unwritable, and the `AGENT_TURBO_SHARED_CACHE=0` opt-out are owned by @@ -107,8 +112,9 @@ the Trusted defaults: `tools/trunk` reads `$TRUNK_CACHE`, else `$XDG_CACHE_HOME/trunk`, else `~/.cache/trunk`, so prewarming only the last one misses a session that sets either override. -- The quality gate classifies that cold-cache 403 as environment-blocked and - skips its Trunk arm instead of hard-failing; a 404 stays a hard failure. See +- The optional legacy gate classifies that cold-cache 403 as + environment-blocked and skips its Trunk arm instead of hard-failing; a 404 + stays a hard failure. See [agent-quality-gate-mechanics.md](agent-quality-gate-mechanics.md). If the container's Node major is older than the repo's `.node-version` (for @@ -135,9 +141,9 @@ denied path in a hosted or sandboxed session. Repo-local `ship` and `babysit-pr` skill adapters live under `.claude/skills/` (mirrored under `.agents/skills/` for Codex), so the familiar `/ship` and -`/babysit-pr` workflows resolve to repo-visible commands (`pnpm -agent:quality-gate`, `pnpm agent:autoreview`, `pnpm pr:ready-state`) without -needing a developer's personal skills present. +`/babysit-pr` workflows resolve to the repo-visible PR operating card, +`pnpm agent:autoreview`, and `pnpm pr:ready-state` without needing a +developer's personal skills present. ### GitHub access in hosted sessions: gh is unreliable diff --git a/docs/pr-checklists/architecture-decisions.md b/docs/pr-checklists/architecture-decisions.md index 04e3753d3..51586df49 100644 --- a/docs/pr-checklists/architecture-decisions.md +++ b/docs/pr-checklists/architecture-decisions.md @@ -3,7 +3,7 @@ title: Architecture Decision Records — when and how status: active owner: eng canonical: true -last_verified: 2026-07-23 +last_verified: 2026-09-02 doc_type: checklist scope: repo-wide review_interval_days: 90 @@ -15,8 +15,8 @@ garden_lane: pr-checklists-process Architectural decisions are recorded as ADRs under [`docs/adr/`](../adr/README.md). This checklist answers the two questions the ADR log depends on: **does this change need an ADR, and if so how do I write one.** Read it when a PR touches an -architecturally significant surface (the quality gate and -`pnpm adr:check` will remind you). +architecturally significant surface. `pnpm adr:check` and required CI provide +the reminder. ## Does this change need an ADR? @@ -37,10 +37,12 @@ change no direction, or anything a code comment at the site already fully explains. When in doubt, prefer recording it — a thin ADR beats a silent decision — but do not manufacture ADRs for non-decisions. -## Trigger surfaces (the gate watches these) +## Trigger surfaces checked by the ADR reminder -These changes almost always encode a decision. `pnpm adr:check` (and the agent -quality gate) flags them when no ADR accompanies the diff: +These changes almost always encode a decision. `pnpm adr:check` flags them when +no ADR accompanies the diff. Step 3 of the +[PR operating card](../notes/pr-operating-card.md) requires that focused check +for the same trigger surfaces: - **A new package/service** — a new top-level directory with its own `AGENTS.md` / `package.json`, or a new workspace package registered in @@ -90,8 +92,9 @@ the new decision, then flip the old one to `status: archived` with a ## When an ADR is genuinely not needed -If the gate flags a trigger surface but the change is not a decision (e.g. a new -workflow that only reformats logs, a stack-file reorder), that is fine — say so -on the [PR template's](../../.github/PULL_REQUEST_TEMPLATE.md) +If `pnpm adr:check` flags a trigger surface but the change is not a decision +(for example, a new workflow that only reformats logs or a stack-file reorder), +that is fine. State the reason on the +[PR template's](../../.github/PULL_REQUEST_TEMPLATE.md) **"Architecture decision?"** line with a one-line reason. A won't-record with a reason is complete; a silent skip is not. diff --git a/docs/pr-checklists/ci-workflow-gates.md b/docs/pr-checklists/ci-workflow-gates.md index 8ae089a32..145235734 100644 --- a/docs/pr-checklists/ci-workflow-gates.md +++ b/docs/pr-checklists/ci-workflow-gates.md @@ -118,8 +118,8 @@ The audit runs every retained deterministic CI job. It runs the focused agent setup and package-policy contract and the focused indexer autoreview invariant contract. It does not execute the legacy local-gate Bash regression suite, routing-table suites, or indexer route parity suite. Ordinary CI keeps those -legacy steps while the mandatory local gate remains active. The audit still -runs the retained package-script validator before dependency installation. +legacy steps during the post-cutover canary. The audit still runs the retained +package-script validator before dependency installation. - [ ] Keep the dispatcher read-only. Do not forward repository or environment secrets. Do not use `secrets: inherit`. Called jobs still receive GitHub's diff --git a/docs/pr-checklists/code-health.md b/docs/pr-checklists/code-health.md index 151efd87b..80171c085 100644 --- a/docs/pr-checklists/code-health.md +++ b/docs/pr-checklists/code-health.md @@ -3,7 +3,7 @@ title: Code Health Checklist status: active owner: eng canonical: true -last_verified: 2026-08-31 +last_verified: 2026-09-02 doc_type: checklist scope: ci/process review_interval_days: 90 @@ -16,16 +16,13 @@ Triggered when your change touches lint configs, package boundaries, dependencies, coverage thresholds, TypeScript compiler options, env loading, or the `.dependency-cruiser.cjs` / `*/knip.json` files. -## Before pushing +## Author checkpoint - [ ] `pnpm code-health` is green (`code-health:knip` + `code-health:deps`). - The agent quality gate selects the changed package's `knip` task always, - and the workspace dependency-cruiser check only when a changed path is - inside a root that check scans (`shared-config`, `ui-dashboard`, - `indexer-envio`, `metrics-bridge`, `integration-probes`, `aegis`), is - `.dependency-cruiser.cjs`, or is a workspace manifest that decides how - imports resolve (`package.json`, `pnpm-lock.yaml`, `pnpm-workspace.yaml`). - Use the umbrella command for a full local sweep. + This checklist applies to package-boundary and code-health configuration + changes, so use the umbrella command for the full local sweep. It scans + `shared-config`, `ui-dashboard`, `indexer-envio`, `metrics-bridge`, + `integration-probes`, and `aegis`. - [ ] If you added a new cross-package import, it goes via `shared-config` (or `@mento-protocol/contracts`), never indexer/dashboard/bridge ↔ each other. - [ ] If you added a new top-level dependency, knip can see it being used. @@ -46,11 +43,12 @@ or the `.dependency-cruiser.cjs` / `*/knip.json` files. ## Adjacent enforced conventions - CI coverage floors run through each package's `test:coverage` command (Aegis - uses `test:cov`), not a bare `test`; CI remains the full-floor authority when - the local gate selects scoped related tests. Use `--full-local-tests` to force - the full local floor. The threshold source of truth is the package's Vitest - config or Aegis Jest config. Re-measure after material test or source changes - and use `floor(measured) - 2`, preserving any scoped buckets and exclusions. + uses `test:cov`), not a bare `test`. Required CI remains the full-floor + authority. Run the package coverage command locally when the change modifies + a coverage threshold or its test infrastructure. The threshold source of + truth is the package's Vitest config or Aegis Jest config. Re-measure after + material test or source changes and use `floor(measured) - 2`, preserving any + scoped buckets and exclusions. - [`shared-config/tsconfig.json`](../../shared-config/tsconfig.json) enables `verbatimModuleSyntax`; use `import type` for type-only imports there. - [ADR 0009](../adr/0009-supply-chain-hardening.md) owns override and @@ -72,9 +70,9 @@ or the `.dependency-cruiser.cjs` / `*/knip.json` files. test changes the value after module initialization or the key is computed at runtime. -## How the gates behave +## How the checks behave -| Gate | Severity | What it catches | Fix | +| Check | Severity | What it catches | Fix | | --------------------------------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `dependency-cruiser` cross-pkg | **error** | dashboard/indexer/bridge cross-imports, shared-config upward imports | Refactor through `shared-config`, or — if it's data-only — narrow the allow list with `pathNot` | | `dependency-cruiser` cycles | **error** | new circular deps anywhere | Extract the shared piece into a third module | @@ -83,7 +81,7 @@ or the `.dependency-cruiser.cjs` / `*/knip.json` files. | `indexer-handlers-no-rpc-internals` (dep-cruiser) | **error** | handler importing from `rpc/pool-state`, `rpc/client`, etc. directly | Wrap the fetcher in a new effect in `rpc/effects.ts`, then call the effect from the handler; or use the `rpc.ts` barrel for DB-only helpers | | `knip` files / deps / unlisted | **error** | unused files, unused listed deps, imports of unlisted deps | Delete file / remove dep / `pnpm add` the missing dep | | `knip` exports / types / enumMembers | warn | unused exports, types, enum entries | Delete on touch; not auto-blocking | -| ESLint complexity budgets | **error** (diff-aware baseline) | over-complex / long / nested / many-arg functions | Refactor; any new tuple that cannot be absorbed as a nearby refactor against `/eslint-baseline.json` fails the gate. After fixing: `pnpm --filter lint:baseline:update`, then commit the regenerated baseline. | +| ESLint complexity budgets | **error** (diff-aware baseline) | over-complex / long / nested / many-arg functions | Refactor; any new tuple that cannot be absorbed as a nearby refactor against `/eslint-baseline.json` fails lint. After fixing: `pnpm --filter lint:baseline:update`, then commit the regenerated baseline. | | `sonarjs/no-redundant-jump` | **error** | dead control-flow jumps | Trivial fix; never opt out | | `sonarjs/cognitive-complexity` | **error** (diff-aware baseline) | hard-to-read nested logic | Extract sub-functions; new violations fail by tuple. Cleanup pattern: same as above (fix + regenerate baseline). | | `sonarjs/no-identical-functions` | **error** | duplicate function bodies | Extract a helper, or — if intentionally parallel — disable per-occurrence | diff --git a/docs/pr-checklists/indexer-handler-invariants.md b/docs/pr-checklists/indexer-handler-invariants.md index bda27421b..01d3263bb 100644 --- a/docs/pr-checklists/indexer-handler-invariants.md +++ b/docs/pr-checklists/indexer-handler-invariants.md @@ -3,7 +3,7 @@ title: Indexer Handler Invariants status: active owner: eng canonical: true -last_verified: 2026-07-29 +last_verified: 2026-09-02 doc_type: checklist scope: indexer-envio review_interval_days: 90 @@ -204,5 +204,5 @@ When a new heal step changes Pool fields or entity-kind classification: - Exercise dashboard-dependent queries against local Hasura with a representative high-history pool to expose row-cap assumptions. - Prove new entity IDs under two writes in the same block. -- Run the package tests selected by the quality gate in step 3 of the - [PR operating card](../notes/pr-operating-card.md). +- Apply the indexer author checks and applicable code-generation rows in step 3 + of the [PR operating card](../notes/pr-operating-card.md). diff --git a/docs/pr-checklists/recurring-review-patterns.md b/docs/pr-checklists/recurring-review-patterns.md index 2b9351345..f8eeaef05 100644 --- a/docs/pr-checklists/recurring-review-patterns.md +++ b/docs/pr-checklists/recurring-review-patterns.md @@ -3,7 +3,7 @@ title: Recurring PR Review Patterns status: active owner: eng canonical: true -last_verified: 2026-08-28 +last_verified: 2026-09-02 doc_type: checklist scope: repo-wide review_interval_days: 90 @@ -47,7 +47,7 @@ tldr: if a PR makes an architectural decision (constrains future work · had a real alternative · the why isn't obvious from the code), it records an ADR under `docs/adr/` in the same PR. High-signal triggers — a new package/service, a new Terraform stack, a new CI/deploy workflow — are flagged by `pnpm adr:check` and -the agent quality gate. A won't-record needs a one-line reason on the PR's +required CI. A won't-record needs a one-line reason on the PR's "Architecture decision?" line. Full rules in the linked checklist. ### Prompt exclusions — [checklist](review-prompt-exclusions.md) @@ -233,12 +233,18 @@ tldr: **ruleset-required** workflows (`ci`, `Code Quality`, `Sentry suites`, the - Files near the line budget are tracked in `docs/notes/file-size-watch.md`; refresh with `node scripts/repo-health/file-size-watchlist.mjs` before starting a split so growth doesn't slip past unnoticed. `.github/workflows/file-size-watchlist.yml` owns the monthly issue-only check against current `main`; keep external copies disabled, use `--format issue` for GitHub Issues, and never route reports to `BACKLOG.md`. - Why this exists: PR #263 split `ui-dashboard/src/app/pool/[poolId]/page.tsx` from 2,831 → 470 lines after a year of unchecked growth. The refactor was a 4-day project; appending one more tab inline was a 30-minute task. Each individual decision was rational; the cumulative drift was not. -### New source modules — routing and coverage +### New source modules — focused coverage -- After adding a module, verify its quality-gate routing by dry-running **that module's path on its own**. A sibling path in the same commit pulls the suites in anyway and masks a module that matches no case at all: `sentry-autofix-second-look.mjs` and `sentry-autofix-decisions.mjs` shipped matching nothing, so a change touching only one of them ran zero suites. -- Check whether a constant the new module owns is a term in another suite's assertion, and route to both. `MAX_HANDLED_ID_QUERIES` feeds the finalize suite's timeout pin while living in a module routed only to the selector suite. +- After adding a module, run its owning focused suite directly. Confirm that + the fixed required CI job includes that suite or its manifest. Do not add a + route to the legacy local selector. +- Check whether a constant the new module owns is a term in another suite's + assertion. Run and update both suites when it is. `MAX_HANDLED_ID_QUERIES` + feeds the finalize suite's timeout pin as well as the selector behavior. - Add the module to the machine-enforced file-size test covering its area. If review is what catches a cap breach, the machinery didn't — the autofix modules were absent from that list while the triage ones were on it. -- Sentry legs only: do NOT add a new `scripts/sentry-*.test.mjs` for a split. A new suite file triggers the registration cascade (manifest floor, a `ci.yml` step, gate routing). Put the tests in an existing suite. +- Sentry legs only: do NOT add a new `scripts/sentry-*.test.mjs` for a split. A + new suite file triggers the registration cascade for the manifest floor and + `ci.yml`. Put the tests in an existing suite. - For a pure split, prove behaviour is unchanged rather than asserting it, with a harness suited to the subsystem. **CLI or script splits:** drive the entry point across its paths against a stub binary, run the identical harness against `git archive` of the pre-split tree, and diff stdout, stderr, exit codes and every generated file. **UI, library or Terraform splits:** the equivalent is the suite the module already owns — visual snapshots, a type surface, or `terraform plan` showing no diff. The requirement is a before/after comparison a reviewer can re-run, not a particular tool. ### Security / CSP @@ -296,13 +302,15 @@ tldr: `generateMetadata` reading access-controlled data must gate on `isPublic = ### Sibling-audit rule for multi-component flows -- When fixing a hazard in one component of a flow that has parallel siblings (form ↔ report editor; modal ↔ detail page; index "+ Add" modal ↔ row-edit modal), audit each sibling for the same hazard class before pushing. Cross-flow / cross-mount / cross-surface races usually need symmetric fixes. PR #345 had ~5 review rounds because each fix landed in one surface while the symmetric surface still had the same bug — saving on the form needed a fix, then deletion needed the same fix, then the report editor needed it, then the modal flow needed it, then the add-new modal needed it. Audit once per round; don't ship a half-fix that obviously asks for a re-raise +- When fixing a hazard in one component of a flow that has parallel siblings (form ↔ report editor; modal ↔ detail page; index "+ Add" modal ↔ row-edit modal), audit each sibling for the same hazard class before review handoff. Cross-flow / cross-mount / cross-surface races usually need symmetric fixes. PR #345 had ~5 review rounds because each fix landed in one surface while the symmetric surface still had the same bug — saving on the form needed a fix, then deletion needed the same fix, then the report editor needed it, then the modal flow needed it, then the add-new modal needed it. Audit once per round; don't ship a half-fix that obviously asks for a re-raise ### Code health budgets — [checklist](code-health.md) Use the linked checklist for package boundaries, dead code, lint and type budgets, coverage, duplication, bundle size, schema diff, and advisory reports. Use the [mutation-testing checklist](mutation-testing.md) for -mutation scope, cadence, and break floors. The agent quality gate owns -changed-path routing and command selection; keep volatile counts, scores, and -workflow details in their canonical owners instead of duplicating them here. +mutation scope, cadence, and break floors. Step 3 of the +[PR operating card](../notes/pr-operating-card.md) owns direct author-check +selection. Required CI owns the full affected suite. Keep volatile counts, +scores, and workflow details in their canonical owners instead of duplicating +them here. diff --git a/docs/pr-checklists/review-prompt-exclusions.md b/docs/pr-checklists/review-prompt-exclusions.md index f700bbab2..4e6a6f155 100644 --- a/docs/pr-checklists/review-prompt-exclusions.md +++ b/docs/pr-checklists/review-prompt-exclusions.md @@ -3,7 +3,7 @@ title: Review Prompt Exclusions status: active owner: eng canonical: true -last_verified: 2026-08-30 +last_verified: 2026-09-02 doc_type: checklist scope: repo-wide review_interval_days: 90 @@ -58,10 +58,11 @@ flag the concrete regression and cite the evidence. ## Existing Guardrails -- Do not ask for another ad hoc quality command when `pnpm agent:quality-gate ---run` has mapped and executed the applicable local checks for the changed - paths. Flag missing targeted checks only when the gate mapping is incomplete - for the diff or when a package-specific `AGENTS.md` requires an extra command. +- Do not ask for another ad hoc quality command when the PR records every + applicable author check from step 3 of the + [PR operating card](../notes/pr-operating-card.md) and every extra check from + the scoped `AGENTS.md`. Flag a missing check only when a matching trigger or + scoped instruction has no recorded result. - Do not flag a missing context-doc update solely because a file under `docs/PLAN-*` changed. Flag context drift when the diff introduces or changes commands, scripts, env vars, hooks, deploy/codegen steps, ownership routing, diff --git a/docs/terraform.md b/docs/terraform.md index 5f36980c5..31da1c448 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -3,7 +3,7 @@ title: Terraform Stacks status: active owner: eng canonical: true -last_verified: 2026-08-20 +last_verified: 2026-09-02 doc_type: runbook scope: repo-wide review_interval_days: 90 @@ -54,8 +54,9 @@ Without a stack, `pnpm tf validate` validates every registered stack. It formats tracked and non-ignored untracked Terraform, then runs backend-free init and validate. On Darwin, it applies the [immutable provider trust and cache rules](notes/agent-quality-gate-mechanics.md). Land trust updates through -reviewed `main` and CI. Then refresh `origin/main` and rerun the gate. Gitignored -operator `*.tfvars` stay outside the source check. +reviewed `main` and CI. Then refresh `origin/main` and rerun +`pnpm tf validate `. Gitignored operator `*.tfvars` stay outside the +source check. For stacks with `ci.apply == "push-main-production-infra-environment"`, local apply requires a clean `main` at `origin/main` unless the operator deliberately diff --git a/governance-watchdog/ADDING_EVENTS.md b/governance-watchdog/ADDING_EVENTS.md index eb6ca7315..758743622 100644 --- a/governance-watchdog/ADDING_EVENTS.md +++ b/governance-watchdog/ADDING_EVENTS.md @@ -98,7 +98,8 @@ not run them against production destinations casually. ### 5. Validate and open the PR -From the repository root, run: +Before the first command, apply the step 3 lifecycle and install review in the +[PR operating card](../docs/notes/pr-operating-card.md) to step 4's `package.json` change. Then run: ```bash pnpm --filter @mento-protocol/governance-watchdog lint @@ -107,7 +108,8 @@ pnpm --filter @mento-protocol/governance-watchdog test:coverage pnpm --filter @mento-protocol/governance-watchdog build ``` -Then run the gate or gates from step 3 of the +Treat `test:coverage` as satisfying the unit-test row. Then apply every other +matching direct author check from step 3 of the [PR operating card](../docs/notes/pr-operating-card.md). The PR must contain the TypeScript handler, source guard, filter input, diff --git a/indexer-envio/AGENTS.md b/indexer-envio/AGENTS.md index dad3f7ac8..e931697f8 100644 --- a/indexer-envio/AGENTS.md +++ b/indexer-envio/AGENTS.md @@ -3,7 +3,7 @@ title: Envio Indexer Instructions status: active owner: eng canonical: true -last_verified: 2026-07-23 +last_verified: 2026-09-02 doc_type: agent-instructions scope: indexer-envio review_interval_days: 90 @@ -60,8 +60,13 @@ types, rollout behavior, and representative browser/query tests agree. Use the root `pnpm indexer:*` commands or package scripts documented in the README. After changing schema, config, entry-point imports, or handler module -reachability, run `pnpm indexer:codegen`; after dashboard queries change, also -run `pnpm dashboard:codegen`. +reachability, run each affected code-generation variant. Use +`pnpm indexer:testnet:codegen` for testnet inputs and +`pnpm --filter @mento-protocol/indexer-envio indexer:bridge-only:codegen` for +bridge-only inputs. Shared schema or ABI changes affect all variants. Run +non-mainnet variants first and `pnpm indexer:codegen` last because the variants +share one generated tree. After dashboard queries change, also run +`pnpm dashboard:codegen`. The wrapper reads `.env`, not named legacy env files. `.env.example` is the variable reference, including Polygon's per-chain RPC and start-block diff --git a/indexer-envio/README.md b/indexer-envio/README.md index 2b361329d..40beb4d44 100644 --- a/indexer-envio/README.md +++ b/indexer-envio/README.md @@ -1,4 +1,4 @@ - + # Mento v3 Envio HyperIndex Indexer @@ -164,8 +164,9 @@ When a new `@mento-protocol/contracts` version is published: 3. Run `pnpm install` from the repository root. 4. From `indexer-envio/`, run `pnpm generate:abis` and commit any vendored ABI changes. -5. Run `pnpm check:yaml-addresses`, then run codegen and the dashboard and - indexer typechecks selected by the root quality gate. +5. Run `pnpm check:yaml-addresses`. Then apply the indexer code-generation and + direct dashboard and indexer package checks in step 3 of the + [PR operating card](../docs/notes/pr-operating-card.md). ### Adding a contract to the index diff --git a/scripts/AGENTS.md b/scripts/AGENTS.md index b5543e3ac..70877fda5 100644 --- a/scripts/AGENTS.md +++ b/scripts/AGENTS.md @@ -3,7 +3,7 @@ title: Scripts Instructions status: active owner: eng canonical: true -last_verified: 2026-09-01 +last_verified: 2026-09-02 doc_type: agent-instructions scope: scripts review_interval_days: 90 @@ -16,8 +16,7 @@ Read the relevant [ADR](../docs/adr/README.md) before changing script behavior. ## Scope -`scripts/` holds deploy and maintenance tools, agent gates, and code-health -checks. +`scripts/` holds deploy, maintenance, gate, and code-health tools. ## Layout @@ -153,14 +152,13 @@ in the same PR. before mutation. `deploy-indexer:promote` acts on a registered remote deployment; use it through the `deploy-indexer` skill after its clean-tree preflight, verification, and production approval. -- Do not add `--no-verify` to normal Git commands. `deploy-indexer.sh` uses it - only for `envio` trigger-ref pushes, which intentionally skip redundant - pre-push hooks; never generalize it. +- Only `deploy-indexer.sh`'s isolated `envio` trigger-ref push may use + `--no-verify`. Never use it in developer Git commands. - New deploy scripts print target, commit, and rollback/verification around mutation. -- New Node root scripts need `pnpm lint:scripts` coverage; new shell scripts must - pass `bash -n`. Add a focused command to `scripts/agent-quality-gate.sh` for - behavior syntax and lint cannot verify. +- Run `pnpm lint:scripts` for new Node root scripts and `bash -n` for new shell + scripts. Add focused tests beyond lint and syntax. Add required CI wiring if + no fixed job owns them. - No ESLint `max-lines` reaches this tree. The file-size watchlist reports it instead — tests aside, three trust-root files exempt: [ADR 0065](../docs/adr/0065-scripts-file-size-watchlist-scope.md). @@ -176,8 +174,9 @@ in the same PR. ## Verification -Run the gate from operating-card step 3. It routes `bash -n`, -`pnpm lint:scripts`, and focused tests. Add -`pnpm agent:quality-gate:test` for gate routing changes, -`node scripts/check-deploy-root-anchors.test.mjs` for deploy wrappers, and -`pnpm agent:context-check` plus `pnpm docs:index` after a move. +Apply [PR operating card step 3](../docs/notes/pr-operating-card.md) to each +changed root tool: `bash -n `, `pnpm lint:scripts`, and +its focused test. Run `pnpm agent:quality-gate:test` only for legacy-gate +changes. Deploy wrappers also run +`node scripts/check-deploy-root-anchors.test.mjs`. After a move, run +`pnpm agent:context-check` and `pnpm docs:index --check`. diff --git a/scripts/agent-autoreview.mjs b/scripts/agent-autoreview.mjs index 873b73a94..e75e1c098 100755 --- a/scripts/agent-autoreview.mjs +++ b/scripts/agent-autoreview.mjs @@ -295,7 +295,7 @@ function parseArgs(argv) { case "--parallel-tests": next(); throw new Error( - "--parallel-tests was removed; run the local or hosted gate command from docs/notes/pr-operating-card.md step 3 before autoreview", + "--parallel-tests was removed; run the applicable direct author checks from docs/notes/pr-operating-card.md step 3 before autoreview", ); case "--timeout-seconds": args.timeoutSeconds = Number.parseInt(next(), 10); diff --git a/scripts/agent-autoreview.test.sh b/scripts/agent-autoreview.test.sh index 591141b64..bd5cbb107 100644 --- a/scripts/agent-autoreview.test.sh +++ b/scripts/agent-autoreview.test.sh @@ -2694,7 +2694,7 @@ run_parallel_tests_removed_regression() { run_helper_in_repo_expect_failure "$review_repo" --mode local --engine local --parallel-tests true expect_stderr_contains "--parallel-tests was removed" - expect_stderr_contains "docs/notes/pr-operating-card.md step 3" + expect_stderr_contains "applicable direct author checks from docs/notes/pr-operating-card.md step 3" } run_review_target_metadata_regression() { diff --git a/scripts/agent-quality-gate.sh b/scripts/agent-quality-gate.sh index e5e867781..fb1571e95 100755 --- a/scripts/agent-quality-gate.sh +++ b/scripts/agent-quality-gate.sh @@ -13,8 +13,8 @@ usage() { cat <<'USAGE' Usage: scripts/agent-quality-gate.sh [--dry-run|--run] [--base ] [--head ] [--changed-paths-file ] [--allow-package-script-changes] [--fail-fast|--keep-going] [--skip-if-fresh] [--pre-push] [--parallel ] [--full-local-tests] -Maps changed paths to the local commands and PR checklists an agent should run -before opening or updating a PR. Defaults to dry-run. +Maps changed paths for the retained optional legacy diagnostic. Normal author +checks come from the PR operating card. Defaults to dry-run. Options: --dry-run Print the mapped commands/checklists without running them. @@ -32,10 +32,10 @@ Options: With --run, skip execution when the previous successful run used the same base, changed paths, command plan, gate implementation, validated file content, toolchain, material - environment, runtime, and scheduler policy. Intended for the - pre-push hook only. - --pre-push Mark this invocation as the git pre-push hook. Hosted setup - uses this to refuse a cold gate inside a blocking git push. + environment, runtime, and scheduler policy. Intended only for + retained --pre-push compatibility. + --pre-push Enable retained git pre-push compatibility behavior. Normal + setup does not install or invoke this path. --parallel With --run, execute independent quality commands with up to n concurrent jobs. Default: auto, capped at 4. Fail-fast mode stays sequential so it still stops before starting the next @@ -857,8 +857,8 @@ if [[ -z "$allow_package_script_changes" ]]; then fi # Use a repo-local scratch dir for tmpfiles so we don't depend on TMPDIR -# being writable — pre-push hooks fork off trunk's daemon, which may carry -# a TMPDIR that's outside a host sandbox's writable allowlist. Select and +# being writable. Compatibility hook callers and hosted runtimes may carry a +# TMPDIR that's outside a host sandbox's writable allowlist. Select and # export the effective directory before the coordinator adapter copy so the # default coordinator and dry-run paths use the same validated fallback. # Mapped subprocesses (e.g. agent-quality-gate.test.sh's bare `mktemp -d`) @@ -986,13 +986,14 @@ success_stamp_file="$scratch_dir/last-success.stamp" # that lost one flaky check resume the commands that already passed instead of # re-executing everything. Bounded by prune_command_stamps below. command_stamps_file="$scratch_dir/command-stamps.tsv" -# An exact-signature success may cover the manual-run-to-pre-push interval even -# for the slowest mapped suites. Keep this fixed rather than environment- -# configurable so callers cannot extend validation reuse beyond two hours. +# An exact-signature success may cover a manual run followed by explicit +# --pre-push compatibility, even for the slowest mapped suites. Keep this fixed +# rather than environment-configurable so callers cannot extend validation +# reuse beyond two hours. success_stamp_ttl_seconds=$((2 * 60 * 60)) -# Trunk's pre-push hook callback runs the gate without a TTY and strips most -# env vars from the calling shell. Re-assert non-interactive markers so the -# mapped commands (e.g. pnpm install) take the CI codepath instead of asking +# The explicit --pre-push compatibility callback can run without a TTY and with +# most caller environment variables removed. Re-assert non-interactive markers +# so mapped commands (e.g. pnpm install) take the CI codepath instead of asking # for TTY confirmation. export CI="${CI:-true}" @@ -6672,9 +6673,11 @@ acquire_gate_run_lock_legacy() { echo "Holder pid ${owner_pid:-unknown} is still alive; let it finish, then retry." >&2 fi echo "Running the gate directly? --no-lock starts anyway and accepts the contention." >&2 - # The pre-push hook passes a fixed command line and Trunk strips the - # environment, so neither escape hatch is reachable from a failed push. - echo "Pushing? Fetch the hook's base, then warm the matching stamp with 'git fetch --quiet origin main && ./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main'; the hook's --skip-if-fresh path can then exit before coordinator registration." >&2 + if [[ "$pre_push" == "1" || "$pre_push" == "true" ]]; then + # The explicit compatibility invocation may use a fixed command line + # and a stripped environment, so it cannot add the escape hatch itself. + echo "Pushing through the retained compatibility path? Fetch its base, then warm the matching stamp with 'git fetch --quiet origin main && ./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main'; its --skip-if-fresh path can then exit before coordinator registration." >&2 + fi # GitHub issue #1894. Every other outcome states itself on stdout — a green # run ends "All mapped commands passed." — but this one used to speak on # stderr alone, so a caller reading the gate's stdout saw the reassuring @@ -6968,8 +6971,8 @@ fi # # Routing classification runs from the gate's own source tree, not the repo # under test, so a `scripts/` move must repoint this literal in the same commit. -# Nothing in CI runs the gate for real; the gate self-test is what exercises this -# import there, and a developer's pre-push is where a stale path bites first. +# Required CI exercises this import through the gate self-test. A direct +# diagnostic execution can encounter a stale path first. # The loader below therefore exits 3 and names the module it could not resolve, # instead of letting the failure read as a generic classifier fault. The verdict # is validated for the same reason: a classifier that answered something other @@ -7018,7 +7021,7 @@ NODE if [[ "$routing_classifier_status" -ne 0 ]]; then if [[ "$routing_classifier_status" -eq 3 ]]; then echo "error: routing-sensitive path classifier could not be loaded from ${routing_classifier_path}" >&2 - echo " scripts/agent-quality-gate.sh imports this module at pre-push time; moving it requires repointing that path in the same commit." >&2 + echo " scripts/agent-quality-gate.sh imports this module during diagnostic/runtime execution; moving it requires repointing that path in the same commit." >&2 fi echo "error: failed to classify routing-sensitive changed paths" >&2 exit 2 @@ -7073,7 +7076,7 @@ mapper_path="$script_source_dir/gate/mapping.mjs" # read as one. if [[ ! -f "$mapper_path" ]]; then echo "error: gate mapping engine could not be loaded from ${mapper_path}" >&2 - echo " scripts/agent-quality-gate.sh runs this module at pre-push time; moving it requires repointing that path in the same commit." >&2 + echo " scripts/agent-quality-gate.sh runs this module during diagnostic/runtime execution; moving it requires repointing that path in the same commit." >&2 exit 2 fi @@ -7511,9 +7514,9 @@ write_command_plan "$command_plan_file" # changed-path set comes from `git diff "$base_ref...$head_ref"`. Under tip # binding every advance of `origin/main` invalidated every warm stamp on the # machine, even when the branch's own bytes and its merge-base had not moved. -# The pre-push hook fetches `origin main` immediately before it runs the gate, -# so a warm-up that merely overlapped somebody else's merge paid for the whole -# gate a second time. +# The former pre-push hook fetched `origin main` immediately before it ran the +# gate. A warm-up that merely overlapped somebody else's merge then paid for the +# whole gate a second time. # # Three guards keep the narrower binding from weakening anything. # @@ -7665,11 +7668,11 @@ validated_content_hash="$(validation_content_signature)" # `allow_package_script_changes` only gates the pre-run package-script refusal, # which is a no-op unless `package_script_risk_changed`. Fold it out of the -# freshness stamp in the common no-risk case so a warm manual run (which may pass -# --allow-package-script-changes defensively) produces the SAME stamp as the -# flag-less pre-push hook — otherwise warm-then-push never skips. When package -# risk IS present, keep the real value so an unacknowledged hook run cannot reuse -# an acknowledged manual run. +# freshness stamp in the common no-risk case so a warm manual run (which may +# pass --allow-package-script-changes defensively) produces the SAME stamp as +# an explicit --pre-push compatibility run. When package risk IS present, keep +# the real value so an unacknowledged compatibility run cannot reuse an +# acknowledged manual run. if [[ "$package_script_risk_changed" == "true" ]]; then stamp_allow_package_scripts="${allow_package_script_changes:-false}" else @@ -7679,10 +7682,10 @@ fi gate_coordinator_freshness_context="" gate_coordinator_execution_head="" -# The coordinator execution fingerprint binds HEAD. The pre-push workflow must -# also accept a warm run made immediately before committing the same validated -# bytes. Build a separate compatibility context from every execution-fingerprint -# input except HEAD; stamp_line already carries base, paths, plan, +# The coordinator execution fingerprint binds HEAD. Retained --pre-push +# compatibility must also accept a warm run made immediately before committing +# the same validated bytes. Build a separate compatibility context from every +# execution-fingerprint input except HEAD; stamp_line already carries base, paths, plan, # implementation, content, and package-risk policy. Equality therefore means # that only HEAD can differ. Legacy and --no-lock runs keep the v3 stamp. gate_coordinator_freshness_context_hash() { @@ -7877,6 +7880,9 @@ is_fresh_success_stamp() { } echo "Agent quality gate" +echo "Retained diagnostic only." +echo "Normal path: use /ship author checks and required CI." +echo "Retirement requires the completed #2128 canary and separate human approval." echo echo "Base: ${base_ref}" echo "Head: ${head_ref}" @@ -8034,12 +8040,7 @@ fi if [[ "$package_script_risk_changed" == true && "$allow_package_script_changes" != "1" && "$allow_package_script_changes" != "true" ]]; then echo "Refusing to run because package manifests, patches, or lockfile changed." >&2 - if [[ "$(git config --bool --get agent.qualityGate.cloudPrePushRequireFresh 2>/dev/null || true)" == "true" ]]; then - echo "Review package scripts, lifecycle hooks, and dependency install scripts first." >&2 - echo "For hosted warm-then-push, set 'git config agent.qualityGate.allowPackageScriptChanges true', then rerun the same direct gate command so the hook reuses that acknowledgement." >&2 - else - echo "Review package scripts, lifecycle hooks, and dependency install scripts first, then re-run with --allow-package-script-changes if they are safe." >&2 - fi + echo "Review package scripts, lifecycle hooks, and dependency install scripts first, then re-run with --allow-package-script-changes if they are safe." >&2 if gate_coordinator_requested; then gate_coordinator_report_no_work_failure 2 "pre-execution policy" \ "No mapped command ran in this request" @@ -8090,9 +8091,9 @@ fi gate_lock_test_delay "${AGENT_QUALITY_GATE_LOCK_HELD_DELAY_SECONDS:-}" # Re-check freshness after the wait. The run we queued behind may have stamped -# this exact fingerprint while we waited — the pre-push hook queued behind the -# manual warm-up run is precisely that case — and re-running its work would -# throw away the reason the hook passes --skip-if-fresh at all. +# this exact fingerprint while we waited. An explicit --pre-push compatibility +# run queued behind a manual warm-up is precisely that case. Re-running its work +# would discard the reason compatibility mode accepts --skip-if-fresh. if ! declare -F gate_coordinator_is_active >/dev/null 2>&1 || ! gate_coordinator_is_active; then if [[ "$skip_if_fresh" == "1" || "$skip_if_fresh" == "true" ]]; then @@ -8224,9 +8225,8 @@ print_failed_command_output() { # egress and answers "Proxy tunneling failed: Forbidden" for anything outside its # allowlist — the launcher exits non-zero before a single linter runs, and the # stamp-exempt Trunk arm would make an otherwise-clean gate unable to exit 0. -# `.trunk/hooks` already models the answer for commits and pushes: warn, name the -# allowlist fix, skip. The gate takes the same posture, with one restriction that -# keeps it honest — only a PROVISIONING failure may downgrade. A provisioned +# The retained diagnostic warns, names the allowlist fix, and leaves enforcement +# to CI. Only a PROVISIONING failure may downgrade. A provisioned # Trunk that finds real problems still fails the gate, so the probe runs AFTER # the command failed and asks the launcher whether it can produce a CLI at all. is_trunk_command() { @@ -12111,8 +12111,8 @@ run_prerequisite_phase() { # WITHIN themselves: a failed step must stop before its dependents — and # before later steps in the SAME phase (e.g. `terraform validate` after a # failed `terraform init`) — run. This preserves the old --fail-fast - # prerequisite behavior even though the hook now drops global --fail-fast so - # the independent quality pool keeps going. Serialized dashboard checks and + # prerequisite behavior even when the caller selects global keep-going so the + # independent quality pool continues. Serialized dashboard checks and # the parallel pool are NOT prerequisites (serialized only for the .next # mutex), so they are run keep-going and still collect their own feedback. local previous_fail_fast="$fail_fast" @@ -12139,7 +12139,7 @@ run_quality_phase() { # Split setup out FIRST, so it reaches run_prerequisite_phase on every path. # While the partition lived below the sequential early-return, --parallel 1 - # and the hook's keep-going setting let a failed setup command's dependents + # and global keep-going let a failed setup command's dependents # run anyway: `terraform validate` after a failed `terraform init`, the # typechecks after a failed shared-config build, and the trusted `pnpm # ` commands after the failed package-script validator that exists to diff --git a/scripts/agent-quality-gate.test.sh b/scripts/agent-quality-gate.test.sh index adfa98b88..3f62835e2 100644 --- a/scripts/agent-quality-gate.test.sh +++ b/scripts/agent-quality-gate.test.sh @@ -1129,44 +1129,13 @@ assert_turbo_task_has_input "react-doctor:score" '$TURBO_ROOT$/.npmrc' assert_turbo_task_has_input "react-doctor:score" '$TURBO_ROOT$/.node-version' assert_turbo_task_has_input "react-doctor:score" '$TURBO_ROOT$/turbo.json' -# The public command must reach the protected Bash shebang before any inherited -# startup control can run. Pin both the prologue and the direct Trunk hook so a -# later wrapper or explicit `bash` invocation cannot silently remove that -# boundary while the dynamic cases below continue to pass for another reason. +# Pin the public diagnostic's protected Bash prologue and the staged pre-commit +# formatter. The focused setup contract owns the removed pre-push surfaces. node - <<'NODE' || const assert = require("node:assert/strict"); const fs = require("node:fs"); const gate = fs.readFileSync("scripts/agent-quality-gate.sh", "utf8"); const trunk = fs.readFileSync(".trunk/trunk.yaml", "utf8"); -const hostedSetups = [ - "scripts/bootstrap/claude-code-web-setup.sh", - "scripts/bootstrap/codex-cloud-maintenance.sh", - "scripts/bootstrap/codex-cloud-setup.sh", -]; -const hostedGateEntryPoints = [ - ".agents/skills/ship/SKILL.md", - ".claude/skills/ship/SKILL.md", - ".agents/roles/verifier.md", - ".github/ISSUE_TEMPLATE/agent-task.yml", - "docs/notes/quick-commands.md", - "scripts/docs/docs-garden-issue-helpers.mjs", -]; -const sweepWorkerEntryPoints = [ - ".agents/skills/backlog-sweep/SKILL.md", - ".claude/skills/backlog-sweep/SKILL.md", -]; -const resolvedBaseEntryPoints = [ - ".agents/skills/ship/SKILL.md", - ".claude/skills/ship/SKILL.md", - ".agents/roles/verifier.md", - "docs/notes/pr-operating-card.md", - "docs/notes/pr-ready-state.md", -]; -const sweepLockEntryPoints = [ - ".agents/skills/backlog-sweep/SKILL.md", - ".claude/skills/backlog-sweep/SKILL.md", - "docs/notes/backlog-sweep.md", -]; const activeTrunkLines = trunk .split("\n") .filter((line) => !line.trimStart().startsWith("#")) @@ -1180,77 +1149,19 @@ const prologue = [ "", ].join("\n"); assert.ok(gate.startsWith(prologue), "quality-gate public Bash prologue drifted"); -assert.match( - activeTrunkLines, - /^[ \t]*run: git fetch --quiet origin main && \.\/scripts\/agent-quality-gate\.sh --run --parallel 3 --skip-if-fresh --pre-push --base origin\/main[ \t]*$/mu, - "Trunk pre-push must execute the protected gate entry directly", -); -assert.doesNotMatch( - activeTrunkLines, - /(?:^|[^\w./])(?:(?:\/bin\/)?bash[ \t]+(?:\.\/)?scripts\/agent-quality-gate\.sh|scripts\/agent-quality-gate\.sh)/mu, - "Trunk pre-push must not bypass or CDPATH-resolve the protected gate entry", -); -for (const setupPath of hostedSetups) { - const setup = fs.readFileSync(setupPath, "utf8"); - assert.match( - setup, - /^git config core\.hooksPath \.trunk\/hooks\ngit config agent\.qualityGate\.cloudPrePushRequireFresh true$/mu, - `${setupPath} must require a fresh hosted pre-push stamp`, - ); -} -for (const entryPointPath of hostedGateEntryPoints) { - const entryPoint = fs.readFileSync(entryPointPath, "utf8"); - assert.match( - entryPoint, - /\.\/scripts\/agent-quality-gate\.sh --run --parallel 3 --base origin\/main/u, - `${entryPointPath} must use the exact hosted pre-push warm command`, - ); -} -for (const entryPointPath of sweepWorkerEntryPoints) { - const entryPoint = fs.readFileSync(entryPointPath, "utf8"); - assert.match( - entryPoint, - /After `\.\/scripts\/setup\.sh` in each fresh or resumed\n clone, set `agent\.qualityGate\.cloudPrePushRequireFresh=true` when that boolean\n is hosted\. Unset the key when it is local\./u, - `${entryPointPath} must propagate the setup type into every worker clone`, - ); -} -for (const entryPointPath of resolvedBaseEntryPoints) { - const entryPoint = fs.readFileSync(entryPointPath, "utf8"); - assert.match( - entryPoint, - /resolved base[\s\S]{0,120}not[\s\S]{0,40}`origin\/main`|hosted fork and stacked PRs/iu, - `${entryPointPath} must preserve fork and stacked resolved-base validation`, - ); -} -const claudeSessionStart = fs.readFileSync( - ".claude/hooks/session-start.sh", - "utf8", -); -const claudeHostedConfigIndex = claudeSessionStart.indexOf( - "git -C \"$REPO_ROOT\" config agent.qualityGate.cloudPrePushRequireFresh true", -); -const claudeSourceFilterIndex = claudeSessionStart.indexOf('case "$SOURCE" in'); -assert.ok(claudeHostedConfigIndex >= 0, "Claude resume hosted config is missing"); assert.ok( - claudeHostedConfigIndex < claudeSourceFilterIndex, - "Claude resume hosted config must precede the source filter", + fs.existsSync(".trunk/hooks/pre-commit"), + "tracked pre-commit formatter hook is missing", ); -for (const entryPointPath of sweepLockEntryPoints) { - const entryPoint = fs.readFileSync(entryPointPath, "utf8"); - assert.match( - entryPoint, - /Local workers wait with `--lock-wait 3600`\.[\s\S]{0,140}Hosted workers use[\s\S]{0,80}1,800-second default/u, - `${entryPointPath} must preserve local and hosted sweep lock waits`, - ); -} -const gateMechanics = fs.readFileSync( - "docs/notes/agent-quality-gate-mechanics.md", - "utf8", +assert.match( + activeTrunkLines, + /^[ \t]*- trunk-fmt-pre-commit[ \t]*$/mu, + "Trunk staged pre-commit formatting must stay enabled", ); assert.match( - gateMechanics, - /so a warm\n`\.\/scripts\/agent-quality-gate\.sh --run --parallel 3 --base origin\/main` satisfies/u, - "gate mechanics must name the exact reusable pre-push warm command", + gate, + /echo "Retained diagnostic only\."[\s\S]*echo "Normal path: use \/ship author checks and required CI\."[\s\S]*echo "Retirement requires the completed #2128 canary and separate human approval\."/u, + "retained gate must state its diagnostic status and retirement boundary", ); const freshnessSkipIndex = gate.indexOf( 'echo "Previous successful agent quality gate run is still fresh; skipping mapped commands."', @@ -1262,13 +1173,8 @@ const lockAcquisitionIndex = gate.lastIndexOf("\nacquire_gate_run_lock\n"); assert.ok(freshnessSkipIndex >= 0, "quality-gate freshness skip is missing"); assert.ok(hostedRefusalIndex > freshnessSkipIndex, "hosted refusal must follow freshness reuse"); assert.ok(lockAcquisitionIndex > hostedRefusalIndex, "hosted refusal must precede lock acquisition"); -assert.match( - gate, - /start '\.\/scripts\/agent-quality-gate\.sh --run --parallel 3 --base origin\/main' as an observable background task\./u, - "hosted refusal must warm the exact hook launcher, base, and parallelism", -); NODE - fail "expected the public quality-gate entry contract to remain pinned" + fail "expected the public diagnostic and local-cutover contract to remain pinned" # The public pnpm entry executes the gate by its `#!/bin/bash -p` shebang. A # caller-controlled non-interactive startup file must not run before the gate @@ -10272,8 +10178,11 @@ STUB > "$output_file" 2>&1 || hosted_package_risk_exit=$? [[ "$hosted_package_risk_exit" -eq 2 ]] || fail "cold hosted package-risk run exited ${hosted_package_risk_exit} instead of 2" - grep -Fq -- "git config agent.qualityGate.allowPackageScriptChanges true" "$output_file" || - fail "cold hosted package-risk run did not explain the reusable acknowledgement" + grep -Fq -- "re-run with --allow-package-script-changes if they are safe" "$output_file" || + fail "cold hosted package-risk diagnostic did not explain the explicit acknowledgement" + if grep -Fq -- "git config agent.qualityGate.allowPackageScriptChanges true" "$output_file"; then + fail "cold hosted package-risk diagnostic printed retired warm-then-push guidance" + fi git config --unset agent.qualityGate.cloudPrePushRequireFresh : > "$output_file" @@ -17896,9 +17805,8 @@ rm -rf "$no_lock_fallback_fixture_dir" no_lock_fallback_fixture_dir="" # --- Cross-run mutual exclusion (GitHub issue #1802) ------------------------- -# Two gate runs on one machine starve each other, and the pre-push hook starts -# one of its own while a manual run is still going, so `--run` takes a -# machine-wide mkdir lock. What has to hold: a live holder makes the second run +# Two gate runs on one machine can starve each other, so `--run` takes a +# machine-wide mkdir lock. A live holder must make the second run # wait rather than race, a holder that was killed never wedges the next run, # and both escape hatches (--no-lock, an inherited nested-run marker) still # start immediately. @@ -18041,12 +17949,25 @@ STUB assert_contains "Waiting for the agent quality gate run lock" assert_contains "held by pid ${live_holder_pid}" assert_contains "timed out after" - # The pre-push hook cannot pass --no-lock, so the timeout must also name the - # recovery that works from a failed push. + assert_contains "Running the gate directly? --no-lock starts anyway and accepts the contention." + assert_not_contains "Pushing through the retained compatibility path?" + [[ -d "$gate_lock_root/run.lock" ]] || + fail "a run that never acquired the lock must not delete the holder's lock" + + # Only an explicit --pre-push compatibility invocation names the retained + # warm-then-push recovery. + sleep 120 & + compatibility_holder_pid=$! + write_lock_owner "$compatibility_holder_pid" + compatibility_exit="$(run_locked_gate --pre-push)" + kill "$compatibility_holder_pid" 2>/dev/null || true + [[ "$compatibility_exit" == "2" ]] || + fail "expected a contended compatibility run to exit 2 after --lock-wait, got $compatibility_exit" + assert_contains "Pushing through the retained compatibility path?" assert_contains "git fetch --quiet origin main && ./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main" assert_contains "before coordinator registration" [[ -d "$gate_lock_root/run.lock" ]] || - fail "a run that never acquired the lock must not delete the holder's lock" + fail "a compatibility run that never acquired the lock must not delete the holder's lock" # GitHub issue #1894: the same expiry, read the way a piped caller reads it. # Every other outcome states itself on stdout — a green run ends "All mapped diff --git a/scripts/bootstrap/agent-setup-contract.test.sh b/scripts/bootstrap/agent-setup-contract.test.sh index 9cbb8ef14..de8026248 100644 --- a/scripts/bootstrap/agent-setup-contract.test.sh +++ b/scripts/bootstrap/agent-setup-contract.test.sh @@ -201,6 +201,43 @@ web_deps_marker_block="$( grep -q 'shared-config/scripts/build.mjs' <<< "$web_deps_marker_block" || fail "scripts/bootstrap/claude-code-web-setup.sh no longer invalidates its dependency marker when the clean-build wrapper changes" +# M5 keeps staged formatting on pre-commit and removes all repository +# verification from pre-push. Pin the tracked hook surface and every hosted +# setup writer so a later setup edit cannot silently restore the old block. +[[ -x .trunk/hooks/pre-commit ]] || + fail ".trunk/hooks/pre-commit must remain executable" +[[ ! -e .trunk/hooks/pre-push ]] || + fail ".trunk/hooks/pre-push must stay absent after local cutover" +grep -Fq -- "- trunk-fmt-pre-commit" .trunk/trunk.yaml || + fail ".trunk/trunk.yaml must keep trunk-fmt-pre-commit enabled" +for removed_pre_push_marker in \ + "trunk-check-pre-push" \ + "agent-quality-gate-pre-push" \ + "git_hooks: [pre-push]" \ + "--pre-push"; do + if grep -Fq -- "$removed_pre_push_marker" .trunk/trunk.yaml; then + fail ".trunk/trunk.yaml retained pre-push marker: $removed_pre_push_marker" + fi +done + +for hosted_setup in \ + scripts/bootstrap/claude-code-web-setup.sh \ + scripts/bootstrap/codex-cloud-maintenance.sh \ + scripts/bootstrap/codex-cloud-setup.sh; do + grep -Fq -- "git config core.hooksPath .trunk/hooks" "$hosted_setup" || + fail "$hosted_setup no longer installs the tracked pre-commit hook path" + if grep -Fq -- "agent.qualityGate.cloudPrePushRequireFresh" "$hosted_setup"; then + fail "$hosted_setup restored hosted pre-push freshness" + fi +done +if grep -Fq -- "agent.qualityGate.cloudPrePushRequireFresh" \ + .claude/hooks/session-start.sh; then + fail ".claude/hooks/session-start.sh restored hosted pre-push freshness" +fi +if grep -Fq -- "Before every push from a server/worktree" scripts/setup.sh; then + fail "scripts/setup.sh restored the mandatory manual pre-push checklist" +fi + # The pre-install validator must reject a changed trusted alias. This fixture # proves the validator itself fails closed without running pnpm install. validator_repo="$(mktemp -d)" diff --git a/scripts/bootstrap/claude-code-web-setup.sh b/scripts/bootstrap/claude-code-web-setup.sh index b16c32990..8d77a1622 100755 --- a/scripts/bootstrap/claude-code-web-setup.sh +++ b/scripts/bootstrap/claude-code-web-setup.sh @@ -25,7 +25,6 @@ git config --global --add safe.directory "$REPO_ROOT" || true echo "==> Configuring repository git hooks" git config core.hooksPath .trunk/hooks -git config agent.qualityGate.cloudPrePushRequireFresh true echo "==> Activating package manager from package.json" if command -v corepack >/dev/null 2>&1; then @@ -36,7 +35,7 @@ fi pnpm --version echo "==> Prewarming Trunk CLI and linters" -# Trunk powers the git pre-commit/pre-push hooks (.trunk/hooks) and `trunk fmt`. +# Trunk powers the git pre-commit hook (.trunk/hooks) and `trunk fmt`. # The launcher self-downloads the pinned CLI from trunk.io, which is NOT in the # default Trusted allowlist for Claude Code on the web. The current operating # allowlist beyond the Trusted defaults is trunk.io, *.trunk.io, and (optional, @@ -67,7 +66,7 @@ if trunk_ver=$(TRUNK_LAUNCHER_QUIET=true ./tools/trunk --version 2>/dev/null); t fi else echo "WARN: Trunk CLI could not be downloaded (is trunk.io allowlisted?)." >&2 - echo "WARN: git pre-commit/pre-push hooks will be skipped this session." >&2 + echo "WARN: the git pre-commit hook will be skipped this session." >&2 echo "WARN: Add 'trunk.io' and '*.trunk.io' to the env's Allowed domains (Custom" >&2 echo "WARN: network access, keep defaults) to enable local Trunk fmt/lint hooks." >&2 fi diff --git a/scripts/bootstrap/codex-cloud-maintenance.sh b/scripts/bootstrap/codex-cloud-maintenance.sh index 30efc63ff..deb6eb866 100755 --- a/scripts/bootstrap/codex-cloud-maintenance.sh +++ b/scripts/bootstrap/codex-cloud-maintenance.sh @@ -93,7 +93,6 @@ refresh_origin_main echo "==> Configuring repository git hooks" git config core.hooksPath .trunk/hooks -git config agent.qualityGate.cloudPrePushRequireFresh true activate_package_manager ensure_autoreview_helper diff --git a/scripts/bootstrap/codex-cloud-setup.sh b/scripts/bootstrap/codex-cloud-setup.sh index 77ddfb5a5..6e8295def 100755 --- a/scripts/bootstrap/codex-cloud-setup.sh +++ b/scripts/bootstrap/codex-cloud-setup.sh @@ -582,7 +582,6 @@ ensure_origin_main_ref echo "==> Configuring repository git hooks" git config core.hooksPath .trunk/hooks -git config agent.qualityGate.cloudPrePushRequireFresh true echo "==> Activating package manager from package.json" if command -v corepack >/dev/null 2>&1; then diff --git a/scripts/docs/check-verification-redesign-evidence.mjs b/scripts/docs/check-verification-redesign-evidence.mjs index 13cc4a957..754e8d981 100644 --- a/scripts/docs/check-verification-redesign-evidence.mjs +++ b/scripts/docs/check-verification-redesign-evidence.mjs @@ -25,11 +25,18 @@ const RETAINED = new Set(Object.keys(DISPOSITION_FIELDS).slice(0, 3)); const REQUIRED_RISKS = new Set(Array.from({ length: 13 }, (_, i) => i + 1)); const DUPLICATE_TARGET_RULE = "duplicate_of needs an acyclic retained target."; const GIT_OPTIONS = { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }; -const WHOLE_FILE_PATHS = new Set( - ".trunk/hooks/pre-push docs/adr/0007-agent-quality-gate-and-merge-oracle.md docs/adr/0069-gate-routing-table-as-data.md docs/adr/0076-fair-quality-gate-coordinator.md docs/notes/agent-quality-gate-mechanics.md scripts/agent-quality-gate.sh scripts/agent-quality-gate.test.sh scripts/check-agent-quality-gate-package-scripts.mjs".split( +const OPTIONAL_WHOLE_FILE_PATHS = new Set([".trunk/hooks/pre-push"]); +const TRUNK_PRE_PUSH_MARKER = + /trunk-check-pre-push|agent-quality-gate-pre-push|git_hooks:\s*\[pre-push\]|agent-quality-gate\.sh.*(?:--skip-if-fresh|--pre-push)/u; +const REQUIRED_WHOLE_FILE_PATHS = new Set( + "docs/adr/0007-agent-quality-gate-and-merge-oracle.md docs/adr/0069-gate-routing-table-as-data.md docs/adr/0076-fair-quality-gate-coordinator.md docs/notes/agent-quality-gate-mechanics.md scripts/agent-quality-gate.sh scripts/agent-quality-gate.test.sh scripts/check-agent-quality-gate-package-scripts.mjs".split( " ", ), ); +const WHOLE_FILE_PATHS = new Set([ + ...OPTIONAL_WHOLE_FILE_PATHS, + ...REQUIRED_WHOLE_FILE_PATHS, +]); const SCOPED_REFERENCE_PATTERN = /^(?:(?:\.agents\/skills\/backlog-sweep\/SKILL\.md|\.claude\/skills\/backlog-sweep\/SKILL\.md|docs\/adr\/0077-operator-triggered-backlog-sweep\.md|docs\/notes\/backlog-sweep\.md):.*run\.lock|docs\/adr\/(?:0064-scripts-module-directories|0073-guardrail-prose-pinned-in-ci)\.md:.*\b(?:lockfile-scope|arms-packages|pins\.test|routing-table\.test|engine\.test|arms-scripts|arms-agent-modules)\.mjs\b|scripts\/sentry\/ci-wiring\/check-sentry-suites-in-ci-gate-probe\.mjs:.*\bfacts\.mjs\b|(?:\.agents\/roles\/verifier\.md|(?:\.agents|\.claude)\/skills\/backlog-sweep\/SKILL\.md|docs\/notes\/(?:backlog-sweep|pr-ready-state)\.md|docs\/pr-checklists\/review-prompt-exclusions\.md):.*--run(?!-)|docs\/notes\/pr-operating-card\.md:.*--(?:run|base)(?!-)|scripts\/pr\/check-adr-reminder\.mjs:.*(?:\bgate.*--(?:head|changed-paths-file)(?!-)|--(?:head|changed-paths-file)(?!-).*\bgate)|scripts\/agent-autoreview\.sh:.*\bgate_stat\b|(?!(?:scripts\/sentry\/ci-wiring\/check-sentry-suites-in-ci-gate-job\.test\.mjs|scripts\/sentry\/gate\/sentry-suite-gate-integrity\.mjs):)[^:]+:.*\bGATE_[A-Z0-9_]+)/u; const EXCLUDED_REFERENCE_PATH = @@ -160,14 +167,38 @@ function countReferenceLines(path, content) { if (matchesReference(path, line)) selected.add(index); }); if (path === ".trunk/trunk.yaml") { + const legacyMarkerIndexes = lines.flatMap((line, index) => + TRUNK_PRE_PUSH_MARKER.test(line) ? [index] : [], + ); + if (legacyMarkerIndexes.length === 0) return selected.size; + const start = lines.findIndex((line) => line.includes("- trunk-check-pre-push"), ); + const definition = lines.findIndex( + (line) => line.trim() === "- id: agent-quality-gate-pre-push", + ); + const run = lines.findIndex((line) => + /run: .*agent-quality-gate\.sh.*(?:--skip-if-fresh|--pre-push)/u.test( + line, + ), + ); + const trigger = lines.findIndex((line) => + /git_hooks:\s*\[pre-push\]/u.test(line), + ); const end = lines.findLastIndex( (line) => line.trim() === "- agent-quality-gate-pre-push", ); - if (start < 0 || end < start) - fail("Cannot locate the Trunk quality-gate action block."); + if ( + start < 0 || + definition <= start || + run <= definition || + trigger <= run || + end <= trigger + ) + fail( + "Trunk quality-gate action block is partially removed or malformed.", + ); for (let index = start; index <= end; index += 1) selected.add(index); } if (path === "turbo.json") { @@ -195,8 +226,17 @@ export function buildManifest({ repoRoot = DEFAULT_ROOT, source }) { .map((entry) => entry.match(/^\d+ blob [0-9a-f]+\t(.+)$/u)?.[1]) .filter(Boolean) .sort(); - for (const path of WHOLE_FILE_PATHS) + for (const path of REQUIRED_WHOLE_FILE_PATHS) if (!paths.includes(path)) fail(`Missing manifest path: ${path}`); + const hookPresent = paths.includes(".trunk/hooks/pre-push"); + const trunkConfig = paths.includes(".trunk/trunk.yaml") + ? git(repoRoot, ["show", `${sourceSha}:.trunk/trunk.yaml`]) + : fail("Missing manifest path: .trunk/trunk.yaml"); + const trunkActionPresent = TRUNK_PRE_PUSH_MARKER.test(trunkConfig); + if (hookPresent !== trunkActionPresent) + fail( + "The pre-push hook and Trunk quality-gate action must be retained or removed together.", + ); const entries = []; for (const path of paths) { const wholeFile = diff --git a/scripts/docs/check-verification-redesign-evidence.test.mjs b/scripts/docs/check-verification-redesign-evidence.test.mjs index 3827db01c..5d34c6b6b 100644 --- a/scripts/docs/check-verification-redesign-evidence.test.mjs +++ b/scripts/docs/check-verification-redesign-evidence.test.mjs @@ -282,7 +282,7 @@ function withGitFixture(run) { " Runs the path-aware agent quality gate before push. The gate maps the", " branch diff to the required local checks instead of always running the", " full monorepo pre-push suite.", - " run: ./scripts/agent-quality-gate.sh --run --skip-if-fresh", + " run: ./scripts/agent-quality-gate.sh --run --skip-if-fresh --pre-push --base origin/main", " triggers:", " - git_hooks: [pre-push]", " enabled:", @@ -442,6 +442,121 @@ test("buildManifest counts whole files and matching reference lines", () => { }); }); +test("buildManifest accepts pre-push removal only with Trunk config", () => { + withGitFixture((repoRoot) => { + fs.rmSync(join(repoRoot, ".trunk/hooks/pre-push")); + fs.writeFileSync( + join(repoRoot, ".trunk/trunk.yaml"), + [ + "actions:", + " disabled:", + " - trunk-announce", + " enabled:", + " - trunk-fmt-pre-commit", + " - trunk-upgrade-available", + "", + ].join("\n"), + ); + execFileSync("git", ["-C", repoRoot, "add", "-A"]); + execFileSync("git", ["-C", repoRoot, "commit", "-qm", "remove pre-push"]); + + const manifest = buildManifest({ repoRoot, source: "HEAD" }); + assert.equal( + manifest.entries.some(({ path }) => path.startsWith(".trunk/")), + false, + ); + fs.rmSync(join(repoRoot, ".trunk/trunk.yaml")); + execFileSync("git", ["-C", repoRoot, "commit", "-qam", "remove config"]); + assert.throws( + () => buildManifest({ repoRoot, source: "HEAD" }), + /Missing manifest path: \.trunk\/trunk\.yaml/u, + ); + }); +}); + +for (const [name, removeOneSide] of [ + [ + "buildManifest rejects a retained hook without the Trunk action", + (repoRoot) => + fs.writeFileSync( + join(repoRoot, ".trunk/trunk.yaml"), + "actions:\n enabled: []\n", + ), + ], + [ + "buildManifest rejects a retained Trunk action without the hook", + (repoRoot) => fs.rmSync(join(repoRoot, ".trunk/hooks/pre-push")), + ], +]) { + test(name, () => { + withGitFixture((repoRoot) => { + removeOneSide(repoRoot); + execFileSync("git", ["-C", repoRoot, "add", "-A"]); + execFileSync("git", ["-C", repoRoot, "commit", "-qm", name]); + assert.throws( + () => buildManifest({ repoRoot, source: "HEAD" }), + /must be retained or removed together/u, + ); + }); + }); +} + +test("buildManifest rejects partial pre-push removal", () => { + withGitFixture((repoRoot) => { + fs.writeFileSync( + join(repoRoot, ".trunk/trunk.yaml"), + [ + "actions:", + " definitions:", + " - id: agent-quality-gate-pre-push", + " triggers:", + " - git_hooks: [pre-push]", + "", + ].join("\n"), + ); + execFileSync("git", ["-C", repoRoot, "add", ".trunk/trunk.yaml"]); + execFileSync("git", [ + "-C", + repoRoot, + "commit", + "-qm", + "partially remove pre-push", + ]); + + assert.throws( + () => buildManifest({ repoRoot, source: "HEAD" }), + /partially removed or malformed/u, + ); + }); +}); + +test("buildManifest rejects malformed pre-push run residue", () => { + withGitFixture((repoRoot) => { + fs.writeFileSync( + join(repoRoot, ".trunk/trunk.yaml"), + [ + "actions:", + " definitions:", + " - run: ./scripts/agent-quality-gate.sh --run --pre-push --base origin/main", + "", + ].join("\n"), + ); + execFileSync("git", ["-C", repoRoot, "add", ".trunk/trunk.yaml"]); + execFileSync("git", [ + "-C", + repoRoot, + "commit", + "-qm", + "leave malformed pre-push run", + ]); + + assert.throws( + () => buildManifest({ repoRoot, source: "HEAD" }), + /partially removed or malformed/u, + ); + }); +}); + test("buildManifest parses compact Turbo input filters", () => { withGitFixture((repoRoot) => { fs.writeFileSync( diff --git a/scripts/docs/docs-garden-issue-helpers.mjs b/scripts/docs/docs-garden-issue-helpers.mjs index 063338c90..0d9630dac 100644 --- a/scripts/docs/docs-garden-issue-helpers.mjs +++ b/scripts/docs/docs-garden-issue-helpers.mjs @@ -178,9 +178,7 @@ export function buildDocsGardenIssueSpec( "pnpm docs:index --check", "pnpm agent:context-check", "pnpm agent:context-budget --strict", - "# Follow docs/notes/pr-operating-card.md step 3.", - "pnpm agent:quality-gate --run # local", - "./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main # hosted hook warm", + "# Apply the direct author checks in docs/notes/pr-operating-card.md step 3.", "```", "", "### Risks, non-goals, and do-not-touch", diff --git a/scripts/docs/docs-garden-issue.test.mjs b/scripts/docs/docs-garden-issue.test.mjs index b5236d5a3..ad2d8d2cc 100644 --- a/scripts/docs/docs-garden-issue.test.mjs +++ b/scripts/docs/docs-garden-issue.test.mjs @@ -182,12 +182,13 @@ await test("generated issue follows the Agent Task body and label contract", () assert.ok(spec.body.includes("#1341")); assert.ok(spec.body.includes("## Generated audit packet")); assert.ok(spec.body.includes("docs-garden:operator-runbooks:1-of-2")); - assert.ok(spec.body.includes("pnpm agent:quality-gate --run # local")); assert.ok( spec.body.includes( - "./scripts/agent-quality-gate.sh --run --parallel 3 --base origin/main # hosted hook warm", + "Apply the direct author checks in docs/notes/pr-operating-card.md step 3.", ), ); + assert.ok(!spec.body.includes("agent:quality-gate")); + assert.ok(!spec.body.includes("hook warm")); assert.ok(!spec.body.includes("@docs-team")); assert.ok(spec.body.includes("@\u200Bdocs-team")); assert.deepEqual(spec.labels, [ diff --git a/scripts/gate/mapping/shell-quote.mjs b/scripts/gate/mapping/shell-quote.mjs index 9d846bb3b..c42523f55 100644 --- a/scripts/gate/mapping/shell-quote.mjs +++ b/scripts/gate/mapping/shell-quote.mjs @@ -37,9 +37,9 @@ * on the LOCALE, not on the build. Measured, `printf %q` of `aéb` gives * `$'a\303\251b'` under `LC_ALL=C` and `aéb` under `LC_ALL=en_US.UTF-8` on both * builds — and with the locale unset, 3.2.57 escapes where 5.3.15 does not. The - * gate's own pre-push hook runs with a stripped environment, so both answers - * are reachable on one machine. `shellQuote` refuses those too. No tracked path - * in this repository carries a non-ASCII byte. + * retained `--pre-push` compatibility path can run with a stripped environment, + * so both answers are reachable on one machine. `shellQuote` refuses those too. + * No tracked path in this repository carries a non-ASCII byte. * * `shell-quote.test.mjs` asks bash itself rather than trusting this comment. */ diff --git a/scripts/gate/routing-table/arms-scripts.mjs b/scripts/gate/routing-table/arms-scripts.mjs index daac80e2d..2478f235c 100644 --- a/scripts/gate/routing-table/arms-scripts.mjs +++ b/scripts/gate/routing-table/arms-scripts.mjs @@ -210,7 +210,7 @@ export const SCRIPT_ARMS = [ reason: "agent quality gate mapping changed", }, { - why: "routing-table.test.mjs reads this file: it asserts `implementation_signature()` lists every routing-table module and no module that is gone. A missing entry hashes as `__missing__` and FREEZES the freshness signature, so `--skip-if-fresh` reuses a stale stamp and skips real pre-push work — the ADR 0064 failure that reds nowhere else. The table's own arm covers a table-only edit; this covers the other direction, where somebody edits the gate's signature list and does not touch the table (ADR 0069).", + why: "routing-table.test.mjs reads this file: it asserts `implementation_signature()` lists every routing-table module and no module that is gone. A missing entry hashes as `__missing__` and FREEZES the freshness signature, so `--skip-if-fresh` reuses a stale stamp and skips real diagnostic work — the ADR 0064 failure that reds nowhere else. The table's own arm covers a table-only edit; this covers the other direction, where somebody edits the gate's signature list and does not touch the table (ADR 0069).", command: "pnpm gate:routing-table:test", reason: "gate holds the routing table's implementation-signature pin", diff --git a/scripts/gate/routing-table/index.mjs b/scripts/gate/routing-table/index.mjs index 7322a2b8d..3df8cbb47 100644 --- a/scripts/gate/routing-table/index.mjs +++ b/scripts/gate/routing-table/index.mjs @@ -51,7 +51,7 @@ * * `implementation_signature()` in the gate lists every module in this directory. * An entry it cannot `stat` hashes as `__missing__`, which FREEZES the - * signature, so `--skip-if-fresh` reuses a stale stamp and skips real pre-push + * signature, so `--skip-if-fresh` reuses a stale stamp and skips real diagnostic * work. Adding a module here without adding it there is the one mistake in this * directory that fails silently. `scripts/AGENTS.md` records the pin. */ diff --git a/scripts/pr/review-materiality.mjs b/scripts/pr/review-materiality.mjs index 5bf3c88b1..83688e530 100644 --- a/scripts/pr/review-materiality.mjs +++ b/scripts/pr/review-materiality.mjs @@ -324,22 +324,22 @@ function classifyBySize(fileCount, lineChanges) { function recommendedReview(tier) { if (tier === "trivial") { return [ - "Run the quality gate from operating-card step 3.", + "Run the applicable direct author checks from docs/notes/pr-operating-card.md step 3.", "Skip semantic autoreview unless the change is deceptively risky.", ]; } if (tier === "standard") { return [ - "Run the quality gate from operating-card step 3.", + "Run the applicable direct author checks from docs/notes/pr-operating-card.md step 3.", "Run pnpm agent:autoreview before pushing.", ]; } return [ - "Run the quality gate from operating-card step 3.", + "Run the applicable direct author checks from docs/notes/pr-operating-card.md step 3.", "Run pnpm agent:autoreview before pushing.", - "Read any mapped checklist and audit sibling surfaces before the next push.", + "Identify every applicable checklist from the changed surfaces and scoped instructions, then audit sibling surfaces before the next push.", ]; } diff --git a/scripts/pr/review-materiality.test.mjs b/scripts/pr/review-materiality.test.mjs index 0ea202d68..80600520a 100644 --- a/scripts/pr/review-materiality.test.mjs +++ b/scripts/pr/review-materiality.test.mjs @@ -220,7 +220,7 @@ test("classifies non-canonical plan-only edits as trivial", () => { assertEqual(report.tier, "trivial"); assertEqual( report.recommendedReview[0], - "Run the quality gate from operating-card step 3.", + "Run the applicable direct author checks from docs/notes/pr-operating-card.md step 3.", ); assertEqual(report.contextUpdateRequired, false); assertEqual(report.contextUpdateMissing, false); @@ -243,6 +243,10 @@ test("classifies root script changes as full and requiring context", () => { assertEqual(report.contextUpdateRequired, true); assertEqual(report.contextUpdatesPresent, false); assertEqual(report.contextUpdateMissing, true); + assertEqual( + report.recommendedReview[2], + "Identify every applicable checklist from the changed surfaces and scoped instructions, then audit sibling surfaces before the next push.", + ); assertIncludes( report.contextReasons.map((reason) => reason.detail).join("\n"), "agent:review-materiality", diff --git a/scripts/repo-health/check-guardrail-prose.test.mjs b/scripts/repo-health/check-guardrail-prose.test.mjs index e203d2423..3526b1f09 100644 --- a/scripts/repo-health/check-guardrail-prose.test.mjs +++ b/scripts/repo-health/check-guardrail-prose.test.mjs @@ -93,9 +93,12 @@ test("a present pinned sentence exits 0", () => { assert.match(output, /1 pinned sentences present across 1 files/); }); -test("a removed pinned sentence exits nonzero, names it, and says how to fix it", () => { +test("a suffix-weakened pinned sentence exits nonzero, names it, and says how to fix it", () => { const fixture = newFixture({ - files: { "AGENTS.md": "# Rules\n\n- Something else entirely.\n" }, + files: { + "AGENTS.md": + "# Rules\n\n- **Never merge without explicit approval** except for automated merges.\n", + }, pins: { "AGENTS.md": [PINNED_SENTENCE] }, }); const { status, output } = runChecker(fixture); diff --git a/scripts/repo-health/guardrail-prose.json b/scripts/repo-health/guardrail-prose.json index ef30bdeee..111b0d118 100644 --- a/scripts/repo-health/guardrail-prose.json +++ b/scripts/repo-health/guardrail-prose.json @@ -12,9 +12,75 @@ "**Forensic drafts stay local.** Use the `forensic-report` skill" ], "docs/notes/pr-operating-card.md": [ + "inspect resolved-base and working-tree changes, including untracked files, for package manifests, package-manager configuration, lockfiles, and patches. Review lifecycle and install effects before any package-manager command, including the claim command.", + "**Run the repository preflight first.** Automatic setup can finish before agent control under a [separate trust boundary](worktree-and-web-setup.md); this preflight does not attest it.", "**Agent sessions never merge a PR without the user's explicit, direct approval of that specific merge.**", "**Agent sessions never merge without explicit approval** for that specific merge", "**Knowingly deferred work needs a GitHub issue first**, linked from `## Deferrals`.", - "**Package-script, package-manager, and lockfile changes require explicit acknowledgement** through the gate; never bypass the refusal." + "First run `./tools/trunk fmt ` on each intended changed file that exists in the final tree. Use deleted paths and both sides of a rename to select matching rows, but never pass a missing path to Trunk.", + "| Source in a workspace package | Run each script that exists for that package: `pnpm --filter lint`, `pnpm --filter typecheck`, and its normal unit-test command. Governance Watchdog uses `pnpm --filter @mento-protocol/governance-watchdog test:unit`; its generic `test` needs a local service. |", + "| Dashboard React or client source | Also run `REACT_DOCTOR_BASE_REF= pnpm --filter @mento-protocol/ui-dashboard react-doctor:diff`. |", + "| Dashboard UI or visual output, route or interaction, browser test, or frontend build/runtime path | Also run `pnpm dashboard:build`, then follow [`dashboard-verification.md`](dashboard-verification.md) for the changed UI or runtime path, console, interaction, breakpoints, and applicable auth states. |", + "| Dashboard bundle input listed in the `dashboard` path filter in `.github/workflows/size-limit.yml` | When `shared-config/**` changes, first run `pnpm --filter @mento-protocol/config build`. After any required install and shared-config build, run `pnpm dashboard:build`, then `pnpm dashboard:size-limit`. Run a command once if another row also selects it. |", + "| `metrics-bridge/peg-registry.json`, `shared-config/chain-metadata.json`, `shared-config/deployment-namespaces.json`, `shared-config/oracle-reporters.json`, `shared-config/src/chains.ts`, `shared-config/src/oracle-reporters.ts`, or `shared-config/src/tokens.ts` | Run `node scripts/alerts/check-peg-registry-integrity.mjs --base-ref `. |", + "| `shared-config/src/thresholds.ts` | Run `node scripts/alerts/check-deviation-threshold-drift.mjs` and `pnpm --filter @mento-protocol/indexer-envio exec vitest run deviationThresholdSharedConfigSync`. |", + "| Indexer schema, configuration, ABI, entry point, or handler reachability | Run each affected code-generation variant from [`../../indexer-envio/AGENTS.md`](../../indexer-envio/AGENTS.md). Run affected non-mainnet variants first and `pnpm indexer:codegen` last. Inspect the generated diff before indexer package checks. |", + "| Dashboard GraphQL query or schema consumer, `indexer-envio/schema.graphql`, or `scripts/envio-schema-stubs.graphql` | Run `pnpm dashboard:codegen` and inspect the generated diff. |", + "| Manifest, lockfile, pnpm configuration, or patch | Inspect lifecycle and install effects. Run `CI=true pnpm install --frozen-lockfile` from the repository root. When one of these inputs changes under `alerts/infra/onchain-event-handler`, `alerts/infra/oncall-announcer`, or `governance-watchdog`, also run `CI=true pnpm install --frozen-lockfile --ignore-scripts --lockfile-dir .` from that root. Complete the installs before code generation or the applicable package rows. |", + "| Package Vitest configuration or hermetic setup | Run `node scripts/repo-health/check-hermetic-vitest-setup.mjs`. |", + "| Trunk configuration or local Git hook | Run `./tools/trunk check --ci --all` and `node scripts/workflows/check-github-action-pins.mjs`. Also run `bash scripts/bootstrap/agent-setup-contract.test.sh` when hook or Trunk action behavior changes. |", + "| Shell file, hosted agent setup, or hook | Run `bash -n` on each surviving changed shell file. Run `bash scripts/bootstrap/agent-setup-contract.test.sh` when hosted setup or hook behavior changes. |", + "| Agent instruction, role, command, skill, runtime configuration, or catalog-visible document metadata | Run `pnpm agent:context-check`, `pnpm agent:context-budget:test`, and `pnpm agent:context-budget --strict`. Also run `pnpm docs:index --check` after adding, moving, or removing managed context, or changing catalog-visible metadata. |", + "| Mirrored agent skill content or mirror checker | Run `node scripts/repo-health/check-skills-mirror.mjs` and `node scripts/repo-health/check-skills-mirror.test.mjs`. |", + "| Guardrail prose pin list or pinned normative text | Run `node scripts/repo-health/check-guardrail-prose.mjs` and `node scripts/repo-health/check-guardrail-prose.test.mjs`. |", + "| GitHub Actions workflow or action, or protected PR admission boundary | Run `pnpm ci:contract:test`, `node scripts/workflows/check-github-action-pins.mjs`, and `node scripts/workflows/check-autofix-ci-trust.mjs`. |", + "| `.coderabbit.yaml` | Run `pnpm coderabbit:config:test`. |", + "| `.lighthouserc.cjs` | Run `node scripts/lighthouse-config.test.mjs`. |", + "| `.gitignore` | Run `pnpm review:eval:test`. |", + "| `.gitattributes`, `.codex/config.toml`, or `.codex/upstash-mcp.example.toml` | Run `node --test scripts/mcp/upstash-mcp-config.test.mjs`. |", + "| `terraform.stacks.json` | Run `pnpm tf:test`. |", + "| New top-level package/service root with `AGENTS.md` or `package.json`, new workspace package registration, new Terraform stack registration, or new GitHub Actions workflow file | Run `pnpm adr:check --base --include-untracked`. |", + "Use the resolved PR base, not a fixed `origin/main`, for every diff-based author check, including stacked PRs.", + "| Root tooling, control plane, or standalone service | Run the focused existing contract named by the nearest scoped `AGENTS.md`. Do not add a root selector. |", + "Record each applicable result in the PR's `## Validation` section as `passed`, `failed`, or `not run: `.", + "Pre-push starts no repository check, fetch, lock, or wait.", + "**Inspect package-script, package-manager, lockfile, and patch changes before any package-manager command.**" + ], + "docs/notes/worktree-and-web-setup.md": [ + "Disable automatic setup before checking out an untrusted, fork, or cross-repository head." + ], + ".agents/skills/ship/SKILL.md": [ + "Run its preflight before agent-invoked repository code.", + "Stop fork and cross-repository heads before agent code.", + "Use the resolved PR base, not a fixed `origin/main`, for every diff-based author check, including stacked PRs.", + "Apply every matching row in card", + "Pre-push runs no repository verification." + ], + ".claude/skills/ship/SKILL.md": [ + "Run its preflight before agent-invoked repository code.", + "Stop fork and cross-repository heads before agent code.", + "Use the resolved PR base, not a fixed `origin/main`, for every diff-based author check, including stacked PRs.", + "Apply every matching row in card", + "Pre-push runs no repository verification." + ], + ".agents/roles/verifier.md": [ + "Use the resolved PR base, not a fixed `origin/main`, for every diff-based author check, including stacked PRs." + ], + "docs/notes/pr-ready-state.md": [ + "Use the resolved PR base, not a fixed `origin/main`, for every diff-based author check, including stacked PRs.", + "Bind `--repo` to the base repository — checkout inference can select the wrong same-number PR on fork PRs." + ], + ".agents/skills/backlog-sweep/SKILL.md": [ + "git remote -v # origin fetch and push must serve mento-protocol/monitoring-monorepo git status --porcelain # must print nothing git fetch origin main # only after both origin URLs pass", + "use the operating-card preflight to resolve and fetch the pull request base, or verified `origin/main` without a pull request. Set `BASE_REMOTE` and `baseRefName` for that base.", + "Run dashboard coverage or scoped related tests, browser work, production builds, and size-limit work without another command-heavy check set." + ], + ".claude/skills/backlog-sweep/SKILL.md": [ + "Run dashboard coverage or scoped related tests, browser work, production builds, and size-limit work without another command-heavy check set." + ], + "docs/notes/agent-quality-gate-mechanics.md": [ + "This mapping describes the optional retained diagnostic. Normal author work follows the matching direct checks in step 3 of the [PR operating card](pr-operating-card.md) and does not invoke the gate.", + "The [PR operating card](pr-operating-card.md#the-loop) owns normal direct author checks and closeout sequencing.", + "Apply every direct author-check row selected by either axis to `final_head`; do not invoke the legacy gate." ] } diff --git a/scripts/setup.sh b/scripts/setup.sh index 0ec66bbb3..4b5ce51ea 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -189,13 +189,4 @@ install_marker_write "$codegen_marker" "$codegen_hash" echo "" echo "✅ Setup complete. You're ready to work and push." echo "" -echo "Before every push from a server/worktree, run the pre-push checks manually:" -echo " git fetch origin main:refs/remotes/origin/main" -echo " ./tools/trunk fmt --all" -echo " ./tools/trunk check --ci --all" -echo " pnpm dashboard:react-doctor:diff" -echo " pnpm --filter @mento-protocol/ui-dashboard typecheck" -echo " pnpm --filter @mento-protocol/indexer-envio typecheck" -echo " pnpm --filter @mento-protocol/indexer-envio test" -echo " pnpm indexer:codegen" -echo " pnpm --filter @mento-protocol/ui-dashboard test:coverage" +echo "Before publishing an agent-authored PR, follow docs/notes/pr-operating-card.md." diff --git a/scripts/workflows/check-no-skip-audit.test.mjs b/scripts/workflows/check-no-skip-audit.test.mjs index 5ebfba15e..ad8c0990d 100644 --- a/scripts/workflows/check-no-skip-audit.test.mjs +++ b/scripts/workflows/check-no-skip-audit.test.mjs @@ -94,8 +94,8 @@ const MUTATIONS = [ ["independent called concurrency", CI, "format('ci-no-skip-{0}', github.run_id)", "format('ci-no-skip-{0}', inputs.audit_source_sha)", /keep audit runs independent/u], ["force-all audit", CI, "${{ inputs.no_skip_audit || steps.filter.outputs.controlPlane", "${{ steps.filter.outputs.controlPlane", /force every routed job/u], ["retained audit input description", CI, "description: Run every retained deterministic job", "description: Run every deterministic job", /reusable CI audit inputs/u], - ["legacy indexer router in audit", CI, " - name: Legacy indexer routing parity suite\n # This remaining suite checks only the legacy local gate's table and\n # checklist router. The no-skip audit measures retained commands.\n if: ${{ !inputs.no_skip_audit }}", " - name: Legacy indexer routing parity suite\n # This remaining suite checks only the legacy local gate's table and\n # checklist router. The no-skip audit measures retained commands.", /exclude the exact legacy local-gate step inventory/u], - ["legacy Bash gate in audit", CI, " - name: Agent quality-gate routing regression suite\n # Keep the mandatory legacy gate safe during the shadow period. The\n # no-skip audit measures only commands retained after gate retirement.\n if: ${{ !inputs.no_skip_audit }}", " - name: Agent quality-gate routing regression suite\n # Keep the mandatory legacy gate safe during the shadow period. The\n # no-skip audit measures only commands retained after gate retirement.", /exclude the exact legacy local-gate step inventory/u], + ["legacy indexer router in audit", CI, " - name: Legacy indexer routing parity suite\n # This remaining suite checks only the optional legacy diagnostic's\n # table and checklist router. The no-skip audit measures retained\n # commands.\n if: ${{ !inputs.no_skip_audit }}", " - name: Legacy indexer routing parity suite\n # This remaining suite checks only the optional legacy diagnostic's\n # table and checklist router. The no-skip audit measures retained\n # commands.", /exclude the exact legacy local-gate step inventory/u], + ["legacy Bash gate in audit", CI, " - name: Agent quality-gate routing regression suite\n # Optional legacy diagnostic regression; no-skip measures required CI.\n if: ${{ !inputs.no_skip_audit }}", " - name: Agent quality-gate routing regression suite\n # Optional legacy diagnostic regression; no-skip measures required CI.", /exclude the exact legacy local-gate step inventory/u], ["legacy routing table in audit", CI, " # It is not part of the retained no-skip target command set.\n if: ${{ !inputs.no_skip_audit }}\n run: pnpm gate:routing-table:test", " # It is not part of the retained no-skip target command set.\n run: pnpm gate:routing-table:test", /exclude the exact legacy local-gate step inventory/u], ["extra legacy command in audit", CI, " run: bash scripts/bootstrap/agent-setup-contract.test.sh\n - name: Agent quality-gate routing regression suite", " run: bash scripts/bootstrap/agent-setup-contract.test.sh\n - name: Unreviewed legacy gate copy\n run: pnpm run agent:quality-gate:test\n - name: Agent quality-gate routing regression suite", /exclude the exact legacy local-gate step inventory/u], ["renamed direct legacy Bash suite", CI, " run: bash scripts/bootstrap/agent-setup-contract.test.sh\n - name: Agent quality-gate routing regression suite", " run: bash scripts/bootstrap/agent-setup-contract.test.sh\n - name: Renamed direct legacy gate copy\n run: bash scripts/agent-quality-gate.test.sh\n - name: Agent quality-gate routing regression suite", /exclude the exact legacy local-gate step inventory/u], diff --git a/shared-config/AGENTS.md b/shared-config/AGENTS.md index 65202f27f..80c0fd1ec 100644 --- a/shared-config/AGENTS.md +++ b/shared-config/AGENTS.md @@ -3,7 +3,7 @@ title: Shared Config Instructions status: active owner: eng canonical: true -last_verified: 2026-07-23 +last_verified: 2026-09-02 doc_type: agent-instructions scope: shared-config review_interval_days: 90 @@ -44,7 +44,9 @@ calendar data, thresholds, and shared ABIs. ## Verification -The shared-config mapping for `pnpm agent:quality-gate --run` covers lint, -typecheck, tests, coverage, knip, clean build, direct-consumer typechecks, -dashboard bundle size, and conditional indexer mirror checks. Consumer-only -mappings clean-build this package before loading its ignored `dist/` output. +Run the direct package checks from step 3 of the +[PR operating card](../docs/notes/pr-operating-card.md). Also run +`pnpm --filter @mento-protocol/config build` before a direct consumer check so +the consumer loads current `dist/` output. Required CI owns coverage, Knip, +downstream consumer, dashboard bundle-size, and conditional indexer-mirror +coverage.