P0.3.2 β Task CRUD — Verification
Task: P0.3.2 — Task repository (CRUD + soft-delete)
Branch: feature/p0-3-2-task-crud
Base: origin/main at 6c26bb58 (post P0.7.1)
Chain head commit: pending (verify step)
Commands executed
cd E:/AMS/.worktrees/claude/p0-3-2-task-crud
npm ci
npm test # full suite
npm run lint
npm run build
Results
Full test suite
Test Suites: 10 passed, 10 total
Tests: 564 passed, 564 total
Time: ~14 s
56 new tests added for repository.ts:
createTask— UUID v4 generation, ISO-8601 timestamps, CHECK enforcement on statusgetTask— hit, miss (null), soft-deleted visibilityupdateTask— partial update, updated_at bumped, missing row →TaskNotFoundErrordeleteTask— soft-delete setsdeleted_at, subsequentgetTaskreturns nulllistTasks— status filter, project_id filter, pagination (limit/offset), soft-delete exclusion,limit > 500 → 500clamp- Roundtrip: create → get → update → get → delete → get
- 100-task paginated retrieval — every id seen exactly once
- Prepared-statement memoization across calls
Incidental test fix (1 follow-up commit)
src/__tests__/db-init.test.ts had 6 assertions hardcoding user_version = 1 from
P0.2.2. Adding 002_tasks.sql bumps user_version to 2 and introduces one table.
Replaced hardcoded 1 with a countRealMigrations() helper that reads the
migrations directory and counts real (prefix 1..899) files. This generalises for
future migrations (P0.6.2 003_skills, P0.7.2 004_thought_records, …) without
requiring per-wave test updates. Also reworded the fresh DB has zero user tables
at the α floor test to fresh DB reflects tables introduced by applied
migrations — the α floor has no tables of its own (001_init is empty), but the
count drifts as β/ε/ζ land.
Coverage (new files — src/domains/tasks/repository.ts)
File | % Stmts | % Branch | % Funcs | % Lines
repository.ts | 100 | 100 | 100 | 100
Lint
npm run lint # eslint src → no output → clean
Build
npm run build # tsc → no errors
Acceptance criteria check
| Criterion | Status |
|---|---|
createTask(input) → UUID v4 id |
✅ |
getTask(id) → task or null |
✅ |
updateTask(id, patch) → partial update |
✅ |
deleteTask(id) → soft delete (sets deleted_at) |
✅ |
listTasks({status?, project_id?, limit?, offset?}) |
✅ |
| Prepared statements (no string interpolation) | ✅ |
| CRUD roundtrip test | ✅ |
| 100% branch coverage | ✅ |
Schema decisions (locked during implementation)
taskstable columns:id, project_id, title, description, status, priority, assignee, created_at, updated_at, deleted_atstatusCHECK enum:INIT, GATHER, ANALYZE, PLAN, APPLY, VERIFY, DONE, CANCELLED— matches βTASK_STATESfrom P0.3.1- No FK to
projects(no projects table yet in Phase 0 —project_idis plain TEXT) - Indexes:
idx_tasks_project_status (project_id, status, deleted_at),idx_tasks_deleted (deleted_at)
Deviations from packet
- Added
countRealMigrations()helper todb-init.test.tsas an incidental fix for pre-existing hardcodeduser_version = 1assertions — captured as a follow-upfeat(...)commit. - Implementation preserves separation between state-machine enforcement (P0.3.1) and CRUD (P0.3.2) —
updateTaskdoes not validate status transitions; that’s P0.3.4’s tool-layer job.
Sigma-locked conventions honored
- Migration number
002(pre-assigned) - Test path
src/__tests__/domains/tasks/repository.test.ts - UUID v4 via
crypto.randomUUID() - Prepared statements only
- No MCP tool registered (deferred to P0.3.4)
Cross-worktree leaks detected during Step 1 pre-clean
None. Clean HEAD at start of work.