Skip to content

feat(ENG-014): per-agent decision log + traceable provenance DAG - #11

Merged
tobyvee merged 1 commit into
mainfrom
feat/eng-014-decision-log
Jun 27, 2026
Merged

tobyvee merged 1 commit into
mainfrom
feat/eng-014-decision-log

Conversation

@tobyvee

@tobyvee tobyvee commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Closes ENG-014 (Wave 4). Makes decision provenance first-class — the same "make an implicit thing explicit" pattern as ENG-006 (approvals), applied to why the unit did what it did. Decisions form a DAG traceable to the originating request, layered over (and referencing, never copying — invariant #2) the append-only audit log.

What's added

  • core — a Decision zod schema (OpenTelemetry-trace-compatible: rootRequestId ≈ trace id, parentDecisionIds = span parents; a DAG, not a tree) and a DecisionLog port (record/get/listByRoot/byWorkItem/traverseToRoot) added to Persistence. A pure, unit-tested traceToRoot BFS is single-sourced and shared by backends.
  • db — an append-only decisions table (parent-id edge set, hierarchy FKs, link back to the audit event), repo functions, DbDecisionLog, and migration 0005.
  • integrations — KnowledgeBackedDecisionLog, the hybrid the ticket recommends: Postgres indexes the queryable node/edges (integrity, traversal); the KB stores a human-readable Markdown body — PR-reviewable files on the GitHub backend.
  • server — a per-epic root request node (trace id = epicId) seeded idempotently; each agent step (shape · decompose · implement · QA) emits a structured decision chained to its parent(s), work item, and audit event; a traversal API (GET /api/decisions?root=…|?ticketId=…, /api/decisions/:id, /api/decisions/:id/trace). Provenance writes are best-effort so they never break the lifecycle.

Acceptance criteria

  • Every agent step (shape/decompose/implement/QA) emits a structured decision linked to its parent(s) + work item.
  • Each decision chains to the originating request (root), verifiable by a traversal API.
  • A backend-pluggable, append-only core DecisionLog port (Postgres index + GitHub-doc body).
  • Decision bodies are human-readable (PR-reviewable on the GitHub backend).
  • Decisions reference audit events / KB artifacts rather than duplicating them.

Design note

The decision graph indexes in Postgres (like the audit log, it's the queryable substrate) and writes its body to whatever KB the backend uses — this is the ticket's "A as the index, B for the body" hybrid, and keeps core backend-agnostic (invariant #5). No graph DB stood up.

Tests

Decision schema + DAG traversal (linear / multi-parent / unknown id); KnowledgeBackedDecisionLog fan-out + read delegation + KB-failure resilience; doc renderer. pnpm typecheck · lint · test (113) · build all green.

🤖 Generated with Claude Code

Make decision provenance first-class — the same "make an implicit thing
explicit" pattern as ENG-006 (approvals), applied to *why* the unit did what
it did. Decisions form a DAG traceable to the originating request, layered
over (and referencing, never copying) the append-only audit log.

- core: `Decision` zod schema (OpenTelemetry-trace-compatible: rootRequestId ≈
  trace id, parentDecisionIds = span parents; DAG, not a tree) + a `DecisionLog`
  port (record/get/listByRoot/byWorkItem/traverseToRoot) added to `Persistence`.
  A pure, unit-tested `traceToRoot` BFS shared by backends.
- db: append-only `decisions` table (parent-id edge set, hierarchy FKs, link
  back to the audit event) + repo fns + `DbDecisionLog` + migration 0005.
- integrations: `KnowledgeBackedDecisionLog` — the hybrid recommended in the
  ticket: Postgres indexes the queryable node/edges, the KB stores a
  human-readable Markdown body (PR-reviewable files on the GitHub backend).
- server: a per-epic root request node (trace id = epicId) seeded idempotently;
  each agent step (shape · decompose · implement · QA) emits a structured
  decision chained to its parent(s) + work item + audit event; traversal API
  (`GET /api/decisions`, `/:id`, `/:id/trace`). Provenance writes are
  best-effort so they never break the lifecycle.

Tests: decision schema + DAG traversal (linear/multi-parent/unknown);
KnowledgeBackedDecisionLog fan-out + read delegation + KB-failure resilience;
doc renderer. typecheck/lint/test (113)/build all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tobyvee
tobyvee merged commit 4b3b75e into main Jun 27, 2026
1 check passed
@tobyvee
tobyvee deleted the feat/eng-014-decision-log branch June 27, 2026 07:35
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