verify
Run and fix the software-factory verification gate (scripts/verify.sh) from the repo root — format, build, config-JSON and oxlint-plugin guards, typecheck, lint, knip, tests with coverage thresholds a
Файлы1
Открыть в GitHubSKILL.md.claude/skills/verify/SKILL.md
GitHubVerify
Run every command from the repo root. Tests only resolve from there.
Which path to run
| When | Command |
|---|---|
| Before every commit (fast loop) | bash scripts/verify.sh --no-e2e |
| Before you push (adds the coverage ratchet) | bash scripts/verify.sh |
| Pipeline integration suites (on demand) | npm run test:integration |
The factory's own CHECK phase runs bash scripts/verify.sh --no-e2e in the build worktree (packages/core/src/checkers/index.ts).
What scripts/verify.sh runs, in order
npm cinpm run format:check(Prettier, includes Markdown)npm run build(tsc -b)npm run adr:index -- --check— the ADR index table indocs/adr/README.mdmust match the ADR filesbash scripts/check-config-json.sh— no JSON may exist underpackages/config/srcordist(#716)bash scripts/check-oxlint-plugin-version.sh—@oxlint/pluginsmust matchoxlintexactly (#795)npm run typechecknpm run lint— Oxlint, type-aware,--deny-warningsnpm run knip— dead code and unused dependencies- Tests:
- full path:
npm run test(Vitest with coverage thresholds), thennpm run coverage-ratchet --no-e2e:npm run test(Vitest with coverage thresholds), no ratchet- after the tests,
npm run slowest-testsprints the 5 slowest files andnpm run test-budgetcompares the test-step wall-clock time againstTEST_BUDGET_SECONDSinscripts/test-budget.ts(450s; override for one run withFACTORY_TEST_BUDGET_SECONDS). It printstest-budget: PASSwithin budget, a warning plus the slowest files when over locally, and fails verify in CI (CIset, e.g.CI=true) withtest-budget: FAILplus the slowest files
- full path:
npm run eval -- --stub- Shell-script tests:
auto-merge-sweep,filter-green-prs,repo-merge-settings,repo-about,repo-issue-optics,ruleset-copilot-review,launchd/install-sweep-plist,publish-workspaces(guards the publish listscripts/publish-workspaces.txtagainst the workspace graph)
CI (.github/workflows/ci.yml) runs the same checks as the full path, split into parallel jobs: static (format, build, guards, typecheck, lint, knip) and test (1/3)…test (3/3) (Vitest shards that write blob reports with raw coverage and no thresholds, via FACTORY_COVERAGE_SHARD=1). The required ci job fails unless all of them succeeded, then merges the shard reports (vitest --merge-reports) and enforces the coverage thresholds, the ratchet, and the stub eval on the merged result. A red ci names the failing job; read that job's log. CI also runs scripts/quickstart-smoke.sh in a separate job. It does not run the install-sweep-plist test.
Coverage gate and ratchet
- Thresholds live in
vitest.config.ts: one global set plus one set per package. Read the file for the current numbers. - A drop below any threshold fails
npm run test. Add tests. Never lower a threshold. npm run coverage-ratchetfails when measured coverage beats a threshold by more than 2 points (DEFAULT_RATCHET_SLACK). Raise that threshold to the suggested value it prints, in the same PR.packages/core/src/types/**andpackages/core/src/test-support/**are excluded from coverage.
Max-lines guard
No lintable file may exceed 500 lines. Tests count, and so do blank lines and comments. The limit is set in oxlint.config.ts and enforced by npm run lint (step 8). scripts/max-lines-config.test.ts enforces it again in the test step.
max-lines-baseline.json grandfathers files that were already over the limit. It is a flat JSON object that maps a repo-relative path to the line count recorded when the file was grandfathered. That count is the file's own ceiling, so the file may shrink but never grow. Never add a new entry and never raise a count. CI enforces this; see Human override.
New file over 500 lines
Lint fails with File has too many lines, and the test step fails because the file is not baselined. Split the file by responsibility into colocated modules of 500 lines or fewer. Keep .js import extensions, and split the colocated tests the same way. Do not add the file to the baseline.
Baseline file grew
Lint fails for the file, and the test step reports it grew past its recorded ceiling. Move code out, or split the file, until it is at or under its recorded count. Never raise the number.
Baseline file shrank or was deleted
The test step names the file in a remove it from max-lines-baseline.json message. Delete its line from max-lines-baseline.json so the default 500 ceiling applies again.
Human override
The CI static job's "Max-lines baseline guard" step diffs max-lines-baseline.json against the PR base. It fails on a raised count or a new entry.
Only a human may approve one, by applying the max-lines:override label to the PR. Then re-run the failed static job (or push), because a label change does not re-trigger CI. A label applied by a bot or app identity, or by a login in the FACTORY_BOT_LOGINS repo variable, does not count. Lowering or removing entries never needs the label.
Agents must never apply the label, never raise a count themselves, and never compact unrelated code to fit. They split the file, or ask a human for the label in the PR body or park comment.
Local verify.sh does not enforce this.
Integration tests
*.integration.test.ts files (real git worktrees, whole plan → build → check → ship cycles) are excluded from both verify paths. They run nightly in .github/workflows/nightly-integration.yml (07:00 UTC). Run them with npm run test:integration when you touch packages/core/src/phases/ or worktree handling.
npm run mutation (Stryker) runs on demand only. It is not part of scripts/verify.sh and CI does not run it (#805).
Fixing common failures
| Failing step | Fix |
|---|---|
format:check |
npm run format, then re-run. |
adr:index --check |
npm run adr:index, commit the README change. If it names an unparseable ADR, fix that file's # ADR-NNNN: heading or - Status: line. |
check-config-json |
Move the data into packages/config/src/defaults.ts as typed TS. Delete the JSON file. |
check-oxlint-plugin… |
Bump oxlint and @oxlint/plugins to the same version in package.json, then npm install. |
lint |
Fix the code. Warnings fail the build too. |
lint / test: max-lines |
See Max-lines guard. |
knip |
Delete the unused export, file, or dependency. |
test threshold |
Add tests for the uncovered lines the report names. |
coverage-ratchet |
Raise the named threshold in vitest.config.ts to the suggested value. |
eval --stub |
See the run-evals skill. |
| Tests pass in root, fail inside a package | Expected. Run from the repo root. Do not change packages/core/package.json's test script. |