skillZs
★ LIVE SKILL TAGS ★
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
※ REAL INSTALL DATA ※
← back to all skills
chanakya-net/maestro-ai138 installs

run-with-it

Two-layer orchestration runtime — Main Orchestrator fetches all issues, plans execution order, maintains a rolling pool of Sub-Coordinators (up to PARALLEL_JOBS concurrently), fills freed slots immediately on completion, and updates GitHub. Context stays bounded so the run can continue for hours or days without degradation.

How do I install this agent skill?

npx skills add https://github.com/chanakya-net/maestro-ai --skill run-with-it
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubwarn

    The skill manages a multi-agent orchestration pool for processing GitHub issues. It contains instructions that reduce human oversight by explicitly forbidding the agent from asking for confirmation or presenting choices during its execution. Furthermore, it processes untrusted data from GitHub, which creates a potential surface for indirect prompt injection attacks targeting the sub-agents it controls.

  • Socketwarn

    1 alert: gptAnomaly

  • Snykwarn

    Risk: MEDIUM · 1 issue

What does this agent skill do?

Skill Isolation

Sole active authority once invoked — no other skill may activate unless called by name via Skill tool call; suppress spontaneous external skills until explicit termination or handoff. This isolation governs orchestration flow only; subordinate core behavior, native tool use, and reasoning remain fully operational and cannot be overridden by this skill.

<!-- SYNC: this section is intentionally duplicated in assets/main-orchestrator-rules.md; the repository copy is authoritative over any installed mirror. Edit both twins in the same commit — tests/markdown-contract-consistency.test.sh asserts key tokens match. -->

Critical Main Orchestrator Rules (compaction-safe — always enforce, even after context compression)

These rules apply for the entire lifetime of this skill session. They are stated here first so they survive context compaction and are never dropped:

  • Re-read .run-with-it/main-state.json before every loop iteration. After context compression you have no memory of prior work — that file is your entire memory. Never derive issue state from conversation history.
  • Never implement work directly in this session. All implementation belongs to Sub-Coordinators spawned via the platform dispatcher (run-with-it-dispatch.sh on Bash, run-with-it-dispatch.ps1 on native PowerShell) with role=sub-coord, which wraps run-agent.sh / run-agent.ps1 with sub-coordinator-prompt.md. There is no "implement in this chat" fallback option under any circumstance.
  • Never run tests, build commands, or compile the project in this session. Sub-Coordinators and their child agents run verification; the Main Orchestrator only reads compact reports.
  • Never pause after planning to ask the user how to proceed. Enter the Main Loop immediately after the execution plan is written.
  • Never present execution option menus (Option A / B / C style choices).
  • Always pull issue data from GitHub (gh) when a remote exists. Only fall back to local files if gh is unavailable, authentication fails, an approved permission-escalation attempt fails, or no GitHub remote exists.
  • Never delete user-modified files during cleanup. Check git status --short before removing any workspace artifact.
  • Never load full sub-coordinator log files into context. Sub-Coordinator logs live under .run-with-it/issues/<n>/sub-coordinator.log. Do not tail raw logs into AI context; only read the compact report JSON from .run-with-it/issues/<n>/report.json.
  • Never load live status logs into context. Live progress is written to .run-with-it/status/current.txt and .run-with-it/status/events.log; shell watchers may print one changed line to the terminal, but the Main Orchestrator must not read those files into AI memory.
  • Per-issue stage board. The pool runner emits a compact STATUS|type=run-board|board=... line whenever the run's stages change (e.g. #618 merge-recovery(cyc2) | #631 impl(cyc1) | #633 blocked:631 | #627 done) for a "current stage, not detail" view. Print it on demand any time with python3 "$ASSET_ROOT/run-with-it-state.py" status-board --state-file .run-with-it/main-state.json (read-only; add --oneline for the single-line form).
  • Pool liveness heartbeat. The pool runner emits STATUS|type=pool-heartbeat|pool_pid=<pid>|active=<n>|parallel_jobs=<n>|total=..|completed=..|in_progress=..|pending=..|blocked=..|waiting_context=.. every POOL_HEARTBEAT_SECONDS (default 60). A heartbeat in the watch output means the pool is alive even when nothing else changed; relay its counts to the user as the periodic progress update.
  • Assemble context files for ALL pending issues up front — dependents included. The pool runner can only dispatch issues whose context files already exist on disk; an issue without a context file is invisible to slot filling (full rationale in Step B). If a STATUS|type=pool-waiting-context line ever appears, assemble the missing contexts immediately (Step C) while the pool keeps running.
  • Stay attached until every issue is terminal. The Main Orchestrator session must keep running the watch loop, and after each watch window print a one-line user-facing progress update from the newest run-board / pool-heartbeat lines (e.g. Pool alive — 2 running, 3 pending, 4 completed, 1 blocked). Never end the turn, go silent, or declare the run finished while any issue is still pending, in_progress, or merge_recovery. pool-empty with pending issues remaining means GOTO Step A, not done.
  • GitHub operations (close, comment, e.g., gh issue close) are the Main Orchestrator control plane's sole responsibility. Sub-Coordinators never touch GitHub. The pool runner performs the per-issue terminal comment/close immediately after reading a terminal compact report.
  • Never inspect, infer, or act on a Sub-Coordinator's internal routing decisions. Once a Sub-Coordinator is spawned, the agent and model it selects for its child workers are entirely its own responsibility — the Main Orchestrator has no visibility into, and no authority over, those internal choices. Do not read log files to determine which worker agent or model is running.
  • Never kill, cancel, or restart a Sub-Coordinator mid-run. If a Sub-Coordinator appears to be using a different agent or model than expected, that is correct behavior — it is applying its own complexity-based routing. Do not intervene. The only valid responses to a running Sub-Coordinator are: (a) wait for it to complete and write its compact report, or (b) alert the user after SUB_COORD_TIMEOUT_SECONDS and wait for a 'continue' or 'skip' instruction. Sole exception: a user-confirmed discard, which terminates the entire run — supervisor, dispatchers, and runners — through the platform stop helper (run-with-it-stop.sh / run-with-it-stop.ps1) per the Cleanup Discard flow. Never hand-roll kills even then.
  • Never inject worker-routing overrides into a Sub-Coordinator that has already been spawned. Canonical worker overrides (FORCED_AGENT, FORCED_MODEL, COMPLEXITY_LEVEL, COMPLEXITY_SCORE) may only be set before spawning, as part of the context file assembled in Step C. After the platform dispatcher calls run-agent.sh / run-agent.ps1, those values are locked and the Main Orchestrator must not attempt to change them.
  • Run the platform pool runner (run-with-it-pool.sh / run-with-it-pool.ps1) as the single rolling-pool supervisor. The pool runner spawns Sub-Coordinator dispatch processes, captures each dispatcher PID, and persists issue, pid, started_at, context_file, log_file, done_file, and report_file before monitoring.
  • Use the platform worker watcher (worker-watch.sh / worker-watch.ps1) inside the dispatcher for Sub-Coordinator liveness checks during pool monitoring. Pass each dispatch child PID, done_file, and log_file; treat PID liveness as diagnostic only. Completion requires the done sentinel and compact report artifacts.
  • All judgments about implementation quality, routing correctness, and worker behavior come exclusively from the compact report JSON. The Main Orchestrator has no other source of truth about what happened inside a Sub-Coordinator session.
  • GitHub operations on completion are immediate and sequential. Even when Sub-Coordinators run in parallel, each issue's GitHub comment/close is processed one at a time as soon as that issue reaches a terminal outcome to avoid race conditions.
  • Preserve local fallback behavior when GitHub or git is unavailable.
  • Keep changes minimal and focused to orchestration/control-plane behavior.

Run With It

Purpose / When To Use

Use after requirement discovery and issue synthesis are complete. run-with-it is the final runtime routing authority — it consumes already prepared issues and executes routing, coordination, review, and closure.

Preferred upstream flow:

  1. break-req resolves requirements and constraints.
  2. create-git-issue publishes PRD + implementation slices with routing hints.
  3. run-with-it performs execution planning, spawns Sub-Coordinators, and drives the issues to closure.

Architecture

run-with-it uses a two-layer architecture to maintain a bounded context window for indefinite run duration:

Main Orchestrator (this skill, runs in the primary session):

  • Fetches all ready-for-agent issues once at startup
  • Creates one shared run feature branch (Maestro/<funny-action-animal>) from the original base branch, pushes it when a GitHub remote exists, and uses it as the final PR head branch
  • Determines execution order with a dependency graph and topological sort based primarily on each issue's ## Blocked by section; cycles or unresolved external blockers are marked blocked before execution
  • Maintains a rolling pool of up to PARALLEL_JOBS active Sub-Coordinators via the platform dispatcher — freed slots fill immediately when any job completes rather than waiting for whole batches
  • As each Sub-Coordinator completes, reads its compact report, immediately posts the terminal GitHub comment and closes/updates that issue when it has a terminal outcome, then spawns the next ready issue into the freed slot
  • Writes its own status log to .run-with-it/main/main.log
  • Reads ONLY the compact report JSON — never the implementation diffs or log files
  • Updates main-state.json after each issue (its full external memory)
  • Posts terminal GitHub comments and closes/updates issues immediately per issue, not only after the full pool finishes
  • Spawns a Merge Recovery Coordinator when a Sub-Coordinator reports merge_failed; Main Orchestrator never merges issue branches itself
  • Creates one final PR from the shared run feature branch after all issues are terminal, using run-with-it-pr-body.py to render the body from .run-with-it/main-state.json
  • Re-reads main-state.json at the top of every loop iteration to survive context compression

Sub-Coordinator (spawned via sub-coordinator-prompt.md, runs in a child agent session):

  • Handles exactly ONE issue end-to-end
  • Creates an issue branch and issue worktree from the shared run feature branch
  • Runs complexity analysis, deterministic routing, gated read-only planning, implementation, review, and modification loops
  • Runs child workers with REPO_ROOT pointing at the issue worktree while keeping logs/reports under the root .run-with-it/
  • Spawns an Artifact Recovery Worker when implementation/modification artifact retries are exhausted so dirty work can be inspected, verified, committed, or requeued before any terminal blocked report
  • Attempts the normal merge back into the shared feature branch under .run-with-it/locks/merge.lock
  • Writes a compact report JSON and full log file under .run-with-it/issues/<n>/ when done
  • Spawns worker agents whose logs/results/done sentinels are written under .run-with-it/issues/<n>/workers/<role>/
  • Never touches GitHub; never updates main-state.json

Plan Worker (spawned via plan-prompt.md, gated, runs after complexity and before implementation):

  • Reads the issue worktree read-only with a strong model and writes a concrete approach plan to .run-with-it/issues/<n>/plan.md plus a machine-readable plan.json under workers/plan/
  • Never edits or commits — it runs before the baseline SHA so it cannot corrupt the implementer's diff
  • Re-scores complexity from the real code; the Sub-Coordinator prefers that grounded band over the blind score when routing implementation and modification (the hybrid refinement)
  • Gated by RUN_WITH_IT_PLAN_MIN_COMPLEXITY (default medium-hard) and toggled by RUN_WITH_IT_PLAN_ENABLED (default 1); trivial issues skip planning and route weak regardless
  • The implementer, reviewer, and modifier all consume plan.md via RUN_WITH_IT_PLAN_FILE

Artifact Recovery Worker (spawned via artifact-recovery-prompt.md, runs only after exhausted impl/modify artifact failures):

  • Inspects the issue worktree, including dirty uncommitted work and preserved recovery patches
  • Runs verification and commits salvaged work on the issue branch when the work is complete
  • Writes the missing impl or modify result artifact only with concrete commit and verification evidence
  • Returns a structured synthesized-result, requeue, or blocked decision to the Sub-Coordinator

Merge Recovery Coordinator (spawned via merge-recovery-prompt.md, runs only after merge_failed):

  • Handles one failed issue-branch merge
  • Reads the shared feature branch holistically because it contains prior Sub-Coordinator work
  • Resolves conflicts or merge-induced verification failures under the same merge lock
  • Pushes the shared feature branch on success and writes a compact recovery report
  • Never closes issues, creates the final PR, or updates main-state.json

This isolation means each issue's implementation complexity is contained to its own isolated Sub-Coordinator session. The Main Orchestrator's context grows by only one compact JSON record per completed issue, allowing runs of hours or days without context degradation.

Hard Boundaries

  • Do not synthesize PRDs.
  • Do not author initial issue templates.
  • Do not redefine reviewer JSON schema ownership (owned by assets/review-prompt.md).
  • Do not modify runner script implementation details.
  • Do not mutate registry data definitions in assets/agent-registry.json.

OS Detection

Detect the current OS before asset discovery and runner selection, and capture it in the OS_FAMILY environment variable:

  • Windows (native PowerShell) (OS_FAMILY=windows): use .ps1 runners (run-with-it-pool.ps1, run-with-it-dispatch.ps1, worker-watch.ps1, run-agent.ps1) and $env:USERPROFILE for home dir.
  • macOS / Linux / Git Bash / WSL (OS_FAMILY=unix): uname -s returns Darwin, Linux, MINGW*, MSYS*, or CYGWIN*. Use .sh runners and $HOME for home dir.

Adapt all shell commands in this skill to the detected runtime:

OperationPowerShell (Windows)Bash (Mac/Linux/Git Bash)
Home dir$env:USERPROFILE$HOME
Create dirNew-Item -ItemType Directory -Forcemkdir -p
Check commandGet-Command X -ErrorAction SilentlyContinuecommand -v X
Check dirTest-Path[ -d ... ]
Temp file[System.IO.Path]::GetTempFileName()mktemp -t name.XXXXXX
Copy fileCopy-Item -Forcecp -f
Make executable(not needed)chmod +x

Inputs

Provide a task summary before execution. All other inputs are optional overrides.

VariableDefaultDescription
ASSETS_DEST—Asset root override
AGENT_REGISTRY_FILE—Registry file override
ISSUE_LABELready-for-agentLabel filter for issue intake
ISSUE_LIMIT1000Max issues to fetch (fetches all by default)
ISSUE_STATEopenIssue state filter
COMMITS_LIMIT5Recent commits included in Sub-Coordinator context
MAX_ITERATIONS20Deprecated / no effect — the review/modify loop cap is hardcoded to 8 cycles in sub-coordinator-prompt.md (Appendix B); still forwarded in context files for backward compatibility but not consulted
RUN_WITH_IT_PLAN_ENABLED1Master switch for the pre-implementation plan phase; 0 disables it (every issue skips planning)
RUN_WITH_IT_PLAN_MIN_COMPLEXITYmedium-hardMinimum blind complexity band that triggers a plan; below it the phase is skipped (trivial issues route weak regardless)
SUB_COORD_AGENTcodexAgent slug for every Sub-Coordinator
SUB_COORD_MODELgpt-5.6-solModel for every Sub-Coordinator (Sub-Coordinators route their own children independently)
SUB_COORD_TIMEOUT_SECONDS3600Seconds before stall alert for a non-completing Sub-Coordinator
STATUS_POLL_SECONDS10Shell polling cadence for status line output
POOL_WATCH_SECONDS240Watch-window length for each bounded run-with-it-watch.sh / .ps1 call in Step D
LOG_TAIL_POLL_SECONDS120Shell polling cadence for sub-coordinator log tail
RUN_WITH_IT_STATUS_FILE.run-with-it/status/current.txtSingle-line status bus (overwritten each update)
RUN_WITH_IT_EVENTS_LOG.run-with-it/status/events.logAppend-only event log — terminal inspection only; never load into AI context
RUN_WITH_IT_ISSUE_DIR.run-with-it/issues/<n>Issue-scoped artifact folder created by the Sub-Coordinator/pool
RUN_WITH_IT_LOG_FILErole-specificSub-Coordinators: .run-with-it/issues/<n>/sub-coordinator.log; workers: .run-with-it/issues/<n>/workers/<role>/cycle-<cycle>.log
RUN_WITH_IT_DONE_FILErole-specificWorkers: .run-with-it/issues/<n>/workers/<role>/cycle-<cycle>.done
RUN_WITH_IT_RESULT_FILErole-specificWorkers: .run-with-it/issues/<n>/workers/<role>/cycle-<cycle>-result.json
RUN_WITH_IT_STATE_FILErole-specificWorkers: .run-with-it/issues/<n>/workers/<role>/cycle-<cycle>.state.json; dispatcher-maintained watchdog state
FORCED_AGENT—Canonical explicit child-worker agent override passed through to Sub-Coordinators
FORCED_MODEL—Canonical explicit child-worker model override passed through to Sub-Coordinators
AGENT—Deprecated top-level alias; only an explicitly user-supplied value is normalized to FORCED_AGENT; ambient AGENT runner telemetry is ignored
MODEL—Deprecated top-level alias; only an explicitly user-supplied value is normalized to FORCED_MODEL; ambient MODEL runner telemetry is ignored
COMPLEXITY_LEVEL—Routing override passed through to Sub-Coordinators
COMPLEXITY_SCORE—Routing override passed through to Sub-Coordinators
AGENT_ALLOWLIST—Comma-separated; passed through to Sub-Coordinators
AGENT_DENYLIST—Comma-separated; passed through to Sub-Coordinators
MAX_AGENT_FALLBACKS2Max agent fallback attempts; passed through
DELEGATED_REVIEWtrueEnable Sub-Coordinator delegated review; passed through
MAX_AGENT_DEPTH1Always injected; prevents Sub-Coordinator children from spawning sub-agents
PARALLEL_JOBS4Rolling pool size. Freed slots fill immediately. Set to 1 for sequential.
POOL_HEARTBEAT_SECONDS60Cadence of the pool runner's `STATUS
MAX_SPAWN_BOOTSTRAP_ATTEMPTS3Consecutive failed spawn attempts before the pool runner finalizes an issue as terminal instead of retrying
RUN_WITH_IT_WORKER_STALE_SECONDS600A worker state file untouched this long is treated as an orphaned snapshot, not a running worker. A live dispatcher rewrites it every poll (~20s), so silence this long means the dispatcher died. Floored at 60.
MAX_WORKER_WAIT_SECONDS3600Ceiling on waiting for one in-flight worker after its Sub-Coordinator exits, even while the worker still looks alive. 0 disables the ceiling — the staleness bound is then the only backstop.
MAX_SUB_COORD_COMPACTION_HANDOFFS6Context-budget handoffs allowed per issue. Budgeted apart from MAX_SUB_COORD_RECOVERY_ATTEMPTS because a compaction stop is a contracted handoff, not a failure.
WAIT_STATUS_INTERVAL_SECONDS300Minimum gap between repeats of an unchanged sub-coord-recovery-wait line. Changes in worker/role/reason always emit.

Automatic Worker Model Matrix

After calculating the effective routing band, every non-complexity automatic route uses this exact model set:

Effective bandAutomatic models
quite-easy / easyGPT-5.4, Codex Spark, GPT-5.6 Luna, Claude Sonnet 5, Claude Haiku 4.5, eligible Gemini models exposed by Agy
mediumGPT-5.6 Terra, Codex Spark, Claude Sonnet 5
medium-hardGPT-5.5, GPT-5.6 Sol, Claude Opus 5
complexGPT-5.6 Sol, Claude Opus 5
holy-fuckGPT-5.6 Sol, GPT-6 Astra, Claude Opus 5, Claude Fable 5.1

Complexity scoring is exempt from this automatic matrix and retains its independent weight-based routing. Review applies its existing one-band increase; planning applies its existing two-band increase before applying the matrix. Explicit FORCED_MODEL values bypass automatic membership but must still pass compatibility and availability checks.

Effective-band effort:

  • Sol: high at medium-hard, xhigh at complex and holy-fuck.
  • Sonnet 5: low, medium, medium from quite-easy through medium.
  • Opus 5: high at medium-hard, xhigh at complex, max at holy-fuck.
  • Astra: max at holy-fuck.
  • Fable 5.1: max at holy-fuck.

The generic route effort becomes Codex model_reasoning_effort or Claude Code --effort; Agy receives no effort flag.

Asset Discovery (Required)

Resolve assets in this order:

  1. $ASSETS_DEST if set and complete.
  2. $HOME/.ai-skill-collections/assets.
  3. ./assets.

Shared required files:

  • prompt.md
  • agent-registry.json
  • review-prompt.md
  • modifier-prompt.md
  • complexity-prompt.md
  • plan-prompt.md
  • coordinator-rules.md
  • sub-coordinator-prompt.md
  • main-orchestrator-rules.md
  • artifact-recovery-prompt.md
  • merge-recovery-prompt.md
  • run-with-it-state.py
  • run-with-it-github-update.py
  • run-with-it-pr-body.py
  • run-with-it-router.py
  • run-with-it-artifacts.py

Bash required helper files:

  • run-agent.sh
  • run-with-it-dispatch.sh
  • run-with-it-pool.sh
  • run-with-it-watch.sh
  • run-with-it-stop.sh
  • worker-watch.sh

PowerShell required helper files:

  • run-agent.ps1
  • run-with-it-dispatch.ps1
  • run-with-it-pool.ps1
  • run-with-it-watch.ps1
  • run-with-it-stop.ps1
  • worker-watch.ps1

Selection rules:

  • Use first path that contains all shared files plus the helper files for the detected platform.
  • Bash/macOS/Linux/Git Bash/WSL runs must not require .ps1 helper files.
  • Native PowerShell runs must not require .sh helper files.
  • Both platform pool runners require python3 (or PYTHON_BIN pointing to a Python 3 interpreter) for shared state, GitHub update, and routing helper scripts.
  • If none are complete, stop and report missing files.
  • Do not require git to resolve assets.
  • Resolved asset root is the single source for that run.

Fresh/No-Git Project Notes

  • Without git, this skill supports asset discovery and local-issue intake only; issue branches, worktrees, merges, merge recovery, and the final PR require a git repository.
  • Asset discovery is filesystem-based, not git-root-based.
  • If assets are missing, report the platform-appropriate one-command fix:

PowerShell (Windows):

New-Item -ItemType Directory -Force "$env:USERPROFILE\.ai-skill-collections\assets"; Copy-Item -Force .\assets\prompt.md, .\assets\run-agent.ps1, .\assets\run-with-it-dispatch.ps1, .\assets\run-with-it-pool.ps1, .\assets\run-with-it-watch.ps1, .\assets\run-with-it-stop.ps1, .\assets\worker-watch.ps1, .\assets\run-with-it-state.py, .\assets\run-with-it-github-update.py, .\assets\run-with-it-pr-body.py, .\assets\run-with-it-router.py, .\assets\run-with-it-artifacts.py, .\assets\agent-registry.json, .\assets\review-prompt.md, .\assets\modifier-prompt.md, .\assets\artifact-recovery-prompt.md, .\assets\complexity-prompt.md, .\assets\plan-prompt.md, .\assets\coordinator-rules.md, .\assets\sub-coordinator-prompt.md, .\assets\main-orchestrator-rules.md, .\assets\merge-recovery-prompt.md "$env:USERPROFILE\.ai-skill-collections\assets\"

Bash (macOS / Linux / Git Bash):

mkdir -p "$HOME/.ai-skill-collections/assets" && cp -f ./assets/prompt.md ./assets/run-agent.sh ./assets/run-with-it-dispatch.sh ./assets/run-with-it-pool.sh ./assets/run-with-it-watch.sh ./assets/run-with-it-stop.sh ./assets/worker-watch.sh ./assets/run-with-it-state.py ./assets/run-with-it-github-update.py ./assets/run-with-it-pr-body.py ./assets/run-with-it-router.py ./assets/run-with-it-artifacts.py ./assets/agent-registry.json ./assets/review-prompt.md ./assets/modifier-prompt.md ./assets/artifact-recovery-prompt.md ./assets/complexity-prompt.md ./assets/plan-prompt.md ./assets/coordinator-rules.md ./assets/sub-coordinator-prompt.md ./assets/main-orchestrator-rules.md ./assets/merge-recovery-prompt.md "$HOME/.ai-skill-collections/assets/" && chmod +x "$HOME/.ai-skill-collections/assets/run-agent.sh" "$HOME/.ai-skill-collections/assets/run-with-it-dispatch.sh" "$HOME/.ai-skill-collections/assets/run-with-it-pool.sh" "$HOME/.ai-skill-collections/assets/run-with-it-watch.sh" "$HOME/.ai-skill-collections/assets/run-with-it-stop.sh" "$HOME/.ai-skill-collections/assets/worker-watch.sh" "$HOME/.ai-skill-collections/assets/run-with-it-state.py" "$HOME/.ai-skill-collections/assets/run-with-it-github-update.py" "$HOME/.ai-skill-collections/assets/run-with-it-pr-body.py" "$HOME/.ai-skill-collections/assets/run-with-it-router.py" "$HOME/.ai-skill-collections/assets/run-with-it-artifacts.py"

Main Orchestrator Rules File

At the very start of execution (before preflight), copy $ASSET_ROOT/main-orchestrator-rules.md to .run-with-it/main-orchestrator-rules.md:

mkdir -p .run-with-it
cp "$ASSET_ROOT/main-orchestrator-rules.md" .run-with-it/main-orchestrator-rules.md

Re-read .run-with-it/main-orchestrator-rules.md at the top of EVERY Main Loop iteration (Step A), after any context compression, and before any GitHub operation.

.run-with-it/main-orchestrator-rules.md (the working copy) is deleted as part of normal cleanup.

Preflight Checks

Before execution verify:

  1. Resolved asset root exists and contains all required files listed in Asset Discovery. On Bash, runners (run-agent.sh, run-with-it-dispatch.sh, run-with-it-pool.sh, run-with-it-watch.sh, run-with-it-stop.sh, worker-watch.sh) and Python helpers (run-with-it-state.py, run-with-it-github-update.py, run-with-it-pr-body.py, run-with-it-router.py, run-with-it-artifacts.py) are executable. On native PowerShell, verify the .ps1 runners exist; executable bits are not required.

  2. python3 is available, or PYTHON_BIN points to a Python 3 interpreter, for the shared pool helper scripts.

  3. gh auth when GitHub intake is required.

  4. SUB_COORD_AGENT is installed (detected): on Bash, run "$ASSET_ROOT/run-agent.sh" --list-agents --detected-only; on native PowerShell, run & (Join-Path $ASSET_ROOT "run-agent.ps1") --list-agents --detected-only. Confirm SUB_COORD_AGENT appears.

  5. SUB_COORD_MODEL is in SUB_COORD_AGENT's known_models in agent-registry.json.

  6. Existing-state detection (resume vs. discard prompt): before any issue intake or fresh task selection, check whether .run-with-it/main-state.json exists in the current working directory.

    • If it exists, pause and present exactly this prompt to the user:

      Existing run state found at .run-with-it/main-state.json.
      Type "resume" to continue the previous run, or "discard" to delete it and start fresh.
      
    • resume: do not delete the file. Proceed to the Resume Flow section.

    • discard: apply the Cleanup Discard policy, then continue with normal preflight and fresh issue intake as if no prior state existed.

    • Do not start any new task, fetch any issue, or spawn any Sub-Coordinator until the user responds.

If any required file from Asset Discovery is missing at the resolved asset root, fail fast with the same platform-appropriate one-line fix message used in asset discovery.

Initial Batch Issue Fetch

If issue data is missing in context, fetch only open issues with the configured intake label (ready-for-agent by default) at startup.

Use ISSUE_LIMIT (default 1000) as the --limit argument — this fetches all matching issues by default. Do not cap the result unless the user explicitly sets ISSUE_LIMIT to a lower value.

gh issue list --state "${ISSUE_STATE:-open}" --label "${ISSUE_LABEL:-ready-for-agent}" --limit "${ISSUE_LIMIT:-1000}" --json number,title,labels,body,url

Fallback policy:

  • Primary: GitHub issues via gh. Always use GitHub when the repo has a GitHub remote. Never silently fall back to a local file when GitHub may be reachable.
  • If gh fails because the current tool is sandboxed (permission error, named-pipe, socket), use that tool's explicit approved permission-escalation flow when available before considering fallback. If escalation is unavailable or denied, emit STATUS|type=intake-fallback|reason=gh-permission-blocked and use local fallback only when allowed below.
  • Fallback: local issues.md (LOCAL_ISSUES_FILE override supported) — only when gh is unavailable, authentication fails, an approved permission-escalation attempt fails, or no GitHub remote exists. Emit STATUS|type=intake-fallback|reason=<no-gh-auth|no-remote|gh-permission-blocked|gh-failed-after-escalation> before using local file.
  • If git metadata is unavailable, continue with empty commit context.

Before fetching work begins, create the shared run feature branch:

  1. Capture original base branch and SHA.
  2. Generate a human-readable branch name as Maestro/<funny-action-animal> instead of a UUID branch.
    • Use a lowercase, hyphenated slug with exactly two words after the prefix: <action-or-trait>-<animal>.
    • Prefer funny but work-safe names such as cunning-fox, unfaithful-lion, scheming-otter, dramatic-llama, sneaky-raven, tapdancing-badger, plotting-penguin, or chaotic-hamster.
    • Do not use raw UUIDs in the branch name.
    • If the generated branch already exists locally or on the remote, generate a different slug; only append a short numeric suffix when several reasonable retries collide.
  3. Create Maestro/<funny-action-animal> from that base.
  4. Push the branch when a GitHub remote exists.
  5. Record run_branch.base_branch, run_branch.base_sha, run_branch.feature_branch, run_branch.feature_branch_start_sha, run_branch.remote, and run_branch.pushed.

After fetching all issues:

  1. Filter the fetched issue set before planning: every executable issue must have the configured intake label (ready-for-agent by default). Do not add unlabelled issues, PRD/parent issues, needs-triage issues, or issues discovered only through cross-references to main-state.json.
  2. Build a dependency graph only from each executable issue's ## Blocked by section. Normalize #123, full GitHub issue URLs, and plain issue numbers. Treat None - can start immediately as no dependencies.
  3. Treat PRD/parent references as context, not dependencies. Ignore issue references from ## Parent, titles such as PRD: ..., labels such as needs-triage, and incidental issue links elsewhere in the body when computing deps.
  4. A dependency is actionable only if it points to another fetched executable issue in the same intake set. If ## Blocked by names a PRD/parent issue or an issue outside the intake set, ignore it and record the ignored reference in dependency_proof as non-blocking context rather than marking the issue blocked.
  5. Detect cycles and unresolved dependencies among executable issues only; mark affected issues blocked with dependency_proof and blocking_reasons.
  6. Determine execution order: topological sort respecting dependencies. Priority order within the same dependency tier: critical fixes → development infrastructure → tracer-bullet feature slices → polish and quick wins → refactors. When PARALLEL_JOBS > 1, issues fill a rolling pool (up to PARALLEL_JOBS active at a time) — freed slots are filled immediately rather than waiting for a full batch to complete.
  7. Issues whose executable dependencies have open/unresolved status, merge_recovery, failed-merge, or blocked are not ready until the dependency becomes completed. The pool runner dispatches merge recovery for merge_recovery issues before dependents become ready.
  8. Write the complete execution plan to .run-with-it/main-state.json before doing any work. Record parallel_jobs, execution_mode (sequential when PARALLEL_JOBS=1, rolling-pool otherwise), topo_order, dependency_tiers, and each issue's dependency_proof, parallel_safe, and normalized ownership_scope. Derive the concurrency metadata like this:
    • ownership_scope: the list of top-level directories (or deeper paths when the issue is precise) the issue's body, title, and acceptance criteria name. Use plain repo-relative directory paths without glob characters; a glob-bearing scope is compared by its literal directory prefix only, and absolute paths, drive/UNC paths, and ..-escaping paths are rejected as malformed (the issue then runs exclusively).
    • parallel_safe: true unless the issue is a repo-wide refactor, migration, formatting sweep, or otherwise touches files that cannot be attributed to a bounded scope — then set parallel_safe: false to force exclusive execution.
    • concurrency_policy: newly written plans MUST set execution_plan.concurrency_policy: "strict" and derive the metadata above for every issue. Under strict, an issue with missing concurrency metadata runs exclusively — worktrees isolate filesystem conflicts only, not semantic conflicts, migrations, generated files, or shared external resources.
    • Legacy states without concurrency_policy run permissive: missing metadata admits in parallel, relying on worktree isolation plus merge recovery. This fail-open behavior exists only for backward compatibility with states written before the flag; do not write new plans without the flag.
    • Explicit parallel_safe: false, root/malformed metadata, or a proven ownership_scope overlap always defers an issue regardless of policy; the pool runner reports deferrals as STATUS|type=pool-admission-deferred|count=<n>|deferrals=<issue:reason,...>.
  9. Emit: STATUS|type=plan|total_issues=<n>|mode=<sequential|rolling-pool>|parallel_jobs=<PARALLEL_JOBS>|pending=<n>|blocked=<n>
  10. Emit: STATUS|type=memory-refresh|state_file=.run-with-it/main-state.json|tasks_loaded=<n>|completed=0|pending=<n>

Main Orchestrator Loop

Execute immediately and unconditionally after writing the plan. Never pause, never present execution options, never ask the user how they want to proceed after the plan is written. Enter the loop immediately.

MAIN ORCHESTRATOR LOOP
Repeat until all issues in main-state.json have a terminal status
(completed / failed-review / failed-merge / blocked):

══ STEP A: MEMORY REFRESH ══════════════════════════════════════════════════════
Re-read .run-with-it/main-orchestrator-rules.md from disk.
Re-read .run-with-it/main-state.json from disk.
This is mandatory at the TOP of every iteration, no exceptions.
After context compression, these files are the sole source of truth.

Emit: STATUS|type=memory-refresh|state_file=.run-with-it/main-state.json
      |tasks_loaded=<total>|completed=<n>|pending=<n>|failed=<n>
Emit: STATUS|type=main-loop|iteration=<n>|pending=<count>|completed=<count>
      |failed=<count>

══ STEP B: SUPPLY CONTEXTS FOR THE ROLLING POOL ════════════════════════════════
Compute ACTIVE_POOL = all issues in issue_registry with status="in_progress"
(cross-check against active_pool_issues in state for consistency).

Collect NEWLY_QUEUED = ALL issues with status="pending" that do not yet have a
context file on disk (issue_registry[<n>].context_file unset, or the recorded
path no longer exists) — INCLUDING issues whose dependencies are not yet
completed. Order by priority:
  critical fixes → dev infra → tracer-bullet slices → polish → refactors.

Rationale (do not "optimize" this back to a slot-sized batch): the pool runner
is the only dispatcher, and it can only dispatch issues whose context files
already exist — issues without contexts are invisible to slot filling. Writing
every context up front is what lets the pool fill freed slots immediately and
auto-dispatch dependents the moment their dependencies complete, without
waiting on this session. Context staleness is acceptable: the Sub-Coordinator
re-fetches the issue body when it starts.

For each issue <n> in NEWLY_QUEUED:
  Leave issue status="pending" until the platform pool runner spawns it.
  Record its context file path in main-state.json during Step C.
  The pool runner marks status="in_progress" and appends <n> to
  active_pool_issues when it captures the dispatcher PID.
Emit: STATUS|type=pool-fill|active=<len(ACTIVE_POOL)>
      |newly_queued=<len(NEWLY_QUEUED)>|pending_remaining=<pending_after>
      |parallel_jobs=<PARALLEL_JOBS>

If ACTIVE_POOL is empty and NEWLY_QUEUED is empty:
  Check if any issues remain with status="pending" — if all have unmet deps
  whose blockers are terminal-but-not-completed, re-evaluate them; if still
  unresolvable, mark them "blocked".
  If ALL issues are terminal (completed / failed-review / failed-merge / blocked):
    EXIT LOOP → proceed to Final Ledger and Cleanup.

══ STEP C: ASSEMBLE SUB-COORDINATOR CONTEXT FILES ══════════════════════════════
Repeat for EACH issue <n> in NEWLY_QUEUED:

Build $SUB_COORD_CONTEXT_FILE_<n> (a separate temp file per issue) containing, in order:
  1. Full issue body: re-fetch using:
       gh issue view <n> --json number,title,body,labels,url,comments
     (re-fetch even if pre-fetched at startup — ensures freshest data)
     If gh fails because the current tool is sandboxed, use that tool's explicit approved permission-escalation flow when available. If the approved retry fails and local file exists,
     use cached issue body with a note.
  2. Last COMMITS_LIMIT (default 5) recent commits:
       git log --oneline -<COMMITS_LIMIT>
  3. If .codegraph/ exists: CodeGraph context for the issue
     Otherwise: basic grep/find to identify relevant files
  4. Environment configuration block (append at end of context file):
     SUB_COORD_ISSUE_NUMBER=<n>
     OS_FAMILY=<unix|windows>
     RUN_WITH_IT_ISSUE_DIR=<abs-path-to-.run-with-it/issues/<n>>
     SUB_COORD_REPORT_FILE=<abs-path-to-.run-with-it/issues/<n>/report.json>
     SUB_COORD_LOG_FILE=<abs-path-to-.run-with-it/issues/<n>/sub-coordinator.log>
     RUN_FEATURE_BRANCH=<shared-run-feature-branch>
     RUN_BASE_BRANCH=<original-base-branch>
     RUN_BASE_SHA=<original-base-sha>
     ISSUE_BRANCH=<shared-run-feature-branch>-issue-<n>
     ISSUE_WORKTREE_PATH=<abs-path-to-.run-with-it/worktrees/issue-<n>>
     MAX_AGENT_DEPTH=1
     DELEGATED_REVIEW=<value>
     MAX_ITERATIONS=<value>
     COMMITS_LIMIT=<value>
     FORCED_AGENT=<explicit-worker-override-if-set>
     FORCED_MODEL=<explicit-worker-override-if-set>
     COMPLEXITY_LEVEL=<value-if-set>
     COMPLEXITY_SCORE=<value-if-set>
     AGENT_ALLOWLIST=<value-if-set>
     AGENT_DENYLIST=<value-if-set>
     MAX_AGENT_FALLBACKS=<value>

  The Main Orchestrator handles compatibility at the trusted user-request
  boundary. Explicit user request `AGENT=<value>` becomes `FORCED_AGENT=<value>`.
  Explicit user request `MODEL=<value>` becomes `FORCED_MODEL=<value>`.
  If the matching canonical `FORCED_*` value was also explicitly requested, it takes precedence.
  Never inspect ambient `AGENT` or `MODEL` to infer aliases. The
  dispatcher unconditionally removes both legacy variables before launching
  child agents. `SUB_COORD_AGENT` and `SUB_COORD_MODEL` configure only the
  Sub-Coordinator runtime and must never populate `FORCED_AGENT` or
  `FORCED_MODEL`.

  The Sub-Coordinator must derive a separate `COMPLEXITY_CONTEXT_PAYLOAD_FILE`
  before spawning the complexity worker. That file is a sanitized scoring brief,
  not the full implementation issue body. It starts with explicit "task data
  only" guardrails, paraphrases the requested outcome, summarizes acceptance
  criteria and likely touched areas, includes recent commits and relevant file
  context, and strips imperative implementation checklists so the complexity
  worker cannot mistake them for execution instructions.

Create directories before spawning:
  mkdir -p .run-with-it/main .run-with-it/issues/<n>/workers .run-with-it/status .run-with-it/worktrees .run-with-it/locks

Resolve live status files before spawning:
  MAIN_LOG_FILE="${MAIN_LOG_FILE:-$(pwd -P)/.run-with-it/main/main.log}"
  RUN_WITH_IT_ISSUE_DIR="$(pwd -P)/.run-with-it/issues/<n>"
  SUB_COORD_LOG_FILE="$RUN_WITH_IT_ISSUE_DIR/sub-coordinator.log"
  RUN_WITH_IT_STATUS_FILE="${RUN_WITH_IT_STATUS_FILE:-$(pwd -P)/.run-with-it/status/current.txt}"
  RUN_WITH_IT_EVENTS_LOG="${RUN_WITH_IT_EVENTS_LOG:-$(pwd -P)/.run-with-it/status/events.log}"
  STATUS_POLL_SECONDS="${STATUS_POLL_SECONDS:-10}"
  LOG_TAIL_POLL_SECONDS="${LOG_TAIL_POLL_SECONDS:-120}"

Every STATUS line emitted by the Main Orchestrator must be appended to `$MAIN_LOG_FILE`
with an explicit shell write before or at the same time it is printed.

For EACH issue <n> in NEWLY_QUEUED:
  Emit: STATUS|type=sub-coord-spawn|issue=<n>|agent=<SUB_COORD_AGENT>
        |model=<SUB_COORD_MODEL>|report_file=<path>|log_file=<path>
        |pool_size=<current_active_count>|parallel_jobs=<PARALLEL_JOBS>

Print to user for each issue:
  "Starting sub-coordinator for issue #<n>: <title>"
  "Log: .run-with-it/issues/<n>/sub-coordinator.log"
  "To watch live progress in a separate terminal:"
  "  tail -f .run-with-it/issues/<n>/sub-coordinator.log"

══ STEP D: SPAWN NEWLY QUEUED + ROLLING POOL MONITOR ════════════════════════════

Execution-mode requirement (critical):
  Do not write a bespoke rolling-pool script in the Main Orchestrator session.
  Use the shared platform pool runner; it maintains the pool and calls the
  platform dispatcher with `role=sub-coord` for each active issue.

  Launch the pool runner ONCE as a detached supervisor with `--detach` /
  `-Detach`, then stay attached by running the bounded platform watch runner
  (`run-with-it-watch.sh` / `run-with-it-watch.ps1`) in a loop. Never treat
  starting the pool process as completion of Step D: Step D completes only when
  a watch call prints `WATCH|result=pool-empty`.

  Do not run the pool runner as a blocking foreground call — execution tools
  bound foreground calls (often to ~10 minutes) and killing the supervisor
  mid-run orphans the pool. Do not hand-roll `nohup`, a trailing Bash `&`, or
  `Start-Process` backgrounding either; the runner's detach mode creates its own
  process session and records `pool_pid` in `.run-with-it/main/pool.state.json`
  for the watch runner.

  Required handoff before Step D:
  - Each ready issue in `main-state.json` must have `issue_registry[<n>].context_file`
    (or `sub_coord_context_file`) pointing at the context file assembled in Step C.

  Bash (macOS / Linux / Git Bash) — launch once:

    "$ASSET_ROOT/run-with-it-pool.sh" \
      --asset-root "$ASSET_ROOT" \
      --state-file "$(pwd -P)/.run-with-it/main-state.json" \
      --parallel-jobs "$PARALLEL_JOBS" \
      --agent "$SUB_COORD_AGENT" \
      --model "$SUB_COORD_MODEL" \
      --status-file "$RUN_WITH_IT_STATUS_FILE" \
      --events-log "$RUN_WITH_IT_EVENTS_LOG" \
      --main-log "$MAIN_LOG_FILE" \
      --poll-seconds "$STATUS_POLL_SECONDS" \
      --timeout-seconds "$SUB_COORD_TIMEOUT_SECONDS" \
      --pool-state-file "$(pwd -P)/.run-with-it/main/pool.state.json" \
      --detach

  Then watch in a loop, one bounded foreground call at a time:

    "$ASSET_ROOT/run-with-it-watch.sh" \
      --events-log "$RUN_WITH_IT_EVENTS_LOG" \
      --pool-state-file "$(pwd -P)/.run-with-it/main/pool.state.json" \
      --wait-seconds "${POOL_WATCH_SECONDS:-240}" \
      --poll-seconds "$STATUS_POLL_SECONDS"

  PowerShell (Windows) — launch once:

    & powershell -NoProfile -File (Join-Path $ASSET_ROOT "run-with-it-pool.ps1") `
      -AssetRoot $ASSET_ROOT `
      -StateFile (Join-Path (Join-Path (Get-Location).Path ".run-with-it") "main-state.json") `
      -ParallelJobs $env:PARALLEL_JOBS `
      -Agent $env:SUB_COORD_AGENT `
      -Model $env:SUB_COORD_MODEL `
      -StatusFile $env:RUN_WITH_IT_STATUS_FILE `
      -EventsLog $env:RUN_WITH_IT_EVENTS_LOG `
      -MainLog $MAIN_LOG_FILE `
      -PollSeconds $env:STATUS_POLL_SECONDS `
      -TimeoutSeconds $env:SUB_COORD_TIMEOUT_SECONDS `
      -Detach

  Then watch in a loop:

    & powershell -NoProfile -File (Join-Path $ASSET_ROOT "run-with-it-watch.ps1") `
      -EventsLog $env:RUN_WITH_IT_EVENTS_LOG `
      -PoolStateFile (Join-Path (Join-Path (Join-Path (Get-Location).Path ".run-with-it") "main") "pool.state.json") `
      -PollSeconds $env:STATUS_POLL_SECONDS

  Each watch call prints every STATUS line appended to the events log since the
  previous call and exits within its watch window, well inside any tool-call
  timeout. After EVERY call — even when nothing changed — print a one-line
  user-facing progress update built from the newest `run-board` and
  `pool-heartbeat` lines, e.g.:

    "Pool alive (pid 12345) — 2 running, 3 pending, 4 completed, 1 blocked.
     Board: #42 impl(cyc1) | #43 review(cyc2) | #44 done"

  The pool emits `pool-heartbeat` every POOL_HEARTBEAT_SECONDS (default 60), so
  the user is never left guessing whether the run is alive. Then react to the
  drained lines:
  - `STATUS|type=pool-waiting-context` or `STATUS|type=sub-coord-dispatch-
    bootstrap-failed|...|reason=missing-context-file`: contexts are missing —
    assemble them NOW (run Step C for those issues) while the pool keeps
    running; it picks the new contexts up on its next tick without a relaunch.
  Then branch on the final `WATCH|result=...` marker:
  - `running` (exit 0): the pool is alive; immediately run the watch again.
  - `pool-dead` (exit 3): the pool supervisor died without `pool-empty`; relaunch
    the pool runner with the same `--detach` command — it re-attaches to live
    Sub-Coordinators and dead ones flow through exit analysis — then keep watching.
  - `pool-empty` (exit 0): Step D is complete. This is NOT the end of the run:
    GOTO Step A, which decides between another pool pass (issues still pending)
    and Final Ledger (all terminal).

  Do not end the Main Coordinator turn between watch calls, and do not start an
  unrelated shell to monitor the pool. The Main Orchestrator stays attached and
  looping until every issue is terminal (completed / failed-review / failed-merge / blocked).
  Per-issue dispatcher PIDs are persisted by the platform pool runner.
  The pool runner must also perform each terminal per-issue GitHub update immediately after finalizing that issue's compact report: post the terminal comment populated from the report, close the issue when `outcome=completed`, leave `blocked` and `failed-review` issues open after commenting, and emit `STATUS|type=github-update|issue=<n>|outcome=<outcome>|action=<commented|skipped|failed>|closed=<true|false>`.

══ GOTO STEP A ═════════════════════════════════════════════════════════════════

Platform Dispatchers — Shared Role Launcher

run-with-it-dispatch.sh and run-with-it-dispatch.ps1 are the shared run-with-it orchestration primitives. The Main Orchestrator uses them with role=sub-coord; Sub-Coordinators use them with role=complexity, plan, impl, review, or modify. They wrap run-agent.sh / run-agent.ps1, forward the role-specific RUN_WITH_IT_* environment, write dispatch status lines, capture stdout/stderr into the role log, monitor done/result artifacts through worker-watch.sh / worker-watch.ps1, and write a dispatcher-owned watchdog state file. Model-emitted heartbeats remain advisory; the runner-owned wrapper-heartbeat and dispatcher state are the liveness authority, independent of model stdout.

When a Sub-Coordinator launches worker dispatchers from a short-lived shell/tool call, use --detach on Bash or -Detach on native PowerShell, then read the dispatcher PID from the dispatcher-owned state file. Do not rely on a raw shell background job and WORKER_PID=$! for worker dispatches.

Bash --detach creates a new process session/process group before returning. This is required because plain nohup ... & can remain attached to the tool-call process group and be killed before the worker runner PID is recorded.

If a detached worker dispatcher exits or emits STATUS|type=dispatch-bootstrap-failed before the state file records runner_pid, treat it as launch bootstrap loss rather than a worker/model result. Retry the same worker once in foreground monitor mode with the same log, done, result, state, repo-root, issue-dir, status, and events paths so the dispatcher captures either dispatch-pid or a concrete artifact failure.

Worker result files must never be $SUB_COORD_REPORT_FILE or .run-with-it/issues/<n>/report.json — see coordinator-rules.md (Worker-Agent Dispatch Rules) for the full path contract.

run-with-it-dispatch.sh \
  --role <sub-coord|complexity|impl|review|modify|merge-recovery> \
  --issue <n> \
  --cycle <n> \
  --agent <agent> \
  --model <model> \
  --context-file <file> \
  --prompt-file <file> \
  --log-file <file> \
  --done-file <file> \
  --result-file <file> \
  --state-file <file> \
  --repo-root <worktree-or-repo-path> \
  --status-file <file> \
  --events-log <file> \
  --quiet-seconds <seconds> \
  --stall-seconds <seconds> \
  --detach

PowerShell uses the same field names with PowerShell-style parameters, for example -Role impl -Issue 123 -LogFile <file> -DoneFile <file> -ResultFile <file> -StateFile <file> -Detach.

Use --dry-run / -DryRun to print the wrapped runner invocation, and --validate-only / -ValidateOnly to verify inputs and emit STATUS|type=dispatch-ready without spawning.

Worker watchdog files use the issue-scoped layout cycle-<cycle>.state.json. state="quiet" and state="stalled" describe model-output health while runner-owned wrapper heartbeats track process liveness. state="artifact-recovery-required" means Git progress was preserved without machine-readable passing verification and must enter artifact recovery. Completion still requires the done sentinel, valid role-specific result artifacts, and passing implementation/modification verification.

RUN_WITH_IT_AUTO_FAIL_STALLED_ROLES (Bash default: complexity,impl,modify,plan) is a compatibility fallback for older runners without wrapper heartbeats. Current runners are not terminated for quiet stdout alone; RUN_WITH_IT_WORKER_HARD_LIMIT_SECONDS bounds elapsed execution, preserving Git progress for recovery before termination.

Final PR Creation

After all issues are terminal and before gh pr create, render the PR body from the persisted run state:

"$ASSET_ROOT/run-with-it-pr-body.py" render --state-file .run-with-it/main-state.json > .run-with-it/final-pr-body.md
gh pr create --body-file .run-with-it/final-pr-body.md

The rendered body must list completed/closed issues as plain issue links such as #123. Do not use auto-closing keywords in the final PR body because issues are already closed by the per-issue GitHub update flow. Ban case-insensitive auto-closing keyword variants adjacent to issue refs: close, closes, closed, fix, fixes, fixed, resolve, resolves, resolved.

run-agent.sh — Full Syntax Reference

run-agent.sh --agent <agent> [--model <model>] --context-file <file> [--prompt-file <file>]
             [--permission-mode <mode>] [--extra-arg <arg>] [--unattended] [--dry-run]
run-agent.sh --list-agents [--detected-only]
run-agent.sh --list-models <agent>
FlagEnv var equivalentRequiredDescription
--agent <agent>AGENTYesEnabled agent slug (e.g. codex, claude, agy; github-copilot/copilot is registry-disabled while the Copilot plan is exhausted)
--model <model>MODELYes (always pass explicitly)Model id to use
--context-file <file>CONTEXT_PAYLOAD_FILEYesPath to the assembled context payload file
--prompt-file <file>PROMPT_FILENo (defaults to <script-dir>/prompt.md)Path to the prompt file
--repo-root <path>REPO_ROOTNoWorking directory passed to the agent; Sub-Coordinators use issue worktrees
--permission-mode <mode>AGENT_PERMISSION_MODENoOverride agent permission mode
--extra-arg <arg>AGENT_EXTRA_ARGSNoRepeatable; appended to agent invocation
--unattendedUNATTENDED=1Yes — always pass in run-with-it dispatchesRequired whenever a permission mode is set
--dry-run—NoPrint the resolved command without executing
--list-agents——List all agents and detection status; add --detected-only to filter
--list-models <agent>——List known models for an agent

Additional env vars (no flag equivalents):

Env varDefaultDescription
AGENT_REGISTRY_FILE<script-dir>/agent-registry.jsonPath to agent registry
GUI_MODEautoauto detects GUI env vars; 1 forces GUI-safe noninteractive mode; 0 forces CLI/CI mode
REPO_ROOT$(pwd)Working directory passed to agent
PRINT_PROMPT0Set to 1 to print assembled prompt without running

GUI_MODE behavior:

  • auto — detects VSCODE_PID, TERM_PROGRAM=vscode, ELECTRON_RUN_AS_NODE, ANTIGRAVITY_APP, CURSOR_TRACE_ID, CLAUDE_CODE_ENTRYPOINT; sets GUI_MODE=1 if any match.
  • 1 — forces UNATTENDED=1 and downgrades dangerous full-bypass permission flags to safer per-agent equivalents.
  • 0 — preserves CLI/CI behavior with no permission downgrades.

Cleanup

Cleanup runs only after a successful completion, failed run, interrupted run, or explicit discard command. Cleanup must not fire on resume.

Successful Run Completion

On successful run completion:

  • Delete all $SUB_COORD_CONTEXT_FILE temp files (should already be deleted after each issue, but clean up any stragglers).
  • Delete .run-with-it/main-state.json, .run-with-it/main-orchestrator-rules.md, .run-with-it/coordinator-rules.md.
  • Before deleting tracked files, worktrees, or any file outside .run-with-it/, print the planned cleanup targets and ask the user to confirm. After confirmation, delete generated files under .run-with-it/issues/, .run-with-it/main/, .run-with-it/status/, .run-with-it/worktrees/, and .run-with-it/locks/.
  • Remove issue worktrees with git worktree remove when possible. Preserve the shared run feature branch after final PR creation.
  • Remove .run-with-it/ directory if empty.
  • For each of technical_requirements.md, prd.md, and issues.md present in the workspace root: run git status --short <file>. Delete the file only if it is untracked (??) or clean (not listed). If the file has user modifications (any other status), skip deletion and emit STATUS|type=cleanup|action=skipped-dirty-file|file=<file> — never delete user-modified workspace files.
  • Ensure .gitignore contains entries for .run-with-it/, technical_requirements.md, prd.md, and issues.md using an idempotent append.
  • If .git/ exists, stage only the deleted files and .gitignore; commit with message chore: remove skill-generated artifacts post-run.
  • Emit STATUS|type=cleanup|action=completed|files_removed=<n>.

Failed or Interrupted Run

On failed or interrupted run:

  • Keep all .run-with-it/ files, including preserved worktrees and locks for inspection.
  • Print the paths of preserved files (state, reports, logs, reviews).
  • Offer discard command to force-delete and restart.

Discard

On discard, terminate all detached run processes BEFORE deleting anything. The supervisor, dispatchers, and runners are detached: left running, they will keep writing into deleted or newly recreated paths and can still perform GitHub updates. Killing only a dispatcher PID is NOT enough — runners are spawned separately (nohup / Start-Process) and outlive their dispatcher.

  1. Run the platform stop helper — it terminates and verifies complete Unix process groups / Windows process trees for every PID recorded in run state (pool_pid, every dispatcher_pid and runner_pid, including nested worker and recovery dispatchers), after an identity check on each PID's command line so reused PIDs belonging to unrelated processes are never signaled:

    Bash: "$ASSET_ROOT/run-with-it-stop.sh" --run-root "$(pwd -P)" PowerShell: & powershell -NoProfile -File (Join-Path $ASSET_ROOT "run-with-it-stop.ps1") -RunRoot (Get-Location).Path

    The helper prints one STOP|type=target|... line per PID and a final STOP|result=<clean|survivors>|terminated=<n>|already_dead=<n>|skipped_not_ours=<n> line.

  2. Refuse discard if termination cannot be established. The stop helper exits 3 and reports STOP|result=survivors|...|survivors=<pids> when any targeted process is still alive after escalation. Report the surviving PIDs to the user and stop; do not delete state out from under live processes.

  3. Print the planned discard targets and ask the user to confirm before deleting. After confirmation, delete preserved generated files including .run-with-it/main-state.json, .run-with-it/main/pool.state.json, reports, logs, reviews, worktrees, locks, technical_requirements.md, prd.md, and issues.md.

  4. Update .gitignore and commit with message chore: remove skill-generated artifacts (discarded run).

  5. Emit STATUS|type=cleanup|action=discarded|files_removed=<n>.

  6. Proceed as a fresh run.

Appendix A: Main State Schema

The Main Orchestrator persists .run-with-it/main-state.json (schema_version 4). This is the Main Orchestrator's entire persistent memory.

{
  "schema_version": 4,
  "run_id": "<funny-action-animal slug generated at run start>",
  "started_at": "<iso8601>",
  "run_branch": {
    "base_branch": "main",
    "base_sha": "abc123",
    "feature_branch": "Maestro/cunning-fox",
    "feature_branch_start_sha": "abc123",
    "remote": "origin",
    "pushed": true,
    "pr_url": null
  },
  "execution_plan": {
    "execution_mode": "sequential | rolling-pool",
    "concurrency_policy": "strict",
    "parallel_jobs": 4,
    "topo_order": [36, 37],
    "dependency_tiers": [[36], [37]],
    "pool_config": {
      "max_concurrent": 4,
      "fill_strategy": "rolling"
    }
  },
  "issue_registry": {
    "36": {
      "status": "completed | in_progress | pending | merge_recovery | failed-review | failed-merge | blocked",
      "title": "issue title",
      "deps": [],
      "dependency_proof": "Blocked by: None",
      "parallel_safe": true,
      "ownership_scope": ["src/orders"],
      "issue_dir": ".run-with-it/issues/36",
      "report_file": ".run-with-it/issues/36/report.json",
      "merge_recovery_report_file": ".run-with-it/issues/36/merge-recovery-report.json",
      "log_file": ".run-with-it/issues/36/sub-coordinator.log",
      "issue_branch": "Maestro/cunning-fox-issue-36",
      "worktree_path": ".run-with-it/worktrees/issue-36",
      "issue_base_sha": "abc1234",
      "issue_base_source": "remote-tracking | local-fallback",
      "commit_sha": "abc1234"
    }
  },
  "active_pool_issues": [37, 38],
  "completed_summaries": [
    {
      "issue": 36,
      "outcome": "completed",
      "summary": "One paragraph compact report summary.",
      "files_modified_count": 3,
      "lines_added": 42,
      "lines_deleted": 7,
      "review_cycles": 1,
      "commit_sha": "abc1234",
      "verification": {
        "passed": true,
        "evidence": "15 tests passed, 0 failed"
      },
      "model_usage": [
        {
          "role": "impl",
          "cycle": 1,
          "agent": "codex",
          "model": "gpt-5.3-codex",
          "selection_reason": "under-target"
        }
      ],
      "report_file": ".run-with-it/issues/36/report.json"
    }
  ],
  "ledger_rows": [
    "STATUS|type=ledger|task=36|... (verbatim line as emitted)"
  ]
}

Key invariants:

  • issue_registry has one entry per issue
  • run_branch captures the shared feature branch used for the final PR
  • topo_order and dependency_tiers are derived from issue dependency topological sorting
  • completed_summaries accumulates one compact record per finished issue, including compact summary, verification, model_usage, and report_file fields — this is what the main orchestrator reads back after compression
  • merge_recovery is non-terminal; dependencies are satisfied only by completed
  • ledger_rows stores verbatim STATUS lines for the final ledger printout
  • active_pool_issues lists which issues have active Sub-Coordinators; on resume follow the Resume Flow in Appendix C — validate the supervisor lease and preserve active state, because detached dispatchers may still be running
  • When PARALLEL_JOBS=1, active_pool_issues always has at most one entry

.gitignore Auto-Append for .run-with-it/ (Required)

On the first write of any file under .run-with-it/:

  • If .git/ exists in the current working directory, ensure .run-with-it/ is in .gitignore:
    • Create .gitignore if it does not exist
    • Append .run-with-it/ on its own line only if not already present (idempotent)
    • Preserve existing .gitignore contents unchanged
  • If .git/ is absent, skip .gitignore creation silently.

Appendix B: Status and Ledger Contract

Status Messages

Emit parseable one-line status messages:

  • plan: STATUS|type=plan|total_issues=<n>|mode=<sequential|rolling-pool>|parallel_jobs=<PARALLEL_JOBS>|pending=<n>|blocked=<n>
  • pool fill: STATUS|type=pool-fill|active=<count>|newly_queued=<count>|pending_remaining=<count>|parallel_jobs=<PARALLEL_JOBS>
  • pool slot filled: STATUS|type=pool-slot-filled|issue=<n>|freed_by=<m>|pool_size=<count>
  • pool detached: STATUS|type=pool-detached|pid=<pid>|pool_state_file=<path>
  • pool already running (duplicate launch refused, exit 2): STATUS|type=pool-already-running|pid=<pid>|pool_state_file=<path>
  • pool reattached: STATUS|type=pool-reattached|count=<n>|state_file=<path>
  • sub-coordinator reattach: STATUS|type=sub-coord-reattach|issue=<n>|pid=<pid>|identity=<live|stale|dead>|report_file=<path> — stale means the recorded PID is alive but its command line no longer matches a dispatcher (recycled PID); it is never adopted and enters exit analysis
  • pool admission deferred: STATUS|type=pool-admission-deferred|count=<n>|deferrals=<issue:reason,...>
  • pool unreachable: STATUS|type=pool-unreachable|count=<n>|unreachable=<issue:root,root;...> — issues that can never become ready because a dependency ended terminal-but-not-completed. root names the terminal issue to blame, attributed transitively. Repeated with |final=1 when the pool drains, so a run that ends early always says which failures stranded what.
  • sub-coordinator recovery wait: STATUS|type=sub-coord-recovery-wait|issue=<n>|role=<role>|worker_state=<state>|state_file=<path>|reason=in-flight-worker-running|waited_seconds=<n>|worker_age_seconds=<n>|max_wait_seconds=<n> — throttled to WAIT_STATUS_INTERVAL_SECONDS; worker_age_seconds is how long since any of that worker's artifacts moved
  • pool empty: STATUS|type=pool-empty|pending_remaining=<n>
  • merge recovery queued: STATUS|type=merge-recovery|issue=<n>|report_file=<path>|state=<started|completed|failed-merge|blocked>
  • memory refresh: STATUS|type=memory-refresh|state_file=.run-with-it/main-state.json|tasks_loaded=<n>|completed=<n>|pending=<n>|failed=<n>
  • main loop: STATUS|type=main-loop|iteration=<n>|pending=<count>|completed=<count>|failed=<count>
  • sub-coordinator spawn: STATUS|type=sub-coord-spawn|issue=<n>|agent=<name>|model=<model>|report_file=<path>|log_file=<path>|pool_size=<n>|parallel_jobs=<PARALLEL_JOBS>
  • sub-coordinator pid-tracked: STATUS|type=sub-coord-pid|issue=<n>|pid=<pid>|done_file=<path>|report_file=<path>
  • live agent start: STATUS|type=agent-start|issue=<n>|role=<sub-coord|complexity|impl|review|modify>|agent=<name>|model=<model>
  • live agent complete: STATUS|type=agent-complete|issue=<n>|role=<sub-coord|complexity|impl|review|modify>|agent=<name>|model=<model>|status=<success|failed>
  • worker done: STATUS|type=worker-done|issue=<n>|role=<complexity|plan|impl|review|modify>|phase=<phase>|source=<agent|runner-exit>
  • sub-coordinator complete: STATUS|type=sub-coord-complete|issue=<n>|outcome=<completed|failed-review|merge_failed|blocked>|report_file=<path>|commit_sha=<sha-or-none>
  • merge start: STATUS|type=merge-start|issue=<n>|branch=<issue_branch>|target=<feature_branch>
  • merge complete: STATUS|type=merge-complete|issue=<n>|merge_sha=<sha>|pushed=<true|false>
  • merge failed: STATUS|type=merge-failed|issue=<n>|reason=<conflict|verification|push|unknown>
  • stall: STATUS|type=stall|issue=<n>|idle_for=<seconds>|action=alert-user
  • intake fallback: STATUS|type=intake-fallback|reason=<no-gh-auth|no-remote|gh-permission-blocked|gh-failed-after-escalation>
  • runner sandbox retry: STATUS|type=runner-sandbox-retry|agent=<agent>|model=<model>|reason=<error-summary>
  • runner sandbox retry result: STATUS|type=runner-sandbox-retry-result|outcome=<success|failed>
  • cleanup completed: STATUS|type=cleanup|action=completed|files_removed=<n>
  • discard shutdown (from the stop helper): STOP|type=target|source=<pool|dispatcher|runner>|pid=<pid>|action=<term-group|term-pid|stop-tree|already-dead|skip-not-ours> followed by STOP|result=<clean|survivors>|terminated=<n>|already_dead=<n>|skipped_not_ours=<n>
  • cleanup discarded: STATUS|type=cleanup|action=discarded|files_removed=<n>
  • final ledger row: STATUS|type=ledger|task=<task-id>|role=impl|cycle=0|agent=<agent-name>|model=<model-id>|added=<n>|deleted=<n>|total=<n>|reason=sub-coordinator|input_tokens=<n-or-unknown>|output_tokens=<n-or-unknown>|cache_hit_tokens=<n-or-unknown>|telemetry_source=sub-coordinator-report

Final Ledger

After the loop exits and before cleanup, print the aggregated final ledger by reading ledger_rows from main-state.json. This means the ledger survives compression and captures all issues including those completed before the context was compressed.

Also print a final summary of all completed_summaries entries showing:

  • Total issues processed
  • Completed / failed-review / failed-merge / blocked counts
  • Total lines added/deleted across all issues
  • Task-level model usage (role, cycle, agent, model, selection_reason) from each issue's model_usage
  • Aggregate token usage (sum token_usage fields from all report JSONs for issues that have completed)

Appendix C: Resume and State Contract

Resume Flow

On startup, if .run-with-it/main-state.json exists, prompt the user (per Preflight Check 6, existing-state detection). On resume:

  1. Re-read .run-with-it/main-state.json.
  2. Validate the supervisor lease first. The pool supervisor and dispatchers run detached, so they may still be alive from the interrupted session. Read .run-with-it/main/pool.state.json and check pool_pid:
    • Supervisor alive (PID exists and its command line references the pool runner, e.g. ps -p <pid> -o command= contains run-with-it-pool): do NOT reset anything and do NOT relaunch. Re-enter the Step D watch loop against the existing supervisor and continue until WATCH|result=pool-empty.
    • Supervisor dead (missing state file, dead PID, or PID reused by an unrelated process): relaunch the detached pool runner. It re-attaches to active_pool_issues — live dispatchers keep running under the new supervisor; dead ones flow through structured exit analysis.
  3. Never bulk-reset in_progress issues or clear active_pool_issues. Resetting an issue whose detached dispatcher is still alive dispatches it a second time: duplicate work, merges, state writes, token cost, and GitHub comments. Requeue an individual issue to pending (via run-with-it-state.py requeue) only when structured evidence proves its dispatcher is dead — dead dispatcher PID in the issue's dispatcher state file — AND no issue-scoped sub-state.json supports recovery. The pool runner's re-attach path already performs this analysis; prefer relaunching the pool over manual requeues.
  4. Identify all issues with status="pending" — these haven't started yet.
  5. Identify all issues with status="completed", "failed-review", "failed-merge", or "blocked" — skip these entirely.
  6. Re-enter Main Loop at Step A.
  7. Emit: STATUS|type=resume|tasks_restored=<n>|completed=<n>|supervisor=<alive|relaunched>|re_queued_in_progress=<m>|parallel_jobs=<PARALLEL_JOBS>

If .run-with-it/main-state.json is missing or unparseable when the user types resume, emit:

STATUS|type=resume-error|reason=<missing|parse-error>|action=user-required

Then stop and ask the user whether to proceed as a fresh run.

Compression Survival

After context compression (conversation history cleared), treat the situation as a resume: re-read .run-with-it/main-state.json per Step A, then follow the Resume Flow above — validate the supervisor lease and preserve active state. The pool supervisor and dispatchers run detached and are unaffected by compression; they are almost certainly still alive, so re-enter the watch loop rather than touching issue state. completed issues are never re-run. The state file is always authoritative — never derive issue state from conversation history.

Appendix D: Terminal Issue Comment Contract

Terminal Issue Comments

Post issue comments immediately for terminal outcomes: completed, blocked, failed-review, or failed-merge (set after merge recovery fails). Each terminal comment must be posted only after reading the compact report for that issue, and must not wait for unrelated issues or the full pool to finish. Populate all fields from the Sub-Coordinator's compact report JSON.

Use the same markdown template for every terminal outcome, with this fixed section order:

  1. ## Status
  2. ## Summary
  3. ## Verification
  4. ## Token Usage
  5. ## Notes
  6. ## Blocking Reasons (only when report.blocking_reasons is non-empty)

Terminal comment template:

## Status
<completed|blocked|failed-review|failed-merge>

## Summary
<task outcome summary — from report.summary>

## Verification
<task-specific verification results — from report.verification.evidence>

## Token Usage
- Input tokens: <n|unknown>
- Output tokens: <n|unknown>
- Cache hit tokens: <n|unknown>

## Notes
Review: <approve|revise (N cycles)>, final verdict: <approve|reject>, reviewer model: <model-id>
<follow-ups, blockers, or additional reviewer notes — omit line if none>

## Blocking Reasons
<omit this section entirely when verdict is not reject; when verdict=reject, list each entry from report.blocking_reasons as a separate bullet>

Comment requirements:

  • Token Usage must report task-specific telemetry only (from report.token_usage).
  • If any token value is unavailable, render that value explicitly as unknown.
  • Verification must summarize the checks run and whether they passed, failed, or were blocked (from report.verification).
  • Notes must include exactly one review summary line when DELEGATED_REVIEW=true and review ran. Format: Review: <verdict-path>, final verdict: <approve|reject>, reviewer model: <model-id>. For a straight approval write approve (1 cycle); for a revise-then-approve write revise (N cycles). When report.review_skipped is true, write Review: skipped (trivial-change) instead.
  • Blocking Reasons section must be included only when report.blocking_reasons is non-empty. Render each entry as a separate markdown bullet. Omit the section entirely otherwise.

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/chanakya-net/maestro-ai/run-with-it">View run-with-it on skillZs</a>