Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e192c88
FE-730: spec + plan for orchestrator POC dual-engine execution
kostandinang May 20, 2026
83e5c29
FE-730: card 1 — foundational types + procedural engine + contract te…
kostandinang May 20, 2026
e1f5553
FE-730: cards 10–15 — plan loader, test runner, worktree, pi-actions,…
kostandinang May 20, 2026
78401fb
FE-730: align spec/design/cards — cwd-scoped worktree isolation
kostandinang May 20, 2026
5320951
FE-730: clean CLI output with elapsed timing
kostandinang May 20, 2026
b762a1e
FE-730: rename fixtureDir → worktreeDir on OrchestratorInput
kostandinang May 20, 2026
e443d45
FE-730: collapse duplicated topo-sort into one generic
kostandinang May 20, 2026
828ba76
FE-730: extract createReport helper — deduplicate report construction
kostandinang May 20, 2026
2bbe8aa
FE-730: migrate contract test #1 to createFakes()
kostandinang May 20, 2026
5c3b62a
FE-730: remove exhausted REFACTOR.md
kostandinang May 20, 2026
da12df2
FE-730: formatting cleanup (oxfmt)
kostandinang May 20, 2026
e78dbfb
FE-730: remove .antigravitycli/ and add to .gitignore
kostandinang May 20, 2026
9e1a7f0
FE-730: update design doc — landed status, seam rename, experiment re…
kostandinang May 21, 2026
aa937a8
FE-730: fix bot-reported issues — NaN retries, multi-dep epics, halt …
kostandinang May 21, 2026
a50ffe5
FE-730: fix unreached-slice false success + report ID collisions
kostandinang May 21, 2026
6557da8
FE-730: fix epic dep fan-out starvation + proc unreached items
kostandinang May 21, 2026
62248f0
FE-730: remove stale fe-716 walkthrough doc (leaked from rebase)
kostandinang May 21, 2026
9c12408
FE-730: make petri the default engine
kostandinang May 21, 2026
085fc17
FE-730: fix bot round 3 — report IDs on throw, dead place, wrong prompt
kostandinang May 21, 2026
ae20730
FE-730: Phase 0 — extract NetCompiler + Interpreter + FiringPolicy
kostandinang May 21, 2026
5585e4e
plan: orchestrator-poc done, petri-semantic-lanes frontier + cards sc…
kostandinang May 21, 2026
44300a6
Fix orchestrator timing and deduplicate engine wrappers.
kostandinang May 25, 2026
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dist-ssr
bun.lock
.notes.md
.brunch/
.cook/
brunch.db*
todo.txt

Expand All @@ -52,3 +53,6 @@ tmp/

# skill quarantine
.agents/_quarantine

# antigravity cli
.antigravitycli/
4 changes: 4 additions & 0 deletions config/vite-server-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ export const createServerRuntimeConfig = <T extends object>({
},
closeBundle() {
copyServerPromptAssets(resolve(rootDir, 'src/server/prompts'), promptAssetsDestinationDir);
copyServerPromptAssets(
resolve(rootDir, 'src/orchestrator/prompts'),
resolve(promptAssetsDestinationDir, '..', 'orchestrator-prompts'),
);
},
},
],
Expand Down
318 changes: 318 additions & 0 deletions docs/design/orchestrator.md

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions fixtures/txt/plan.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
epics:
- id: scaffolding
summary: "CLI scaffolding"
depends_on: []
verification:
- kind: integration-test
target: "tests/cli-scaffolding.integration.test.ts"

- id: text-ops
summary: "Text operations"
depends_on: [scaffolding]
verification:
- kind: integration-test
target: "tests/text-ops-pipe.integration.test.ts"

slices:
- id: version-flag
epic_id: scaffolding
definition: "Add `--version` flag that prints the version from package.json"
depends_on: []
verification:
- kind: unit-test
target: "tests/version.test.ts"

- id: help-flag
epic_id: scaffolding
definition: "Add `--help` flag that lists subcommands: reverse, count, slugify"
depends_on: [version-flag]
verification:
- kind: unit-test
target: "tests/help.test.ts"

- id: reverse
epic_id: text-ops
definition: "Add `reverse` subcommand. Pure function reverses a string. CLI wires it to argv[2]."
depends_on: []
verification:
- kind: unit-test
target: "tests/reverse.test.ts"

- id: count
epic_id: text-ops
definition: "Add `count` subcommand that counts whitespace-separated words. Empty input returns 0."
depends_on: []
verification:
- kind: unit-test
target: "tests/count.test.ts"

- id: slugify
epic_id: text-ops
definition: "Add `slugify` subcommand. Lowercase, replace non-alphanumerics with single dash, collapse multiple dashes, trim leading/trailing dashes. Handle unicode by removing diacritics."
depends_on: []
verification:
- kind: unit-test
target: "tests/slugify.test.ts"
1,106 changes: 124 additions & 982 deletions memory/CARDS.md

Large diffs are not rendered by default.

70 changes: 63 additions & 7 deletions memory/PLAN.md

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions memory/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ Brunch operates inside a **workspace**: the cwd-backed software context whose lo
26. The homepage surfaces workspace (CWD) binding so the user understands listed specifications and the new-spec affordance are scoped to the current project directory.
33. Graph view is a first-class alternative to chat view, accessed as a peer route, and projects the intent graph as a navigable workspace with visible relationship topology and graph-launched refinement. The first ship is a structured-list layout; a spatial canvas follows as a layout switch inside graph mode.

#### Orchestrator (`cook`)

46. `brunch cook <dir>` takes a plan YAML (epics → slices) and executes it end-to-end by dispatching agents through a name-keyed `ActionRegistry`.
47. Two engines (`proc` and `petri`) implement the same `Orchestrator` interface and must pass the same contract test suite.
48. `reports.jsonl` is the communication medium: tokens carry only pointers, all event content lives in the append-only log.
49. Each run gets worktree isolation at `<cwd>/.cook/runs/<runId>/worktree/` (cwd-scoped, not fixture-scoped); fixture directory and source repo stay untouched.
50. Dual-mode CLI resolver: `<dir>/plan.yaml` = fixture (greenfield), `<dir>/.cook/plan.yaml` = codebase (brownfield, reserved).

#### Provider / agent substrate

40. Prompt and context engineering are first-class server subsystems: prompts and reusable policy doctrines live as inspectable markdown assets, while typed context-pack builders derive scenario-specific intent-graph renderings.
Expand Down Expand Up @@ -191,6 +199,14 @@ Brunch operates inside a **workspace**: the cwd-backed software context whose lo
153. **Conversational Workspace Runtime supersedes independent side-chat persistence without adding schema-level threads now** — continuous workspace is the host; side, reconciliation, qa, and strategy work should converge into inline secondary chats over the existing chat/turn substrate, while `changeset` / `change` remains the semantic mutation spine. A future `thread` table is deferred until chat/turn proves insufficient.
154. **Chat context is transcript-first with turn-level snapshots and chat-level handles** — a chat primarily uses its own transcript as prompt context. Additional graph/workspace context enters through explicit context snapshot artifacts stored on `turn` rows, so replay shows what the assistant saw at snapshot time. Active chat handles reference mentioned or anchored intent item ids and record the last snapshotted item version/fingerprint; they trigger fresh snapshots only when the referenced subject advances, including changes made by other chats. Do not introduce a persisted context-spec table by default; derive snapshots from intent graph truth via reusable context builders for item, neighborhood, economic whole-graph, and eventually changeset-historical neighborhoods. The V1 anchor/handle implementation is transcript-projected: the chat's pin is the projection seed, mention parsing and explicit add/remove emit `anchor_op` events on turns, and the bundle projector returns the current anchor set. Anchors are not chat-row state.

#### Orchestrator (`cook`)

155. **Dual-engine experiment behind shared `Orchestrator` seam** — `proc` (procedural state machine) and `petri` (Petri-net interpreter) implement the same interface; the experiment validates whether the Petri-net substrate earns its complexity. Depends on: Requirements 46, 47.
156. **`reports.jsonl` is the communication medium, not just audit log** — tokens carry only `{ reportId, sliceId, epicId }` pointers; transitions communicate by appending/reading lines. The net stays narrow because the log is rich. POC: petri engine enforces token-pointer discipline internally; proc engine is free to pass data through normal function calls — the shared seam is inputs and outputs. Depends on: Requirement 48.
157. **Action dispatch is name-keyed and extensible** — engines orchestrate which action fires when; handlers own how. POC uses inline dispatch per engine; promote to a real `ActionRegistry` when a 3rd action type lands. Depends on: Requirement 46.
158. **Plan model is two-level (epics → slices), no milestones in POC** — schema is provisional pending canonical brunch plan emission. Forward-compatible for intent/design/oracle pointers.
159. **Worktree isolation per run** — agents write freely inside `<cwd>/.cook/runs/<runId>/worktree/` (cwd-scoped, not fixture-scoped); fixture dir and source repo untouched. Fixtures stay byte-identical before and after a run. Depends on: Requirement 49.

#### Provider, prompt/context, and agent substrate

130. **First-run setup becomes a product surface, not README-only configuration** — dashboard/provider setup replaces project `.env` docs as the only user-facing path.
Expand Down Expand Up @@ -237,6 +253,9 @@ Each invariant is a formalization candidate: the property is stated in human lan
| I118 | Reconciliation/direct-edit cascade never infers affected endpoints from raw edge direction alone; it consults relation policy source-change / target-change behavior. | planned: relation-policy/edit-impact/reconciliation tests | A93; D137, D150 |
| I119 | Scenario-option candidate bundles can become canonical only by accepting a coherent bundle changeset; accepted-with-issues candidates also create durable follow-on review/process debt. | planned: scenario-runner, turn-artifacts, changeset tests | A90, A91; D151, D152 |
| I120 | Secondary chats remain conversational process containers, not workflow or semantic truth: inline rendering, collapse/reload state, turn-level context snapshot replay, and item-version-gated stale-handle refresh may organize discussion, but accepted mutations still flow through Brunch-owned handlers and changesets. | planned: chat-runtime, context-provision, changeset/app tests | Requirement 45; A94, A95; D143, D149, D153, D154 |
| I121-K | Both orchestrator engines (`proc` and `petri`) pass the same contract test suite with identical observable behavior. | contract tests with fake agents/runner | Requirements 46, 47; D155-K |
| I122-K | Orchestrator event content lives in `reports.jsonl`; petri engine tokens carry only `{ reportId, sliceId, epicId }` pointers. Proc engine may pass data through normal function calls — the shared seam is inputs and outputs. | contract tests | Requirement 48; D156-K |
| I123-K | Worktree isolation holds — fixture directory and source repo are never mutated by an orchestrator run; worktree is cwd-scoped at `<cwd>/.cook/runs/<runId>/worktree/`. | integration tests, worktree.test.ts | Requirement 49; D159-K |

## Future Direction Register

Expand Down Expand Up @@ -341,6 +360,16 @@ Detailed card styling, typography tokens, and legacy layout minutiae are impleme
| **greenfield / brownfield** | Grounding strategies for new concepts vs existing-codebase work. |
| **end-to-end build / incremental feature** | Delivery postures for whole-system shaping vs bounded changes. |
| **output view** | Terminal route available when phases are closed; not a workflow phase. |
| **orchestrator** | CLI execution engine (`brunch cook`) that takes a plan YAML and drives it to completion via agent dispatch and deterministic verification. |
| **engine** | Implementation of the `Orchestrator` interface. Two exist: `proc` (procedural state machine) and `petri` (Petri-net interpreter). |
| **epic** | Organizational grouping of slices with cross-slice integration verification in a plan. |
| **plan (orchestrator)** | YAML file describing epics + slices with definitions, dependencies, and verifications. The orchestrator's input. |
| **action (orchestrator)** | A handler in the `ActionRegistry` (e.g. `write-tests`, `write-code`, `run-tests`). Engines look up by name. |
| **report** | One structured event line in `reports.jsonl`. Carries durable content; tokens carry only pointers. |
| **worktree (orchestrator)** | Isolated filesystem location where agents write during a run. Per-run; ephemeral. Cwd-scoped (`<cwd>/.cook/runs/<runId>/worktree/`), not fixture-scoped. |
| **fixture (orchestrator)** | Packaged test scenario for the orchestrator (plan + supporting artifacts). Used to test `cook` itself. |
| **fixture mode** | Greenfield execution: plan at `<dir>/plan.yaml`, empty worktree. POC default. |
| **codebase mode** | Brownfield execution: plan at `<dir>/.cook/plan.yaml`, worktree seeded from `<dir>`. Designed but not implemented in POC. |

## Verification Design

Expand Down
40 changes: 16 additions & 24 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
"tw-animate-css": "^1.4.0",
"use-stick-to-bottom": "^1.1.3",
"xstate": "^5.30.0",
"yaml": "^2.9.0",
"zod": "^4.3.6"
},
"devDependencies": {
Expand Down
10 changes: 10 additions & 0 deletions src/orchestrator/prompts/code-writer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
You are a code-writing agent. Your job is to write the minimum implementation to make existing tests pass.

## Rules

- Read the existing test files first to understand what's expected.
- Write the minimum code to make ALL tests pass.
- Use TypeScript with Bun conventions.
- Do NOT modify test files.
- Do NOT add features beyond what the tests require.
- Create any necessary directory structure and configuration files.
11 changes: 11 additions & 0 deletions src/orchestrator/prompts/evaluator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
You are an evaluator agent. Your job is to assess whether a slice specification is fully satisfied by the current code.

## Rules

- Read the slice definition and verification targets.
- Check if test files exist and if they cover the specification.
- Run `bun test` on the verification targets to check if tests pass.
- Respond with a JSON object: { "done": true/false, "reasoning": "..." }
- "done": true means ALL verification targets pass and the slice spec is satisfied.
- "done": false means more work is needed.
- Be honest — if tests are missing, failing, or incomplete, say so.
11 changes: 11 additions & 0 deletions src/orchestrator/prompts/test-writer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
You are a test-writing agent. Your job is to write failing tests for a given slice specification.

## Rules

- Write tests that will initially FAIL because the implementation doesn't exist yet.
- Use `bun test` conventions (import { describe, expect, it } from "bun:test").
- Each test should verify one observable behavior from the slice definition.
- Write tests to the file paths specified in the verification targets.
- Keep tests simple and focused — test behavior, not implementation.
- Create any necessary directory structure.
- Do NOT write implementation code — only tests.
36 changes: 36 additions & 0 deletions src/orchestrator/src/cook-cli.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { describe, expect, it } from 'vitest';

import { parseCookArgs } from './cook-cli.js';

describe('parseCookArgs', () => {
it('parses dir only', () => {
const opts = parseCookArgs(['./fixtures/txt']);
expect(opts.dir).toContain('fixtures/txt');
expect(opts.engine).toBe('petri');
expect(opts.maxRetries).toBe(3);
expect(opts.verbose).toBe(false);
});

it('parses --engine=petri', () => {
const opts = parseCookArgs(['./f', '--engine=petri']);
expect(opts.engine).toBe('petri');
});

it('parses --max-retries=5', () => {
const opts = parseCookArgs(['./f', '--max-retries=5']);
expect(opts.maxRetries).toBe(5);
});

it('throws on missing dir', () => {
expect(() => parseCookArgs(['--engine=proc'])).toThrow('Usage');
});

it('throws on unknown engine', () => {
expect(() => parseCookArgs(['./f', '--engine=unknown'])).toThrow('Unknown engine');
});

it('parses --verbose', () => {
expect(parseCookArgs(['./f', '--verbose']).verbose).toBe(true);
expect(parseCookArgs(['./f', '-v']).verbose).toBe(true);
});
});
Loading
Loading