Notation
Skill(name) / Skill(name, args) = load ~/.codex/skills/{name}/SKILL.md or .codex/skills/{name}/SKILL.md(project overrides global), args fill the input parameter slots of the target SKILL.md <context> block. This is an internal call between skills,not a CLI command. Strictly forbidden to translate as Bash("maestro {name} {args}")— the CLI does not accept bare intent.
Valid CLI subcommands are limited to structured operations:maestro ralph next、maestro ralph complete、maestro ralph skills、maestro delegate、maestro explore , etc.
Session
.workflow/.maestro/{session_id}/status.json — single source of truth for the workflow (schema see <appendix>). session_id format:ralph-{YYYYMMDD-HHmmss}(created by this skill, adaptive chain) or maestro-{YYYYMMDD-HHmmss}(Skill(maestro) created by the coordinator, static chain). Both types are advanced by Skill(maestro-ralph-execute) . When session-id is omitted: continue/execute take the latest status=="running"; status takes the latest session (by created_at, regardless of status).
Entry points
Skill(maestro-ralph, "intent")— create new session: infer → decompose → build → create_goal (if there is a decomposition) → dispatch ralph-executeSkill(maestro-ralph, "continue [session-id]")— user entry point: resume execution, route to S_DISPATCH →Skill(maestro-ralph-execute). When session-id is omitted, take the lateststatus=="running"sessionSkill(maestro-ralph, "status [session-id]")— display progress. When session-id is omitted, take the latest session (by created_at, regardless of status)
continue vs ralph-execute: when the user says "continue", go through
Skill(maestro-ralph, "continue")(user entry point, via S_DISPATCH handoff); the internal step advancement chain and decision callbacks go throughSkill(maestro-ralph-execute)(internal handoff, skipping the ralph routing layer). Both ultimately execute the step via ralph-execute.
Advancement rules:step advancement is handled by
Skill(maestro-ralph-execute)is responsible; ralph only intervenes during build / decision evaluation. Decision nodes are automatically handled by ralph-executeSkill(maestro-ralph)directly calling handoff, with no need for the user to switch manually.
CLI vs Skill boundary:
maestroas a CLI binary only has structured subcommands (ralph、delegate、explore, etc.), and does not accept bare intent.Bash("maestro \"some intent\"")will error out and exit. Creating sessions and routing intent must be done throughSkill(maestro-ralph)orSkill(maestro)skill calls. The CLI layer is only used for step loading (ralph next) and completion marking (ralph complete)。
Initial decomposition (S_DECOMPOSE): boundary-clarified via ≤3 questions for broad intents (重构/全面/迁移/重写). Write to status.json's boundary_contract / execution_criteria / task_decomposition, register the goal via create_goal .
Step kinds:
- Execute step: ralph-execute calls
Bash("maestro ralph next")to load SKILL.md + required_reading in full, and executes inline according to stdout - decision step:
step.decisionfield is non-empty; return to ralph for evaluation (CLI is read-only analysis)
Key difference from maestro coordinator:
- maestro: static chain → one-time selection → runs all steps
- ralph: living chain → decision nodes re-evaluate → chain grows/shrinks dynamically
Session: .workflow/.maestro/ralph-{YYYYMMDD-HHmmss}/status.json
Mutual invocation with Skill(maestro-ralph-execute) forms a self-perpetuating work loop.
Execution Flow
Skill(maestro-ralph, "intent") ─▶ ralph infer → decompose → build chain
│ resolves command_path per step
│ writes status.json
│ calls create_goal
▼
ralph-execute ◀─┐ 执行 step → `maestro ralph next` + inline + `ralph complete`
│ │ decision step → Skill(maestro-ralph)
└─────────┘ CLI writes step.completion_confirmed
loop until all completion_confirmed | paused
<deferred_reading>
- ralph-amend-goal.md — read when
--amendflag active for goal amendment flow </deferred_reading>
Parse:
-y flag → auto_confirm = true
--amend / -a → amend_mode = true (running session 存在时触发目标修改流程)
.md/.txt path → input_doc (supplementary context only, NEVER substitutes lifecycle stages)
status|continue + session-id → 当 intent ∈ {status,continue} 且后续 token 匹配 ralph-*|maestro-* → target_session_id
Remaining → intent (amend_mode 时为 change_request)
State files:
.workflow/state.json— artifact registry, milestones, phases.workflow/roadmap.md— milestone/phase structure.workflow/.maestro/ralph-*/status.json— ralph session state
<state_machine>
S_PARSE_ROUTE: → S_STATUS WHEN: intent == "status" → S_CONTINUE WHEN: intent == "continue" → S_AMEND_GOAL WHEN: amend_mode == true AND running session exists → S_FALLBACK WHEN: amend_mode == true AND no running session DO: Display: "No running session, --amend requires an active session" → S_DECISION_EVAL WHEN: running session with decision step in "running" status → S_PREPARE_SESSION WHEN: intent is non-empty ← derive all facts such as phase/position in one pass → S_FALLBACK WHEN: no intent AND no running session
S_STATUS: → END DO: A_SHOW_STATUS
S_CONTINUE: → S_DISPATCH WHEN: target_session_id provided AND session exists → S_DISPATCH WHEN: running session found (no target_session_id → latest running) → S_FALLBACK WHEN: no running session DO: display "No running ralph session"
S_PREPARE_SESSION: → S_DECOMPOSE WHEN: preparation succeeded DO: A_PREPARE_SESSION → S_FALLBACK WHEN: ambiguous GUARD: auto_confirm does NOT skip phase ambiguity
S_DECOMPOSE: → S_BUILD_CHAIN DO: A_DECOMPOSE_TASKS GUARD: broad intent → MUST clarify boundary even if auto_confirm GUARD: narrow intent → auto-derive, skip questions GUARD: lifecycle_position ∈ {grill, brainstorm, blueprint, init} → skip decomposition
S_BUILD_CHAIN: → S_CREATE_SESSION DO: A_BUILD_STEPS
S_CREATE_SESSION: → S_CONFIRM WHEN: not auto_confirm DO: A_CREATE_SESSION → S_DISPATCH WHEN: auto_confirm DO: A_CREATE_SESSION
S_CONFIRM: → S_DISPATCH WHEN: user selects "Proceed" → S_BUILD_CHAIN WHEN: user selects "Edit" → END WHEN: user selects "Cancel"
S_DISPATCH: → END DO: Skill(maestro-ralph-execute)
S_DECISION_EVAL: (decision node == step.decision is non-empty; the following gate names are taken from that field)
→ S_APPLY_VERDICT WHEN: quality-gate (post-execute, post-business-test, post-review, post-test)
DO: A_DELEGATE_EVALUATE
→ S_APPLY_VERDICT WHEN: goal-gate (post-goal-audit)
DO: A_GOAL_AUDIT_EVALUATE
→ S_APPLY_VERDICT WHEN: scope-gate (post-analyze-scope)
DO: A_SCOPE_EVALUATE
→ S_APPLY_VERDICT WHEN: reground-gate (post-reground)
DO: A_REGROUND_EVALUATE
→ S_APPLY_VERDICT WHEN: structural (post-milestone, post-debug-escalate)
DO: A_STRUCTURAL_EVALUATE
S_APPLY_VERDICT: → S_DISPATCH WHEN: verdict == "proceed" DO: A_APPLY_PROCEED → S_DISPATCH WHEN: post-goal-audit + unmet sub-goals DO: A_APPLY_GOAL_FIX → S_DISPATCH WHEN: post-goal-audit + all sub-goals met DO: A_APPLY_GOAL_DONE → S_DISPATCH WHEN: post-analyze-scope DO: A_APPLY_SCOPE_VERDICT → S_DISPATCH WHEN: verdict == "fix" DO: A_APPLY_FIX → S_DISPATCH WHEN: verdict == "escalate" DO: A_APPLY_ESCALATE → S_DISPATCH WHEN: post-milestone + standard + next milestone DO: A_ADVANCE_MILESTONE → END WHEN: post-milestone + standard + no next milestone DO: mark completed → END WHEN: post-milestone + adhoc DO: mark completed (adhoc self-contained) → END WHEN: post-debug-escalate (always STOP) DO: A_PAUSE_ESCALATE → END WHEN: post-reground + drifted + confidence_score >= 60 DO: A_REGROUND_HALT → S_DISPATCH WHEN: post-reground + aligned DO: A_APPLY_PROCEED → S_DISPATCH WHEN: post-reground + drifted + confidence_score < 60 DO: A_APPLY_PROCEED (marked LOW CONFIDENCE) GUARD: post-reground + drifted + confidence_score >= 60 → A_REGROUND_HALT (drift circuit breaker, auto_confirm does not skip) GUARD: retry_count >= max_retries → force escalate GUARD: confidence_score < 60 AND proceed → override to fix GUARD: confidence_score > 95 AND fix AND retry > 0 → suggest proceed GUARD: auto_confirm → skip user prompt, apply adjusted verdict GUARD: not auto_confirm → request_user_input with override options
S_AMEND_GOAL: → S_DISPATCH WHEN: change applied + user confirmed DO: A_AMEND_GOAL → END WHEN: user cancels GUARD: RISK_LEVEL=high → auto_confirm invalid, force user confirmation
S_FALLBACK: → S_PARSE_ROUTE WHEN: user provides input DO: request_user_input → END WHEN: user cancels
A_SHOW_STATUS
- If
target_session_idis provided → load directly.workflow/.maestro/{target_session_id}/status.json; otherwise take the latest session (by created_at, regardless of status) - Display: Session, Status, Position, Progress, Current step
- List steps: [✓] completion_confirmed, [▸] current, [ ] pending, [◆] decision(
step.decisionis non-empty); execution step appendscommand_scope(global/project) +command_path - If
task_decompositionpresent (absent → skip):Sub-goals ({done}/{total}) source: {session_dir}/status.json#/task_decomposition [x] G1 done_when={done_when} evidence={evidence} confirmed={completion_confirmed} [ ] G2 done_when={done_when} evidence={evidence} confirmed=false ◀ unmet
A_PREPARE_SESSION
Parse phase, infer lifecycle_position, read scope_verdict, decide quality_mode, decide planning_mode in one pass.
1. Phase & Milestone Derivation:
- Match
phase\s*(\d+)-> take the corresponding phase number from state.json. - intent-derived phrase -> look up
state.json.milestones[*].phase_slugsorartifacts[*].path。 - newly derived phase -> phase_is_new = true.
- When parsing a numeric phase, reverse-look up the milestone:
for ms in state.json.milestones: if str(phase_number) in ms.phase_slugs: return ms.id return state.json.current_milestone
2. Lifecycle Position Derivation:
- Explicit override:
grill(interrogation),brainstorm(storm),blueprint(spec),analyze-macro(broad intent). - Startup detection: no
.workflow/->brainstorm(no source code) /init(has source code); nostate.json->init。 - Phase-sensitive artifact inference:
phase_is_new == true->analyze- latest artifact is
analyze->plan - latest artifact is
plan->execute - latest artifact is
execute->review
3. Scope Verdict Read:
- Locate the latest
type=="analyze"andscope=="macro"artifact, readconclusions.jsonofscope_verdict(large | medium | small)。
4. Quality Mode Decision:
- Explicit override
--quality; if none, default: existsspecs/REQ-*.mdand business is clear ->full(includes business-test/test); otherwise ->standard;--quality quick->quick。
5. Planning Mode Decision:
lifecycle_position ∈ {grill, brainstorm, init, roadmap}->independent。- Otherwise, if the milestone contains multiple phases, set
unifiedwhen auto_confirm, and ask the user interactively when not auto_confirm.
6. Persist Write:
- Write
phase,phase_is_new,milestone,lifecycle_position,scope_verdict,quality_mode,planning_modetostatus.json。
A_DECOMPOSE_TASKS
Runs once before chain build; additive to status.json.
1. Classify intent breadth:
| Pattern | Breadth | Clarify? |
|---|---|---|
| refactor/overhaul/rewrite/redo/holistic/migrate · overhaul/migrate/rewrite/revamp | broad | MUST (ignores auto_confirm) |
| named single file/function/bug, "fix X", "add Y to Z" | narrow | skip — auto-derive |
| otherwise | medium | clarify unless auto_confirm |
2. Clarify boundary (broad/medium) — request_user_input, ≤3 rounds, options pre-filled from intent + a quick Glob/Grep scan of the target module:
| Round | Question | Drives |
|---|---|---|
| Scope | Which directories/files/layers are in scope? What is explicitly excluded? | boundary_contract.in_scope / out_of_scope |
| Constraints | Must be backward compatible? Public API frozen? Behavior/performance budget? Test threshold? | boundary_contract.constraints + execution_criteria |
| Done | What observable result counts as "done"? (e.g., all tests green + zero behavior change + X metric) | boundary_contract.definition_of_done |
narrow → derive defaults from intent + codebase, skip questions.
3. Derive execution_criteria: backward-compat、scope-freeze、test/coverage bar、fix-don't-hide、incremental commit。
4. Derive task_decomposition (sub-goal list — outcome-oriented, NOT lifecycle stages). Each entry:
{ "id": "G1", "goal": "<deliverable>", "boundary": "<in/out note>",
"done_when": "<objectively checkable condition>",
"evidence": "verification.json|review.json|uat.md|<test path>",
"lifecycle": ["analyze","execute","verify"], "status": "pending" }
done_when Must be objectively verifiable and reference an artifact already produced by ralph;lifecycle Fields map to the lifecycle stage that produces the evidence.
5. Persist (additive): boundary_contract, execution_criteria, task_decomposition. Each sub-goal contains status: "pending" + completion_confirmed: false。
6. Register goal via create_goal:
create_goal({
objective: "Ralph {intent} — converge {N} sub-goals within boundary",
success_criteria: task_decomposition.map(g => `${g.id}: ${g.done_when}`),
constraints: [...execution_criteria,
"通过 Skill(maestro-ralph-execute) 推进 step,禁止绕过直接执行 steps[*].skill",
"禁止修改 boundary_contract.out_of_scope"]
})
A_BUILD_STEPS
Generate steps from session.lifecycle_position to milestone-complete(session.milestone when present) or the last quality gate (when standalone).
| Stage | Skill (independent) | Skill (unified) | Decision after | quality_mode |
|---|---|---|---|---|
| grill | maestro-grill "{intent}" |
(same) | — | all (auto_confirm → pass through -y, do not skip) |
| brainstorm | maestro-brainstorm "{intent}" --from grill:{grill_id} (if grill ran) / maestro-brainstorm "{intent}" (otherwise) |
(same) | — | all |
| blueprint | maestro-blueprint "{intent}" |
(same) | — | all |
| init | maestro-init |
(same) | — | all |
| analyze-macro | maestro-analyze "{intent}" |
(same) | post-analyze-scope |
all |
| roadmap | maestro-roadmap --from analyze:{analyze_macro_id} |
(same) | — | all |
| analyze | maestro-analyze {milestone} |
maestro-analyze |
— | all |
| plan | maestro-plan {milestone} (scope=phase) / maestro-plan --from analyze:{analyze_macro_id} (scope=standalone) / maestro-plan --from blueprint:{blueprint_id} (scope=standalone) |
maestro-plan |
— | all |
| execute | maestro-execute {phase} |
maestro-execute |
post-execute |
all |
| business-test | quality-auto-test {phase} |
quality-auto-test |
post-business-test |
full only |
| review | quality-review {phase} |
quality-review |
post-review |
all (quick: append --tier quick) |
| test-gen | quality-auto-test {phase} |
quality-auto-test |
— | full / standard if coverage<80% |
| test | quality-test {phase} |
quality-test |
post-test |
full, standard |
| milestone-audit | maestro-milestone-audit |
(same) | — | all |
| goal-audit | (decision-only) | (same) | post-goal-audit |
all (only if decomposed) |
| milestone-complete | maestro-milestone-complete |
(same) | post-milestone |
all |
All execution stages uniformly go through
maestro ralph nextCLI loading + inline execution; decision nodes are inserted separately as independent steps (see rule 4).
Build rules (apply in order):
- planning_mode column selection:
unified→ Skill (unified) column;independent→ Skill (independent) column - Starting point: start from
session.lifecycle_positionstart - Skip completed: skip stages that already have a completed artifact under the current milestone+phase (filter by
session.phase); unified filters by milestone - quality_mode filtering: exclude non-matching stages by
session.quality_mode3.5. grill auto_confirm pass-through:auto_confirm == truewhen it isgrillappend to step args-y(grill's own Auto mode uses code to answer on its behalf); preservegrillstage and brainstorm's--from grill:* - decision node: after each stage whose Decision is non-empty, insert
{ decision: "<gate>", retry_count: 0, max_retries: 2, command_scope: null, command_path: null } - goal-audit insertion:
task_decompositionwhen present, after the last evidence-producing stage (verify/review/test), beforemilestone-completeinsertdecision:post-goal-audit5.5. re-grounding insertion:WHENtask_decompositionwhen present AND execution steps (excluding decision) ≥3- Starting from the 3rd execution step, insert every 3 steps
{ decision: "post-reground", retry_count: 0, max_retries: 0, command_scope: null, command_path: null } - do not insert after the last execution step (covered by goal-audit)
- not adjacent to an existing quality-gate decision node (defer to the next 3-step boundary)
- steps dynamically inserted by fix-loop included incount (recalculate the 3-step interval from the insertion point)
- Starting from the 3rd execution step, insert every 3 steps
- endpoint hard constraint:
session.milestonewhen present, the chain ends withmilestone-completeends with;session.milestone=null(standalone) skipmilestone-audit+milestone-completestage, the chain ends with the last quality-gate stage - goal_ref propagation:
task_decompositionwhen present, each step matches bystep.stage ∈ g.lifecyclematchstep.goal_ref = g.id(multiple matches take the lexicographically smallest); decision nodes do not carry goal_ref - placeholder: independent preserves
{phase}{intent}; unified does not carry{phase} - command_path resolution(each execution step, decision nodes skipped):
- take the skill name (the first token before args)
- pre-validation passes
Bash("maestro ralph skills --platform codex --json --quiet")fetch all available codex skills at once (global~/.codex/skills/+ project.codex/skills/, project overrides global), match the skill name to get:- hit →
command_scope = "global" | "project",command_path = <绝对 SKILL.md 路径> - Miss →
command_scope = "missing",command_path = null, A_CREATE_SESSION reports error E006
- hit →
- Do not read SKILL.md content during the build phase;
<required_reading>/<deferred_reading>Parsing and loading are performed bymaestro ralph nextCLI at execution time
- Initialize each step
completion_confirmed: false,completion_status: null,completion_evidence: null,completion_summary: null,completion_decisions: null,completion_caveats: null,completion_deferred: null,deferred_reads: [],load: null(written byralph next) - scope_verdict gating(only when the chain start point =
analyze-macro):scope_verdict ∈ {medium, small}→ skiproadmap+analyzetwo stages;planselect the standalone column (--from analyze:{analyze_macro_id}), without{phase}scope_verdict == large→ retainroadmap+analyze;planselect the phase column ({phase})scope_verdict == unknown→ default to the large path; corrected by thepost-analyze-scopedecision node after macro analyze completes (A_APPLY_SCOPE_VERDICT)
- --from auto-injected:
analyze_macro_idexists and the current step isroadmap→ args changed to--from analyze:{analyze_macro_id}analyze_macro_idexists andscope_verdict ∈ {medium, small}and the current step isplan→ args changed to--from analyze:{analyze_macro_id}blueprint_idexists → the current step isplan→ args changed to--from blueprint:{blueprint_id}(lower priority than the phase numeric parameter)- deferred chaining(standalone mode): the preceding artifact of the build phase has not yet been produced; A_RESOLVE_ARGS (ralph-execute) looks it up from state.json at runtime and injects it:
planstep (including the{milestone}placeholder) → look up the latest completed analyze artifact of the same milestone,--from analyze:{milestone_analyze_id}, writesource_artifact_refexecutestep (including the{phase}placeholder) → look up the latest completed plan artifact of the same phase+milestone,--dir {plan_path}(existing logic), writesource_artifact_ref = "plan:{id}"
- write
step.source_artifact_reffor auditing
- D-007 Milestone-ref annotation: every step containing the
{phase}placeholder →step.milestone_id = session.milestone(derived by reverse lookup via A_RESOLVE_PHASE); readingcurrent_milestone - is prohibited; dynamically insert steps(A_APPLY_*) likewise applies rules 7-13
A_CREATE_SESSION
- Validate: all steps'
command_scope != "missing"; otherwise raise E006 + list the missing skills - Write
.workflow/.maestro/ralph-{YYYYMMDD-HHmmss}/status.json(Appendix: Session Schema); includingplatform: "codex",cli_tool: "codex" - Display chain overview: each step displays
{index}. {skill} [{type}] [{command_scope}] - If
task_decompositionpresent: callcreate_goal(already registered by A_DECOMPOSE_TASKS) +update_plan, continue handoff
A_DELEGATE_EVALUATE
- Resolve artifact dir:
.workflow/scratch/{artifact.path}/with fallback glob - Parse decision metadata:
{ decision, retry_count, max_retries } - Map result files:
Decision Files post-execute verification.json post-business-test .tests/auto-test/report.json post-review review.json post-test uat.md, .tests/test-results.json - Check artifact for confidence section → include as signal
- Execute delegate (run_in_background, STOP, wait for callback):
maestro delegate "PURPOSE: 评估 {decision} 质量门结果 TASK: 读取结果 | 分析状态 | 评估严重性 | 给出建议 EXPECTED: ---VERDICT--- STATUS/REASON/GAP_SUMMARY/CONFIDENCE(high|medium|low)/CONFIDENCE_SCORE(0-100)/WEAKEST_DIMENSION ---END--- CONSTRAINTS: 只评估 | 置信度<60% 倾向 fix | retry {n}/{max} 达上限必须 escalate" --role analyze --mode analysis - On callback: parse verdict; if parse fails → fallback STATUS="fix"
- Confidence adjustment: <60 + proceed → fix; >95 + fix + retry>0 → suggest proceed
- Decision log: Append to
{session_dir}/decisions.ndjson:{ "id": "DEC-{timestamp}", "timestamp": "{ISO}", "source": "ralph", "node_id": "{step.decision}", "type": "quality-gate", "verdict": "{adjusted_verdict}", "confidence_score": {N}, "close_call": {N>=50 && N<=70}, "summary": "{REASON}" }
A_STRUCTURAL_EVALUATE
post-milestone:
- Read state.json → resolve completed milestone object
- Determine milestone type:
milestone_obj.type(default"standard"if missing) - Standard milestone (
type != "adhoc"): next milestone exists? → insert lifecycle steps / complete - Adhoc milestone (
type == "adhoc"): always END — adhoc milestones are self-contained, no successor to advance to. Setcurrent_milestone = null.
post-debug-escalate: Always STOP → set paused, display "please intervene manually"
A_SCOPE_EVALUATE
Triggered only by the post-analyze-scope decision node; after macro analyze completes, read conclusions.json.scope_verdict to determine the downstream chain.
- Locate the just-completed macro analyze artifact →
analyze_macro_id,conclusions_path = {artifact_path}/conclusions.json - read
conclusions.scope_verdict(large | medium | small), missing →unknown - write
session.scope_verdict+session.analyze_macro_id - Append
{session_dir}/decisions.ndjson:{ "id": "DEC-{timestamp}", "type": "scope-gate", "source": "ralph", "node_id": "post-analyze-scope", "verdict": "{scope_verdict}", "analyze_macro_id": "{ANL_ID}" } - → A_APPLY_SCOPE_VERDICT
A_GOAL_AUDIT_EVALUATE
Runs only when task_decomposition present.
- Read
session.task_decompositionfrom status.json - For each sub-goal
status != "done": resolveevidenceartifact under current phase scratch dir - Delegate read-only audit (run_in_background, STOP, wait):
maestro delegate "PURPOSE: 审计未完成子目标,判定 met / unmet TASK: 1. 读取 status.json.task_decomposition 中 status!=done 的子目标 2. 打开 evidence 产物,对照 done_when 严格判定 3. 输出 met / unmet,unmet 给出 gap + target_phase CONTEXT: status.json = {session_dir}/status.json evidence = {evidence artifacts} execution_criteria = {execution_criteria} boundary_contract = {boundary_contract} EXPECTED: ---VERDICT--- STATUS=all_met|has_unmet UNMET=[{id:G2,gap:'...',target_phase:execute}, ...] CONFIDENCE_SCORE=0-100 ---END--- CONSTRAINTS: - 只评估,不修改文件 - 严格按 done_when 判定;evidence 缺失 → unmet - 不得建议超出 boundary_contract 的修改 " --role analyze --mode analysis - On callback: for each met sub-goal, set
task_decomposition[i].status="done"+completion_confirmed=true+completed_at=now - Append
{session_dir}/decisions.ndjsonwith"type": "goal-gate",unmet_count,unmet_ids - Verdict:
all_met→ A_APPLY_GOAL_DONE;has_unmet→ A_APPLY_GOAL_FIX GUARD: retry_count >= max_retries AND still unmet → A_APPLY_ESCALATE
A_APPLY_PROCEED
- Mark decision completed, write status.json
- Display: ◆ Decision: {type} → proceed ({reason})
A_APPLY_FIX
- Insert fix-loop commands after current step (see Appendix: Fix-Loop Templates)
- Reindex steps, increment retry_count, write status.json
- Display: ◆ Decision: {type} → fix, +{N} commands inserted
A_APPLY_ESCALATE
- Insert
[quality-debug "{gap_summary}", decision:post-debug-escalate] - Increment retry_count, reindex, write status.json
A_APPLY_SCOPE_VERDICT
Triggered by post-analyze-scope , based on session.scope_verdict reshape the downstream chain.
- read
session.scope_verdict - Path A (
large): keep the current chain; for subsequentroadmapstep inject--from analyze:{analyze_macro_id}; for subsequentplanstep select the phase column; continue advancing - Path B (
medium/small):- delete all incomplete
goal-auditbeforeroadmap+analyze(phase) step - change the next incomplete
planstep tomaestro-plan --from analyze:{analyze_macro_id}, remove{phase},source_artifact_ref = analyze:{analyze_macro_id} - Subsequent
execute/verifyetc. continue with the same standalone scope (without{phase}, driven by the task list written by plan)
- delete all incomplete
- Path C (
unknown):- not auto_confirm → request_user_input choose one of two (large / medium-small); auto_confirm → default large
- Reindex steps, mark decision completed, write status.json
- Display: ◆ Scope verdict: {verdict} → {kept|collapsed to standalone via analyze:{ANL_ID}}
A_APPLY_GOAL_FIX
- For each unmet subgoal
G{n}(deduplicated bytarget_phasegrouping): before thegoal-auditnode, insert a scoped mini-loop (see Appendix: Fix-Loop Templates → post-goal-audit), and for each inserted stepgoal_ref: "G{n}", parse according to A_BUILD_STEPS rule 9command_path - re-append
decision:post-goal-audit {retry+1} - Reindex steps, increment retry_count, write status.json
- Display: ◆ Goal audit: {k} unmet → +{N} steps inserted (G{ids}), retry {r}/{max}
A_APPLY_GOAL_DONE
- status.json: set each
task_decomposition[*].status="done",completion_confirmed=true,completed_at=now, top-leveltask_decomposition_all_done=true - Mark goal-audit decision completed;proceed to
milestone-complete - Display: ◆ Goal audit: all met ✓
A_ADVANCE_MILESTONE
- Update session: milestone, phase, reset passed_gates
- Insert full lifecycle steps for next milestone
- Reindex, write status.json
A_REGROUND_EVALUATE
GUARD: task_decomposition exists (periodically triggered, see build rule 5.5)
- Read status.json:
session.intent,session.boundary_contractsteps[]WHEREstatus=="completed"→ takecompletion_evidence,completion_summary,completion_decisions,completion_caveatstask_decomposition[]WHEREstatus=="done"→ takegoal,done_when
- Delegate read-only audit (run_in_background, STOP, wait):
maestro delegate "PURPOSE: 意图保真检查 — 对照 intent 验证累积执行是否漂移 TASK: 1. 读取 intent + boundary_contract.definition_of_done 2. 读取已完成 steps 的 completion_summary + completion_decisions 3. 判定累积产出是否仍服务 intent;是否有 step 产出超出 in_scope 或触碰 out_of_scope 4. 输出 aligned / drifted CONTEXT: intent = {session.intent} definition_of_done = {boundary_contract.definition_of_done} in_scope = {boundary_contract.in_scope} out_of_scope = {boundary_contract.out_of_scope} completed_steps = [{index, skill, stage, completion_evidence, completion_summary, completion_decisions, completion_caveats}, ...] done_goals = [{id, goal, done_when}, ...] accumulated_deferred = [{from_step, item}, ...] goal_changelog = {session.goal_changelog ?? []} EXPECTED: ---VERDICT--- STATUS=aligned|drifted DRIFT_DESCRIPTION=<空或具体描述> CORRECTIVE_ACTION=<空或建议> CONFIDENCE_SCORE=0-100 ---END--- CONSTRAINTS: - 只评估不修改 - aligned 阈值:≥80% 已完成产出直接服务 intent - 单个 step 触碰 out_of_scope → 直接判 drifted - goal_changelog 存在 → 以最新 after.goals 为基准" --role analyze --mode analysis - On callback: parse verdict
- Append
{session_dir}/decisions.ndjson:{ "id": "DEC-{ts}", "type": "reground-gate", "source": "ralph", "node_id": "post-reground", "verdict": "{aligned|drifted}", "confidence_score": {N} } - Verdict routing:
aligned→ A_APPLY_PROCEED;drifted+confidence_score >= 60→ A_REGROUND_HALT;drifted+confidence_score < 60→ A_APPLY_PROCEED (mark LOW CONFIDENCE)
A_REGROUND_HALT
Drift circuit breaker (safety gate, auto_confirm does not skip).
- Set
session.status = "paused",write status.json - Display:
⚠️ Re-grounding 检测失败 — 执行已偏离 intent。 Intent: {session.intent} Drift: {drift_description} 建议回归: {corrective_action} 选项:1) Skill(maestro-ralph, "continue") 忽略漂移继续 2) 手动修正后 continue 3) Skill(maestro-ralph, "status") 查看后决定 - GUARD: auto_confirm is ineffective for this action—the drift circuit breaker cannot be automatically skipped
A_PAUSE_ESCALATE
- Set session status = "paused", write status.json
- Display: ◆ Maximum retry count reached, debug has been executed. Manual intervention required.
- Display: Skill(maestro-ralph, "continue") resume
A_AMEND_GOAL
Modify the goal of a running session. The detailed procedure is loaded by <deferred_reading> loads ralph-amend-goal.md。
| Phase | behavior | output |
|---|---|---|
| 1. Snapshot | Read task_decomposition + boundary_contract + the completed steps' completion_summary |
Display: goal list + progress |
| 2. Parse | change_request non-empty → use directly; empty → request_user_input (modify/add/remove/adjust boundaries) |
change_type + change_request |
| 3. Mini Grill | maestro delegate --role analyze --mode analysis: assess impact |
RISK_LEVEL + AFFECTED_GOALS + INVALIDATED_STEPS + NEW_GAPS |
| 4. Confirm | request_user_input: apply and continue / only change the goal / cancel | User selection |
| 5. Apply | Archive the old goal (superseded) → write the new goal (origin: CHG-xxx) → rebuild the chain → write status.json |
handoff Skill(maestro-ralph-execute) |
GUARD: RISK_LEVEL == high → request_user_input is not skipped (auto_confirm is ineffective)
GUARD: a completed (status: "done") goal cannot be superseded (skip + warn)
</state_machine>
Session Schema
{
"session_id": "ralph-{YYYYMMDD-HHmmss}",
"source": "ralph", "status": "running",
"ralph_protocol_version": "2", // CLI-driven; absent/0 → legacy; "1" → basic CLI; "2" → structured completion + enhanced anchor
"active_step_index": null, // CLI-managed; only one step held at a time
"intent": "", "lifecycle_position": "",
"phase": null, "phase_is_new": false,
"milestone": "", // D-007 反查结果,禁止读 current_milestone
"auto_mode": false,
"quality_mode": "standard", // "full" | "standard" | "quick"
"planning_mode": "independent", // "unified" | "independent"
"scope_verdict": null, // "large" | "medium" | "small" | "unknown" | null
"analyze_macro_id": null, // "ANL-xxx" 来自最新 macro analyze
"blueprint_id": null, // "BLP-xxx" 若存在
"cli_tool": "codex",
"platform": "codex", // codex skills (`.codex/skills/`)
"passed_gates": [],
"context": { "issue_id": null, "scratch_dir": null, "plan_dir": null,
"analysis_dir": null, "brainstorm_dir": null, "blueprint_dir": null },
"steps": [{
"index": 0,
"skill": "", // 执行 step 有值;decision 节点为空字符串/null
"args": "",
"stage": "", // brainstorm|blueprint|init|analyze-macro|roadmap|analyze|plan|execute|...
"scope": null, // "phase"|"standalone"|"milestone"|null(plan 等需要)
"decision": null, // 非 null → decision 节点(值为 gate 名,如 "post-execute");null → 执行 step
"retry_count": 0, // decision 节点专用
"max_retries": 2, // decision 节点专用
"command_scope": "global|project|missing|null", // 执行 step;decision 节点固定 null
"command_path": "<absolute SKILL.md path resolved by `maestro ralph skills --platform codex --json --quiet`> | null",
"milestone_id": null, // D-007 反查注入;仅含 {phase} 占位符的 step 有
"source_artifact_ref": null, // "analyze:ANL-xxx" | "blueprint:BLP-xxx" | null
"status": "pending|running|completed|skipped|failed",
"goal_ref": null,
"completion_confirmed": false,
"completion_status": null,
"completion_evidence": null,
"completion_summary": null, // 一句话总结:做了什么(MUST on DONE)
"completion_decisions": null, // 本 step 做出的关键决策列表
"completion_caveats": null, // 后续 step 需注意的事项
"completion_deferred": null, // 被推迟到后续的工作列表
"completed_at": null,
"deferred_reads": [], // 由 ralph next CLI 解析 SKILL.md 时填充
"load": null // { loaded_at, required_files[], deferred_files[], resolve_version } —— 由 ralph next 写入
}],
"waves": [], "current_step": 0,
// Optional decomposition block (additive; absent → decomposition off)
"boundary_contract": {
"in_scope": [], "out_of_scope": [], "constraints": [], "definition_of_done": ""
},
"execution_criteria": [],
"task_decomposition": [
{ "id": "G1", "goal": "", "boundary": "", "done_when": "",
"evidence": "", "lifecycle": [], "status": "pending|done|superseded",
"completion_confirmed": false, "completed_at": null,
"superseded_by": null, "superseded_at": null, "origin": null }
],
"task_decomposition_all_done": false,
// goal_changelog: additive; absent → no amendments
"goal_changelog": [
{ "id": "CHG-001", "timestamp": "{ISO}",
"change_type": "modify|add|remove|boundary",
"reason": "变更描述",
"impact_assessment": { "risk_level": "low|medium|high",
"invalidated_steps": [], "new_steps_inserted": 0 },
"before": { "goals": [{"id":"G1","goal":"...","done_when":"..."}] },
"after": { "goals": [{"id":"G1v2","goal":"...","done_when":"..."}] } }
]
}
New fields are optional; default = old behavior; existing field names are neither deleted nor changed.
Fix-Loop Templates
All inserted execution steps parse according to A_BUILD_STEPS rule 9 command_path + command_scope;decision:* entries as decision nodes (step.decision field).
post-execute:
quality-debug "{gap_summary}"
maestro-plan --gaps {phase}
maestro-execute {phase}
decision:post-execute {retry+1}
post-business-test:
quality-debug --from-business-test "{gap_summary}"
maestro-plan --gaps {phase}
maestro-execute {phase}
decision:post-execute {retry: 0}
quality-auto-test {phase}
decision:post-business-test {retry+1}
post-review:
quality-debug "{gap_summary}"
maestro-plan --gaps {phase}
maestro-execute {phase}
quality-review {phase}
decision:post-review {retry+1}
post-test:
quality-debug --from-uat "{gap_summary}"
maestro-plan --gaps {phase}
maestro-execute {phase}
decision:post-execute {retry: 0}
quality-auto-test {phase}
decision:post-business-test {retry: 0}
quality-review {phase}
decision:post-review {retry: 0}
quality-auto-test {phase}
quality-test {phase}
decision:post-test {retry+1}
post-goal-audit: (per unmet sub-goal group)
# for each unmet sub-goal G{n}, scoped to target_phase:
maestro-plan --gaps {target_phase} "G{n}: {gap}" [goal_ref: G{n}]
maestro-execute {target_phase} [goal_ref: G{n}]
# after all unmet groups inserted:
decision:post-goal-audit {retry+1}
Goal Management (Codex Built-in)
After Decomposition output, manage goals through Codex built-in tools (called by A_DECOMPOSE_TASKS step 6):
create_goal— register goal + success_criteria + constraintsupdate_plan— sync steps[] progress to the Codex plan viewupdate_goal— release on convergence (A_APPLY_GOAL_DONE / session completed); keep on abort/pause (supportsSkill(maestro-ralph, "continue")resume)
Error Codes
| Code | Severity | Description | Recovery |
|---|---|---|---|
| E001 | error | No intent and no running session | Prompt for intent |
| E002 | error | Cannot infer lifecycle position | Show raw state, ask |
| E003 | error | Artifact dir not found for decision | Show glob, ask |
| E004 | error | Delegate verdict parse failed | Fallback: "fix" |
| E005 | error | Delegate execution failed | Fallback: "fix" |
| E006 | error | command_scope == "missing" for one or more steps | List missing skills, abort build |
| W001 | warning | Decision expanded chain | Auto-handled |
| W002 | warning | Max retries, escalating | Auto-handled |
| W003 | warning | Multiple running sessions | Use latest, warn |
| W004 | warning | Low delegate confidence | Show warning |
Success Criteria
- Phase is resolved before position; the phase_is_new flag is written to session
- D-007 reverse lookup: phase number →
session.milestone, reading current_milestone is prohibited; write to step.milestone_id - phase_is_new=true → lifecycle_position forced
analyze - Intent overrides identify grill / brainstorm / blueprint / analyze-macro
- when auto_confirm=true, append to grill step args
-y(Auto mode code auto-answer, stage not skipped) - A_RESOLVE_SCOPE_VERDICT reads macro analyze conclusions.scope_verdict, writes to session.scope_verdict + analyze_macro_id
- Chain start point = at analyze-macro: large→roadmap+analyze+plan(milestone); medium/small→jump directly to plan --from analyze:{ANL_ID} (skip roadmap+analyze)
- post-analyze-scope decision node is inserted after macro analyze; A_SCOPE_EVALUATE/A_APPLY_SCOPE_VERDICT reshape the chain
- plan step args support three paths:
{milestone}/--from analyze:{ANL_ID}/--from blueprint:{BLP_ID}, write to step.source_artifact_ref - roadmap step args automatically inject
--from analyze:{analyze_macro_id}(if present) - artifact filtering by session.phase; unified by milestone
- quality_mode is determined by A_DETERMINE_QUALITY_MODE, filters build steps
- Decomposition: broad intent ≤3 question clarify;narrow auto-derive
- status.json single source of truth: boundary_contract + execution_criteria + task_decomposition; no external manifest
- execution step contains
command_scope+command_path(pre-validated viamaestro ralph skills --platform codex --json --quietpre-validation, project overrides global); decision step identified viastep.decisionfield - Ralph build phase only validates path existence via
ralph skills --platform codex, does not read SKILL.md content;<required_reading>loading is done bymaestro ralph nextCLI - each step contains
completion_confirmed+completion_status+completion_evidence+deferred_reads(initially false/null/[]) - each sub-goal contains
completion_confirmed(initially false) - post-goal-audit decision is inserted only when decomposed, located before milestone-complete
- Unmet sub-goals dynamically grow steps[] (goal_ref tagged); max retries → escalate
- planning_mode explicitly determined; unified=no placeholders, independent=analyze/plan with
{milestone}, execute/quality with{phase} - Chain must end with
milestone-completeend - Decision nodes are evaluated by maestro delegate --role analyze
- Ralph does not execute steps, only evaluates;
Skill(maestro-ralph-execute)directly calls handoff - session.platform = "codex"; all CLI calls carry
--platform codex - Deferred chaining: plan/execute step's
--from/--dirinjection is done at runtime by A_RESOLVE_ARGS (ralph-execute); build phase marks intent, does not know artifact ID in advance - Milestone-level plan step obtains at runtime
--from analyze:{milestone_analyze_id}(looked up and injected from state.json by ralph-execute) - Phase-level execute step obtains at runtime
source_artifact_ref = "plan:{id}" - each step contains
completion_summary+completion_decisions+completion_caveats+completion_deferred(initially null) -
completion_summaryis MUST at DONE/DONE_WITH_CONCERNS (passed in via CLI--summaryparameter) - session_anchor contains the
completion_summary+completion_caveatsof the most recent 5 completed steps (sliding window) - session_anchor contains the task_decomposition global view (only
status != "superseded"goals) - session_anchor contains Accumulated Signals (aggregates all caveats + deferred)
-
--amendroutes to S_AMEND_GOAL (requires running session) - A_AMEND_GOAL executes 5 phases (snapshot→parse→mini grill→confirm→apply), each phase produces auditable
- old goal marked
superseded(superseded_by+superseded_at), new goal markedorigin: "CHG-xxx" -
goal_changelogrecords complete before/after snapshot + impact_assessment -
RISK_LEVEL=highamend does not skip auto_confirm when - re-grounding completes, steps information includes completion_summary/decisions/caveats
- fix-loop dynamically inserted steps are counted in the re-grounding 3-step count
- post-reground + drifted + confidence >= 60 → A_REGROUND_HALT (auto_confirm is not skipped)
- session_anchor boundary_contract is not truncated (capAnchorList n=8)