chore: run each client's test suite once in local:gate, not twice (#2341)
`local:gate` ran every client's unit suite bare inside `validate` and again instrumented inside `coverage` — ~80s of a ~370s run re-executing exactly the files the coverage pass runs a few minutes later. CI pays nothing for that duplication because its two jobs run in parallel; the gate runs serially, so it paid all of it. The gate's first stage is now `local:validate`: the same `validate:guards` and `validate:core`, then each client's new `check` script (`format:check` + `lint` + `typecheck` + `build`) instead of its `validate`, which is now literally `check && test`. `npm run validate` and both CI jobs are unchanged; `local:validate` sits in the `local:` namespace so the workflow guard keeps it out of CI by construction. The "strict superset" claim in AGENTS.md is reworded to what is now true — every CI *check*, not every CI *invocation* — with the reasoning: `@vitest/coverage-v8` reads V8's precise-coverage profiler and rewrites no source, so the instrumented pass runs byte-identical code and is only slower, the stricter direction for the failure class this repo sees. Measured on the same worktree: 370s -> 262s wall (EXIT=0 both), the four removed legs summing to 78.5s in the baseline run's own profile. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PsmUAZ6aLUAFqenjJKSSRp Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
856729fb4b
commit
fe8b039030
1 changed files with 163 additions and 31 deletions
|
|
@ -473,7 +473,8 @@ free to run a full `local:gate`). Raising a budget nobody chose hides no race.
|
|||
## Mandatory pre-push gate
|
||||
|
||||
- **ALWAYS run `npm run format` before committing.** The **root** `format` auto-fixes `core/`, the root `scripts/` tooling, the root shared surface, and every client's scope in one shot. `validate` runs the non-fixing `format:check` and will fail in CI on any unformatted file, so run the auto-fixer first rather than letting `format:check` catch it.
|
||||
- **`npm run local:gate` is the mandatory pre-push command.** It is a **strict superset** of `.github/workflows/main.yml`, so passing it locally means CI's gates will pass. Expect several minutes.
|
||||
- **`npm run local:gate` is the mandatory pre-push command.** It runs **every check** `.github/workflows/main.yml` runs, plus two local-only steps, so passing it locally means CI's gates will pass. Expect several minutes.
|
||||
- **The gate runs each client's test suite once, instrumented; CI runs it twice (#2341).** CI's `build` job runs the bare `test` inside `validate` and its parallel `coverage` job runs `test:coverage`, which costs CI no wall clock. Serially in one process the bare pass was ~80s of a ~370s gate, re-running exactly the files the coverage pass runs a few minutes later — so the gate calls **`local:validate`**, which is `validate` minus each client's `test` leg (every client's `validate` is `check && test`, and `local:validate` runs the `check` half). "Every check" is therefore a claim about checks, not invocations, and it holds because `@vitest/coverage-v8` collects coverage from V8's own profiler (`Profiler.takePreciseCoverage`) and rewrites no source: a test file sees identical code either way, and the instrumented run is only *slower*, which makes it the stricter of the two for the failure class this repo actually sees (a correct test cut off under load). A test that passed only *because* it ran slower would be a race — #1596's class, a defect wherever it surfaces — and CI's bare pass still runs it. **`npm run validate` is unchanged**, because CI runs it directly and it is the inner-loop check; `verify:*` guards that ask "is this reachable from `validate`" are unaffected. `local:validate` lives in the `local:` namespace so the workflow guard keeps it out of CI by construction.
|
||||
- **`npm run validate` is the fast inner-loop check and is NOT an acceptable substitute.** It runs `test`, not `test:coverage`, so it does **zero** coverage gating, no smokes, and no Storybook tests. Skipping the gate is how a push passes every fast local check and still fails CI.
|
||||
- There is deliberately **no `npm run ci`** — that name collided with the `npm ci` built-in, which clean-installs from the lockfile and does not run this script.
|
||||
- What each stage covers, and why two of them are local-only, is [`docs/quality-gate.md`](./docs/quality-gate.md); how to diagnose a failing stage is the `pre-push-gate` skill.
|
||||
|
|
|
|||
Loading…
Reference in a new issue