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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,20 +129,20 @@ src/
### Key patterns

- **Turn tree**: Conversations are branching trees, not flat logs. Each turn points to a parent. `active_turn_id` is HEAD. Active path resolved via recursive CTE.
- **Two-agent pattern**: Interviewer asks structured questions. Observer extracts decisions/assumptions after each turn. Different models, different prompts, independent testability.
- **Two-agent pattern**: Interviewer asks structured questions. Observer extracts typed knowledge items after each turn. Different models, different prompts, independent testability.
- **Typed message contract**: `BrunchUIMessage` (AI SDK `UIMessage` with custom generics) spans server validation, persistence, streaming, and client hydration.
- **Parts-based persistence**: `assistant_parts` and `user_parts` JSON columns store the full UI state per turn. Scalar fields (`question`, `why`, `impact`) retained for queryability.
- **Zod everywhere**: Tool input/output schemas, data part schemas, parts deserialization, API payload validation.

## Current state

**Working**: Full four-phase interview (scope → design → requirements → criteria), phase-aware observer extraction across all 8 canonical knowledge kinds, explicit phase outcomes with closure provenance, requirements and criteria review with approve/reject state, knowledge workspace, markdown export, project dashboard with workflow state, fixture scenarios with rich seeded content.
**Working**: Full four-phase interview (scope → design → requirements → criteria), phase-aware observer extraction across all 8 canonical knowledge kinds, explicit phase outcomes with closure provenance, requirements and criteria review with approve/reject state, knowledge workspace, markdown export, project dashboard with workflow state, fixture scenarios with rich seeded content, local-first `.brunch/` storage, and greenfield/brownfield project kickoff with scope-grounded brownfield exploration.

**Not yet built**: Review lifecycle refinement (13a), npx distribution (14). See `memory/PLAN.md` for the full roadmap.
**Not yet built**: Knowledge-graph revisit / edit-mode cascade flow (phase 8 stretch). See `memory/PLAN.md` for the full roadmap.

## Tests

223 tests across 24 test files covering DB operations, app routes, core logic, interview flow, observer extraction, parts serialization, context builders, workspace hydration/controller/data, client components, phase-close logic, and build boundaries. Provider calls are mocked for CI; prompt quality depends on manual evaluation.
288 tests across 33 test files covering DB operations, app routes, launcher/distribution seams, core logic, interview flow, observer extraction, parts serialization, context builders, workspace hydration/controller/data, client components, phase-close logic, and build boundaries. Provider calls are mocked for CI; prompt quality depends on manual evaluation.

```bash
npm test
Expand Down
25 changes: 25 additions & 0 deletions bin/brunch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env node

import { spawn } from 'node:child_process';
import { createRequire } from 'node:module';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
const cliEntrypoint = join(packageRoot, 'src', 'server', 'cli.ts');
const require = createRequire(import.meta.url);
const tsxEntrypoint = require.resolve('tsx');

const child = spawn(process.execPath, ['--import', tsxEntrypoint, cliEntrypoint, ...process.argv.slice(2)], {
stdio: 'inherit',
env: process.env,
});

child.on('close', (code) => {
process.exit(code ?? 1);
});

child.on('error', (error) => {
console.error('Failed to start brunch:', error);
process.exit(1);
});
21 changes: 11 additions & 10 deletions docs/design/BROWNFIELD_EXPLORATION.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Brownfield Exploration Design

> Design exploration from 2026-04-12. Referenced by SPEC.md D82, D83.
> Status: **approved direction** — First-turn exploration via prompt + core tools.
> Status: **implemented** — Scope-only exploration via prompt + read-only exploration tools.

## Shape

No new module boundary. Brownfield exploration is a prompt/context/tool-configuration concern:

1. **Tool set:** In brownfield mode, the interviewer agent receives core tools (read, grep, find, ls, bash) alongside interview tools (ask_question, propose_phase_closure).
2. **System prompt:** A brownfield variant of the scope system prompt instructs the agent to explore the codebase before asking its first scope question.
1. **Tool set:** During brownfield scope only, the interviewer agent receives a read-only exploration subset (`read`, `grep`, `find`, `ls`) alongside interview tools (`ask_question`, `propose_phase_closure`).
2. **System prompt:** A brownfield variant of the scope system prompt instructs the agent to explore the codebase before asking its first scope question. Later phases keep their normal phase prompts.
3. **Context builder:** `buildInterviewerContext()` receives the project's `cwd` and `mode` (greenfield/brownfield) to construct the appropriate first-turn prompt.

## Interviewer configuration change
Expand All @@ -18,11 +18,11 @@ No new module boundary. Brownfield exploration is a prompt/context/tool-configur
const tools = {
ask_question,
...(closeable ? { propose_phase_closure } : {}),
...(mode === 'brownfield' ? createCoreTools(projectCwd) : {}),
...(phase === 'scope' && mode === 'brownfield' ? createExplorationTools(projectCwd) : {}),
}

const instructions = mode === 'brownfield'
? getBrownfieldSystemPrompt(phase)
const instructions = phase === 'scope' && mode === 'brownfield'
? getBrownfieldScopePrompt(projectCwd)
: getSystemPrompt(phase)
```

Expand Down Expand Up @@ -68,8 +68,9 @@ The brownfield system prompt should:
- Set a budget: "Spend no more than 5-8 tool calls on exploration before synthesizing"
- Transition: "Once you have a working understanding, summarize what you found and begin scope questions grounded in that context"

## Open questions
## Current implementation notes

- Should brownfield mode persist core tool access throughout the entire interview, or only on the first turn? (Probably throughout — the user might say "look at the auth module" during design phase.)
- Should the exploration summary be stored as a special data part for context rebuilding? (Probably not for V1 — it's just part of the first turn's assistant_parts.)
- Does the `ToolLoopAgent` `stopWhen: stepCountIs(4)` need to increase for brownfield first turns? (Likely yes — exploration needs more steps.)
- Brownfield exploration is deliberately **scope-only**; later phases keep their normal prompts and tool surface.
- The exploration tool surface is deliberately **read-only** — no `write`, `edit`, or `bash` during brownfield discovery.
- The exploration summary is not stored as a special data part; it remains part of the first assistant turn.
- Brownfield scope raises the `ToolLoopAgent` step budget from 4 to 12 to allow exploration before the first structured question.
19 changes: 9 additions & 10 deletions memory/PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@
- Acceptance: deferred review refinements such as edit/add/merge/stale semantics across requirements and criteria can land behind one cross-cutting slice without regressing completion, export, or workflow-state coherence
- **Verification approach**: inner — mutation/read-model/invalidation tests per refinement added. Outer — manual cross-phase review lifecycle walkthrough after the dedicated knowledge workspace exists.

## Phase 7: Distribution + Brownfield + UI Alignment
## Phase 7: Distribution + Brownfield + UI Alignment `done`

<!-- Local-first storage, npx distribution, greenfield/brownfield routing, codebase exploration,
and design-system alignment from the brunch-ui prototype.
Expand All @@ -149,24 +149,23 @@

17. **UI refinement + design-system alignment** `done`
- Shipped: Inter font, Figma color ramp, typography scale, shadow tokens, Ladle stories, sidebar toggle, card-within-card in KnowledgeWorkspace, resizable panels in InterviewWorkspace, skeleton loading, empty-state vocabulary
- Evidence: 11 Ladle stories, 236/237 tests pass, npm run verify green
- Evidence: 11 Ladle stories, 288 tests pass, npm run verify green
- Debt: dark mode tokens, question card V2 (TurnCard refactor), badge mono font, per-route skeleton tuning

17a. **Debug route removal + shiki decoupling** `done`
- Shipped: tool JSON renders via plain `<pre><code>` (no shiki); `/debug` route removed; AI Elements showcase migrated to Ladle story; shiki eliminated from all production chunks
- Evidence: build-boundary.test.ts (no-shiki oracle), capability-boundaries.test.ts, 253 tests pass, npm run verify green
- Evidence: build-boundary.test.ts (no-shiki oracle), capability-boundaries.test.ts, 288 tests pass, npm run verify green

14. **Local-first storage + npx distribution** `done`
- Shipped: `BrunchProject` resolution with walk-up discovery, Express launcher serves API + static on one port, bin entry for `npx @hashintel/brunch`, drizzle migrations resolved via `import.meta.url`
- Evidence: project.test.ts (8 pass), launcher.test.ts (3 pass), 264 total tests pass, npm run verify green
- Debt: actual npx publish/distribution testing, `--port` flag, graceful shutdown
- Shipped: `BrunchProject` resolution walks up safely, rejects invalid `.brunch` path shapes early, preserves API 404s when static assets are mounted, and ships a real JS bin entrypoint for `npx brunch`; empty `BRUNCH_DB` falls back safely; migrations still resolve via `import.meta.url`
- Evidence: project.test.ts, launcher.test.ts, cli.test.ts, runtime-config.test.ts; 288 tests pass, npm run verify green
- Debt: real published `npx` smoke test, `--port` flag, graceful shutdown
- Unblocks: 14a (greenfield/brownfield), 16 (drizzle-kit audit)

14a. **Greenfield/brownfield first-screen + exploration** `done`
- Shipped: project table stores `mode` (greenfield/brownfield) and `cwd`; dialog-based first-screen routes between modes; brownfield interviewer gets core tools + exploration system prompt + higher step budget (12 vs 4); server derives cwd from launcher; greenfield path unchanged
- Evidence: db.test.ts (5 new assertions), interview.test.ts (3 new), app.test.ts (3 new), ProjectList.test.tsx (updated), 274 tests pass, npm run verify green
- Design: `docs/design/BROWNFIELD_EXPLORATION.md`
- Debt: outer-loop manual brownfield walkthrough (A47 validation), brownfield prompt for non-scope phases
- Shipped: project table stores `mode` (greenfield/brownfield) and `cwd`; dialog-based first-screen routes between modes; brownfield scope uses read-only exploration tools + a scope-only exploration prompt + a higher step budget (12 vs 4); later phases keep their normal prompts; server derives cwd from launcher
- Evidence: db.test.ts, interview.test.ts, app.test.ts, ProjectList.test.tsx; 288 tests pass, npm run verify green
- Debt: outer-loop manual brownfield walkthrough (A47 validation)

## Phase 8: Knowledge-Graph Revisit (stretch)

Expand Down
Loading