diff --git a/.agents/skills/openspec-loop/SKILL.md b/.agents/skills/openspec-loop/SKILL.md new file mode 100644 index 0000000..ce78d70 --- /dev/null +++ b/.agents/skills/openspec-loop/SKILL.md @@ -0,0 +1,65 @@ +--- +name: openspec-loop +description: Supervise an openspec-loop run of a committed OpenSpec change. Use when the user asks to run, step, watch, stop or resume a change with the loop, or asks what a loop run is doing. +--- + +# Supervise an openspec-loop run + +The loop runs a committed OpenSpec change unattended. Supervision uses only these five commands: + +- `loop run ` starts a run and advances it in the foreground. It prints a progress line, prefixed with the time, as each step starts and ends, then a report. It exits 0 when the run completes, 1 when it stops, and 2 when it refuses to start. +- `loop step ` enrolls a new run or continues an existing one through the first successful pending-stage completion, including its internal cycles and recovery handoffs. It exits 0 when it returns control between stages or completes the whole run, 1 when it stops and 2 when it refuses. It shares the existing state, preparation, lock, transcripts and configured attempt budgets; it accepts no options. +- `loop status ` shows the run's state, branch, stages and locations. +- `loop stop ` ends the current step at once; the active advancement then prints its stop report. +- `loop run`, `loop step` and `loop resume` accept four agent aliases after the change name, in role order: proposal reviewer, plan reviser, implementer, implementation reviewer. When the user names four agents, pass them in that order, for example `loop run claude codex muse deepseek`. The loop writes them to the run worktree's `openspec/loop.local.yaml`, so later commands invoked from that worktree keep them. +- `loop resume ` continues a run that is between stages, stopped or interrupted, with a fresh attempt budget; `loop resume --attempts ` sets that budget, and `--implement` sends the run back to the implementer, which implements the plan as it stands; proposal review stays as it is, so an approved plan is not reviewed again. It advances in the foreground like `loop run`, with the same output and exit statuses. + +## Rules + +- Run every `loop` command outside the supervising session's sandbox. The loop writes the repository's Git directory, which sandboxes make read-only, and it starts its own workers. In a Codex session, request escalated permissions for each `loop` command. +- Relay each progress line to the user as it appears, in order and unchanged. Do not batch them until the run ends. +- When the command exits, show the user the report unchanged, in a code block. On a stop, identify the reported stage and transcript paths, then diagnose the stop as described under Diagnosing a stop before discussing recovery. Relaying the report and explaining the cause are separate obligations; a stage, agent alias and exit status are not a causal diagnosis. +- Run `loop stop` only when the user asks. Run `loop resume` or another `loop step` only after the user agrees, even when the report names it as the continuation or recovery. A successful stage boundary is an inspection point: show its report unchanged, identify what can run next and wait for the user without diagnosing a failure or automatically advancing. +- Change nothing to investigate a stop: do not edit the run's state, worktree or transcripts, and do not commit, resume or rerun anything to test a theory. Diagnose by reading only, as described under Diagnosing a stop. The one exception is answering a decision stop, below, and only with the user's agreement. + +## Watching a run in Claude Code + +1. Start the command with Bash and `run_in_background: true`, redirecting its output to a log file: `loop run > 2>&1`. Use `loop resume ` or `loop step ` the same way. +2. Start a Monitor on `tail -n +1 -f ` with the longest timeout. Each new line arrives as a notification. Relay each progress line, which starts with the time, and keep count of the lines relayed. The first line that does not start with the time ends the relay: relay neither it nor any line after it, because Monitor events drop each line's leading whitespace, and step 3 shows the rest from the log. If the monitor expires while the run continues, re-arm it with `tail -n + -f `, so no line is skipped or repeated. +3. When Bash reports that the background command exited, stop the monitor, read the log with Bash from the first line not yet relayed to the end, and show the user all of those lines unchanged, in a code block, with the exit status. + +## Watching a run in Codex + +Verified with Codex CLI 0.160.0. Start the command with `exec_command` and a short `yield_time_ms` such as 1000. While the command runs, the call returns the lines printed so far and a session id. Poll that session with `write_stdin`, passing empty `chars`, and relay the new lines from each poll. The poll that returns the exit status also carries the report. + +## Stopping and resuming + +To stop, run `loop stop ` from any checkout of the repository; the watched advancement prints the stop report and exits 1. To continue after the user agrees, start `loop resume ` and watch it the same way. For one successful stage at a time, use `loop step ` and watch it the same way; the report names the stage completed and what can run next. Returning between stages is different from a stopped run and from whole-run completion. After resolving a stop, `step` follows the same recovery as `resume`, within its single-stage limit. If `loop status` shows the run as interrupted, the process advancing it died; `loop resume` takes the run over and redoes the interrupted step. + +## Diagnosing a stop + +The loop reports observed outcomes without investigating their cause. The supervising session diagnoses stops with the user. Use only reads: the report, `loop status`, `cat`, `tail` and `jq` on the files under the run directory, `git status --short`, `git log` and `git diff` in the run's worktree, and `cat` on the invoking checkout's `openspec/loop.yaml` and `openspec/loop.local.yaml` and the main checkout's `openspec/loop.local.yaml`. When needed to distinguish a harness failure from an adapter's reply rejection, also use `command -v`, `readlink` and filesystem reads of the invoked adapter and its directly relevant helper. Inspect only the execution and reply-handling path needed to explain the error. The report names the worktree, the run directory and the transcripts directory. + +Permitted commands for locating the main checkout include `git rev-parse --absolute-git-dir`, `git rev-parse --path-format=absolute --git-common-dir` and `git worktree list --porcelain -z` in the invoking checkout. When the Git directories match, that checkout is the main checkout. Otherwise, use the first NUL-delimited worktree record; a `bare` record means there is no main checkout. Verification may use `git rev-parse --show-toplevel` and the common-directory command in the reported checkout to check that its root matches the record and it belongs to the same clone. If Git does not identify an accessible working tree, report the location refusal; do not search for another root or change Git configuration. This includes linked worktrees with separated metadata when Git reports the metadata directory instead of the main checkout. Direct invocation from the main checkout with separated metadata works. + +Configuration is merged from invoking committed, main local, then distinct invoking local files, and is reread on each run, resume or step. Local files are optional; a bare clone has only the invoking files. `defaultBranch`, `worktrees`, `checks` and `delivery` replace whole settings; `agents`, `roles` and `attempts` replace individual entries. Relative agent commands and worktrees paths refer to the invoking checkout, regardless of which file defines them. + +1. **Classify the stop from the report's cause.** A stop by the user needs no diagnosis. A decision stop is answered as described below. A stop at integration or delivery for a dirty checkout, unpushed or diverged commits, or a rejected push carries its own recovery: explain it. Diagnose the rest as an execution failure or as exhausted attempts. +2. **An execution failure.** Read the end of the transcript the cause names, the reply file if there is one, and the usage on the step's end line. For a worker's failure, also read the entry under `agents` for the alias the cause names: use the invoking local file when it defines that alias, otherwise the main local file when it defines it, otherwise the invoking committed file. Check the effective command's arguments, such as the model, against the error. + - Identify the specific failed operation and quote the evidence establishing it, such as an authentication failure, a quota or rate limit (`401`, `402`, `429`), a network error, a permission the harness denied, a turn limit, a missing command, or reply rejection. Trace which process produced the reported failure; the wrapper's nonzero exit does not establish that its child failed. + - If the transcript and command do not establish that distinction, locate and read the invoked adapter and its relevant helper. Inspect a script named in an interpreter's arguments, not just the interpreter. Relative commands and script paths refer to the invoking checkout. Name the inspected path; repository source may differ from the installed adapter used by the run. If the relevant code or its identity at the time of failure is unavailable, state that limit rather than applying current source behavior to an unverified invocation. Do not install, rebuild or execute the adapter or harness to investigate. + - For example, cut-pass prose followed by JSON can make parsing the entire final-message text fail. If the invoked helper returns only after child exit 0 and parsing happens after that return, explain the causal chain: the child succeeded, the adapter rejected its final text, and the adapter exited before writing a reply. Merely noticing prose before JSON does not complete that explanation, and parsing rejection does not establish why the model ignored its formatting instruction. Recover with a schema-conforming final reply while preserving strict validation; an output-contract change needs its own proposal. + - Establish the work left behind with `git status --short`, the existing history/diffs and run records: what is committed, what remains uncommitted, and which required checks and reviews completed or remain pending. Checks recorded inside a worker transcript are not proof that the loop ran its own checks or review. A failed final reply does not imply that implementation edits were lost or fully reviewed. If a part of that state cannot be established, name the missing evidence. + - Say what the evidence does not show. When nothing in the report, the transcript or the reply names an error, such as a transcript that ends without one, an empty transcript or a step killed by a signal, the cause is open: say so instead of guessing. Missing usage alone does not make an explicit error uncertain. + - A failed `git` or `gh` command quotes its output in the cause. A refused `openspec archive` names only its transcript, which holds OpenSpec's explanation: read it. An execution failure of the loop itself has no transcript, and its cause is all the evidence there is. +3. **Exhausted attempts.** List the run's `*.verdict.json` and `*.findings.json` files in the transcripts directory in step order, and compare their findings from attempt to attempt: + - The same finding repeats: the implementer or plan reviser does not address it, or cannot within the plan. + - The findings change every attempt: the reviewer's demands move, or each fix breaks something new. + - The same check failure repeats unchanged: it may fail on the base too, and the implementer must not repair what the change did not break. Suggest the user check the base. + + Then look at what each attempt changed. Each implementation review record names the `commit` it reviewed: `git diff` consecutive ones in the worktree. For proposal review, diff the plan between the `: revise plan` commits that `git log` shows on the run's branch. +4. **Present and wait.** Give the likely cause with the files and lines that support it and what the evidence leaves open. For an execution failure, include the failed operation and the work and validation left behind before proposing recovery. Then give the recoveries that fit: `loop resume ` after the user fixes the environment, `loop resume --attempts `, a decision or plan edit committed on the run's branch and then resumed, or discarding the run as the README describes. When the user has edited the plan of a run whose implementation is complete, offer `loop resume --implement`, which has the implementer implement the edited plan; a plain resume would continue where the run stopped. It is refused once the change is archived. Do nothing more until the user chooses. + +## Answering a decision stop + +When the report's cause says a review needs decisions the plan does not record, show the user each question exactly as the report lists it. Only the user may answer these questions; do not supply decisions on the user's behalf. When the user has answered, offer to record the answers. With the user's agreement, write each decision into the change's `design.md` in the run's worktree that the report's recovery names, and commit it there on the run's branch with `git commit`. Then resume with `loop resume ` once the user agrees, and watch the run as before. The resumed run reviews the plan again. diff --git a/.agents/skills/openspec-scope/SKILL.md b/.agents/skills/openspec-scope/SKILL.md new file mode 100644 index 0000000..948c6b4 --- /dev/null +++ b/.agents/skills/openspec-scope/SKILL.md @@ -0,0 +1,69 @@ +--- +name: openspec-scope +description: Prepare selected GitHub issues as individually committed OpenSpec proposals in an attended scoping worktree, then deliver them together. Use when the user asks to scope issues with the loop or invokes openspec-scope. +--- + +# Attend a scoping session + +Prepare native OpenSpec proposals with the user. The deterministic commands create and deliver the session; the user chooses issues, settles material decisions and chooses when to continue or finish. Scoping does not implement, enroll or archive changes, and leaves source issues open. + +## Permissions and working directories + +- Read applicable repository instructions first, including their issue/Git workflow. Use the repository's native OpenSpec proposing skill or command rather than a replacement planner. +- Run `loop scope start ` and `loop scope finish ` outside a sandbox that makes the shared Git directory read-only. Proposal staging and commits need the same Git-write permissions. In Codex, request escalated permissions for these commands, as the supervision skill does. A permission refusal does not justify authoring in the default checkout. +- Remember the checkout where start was invoked. Both commands use the existing configuration merge order: invoking `openspec/loop.yaml`, shared main-checkout `openspec/loop.local.yaml`, then the invoking checkout's local overrides; finish from that same checkout unless the user deliberately chooses different settings. Shared main-checkout overrides are inherited when configuration is read; invoking overrides are not copied into the session. +- Set the reported session worktree explicitly as the working directory for native proposing, all OpenSpec context/artifact commands and proposal commits. Run `openspec list --json` there and inspect its resolved root, then inspect native instructions' artifact paths before writing or staging. Require those paths to resolve inside the session worktree. If the project selects a store, follow native store selection; if its resolved root is outside the session worktree, stop and explain the conflict rather than write outside it or silently switch roots. + +## Select and start + +1. List open issues using the repository's issue-listing workflow. Otherwise read them with `gh issue list` and relevant details with `gh issue view`; explain an order favoring blockers, correctness work and small work whose decisions are settled. Wait for the user to select issues before drafting. An issue selection already given by the user counts; do not ask for it again. +2. Use the user's session name, or agree on one, then run `loop scope start ` from the invoking checkout. It creates `scope/` and `/scope-` from the configured local default branch without fetching or changing that branch. Git validates the generated branch name. Show the reported path, branch and finish command. +3. To continue interrupted work or handle an existing-session refusal, inspect `git worktree list`, then read the existing session's files, `git status` and `git log`. Reopen that worktree without replacing the branch or checkout. If finish cannot find a session during a detached manual rebase, complete or abort that rebase or restore its checkout before retrying. Completed commits and unfinished drafts are the recovery record; no separate session state is needed. + +## Propose one selected issue at a time + +1. Read the selected issue, its comments and relevant project context. Invoke native OpenSpec proposing from the session worktree for one coherent implementable change. Verify its root and artifact paths as above. +2. Respect the native proposal's planning boundary. If proposing returns for review, show the artifacts and wait for the user to request the next action before resuming scoping. A scoping invocation does not authorize bypassing that boundary or starting implementation. +3. With the user, inspect the generated proposal, design, spec deltas and tasks. Ask about unresolved choices that materially affect behavior or scope and stop until answered. Use explicit defaults for routine choices, recording them as defaults in `design.md`; record the user's material decisions there as well. Do not silently choose behavior so later unattended implementation can proceed. +4. Trim to one coherent change and record non-goals. Explicit invocation of this skill authorizes filing omitted requested work as follow-up GitHub issues. Follow the repository's issue conventions, check for an existing follow-up, and create only the necessary follow-ups. Each must link the source issue URL and name the OpenSpec change; link it from the proposal's non-goals. The proposal need not be published and no proposal URL is required. Use a structured body argument or a body file for multiline issue text. Do not file unrelated work or close the source issue. +5. Record `Source issue: ` in `proposal.md`. Once that proposal's artifacts are ready, inspect its diff and stage only `openspec/changes//` in the session worktree. Inspect the staged paths to avoid including another proposal or unrelated staged work, then commit that proposal separately, for example: + + ```sh + git add -- openspec/changes// + git diff --cached --name-only + git commit -m 'docs(scope): propose (relates to #14)' -- openspec/changes// + ``` + + Use the actual change name and source issue number, without closing keywords. Each completed proposal gets its own artifact-only commit before moving to another issue. Do not invent artifact-content checks or Git hooks. +6. Show the finished proposal commit and remaining issues, then continue or finish when the user chooses. If interrupted, leave the draft in place; resume by inspecting the same files and Git history. + +## Finish and recover + +When the user chooses to finish, run `loop scope finish ` from the original invoking checkout. Relay its progress and outcome, including external effects and the reported recovery. Exit 0 means delivery succeeded, 1 means integration/publication failed, and 2 means a refusal. Keep the session branch and worktree. + +Finish requires no uncommitted tracked or untracked session work. An unfinished draft refuses with exit 2 and remains available. Continue authoring it or let the user deliberately move it elsewhere; do not commit, stash or delete drafts just to finish. + +- `local` rebases onto the local default branch and fast-forwards it without contacting a remote. This differs from local run delivery, which leaves the default branch untouched. +- `pr` fetches and rebases onto the default branch's upstream, pushes the session branch without force, then opens or finds one PR targeting that upstream branch/repository. The local default branch stays unchanged. `gh pr create --fill` carries the issue-bearing commit subjects into the PR. +- `merge` fetches and synchronizes the local default branch safely, rebases onto it, pushes to its upstream default branch, then fast-forwards the local default branch. Dirty default holders, ahead/diverged defaults and obstructing files require attended recovery. + +A conflicting finish rebase is aborted. Explain Git's error and reconcile in the session worktree before retrying; no automatic merge fallback or force push is allowed. Preserve any pre-existing user operation. Do not retry until the user chooses to continue after resolving the cause. + +If a merge push succeeded before the local update failed, retry can complete that safe update. An open PR is reused only after a successful non-force push. When a moved base causes an already-published PR branch to be rebased and its push rejected, reconcile both histories in the session worktree: + +1. Fetch the configured upstream remote's published session branch and current base. +2. Merge the published session history into the rebased local session branch. +3. Merge the current base if it is not already an ancestor of the session tip. +4. Resolve and commit any conflicts, then retry finish from the original invoking checkout when the user chooses. + +For example, with upstream `origin/main` and session `planning`: + +```sh +git fetch origin scope/planning main +git merge --no-edit origin/scope/planning +git merge --no-edit origin/main # if not already an ancestor of HEAD +``` + +Both the published tip and current base must be ancestors of the session tip, so finish skips another rebase and can push without force. Resetting only to the published tip repeats the rebase and rejection. Use the actual configured remote/branch names and retain Git's errors for attended recovery. + +After delivery, tell the user to enroll a proposal explicitly with `loop run ` or `loop step ` from the default branch once it has landed there. In `pr` mode the proposal PR must be merged first. Enrollment from the multi-proposal session branch includes sibling proposal commits in the selected change's patch. Do not enroll automatically. Source issues remain open until their changes are implemented; session cleanup remains ordinary manual Git work. diff --git a/.claude/commands/opsx/apply.md b/.claude/commands/opsx/apply.md new file mode 100644 index 0000000..1c6a483 --- /dev/null +++ b/.claude/commands/opsx/apply.md @@ -0,0 +1,201 @@ +--- +name: "OPSX: Apply" +description: "Implement tasks from an OpenSpec change (Experimental)" +allowed-tools: Bash(openspec:*) +category: "Workflow" +tags: ["workflow", "artifacts", "experimental"] +--- + +Implement tasks from an OpenSpec change. + +**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. + +**Project check:** These steps expect a project that already uses OpenSpec. Before the first step that writes anything (`new change`, `archive`, `sync specs`, or authoring an artifact file), confirm the project has a root: run `openspec list --json` (with `--store ` when a store is selected, since the store is then the root) and read `root`. A root object means the project is set up. `"root": null` means it is not - there is no `openspec/` directory here, and a write such as `openspec new change` would create one as a side effect. The command also exits non-zero, which is that answer rather than a broken CLI, so read the JSON instead of retrying or working around it. + +One `"root": null` is not about setup: when a `status` error message starts with `Declared in` or `Invalid store declaration in` and names this project's `openspec/config.yaml` (or `config.yml`), the project does use OpenSpec through a store it declares, which this machine cannot resolve (the store is not registered, or the `store:` line is malformed). Do not treat it as uninitialized and skip the branches below: stop before writing and show the user that error's `message` and `fix`. + +Otherwise, with no root, what happens next depends on how this workflow was reached: + +- **Auto-selected**: you chose this workflow yourself, without the user naming OpenSpec, naming this skill, or running its slash command. Stop using OpenSpec and answer the request normally, as you would with no OpenSpec installed. Do not ask them to set anything up and do not mention OpenSpec setup. +- **Explicit OpenSpec request**: the user named OpenSpec, named this skill, or ran its slash command. Stop before writing and ask how to proceed: set this project up (`openspec init`), target a store they already have (`--store `), or continue without OpenSpec for this request. Wait for their answer. + +In both branches, never create the root as a side effect: do not run `openspec init` until the user asks for it, do not hand-create `openspec/` files, and do not let a command create it. + +**Input**: Optionally specify a change name (e.g., `/opsx:apply add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. + +**Steps** + +1. **Select the change** + + If a name is provided, use it. Otherwise: + - Infer from conversation context if the user mentioned a change + - Auto-select if only one active change exists + - If ambiguous, run `openspec list --json` to get available changes and ask the user to select one + + Always announce: "Using change: " and how to override (e.g., `/opsx:apply `). + +2. **Check status to understand the schema** + ```bash + openspec status --change "" --json + ``` + Parse the JSON to understand: + - `schemaName`: The workflow being used (e.g., "spec-driven") + - `planningHome`, `changeRoot`, and `actionContext`: planning scope and edit constraints + - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others) + +3. **Get apply instructions** + + ```bash + openspec instructions apply --change "" --json + ``` + + This returns: + - `contextFiles`: artifact ID -> array of concrete file paths (varies by schema - could be proposal/specs/design/tasks or spec/tests/implementation/docs) + - Progress (total, complete, remaining) + - Task list with status, source path, and source line + - Dynamic instruction based on current state + - Optional `context`: current required project instruction input from the selected root + - Optional `operationGuidance`: current advisory guidance for apply + - `missingArtifacts` (when present): required artifact ids with no output + + **Handle states:** + - If `state: "blocked"`: show the message and pause implementation. + - If `missingArtifacts` is non-empty: suggest completing the missing artifacts. Run `openspec status --change "" --json`, select the next `ready` artifact (not `skipped` or `blocked`), and use `openspec instructions "" --change "" --json` for its rules and template. Keep the selected `--store ` on both commands. + - Otherwise, follow the CLI instruction to create or repair the schema-configured tracking file from existing planning artifacts. Do not assume another artifact is ready or start implementation while blocked. + - If `state: "all_done"`: congratulate, suggest archive + - Otherwise: proceed to implementation + + Treat `context` as a required prompt-level input. Read and consider it, and + apply relevant project facts, conventions, and constraints while implementing. + Treat `operationGuidance` as optional additive advice. Read and consider every + entry, and follow entries that are applicable and compatible with the built-in + workflow. + + Keep both fields separate from CLI-returned state, missing artifacts, tasks, + progress, `contextFiles`, and the built-in `instruction`. They are not + evidence of task completion, do not replace the built-in instruction, and do + not permit bypassing a blocked state. If context conflicts with the built-in + instruction, an explicit user choice, or a CLI-controlled value, report the + conflict and preserve the controlling value. If guidance is inapplicable or + conflicts with those controlling inputs, do not follow it and explain why. + These are prompt-level behavior contracts, not enforceable checks. + +4. **Read context files** + + Read every file path listed under `contextFiles` from the apply instructions output. + The files depend on the schema being used: + - **spec-driven**: proposal, specs, design, tasks + - Other schemas: follow the contextFiles from CLI output + + Do not copy `context` or `operationGuidance` verbatim into implementation + files or planning artifacts unless the user separately asks for that content. + +5. **Show current progress** + + Display: + - Schema being used + - Progress: "N/M tasks complete" + - Remaining tasks overview + - Dynamic instruction from CLI + +6. **Implement tasks (loop until done or blocked)** + + For each pending task: + - Show which task is being worked on + - Make the code changes required + - Keep changes minimal and focused + - Before editing, confirm the checkbox at the returned `sourcePath` and `line` still matches the task description; if it does not, rerun the apply instructions and use the refreshed location + - Mark the task complete at its returned `sourcePath` and `line`: `- [ ]` → `- [x]` + - Rerun the apply instructions and confirm that task is now done and progress changed + - Continue to next task + + **Pause if:** + - Task is unclear → ask for clarification + - Implementation reveals a design issue → suggest updating artifacts + - A task needs work beyond what the spec and tasks describe, or you are tempted to drop, narrow, defer, or accept exceptions to specified behavior to make it fit → surface the added scope and ask; do not absorb it silently + - Error or blocker encountered → report and wait for guidance + - User interrupts + +7. **On completion or pause, show status** + + Display: + - Tasks completed this session + - Overall progress: "N/M tasks complete" + - If all done: suggest archive + - If paused: explain why and wait for guidance + +**Output During Implementation** + +``` +## Implementing: (schema: ) + +Working on task 3/7: +[...implementation happening...] +✓ Task complete + +Working on task 4/7: +[...implementation happening...] +✓ Task complete +``` + +**Output On Completion** + +``` +## Implementation Complete + +**Change:** +**Schema:** +**Progress:** 7/7 tasks complete ✓ + +### Completed This Session +- [x] Task 1 +- [x] Task 2 +... + +All tasks complete! You can archive this change with `/opsx:archive`. +``` + +**Output On Pause (Issue Encountered)** + +``` +## Implementation Paused + +**Change:** +**Schema:** +**Progress:** 4/7 tasks complete + +### Issue Encountered + + +**Options:** +1.