From 3da5358b33319a64836975cf489fc60b0dcbfcd3 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Wed, 29 Jul 2026 10:08:29 -0700 Subject: [PATCH] test(U9): add a core unit-gate so dependency gating and FN-5819 block merges (#2569) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **U9, PR10.** Two `package.json` lines. No test or production changes — this only decides *when* existing tests run. ## The gap Two U9 safeguards are well covered but sat in **no blocking gate**. Their proof lives in `packages/core/src/__tests__/task-merge.test.ts`, and core's only gate job is `test:pg-gate` (two PG tests). A regression in either surfaced in non-blocking full-suite — after the merge. ## What's now gated, each verified by mutation delta **`task-merge.test.ts`** | Invariant | Mutation | NEW failures | |---|---|---| | Safeguard 3 — dependency gating | `getTaskCompletionBlocker` drops the unresolved-dependency reason | **5** | | FN-5819 — exception bounded to a live group | drop `group.status === "open"` | **1** | | FN-5819 — exception bounded to shared members | widen `isSharedBranchGroupMemberIntegration` to every task | **4** | Both FN-5819 directions matter. This is the **only** scoped exception to `autoMerge:false`, so its *narrowness* is the invariant — not merely its existence. A test that only proves the exception works would pass while the exception swallowed every task. **`legacy-adoption.test.ts`** | Invariant | Mutation | NEW failures | |---|---|---| | FN-8492 — orphaned pending results REWRITTEN to failed, never DELETED | delete instead of rewrite | **2** | That one matters because deletion *silently satisfies* the merge gate: the gate blocks on pending/failed results, not on an enabled step with no result, so deleting lets a task merge with its review skipped. ## Implementation Adds `packages/core` → `test:unit-gate`, a curated **non-PG allow-list** mirroring `engine-core`'s discipline (explicit membership, not a glob), run as a third parallel job in the root `test:gate` block alongside the engine and PG jobs. **Gate fires — verified, not assumed:** - drop the dependency reason → `pnpm test:gate` **exits 1** - drop the FN-5819 open-group bound → **exits 1** - restored → **exits 0** ## Cost: no measurable increase | | Runs | |---|---| | baseline | 13.07s, 14.95s | | with the job | 12.20s, 12.58s | It runs in parallel with the existing jobs and finishes well inside them, so the delta sits inside run-to-run variance. **I am not claiming a speedup** — the honest reading is "no measurable cost", and the variance band here is wider than the change. ## Reversible call made rather than asked A new `test:unit-gate` script rather than widening `test:pg-gate` or adding a glob. `test:pg-gate` carries PG setup these pure unit tests do not need, and a glob would admit all of core by default — which AGENTS.md explicitly forbids ("tests never graduate into the gate by default"). Membership stays explicit so the next addition has to state its evidence. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) --- package.json | 2 +- packages/core/package.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b6986dab4d..43d2712ead 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "check:changesets": "node scripts/check-changeset-format.mjs", "check:quarantine-ledger": "node scripts/check-quarantine-ledger.mjs", "check:mock-completeness": "node scripts/check-mock-completeness.mjs", - "test:gate": "node scripts/check-no-nohup.mjs && node scripts/check-no-cwd-relative-dashboard-test-reads.mjs && node scripts/check-no-kill-4040.mjs && node scripts/check-no-getdatabase.mjs && node scripts/check-capacity-pool-id.mjs && node scripts/check-no-node-only-core-imports-in-dashboard.mjs && node scripts/check-pi-versions-pinned.mjs && node scripts/check-no-test-timeout-appeasement.mjs && node scripts/check-changeset-format.mjs && node scripts/check-mock-completeness.mjs && sh -c 'pnpm --filter @fusion/engine test:core & engine_pid=$!; pnpm --filter @fusion/core test:pg-gate & pg_pid=$!; status=0; wait $engine_pid || status=1; wait $pg_pid || status=1; exit $status' && pnpm --filter @runfusion/fusion test:ci-shape", + "test:gate": "node scripts/check-no-nohup.mjs && node scripts/check-no-cwd-relative-dashboard-test-reads.mjs && node scripts/check-no-kill-4040.mjs && node scripts/check-no-getdatabase.mjs && node scripts/check-capacity-pool-id.mjs && node scripts/check-no-node-only-core-imports-in-dashboard.mjs && node scripts/check-pi-versions-pinned.mjs && node scripts/check-no-test-timeout-appeasement.mjs && node scripts/check-changeset-format.mjs && node scripts/check-mock-completeness.mjs && sh -c 'pnpm --filter @fusion/engine test:core & engine_pid=$!; pnpm --filter @fusion/core test:pg-gate & pg_pid=$!; pnpm --filter @fusion/core test:unit-gate & unit_pid=$!; status=0; wait $engine_pid || status=1; wait $pg_pid || status=1; wait $unit_pid || status=1; exit $status' && pnpm --filter @runfusion/fusion test:ci-shape", "smoke:boot": "node scripts/boot-smoke.mjs", "local": "node scripts/start-local.mjs", "dev": "node scripts/dev-with-memory.mjs", diff --git a/packages/core/package.json b/packages/core/package.json index aeebbb1a5f..3b049e3eeb 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -48,7 +48,8 @@ "typecheck": "tsc --noEmit", "test": "vitest run --silent=passed-only --reporter=dot", "test:embedded-postgres": "vitest run src/__tests__/postgres/embedded-lifecycle.test.ts --silent=passed-only --reporter=dot", - "test:pg-gate": "vitest run --config vitest.pg.config.ts src/__tests__/postgres/handoff-to-review-atomicity.pg.test.ts src/__tests__/postgres/task-lifecycle-e2e.pg.test.ts --silent=passed-only --reporter=dot" + "test:pg-gate": "vitest run --config vitest.pg.config.ts src/__tests__/postgres/handoff-to-review-atomicity.pg.test.ts src/__tests__/postgres/task-lifecycle-e2e.pg.test.ts --silent=passed-only --reporter=dot", + "test:unit-gate": "vitest run src/__tests__/task-merge.test.ts src/__tests__/legacy-adoption.test.ts --silent=passed-only --reporter=dot" }, "devDependencies": { "@earendil-works/pi-coding-agent": "0.82.1",