Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
85 lines
4.4 KiB
Markdown
85 lines
4.4 KiB
Markdown
---
|
||
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 `<automated>` 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
|