Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions drizzle/0003_tidy_knowledge_layer.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
CREATE TABLE `knowledge_item` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`project_id` integer NOT NULL,
`kind` text NOT NULL,
`subtype` text,
`content` text NOT NULL,
`rationale` text,
FOREIGN KEY (`project_id`) REFERENCES `project`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
CREATE TABLE `turn_knowledge_item` (
`turn_id` integer NOT NULL,
`item_id` integer NOT NULL,
`relation` text DEFAULT 'captured' NOT NULL,
PRIMARY KEY(`turn_id`, `item_id`, `relation`),
FOREIGN KEY (`turn_id`) REFERENCES `turn`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`item_id`) REFERENCES `knowledge_item`(`id`) ON UPDATE no action ON DELETE no action
);
7 changes: 7 additions & 0 deletions drizzle/meta/_journal.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@
"when": 1775127507844,
"tag": "0002_bright_master_mold",
"breakpoints": true
},
{
"idx": 3,
"version": "6",
"when": 1775580000000,
"tag": "0003_tidy_knowledge_layer",
"breakpoints": true
}
]
}
14 changes: 10 additions & 4 deletions memory/PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,20 @@
- `6d.2` Zero selections + required free-text-only response. `done`
- `6d.3` True many-selection UX + persistence/hydration. `done`

6e. **Generic knowledge layer schema + sidebar projection** — Introduce the broader semantic layer (`framing`, `constraint`, `decision`, `assumption`, `requirement`, `criterion`) with generic provenance and graph edges, then project it cleanly into the sidebar without regressing existing reads. `not-started`
6e. **Generic knowledge layer schema + sidebar projection** — Introduce the broader semantic layer (`framing`, `constraint`, `decision`, `assumption`, `requirement`, `criterion`) with generic provenance and graph edges, then project it cleanly into the sidebar without regressing existing reads. `done`
- Requirements: → SPEC.md §Requirements #5, #6, #14
- Assumptions: → SPEC.md §Assumptions A14
- Decisions: → SPEC.md §Decisions D5, D13, D25
- Assumptions: → SPEC.md §Assumptions A14, A34, A35
- Decisions: → SPEC.md §Decisions D5, D13, D25, D49, D50, D51
- Candidate invariant goals: generic knowledge-item persistence with turn linkage; graph-edge fidelity across item kinds
- Invariants to respect: → SPEC.md §Invariants I20, I21, I23, I34
- Invariants established: → SPEC.md §Invariants I48, I49, I50, I51, I52, I53
- Acceptance: project state can load and display generic knowledge items and edges from the active path without losing current resume behavior
- **Verification approach**: inner — DB/core tests for generic item persistence and projection. Middle — workspace integration tests for sidebar hydration.
- **Observed current state (2026-04-07, tracer bullets 1–2b):** generic `knowledge_item` + `turn_knowledge_item` persistence now carries `framing`, `constraint`, `requirement`, and `criterion` items with subtype/rationale metadata, `/api/projects/:id/entities` returns those kind-specific collections plus a typed `relationships[]` projection alongside legacy decisions/assumptions, and the workspace sidebar renders Framing, Constraints, Requirements, Criteria, Decisions, and Assumptions tabs without regressing existing dependency affordances.
- **Verification approach**: inner — DB/core tests for generic item persistence and relationship projection. Middle — workspace integration tests for sidebar hydration and dependency rendering.
- Tracer bullets:
- `6e.1` Framing items through the generic knowledge seam. `done`
- `6e.2a` Legacy dependency edges through the generic entity seam. `done`
- `6e.2b` Remaining kind widening through the sidebar seam. `done`

6f. **Phase-aware observer extraction** — Teach the observer to bias extraction by mode: scope prefers framing/constraints, design prefers decisions/assumptions, later modes can surface requirements/criteria and revisions. Keep the observer as a single structured extraction pass, but give it richer context and a broader ontology. `not-started`
- Requirements: → SPEC.md §Requirements #5, #6, #11, #12
Expand Down
22 changes: 18 additions & 4 deletions memory/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ Detailed schema and mode-model rationale: `docs/design/INTERVIEW_MODE_MODEL.md`.
| A28 | AI SDK `ToolLoopAgent` with `stopWhen: stepCountIs(N)` is sufficient for brunch's multi-step interviewing, review, and phase-transition needs — no custom agent loop required | high | D31 | Agent loop, Phase transitions | Validate with mode-transition and review slices: agent must ask, synthesize, and propose closure without a handwritten loop. |
| A29 | Models can reliably compose generic filesystem tools (read, write, edit, bash, grep, find, ls) to explore and characterize an existing project | **validated** | D32 | Characterization kickoff | Validated (spike): `ToolLoopAgent` with 7 core tools explored brunch in 22 tool calls across 23 steps. See `spike/filesystem-tools.ts`. |
| A33 | Structured turn responses can replace today's single-select flow while keeping persisted response parts, transcript hydration, and interviewer-context projection aligned for the first thin slice | **validated** | D23, D24, D25, D45, D46, D47, D48 | 6d flexible turn-response model | Validated: `parts.test.ts`, `app.test.ts`, `context.test.ts`, and `InterviewWorkspace.test.tsx` now prove zero/one/many selected options plus optional free-text persist, rehydrate, and reach interviewer context coherently through the shared turn-response seam. |
| A34 | A generic knowledge-item read model can coexist with today's decision/assumption-specific writes long enough to prove sidebar projection before observer widening | **validated** | D5, D13, D22, D49, D51 | 6e generic knowledge layer, 6f observer widening | Validated: `db.test.ts`, `app.test.ts`, `workspace-data.test.ts`, and `InterviewWorkspace.test.tsx` now prove generic `framing`, `constraint`, `requirement`, and `criterion` items can persist with metadata, project through `/api/projects/:id/entities`, and render in the workspace sidebar without regressing legacy decision/assumption views. |
| A35 | A mixed-source relationship read model can project today's legacy dependency tables and new generic knowledge items through one sidebar graph seam before observer writes migrate | **validated** | D5, D13, D22, D49, D50 | 6e generic knowledge layer, 6f observer widening | Validated: `db.test.ts`, `app.test.ts`, `workspace-data.test.ts`, and `InterviewWorkspace.test.tsx` now prove legacy parent/dependency links project through the shared entities API, hydrate through the workspace loader/query seam, and render as visible sidebar dependency affordances without regressing current framing/decision/assumption tabs. |

## Decisions

Expand Down Expand Up @@ -127,6 +129,12 @@ Detailed schema and mode-model rationale: `docs/design/INTERVIEW_MODE_MODEL.md`.

48. **Choice-turn cards stage many selections locally and submit one array-shaped response seam** — Turn-card interaction now toggles zero/one/many selected options locally, then submits a single turn response carrying `positions[]` plus optional free-text through the same mutation/server boundary used by the other response paths. This keeps transcript hydration, persistence, and interviewer-context projection aligned without preserving the old immediate single-click selection behavior. Depends on: D45, D47. Supersedes: immediate single-option submit UI.

49. **Generic knowledge reads widen the entity seam before observer writes migrate** — `knowledge_item` plus `turn_knowledge_item` form the first generic knowledge persistence seam, but current observer writes for decisions and assumptions remain on their legacy tables. The shared `/api/projects/:id/entities` projection and workspace sidebar now read `framing` from the generic seam alongside legacy `decision`/`assumption` collections so slice 6e can prove the migration path incrementally before widening observer output. Depends on: D5, D13, D22. Supersedes: decision/assumption-only entity reads in the sidebar.

50. **Mixed-source dependency edges read through one typed entity-graph seam** — Legacy dependency tables still own today’s persisted edges, but `/api/projects/:id/entities` now projects them as one typed `relationships[]` payload with explicit source/target identity (`collection`, `kind`, `id`) so the workspace sidebar can render dependency affordances without waiting for observer writes to migrate to generic graph tables. Depends on: D5, D13, D22, D49. Supersedes: flat entity reads with no graph relationship projection.

51. **Generic knowledge reads stay kind-specific at the sidebar seam** — While generic knowledge items share one persistence table, the shared entities API and workspace sidebar should project `framing`, `constraint`, `requirement`, and `criterion` as distinct collections rather than a flat mixed list. This keeps tab-level affordances simple and preserves room for mixed legacy/generic writes during the migration. Depends on: D22, D49, D50. Supersedes: framing-only generic projection in the sidebar.

26. **`md-pen` for programmatic markdown rendering** — Structured data (entity tables, dependency graphs, checklists) rendered to markdown via `md-pen` rather than hand-rolled string concatenation. Pure string-return functions (`table()`, `taskList()`, `mermaid()`, `heading()`, `alert()`, `details()`) compose by nesting — no AST, no intermediate representation. Escaping is context-aware per function (table cells, URLs, code fences), eliminating a class of bugs when rendering user-supplied text from interviews. Primary use cases: (1) observer context builders presenting growing entity graphs to agents (`table()` for decisions/assumptions with metadata, `taskList()` for reviewed/unreviewed items), (2) spec export rendering active-path entities into downloadable markdown (slice 13), (3) any future agent-facing or user-facing projection of structured data. Zero dependencies, ESM-only, TypeScript-first. Depends on: —. Supersedes: hand-rolled string assembly in context builders.

### Domain model
Expand Down Expand Up @@ -214,6 +222,12 @@ Detailed schema and mode-model rationale: `docs/design/INTERVIEW_MODE_MODEL.md`.
| I45 | Interviewer history projects chosen options and/or free-text from structured turn responses when available | Slice 6d.1 / 6d.2 (single-option + free-text; free-text-only) | context.test.ts | D25, D46 |
| I46 | Free-text-only choice-turn replies require non-empty text and submit through the same turn-response seam as option picks | Slice 6d.2 (zero-selection + required free-text) | parts.test.ts, app.test.ts, InterviewWorkspace.test.tsx | D24, D47 |
| I47 | Choice-turn replies can stage and persist many selected options as one structured turn response without collapsing back to scalar selection semantics | Slice 6d.3 (many-selection UX + persistence/hydration) | app.test.ts, parts.test.ts, context.test.ts, InterviewWorkspace.test.tsx | D24, D45, D46, D48 |
| I48 | Generic `framing` knowledge items persist with project linkage and turn provenance without disturbing legacy decision/assumption storage | Slice 6e.1 (generic framing seam + sidebar projection) | db.test.ts | D49 |
| I49 | Workspace entity projections can surface `framing` items alongside legacy decision/assumption collections through the shared entity seam | Slice 6e.1 (generic framing seam + sidebar projection) | app.test.ts, workspace-data.test.ts, InterviewWorkspace.test.tsx | D22, D49 |
| I50 | Legacy decision/assumption parent links project into one typed relationship read model with stable source/target identity | Slice 6e.2a (legacy dependency edges through the entity seam) | db.test.ts | D50 |
| I51 | Workspace entity projections hydrate and render dependency relationships through the shared entity seam without regressing existing tabs | Slice 6e.2a (legacy dependency edges through the entity seam) | app.test.ts, workspace-data.test.ts, InterviewWorkspace.test.tsx | D22, D50 |
| I52 | Generic `constraint`, `requirement`, and `criterion` items project through kind-specific sidebar collections with preserved subtype/rationale metadata | Slice 6e.2b (remaining generic kinds through the sidebar seam) | db.test.ts | D49, D51 |
| I53 | Workspace entity projections hydrate and render remaining generic knowledge kinds through the shared entity seam without regressing existing tabs | Slice 6e.2b (remaining generic kinds through the sidebar seam) | app.test.ts, workspace-data.test.ts, InterviewWorkspace.test.tsx | D22, D51 |

## Lexicon

Expand Down Expand Up @@ -406,16 +420,16 @@ This projection difference is a deliberate design choice, not an implementation

| File | Tests | Protects |
| ----------------------------- | ----- | ----------------------------------------------------- |
| db.test.ts | 32 | I5, I6, I9, I10, I11, I20 |
| app.test.ts | 9 | I1, I2, I3, I7, I14, I21, I23, I44, I46, I47 |
| db.test.ts | 33 | I5, I6, I9, I10, I11, I20, I48, I50, I52 |
| app.test.ts | 10 | I1, I2, I3, I7, I14, I21, I23, I44, I46, I47, I49, I51, I53 |
| core.test.ts | 6 | I12, I13, I18 |
| interview.test.ts | 6 | I16 |
| parts.test.ts | 10 | I17, I18, I44, I46, I47 |
| context.test.ts | 11 | I19, I45, I47 |
| observer.test.ts | 2 | I20, I21 |
| InterviewWorkspace.test.tsx | 9 | I24, I25, I23, I33, I34, I35, I36, I43, I44, I46, I47 |
| InterviewWorkspace.test.tsx | 10 | I24, I25, I23, I33, I34, I35, I36, I43, I44, I46, I47, I49, I51, I53 |
| ProjectList.test.tsx | 2 | I36 |
| workspace-data.test.ts | 4 | I33 |
| workspace-data.test.ts | 4 | I33, I49, I51, I53 |
| chat-hydration.test.ts | 3 | I35 |
| workspace-controller.test.tsx | 3 | I41, I43 |
| client-mutation.test.ts | 3 | I42 |
Expand Down
Loading