FE-544: Turn tree schema and API#13
Conversation
FE-544 Turn tree schema + API
project_snapshot table. Auto-snapshot at phase transitions. Manual snapshot button. Restore from previous. Client-side diff view. |
🤖 Augment PR SummarySummary: This PR migrates Brunch’s persistence layer from a flat Changes:
Technical Notes: Active-path resolution is performed in SQLite using a recursive query from 🤖 Was this summary useful? React with 👍 or 👎 |
| id TEXT PRIMARY KEY, | ||
| id INTEGER PRIMARY KEY AUTOINCREMENT, | ||
| name TEXT NOT NULL, | ||
| active_turn_id INTEGER, |
There was a problem hiding this comment.
project.active_turn_id isn’t declared as a foreign key, and SQLite won’t enforce any REFERENCES constraints unless PRAGMA foreign_keys=ON is set, so HEAD/parent pointers can silently become invalid and break getActivePath() semantics.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
|
|
||
| return db.prepare(` | ||
| WITH RECURSIVE path AS ( | ||
| SELECT * FROM turn WHERE id = ? |
There was a problem hiding this comment.
getActivePath()’s recursive CTE doesn’t constrain by project_id, so if a parent_turn_id chain ever crosses projects (which the current schema allows), this can traverse into another project’s turns and leak history.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| saveMessage(db, project.id, 'assistant', assistantText); | ||
| updateTurn(db, turn.id, { question: assistantText }); | ||
| } | ||
| advanceHead(db, project.id, turn.id); |
There was a problem hiding this comment.
In the error path, assistantText stays empty but advanceHead() still runs, leaving HEAD pointing at a turn with question=''; subsequent formatHistory() will omit the assistant side of that exchange and degrade prompt context.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
Replace the message table with the full schema.dbml entity model (13 tables: project, turn, option, decision, assumption, requirement, criterion + 6 join tables). Project gains active_turn_id as HEAD pointer. POST /api/chat creates turns with parent chain and advances HEAD. GET /api/projects/current returns turns on the active path via recursive CTE. Client hydrates useChat from turns. Integer autoincrement PKs replace TEXT UUIDs. Entity/join tables beyond turn/option are created but unpopulated until later slices. 39 tests passing (18 db + 9 app + 12 sse-adapter). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add D15 (transitional turn-field inversion — answer=user, question=agent during pre-structured-interview phase) and D16 (integer autoincrement PKs replace TEXT UUIDs). Both surfaced during slice 3 build. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fully superseded by docs/design/schema.dbml (entity model) and memory/SPEC.md (domain semantics, decisions, lexicon). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Grill session findings added to SPEC.md: - D17: two invalidation mechanisms (path exclusion + flag propagation) - D18: Drizzle ORM replaces raw DDL (single source of truth) - D19: layered architecture with DomainEvent streaming (core → adapters) - D20: CLI executable with subcommands - A18/A19: Drizzle migrations and AsyncIterable assumptions - Lexicon: branch, checkout, path exclusion, flag propagation, core, domain event; soft invalidation updated - Architecture section rewritten for db → core → adapters layering - Constraint updated: "no automatic deletion cascading" replaces "no belief invalidation cascading" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Maps 3 places (project list, interview workspace, export preview), UI affordances per place, 20 API routes grouped by concern, data stores, and 5 key wiring flows (page load, interview turn, decision revisit, assumption falsification, phase transition). Identifies 5 candidate slices and 3 open uncertainties for ln-plan. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Type-safe routing with route loaders for data fetching on navigation. Three MVP routes per breadboard: project list, interview workspace, export preview. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Major re-plan incorporating grill + breadboard findings: - Phase 2 gains 3c (Drizzle + core extraction) and 3d (multi-project routing with TanStack Router) as architecture infrastructure - Phase 5 restructured: 11 (branch+checkout), 12 (entity lifecycle API with flag propagation), 13 (export) - Horizon updated: CLI interview, MCP adapter, graph visualizations - Dependencies and parallelism updated for new slice topology - Breadboard cross-references added to UI-touching slices Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add .agents/skills/cli-cdp/ and .agents/skills/cli-cmux/ skill defs - Update AGENTS.md manual testing section: cli-cmux for terminal panes only (not browser), cli-cdp for Chrome DevTools interaction - Include design scratch docs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ea42210 to
95d8dd0
Compare

chore: align Linear issues with PLAN.md slices
feat: migrate from flat message table to turn-tree schema
Replace the message table with the full schema.dbml entity model (13 tables:
project, turn, option, decision, assumption, requirement, criterion + 6 join
tables). Project gains active_turn_id as HEAD pointer. POST /api/chat creates
turns with parent chain and advances HEAD. GET /api/projects/current returns
turns on the active path via recursive CTE. Client hydrates useChat from turns.
Integer autoincrement PKs replace TEXT UUIDs. Entity/join tables beyond
turn/option are created but unpopulated until later slices.
39 tests passing (18 db + 9 app + 12 sse-adapter).
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
docs: record transitional turn-field mapping and integer PK decisions
Add D15 (transitional turn-field inversion — answer=user, question=agent
during pre-structured-interview phase) and D16 (integer autoincrement PKs
replace TEXT UUIDs). Both surfaced during slice 3 build.
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com