compose

package
v0.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 9, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package compose implements fairpeer's structured development workflow: after a plan is approved, a multi-task feature runs through Implement → Verify → (Review) with bounded retries, instead of a single execution turn that never validates the result.

The runner is a deterministic Go orchestrator (mirroring MiMo-Code's compose.js design choice): it drives subagent calls in a fixed phase order and gates transitions on structured verify results — it does NOT rely on the model to self-navigate the phases. The model's job is to implement and fix; the orchestrator's job is to decide when to verify, retry, and stop.

This package is intentionally decoupled from control: the Controller calls ShouldCompose to decide whether to hand off, then calls Run inside the approved-plan execution window. The runner borrows the controller's Runner/Sink/Executor to dispatch turns, but owns its own cross-turn state (verify results, attempt counts) because the agent's evidence ledger resets every Run (agent.go:630).

Index

Constants

View Source
const MaxImplementAttempts = 3

MaxImplementAttempts bounds the Implement→Verify retry loop. After this many failed verify rounds the run gives up and returns the last failure to the caller (the controller marks the plan todos complete regardless, since the user approved the plan and the work partially landed).

View Source
const MaxReplans = 2

MaxReplans bounds how many times the workflow can pause and re-plan when the model discovers the approved plan's assumptions are wrong (VERDICT: PLAN_INVALID). Each replan is a fresh planning turn + a user approval, so this also bounds how many times the user is interrupted for re-approval.

View Source
const MinTasksForCompose = 3

MinTasksForCompose is the task-count threshold above which the controller hands off to the compose runner instead of the single-turn execution path. Below this, the plan is small enough that one execution turn suffices.

Variables

This section is empty.

Functions

func ShouldCompose

func ShouldCompose(seededTodosJSON string) bool

ShouldCompose reports whether an approved plan's seeded todo list is large enough to warrant the compose workflow. The controller calls this with the JSON string returned by seedPlanTodos to decide which execution path to take.

Types

type Runner

type Runner struct {
	// contains filtered or unexported fields
}

Runner orchestrates the Implement → Verify → (Review) loop for an approved plan. It borrows the controller's Runner (to dispatch execution turns) and Sink (to surface progress), and holds cross-turn state that the agent's per-turn evidence ledger cannot (the ledger resets every Run).

func NewRunner

func NewRunner(r agent.Runner, sink event.Sink, synthesizeFn func(string) string, historyFn func() string, implementNudge string, requestApprovalFn func(ctx context.Context, reason string) (bool, error)) *Runner

NewRunner builds a Runner that borrows the controller's dispatch primitives. implementNudge is the plan-approved message the controller would normally send (passed in to avoid compose importing control). history returns the last assistant reply text so the runner can parse the verify verdict. requestApproval is called when the workflow needs the user to confirm a mid-run plan revision (VERDICT: PLAN_INVALID); nil disables replanning.

func (*Runner) GaveUp

func (r *Runner) GaveUp() bool

GaveUp reports whether the last Run gave up without a clean review (attempts exhausted or replan declined). When true, the work only partially landed and the caller should not mark the plan as fully completed.

func (*Runner) Run

func (r *Runner) Run(ctx context.Context, proposal string, seededTodosJSON string) error

Run executes the compose workflow for an approved plan. It is called inside the controller's approved-plan execution window (approvedPlanAutoApproveTools is already true), so writer tools auto-approve during each Implement turn.

The workflow:

  1. Implement — drive the model to execute the plan (one full runner.Run)
  2. Verify — ask the model to run the project's tests/build and report pass/fail with evidence (a second runner.Run with a verify nudge)
  3. If verify failed and attempts remain, feed failures back and retry from 1
  4. Stop on first green verify, or after MaxImplementAttempts
  5. PLAN_INVALID: at any verify/review failure, if the model judges the plan's assumptions are wrong (not just a code bug), it emits VERDICT: PLAN_INVALID. The runner pauses, notifies the user, and requests approval to re-plan. On approval, the model re-plans the remaining work and execution resumes. This is bounded by MaxReplans so the user isn't interrupted indefinitely.

The runner does NOT do Review in this MVP (A6 adds it); verify is the gate.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL