Skip to content

FE-871: brunch toolchain detection — detect + plan-emitter wiring#214

Draft
kostandinang wants to merge 4 commits into
ka/fe-867-agent-extension-hostfrom
ka/fe-871-brunch-detect
Draft

FE-871: brunch toolchain detection — detect + plan-emitter wiring#214
kostandinang wants to merge 4 commits into
ka/fe-867-agent-extension-hostfrom
ka/fe-871-brunch-detect

Conversation

@kostandinang

@kostandinang kostandinang commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Stacks on FE-867. Second Arc-1 frontier — closes the brunch detect gap FE-843 deferred. Slices 1 + 2 both land here.

What?

Resolve a real repo's toolchain to a registry ProfileId at plan time, and use it as the brownfield front of the FE-843 chain.

  • Slice 1 — detector (detectProfile, project-detect.ts): pure, evidence-first — the cheap "which lockfile/manifest is present" check, not a language-detection engine. Bun lockfile → bun; deno config → deno; package.json deps → vitest/jest/none → node-vitest/node-jest/node-test. One clear supported signal resolves; anything else fails loud ({detected:false, reason}), never a silent default; maps only to registry ids.
  • Slice 2 — wire it in (resolveEmittedProfile, plan-emitter.ts): detected becomes the brownfield front of the chain —
--profile ≫ detected (brownfield) ≫ spec ≫ architect ≫ bun

repoDir threads CLI cwd → runPlanemitPlanFromSnapshot; injectable detect seam keeps tests hermetic. A loud failure throws rather than silently falling to bun. Greenfield (no repoDir) keeps the unchanged FE-843 chain.

Why?

Per-slice verification runs one target at a time, and that command is runner-specific (bun test vs npx vitest run vs npx jest vs deno test). The toolchain must be known at plan time — the deterministic runner reads the stamped plan.profile with no agent in the loop, so a wrong default runs the wrong command with no diagnostic. For an existing repo the manifest is the authoritative source; every other source is a guess or a manual step.

D160-K-clean: profile-id resolution is an input to authoring, not architect host-introspection — no amendment needed.

Review fixes (this revision)

  • Bug — ambiguous evidence was resolved by check-order. A package.json declaring both vitest and jest silently picked vitest, violating the fail-loud-not-silent-default invariant (acceptance Dolt #4). It now returns a loud {detected:false} reason and defers to --profile.
  • Overengineering trim. Dropped the pyproject.toml/setup.py/go.mod special-cases (+ the unsupported helper): they only renamed an error the catch-all already produces actionably — the "language-detection framework" the design explicitly rejects. Non-JS repos still fail loudly via one actionable catch-all; only the per-stack naming is gone.

Co-authored-by: Amp amp@ampcode.com

🤖 Generated with Claude Code

kostandinang and others added 2 commits June 15, 2026 16:13
Add detectProfile(repoDir): a pure, evidence-first detector that maps a real
repo's manifests/lockfiles to a registry ProfileId — the brownfield front of
the FE-843 selection chain. Bun lockfile → bun; deno config/lock → deno;
package.json vitest/jest/none → node-vitest/node-jest/node-test (lockfile
evidence wins over package.json deps).

Fails loudly instead of defaulting: known-but-unsupported stacks (Python via
pyproject.toml/setup.py, Go via go.mod) and unrecognized dirs return
{detected:false, reason} with an actionable message and the valid profile
list — a wrong-but-silent toolchain produces unrunnable tests, the failure
this closes. A malformed package.json is treated as a Node project (node-test).

Pure detector only; wiring into the plan-emitter chain + the greenfield no-op
and greenfield-protecting check are slice 2.

Amp-Thread-ID: https://ampcode.com/threads/T-019ecb9a-9a08-733b-833d-76885fc8243a
Co-authored-by: Amp <amp@ampcode.com>
Insert brunch-detect as the brownfield front of the FE-843 selection
chain via resolveEmittedProfile: flag >> detected (brownfield) >> spec
>> architect-classified >> bun. A loud detection failure throws rather
than silently defaulting to bun (falling through to an explicit
spec/architect choice first). Greenfield (or brownfield without a
repoDir) keeps the unchanged chain.

Thread repoDir from the CLI launch cwd through runPlan into
emitPlanFromSnapshot; expose an injectable detect seam for hermetic
emitter tests.

Amp-Thread-ID: https://ampcode.com/threads/T-019ecb9a-9a08-733b-833d-76885fc8243a
Co-authored-by: Amp <amp@ampcode.com>

kostandinang commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

… verification

Fold the agent-native action vs harness-owned verification distinction
into both frontier definitions: the value is the independent,
deterministic, unshortcuttable check (the FE-800 orphan problem is
unsolvable by agent self-report — same read-only discipline as
evaluate-done at pi-actions.ts:70), not the boot/wiring action, which is
agent-native via bash. Boot mechanics may lean on agent bash rather than
a bespoke per-stack boot engine.

Amp-Thread-ID: https://ampcode.com/threads/T-019ecb9a-9a08-733b-833d-76885fc8243a
Co-authored-by: Amp <amp@ampcode.com>
@kostandinang kostandinang changed the title FE-871: brunch toolchain detection — detectProfile (slice 1) FE-871: brunch toolchain detection — detect + plan-emitter wiring Jun 15, 2026
…nches

Review fix (oracle-confirmed): detectProfile silently resolved ambiguous
evidence by check-order — a package.json declaring both vitest and jest
picked vitest, violating the fail-loud-not-silent-default invariant
(acceptance #4). It now returns a loud {detected:false} reason and defers
to --profile.

Also trims the pyproject.toml/setup.py/go.mod special-casing (+ the
'unsupported' helper): those only renamed an error the catch-all already
produces actionably, which is the 'language-detection framework' the design
explicitly rejects. Any repo with no JS/TS evidence now falls to one
actionable catch-all. Behavior for non-JS repos is unchanged (still a loud,
actionable failure); only the per-stack naming is gone.

PLAN.md brunch-detect definition updated to match.

Amp-Thread-ID: https://ampcode.com/threads/T-019ecb9a-9a08-733b-833d-76885fc8243a
Co-authored-by: Amp <amp@ampcode.com>
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