You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
FE-841: Pi agent foundations β in-process SDK, toolchain profiles (#194)
* FE-841: Embed pi as an in-process SDK to drop the external pi CLI dependency
Replace the spawn('pi', β¦) subprocess in pi-actions.ts with an in-process
createAgentSession over @earendil-works/pi-coding-agent (pinned 0.79.1), so a
fresh checkout no longer needs an external pi binary on $PATH β only
ANTHROPIC_API_KEY.
- buildSessionOptions maps the old CLI flags to SDK config: tools allowlist,
model-registry lookup, system-prompt override, in-memory session + empty
resource overrides (no context files).
- Auth fed from brunch's own ANTHROPIC_API_KEY (no pi login / ~/.pi/auth.json);
one reused per-process agent dir, no per-call temp leak.
- Output captured off text_delta events (never brunch's stdout, keeps the cook
SSE stream clean); cooperative timeout + 10MB output cap.
- Read-only evaluator scoping (I126-K) preserved via the SDK tools allowlist;
injectable SessionFactory keeps the drive loop offline-testable.
- Drops the `which pi` prereq from the cook guide (npx pi for the interim helper).
- Override transitive hono to 4.12.25 (patches the moderate advisories the
dependency-review gate flags).
- PI_REAL_LLM-gated smoke proves a real in-process run with no pi on $PATH.
π€ Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* FE-841: Harden in-process pi session guards
Co-authored-by: Cursor <cursoragent@cursor.com>
* FE-841: Clean up late pi setup timeouts
Co-authored-by: Cursor <cursoragent@cursor.com>
* FE-841: Tighten pi timeout and output caps
Co-authored-by: Cursor <cursoragent@cursor.com>
* FE-841: pin pi SDK nested vulnerable patches
Co-authored-by: Cursor <cursoragent@cursor.com>
* FE-841: pin root ws to patched release
Co-authored-by: Cursor <cursoragent@cursor.com>
* FE-841: require the pi SDK node floor
Co-authored-by: Cursor <cursoragent@cursor.com>
* FE-843: Frontier setup β toolchain-profile-expansion plan entry + 3-card queue
Co-authored-by: Claude <noreply@anthropic.com>
* FE-843: Data-driven profile registry + node-vitest/node-test/node-jest/deno profiles
Profiles are now data literals (path templates + argv template + conventions
prose) compiled into the unchanged Toolchain interface β adding a runtime is
one data entry. Registry invariants pinned enumerably across all profiles.
Co-authored-by: Claude <noreply@anthropic.com>
* FE-843: Live + strict profile selection β flag β« spec β« bun, persisted into plan.yaml
brunch plan gains --profile=<id> (validated via parseProfileId); the emitter
resolves the chain once and stamps the id on both the authored and fallback
plans, so cook always reads the profile the emitter used. resolveToolchain
now throws UnknownProfileError on a typo'd id instead of silently running
bun; absent stays lenient for hand-authored fixtures.
Co-authored-by: Claude <noreply@anthropic.com>
* FE-843: Architect classifies the toolchain profile from spec prose
architectPlan's schema gains an optional profile enum (registry ids,
null when the spec is silent); the emitter chain becomes flag β« spec
profile β« architect-classified β« bun. A hallucinated profile fails the
schema parse and rides the existing deterministic fallback. D160-K
intact β classification reads projected spec prose only.
Queue exhausted: CARDS.md retired; PLAN frontier marked branch-complete.
Co-authored-by: Claude <noreply@anthropic.com>
* FE-843: reject inherited profile names
Co-authored-by: Cursor <cursoragent@cursor.com>
* FE-841: bump pi SDK to 0.79.8 for patched undici
pi-coding-agent 0.79.1 pinned undici 8.3.0, which trips three advisories
flagged by the dependency-review check (GHSA-38rv-x7px-6hhq,
GHSA-vmh5-mc38-953g, GHSA-pr7r-676h-xcf6). 0.79.8 is the first patch
release that depends on the fixed undici 8.5.0. A root override can't
reach the SDK's exact-pinned nested undici, so bump the SDK itself.
* FE-841: reject failed embedded pi turns
Detect SDK-level assistant failures after prompt resolution so cook does not advance past a failed in-process agent run.
Co-authored-by: Cursor <cursoragent@cursor.com>
* FE-841: tolerate empty plan profiles
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Copy file name to clipboardExpand all lines: docs/praxis/orchestration-guide.md
+8-4Lines changed: 8 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,11 +5,13 @@ Run `brunch cook` against the brunch repo in codebase (brownfield) mode.
5
5
## Pre-flight
6
6
7
7
```sh
8
-
which pi && pi --version# pi >= 0.74
9
-
npm run build # dist/ fresh
8
+
npm run build # dist/ fresh (bundles the in-process pi SDK)
9
+
grep -q '^ANTHROPIC_API_KEY=' .env# cook feeds this to the embedded agent
10
10
git status --porcelain --untracked-files=no # must be empty
11
11
```
12
12
13
+
`brunch cook` embeds `@earendil-works/pi-coding-agent` in-process (FE-841), so no external `pi` binary on `$PATH` is required β only `ANTHROPIC_API_KEY` in `.env`, which the cook command loads via `--env-file=.env`.
14
+
13
15
`.brunch/` is already gitignored, so cook artifacts won't appear in `git status`.
14
16
15
17
## Author the plan
@@ -28,10 +30,12 @@ Run `/ln-scope` on a `memory/PLAN.md` frontier to produce a scope card (Target B
28
30
29
31
Extract the frontier section and ask pi for YAML:
30
32
33
+
The `pi` CLI is no longer a global prerequisite, but it still ships inside the bundled dep β invoke it with `npx pi` (resolves to `node_modules/.bin/pi`):
- **Pi evaluator may short-circuit.** Pi has `read,write,edit,bash` even during `evaluate-done` and may fix the file during evaluation rather than going through write-tests β write-code β run-tests. Non-deterministic.
125
+
- **Agent runs in-process.** Cook drives the agent via the embedded `@earendil-works/pi-coding-agent` SDK (FE-841), not a spawned `pi` CLI. `evaluate-done` is scoped to a read-only tool allowlist (`toolsForAction('evaluate-done')`), so the evaluator cannot fix the file during evaluation (I126-K); `done` comes from executing the verification targets, not an LLM verdict.
122
126
- **No commit on the cook branch.** Modification is in untracked subdirs of the cook branch's worktree, not committed. Promotion is manual `cp -R`.
123
127
- **Plan vs frontier mismatch.** `.brunch/cook/plan.yaml` is orchestrator runtime, not planning vocabulary. `/ln-scope` or pi-assisted translation is the bridge.
Copy file name to clipboardExpand all lines: memory/PLAN.md
+15Lines changed: 15 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -33,6 +33,7 @@ The May 2026 intent-spec, multi-chat, changeset-ledger, prompt/context, and agen
33
33
6.`cook-mode-from-spec` β **FE-826**; **branch-complete on `ka/fe-826-cook-mode-from-spec`** (stacked on FE-819). Greenfield/brownfield is now spec-derived plan truth: `brunch plan <specId>` writes `specification.mode` into `plan.yaml` (`Plan.mode`); `brunch cook` reads `plan.mode` to pick the worktree strategy β greenfield β empty worktree (generate from scratch), brownfield β cwd clone + clean-tree gate. Resolver split into `resolveCookPlan` (path-only) + `resolveSandboxPlan` (mode-driven). Cook `dir` arg is now optional (defaults to cwd). Reverses the location-keyed reading of Requirement 50, refines I123-K, adds D164-K. Refinement on `cook-codebase-mode` (done) + `spec-to-cook-plan` (FE-800).
34
34
7.`cook-greenfield-single-tree` β **FE-827**; **branch-complete on `ka/fe-827-greenfield-single-tree`** (stacked on FE-826). Cook slice layout is now policy-selected (D165-K): serial greenfield runs one shared accreted tree (verify in place, no `__epic__`); parallel greenfield isolates per-slice + `__epic__` merge (race-safe); brownfield unchanged. Adds greenfield promotion-back (D166-K, I128-K): `--out`/`--force`, completed-gated, commit-on-branch, never silent β serial copy-commits the run tree, parallel commits a whole-plan merge (order-wins, collisions reported). Closes the cook output-promotion gap for greenfield; brownfield promotion stays a follow-on. New seams: `promote-run.ts`, `mergeCompletedSlicesIntoTree`, `promotionSourceDir`. LLM conflict reconciliation β Horizon `parallel-merge-conflict-reconciliation`.
35
35
8. `plan-build-architect` β **FE-829**; **active, building on `ka/fe-829-build-architect`** (stacked on FE-827, draft PR #185). Evolves `brunch plan` from a sequencer into a build-architect emitting fixture-quality, cook-executable `plan.yaml` (target shape = the three reference fixtures). Slice 1 (**done** 2026-06-09): self-contained `PlanContract` (`checkPlan` base/emitted profiles + `repairPlan`) + shared `plan-graph` Kahn helper + `Toolchain` descriptor in the emitter β synthesizes the multi-slice-epic integration seam, closing FE-800's integration-blind / "green checks, no artifact" gap (D167-K, I129-K; no LLM, no D160-K change). Slice 2 (**done** 2026-06-09): toolchain-agnostic cook prompts + runner β `ToolchainTestRunner` + toolchain-driven cook task builders + de-hardcoded `test-writer.md`, resolved from `plan.profile` (I130-K). Slice 3 (**done** 2026-06-09): build-architect LLM stage β the planner prompt now carries each slice's acceptance criteria, spec relation hints projected into slice-id space (`projectPlanningContext`), and the three reference fixtures inlined as comment-stripped few-shot exemplars; output schema unchanged (classify/group/order the existing `req-*` slices only). Slice 4A (**done** 2026-06-09): file-ownership contract β `Slice.writes?: string[]` + single-writer-per-file `checkPlan` finding (`file-write-conflict`, design-class warning, never auto-repaired) + the D160-K coordination-file-layout-namespace amendment (I132-K). Slice 4B (**done** 2026-06-09): the architect now AUTHORS the slice set β `architectPlan` (new schema: authored slices + `writes` + `derivedFrom`) β `materializeArchitectedPlan` (deterministic normalize + requirement-provenance coverage sidecar) β `repairPlan` + `checkPlan` (emitted + generalized coverage), with a deterministic projection fallback when authoring throws/parses-malformed/leaves a requirement uncovered (I133-K; supersedes the slice-3 `planExecutionOrdering` enrichment stage on the mainline). Slice 5 (**done** 2026-06-09): eval harness β `evaluatePlanShape` (`plan-eval.ts`), a deterministic outer-loop acceptance oracle (narrow `verdict` gate + graded structural-feature metrics scored against the abstract fixture-design principles, no id/path/count overfit); the 3 reference fixtures are its self-test and were refreshed (`writes` on every slice + the missing integration seam on the `core` / `pipeline` epics of two of them) to score `overall === 1` (I134-K). Post-slice-5 cleanup (**done** 2026-06-09): retired the dormant `planExecutionOrdering` β deleted `plan-llm-planning.ts` (+ test), relocated the surviving `PlanningEnrichment` type into `plan-reconciliation.ts`, consolidated the duplicate `RunModel` onto `plan-architect.ts` (I131-K retired). Opt-in real-LLM eval smoke (**done** 2026-06-09): `plan-emitter.test.ts` env-gated block (`PLANNING_REAL_LLM=1` + `ANTHROPIC_API_KEY`, `it.skip` otherwise) runs the production architect end-to-end on the `brunch-graphs-snapshot.json` fixture and asserts `evaluatePlanShape(plan).verdict === 'accept'` β restoring the opt-in real-LLM coverage lost with `plan-llm-planning.test.ts` at the I134-K gate. **Branch-complete** (slices 1β5 + post-slice-5 cleanup + opt-in smoke). Refinement on `spec-to-cook-plan` (FE-800).
36
+
9. `toolchain-profile-expansion` β **FE-843**; **branch-complete on `ka/fe-843-toolchain-profiles`** (stacked on FE-841). Expands the FE-829 toolchain contract so cook builds on more technologies. Card 1 (**done** 2026-06-10): data-driven profile registry β profiles are data literals (path templates + argv template + conventions prose) compiled into the unchanged `Toolchain` interface; added `node-vitest`, `node-test`, `node-jest`, `deno`; registry invariants pinned enumerably. Card 2 (**done** 2026-06-10): live + strict selection β `brunch plan --profile=<id>` (validated via `parseProfileId`), emitter resolves the chain once and stamps the id on both authored and fallback plans, `resolveToolchain` throws `UnknownProfileError` on unknown ids (absent stays lenient for fixtures). Card 3 (**done** 2026-06-10): architect-schema profile enum β chain is flag β« `snapshot.profile` β« architect-classified-from-spec-prose β« `bun`; a hallucinated profile fails schema parse β deterministic fallback (D160-K intact). No harness install verb (the cook agent scaffolds per A98) β assumption pending outer-loop validation (greenfield cook smoke `--profile=node-vitest`). I130-K refinement + agent-install assumption β SPEC at ln-sync tie-off. Deferred follow-ons: fail/infra test-outcome split, brownfield drift-check at cook open, `brunch detect`. Refinement on `plan-build-architect` (FE-829).
36
37
37
38
### Recently Completed
38
39
@@ -349,6 +350,20 @@ The May 2026 intent-spec, multi-chat, changeset-ledger, prompt/context, and agen
349
350
-**Traceability:** Requirements 46β50; A97, A100-K; D158-K, D160-K (amended in slice 3), D161-K, D167-K; I129-K, I130-K; Future Direction Β§Cook plan generation. Refinement on `spec-to-cook-plan` (FE-800) β resolves its integration-blind follow-on. Builds on FE-826, FE-827.
-**Objective:** Expand the FE-829 `Toolchain` contract (`project-profile.ts`) so cook builds on more technologies: profiles as data literals compiled into the existing `Toolchain` interface (consumers untouched); profile resolved once at plan time (`--profile` flag β« `snapshot.profile` β« architect-classified β« `bun`), persisted into `plan.yaml`; cook errors on unknown ids (lenient on absent, mirroring the `checkPlan` base/emitted split). The architect's existing schema-constrained call gains an optional profile enum β classification reads projected spec prose only (D160-K intact, no host introspection).
360
+
-**Why now / unlocks:** Today both implemented profiles are TypeScript and the selection path is dead (`snapshot.profile` never populated) β every cook run silently resolves to bun, and a typo'd profile id silently defaults rather than erroring. Without live selection, adding profiles changes nothing at runtime; without more profiles, "brunch builds on different technologies" is false in practice.
361
+
-**Design (ln-design 2026-06-10):** flat data registry (A) over composed axes (B β deferred until real combo demand; retreat is cheap since the consumer surface never changes); no harness install verb β the cook agent scaffolds + installs per A98 (pressure trigger: first profile where the runner fails for missing install). Deferred follow-ons: fail/infra test-outcome split in `ToolchainTestRunner`, brownfield drift-check at cook open (path-neutral by type), `brunch detect` CLI convenience. Durable end-state for selection: the spec interview captures stack as a structured field (the D164-K `mode` pattern); the chain already reserves that rung.
0 commit comments