Skip to main content

Module exec

Module exec 

Source
Expand description

kranz exec -f <mission.md> — fully headless missions for CI (roadmap M5).

Plan file in, exit code out. There is no human on the other end: the mission.md is a ticket-shaped markdown that must be self-sufficient, and approval is automatic. The one place a headless run can’t proceed is when the orchestrator answers request_plan with clarifying questions instead of a plan — that means the plan file was underspecified, so exec fails with a distinct exit code (3) and prints the questions to stderr for the CI log.

Flow (mirrors cmd_draft’s non-interactive seed→plan path, but then runs the mission instead of parking it): parse file → Ticket::mission_goal() → build backend → MissionEngine::create → one planning_turn seeding the whole ticket → request_plan() → auto-approve (or exit 3) → run() to a terminal state.

Events stream to stderr live (the same tail::tail_events feed kranz run uses) so CI logs show progress; the only thing on stdout is the final one-line machine-readable summary: kranz exec <id> <STATUS> cost=$X.XX branch=<b>

stdin is never read and no TUI is ever opened.

Structs§

ExecOptions
Non-file inputs to one headless exec invocation.
ExternalEnqueueSource

Constants§

EXIT_PUSH_FAILED
Exit code when the mission COMPLETE’d but --push failed. Distinct from mission failure (1) and underspecified (3) so CI can tell delivery apart from the run itself. Stdout still reports pushed=false.
EXIT_UNDERSPECIFIED
Exit code exec fails with when the plan file is underspecified: the orchestrator wanted clarification it cannot get headlessly (NotReady).

Functions§

cmd_exec
kranz exec -f <mission.md> [--repo <path>] [--yes] [--max-cycles N] [--enqueue] [--allow-unvalidated].
exit_code_for
Map a terminal mission status to the process exit code exec returns.
parse_mission_markdown
Parse a ticket-shaped plan file into a Ticket. The slug is derived from the file stem (like Ticket::load), so the folded Ticket::mission_goal carries the goal, scoping answers, acceptance hints, and context verbatim.
scrutiny_gate
The unattended scrutiny floor: exec runs with no human present, so a mission whose config disables the scrutiny validator (skipScrutiny) has no adversarial reader at all and can satisfy its own acceptance tautologically (docs/gascity.md lesson 3 records exactly this incident). Interactive run/plan are not gated — a human is present there. Passing --allow-unvalidated (or setting KRANZ_ALLOW_UNVALIDATED=1) is an explicit, auditable acknowledgment that overrides the floor.