Documentation
¶
Overview ¶
Session-initiated handoff (CLA-352): a session ends its FINAL message with a marker line followed by the prompt for its successor, and the driver respawns a fresh session on that prompt — same task, same run-continuity rules as a phase resume — instead of moving to the next backlog iteration. The phase split (v0.5.0) is this idea at two fixed, driver-chosen points; this generalises it to points the session chooses.
The prompt is parsed out of the final message, NOT a file: the state dir is deliberately outside every session workdir (CLA-259) precisely so sessions cannot write control markers, and the result stream is a channel the driver already consumes.
A session-authored respawn prompt is self-directed prompt injection, so it is honoured only inside three non-negotiable guards, enforced in drainPhases: a respawn counts as an iteration against max_iterations and the token budget (checked BEFORE the respawn), an over-size prompt is refused with a logged fallback, and a chain of consecutive handoffs is capped.
Package loop is the driver: a long-running daemon that gates each iteration on a cheap backlog read, spends a fresh harness session only when there is claimable work, and — crucially — stays alive and keeps polling when the queue is empty, so it reacts when questions are answered, items are promoted, or new work is filed. On a usage limit it pauses and polls for an early reset; on a transient blip it backs off and retries. All durable state lives in the backlog (over MCP), so a session killed mid-task is reclaimed by the next iteration.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Driver ¶
type Driver struct {
// contains filtered or unexported fields
}
Driver runs the loop for one harness against one or more backlogs.
func New ¶
New builds a single-project Driver — the original mode, driven entirely by the top-level config fields.
func NewMulti ¶
NewMulti builds a Driver over several targets (CLA-142): one loop instance, one account key, many project queues — round-robin over whichever have claimable work.
type Target ¶
type Target struct {
// Name is the project slug, used to prefix log lines when there is more than
// one target. Empty for the single default target.
Name string
// Poller is this project's cheap backlog read.
Poller backlog.Poller
// WorkDir is where this project's sessions run. Empty = the config's workdir.
WorkDir string
// MCPConfigPath points this project's sessions at its .mcp.json (the file
// whose /mcp/<slug> URL selects the project). Empty = the config's path.
MCPConfigPath string
// MCPConfigPaths is this project's MCP config PER HARNESS, for a sequence
// whose phases are not all on one harness (CLA-366). MCPConfigPath above is
// the top-level harness's file; a phase on another harness needs the same
// project in that harness's schema, which is a different file. Empty on every
// single-harness run, and config.Validate refuses the combination that would
// need an entry here and lacks one.
MCPConfigPaths map[string]string
// Releaser hands back a claim a session left holding (CLA-242). Nil disables
// the handback for this target, which costs only the reclaim an expiring lease
// would have cost anyway — so a target without one degrades, it does not break.
Releaser plane.Releaser
}
Target is one backlog a Driver drives: a project's cheap poller plus where that project's drain sessions run (CLA-142). A single-project Driver has exactly one, unnamed target; a multi-project Driver has one per configured project.