Skip to content

feat(task-manager): durable task system with append-only event history#132

Open
codeaholicguy wants to merge 1 commit into
mainfrom
feature-task-system
Open

feat(task-manager): durable task system with append-only event history#132
codeaholicguy wants to merge 1 commit into
mainfrom
feature-task-system

Conversation

@codeaholicguy

Copy link
Copy Markdown
Owner

Summary

Introduces @ai-devkit/task-manager as the durable unit for development/debug work. A task has a stable id and encapsulates artifacts, evidence, progress, blockers, lifecycle phase, agent attribution, branch/worktree/PR links, and an append-only event history.

This also publishes a locked Task/TaskEvent contract that a separate tracing worker (agent-session-tracing) builds against as a dependency-inversion port — type names, field names, event-type strings, and method signatures are frozen.

What's included

  • New package @ai-devkit/task-manager mirroring @ai-devkit/memory:
    • TaskService (storage-agnostic; consume-only surface) — 18 async methods.
    • TaskStore SPI + FileTaskStore — atomic task.json writes (temp-file + rename), append-only events.jsonl.
    • Locked types: Actor, Task, TaskEvent, and a closed set of 14 task.* event types.
    • Stable ids (task-<YYYYMMDDHHMMSS>-<4 base36>), collision-safe, lexicographically sortable.
  • CLI ai-devkit task ...: create/list/show/update/phase/status/progress/next/blocker/evidence/artifact/assign/note/event/close, with --json and attribution flags.
  • Contract of record: docs/ai/design/2026-07-01-feature-task-system.md + ...CONTRACT.md quick reference.

Storage layout (file-backed MVP, frozen)

~/.ai-devkit/tasks/<task-id>/
  task.json      # snapshot, authoritative for reads, atomic write
  events.jsonl   # append-only audit trail, one JSON object per line

Storage-agnostic by design: a future SqliteTaskStore implements the same TaskStore SPI without changing callers.

Key decisions

  • One task per feature; phase is a single advancing field (not one task per phase).
  • Snapshot + append-only events (not pure event sourcing) — reads are cheap; full audit trail preserved. Replay is a documented future capability.
  • Artifacts are references only — store never copies files.

Validation

Command Result
nx run-many -t test (6 projects) 890 passing, 0 failing (73 test files)
nx run-many -t build (6 projects) Success
nx run-many -t lint (6 projects) 0 errors (5 pre-existing warnings, none in new code)
task-manager coverage 93.5% stmt / 78.5% branch / 98.6% func / 94.1% line (≥75% thresholds)
E2E CLI smoke (full lifecycle) create→phase→progress→evidence→blocker→note→close ✓; storage layout confirmed
Contract integrity All exported type names + 14 event strings + 18 method names match the contract

Tests

  • packages/task-manager/tests/unit/{ids,actor-resolver,errors}.test.ts
  • packages/task-manager/tests/integration/{file-store,service,add-event-coverage}.test.ts
  • packages/cli/src/__tests__/commands/task.test.ts (20 tests, mocked service)

Risks / limitations (MVP)

  • Single-writer assumption per task — no fs-level locking yet (documented; concurrency is out of MVP scope).
  • Snapshot authoritative; event-sourced replay deferred — events already carry enough to reconstruct.
  • No project management — no boards/milestones/hierarchies/permissions (intentional non-goal).
  • package-lock.json includes an npm-enforced version sync (0.45.0→0.46.0) required to add the new workspace entry; root package.json was already 0.46.0.
  • Coordination: agent-session-tracing has ACK'd the contract and is building against it; do not change Task/TaskEvent field names or event-type strings after merge without coordinating.

🤖 Generated with assistance from the ai-devkit dev-lifecycle skills. Not for merge — awaiting review.

codeaholicguy added a commit that referenced this pull request Jul 1, 2026
)

Add a guarded integration test proving the real TaskService (shipped on
feature-task-system) satisfies the tracing ITaskService port end-to-end, with
NO mapping-logic divergence. Round-trips every semantic (ensureFeatureTask,
phase/progress/nextStep/blocker/evidence/attribution/note/custom/close) through
the real service + file-backed store and asserts the exact contract event-type
strings + persisted snapshot.

- tests/integration.task-manager.test.ts: skips cleanly (1 passed | 5 skipped)
  when @ai-devkit/task-manager is not resolvable, so standalone CI is green
  before #132 merges; auto-activates once #132 lands. Both states verified.
- .eslintrc.json: add package lint config (mirrors @ai-devkit/agent-manager).
- README/implementation/testing: mark wiring SHIPPED; note the real TaskService
  is assignable to the port via method bivariance (no port change needed).

Validation (fresh, real package resolvable): tsc --noEmit exit 0; vitest run
44 passed (38 unit + 6 real integration) exit 0; build exit 0; eslint 0 errors.
Standalone (package absent): 39 passed | 5 skipped, exit 0.
@codeaholicguy codeaholicguy force-pushed the feature-task-system branch 2 times, most recently from e412ac7 to 852f83a Compare July 1, 2026 20:08
…story

Introduce @ai-devkit/task-manager as the durable unit for development/debug
work. A task has a stable id and encapsulates artifacts, evidence, progress,
blockers, lifecycle phase, agent attribution, branch/worktree/PR links, and an
append-only event history.

- SQLite storage at ~/.ai-devkit/tasks.db via better-sqlite3 (same library and
  WAL/busy_timeout approach as @ai-devkit/memory): a tasks table of snapshots and
  a task_events table for the append-only history. Versioned migrations tracked
  with the user_version pragma.
- Storage-agnostic: TaskService depends only on a TaskStore SPI so storage can be
  swapped without changing callers; SqliteTaskStore is the default impl.
- Stable task ids (task-<YYYYMMDDHHMMSS>-<6 base36>), one task per feature with
  phase as a single advancing field, 14 task.* event types.
- CLI: ai-devkit task create/list/show/update/phase/status/progress/next/
  blocker/evidence/artifact/assign/note/event/close, with --json and attribution.
- Tests: 890 passing repo-wide; task-manager coverage 92% stmt / 79% branch.

Public API (Task/TaskEvent shapes, TaskService method signatures, CLI commands,
event type strings) is stable. Note vs the original file-backed draft: exports
swapped (FileTaskStore -> SqliteTaskStore, resolveStoreRoot -> resolveDbPath)
and env var renamed (AIDEVKIT_TASKS_DIR -> AIDEVKIT_TASKS_DB); TaskService
method signatures and event types are unchanged.
@codeaholicguy codeaholicguy force-pushed the feature-task-system branch from 852f83a to ce60124 Compare July 1, 2026 20:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant