/ogre:execute
Use this skill after the plan is reviewed and approved.
Inputs
Accept:
- Issue number, e.g.
107
- Plan name, e.g.
issue-107
- Plan path, e.g.
.ai/.ogre/plans/issue-107.md
--job <job-id> instead of any of the above, e.g. /ogre:execute --job job-6d7715e4-...
Optional flags:
--executor codex|claude — omitted, this falls back to defaults.executor in
.ai/.ogre/config.json, then claude. Never add --executor/--model on your
own initiative "to be explicit" or "to be safe" when the user's own message
didn't name one - omit both and let config.json resolve it. A real caught
bug: a driving session hardcoded --rescuer claude --model claude-sonnet-5 (same
pattern applies to --executor) on a project whose config had a different
provider set as default, silently overriding it with no user request behind it.
If you don't know the project's configured default, check ogre config first or
simply omit the flag - don't guess. Every codex spawn runs fully unsandboxed (--dangerously-bypass-approvals-and-sandbox: no filesystem/shell/network confinement, no approval prompts), unconditional, not just [BROWSER-CHECK] steps. There is no opt-in flag for this anymore (--codex-unsandboxed-browser-check/codex_unsandboxed_browser_check are retired) — it's simply how codex always runs in Ogre now, because codex's own sandbox otherwise blocks things Ogre needs outright (real registry/network access, spawning a real browser). Ogre is a dev-only tool as a result. claude isolates fine by default (--permission-mode bypassPermissions) and needs no such tradeoff. If you see the WARNING: codex steps run UNSANDBOXED log line, that is expected on every codex step now, not a bug or a sign something was misconfigured — do not stop the chain over it.
--model MODEL
--reasoning LEVEL — reasoning effort for the executor (claude -p gets --effort LEVEL, codex exec gets -c model_reasoning_effort=LEVEL). Omit it to use the CLI's own default; Ogre never forces one.
--task <task-id> — target one specific seeded step out of order
--step <n> — target step N (1-based) out of order
--retry — re-run the lowest failed step in a fresh session. The failed attempt's exit code and log tail are injected into the runner prompt so the new session diagnoses the failure instead of repeating the same approach blindly. Prefer this over asking the user to explain what went wrong. Not combinable with --all.
--all — chain through every remaining step automatically. Each session hands off to a fresh one (cleanly, via task-complete --status passed, not as an error) at the --max-steps cap or once it estimates ~50%+ of its context used, whichever comes first — so simple steps can share one session while a heavier one splits off on its own. Works with --main/--background too. Browser-check steps run isolated in the chain when the executor has a browser MCP; only if none is detected does the chain stop on one — see "[BROWSER-CHECK] Steps" below, and handle it yourself rather than relaying the error.
--max-steps N — hard cap on checklist items per chained --all session (default: 3). Self-assessed context estimates are unreliable, so the cap is the authoritative limit.
--resume (-F) - accepted and recorded on the task (shown as Freshness: fresh|resume in the runner/ledger), but currently cosmetic - no codex exec resume/claude --resume gets triggered by it, nothing else branches on it either.
Pass it through when the user actually typed it; don't skip it just because it's a
no-op today.
--fresh (-f) - real, destructive-ish reset, not cosmetic like --resume.
Resets the WHOLE job back to step 1: every checklist item in the plan file gets
unchecked, every AUTO-FIX line synthesized during a prior [BROWSER-CHECK] retry
gets removed entirely, and every seeded ledger step-task is cleared back to
pending. Requires --yes together with it (ogre execute <issue> --fresh --yes) - --fresh alone refuses with an explanation, since this touches the whole
job's tracked progress, not just one step. Mutually exclusive with
--retry/--task/--step (those target one specific step; --fresh targets the
whole job) - passing both errors out.
Does NOT touch any file the earlier steps already created/edited - Ogre never
reverts code (same principle as ogre stop), and there's no per-step git snapshot
to revert to even if it wanted to. Only the tracking state resets; the codebase
keeps whatever step 1-N already did to it. Every runner prompt for a job that's
ever been --fresh-reset gets a permanent warning (fresh_restart_warning_block)
telling the executor to check whether an item's work already exists in the code
before redoing it from scratch - the same problem --task/--step targeting warns
about via backfill_warning_block, same fix.
If the user describes this as "restart/redo the chain from the beginning" without
naming the flag, this is what they mean - --fresh --yes, not --resume
(--resume does nothing).
--main — run inline in the current Claude Code session instead of spawning a new isolated codex/claude session. Opt-in only: Ogre never forces it, except as the automatic fallback for a [BROWSER-CHECK] step when no browser MCP is detected (and it says so). Use it deliberately only when the user explicitly wants the edit made in this conversation — it defeats the whole point of Ogre (keeping the main context clean) if used as a habit.
--mcp-config PATH — browser MCP config-file handed to the spawned claude session so [BROWSER-CHECK] steps run isolated. Also settable persistently as "browser_mcp" in .ai/.ogre/config.json. claude-only. Codex gets its browser MCP from its own ~/.codex/config.toml mcp_servers instead — codex [BROWSER-CHECK] also runs isolated when an external Playwright/Puppeteer MCP is in codex mcp list (Ogre's codex runner forces the external MCP over Codex's desktop in-app browser, which can't run headless — verified). No such MCP → --main fallback.
--background — same isolation as default (new session) but detached/non-blocking
--yes — required to proceed non-interactively (e.g. from this agent) when the target step/job was previously stopped, or when jumping to an out-of-order step whose earlier steps aren't passed yet. Only pass this after the user has explicitly confirmed.
--live — opt-in, off by default. Runs the executor with --json (codex) or --output-format stream-json --verbose (claude) instead of plain text, writing raw JSONL to the log path. Only use this when the user explicitly wants to watch the executor's activity live (commands it runs, files it touches) inside this same Claude Code conversation — it changes nothing about the edit itself, purely a visibility option. Passing --live alone does nothing beyond changing the log format; see /ogre:rescue's "Watching a --live rescue live" section for the Monitor+jq recipe that actually surfaces it as it happens (same recipe applies here, just against execute's own log path).
- Combined with
--all: every hand-off link normally rotates to a brand-new log file, which would leave a Monitor armed on link 1 stale the moment link 2 starts. --live --all together avoids that automatically — every link appends to the same log path for the life of the chain (announced as Live + --all: every hand-off link appends to this same log path... right after launch) instead of rotating. Arm Monitor on that one path once, right after launch — it keeps delivering events across every hand-off with no re-arming, no polling for a new path. This is the only combination where the log path is stable across a chain; --live without --all (single link, nothing to rotate) and --all without --live (per-link rotation, plain text) are unaffected. Once the whole chain's own completion signal fires (the backgrounded/polled execute --all call itself finishes or blocks), TaskStop that Monitor right away — same reasoning as rescue's: tail -f never exits on its own, so it otherwise sits open in the TUI until timeout or a manual (x).
- Format every delivered Monitor event's summary as
⎿ (Claude Code's own tree-connector glyph) followed by the summary text wrapped in a single backtick code span — e.g. ⎿ `Editing CheckoutController.php, adding validation.`, never as bold or plain prose. This is the same rule as /ogre:rescue's — restated here in full (not just "see rescue's section") so it isn't missed by a session that only reads this file.
Flags are forwarded verbatim, never reinterpreted. If the user's own message
names an actual CLI flag/short-form, pass that exact token through unchanged into the
ogre execute ... call — do not translate it into a different flag based on a guess
at what they meant, and do not silently substitute a similarly-spelled one you assume
is equivalent. --reasoning is -R (uppercase, consistent with every other
subcommand's reasoning flag) — --retry reclaimed the now-free -r (no -r/-R
collision anymore since they're unrelated single letters, not a case-only pair).
-f/-F (--fresh/--resume) and -m/-M (--model/--main) still differ only by case
with unrelated-or-opposite meanings, so a wrong guess on either is silent (no parse
error, just the wrong behavior) — this is exactly how -F got treated as --fresh
instead of --resume in practice. If you don't recognize a flag/short-form, check
this file's own flag list above (or scripts/ogre's actual parsing) before running
anything — never guess and substitute. Only translate into a flag yourself when the
user names no flag at all and describes pure intent in plain English (e.g. "resume
where it left off" → you choose --resume, having actually checked what it does
first).
Default
Default behavior is the isolated mode Ogre exists for:
- executor:
codex
- target: the lowest-numbered step still
pending (no --task/--step needed for normal sequential use)
- freshness:
fresh
- isolation: foreground, brand-new codex/claude session — this actually runs the executor now (no
--run needed anymore; that flag still works as a harmless no-op alias for this default). Main conversation context is untouched.
- Pass
--main to instead do the edit inline in this session (no subprocess), or --background to run the new session detached/non-blocking.
- Pass
--all to chain through every remaining step automatically instead of just the next one — combine with --main/--background as needed. Ogre keeps spawning fresh sessions for you as long as each one reports passed and steps remain; it stops the chain on the first failed or once nothing is left.
Job / Task Tracking
Every feature is a job (1:1 with the issue, id job-<uuid>, stored as job_id in .ai/.ogre/state/issue-<issue>.json). Every checklist step in the approved plan is seeded as a task the moment the plan is synced (id task-<uuid>, recorded in the shared ledger .ai/.ogre/state/tasks.json, step/step_index fields hold the checklist text and its 1-based position) — this happens automatically on status/task-list/execute, not only when execute runs. So ogre task-list <job-id> shows every step from planning onward, pending for ones never attempted, not just the ones someone has already run. Task status is one of: pending, running, passed, failed, stopped.
ogre execute no longer creates a fresh task per invocation (except --all, see below) — it finds the matching seeded task and updates it in place. --task <id>/--step <n> let you jump to any step out of order; without them it takes the lowest pending step_index. sync_state_from_plan also reconciles both directions every time it runs: if a checklist item shows [x] in the plan but its task isn't passed yet, the task is force-flipped to passed — the plan file is the source of truth for "done," so ledger and checklist can never drift apart for long. --all is the one exception: it still creates an ad-hoc, unlinked task covering every remaining step in one runner call, for cases where you deliberately want the old bulk behavior.
--run/--background auto-mark the task passed/failed when the subprocess exits. Every other path — a human running the printed codex exec command by hand, a /codex:rescue handoff, or (most common) the live Claude Code session executing the checklist item directly in this conversation — does NOT touch the ledger on its own. In all of those cases, the executing agent must run ${CLAUDE_PLUGIN_ROOT}/scripts/ogre task-complete <task-id> --status passed|failed as the last step (the exact command and task id are embedded in the generated runner file and in templates/execution-handoff.md's "After Editing" section). Skipping it leaves the task stuck pending forever even though the real work is done — do not skip it.
${CLAUDE_PLUGIN_ROOT}/scripts/ogre status --task <id> — show one task's full record (status, pid, exit_code, timestamps, log path).
${CLAUDE_PLUGIN_ROOT}/scripts/ogre status --tasks [issue] — list all tasks, optionally filtered to one issue.
${CLAUDE_PLUGIN_ROOT}/scripts/ogre status --job <job-id> — same as ogre status <issue>, addressed by job id instead of issue slug.
${CLAUDE_PLUGIN_ROOT}/scripts/ogre status <issue> — also lists tasks for that issue below the state json.
${CLAUDE_PLUGIN_ROOT}/scripts/ogre stop <issue> / ${CLAUDE_PLUGIN_ROOT}/scripts/ogre stop --job <job-id> — stops the whole job: kills any running task's pid and marks all pending/running tasks for that issue stopped.
${CLAUDE_PLUGIN_ROOT}/scripts/ogre stop --task <id> — stops just that one task (kills its pid if running). Sibling tasks and the job/issue state are untouched. Use this to kill one misbehaving background attempt without aborting the whole feature.
Use this when the user asks "what's still running", "did step N pass or fail", "show me task <id>", or "stop just that one background run".
Native LLM Session Resume
Every --run/--background task also records the underlying CLI's own session id in the task's session_id field, so the user can drop into that exact session in their own terminal afterward:
--executor claude: Ogre pre-generates a uuid and passes it as claude -p --session-id <uuid> ..., so it's known and printed immediately. Resume with claude --resume <session_id>.
--executor codex: Codex prints its own session id: <uuid> in its startup banner; Ogre parses it out of the task's log after the run (foreground) or when the background task is reaped. Resume with codex resume <session_id> (TUI) or codex exec resume <session_id> (CLI).
Always report session_id and the exact resume command back to the user after a task finishes (execute output shows it; ogre status --task <id> shows it too, once captured). For background codex tasks, it may be null until the process finishes — check status again after.
[BROWSER-CHECK] Steps
Whether a plan has any [BROWSER-CHECK] steps at all is decided at planning time, not execution time: ogre feature only tags steps this way when --browser-check was passed (see /ogre:feature). By default a plan has none, and the user is expected to verify the feature themselves — nothing below applies. Everything in this section only matters for a plan that opted in.
A step tagged [BROWSER-CHECK] needs a real rendered browser to verify (visual layout, interactive behavior). By default these now run ISOLATED like any other step — Ogre keeps main context clean whenever it can. What happens depends on whether the executor has a browser MCP:
- Browser MCP available —
claude executor: with a Playwright/browser MCP configured (ambient project/user MCP shown in claude mcp list, browser_mcp in .ai/.ogre/config.json, or --mcp-config PATH), the spawned claude -p session verifies the step with its own browser tools (verified: it inherits the ambient MCP and drives a real headless browser). Nothing special for you to do — single steps and --all chains run straight through, main context untouched. This is the goal state; prefer configuring a browser MCP so browser-check never touches this session.
codex executor: now the same shape as claude — since every codex spawn already runs fully unsandboxed (see the --executor note above), a confirmed playwright/puppeteer entry in codex mcp list is sufficient on its own. No opt-in flag needed or checked anymore. Without a browser MCP present, codex [BROWSER-CHECK] still falls back to --main, correctly, every single time — that is expected behavior, not flakiness.
- No browser MCP detected: Ogre falls back so the step still completes automatically (no manual retrigger):
- Single-step:
ogre execute auto-switches that one step to --main and prints a NOTE saying why. Just do the check as instructed in this session, then task-complete.
--all foreground (no --background): the chain stops at the browser-check with a message. This is a mechanical continuation, not a question for the user — resolve it in the same turn: run ${CLAUDE_PLUGIN_ROOT}/scripts/ogre execute <issue> --main, do that one step's real browser check yourself, ${CLAUDE_PLUGIN_ROOT}/scripts/ogre task-complete <task-id> --status passed|failed, then re-run ${CLAUDE_PLUGIN_ROOT}/scripts/ogre execute <issue> --all (same executor/model/reasoning) to resume. Loop until the chain reports completed/failed/nothing left.
--all --background: regardless of anything below, ogre execute --background never notifies this session on its own when the chain finishes — it self-detaches into its own process group, so nothing calls back here. The moment you launch it, start a poll loop yourself in this same session (one Bash tool call, run_in_background: true, wrapping while :; do ${CLAUDE_PLUGIN_ROOT}/scripts/ogre status <issue>; sleep 20; done breaking on completed/stopped/failed/blocked) — do this even when the plan has zero [BROWSER-CHECK] steps. "No browser-check steps" only means nothing below will make the poll loop stop early to intervene; it is not a reason to skip starting the loop in the first place. A prior version of this doc said "None tagged → just kick off --background and stop; nothing will pause" here, which a live session read as "no polling needed" and silently left a finished chain unreported for hours — don't repeat that.
Separately, decide at launch time whether this run is isolated-capable for [BROWSER-CHECK] — claude executor with a browser MCP actually configured (ambient claude mcp list, browser_mcp in config, or --mcp-config), or codex executor with a confirmed playwright/puppeteer entry in codex mcp list (check it yourself — codex is always unsandboxed now, so the MCP presence alone is the only signal, no flag to check). This only decides whether the poll loop ever needs to intervene mid-chain, not whether the loop exists at all.
- Isolated-capable: grep for
[BROWSER-CHECK] doesn't matter — the background driver handles every step, browser-check or not, the exact same way, fully inside itself. Do not treat current_step containing [BROWSER-CHECK] as a signal to intervene. That's the normal, expected state while the driver is actively (successfully) working the step in isolation — jumping in with a manual --main at that moment doesn't rescue anything, it races and duplicates work the background chain is already doing correctly. This is the actual cause of "worked before, now it doesn't" reports: the driver silently finishes the step fine while you're mid-poll, or you catch it mid-flight and stomp on it — pure timing luck, not the chain being broken. Poll exactly like a chain with no browser-check steps at all: wait for completed/stopped/failed, nothing else.
- Not isolated-capable (no MCP found): grep the plan's remaining unchecked items for
[BROWSER-CHECK]. None tagged → the poll loop above just waits for completed/stopped/failed/blocked, nothing else to do. At least one tagged → whenever current_step contains [BROWSER-CHECK] and the job isn't completed/stopped, resolve it like case 2 (--main, real check, task-complete, resume with --all --background preserving flags), then keep polling the same way.
- Either way: never spawn an
Agent (fork or otherwise) to supervise this — the background driver is already self-contained (drives every remaining step, writes to the ledger, exits on its own), and a supervising subagent adds no value while a fork specifically always runs on the Claude model regardless of which executor (codex/claude) the actual steps use, silently burning Claude quota for pure babysitting. Run one single Bash tool call with run_in_background: true around a real shell while+sleep loop (e.g. while :; do ${CLAUDE_PLUGIN_ROOT}/scripts/ogre status <issue>; sleep 20; done breaking on the condition that actually applies per the branch above). The harness delivers a completion notification straight to this same session the moment the loop exits — that's the entire mechanism, no subagent needed to relay it. Never poll across separate assistant turns, and never hand the polling off to a fork/subagent.
- Never report a step number/
current_step/count from memory — always quote the most recent ogre status output.
- Loop until
completed/stopped/failed for a real reason, then return one final summary from the last real status read. If --live was used and a Monitor is armed on the log path, TaskStop it right here, before that final summary — tail -f never exits on its own, so it stays open in the TUI until timeout or a manual (x) if you don't.
The cleanest fix for all of this is to give the executor a browser MCP once — then every case above collapses to "runs isolated, nothing to intervene on." The completion poll loop from case 3 above still runs regardless — that's for chain-finished notification, not browser-check specifically.
ogre status <issue> also self-heals a chain whose --background driver died outright (observed in the wild: no crash trace, process just gone, pending steps left with nothing running) — it detects a dead pid on the last mode=all chain task with steps still pending and auto-relaunches --all --background with the same executor/model/reasoning/mcp-config (whichever of those were set on the original invocation, read back off that task's own ledger record). This means the poll loop above (which already calls ogre status) recovers from that case for free; no separate dead-process detection needed.
This self-heal deliberately does NOT cover status: "blocked". A chain stops blocked (instead of just failing) when should_continue_chain finds a real, unresolved reason to stop — a genuine step failure, an exhausted [BROWSER-CHECK] [AUTO-FIX] cap, or a NEEDS INSPECTION-style guardrail refusing to guess at ambiguous/missing data — as opposed to the driver merely dying. Auto-respawning that would just re-run the same doomed step forever, which is the exact loop this status exists to prevent. When your poll loop's ogre status output shows Blocked: <reason> and a Resume once fixed: ogre execute --job <id> --all --background ... line, stop polling, read the reason, resolve it yourself or ask the user only if it's a genuine product-decision ambiguity (same bar as the Auto-Fix Cap section below), then re-invoke the printed resume command yourself — same flags, same --background/--live as the original run — and restart the poll loop. See CLAUDE.md's "Orchestrating ogre execute" section for the full protocol.
Do not spawn any subagent for any of cases 1-3 above — cases 1-2 already resolve synchronously within the same turn, and case 3's backgrounded poll loop already delivers its own completion notification straight to this session. A subagent would only inherit the whole conversation (or, for a fork, burn Claude quota) for zero added benefit.
Auto-Fix Cap Exceeded
When [BROWSER-CHECK] keeps failing and the ad-hoc [AUTO-FIX] attempts hit auto_fix_cap, ogre execute marks the task failed and exits non-zero with [BROWSER-CHECK] still failing after N ad-hoc [AUTO-FIX] attempts. This is not an automatic "stop and ask the user" case like line 98's generic rule — decide it yourself:
- Read the last verification failure (printed, and in the task's
notes) and the plan's [AUTO-FIX] entries to see what was actually tried.
- Judge scope: is the failure caused by (or squarely inside) what this plan's steps are building, or is it a pre-existing, site-wide condition unrelated to the feature (e.g. a global asset like
favicon.ico that 404s on every page, not just the ones this plan touches)?
- Pre-existing / out-of-scope: resolve it yourself, don't ask the user to pick between options:
- Prefer the smallest fix that actually clears the check. If that means creating a small, self-contained file the site/feature is genuinely missing (e.g. a real
favicon.ico at the site root so the browser's default request stops 404ing), create it — a minimal, real, working file, not a fake stub that only silences the checker.
- Revert any half-finished edits the failed
[AUTO-FIX] attempts left behind that are outside the plan's intended file scope (e.g. a stray <link> edit) if they didn't actually fix it.
- Mark the original step
passed via task-complete --status passed --notes "..." naming exactly what was created/changed to resolve it, that it's a minimal out-of-scope fix, and that the underlying condition predates this plan.
- Report to the user afterward what file(s) you created or reverted, that they're minimal/temporary in nature, and that the blast radius is low (e.g. "created a real
favicon.ico, one small binary file at the project root, doesn't touch any of the 12 pages' existing icon links"). Tell, don't ask.
- In-scope: the plan's own change caused it, or fixing it is what the step exists to verify. Still don't open a multi-option menu for the user to pick a fix. Diagnose it yourself from the failure log and the plan's intent, apply the smallest correct fix, and re-verify. Only actually stop and ask when the fix requires a real judgment call outside what the plan already specifies — a genuine product/business decision (which of two valid UX behaviors is wanted), or an irreversible/destructive action (deleting data, dropping a migration, overwriting something not created by this plan). If you can't safely determine the fix and it's neither of those, mark the step
failed with a note giving the concrete diagnosis and what you tried — report the failure plainly, that's not the same thing as pausing to ask which option to pick.
- This same distinction — decide and act vs. stop-and-ask only for irreversible/ambiguous calls — applies to any new error that surfaces while resolving one of these, not just the first one. Don't ratchet back to asking just because a second or third error showed up; keep diagnosing and fixing within the cap, and only escalate per the actual escalation criteria above.
- Whatever the path, never leave a stray out-of-scope edit (like a partial favicon link change or an orphaned asset file) sitting in the working tree just because the cap was hit — clean it up as part of resolving the step, in the same commit/session, not as a follow-up ask.
Behavior
- Run:
${CLAUDE_PLUGIN_ROOT}/scripts/ogre execute <issue-or-plan> [flags]
- If this exits non-zero because the next step is
[BROWSER-CHECK] (only possible with --all, see "Auto-Resolving [BROWSER-CHECK] Pauses" above): that's a mechanical continuation, not a confirmation case - handle it per that section, do not stop and ask the user.
- If this exits non-zero because the AUTO-FIX cap was exceeded (
[BROWSER-CHECK] still failing after N ad-hoc [AUTO-FIX] attempts): not a confirmation case either - handle it per "Auto-Fix Cap Exceeded" above, do not stop and ask the user.
- If it exits non-zero for any other reason, or prints
ERROR: Refusing to proceed non-interactively without confirmation...: STOP HERE. Do not read the runner file, do not edit any files, even if a runner file already exists from a prior attempt (it may be stale). Relay the exact warning to the user (e.g. "step/job was previously stopped, may depend on unfinished earlier steps") and ask whether to proceed. Only re-run with --yes after the user explicitly confirms.
- Without
--main, this call blocks and actually runs codex/claude in a new isolated session — don't do the edit yourself in parallel. Always run it via a Bash tool call with run_in_background: true instead of a plain synchronous call, even for a single step: this keeps the main conversation free while it runs and makes it visible in /tasks, rather than hard-blocking the turn on a plain wait. The harness delivers one completion notification straight to this session the moment the command exits — read the printed pass/fail from that output. This matters even more for --all (no ogre --background), where the chain runs every remaining step sequentially inside this one call and can run long enough to exceed the Bash tool's own synchronous timeout (~10 min) if left unwrapped. This is a different thing from ogre's own --background flag (see the [BROWSER-CHECK] --all --background case above): here ogre itself stays in its default blocking foreground mode, it's only the Bash-level call wrapping it that's backgrounded. If --live was used and a Monitor is armed on the log path, TaskStop it right here, before reporting — tail -f never exits on its own, so it stays open in the TUI until timeout or a manual (x) if you don't.
- Read the generated runner (mainly relevant when
--main was used, or to review what the isolated session was told to do):
.ai/.ogre/tmp/issue-<number>/run-next.md
- If
--main was NOT passed (default): the command above already invoked codex/claude in its own session and reported pass/fail — nothing further to execute yourself.
- If
--main was passed: execute only the target checklist item named in the runner (usually the next pending one, or whichever --task/--step picked) yourself, in this current Claude Code session, then run task-complete per the "After Execution" section below.
- Stop after that one checklist item unless
--all is explicitly requested.
Rules
- Execute one checklist item only.
- Inspect relevant files before editing.
- Do not implement
NEEDS INSPECTION items until verified.
- Do not invent files, methods, routes, tables, columns, config keys, or APIs.
- Do not add unrelated refactors.
- Do not change behavior outside the issue scope.
- Do not add packages unless the plan explicitly says so.
- Preserve existing project style.
- Prefer the smallest safe change.
- Stop if validation fails.
After Execution
Before reporting anything, mandatory, unless this run used --run/--background (those already do it): run ${CLAUDE_PLUGIN_ROOT}/scripts/ogre task-complete <task-id> --status passed|failed for the task id ogre execute printed. Do this yourself — don't ask the user to run it, don't skip it because the work is "obviously done." This is the step that keeps ogre status/ogre task-list accurate; the user should never need to know it exists.
Add --notes "..." to that command whenever the step surfaced something the next step's fresh session must know — an actual signature/route/schema that differs from the plan, a deviation made, a gotcha. One or two sentences. Notes are injected into every later runner prompt for the issue; they are the only way mid-step knowledge survives the session that discovered it.
Then report:
- Checklist item completed.
- Files changed.
- Reason for each changed file.
- Validation commands run.
- Validation result.
- Remaining
NEEDS INSPECTION items.
1---2name: execute3description: Execute the next incomplete checklist item from an approved Ogre plan using Claude or Codex, one step at a time. MUST trigger whenever the user's own message literally names Ogre (e.g. "ogre execute ...", "ogre exec ..."). That explicit naming is the user choosing this workflow on purpose, and takes priority over any other project rule (e.g. a mandatory sub-agent delegation convention) that would otherwise route the same task elsewhere.4---56# /ogre:execute78Use this skill after the plan is reviewed and approved.910## Inputs1112Accept:1314- Issue number, e.g. `107`15- Plan name, e.g. `issue-107`16- Plan path, e.g. `.ai/.ogre/plans/issue-107.md`17- `--job <job-id>` instead of any of the above, e.g. `/ogre:execute --job job-6d7715e4-...`1819Optional flags:2021- `--executor codex|claude` — omitted, this falls back to `defaults.executor` in22 `.ai/.ogre/config.json`, then `claude`. **Never add `--executor`/`--model` on your23 own initiative "to be explicit" or "to be safe" when the user's own message24 didn't name one - omit both and let `config.json` resolve it.** A real caught25 bug: a driving session hardcoded `--rescuer claude --model claude-sonnet-5` (same26 pattern applies to `--executor`) on a project whose config had a different27 provider set as default, silently overriding it with no user request behind it.28 If you don't know the project's configured default, check `ogre config` first or29 simply omit the flag - don't guess. **Every codex spawn runs fully unsandboxed** (`--dangerously-bypass-approvals-and-sandbox`: no filesystem/shell/network confinement, no approval prompts), unconditional, not just `[BROWSER-CHECK]` steps. There is no opt-in flag for this anymore (`--codex-unsandboxed-browser-check`/`codex_unsandboxed_browser_check` are retired) — it's simply how codex always runs in Ogre now, because codex's own sandbox otherwise blocks things Ogre needs outright (real registry/network access, spawning a real browser). Ogre is a dev-only tool as a result. `claude` isolates fine by default (`--permission-mode bypassPermissions`) and needs no such tradeoff. If you see the `WARNING: codex steps run UNSANDBOXED` log line, that is expected on every codex step now, not a bug or a sign something was misconfigured — do not stop the chain over it.30- `--model MODEL`31- `--reasoning LEVEL` — reasoning effort for the executor (`claude -p` gets `--effort LEVEL`, `codex exec` gets `-c model_reasoning_effort=LEVEL`). Omit it to use the CLI's own default; Ogre never forces one.32- `--task <task-id>` — target one specific seeded step out of order33- `--step <n>` — target step N (1-based) out of order34- `--retry` — re-run the lowest `failed` step in a fresh session. The failed attempt's exit code and log tail are injected into the runner prompt so the new session diagnoses the failure instead of repeating the same approach blindly. Prefer this over asking the user to explain what went wrong. Not combinable with `--all`.35- `--all` — chain through every remaining step automatically. Each session hands off to a fresh one (cleanly, via `task-complete --status passed`, not as an error) at the `--max-steps` cap or once it estimates ~50%+ of its context used, whichever comes first — so simple steps can share one session while a heavier one splits off on its own. Works with `--main`/`--background` too. Browser-check steps run isolated in the chain when the executor has a browser MCP; only if none is detected does the chain stop on one — see "`[BROWSER-CHECK]` Steps" below, and handle it yourself rather than relaying the error.36- `--max-steps N` — hard cap on checklist items per chained `--all` session (default: 3). Self-assessed context estimates are unreliable, so the cap is the authoritative limit.37- `--resume` (`-F`) - accepted and recorded on the task (shown as `Freshness:38 fresh|resume` in the runner/ledger), but **currently cosmetic** - no `codex exec39 resume`/`claude --resume` gets triggered by it, nothing else branches on it either.40 Pass it through when the user actually typed it; don't skip it just because it's a41 no-op today.42- `--fresh` (`-f`) - **real, destructive-ish reset**, not cosmetic like `--resume`.43 Resets the WHOLE job back to step 1: every checklist item in the plan file gets44 unchecked, every AUTO-FIX line synthesized during a prior `[BROWSER-CHECK]` retry45 gets removed entirely, and every seeded ledger step-task is cleared back to46 `pending`. **Requires `--yes` together with it** (`ogre execute <issue> --fresh47 --yes`) - `--fresh` alone refuses with an explanation, since this touches the whole48 job's tracked progress, not just one step. Mutually exclusive with49 `--retry`/`--task`/`--step` (those target one specific step; `--fresh` targets the50 whole job) - passing both errors out.51 **Does NOT touch any file the earlier steps already created/edited** - Ogre never52 reverts code (same principle as `ogre stop`), and there's no per-step git snapshot53 to revert to even if it wanted to. Only the tracking state resets; the codebase54 keeps whatever step 1-N already did to it. Every runner prompt for a job that's55 ever been `--fresh`-reset gets a permanent warning (`fresh_restart_warning_block`)56 telling the executor to check whether an item's work already exists in the code57 before redoing it from scratch - the same problem `--task`/`--step` targeting warns58 about via `backfill_warning_block`, same fix.59 If the user describes this as "restart/redo the chain from the beginning" without60 naming the flag, this is what they mean - `--fresh --yes`, not `--resume`61 (`--resume` does nothing).62- `--main` — run inline in the current Claude Code session instead of spawning a new isolated codex/claude session. Opt-in only: Ogre never forces it, except as the automatic fallback for a `[BROWSER-CHECK]` step when no browser MCP is detected (and it says so). Use it deliberately only when the user explicitly wants the edit made in this conversation — it defeats the whole point of Ogre (keeping the main context clean) if used as a habit.63- `--mcp-config PATH` — browser MCP config-file handed to the spawned `claude` session so `[BROWSER-CHECK]` steps run isolated. Also settable persistently as `"browser_mcp"` in `.ai/.ogre/config.json`. **`claude`-only.** Codex gets its browser MCP from its own `~/.codex/config.toml` `mcp_servers` instead — codex `[BROWSER-CHECK]` also runs isolated when an external Playwright/Puppeteer MCP is in `codex mcp list` (Ogre's codex runner forces the external MCP over Codex's desktop in-app browser, which can't run headless — verified). No such MCP → `--main` fallback.64- `--background` — same isolation as default (new session) but detached/non-blocking65- `--yes` — required to proceed non-interactively (e.g. from this agent) when the target step/job was previously `stopped`, or when jumping to an out-of-order step whose earlier steps aren't `passed` yet. Only pass this after the user has explicitly confirmed.66- `--live` — opt-in, off by default. Runs the executor with `--json` (codex) or `--output-format stream-json --verbose` (claude) instead of plain text, writing raw JSONL to the log path. Only use this when the user explicitly wants to watch the executor's activity live (commands it runs, files it touches) inside this same Claude Code conversation — it changes nothing about the edit itself, purely a visibility option. Passing `--live` alone does nothing beyond changing the log format; see `/ogre:rescue`'s "Watching a `--live` rescue live" section for the Monitor+jq recipe that actually surfaces it as it happens (same recipe applies here, just against `execute`'s own log path).67 - **Combined with `--all`**: every hand-off link normally rotates to a brand-new log file, which would leave a Monitor armed on link 1 stale the moment link 2 starts. `--live --all` together avoids that automatically — every link appends to the *same* log path for the life of the chain (announced as `Live + --all: every hand-off link appends to this same log path...` right after launch) instead of rotating. Arm Monitor on that one path once, right after launch — it keeps delivering events across every hand-off with no re-arming, no polling for a new path. This is the only combination where the log path is stable across a chain; `--live` without `--all` (single link, nothing to rotate) and `--all` without `--live` (per-link rotation, plain text) are unaffected. Once the whole chain's own completion signal fires (the backgrounded/polled `execute --all` call itself finishes or blocks), `TaskStop` that Monitor right away — same reasoning as rescue's: `tail -f` never exits on its own, so it otherwise sits open in the TUI until timeout or a manual `(x)`.68 - **Format every delivered Monitor event's summary as `⎿ ` (Claude Code's own tree-connector glyph) followed by the summary text wrapped in a single backtick code span** — e.g. `` ⎿ `Editing CheckoutController.php, adding validation.` ``, never as bold or plain prose. This is the same rule as `/ogre:rescue`'s — restated here in full (not just "see rescue's section") so it isn't missed by a session that only reads this file.6970**Flags are forwarded verbatim, never reinterpreted.** If the user's own message71names an actual CLI flag/short-form, pass that exact token through unchanged into the72`ogre execute ...` call — do not translate it into a different flag based on a guess73at what they meant, and do not silently substitute a similarly-spelled one you assume74is equivalent. `--reasoning` is `-R` (uppercase, consistent with every other75subcommand's reasoning flag) — `--retry` reclaimed the now-free `-r` (no `-r`/`-R`76collision anymore since they're unrelated single letters, not a case-only pair).77`-f`/`-F` (`--fresh`/`--resume`) and `-m`/`-M` (`--model`/`--main`) still differ only by case78with unrelated-or-opposite meanings, so a wrong guess on either is silent (no parse79error, just the wrong behavior) — this is exactly how `-F` got treated as `--fresh`80instead of `--resume` in practice. If you don't recognize a flag/short-form, check81this file's own flag list above (or `scripts/ogre`'s actual parsing) before running82anything — never guess and substitute. Only translate into a flag yourself when the83user names no flag at all and describes pure intent in plain English (e.g. "resume84where it left off" → you choose `--resume`, having actually checked what it does85first).8687## Default8889Default behavior is the isolated mode Ogre exists for:9091- executor: `codex`92- target: the lowest-numbered step still `pending` (no `--task`/`--step` needed for normal sequential use)93- freshness: `fresh`94- isolation: **foreground, brand-new codex/claude session** — this actually runs the executor now (no `--run` needed anymore; that flag still works as a harmless no-op alias for this default). Main conversation context is untouched.95- Pass `--main` to instead do the edit inline in this session (no subprocess), or `--background` to run the new session detached/non-blocking.96- Pass `--all` to chain through every remaining step automatically instead of just the next one — combine with `--main`/`--background` as needed. Ogre keeps spawning fresh sessions for you as long as each one reports `passed` and steps remain; it stops the chain on the first `failed` or once nothing is left.9798## Job / Task Tracking99100Every feature is a **job** (1:1 with the issue, id `job-<uuid>`, stored as `job_id` in `.ai/.ogre/state/issue-<issue>.json`). Every checklist step in the approved plan is seeded as a **task** the moment the plan is synced (id `task-<uuid>`, recorded in the shared ledger `.ai/.ogre/state/tasks.json`, `step`/`step_index` fields hold the checklist text and its 1-based position) — this happens automatically on `status`/`task-list`/`execute`, not only when `execute` runs. So `ogre task-list <job-id>` shows every step from planning onward, `pending` for ones never attempted, not just the ones someone has already run. Task status is one of: `pending`, `running`, `passed`, `failed`, `stopped`.101102`ogre execute` no longer creates a fresh task per invocation (except `--all`, see below) — it finds the matching seeded task and updates it in place. `--task <id>`/`--step <n>` let you jump to any step out of order; without them it takes the lowest pending `step_index`. `sync_state_from_plan` also reconciles both directions every time it runs: if a checklist item shows `[x]` in the plan but its task isn't `passed` yet, the task is force-flipped to `passed` — the plan file is the source of truth for "done," so ledger and checklist can never drift apart for long. `--all` is the one exception: it still creates an ad-hoc, unlinked task covering every remaining step in one runner call, for cases where you deliberately want the old bulk behavior.103104**`--run`/`--background` auto-mark the task `passed`/`failed` when the subprocess exits.** Every other path — a human running the printed `codex exec` command by hand, a `/codex:rescue` handoff, or (most common) the live Claude Code session executing the checklist item directly in this conversation — does NOT touch the ledger on its own. In all of those cases, the executing agent must run `${CLAUDE_PLUGIN_ROOT}/scripts/ogre task-complete <task-id> --status passed|failed` as the last step (the exact command and task id are embedded in the generated runner file and in `templates/execution-handoff.md`'s "After Editing" section). Skipping it leaves the task stuck `pending` forever even though the real work is done — do not skip it.105106- `${CLAUDE_PLUGIN_ROOT}/scripts/ogre status --task <id>` — show one task's full record (status, pid, exit_code, timestamps, log path).107- `${CLAUDE_PLUGIN_ROOT}/scripts/ogre status --tasks [issue]` — list all tasks, optionally filtered to one issue.108- `${CLAUDE_PLUGIN_ROOT}/scripts/ogre status --job <job-id>` — same as `ogre status <issue>`, addressed by job id instead of issue slug.109- `${CLAUDE_PLUGIN_ROOT}/scripts/ogre status <issue>` — also lists tasks for that issue below the state json.110- `${CLAUDE_PLUGIN_ROOT}/scripts/ogre stop <issue>` / `${CLAUDE_PLUGIN_ROOT}/scripts/ogre stop --job <job-id>` — stops the whole job: kills any `running` task's pid and marks all pending/running tasks for that issue `stopped`.111- `${CLAUDE_PLUGIN_ROOT}/scripts/ogre stop --task <id>` — stops just that one task (kills its pid if running). Sibling tasks and the job/issue state are untouched. Use this to kill one misbehaving background attempt without aborting the whole feature.112113Use this when the user asks "what's still running", "did step N pass or fail", "show me task \<id\>", or "stop just that one background run".114115## Native LLM Session Resume116117Every `--run`/`--background` task also records the underlying CLI's own session id in the task's `session_id` field, so the user can drop into that exact session in their own terminal afterward:118119- `--executor claude`: Ogre pre-generates a uuid and passes it as `claude -p --session-id <uuid> ...`, so it's known and printed immediately. Resume with `claude --resume <session_id>`.120- `--executor codex`: Codex prints its own `session id: <uuid>` in its startup banner; Ogre parses it out of the task's log after the run (foreground) or when the background task is reaped. Resume with `codex resume <session_id>` (TUI) or `codex exec resume <session_id>` (CLI).121122Always report `session_id` and the exact resume command back to the user after a task finishes (execute output shows it; `ogre status --task <id>` shows it too, once captured). For background codex tasks, it may be `null` until the process finishes — check status again after.123124## `[BROWSER-CHECK]` Steps125126Whether a plan has any `[BROWSER-CHECK]` steps at all is decided at planning time, not execution time: `ogre feature` only tags steps this way when `--browser-check` was passed (see `/ogre:feature`). By default a plan has none, and the user is expected to verify the feature themselves — nothing below applies. Everything in this section only matters for a plan that opted in.127128A step tagged `[BROWSER-CHECK]` needs a real rendered browser to verify (visual layout, interactive behavior). **By default these now run ISOLATED like any other step** — Ogre keeps main context clean whenever it can. What happens depends on whether the executor has a browser MCP:129130- **Browser MCP available** — `claude` executor: with a Playwright/browser MCP configured (ambient project/user MCP shown in `claude mcp list`, `browser_mcp` in `.ai/.ogre/config.json`, or `--mcp-config PATH`), the spawned `claude -p` session verifies the step with its own browser tools (verified: it inherits the ambient MCP and drives a real headless browser). Nothing special for you to do — single steps and `--all` chains run straight through, main context untouched. This is the goal state; prefer configuring a browser MCP so browser-check never touches this session.131 - `codex` executor: now the same shape as `claude` — since every codex spawn already runs fully unsandboxed (see the `--executor` note above), a confirmed playwright/puppeteer entry in `codex mcp list` is sufficient on its own. No opt-in flag needed or checked anymore. Without a browser MCP present, codex `[BROWSER-CHECK]` still falls back to `--main`, correctly, every single time — that is expected behavior, not flakiness.132- **No browser MCP detected**: Ogre falls back so the step still completes automatically (no manual retrigger):133 1. **Single-step**: `ogre execute` auto-switches that one step to `--main` and prints a NOTE saying why. Just do the check as instructed in this session, then `task-complete`.134 2. **`--all` foreground (no `--background`)**: the chain stops at the browser-check with a message. This is a mechanical continuation, not a question for the user — resolve it in the same turn: run `${CLAUDE_PLUGIN_ROOT}/scripts/ogre execute <issue> --main`, do that one step's real browser check yourself, `${CLAUDE_PLUGIN_ROOT}/scripts/ogre task-complete <task-id> --status passed|failed`, then re-run `${CLAUDE_PLUGIN_ROOT}/scripts/ogre execute <issue> --all` (same executor/model/reasoning) to resume. Loop until the chain reports `completed`/`failed`/nothing left.135 3. **`--all --background`**: **regardless of anything below, `ogre execute --background` never notifies this session on its own when the chain finishes** — it self-detaches into its own process group, so nothing calls back here. The moment you launch it, start a poll loop yourself in this same session (one Bash tool call, `run_in_background: true`, wrapping `while :; do ${CLAUDE_PLUGIN_ROOT}/scripts/ogre status <issue>; sleep 20; done` breaking on `completed`/`stopped`/`failed`/`blocked`) — do this even when the plan has zero `[BROWSER-CHECK]` steps. "No browser-check steps" only means nothing below will make the poll loop stop early to intervene; it is not a reason to skip starting the loop in the first place. A prior version of this doc said "None tagged → just kick off `--background` and stop; nothing will pause" here, which a live session read as "no polling needed" and silently left a finished chain unreported for hours — don't repeat that.136 Separately, decide at launch time whether this run is **isolated-capable** for `[BROWSER-CHECK]` — `claude` executor with a browser MCP actually configured (ambient `claude mcp list`, `browser_mcp` in config, or `--mcp-config`), or `codex` executor with a confirmed playwright/puppeteer entry in `codex mcp list` (check it yourself — codex is always unsandboxed now, so the MCP presence alone is the only signal, no flag to check). This only decides whether the poll loop ever needs to intervene mid-chain, not whether the loop exists at all.137 - **Isolated-capable**: grep for `[BROWSER-CHECK]` doesn't matter — the background driver handles every step, browser-check or not, the exact same way, fully inside itself. **Do not treat `current_step` containing `[BROWSER-CHECK]` as a signal to intervene.** That's the normal, expected state while the driver is actively (successfully) working the step in isolation — jumping in with a manual `--main` at that moment doesn't rescue anything, it races and duplicates work the background chain is already doing correctly. This is the actual cause of "worked before, now it doesn't" reports: the driver silently finishes the step fine while you're mid-poll, or you catch it mid-flight and stomp on it — pure timing luck, not the chain being broken. Poll exactly like a chain with no browser-check steps at all: wait for `completed`/`stopped`/`failed`, nothing else.138 - **Not isolated-capable** (no MCP found): grep the plan's remaining unchecked items for `[BROWSER-CHECK]`. None tagged → the poll loop above just waits for `completed`/`stopped`/`failed`/`blocked`, nothing else to do. At least one tagged → whenever `current_step` contains `[BROWSER-CHECK]` and the job isn't `completed`/`stopped`, resolve it like case 2 (`--main`, real check, `task-complete`, resume with `--all --background` preserving flags), then keep polling the same way.139 - Either way: **never spawn an `Agent` (fork or otherwise) to supervise this** — the background driver is already self-contained (drives every remaining step, writes to the ledger, exits on its own), and a supervising subagent adds no value while a `fork` specifically always runs on the Claude model regardless of which executor (`codex`/`claude`) the actual steps use, silently burning Claude quota for pure babysitting. Run **one single Bash tool call with `run_in_background: true`** around a real shell `while`+`sleep` loop (e.g. `while :; do ${CLAUDE_PLUGIN_ROOT}/scripts/ogre status <issue>; sleep 20; done` breaking on the condition that actually applies per the branch above). The harness delivers a completion notification straight to this same session the moment the loop exits — that's the entire mechanism, no subagent needed to relay it. Never poll across separate assistant turns, and never hand the polling off to a fork/subagent.140 - Never report a step number/`current_step`/count from memory — always quote the most recent `ogre status` output.141 - Loop until `completed`/`stopped`/`failed` for a real reason, then return one final summary from the last real status read. **If `--live` was used and a Monitor is armed on the log path, `TaskStop` it right here, before that final summary** — `tail -f` never exits on its own, so it stays open in the TUI until timeout or a manual `(x)` if you don't.142143The cleanest fix for all of this is to give the executor a browser MCP once — then every case above collapses to "runs isolated, nothing to intervene on." The completion poll loop from case 3 above still runs regardless — that's for chain-finished notification, not browser-check specifically.144145`ogre status <issue>` also self-heals a chain whose `--background` driver died outright (observed in the wild: no crash trace, process just gone, pending steps left with nothing running) — it detects a dead pid on the last `mode=all` chain task with steps still pending and auto-relaunches `--all --background` with the same executor/model/reasoning/mcp-config (whichever of those were set on the original invocation, read back off that task's own ledger record). This means the poll loop above (which already calls `ogre status`) recovers from that case for free; no separate dead-process detection needed.146147**This self-heal deliberately does NOT cover `status: "blocked"`.** A chain stops `blocked` (instead of just failing) when `should_continue_chain` finds a real, unresolved reason to stop — a genuine step failure, an exhausted `[BROWSER-CHECK]` `[AUTO-FIX]` cap, or a `NEEDS INSPECTION`-style guardrail refusing to guess at ambiguous/missing data — as opposed to the driver merely dying. Auto-respawning that would just re-run the same doomed step forever, which is the exact loop this status exists to prevent. When your poll loop's `ogre status` output shows `Blocked: <reason>` and a `Resume once fixed: ogre execute --job <id> --all --background ...` line, stop polling, read the reason, resolve it yourself or ask the user only if it's a genuine product-decision ambiguity (same bar as the Auto-Fix Cap section below), then re-invoke the printed resume command yourself — same flags, same `--background`/`--live` as the original run — and restart the poll loop. See CLAUDE.md's "Orchestrating `ogre execute`" section for the full protocol.148149 Do **not** spawn any subagent for any of cases 1-3 above — cases 1-2 already resolve synchronously within the same turn, and case 3's backgrounded poll loop already delivers its own completion notification straight to this session. A subagent would only inherit the whole conversation (or, for a fork, burn Claude quota) for zero added benefit.150151### Auto-Fix Cap Exceeded152153When `[BROWSER-CHECK]` keeps failing and the ad-hoc `[AUTO-FIX]` attempts hit `auto_fix_cap`, `ogre execute` marks the task `failed` and exits non-zero with `[BROWSER-CHECK] still failing after N ad-hoc [AUTO-FIX] attempts`. This is **not** an automatic "stop and ask the user" case like line 98's generic rule — decide it yourself:1541551. Read the last verification failure (printed, and in the task's `notes`) and the plan's `[AUTO-FIX]` entries to see what was actually tried.1562. Judge scope: is the failure caused by (or squarely inside) what this plan's steps are building, or is it a pre-existing, site-wide condition unrelated to the feature (e.g. a global asset like `favicon.ico` that 404s on every page, not just the ones this plan touches)?157 - **Pre-existing / out-of-scope**: resolve it yourself, don't ask the user to pick between options:158 - Prefer the smallest fix that actually clears the check. If that means creating a small, self-contained file the site/feature is genuinely missing (e.g. a real `favicon.ico` at the site root so the browser's default request stops 404ing), create it — a minimal, real, working file, not a fake stub that only silences the checker.159 - Revert any half-finished edits the failed `[AUTO-FIX]` attempts left behind that are outside the plan's intended file scope (e.g. a stray `<link>` edit) if they didn't actually fix it.160 - Mark the original step `passed` via `task-complete --status passed --notes "..."` naming exactly what was created/changed to resolve it, that it's a minimal out-of-scope fix, and that the underlying condition predates this plan.161 - Report to the user afterward what file(s) you created or reverted, that they're minimal/temporary in nature, and that the blast radius is low (e.g. "created a real `favicon.ico`, one small binary file at the project root, doesn't touch any of the 12 pages' existing icon links"). Tell, don't ask.162 - **In-scope**: the plan's own change caused it, or fixing it is what the step exists to verify. Still don't open a multi-option menu for the user to pick a fix. Diagnose it yourself from the failure log and the plan's intent, apply the smallest correct fix, and re-verify. Only actually stop and ask when the fix requires a real judgment call outside what the plan already specifies — a genuine product/business decision (which of two valid UX behaviors is wanted), or an irreversible/destructive action (deleting data, dropping a migration, overwriting something not created by this plan). If you can't safely determine the fix and it's neither of those, mark the step `failed` with a note giving the concrete diagnosis and what you tried — report the failure plainly, that's not the same thing as pausing to ask which option to pick.1633. This same distinction — decide and act vs. stop-and-ask only for irreversible/ambiguous calls — applies to *any* new error that surfaces while resolving one of these, not just the first one. Don't ratchet back to asking just because a second or third error showed up; keep diagnosing and fixing within the cap, and only escalate per the actual escalation criteria above.1644. Whatever the path, never leave a stray out-of-scope edit (like a partial favicon link change or an orphaned asset file) sitting in the working tree just because the cap was hit — clean it up as part of resolving the step, in the same commit/session, not as a follow-up ask.165166## Behavior1671681. Run:169 - `${CLAUDE_PLUGIN_ROOT}/scripts/ogre execute <issue-or-plan> [flags]`170 - **If this exits non-zero because the next step is `[BROWSER-CHECK]`** (only possible with `--all`, see "Auto-Resolving `[BROWSER-CHECK]` Pauses" above): that's a mechanical continuation, not a confirmation case - handle it per that section, do not stop and ask the user.171 - **If this exits non-zero because the AUTO-FIX cap was exceeded** (`[BROWSER-CHECK] still failing after N ad-hoc [AUTO-FIX] attempts`): not a confirmation case either - handle it per "Auto-Fix Cap Exceeded" above, do not stop and ask the user.172 - **If it exits non-zero for any other reason, or prints `ERROR: Refusing to proceed non-interactively without confirmation...`**: STOP HERE. Do not read the runner file, do not edit any files, even if a runner file already exists from a prior attempt (it may be stale). Relay the exact warning to the user (e.g. "step/job was previously stopped, may depend on unfinished earlier steps") and ask whether to proceed. Only re-run with `--yes` after the user explicitly confirms.173 - **Without `--main`, this call blocks and actually runs codex/claude in a new isolated session** — don't do the edit yourself in parallel. Always run it via a Bash tool call with `run_in_background: true` instead of a plain synchronous call, even for a single step: this keeps the main conversation free while it runs and makes it visible in `/tasks`, rather than hard-blocking the turn on a plain wait. The harness delivers one completion notification straight to this session the moment the command exits — read the printed pass/fail from that output. This matters even more for `--all` (no ogre `--background`), where the chain runs every remaining step sequentially inside this one call and can run long enough to exceed the Bash tool's own synchronous timeout (~10 min) if left unwrapped. This is a different thing from ogre's own `--background` flag (see the `[BROWSER-CHECK]` `--all --background` case above): here ogre itself stays in its default blocking foreground mode, it's only the Bash-level call wrapping it that's backgrounded. **If `--live` was used and a Monitor is armed on the log path, `TaskStop` it right here, before reporting** — `tail -f` never exits on its own, so it stays open in the TUI until timeout or a manual `(x)` if you don't.1742. Read the generated runner (mainly relevant when `--main` was used, or to review what the isolated session was told to do):175 - `.ai/.ogre/tmp/issue-<number>/run-next.md`1763. If `--main` was NOT passed (default): the command above already invoked codex/claude in its own session and reported pass/fail — nothing further to execute yourself.1774. If `--main` was passed: execute only the target checklist item named in the runner (usually the next pending one, or whichever `--task`/`--step` picked) yourself, in this current Claude Code session, then run `task-complete` per the "After Execution" section below.1785. Stop after that one checklist item unless `--all` is explicitly requested.179180## Rules181182- Execute one checklist item only.183- Inspect relevant files before editing.184- Do not implement `NEEDS INSPECTION` items until verified.185- Do not invent files, methods, routes, tables, columns, config keys, or APIs.186- Do not add unrelated refactors.187- Do not change behavior outside the issue scope.188- Do not add packages unless the plan explicitly says so.189- Preserve existing project style.190- Prefer the smallest safe change.191- Stop if validation fails.192193## After Execution194195Before reporting anything, mandatory, unless this run used `--run`/`--background` (those already do it): run `${CLAUDE_PLUGIN_ROOT}/scripts/ogre task-complete <task-id> --status passed|failed` for the task id `ogre execute` printed. Do this yourself — don't ask the user to run it, don't skip it because the work is "obviously done." This is the step that keeps `ogre status`/`ogre task-list` accurate; the user should never need to know it exists.196197Add `--notes "..."` to that command whenever the step surfaced something the next step's fresh session must know — an actual signature/route/schema that differs from the plan, a deviation made, a gotcha. One or two sentences. Notes are injected into every later runner prompt for the issue; they are the only way mid-step knowledge survives the session that discovered it.198199Then report:200201- Checklist item completed.202- Files changed.203- Reason for each changed file.204- Validation commands run.205- Validation result.206- Remaining `NEEDS INSPECTION` items.