--- phase: 9 slug: faster-write-back status: draft nyquist_compliant: false wave_0_complete: false created: 2026-06-12 --- # Phase 9 — Validation Strategy > Per-phase validation contract for feedback sampling during execution. --- ## Test Infrastructure | Property | Value | |----------|-------| | **Framework** | Vitest (existing) | | **Config file** | `apps/api/vitest.config.ts` | | **Quick run command** | `cd apps/api && npx vitest run tests/broker/outboxWorker.test.ts` | | **Full suite command** | `cd apps/api && npm test` (→ `vitest run`) | | **Estimated runtime** | ~5–20 seconds (existing broker suite + new signal cases; no live Fastmail) | --- ## Sampling Rate - **After every task commit:** Run quick command (`vitest run tests/broker/outboxWorker.test.ts`) - **After every plan wave:** Run full suite (`npm test`) + `npm run typecheck` (`tsc --noEmit` — esbuild/Vitest does not catch type errors; see [[vitest-passes-tsc-fails]]) - **Before `/gsd-verify-work`:** Full suite + typecheck must be green - **Max feedback latency:** ~20 seconds --- ## Per-Task Verification Map > Task IDs are assigned by the planner; rows below map each Success Criterion + CAL-15 to its > concrete automated assertion (Nyquist coverage). The signal-path tests need no fake timers — > a `setImmediate`/microtask flush is sufficient to observe the synchronous emit → drain wiring > (per RESEARCH.md). The 15s `setInterval` fallback is exercised with Vitest fake timers as today. | Item | Wave | Requirement | Threat Ref | Expected Behavior | Test Type | Automated Command | File Exists | Status | |------|------|-------------|------------|-------------------|-----------|-------------------|-------------|--------| | SC-1 signal → prompt drain | 1 | CAL-15 | — | Enqueuing a pending row publishes the trigger and `runOutboxDrain` runs without waiting for the 15s interval (CalDAV dispatch stubbed) | unit/integration | `vitest run tests/broker/outboxWorker.test.ts` | ✅ extends existing | ⬜ pending | | SC-2 fire-and-forget 202 | 1 | CAL-15 | — | Publishing the signal is non-blocking; route enqueue path makes no inline CalDAV call (signal is fire-and-forget) | unit | `vitest run tests/broker/outboxWorker.test.ts` | ✅ extends existing | ⬜ pending | | SC-3 create-before-delete under move | 1 | CAL-15 | — | Edit-as-move publishes once after the transaction commits; CREATE row precedes DELETE; no signal fires between the two inserts | unit | `vitest run tests/broker/outboxWorker.test.ts` | ✅ extends existing | ⬜ pending | | SC-4 exactly-once overlap | 1 | CAL-15 | — | Concurrent `scheduleOutboxDrain` calls + 15s fallback overlap produce no duplicate CalDAV PUT for the same uid (`isDraining` guard + `pending AND next_attempt_at <= NOW()` selection unchanged) | unit | `vitest run tests/broker/outboxWorker.test.ts` | ✅ extends existing | ⬜ pending | | SC-5 / D-05 trailing re-drain | 1 | CAL-15 | — | A signal arriving during an in-flight drain sets `drainRequested` and triggers exactly one follow-up drain after the current one finishes; the 15s `setInterval` fallback still runs and recovers missed rows | unit | `vitest run tests/broker/outboxWorker.test.ts` | ✅ extends existing | ⬜ pending | *Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky* --- ## Wave 0 Requirements - Existing infrastructure covers all phase requirements. `apps/api/tests/broker/outboxWorker.test.ts` already provides the DB / write / sync mock scaffold (`isDraining`, drain, edit-as-move ordering). New cases are added to that file (or a sibling `tests/broker/outboxTrigger.test.ts`); no new framework, config, or fixtures are installed. --- ## Manual-Only Verifications | Behavior | Requirement | Why Manual | Test Instructions | |----------|-------------|------------|-------------------| | — | — | — | — | *All phase behaviors have automated verification. No operator-stopwatch checkpoint (D-10): the dev-bypass user (id 1) has no CalDAV credential/calendars, so a live event-create 422s in the dev stack ([[dev-data-user1-no-calendars]]); the automated wiring test is the durable, CI-guarded evidence.* --- ## Validation Sign-Off - [ ] All tasks have `` verify or Wave 0 dependencies - [ ] Sampling continuity: no 3 consecutive tasks without automated verify - [ ] Wave 0 covers all MISSING references - [ ] No watch-mode flags (`vitest run`, not `vitest`) - [ ] Feedback latency < 20s - [ ] `nyquist_compliant: true` set in frontmatter **Approval:** pending