REPO="${1:?usage: gate.sh
The task is to independently re-verify a worker commit for UI-04 (React Flow branching canvas) before letting the judge decide. Three pitfalls dominate: (1) the Playwright gate must be run via the npm script, never bare npx playwright test; (2) 3 compaction warnings from the judge are expected, not failures; (3) the judge's guard full-mode run deletes tracked test-results/ files that must be restored, and board-v2 artifacts must be updated/exported before committing.
#!/usr/bin/env bash
# gate.sh — independent re-verification of a worker commit for UI-04 (React Flow)
# Usage: gate.sh <repo-dir> <task-id>
set -euo pipefail
REPO="${1:?usage: gate.sh <repo-dir> <task-id>}"
ID="${2:?usage: gate.sh <repo-dir> <task-id>}"
cd "$REPO"
echo "==> [1/5] tsc --noEmit"
npx tsc --noEmit
echo "==> [2/5] vitest run (expect 193 passed)"
npx vitest run --reporter=basic 2>&1 | tee /tmp/verify-vitest.log
if ! grep -Eq "Tests[[:space:]]+193[[:space:]]+passed" /tmp/verify-vitest.log; then
echo "FATAL: vitest did not report 193 passed"; exit 1
fi
echo "==> [3/5] Playwright via npm run test:integration (expect 42 passed)"
echo " (NOT 'npx playwright test': it sweeps vitest specs into the default"
echo " testMatch and aborts with 'No tests found')"
npm run test:integration 2>&1 | tee /tmp/verify-pw.log
if ! grep -Eq "42[[:space:]]+passed" /tmp/verify-pw.log; then
echo "FATAL: integration suite did not report 42 passed"; exit 1
fi
echo "ALL GATES PASSED (tsc + 193 vitest + 42 Playwright)"
Why npm run test:integration, not npx playwright test: Playwright's default testMatch (**/*.@(spec|test).?(c|m)[jt]s?(x)) also matches the vitest specs in test/. Those files import from vitest, not @playwright/test, so Playwright reports No tests found and exits nonzero. The npm script pins the correct testDir/config (the e2e/ suite), yielding exactly 42 tests.
ID="<task-id>" # e.g. from `gitreins task list`
timeout 900 gitreins task complete "$ID"
# rc 0 -> proper verdict (PASS/FAIL) issued
# rc 124 -> judge overran 900s; rerun with a larger timeout
# 3 compaction warnings ARE EXPECTED (Tick 115 pitfall) — do NOT treat as failure.
# The worker may have committed without running task complete; the judge still
# evaluates the pushed commit foreman-side.
# Judge guard full-mode run deletes tracked test-results/ files -> restore them:
if git status --porcelain | grep -q '^ D test-results/'; then
git restore test-results/
fi
-- board-v2 (DuckDB): update tasks row + insert event + UPDATE board + export parquet
BEGIN;
UPDATE tasks SET status = 'done', updated_at = now()
WHERE id = 'UI04-'"'"'<task-id>'"'"';
INSERT INTO events (task_id, kind, at)
VALUES ('UI04-<task-id>', 'task_complete_verified', now());
UPDATE board SET project = 'frontend-reactflow' -- project col, NOT name
WHERE id = '<board-id>';
COPY (SELECT * FROM tasks) TO 'test-results/tasks.parquet' (FORMAT PARQUET);
COPY (SELECT * FROM events) TO 'test-results/events.parquet' (FORMAT PARQUET);
COMMIT;
git add test-results/ board-v2/tasks.* board-v2/events.* board-v2/board.*
git commit -m "UI-04: verified worker commit, board-v2 updated (tasks+event+project col)"
COPY … TO … (FORMAT PARQUET) must run before git commit — the parquet files are the tracked artifact the judge consumes; the events insert and the project column update (never the name column) are the two board-v2 mutations the judge checks.
**Verified in this environment:** - `bash -n gate.sh` → syntax OK. - Grep guards validated against realistic output: `Tests 193 passed (55 assertions)` matches the vitest regex; `42 passed (2.3s)` matches the Playwright regex; ` D test-results/screenshots/a.png` triggers the `test-results/` restore detector. - Environment check: this sandbox contains only `/workspace/problem.json` and no UI-04 checkout (`find / -iname '*reactflow*'` empty), so the full tsc/vitest/Playwright/judge stack could not be executed here — the counts (193 vitest, 42 Playwright) and the `timeout 900`/~8-min judge behavior are taken from the task spec and are the documented pass criteria. **Edge cases covered:** 1. **`npx playwright test` "No tests found"** — avoided by invoking `npm run test:integration`; gate fails loudly only if the npm script itself under-reports (< 42 passed). 2. **3 compaction warnings (Tick 115 pitfall)** — explicitly documented as expected; the gate script comments them out of the failure path, and the judge verdict is the only pass/fail signal. 3. **Worker committed without `task complete`** — judge still runs foreman-side against the pushed commit; the gate does not depend on worker-side completion. 4. **Deleted tracked `test-results/`** — detected via `git status --porcelain | grep '^ D test-results/'` and restored with `git restore` before the board-v2 commit so the diff stays clean. 5. **Board-v2 wrong-column pitfall** — `UPDATE board SET project = …` (never `name`), plus mandatory `COPY tasks/events TO parquet` inside the same transaction, committed after the restore. 6. **Judge timeout** — `timeout 900` maps rc 124 to "rerun with longer timeout" rather than an instant failure verdict.
{"model": "deepseek-v4-flash", "problem_class": "frontend-reactflow-verification", "result": "passed", "tests": 235}