Documentation Index
Fetch the complete documentation index at: https://docs.odds-api.io/llms.txt
Use this file to discover all available pages before exploring further.
PR Test Workflow Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.
Goal: Add a GitHub Actions workflow that runs all unit tests, typecheck, and lint for v3/, account-service/, and web/ on every PR, and gate merges on it passing.
Architecture: One workflow file with three parallel per-subproject jobs plus an aggregator job. Path filters skip irrelevant jobs; the aggregator (all-checks) is the single required status check so branch protection works correctly with skipped jobs.
Tech Stack: GitHub Actions, actions/setup-go@v5, actions/setup-node@v4, pnpm/action-setup@v4, Go 1.24, Node 22, pnpm.
Spec: docs/superpowers/specs/2026-05-06-ci-pr-tests-design.md
File Structure
Create:.github/workflows/pr-tests.yml— the workflow.github/workflows/README.md— branch-protection setup instructions
web/package.json— addtypecheckscriptv3/websocket/load_test.go— guard heavy test withtesting.Short()v3/websocket/load_stress_test.go— guard heavy testsv3/websocket/hub_performance_test.go— guard the performance/throughput tests (not the simple unit ones)v3/websocket/replay_benchmark_test.go— guard the latency testv3/websocket/throughput_benchmark_test.go— guard the throughput testsv3/websocket/peak_hour_fixes_test.go— guard only the integration test
Task 1: Add typecheck script to web/package.json
Files:
-
Modify:
web/package.json - Step 1: Read current scripts block
grep -n typecheck web/package.json
Expected: no matches (script doesn’t exist yet)
- Step 2: Add the script
web/package.json, in the "scripts" object, add this line after "test:watch": "vitest":
"scripts" block should end up looking like:
- Step 3: Run it locally to verify it works
cd web && pnpm typecheck
Expected: exits 0 with no output (or known pre-existing errors — note them, but don’t fix as part of this task; if there are errors, jump to Task 2 and come back)
- Step 4: Commit
Task 2: Fix any pre-existing typecheck errors in web/
Only do this task if Task 1 step 3 surfaced errors. Skip if it was clean.
Files:
-
Modify: whatever files
tsc --noEmitcomplains about - Step 1: Capture the full error list
cd web && pnpm typecheck 2>&1 | tee /tmp/web-tsc-errors.log
- Step 2: Triage
/tmp/web-tsc-errors.log. For each error:
- If it’s a real type bug → fix it
- If it’s noise from a misconfigured
tsconfig.json(e.g. excluded files being included) → fix thetsconfig.jsoninstead
any or add // @ts-ignore to make errors disappear.
- Step 3: Re-run until clean
cd web && pnpm typecheck
Expected: exits 0 with no output
- Step 4: Commit
Task 3: Audit and guard heavy Go tests with testing.Short()
The CI workflow will run go test -short ./.... Tests that should be excluded need a t.Skip guard.
Files to modify (the audit list — verify each before editing):
v3/websocket/load_test.go—TestLoadSimulation_50Clients_HighThroughputv3/websocket/load_stress_test.go—TestLoadStress_50Clients_MaxThroughput,TestLoadStress_200Clientsv3/websocket/hub_performance_test.go—TestHubThroughput,TestHubBackpressure,TestHubLastKnownStateCleanup(audit each first — skip only the truly heavy ones; the file also has lightweight tests likeTestHubClientFiltering,TestHubSportFilter,TestHubStatusFilterthat should NOT be guarded)v3/websocket/replay_benchmark_test.go—TestReplayBatchProcessingLatencyv3/websocket/throughput_benchmark_test.go—TestThroughputComparison,TestMessageDeliveryGuarantee,TestBackpressureHandlingv3/websocket/peak_hour_fixes_test.go— onlyTestPeakHourCoalescingIntegration. The other Test funcs in that file (TestCoalescing*,TestWorkerPool*,TestBookmakerSet*,TestGetBookmakerSetConsistency) are simple unit tests — leave them.
go test -run TestX -v ./websocket takes >5s on your machine, skip it under -short.
- Step 1: Audit one file
func Test* confirm whether it should be skipped under -short. Make a list.
- Step 2: Add the skip guard
TestLoadSimulation_50Clients_HighThroughput in v3/websocket/load_test.go:
- Step 3: Repeat for all files in the audit list
- Step 4: Verify the short suite passes locally
cd v3 && go test -short -race ./...
Expected: all tests pass; the heavy ones report as --- SKIP:. Should complete in well under a minute.
If you see any test panic or hang, that’s a real bug — fix the root cause, don’t skip the test.
- Step 5: Verify the full suite still works (sanity check, optional but recommended)
-short to confirm it still runs:
Run: cd v3 && go test -run TestLoadSimulation_50Clients_HighThroughput -v ./websocket
Expected: PASS (not skipped)
- Step 6: Commit
Task 4: Verify all subproject test/lint commands work locally
This catches problems with the local commands BEFORE we put them in CI, where failures are slower to debug. Files: none- Step 1: Confirm Go suite passes under
-short
gofmt -l . produces no output; everything else exits 0.
If gofmt -l . lists files, run gofmt -w <files> and commit those changes separately:
- Step 2: Confirm account-service commands work
biome check reports errors, run pnpm exec biome check . --write and commit. If pnpm typecheck reports errors, fix them — same rule as Task 2: no any, no @ts-ignore band-aids.
- Step 3: Confirm web commands work
pnpm lint reports errors, run pnpm lint:fix and commit. If pnpm build fails, fix the underlying issue.
- Step 4: Commit any fixups
Task 5: Create the workflow file
Files:-
Create:
.github/workflows/pr-tests.yml - Step 1: Create directory if needed
mkdir -p .github/workflows
- Step 2: Write the workflow
.github/workflows/pr-tests.yml with this exact content:
dorny/paths-filter@v3 inside the job (after checkout) instead of GitHub’s top-level paths: filter, then guards every meaningful step with if: steps.changes.outputs.X == 'true'. This pattern lets the job always run (so it always reports a status) but no-op when its files didn’t change. It’s the workaround for the well-known “skipped path-filtered jobs block required-checks branch protection” issue.
- Step 3: Validate the YAML locally
python3 -c "import yaml; yaml.safe_load(open('.github/workflows/pr-tests.yml'))"
Expected: no output, exit 0.
If you don’t have Python with PyYAML, alternatively use yq or just rely on the GitHub validation when you push — but local validation catches syntax errors before the CI round-trip.
- Step 4: Commit
Task 6: Document branch-protection setup
Files:-
Create:
.github/workflows/README.md - Step 1: Write the README
.github/workflows/README.md with this content:
- Step 2: Commit
Task 7: End-to-end validation on a real PR
Files: none — this validates the workflow against GitHub.- Step 1: Push the branch and open a PR
- Step 2: Watch the run
gh pr checks --watch
Expected: all four jobs (v3 (Go), account-service (TS), web (Next.js), all-checks) report success.
- Step 3: Triage failures
- Run
gh run view --log-failedto get failing step output - Reproduce locally with the exact command from that step (e.g.
cd web && pnpm test) - Fix the root cause — do NOT loosen the check to make it green. If a test is flaky in CI but passes locally, that’s a CI environment issue worth fixing (timing, missing env var, etc.), not something to retry-loop around.
- Push fix; checks rerun automatically.
- Step 4: Enable branch protection
.github/workflows/README.md to enable branch protection. This is a manual step in the GitHub UI.
- Step 5: Verify branch protection works
all-checks. If all-checks is not listed as required, the rule was misconfigured — go back to step 4.
- Step 6: Merge the PR
Done criteria
-
.github/workflows/pr-tests.ymlexists and is valid YAML -
.github/workflows/README.mdexists with setup instructions -
web/package.jsonhas atypecheckscript - Heavy Go tests skip under
-short; lightweight ones still run - All four jobs report success on the bootstrapping PR
- Branch protection is enabled and gates merges on
all-checks - PR is merged