ADR-004 — Plans become a DB-backed graph engine (editable + actionable in-app)
reference· tech-lead · updated 2026-06-21 · source
- Status: Accepted (2026-06-20; built by effort #560)
- Date: 2026-06-16
- Owner: Tech Lead
- Related issue: #560 (Plan Engine effort)
- Supersedes: decision #221 (2026-06-10, file-based MDX plans)
Context
- Today plans are MDX in
apps/admin/src/plans/, read from disk (src/lib/plans.ts); editing them requires an IDE + PR. - José wants to edit and act on plans from admin/desktop (or via Claude), not through an IDE.
- They aren't flat plans: it's plan → subplans (
parent+dependsOn+timeline) —product-development-flow.mdalready calls for a "product Timeline" with meetings/approvals. - The roadmap must always stay aligned — today that's manual sync work.
- Git-as-CMS rejected by José (no editing via IDE/commit).
Decision
- Move plans from files to a Plan Engine with a single graph in Postgres (existing Drizzle/Fastify). Headline: one graph, three views, actionable.
- Model — 5 tables (
@tedos/db, Drizzle/Postgres):plan_node(parent_id → tree),plan_dependency(DAGdependsOn/blocks),plan_version(append-only = versioning),plan_link(issue/PR/deploy/branch = live Deliverables, the issue#↔node map), andsync_event(idempotency / loop-prevention for the bidirectional GitHub↔graph + Vercel sync: source · external_id · payload_hash · processed_at · unique(source, payload_hash)). The fifth table was added when ADR-005 made the graph a bidirectionally synced mirror of GitHub — without it the sync echoes loop. - The roadmap is NOT a doc: it's the
timelineprojection of the same graph → aligned by construction, nothing to sync. - In-app editing + actions (create/link issue, start, status); Claude and the admin hit the same backend (Fastify endpoints exposed as MCP) — one engine, two clients.
- Body = markdown + structured blocks (Callout/Timeline/Deliverables as data), no JSX at runtime.
- Scope: plans only.
knowledge/stays file-based (governed byknowledge-base.md).
Consequences
Positive
- Edit/act without IDE or PR; roadmap always aligned; version history with diff/restore.
- The subplan-graph is the navigation (tree), not a flat list.
Negative / trade-offs
- Loses git-native review of plans (rebuilt with a human gate +
plan_version). - New write surface to GitHub + a render runtime (markdown+blocks instead of build-time MDX).
Follow-ups required (done under effort #560)
- Build: effort #560 stands up
@tedos/db(5 tables), the/plan/*API, MCP tools, the GitHub↔graph + Vercel sync, the admin/plan+/roadmapviews, and the one-shot issue ingest. The plan IS the parent issue (ADR-006) — no MDX plan file. - One-shot ingest of the existing GitHub issues →
plan_node/plan_version(guarded, idempotent). - Reconciled
plan-output-format.md,workflow-vs-product.md,kit-engine-boundary.md, CLAUDE.md; retiredpackages/engine/src/tickets.ts(#570).
Alternatives considered
| Option | Why not |
|---|---|
| Git-as-CMS (editor → commit/PR) | José: no editing via IDE/commit; not "live" |
| TinaCMS (git-backed MDX) | Still anchored to git/PR; same rejection |
| Hybrid DB + git snapshot on publish | More complex; the snapshot is added later as a "publish" action if needed |
References
- Build effort: #560 (parent issue = the plan, ADR-006)
knowledge/product-development-flow.md·.claude/rules/plan-output-format.md·.claude/rules/workflow-vs-product.md·.claude/rules/kit-engine-boundary.md- Related: ADR-005 (tasks→graph, adds
sync_event) · ADR-006 (effort workflow) - Prior decision: #221 (2026-06-10) in
decisions/log.md