---
name: magos-iterator
description: "Deep plan-and-track workflow for multi-step engineering tasks. Load when the user wants a persisted, reviewed .scriptorum/ plan with explicit progress tracking, autopilot step execution, and a closing diff review — invoked via $magos-iterator. Encodes the Understand → Plan → Track → autopilot → Close loop, entry modes (Fresh / Track / List), the enginseer dispatch template with the [DISPATCH: magos-iterator] sentinel, the sequential/bounded autopilot subsection, and the magos-reductor Close phase."
---

# magos-iterator

A workflow for engineering tasks that need alignment, a reviewed plan, progress tracking across sessions, and a diff review at the end. Load this skill when the user invokes `$magos-iterator` or asks for a tracked, persisted plan.

Always load the `plan-workflow` skill first. It defines the scriptorum root, filename format, frontmatter schema, checkbox grammar, slug-to-file resolution, and the `magos-artisan` action contract used throughout this workflow.

## Planner-only invariant — CRITICAL

**While running this workflow, orchestrate only. Never edit code directly.**

The old `magos-iterator` primary agent enforced this via `edit: deny` permissions. The host agent (archmagos) is write-capable, so this invariant is now **instruction-enforced, not permission-enforced**. That makes it more important to follow explicitly, not less.

Rules:
- Every `.scriptorum/` mutation goes through `magos-artisan` (dispatched as a subagent). No exceptions.
- Code implementation is delegated to `enginseer` (in-session dispatch) or to the user's own session. Never implement steps directly.
- If you catch yourself about to edit a file outside `.scriptorum/`, stop. Dispatch `enginseer` or redirect the user instead.
- The blast radius of this workflow is bounded to `.scriptorum/` by design. Honour that boundary even though the host agent could cross it.

## Entry modes

Decide which mode applies from the user's first message:

| Input | Mode | What to do |
|---|---|---|
| `<slug>` (no other context) or `--resume <slug>` | **Track** | Read the plan, show status, react to user requests. |
| `<task description>` (a new task) | **Fresh** | Run the full Understand → Plan flow, write the plan, get it reviewed, hand off. |
| Empty / "what's in progress?" / no task | **List** | Scan `.scriptorum/*--*.md`, show those with `status ∈ {not-started, in-progress, unknown}` sorted by `updated` desc, ask the user to pick. Once picked, switch to Track. |

If the input is ambiguous between Fresh and Track (looks like both a slug and a task description), prefer Track and ask the user one focused question with two options: "resume this plan" / "start a new plan with this description".

## Phase 1 — Understand (Fresh mode only)

Ground every claim in the plan in real code. Skip in Track mode — the original plan already did this work.

1. Dispatch `explore` as a subagent with the user's task as the question, asking for a written answer with evidence. Use `medium` thoroughness for narrowly scoped tasks; increase to `high` when you need a complete explainer across many files.
2. Read the agent's output. Open and verify the most load-bearing files yourself (via `read`) before using them in the plan. Treat the subagent's `path:line` references as a map, not final evidence — verify before citing.
3. If the explorer returned significant unknown unknowns or open questions, surface them to the user before planning. Decide together whether they need answering now or can be deferred into the plan as `> note:` lines.

The explorer's full writeup stays internal — don't dump it to the user unless they ask.

## Phase 2 — Plan (Fresh mode only)

1. **Catechism.** Load the `catechism` skill and run the protocol — unless the user's initial task description already contains an explicit Goal, Scope, Constraints, and at least one edge case. In that case, restate your understanding in 1-2 lines, confirm with one focused question, and skip the multi-round interview. Run the catechism when alignment is genuinely needed; skip it on a fully-specified task.

   Short-circuit heuristic — skip the multi-round interview when **all** of these hold:
   - An explicit goal phrased as a single sentence ("I want to <do X> so that <Y>").
   - An explicit scope (named files, named modules, named feature).
   - At least one named constraint, deadline, or non-goal.
   - No vague verbs ("improve", "fix", "clean up", "refactor") without a concrete target.

2. **Decide plan weight.** Pick `light`, `standard`, or `heavy` per the `plan-workflow > Plan weight` section. Default to `standard`. Go `light` only for trivial single-file work; go `heavy` for multi-module changes, unfamiliar territory, or anything where wrong assumptions would cost real time. Record the choice — it goes in frontmatter and shapes step bodies.

3. **Synthesize the plan body.** Match the five required sections from `plan-workflow`:
   - `## Summary` (1-3 sentences)
   - `## Scope` (bullets)
   - `## Numbered steps` (numbered checkbox list with per-step sub-items at the chosen weight)
   - `## Acceptance criteria` (unordered checkbox list — cross-cutting invariants only; per-step outcomes belong in `Done when:`)
   - `## File touchpoints` (regular bullets — no checkboxes)

   Embed `path:line` citations for every concrete reference to existing code. Bare paths for new files. Do not embed the catechism recap verbatim.

4. **Preview to the user.** Print the frontmatter (created/updated dates, slug, goal, status: not-started, weight: <chosen>, supersedes: []) followed by the full body. Ask: `Write plan to <abs-path>? [Y/n]`. Default Y.

5. **On confirmation, dispatch `magos-artisan`** as a subagent:
   ```
   action: write-plan
   payload:
     slug: <slug>
     goal: <single-line goal from the recap>
     title: <H1 title>
     body: <markdown body, sections only — no frontmatter>
     overwrite: <true if user accepted the overwrite prompt>
     weight: light | standard | heavy
     supersedes: []
   ```
   Surface the artisan's return verbatim.

6. **Dispatch `logis`** as a subagent with the absolute path of the plan just written. This is automatic — do not ask. Surface its return.

7. **Triage the review.**
   - If verdict is `approve` or `## Blocking concerns` is `_(none)_` → proceed to Handoff.
   - If there are blocking concerns → propose amendments, show the diff against the current plan body, ask: `Apply these amendments and re-write the plan? [Y/n]`.
      - On Y → dispatch `magos-artisan` (subagent) with `write-plan`, `overwrite: true`, new body. Re-dispatch `logis` if the changes were substantial.
     - On N → ask the user how to proceed (skip the concern with an `append-note` justification / amend partially / abandon plan).

## Handoff (end of Fresh mode)

After the plan is written and reviewed, print:

```
Plan ready at <abs-path>.

To execute, either:
  - Stay here and say "execute step 1" — I'll dispatch enginseer for that step (it will commit).
  - Or drive execution manually in a separate session.

To resume tracking later: $magos-iterator <slug>.
```

Then stop. Do not enter Track mode in the same session unless the user explicitly asks.

## Phase 3 — Track (Track mode)

Track mode is **reactive**. Read the plan, show the user where things stand, and dispatch `magos-artisan` to mutate the plan whenever they report something changed. Do not run autonomously through steps.

### On entry

1. Resolve the file via `plan-workflow`'s slug-to-file resolution. If ambiguous, ask the user to disambiguate.
2. Read the plan. Parse frontmatter: `status`, `goal`, `weight` (default `standard` if absent), `supersedes`, `updated`. Parse `## Numbered steps` and `## Acceptance criteria` to count `[ ]` / `[x]` per section.
3. Handle status edge cases:
   - `status: complete` → report `Plan <slug> is already complete (updated <date>).` Ask: reopen (dispatch `update-status in-progress`) / start a fresh plan / nothing.
   - `status: abandoned` → similar; offer to reopen or stay closed.
   - `status: not-started` → on first user-driven mutation, artisan auto-promotes to `in-progress`. No action needed.
   - `status: in-progress` or `unknown` → proceed.
4. Print a short status block:
   ```
   Plan: <slug>  (status: in-progress, updated <date>)
   Goal: <goal>

   Numbered steps: [3/8 done]
     1. [x] <step>
     2. [x] <step>
     3. [x] <step>
     4. [ ] <step>          ← next
     5. [ ] <step>
     ...

   Acceptance criteria: [0/4 verified]
     - [ ] <criterion>
     - [ ] <criterion>
     ...
   ```
   Show all numbered steps and acceptance criteria. Mark the first `[ ]` with `← next`.

### Reacting to the user

Interpret natural-language updates and dispatch the appropriate `magos-artisan` action:

| User says | Action |
|---|---|
| "Step 4 done." / "Tick step 4." | `tick-task` section=numbered-steps index=4 state=done |
| "Mark step 4 as done and step 5 as done." | Two `tick-task` dispatches in sequence. |
| "Step 4 is blocked — upstream API changed." | `append-note` section=numbered-steps index=4 note="blocked — upstream API changed" (checkbox stays `[ ]`) |
| "Untick step 3, I had to revert it." | `tick-task` section=numbered-steps index=3 state=undone |
| "Add a note to step 2: tried approach X, reverted." | `append-note` section=numbered-steps index=2 note="tried approach X, reverted" |
| "Acceptance criterion 1 passes." | `tick-task` section=acceptance-criteria index=1 state=done |
| "Execute step N." | Dispatch `enginseer` via `task` with the dispatch payload (template below). Surface the returned `<result>` block verbatim. If `blockers` is empty and `committed` is a SHA, dispatch `magos-artisan tick-task` for step N and include the SHA in the confirmation line. If `committed: not run` (no-op step), still tick if the user confirms the step was already satisfied. If `blockers` is set, do not tick — surface and ask how to proceed. |
| "Execute steps X, Y, Z in parallel." | Multiple concurrent `enginseer` dispatches in a single message. Tick each as it returns, only if it has no blockers and committed a SHA. Only parallelize when the user explicitly names each step — never auto-parallelize, because steps may share files. |
| "Go." / "Execute all remaining." / "Run the rest." | Sequential autopilot. See **Sequential autopilot** below. |
| "Run next N." / "Run through step M." | Bounded autopilot. Same loop as "Go" but exits after N steps from first unticked (or after step M is ticked, inclusive). Print the updated status block and stop. Do not prompt for Close. |
| "Plan is wrong — file moved and step 3 needs to change." | Pause-and-amend (see below). |
| "Mark this plan complete." | Run **Close** (see Phase 4). |
| "Abandon this plan." | `update-status abandoned`. Report and stop. |
| "What's left?" | Re-print the status block. No mutation. |
| "Show the plan." | Read the file and print the full body. No mutation. |

### Dispatch template for `enginseer`

When dispatching `enginseer` as a subagent for step execution, the prompt **must** start with the sentinel `[DISPATCH: magos-iterator]`. The payload hoists the step's contract from the plan verbatim — no content is invented at dispatch time.

```
[DISPATCH: magos-iterator]
Plan: <abs-path-to-plan-file>
Weight: <light | standard | heavy from plan frontmatter, or "standard" if absent>
Step <N>: <step text verbatim from the plan>
Outcome: <Outcome: line verbatim from the step, or "see step text" if absent>
Done when:
  - <observable outcome verbatim from the step's Done when: sub-list>
  - <observable outcome verbatim>
Touchpoints: <per-step Touchpoints: line verbatim, or relevant subset of ## File touchpoints>
Anti-touch: <per-step Anti-touch: line verbatim, or "none">
Verification: <per-step Verification: line verbatim, or "none">
Independent Test: <per-step Independent Test: line verbatim, or "none">
Pre-conditions: <per-step Pre-conditions: line verbatim, or "none">
Plan-level acceptance (relevant): <subset of ## Acceptance criteria that this step affects, or "none">

Execute this step. Touch only the named touchpoints. Independent Test is your behavioral confidence gate — run it (or document the manual repro in your commit message). Return one structured <result> block.
```

Rules:

- **Sentinel is non-negotiable** — without `[DISPATCH: magos-iterator]` on the first line, enginseer cannot disambiguate a stray invocation from a real plan dispatch.
- **Always include every labelled line** even if it resolves to "none". Enginseer relies on the shape.
- **Verbatim hoisting only.** Do not paraphrase the step text or sub-items. If the plan is wrong, run pause-and-amend; do not "fix" content at dispatch time.
- **Light-weight plans** have no `Done when:` / per-step `Touchpoints:` sub-items. Fall back to: `Done when: <step text restated as a single outcome>`, `Touchpoints:` from the plan-level `## File touchpoints` filtered to anything the step text mentions, `Outcome: see step text`, `Independent Test: none`. Surface "none" for the other labels.
- **Standard-weight plans** always have `Done when:` and `Touchpoints:` per step. Use them verbatim. `Outcome:` and `Independent Test:` resolve to `see step text` and `none` respectively.
- **Heavy-weight plans** carry required `Outcome:` and `Independent Test:`, plus any of `Anti-touch:`, `Verification:`, `Pre-conditions:` per step — hoist whichever are present verbatim.

Never auto-parallelize step execution. Concurrent dispatches require explicit user direction naming each step.

If the user's request is ambiguous (e.g. "tick the auth one" but multiple steps mention auth), ask one focused question to disambiguate. Do not guess.

After every successful artisan dispatch following an enginseer commit, print a one-line confirmation including the new state and SHA (`Step 4 → done (commit abc1234). Plan now at 4/8.`).

### Sequential autopilot

When the user invokes autopilot (`go`, `execute all remaining`, `run the rest`, `run next N`, `run through step M`), walk through unticked numbered steps in order:

1. **Loop body, per step N:**
   - Dispatch `enginseer` with the standard `[DISPATCH: magos-iterator]` payload for step N.
   - Surface the returned `<result>` block.
   - If `blockers` is empty:
     - If `committed` is a SHA → dispatch `magos-artisan tick-task` for step N. Print the one-line confirmation including the SHA.
     - If `committed: not run` (no-op step) → still tick. Autopilot assumes the plan is correct and a no-op means the step was already satisfied. Note the no-op in the confirmation (`Step N → done (no-op, nothing to commit). Plan now at X/Y.`).
   - If `blockers` is set:
     - **Stop the loop.** Do not dispatch further steps.
     - Print: `Autopilot stopped at step N. Blocker: <one-liner>. Plan now at X/Y done.`
     - Wait for user direction.

2. **Bound handling** (only for `run next N` / `run through step M`):
   - After N successful steps (counting from first unticked) or after step M is ticked, exit the loop. Print the updated status block. **Do not prompt for Close.**

3. **End-of-plan handling** (only for unbounded `go` / `execute all remaining` / `run the rest`):
   - When the last unticked numbered step ticks successfully, print: `All numbered steps complete (X/X). Run Close to verify acceptance criteria and transition to complete?`
   - Wait for user direction. **Do not auto-transition to `complete`** — that's an explicit Close gate.

**Autopilot constraints:**

- **Sequential only.** Never parallelize during autopilot — steps may share files and the plan has no dependency metadata.
- **No mid-loop questions.** Autopilot does not invoke `question` mid-run. If a step is genuinely ambiguous or wrong, that is a plan defect — enginseer returns a blocker, the loop stops, and handle it via standard pause-and-amend on the next user turn.
- **No acceptance-criteria auto-check.** Autopilot only walks `## Numbered steps`. Acceptance criteria stay user-driven; they often need human judgement.
- **Plan amendments mid-autopilot:** the loop is single-turn. If the user reports the plan is wrong after autopilot stopped, run pause-and-amend, then resume with `go` (or `run next N`) on the next turn.

### Pause-and-amend

If the user reports that the plan itself is wrong (a step is impossible as written; a touchpoint moved; an assumption is broken), do **not** silently work around it. Ask a multiple-choice question with three options:

- `Amend the plan` → propose a revised body that fixes the affected sections, show it to the user, and on confirmation dispatch `magos-artisan` (subagent) with `write-plan`, `overwrite: true`. Re-dispatch `logis` if the change was substantial. Resume Track.
- `Continue with a caveat` → dispatch `magos-artisan` with `append-note` on the affected step explaining the deviation. Continue Track.
- `Abandon the plan` → dispatch `magos-artisan` with `update-status abandoned`. Stop.

## Phase 4 — Close

Triggered when the user says "mark complete" or "this is done", or implicitly when they tick the last unchecked box and ask "anything else?".

Before transitioning the plan to `complete`:

1. **Sanity-check coverage.** If any `## Numbered steps` or `## Acceptance criteria` are still `[ ]`, surface them and ask the user: tick remaining / waive (via `append-note` with a justification) / abort the Close.
2. **Dispatch `magos-reductor`** as a subagent. Tell it to review the working-tree diff against `HEAD` (or the diff since the plan started, if a meaningful base ref is known). Surface its output verbatim.
3. **Triage the diff review.**
   - Blocking issues → surface them; ask whether to (a) un-mark for fixing (don't transition to complete), (b) record as a `> note:` on a relevant step, or (c) waive with the user's acknowledgement.
   - Non-blocking / refactoring opportunities → surface; default is to defer (plan is closing) unless the user wants to act.
4. **Mark the plan complete.** Dispatch `magos-artisan` (subagent) with `update-status complete`. Report the final path.
5. **Summarise.** End with the compact shape from the project's `AGENTS.md`:
   ```
   - Changed: <short summary of what landed across all steps>
   - Verified: <plan review, diff review, any acceptance checks>
   - Notes: <only important caveats — e.g. acceptance criterion N waived per user>
   ```
   Then ask if the user wants a commit. Do not commit unprompted; route through `servitor` if asked.

## Subagent roster

| Subagent | When to dispatch |
|---|---|
| `explore` | Understand phase — code exploration before planning. Dispatch as a subagent. |
| `magos-artisan` | Every `.scriptorum/` mutation: `write-plan`, `tick-task`, `append-note`, `update-status`, `supersede`. Dispatch as a subagent. |
| `logis` | After every plan write and after substantial amendments. Dispatch as a subagent. |
| `enginseer` | Step execution in Track mode, via the `[DISPATCH: magos-iterator]` sentinel. Dispatch as a subagent. Enginseer commits per step and returns a SHA. |
| `magos-reductor` | Close phase — diff review before transitioning to `complete`. Dispatch as a subagent. |
| `servitor` | Commits when the user asks at the end of Close. Dispatch as a subagent. |

## Hard rules

- **Orchestrate only.** While in this workflow, never edit code directly. Dispatch `enginseer` for execution, or redirect the user to a separate session. This is instruction-enforced — the host agent is write-capable, so the discipline must be explicit.
- **All `.scriptorum/` mutations go through `magos-artisan` (dispatched as a subagent).** The invariant "only artisan writes the scriptorum" must hold.
- **Do not implement code.** Not the steps, not "small helper" edits, not config tweaks.
- **Do not auto-set `status: complete`.** Completion is an explicit `update-status complete` dispatch at the end of Close, after step coverage and diff review.
- **Do not skip plan review.** `logis` runs after every plan write. Re-dispatch after substantial amendments.
- **Do not skip diff review at Close.** `magos-reductor` runs before transitioning to `complete`. Surface its output even when clean.
- **Do not commit automatically.** Commits go through `servitor` when the user asks.
- **Do not run autonomously through steps in Track mode by default.** Track is reactive: one user message per step. The only exception is explicit autopilot invocation.
- **Do not silently work around a broken plan.** Pause and ask via `question` per the pause-and-amend rule.
- **Do not re-run Understand or Plan on Track.** Trust the existing plan file.
- **Do not modify legacy `<slug>.md` plan files.** Read them on Track if no dated match exists, but treat them as read-only history.
- **Match the project's `AGENTS.md`.** Direct, concise, outcome-first. Don't restate the request. Don't narrate obvious steps.
