Skip to content

FE-755: Cook codebase mode for brownfield brunch#155

Open
kostandinang wants to merge 5 commits into
ka/fe-747-petri-declarative-routingfrom
ka/fe-755-cook-codebase-mode
Open

FE-755: Cook codebase mode for brownfield brunch#155
kostandinang wants to merge 5 commits into
ka/fe-747-petri-declarative-routingfrom
ka/fe-755-cook-codebase-mode

Conversation

@kostandinang
Copy link
Copy Markdown
Contributor

@kostandinang kostandinang commented May 26, 2026

Summary

  • resolveCookMode selects fixture vs codebase when .brunch/cook/plan.yaml is present, the tracked working tree is clean, and the target directory is a git repository.
  • Codebase runs use a parent git worktree on branch cook/<runId> and per-slice worktrees on cook-slice/<runId>/<sliceId>, with copy-on-write for untracked/gitignored content where the OS supports it.
  • Cook run artifacts live under .brunch/cook/runs/<runId>/ (replacing .cook/); adds docs/praxis/orchestration-guide.md for operators running cook on real repos.

Context

  • Stacks on the Petri substrate delivered in FE-738 through FE-747. This frontier moves brunch cook from fixture-only greenfield runs to brownfield repositories while keeping the user’s source branch byte-identical for the duration of a run.
  • Hybrid sandboxes avoid fully duplicating large trees (node_modules, build outputs): APFS clonefile, Linux reflink, then cpSync fallback.
  • Agent invocation (pi-actions.ts) stays unchanged at the seam; only sandbox resolution and filesystem layout change.

What changed

  • Brownfield resolver wired into the existing cook CLI entry; fixture mode behavior unchanged when resolver conditions are not met.
  • cowCopy seeds untracked/gitignored files into slice sandboxes without mutating the source checkout.
  • Slice id validation rejects ids that would collide with real repo paths.
  • Integration coverage via brownfield-smoke.integration.test.ts plus a documented 2026-05-26 real-pi smoke on a temporary git repo.

Verification

  • Unit tests for mode resolver, sandbox paths, and hybrid seed behavior.
  • Brownfield integration smoke; full npm run verify green (1449 tests at PR time).

Out of scope

  • Branch commit/merge promotion and artifact lifecycle (cook-artifact-lifecycle frontier).
  • Evaluator tool scoping and Sandcastle adoption.

Traceability

  • Requirements 46–50; SPEC §D50, §A49, §I123-K; frontier cook-codebase-mode in memory/PLAN.md; stacks on FE-747.

@kostandinang kostandinang changed the title FE-755: Cook codebase-mode — brownfield resolver for brunch cook. FE-755: Cook codebase-mode — brownfield resolver for brunch cook May 26, 2026
@kostandinang kostandinang marked this pull request as ready for review May 26, 2026 17:03
@cursor
Copy link
Copy Markdown

cursor Bot commented May 26, 2026

PR Summary

Medium Risk
Changes git worktree/branch lifecycle and filesystem layout for cook runs; mistakes could touch user repos, though the clean-tree gate and source-byte-identical tests target isolation.

Overview
brunch cook gains brownfield (codebase) mode so runs can target a real git repo via .brunch/cook/plan.yaml, while greenfield fixture mode (plan.yaml at repo root) stays the same.

Cook artifacts move from .cook/ to .brunch/cook/ (runs, plans, gitignore). resolveCookMode picks fixture vs codebase, requires a git repo and a clean tracked working tree for brownfield (untracked .brunch/ is ignored for the gate).

Codebase sandboxes use a parent git worktree on cook/<runId> and per-slice worktrees on cook-slice/<runId>/<sliceId>, with CoW copy for untracked/gitignored top-level dirs (node_modules, etc.). The petrinet compiler wires sandboxMode + runId into slice seeding via seedSliceFromParentWorktree.

Docs/spec/plan updated; docs/praxis/orchestration-guide.md added. Tests cover resolver, worktree paths, hybrid seed, and brownfield-smoke.integration.test.ts. Branch commit/merge promotion and pi evaluator tool scoping remain out of scope.

Reviewed by Cursor Bugbot for commit 3cc97a2. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread src/orchestrator/src/epic-sandbox-merge.ts
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented May 26, 2026

🤖 Augment PR Summary

Summary: This PR implements “codebase mode” for brunch cook <dir>, enabling brownfield runs against an existing git repo while keeping the source branch’s tracked files unchanged.

Changes:

  • Introduced resolveCookMode(dir) (fixture/codebase/error) and replaced the prior “not yet implemented” exit.
  • Added a clean-tree gate for codebase mode using git status --porcelain --untracked-files=no and rejected non-git dirs.
  • Extended createSandbox to support codebase mode via git worktree add -b cook/<runId> ... HEAD.
  • Added per-slice seeding from the parent worktree (excluding .git, sibling slice dirs, and __epic__/) and wired it into the Petri net compiler.
  • Threaded sandboxMode through orchestrator input so engines can branch on fixture vs codebase behavior.
  • Consolidated cook run output paths from .cook/ to .brunch/cook/ and updated docs/spec/plan accordingly.
  • Added unit + integration coverage, including an end-to-end brownfield smoke test using a real tmp git repo.

Technical notes: Codebase mode checks out a separate worktree branch (cook/<runId>) and runs agents against seeded slice worktrees without mutating the source repo’s HEAD or tracked-file status.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/orchestrator/src/epic-sandbox-merge.ts
Comment thread src/orchestrator/src/net-compiler.ts Outdated
Comment thread src/orchestrator/src/net-compiler.ts
@kostandinang kostandinang force-pushed the ka/fe-755-cook-codebase-mode branch from 4e77df6 to c2cfb6e Compare May 27, 2026 20:44
@kostandinang kostandinang force-pushed the ka/fe-747-petri-declarative-routing branch from ee16289 to eef2f05 Compare May 27, 2026 20:44
Comment thread src/orchestrator/src/worktree.ts
Comment thread src/orchestrator/src/epic-sandbox-merge.ts Outdated
@kostandinang kostandinang changed the title FE-755: Cook codebase-mode — brownfield resolver for brunch cook FE-755: Cook codebase mode for brownfield brunch cook May 27, 2026
@kostandinang kostandinang force-pushed the ka/fe-755-cook-codebase-mode branch from c2cfb6e to e549e84 Compare May 27, 2026 21:13
@kostandinang kostandinang force-pushed the ka/fe-747-petri-declarative-routing branch from eef2f05 to 578e7c9 Compare May 27, 2026 21:16
@kostandinang kostandinang changed the title FE-755: Cook codebase mode for brownfield brunch cook FE-755: Cook codebase mode for brownfield brunch May 27, 2026
@kostandinang kostandinang force-pushed the ka/fe-755-cook-codebase-mode branch from e549e84 to ecc2cc5 Compare May 27, 2026 23:16
@kostandinang kostandinang force-pushed the ka/fe-747-petri-declarative-routing branch from 578e7c9 to 921cb17 Compare May 27, 2026 23:16
kostandinang and others added 5 commits May 28, 2026 01:20
`brunch cook <dir>` now runs against an existing repo. When
`<dir>/.brunch/cook/plan.yaml` exists and the working tree's tracked
files are clean, cook initializes the sandbox via
`git worktree add <sandboxDir> -b cook/<runId> HEAD` from the source
repo, per-slice worktrees are seeded by file-copy from the parent
(excluding `.git`, sibling slice dirs, and `__epic__/`), and pi-actions
run unchanged against pre-existing code. The source branch in `<dir>`
stays byte-identical.

Also consolidates cook's filesystem footprint from `<cwd>/.cook/` to
`<cwd>/.brunch/cook/` so all cook state lives under the existing
`.brunch/` workspace convention.

Acceptance criteria covered:
- Resolver replaces the "not yet implemented" early-exit at
  cook-cli.ts:65-70 with a pure `resolveCookMode(dir)` discriminated
  union (fixture / codebase / error).
- Clean-tree gate refuses brownfield runs with uncommitted tracked
  changes (`git status --porcelain --untracked-files=no`).
- `createSandbox` gains a `CreateSandboxOptions` discriminated union;
  codebase mode invokes `git worktree add` on branch `cook/<runId>`.
- `seedSliceFromParentWorktree` populates per-slice dirs from the
  parent worktree contents.
- `OrchestratorInput.sandboxMode?: 'fixture' | 'codebase'` threads the
  mode through to net-compiler.
- `pi-actions.ts` unchanged. Existing greenfield fixture-mode tests
  pass; new tests in cook-cli.test.ts (resolveCookMode), worktree.test.ts
  (codebase-mode createSandbox), epic-sandbox-merge.test.ts
  (seedSliceFromParentWorktree), plus a tmpdir+fake-actions
  brownfield-smoke.integration.test.ts that pins source-byte-identical
  isolation. Total: 1447/1447 tests pass.

Known follow-ons (out of scope for this PR):
- pi-actions evaluator currently gets full write tools, collapsing the
  TDD-shaped workflow when pi can satisfy the slice during evaluation.
- No "promote cook artifact back" story — modification lives in
  untracked subdirs of the cook branch's worktree, not as commits.
- Multi-slice brownfield over-copy (TODO in `seedSliceFromParentWorktree`)
  — slice 2's 1-slice fixture didn't exercise it.

A 2026-05-26 spike evaluated `@ai-hero/sandcastle` for hybrid adoption.
Technically viable (built-in pi provider, decoupled worktree primitives,
noSandbox available) but deferred until sandcastle ships 1.0 or
multi-slice over-copy becomes a measurable bottleneck.

A 2026-05-26 outer-loop smoke against a tmpdir git repo with real pi
confirmed in-place file modification and source-byte-identical isolation
end-to-end.

Updates SPEC §D50, §A49, §I123-K, §Lexicon (path consolidation) and
PLAN.md `cook-codebase-mode` frontier definition (now Recently
Completed with three follow-on findings).

Co-Authored-By: Claude <noreply@anthropic.com>
Slice 3 of FE-755 refactors per-slice worktree population into a hybrid
mechanism. Tracked content arrives via `git worktree add` on a slice-level
branch (`cook-slice/<runId>/<sliceId>`); untracked/gitignored content
(`node_modules/`, `dist/`, etc.) arrives via copy-on-write (`cp -c` on
macOS APFS, `cp --reflink=auto` on Linux btrfs/xfs/zfs, recursive `cpSync`
fallback).

Solves the multi-slice over-copy problem flagged as a TODO in slice 2
(~90% disk savings on CoW filesystems) while keeping runtime deps present
so pi-actions can run `npm test`/`bun test` against the slice worktree.

Slice branches use the `cook-slice/<runId>/<sliceId>` sibling namespace
rather than nesting under `cook/<runId>/<sliceId>` because git refs are
leaf-or-directory: with `cook/<runId>` already a leaf, the nested form
fails with "cannot lock ref ... 'refs/heads/cook/<runId>' exists."

OrchestratorInput.runId threads through from cook-cli for slice-branch
naming. pi-actions.ts unchanged.

Test changes:
- epic-sandbox-merge.test.ts: rewrites seedSliceFromParentWorktree tests
  around real git parents — tracked-via-git, untracked-via-CoW, slice-level
  branch checkout, sibling-slice exclusion, __epic__ exclusion.
- brownfield-smoke.integration.test.ts: passes runId; asserts the slice
  worktree is on its cook-slice/<runId>/<sliceId> branch.
- Verify: 123 test files, 1449 tests pass; 0 errors.

Also: docs/praxis/cook-brownfield.md — brunch-specific operational guide
covering pre-flight, hand-authored vs ln-scope-derived plans, the
absolute-path invocation gotcha, source-byte-identical verification,
manual artifact promotion, and cleanup.

PLAN.md updated: the multi-slice over-copy follow-on is retired (subsumed
by this work). `cook-artifact-lifecycle` remains as a separate proposed
frontier: commit slice work, replace mergeSlicesIntoEpicSandbox's file-copy
with `git merge` of slice branches (surfaces real conflicts; today's
behavior is silent last-slice-wins), and merge epic branches back to
cook/<runId> so `git merge cook/<runId>` becomes the promotion path. This
slice sets up the substrate (real slice branches) so that frontier can
land cleanly on top.

Co-Authored-By: Claude <noreply@anthropic.com>
…tion.

Renames docs/praxis/cook-brownfield.md → docs/praxis/orchestration-guide.md
to make room for the doc to grow beyond pure brownfield-mode notes (e.g.
greenfield fixture workflows, future graph-compiled plans).

Restructures the "Author the plan" section to lead with the intended
long-term target: read the plan from a spec-graph projection emitted by
`petri-graph-compilation` (currently blocked on FE-700 intent-graph-
semantics). Until that lands, two interim bridges remain — `/ln-scope`-
then-translate (most disciplined) and one-shot pi translation (cheap) —
plus hand-authoring as an escape hatch for one-off experiments.

Co-Authored-By: Claude <noreply@anthropic.com>
Fail before git worktree add when a slice id matches an existing
top-level path in the parent worktree (e.g. src/).

Co-authored-by: Cursor <cursoragent@cursor.com>
git worktree add only checks out tracked files; CoW-copy missing
top-level entries from the source cwd when creating the parent sandbox
so slice seeding inherits node_modules/dist-style artifacts. Extract
cowCopy into cow-copy.ts with complete JSDoc and reuse for slice seed.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kostandinang kostandinang force-pushed the ka/fe-747-petri-declarative-routing branch from 921cb17 to 2047ef2 Compare May 27, 2026 23:21
@kostandinang kostandinang force-pushed the ka/fe-755-cook-codebase-mode branch from ecc2cc5 to 3cc97a2 Compare May 27, 2026 23:21
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3cc97a2. Configure here.

// `git worktree add` only materializes tracked files; CoW-copy untracked /
// gitignored top-level dirs (e.g. `node_modules/`) from the source cwd so
// slice seeding and pi-actions see the same runtime deps as the developer tree.
copyMissingTopLevelEntries(opts.sourceDir, sandboxDir);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CoW copy missing .brunch exclusion causes recursive copy

Medium Severity

copyMissingTopLevelEntries(opts.sourceDir, sandboxDir) uses the default exclude set ({'.git'}) and does not exclude .brunch. Since .brunch/ is gitignored, it won't exist in the worktree after git worktree add, so existsSync returns false and it gets CoW-copied. In the common case where baseDir === sourceDir (e.g. brunch cook "$(pwd)"), this copies sourceDir/.brunch/cook/runs/<runId>/worktree/ — the current sandbox itself — into a nested .brunch/ inside the sandbox, wastefully duplicating the entire worktree content plus any previous run artifacts.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3cc97a2. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant