/execute — Plan-Driven Orchestrator

SkillDev tools

Plan-driven orchestrator. Reads plan.json (from /blueprint) or requirements.md, then dispatches workers to build the system. Use when: "/execute", "execute", "plan 실행", "blueprint 실행"

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the /execute — Plan-Driven Orchestrator skill

What this skill tells your AI

The instructions your AI receives, as published by team-attention/hoyeon in skills/execute/SKILL.md and read by ahel’s review.

You are the conductor. You do not play instruments. Delegate to workers, manage parallelization, verify the result.

Core Principles

  1. DELEGATE — Agent/Team: workers do the work. Direct: orchestrator does.
  2. PARALLELIZE — Run unblocked tasks simultaneously via run_in_background: true.
  3. plan.json is the ledger — Task state via hoyeon-cli plan commands. Never direct file writes.
  4. Contracts guide workers — If contracts.md exists, workers reference it for cross-module agreements.
  5. Context flows forward — Workers write learnings; next-round workers read them.

Runtime Surface

Claude Code

  • Use the existing Agent, Task*, Team*, and AskUserQuestion surfaces described below when they are available.
  • Claude hooks may enforce orchestration guards and stop transitions.
  • Logical subagent names remain the canonical Hoyeon names, for example worker, verifier, and code-reviewer.

Codex

  • Codex v1 is Bash-first and no-MCP. Use hoyeon-cli for all plan state.
  • Do not edit plan.json directly; use hoyeon-cli plan task for every status transition.
  • Use logical Hoyeon subagent names in the charter, mapped to Codex adapters when installed:
    • worker -> hoyeon-worker
    • verifier -> hoyeon-verifier
    • code-reviewer -> hoyeon-code-reviewer
  • In Codex, translate every logical Agent(...) dispatch in the references to the native spawn_agent tool:
    • Agent(subagent_type="worker", ...) -> spawn_agent(agent_type="hoyeon-worker", ...)
    • Agent(subagent_type="verifier", ...) -> spawn_agent(agent_type="hoyeon-verifier", ...)
    • Agent(subagent_type="code-reviewer", ...) -> spawn_agent(agent_type="hoyeon-code-reviewer", ...) Pass the worker charter as the agent message, and keep the charter's path-and-ID-only contract unchanged.
  • Treat TaskCreate, TaskUpdate, TaskOutput, and TeamCreate examples in the reference recipes as Claude Code protocol notes, not literal Codex calls. Codex execute state is tracked through hoyeon-cli plan task plus returned subagent messages.
  • If the current Codex session has not loaded the adapter names, fall back to direct single-worker execution and keep the same charter/output contract.
  • Do not rely on hooks, TeamCreate, or automatic stop transitions in Codex v1.
  • Parallel Codex worker dispatch is allowed for disjoint parallel_safe tasks when the hoyeon-worker adapter is prompt-visible. Use spawn_agent for dispatch, hoyeon-cli plan task for state, and returned subagent messages for evidence.
  • scripts/codex-execute-smoke.sh validates only single-worker plan state transitions. It does not prove parallel subagent behavior; verify parallel changes with a bounded live spawn_agent smoke.

Phase 0: Initialize

Phase 0 is plan-first. The orchestrator resolves an input to a valid plan.json, asks two questions (dispatch + verify depth), and prepares a worker charter template. Phase 0 never reads requirements.md or contracts.md body — only plan.json structural fields (INV-3).

0.1 Parse Input & Resolve

/execute [<spec_dir>] [--work worktree|branch|no-commit]
raw_path = $1  (may be empty)

# (a) No argument → virtual plan path (R-F1.3)
IF raw_path is empty:
  input_mode = "virtual"
  spec_dir   = null   # resolved later in 0.2
  GOTO 0.2

# (b) Argument provided → must exist (R-F1.4)
IF NOT exists(raw_path):
  ERROR: "No such path: {raw_path}"
  guidance: "Provide a directory containing plan.json or requirements.md,
             or call /execute with no argument to synthesize a virtual plan."
  ABORT

spec_dir = raw_path if is_dir(raw_path) else dirname(raw_path)

# (c) Classify what we found
IF exists(spec_dir/plan.json):
  input_mode = "plan"          # R-F1.1
ELIF exists(spec_dir/requirements.md):
  input_mode = "requirements"  # R-F1.2
ELSE:
  ERROR: "{spec_dir} has neither plan.json nor requirements.md"
  guidance: "Run /blueprint on requirements.md, or call /execute without arguments
             for a session-synthesized virtual plan."
  ABORT

0.2 Resolve to plan.json

Handle each input_mode — the goal is to end this sub-phase with a validated plan.json on disk and spec_dir set.

IF input_mode == "plan":                             # R-F1.1
  # Direct use — NO user confirm.
  Bash("hoyeon-cli plan validate {spec_dir}")

ELIF input_mode == "requirements":                   # R-F1.2
  # Try /blueprint first; fall back to inline planning if unavailable.
  IF Skill(blueprint, args="{spec_dir}") succeeds AND exists(spec_dir/plan.json):
    Bash("hoyeon-cli plan validate {spec_dir}")
  ELSE:
    # Inline planning — lightweight alternative to /blueprint.
    # Read requirements.md directly (exception to INV-3 — only during init).
    reqs_content = Read("{spec_dir}/requirements.md")

    # Extract frontmatter (type, goal, non_goals) + sub-requirements
    meta_type = parse_frontmatter(reqs_content).type
    sub_reqs  = parse_sub_reqs(reqs_content)  # [{id, given, when, then}]

    # Check pre-work section (if present)
    pre_work = parse_pre_work(reqs_content)   # see "Pre-work Gate" below

    # Generate task graph inline (no contracts, no journeys)
    draft_tasks = []
    FOR EACH logical group of sub_reqs (by parent R-X):
      draft_tasks.append({
        id: "T{n}", action: "<what to build>",
        fulfills: [sub_req.id for sub_req in group],
        depends_on: [], parallel_safe: true
      })

    # Generate basic verify_plan (gate 1+2 for all)
    draft_verify = []
    FOR EACH sub_req in sub_reqs:
      draft_verify.append({ target: sub_req.id, type: "sub_req", gates: [1, 2] })

    # Preview (same pattern as blueprint Step 2.3)
    print("[execute] Inline Plan (no /blueprint)")
    print_task_table(draft_tasks)
    print(f"Verify: {len(draft_verify)} entries (all G1+G2)")

    choice = AskUserQuestion(
      question: "Proceed with this inline plan?",
      options: [
        { label: "Proceed", description: "Write plan.json and execute" },
        { label: "Edit",    description: "Revise tasks before proceeding" },
        { label: "Abort",   description: "Stop — run /blueprint first for a detailed plan" }
      ]
    )
    IF choice == "Abort": HALT
    IF choice == "Edit": draft_tasks = interactive_edit(draft_tasks)

    # Write via cli
    Bash("hoyeon-cli plan init {spec_dir} --type {meta_type}")
    write_json_to_tmp({tasks: draft_tasks, verify_plan: draft_verify}) → /tmp/plan-inline.json
    Bash("hoyeon-cli plan merge {spec_dir} --json \"$(cat /tmp/plan-inline.json)\"")
    Bash("hoyeon-cli plan validate {spec_dir}")

ELIF input_mode == "virtual":                        # R-F1.3
  # Session-context synthesis with user confirm.
  timestamp = Bash("date +%Y%m%d-%H%M%S").trim()
  spec_dir  = ".hoyeon/specs/adhoc-{timestamp}"
  Bash("mkdir -p {spec_dir}")

  # Synthesize a minimal plan from recent user messages + cwd state.
  # Keep it in memory first; do NOT write until the user confirms.
  draft_plan = synthesize_virtual_plan(
    recent_user_messages,
    cwd_state = Bash("ls -la").trim()
  )
  # draft_plan shape: { meta, tasks[{id, action, fulfills:[], depends_on:[], parallel_safe}], verify_plan:[] }

  # Summary preview (stdout, not a file)
  print("Virtual plan synthesized ({len(draft_plan.tasks)} tasks):")
  for t in draft_plan.tasks: print("  {t.id}  {t.action}")

  choice = AskUserQuestion(
    question: "Proceed with this virtual plan?",
    options: [
      { label: "Proceed", description: "Write plan.json to {spec_dir} and execute" },
      { label: "Edit",    description: "Open an interactive edit loop to revise tasks" },
      { label: "Abort",   description: "Discard and exit" }
    ]
  )
  IF choice == "Abort": HALT
  IF choice == "Edit":
    draft_plan = interactive_edit(draft_plan)  # loop until user says proceed

  # Persist via cli (INV-5). Write, then validate.
  write_json_to_tmp(draft_plan) → /tmp/plan-virtual.json
  Bash("hoyeon-cli plan init {spec_dir} --type {draft_plan.meta.type}")
  Bash("hoyeon-cli plan merge {spec_dir} --json \"$(cat /tmp/plan-virtual.json)\"")
  Bash("hoyeon-cli plan validate {spec_dir}")

At the end of 0.2 we have: spec_dir/plan.json (valid) + input_mode + (optionally) spec_dir/contracts.md.

0.2b Pre-work Gate (optional)

If requirements.md exists and contains a ## Pre-work section, parse it and gate on blocking items before proceeding.

IF exists("{spec_dir}/requirements.md"):
  pre_work = scan for "## Pre-work" section → parse checkbox items
  # Expected format: "- [ ] action (blocking)" or "- [ ] action (non-blocking)"
  blocking = [item for item in pre_work if "blocking" in item]

  IF len(blocking) > 0:
    print("Pre-work items requiring completion:")
    FOR EACH item in blocking:
      print("  - {item.action}")

    AskUserQuestion(
      question: "Have you completed all blocking pre-work items?",
      options: [
        { label: "Yes, all done", description: "Continue to execution" },
        { label: "Not yet",       description: "Abort — complete pre-work first" }
      ]
    )
    IF answer == "Not yet": HALT

If there is no ## Pre-work section, skip silently.

0.3 Load plan.json (structural fields only)

INV-3: read only structural fields from plan.json. Do NOT open requirements.md or contracts.md body here.

plan = Read("{spec_dir}/plan.json") → JSON.parse

# Structural metrics used by 0.4 prompts
task_count     = len(plan.tasks)
parallel_count = count(t for t in plan.tasks if t.parallel_safe)
parallel_ratio = parallel_count / task_count if task_count else 0

# Gate distribution across verify_plan (for the verify-depth hint)
gate_hist = {1:0, 2:0, 3:0, 4:0}
FOR vp in plan.verify_plan:
  FOR g in vp.gates: gate_hist[g] += 1
max_gate = max(g for g,c in gate_hist.items() if c > 0) if any else 0

# contracts.md path — path only, never the body (INV-2)
contracts_path = "{spec_dir}/contracts.md" if exists(spec_dir/contracts.md) else null

0.4 User Configuration (dispatch + verify depth)

Two AskUserQuestion calls in order. Both include a structural hint computed in 0.3.

# --- Dispatch mode (R-F2.1) -----------------------------------------
# Recommendation from task count + parallel_safe ratio:
IF task_count <= 3:          recommended = "Direct"
ELIF parallel_ratio >= 0.6:  recommended = "Team"      # many independent tasks
ELSE:                        recommended = "Agent"

dispatch = AskUserQuestion(
  question: "Dispatch mode? ({task_count} tasks, {parallel_count} parallel_safe → recommended: {recommended})",
  options: [
    { label: "Direct", description: "Orchestrator executes tasks sequentially in its own context (best for ≤3 tasks)" },
    { label: "Agent",  description: "Spawn worker subagents per module group, round-level commit" },
    { label: "Team",   description: "TeamCreate persistent workers claim tasks (best for high parallel_safe ratio)" }
  ]
)

# --- Verify depth (R-F2.2) ------------------------------------------
# Hint shows gate distribution from plan.verify_plan.
hint = "gates present: " + join([f"{g}={gate_hist[g]}" for g in [1,2,3,4] if gate_hist[g] > 0], ", ")
IF max_gate == 0: hint = "no verify_plan entries"

verify = AskUserQuestion(
  question: "Verify depth? ({hint})",
  options: [
    { label: "Light",    description: "Gate 1 only — build/lint/typecheck (caps all sub_reqs at gate ≤ 1)" },
    { label: "Standard", description: "Gates 1-2 — build + sub_req double-review (caps all sub_reqs at gate ≤ 2)" },
    { label: "Thorough", description: "All gates — no cap; runs gate 3 (qa-verifier) where planned" }
  ]
)

# --- Work mode (flag or prompt) -------------------------------------
IF --work flag provided:
  work = flag_value
ELSE:
  work = AskUserQuestion(
    question: "Work mode?",
    options: [
      { label: "Worktree",           description: "Isolated worktree, commit per round" },
      { label: "New Branch + Commit", description: "Create feat/ branch from current, commit per round" },
      { label: "Branch + Commit",     description: "Current branch as-is, commit per round" },
      { label: "No Commit",           description: "No git commits" }
    ]
  )

0.5 Setup — session state + charter template

# (a) Session state
STATE_FILE="$HOME/.hoyeon/$CLAUDE_SESSION_ID/state.json"
Bash: jq -n \
  --arg dispatch "{dispatch}" \
  --arg verify   "{verify}" \
  --arg work     "{work}" \
  --arg spec_dir "{spec_dir}" \
  --arg input    "{input_mode}" \
  --arg contracts "{contracts_path or ""}" \
  '{dispatch:$dispatch, verify:$verify, work:$work, spec_dir:$spec_dir,
    input_mode:$input, contracts_path: ($contracts|select(length>0))}' \
  > $STATE_FILE

# (b) Branch/Worktree setup
IF work == "Worktree":
  spec_dir       = Bash("realpath {spec_dir}").trim()
  contracts_path = Bash("realpath {contracts_path}").trim() if contracts_path
  EnterWorktree(name=basename(spec_dir))

IF work == "New Branch + Commit":
  branch_name = "feat/{spec_name}"   # derived from spec_dir basename
  Bash: git checkout -b {branch_name}
  audit_append("BRANCH_CREATE {branch_name} from {current_branch}")

# (c) Context files (next to plan.json)
CONTEXT_DIR = spec_dir
Bash: [ -s {CONTEXT_DIR}/learnings.json ] || echo '[]' > {CONTEXT_DIR}/learnings.json   # initialize to [] if new
Bash: [ -s {CONTEXT_DIR}/issues.json ]    || echo '[]' > {CONTEXT_DIR}/issues.json      # initialize to [] if new
Bash: touch {CONTEXT_DIR}/audit.md

# (d) Worker charter template — paths and IDs only (INV-2, R-N15.1)
# NEVER inline GWT, requirements prose, or contracts body into this template.
CHARTER_TEMPLATE = {
  task_id:              "<injected per task>",
  plan_path:            "{spec_dir}/plan.json",
  contracts_path:       contracts_path,          # path only — see R-F2.3
  contracts_directive:  (contracts_path != null)
                          ? "Read contracts.md before coding — it defines the
                             cross-module surface you must respect."
                          : null,
  sub_req_ids:          "<injected per task from plan.tasks[].fulfills>",
  round:                1,
  prior_failure_context: null
}

CHARTER_TEMPLATE is consumed by dispatch references (direct/agent/team) and by the worker charter recipe (T7). The contracts_directive field fulfills R-F2.3: if contracts.md exists, its path is embedded in every charter together with a "read before coding" instruction; its body is never inlined (INV-2).


Orchestrator Boundaries (INV-3, R-N15.2)

The orchestrator is a router over structure. It must NOT read the body of any spec prose. Enforced everywhere in this skill and all dispatch/verify references.

MAY read (structural, via hoyeon-cli plan get or Read on plan.json only):

  • plan.json fields: tasks, journeys, verify_plan, meta, contracts.artifact, context
  • Session state in $HOME/.hoyeon/$CLAUDE_SESSION_ID/state.json
  • Worker output JSON returned by dispatch (WorkerOutput payload)
  • audit.md, learnings.json, issues.json for round-to-round context

MUST NOT read:

  • requirements.md body (GWT, behavior prose, decisions, context text)
  • contracts.md body (invariants, interfaces, data shapes — only the path flows through charters)

That body-read responsibility belongs to workers via the self-read pattern in references/worker-charter.md (§1.3, §2 Self-Read). If the orchestrator ever needs to influence behavior based on a requirement's body, route through a worker or through the contracts-patch recipe — never inline-read.


Resume Behavior (R-F8.2 idempotent restart)

On any re-entry (compaction recovery, session restart, /execute re-invocation on an existing spec_dir), the orchestrator MUST treat plan.json as the source of truth and skip any task whose status == "done". This rule applies uniformly across all three dispatch modes.

# Runs at the top of every dispatch recipe, before any worker is spawned.
plan       = Read("{plan_path}") → JSON.parse
done_ids   = { t.id for t in plan.tasks if t.status == "done" }   # INV-9: monotonic
pending    = [ t for t in plan.tasks if t.status != "done" ]

# Downstream readiness uses done_ids to satisfy depends_on.
ready = [ t for t in pending if all(d in done_ids for d in t.depends_on) ]
ModeWhere the skip happens
direct.mdPhase 1.2 (A) — current.status == "done" → CONTINUE (per-task loop)
agent.mdPhase A compute_ready_set()t.status == "done" → continue (INV-9)
team.mdPhase 1 ready-set filter + Phase 2 claim loop skip already-done

Additional guarantees:

  • Verify (references/verify.md) builds its coverage matrix from done_tasks only, so a partial run resumes verification on exactly the tasks that completed.
  • hoyeon-cli plan task --status X=done is idempotent (INV-5, INV-9); re-issuing it on a task that is already done is a no-op, never a re-transition.
  • The orchestrator NEVER rewrites plan.json directly — resume reads are through hoyeon-cli plan get (INV-5).

Concurrency Rules (INV-4 — no sleep, no polling)

Every parallel burst MUST be emitted as a single message with all background dispatches at once. Results arrive via notifications (TaskOutput, SendMessage, run_in_background:true completion events), never via a sleep / re-read poll loop.

Hard bans — enforced across SKILL.md and every dispatch / verify reference:

  • No sleep <n> between dispatches.
  • No while not done: ... sleep over plan.json or worker state.
  • No hoyeon-cli plan get called in a loop to poll for status == "done".
  • No serial Bash calls in separate messages where a single-message parallel burst would work (e.g. per-round worker fan-out, gate-1 toolchain fan-out).

Already-enforced sites (for reference):

  • direct.md — sequential by design, no polling (one task per loop iteration).
  • agent.md — Phase C notification handler, explicitly await_round_notifications(round_id) with the comment "NO SLEEP" (R-N16.1 fulfilled).
  • team.md — Phase 2 lead loop uses wait_for_SendMessage() events; standing-by workers wait on inbound SendMessage rather than polling plan.json (INV-4).
  • verify.md — INV-4 listed in invariants block; gate-1/gate-2 fan-out runs as a single-message burst.

If you feel tempted to add sleep, you are wrong. Use background dispatch + notification handler instead.


Dispatch Routing

The orchestrator picks one of three recipes based on dispatch from Phase 0.4. All three consume the same Phase 0 state and delegate worker construction to the canonical charter in references/worker-charter.mdno recipe inlines its own charter format.

IF dispatch == "direct":
  Read: ${baseDir}/references/direct.md
  Follow ALL instructions. (sequential — one task at a time in orchestrator context)

ELIF dispatch == "agent":
  Read: ${baseDir}/references/agent.md
  Follow ALL instructions. (round-based parallel — TaskCreate per ready-set group)

ELIF dispatch == "team":
  Read: ${baseDir}/references/team.md
  Follow ALL instructions. (persistent TeamCreate workers claim tasks)

Canonical charter — every dispatch recipe builds worker charters by importing references/worker-charter.md. The charter carries paths and IDs only (INV-2, R-N15.1): task_id, plan_path, contracts_path, sub_req_ids, round, prior_failure_context. No GWT, no requirements prose, no contracts body.

All dispatch references receive these variables from Phase 0:

  • plan_path{spec_dir}/plan.json (workers self-read it, orchestrator structural-reads it)
  • spec_dir, CONTEXT_DIR — directory paths
  • contracts_path — path to contracts.md, or null
  • work"Worktree" | "Branch + Commit" | "No Commit"
  • verify"Light" | "Standard" | "Thorough" (depth cap for verify.md)
  • CHARTER_TEMPLATE — from Phase 0.5, passed through to worker-charter.md

Resume behavior (R-F8.2) is mandatory across all three — see "Resume Behavior" above for the uniform done-skip contract.


Verify Routing

After all plan tasks reach done / failed / blocked, run verification. There is a single verify recipe; verify depth is a parameter that caps gates per sub_req, not a selector between different recipes (T8 design).

Read: ${baseDir}/references/verify.md
Follow ALL instructions; pass `verify` ∈ {"light","standard","thorough"} as the
depth parameter. verify.md reads done tasks from plan.json (structural only) and
evaluates each sub_req / journey against its capped gate set.

Contracts mismatch hook (C4, R-F9.1)

On any worker output that signals a cross-module contract mismatch — during dispatch OR during verify fix loops — the orchestrator invokes the auto-patch recipe before marking the task done or enqueueing a retry:

Read: ${baseDir}/references/contracts-patch.md
Follow ALL instructions. (detect → patch → audit-log → return control)

This hook runs without user confirmation (INV-7), is idempotent per worker output, and routes only through Read / Edit / Write on contracts.md and audit.md — never through hoyeon-cli (INV-5). See references/contracts-patch.md for detection signals (explicit contract_mismatch, contract_issues[], or BLOCKED-with-contract-reason).


Output Artifacts (R-F13.2, R-F13.3, R-F13.4)

execute produces exactly 5 file artifacts during a run, all inside <spec_dir>/. There is no report.md — the final report is stdout-only (INV-8 / R-F13.4 / C5).

ArtifactOwnerToolLifecycle
plan.jsonorchestratorhoyeon-cliStatus mutated via plan task --status (INV-5, INV-9; never direct edit)
contracts.mdorchestratorEdit / WriteInline patched by contracts-patch recipe (no user confirm; INV-7)
audit.mdorchestratorRead + EditAppend-only timestamped event log (R-F13.2)
learnings.jsonworkersRead + WriteWorkers append on success per worker-charter.md §3.5 (R-F6.4, R-F13.3)
issues.jsonworkersRead + WriteWorkers append on BLOCKED / FAILED per worker-charter.md §3.5 (R-F6.4, R-F13.3)

audit.md (R-F13.2) — append-only timestamped event log

The orchestrator appends one entry per orchestrator-level event. Format: a markdown list item starting with an ISO-8601 timestamp. Entries are append-only — never edit or delete prior entries. audit.md is initialized as an empty file by Phase 0.5.

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
174
Forks
24
Last commit
May 2026
Advanced
Catalog kind
skill
Gateway key
execute-team-attention
Source
github.com/team-attention/hoyeon