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 status
  • getTask — hit, miss (null), soft-deleted visibility
  • updateTask — partial update, updated_at bumped, missing row → TaskNotFoundError
  • deleteTask — soft-delete sets deleted_at, subsequent getTask returns null
  • listTasks — status filter, project_id filter, pagination (limit/offset), soft-delete exclusion, limit > 500 → 500 clamp
  • 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)

  • tasks table columns: id, project_id, title, description, status, priority, assignee, created_at, updated_at, deleted_at
  • status CHECK enum: INIT, GATHER, ANALYZE, PLAN, APPLY, VERIFY, DONE, CANCELLED — matches β TASK_STATES from P0.3.1
  • No FK to projects (no projects table yet in Phase 0 — project_id is plain TEXT)
  • Indexes: idx_tasks_project_status (project_id, status, deleted_at), idx_tasks_deleted (deleted_at)

Deviations from packet

  • Added countRealMigrations() helper to db-init.test.ts as an incidental fix for pre-existing hardcoded user_version = 1 assertions — captured as a follow-up feat(...) commit.
  • Implementation preserves separation between state-machine enforcement (P0.3.1) and CRUD (P0.3.2) — updateTask does 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.


Back to top

Colibri — documentation-first MCP runtime. Apache 2.0 + Commons Clause.

This site uses Just the Docs, a documentation theme for Jekyll.