--- name: studio description: "Client mode: one contract sign-off, then the agents run like a studio until delivery - consilium panels decide instead of the user, milestones are atomic and verified, all state lives on disk, and any session can resume the run. Zero questions between sign-off and delivery." argument-hint: " | --resume" --- ## Progress Contract **OCTO_ROOT** = `${CLAUDE_PLUGIN_ROOT}` when set; otherwise two directories above this skill's base directory (`skills//` sits at `/skills//`). Resolve once at start. Register these phases as a native task list at the start of Phase 1, before any interview. Report progress as "N phases remaining, milestone M of K" β€” never wall-clock ETAs. Register steps in the native task list named `πŸ™ / β€” `; update each to in_progress/completed as you go β€” the checklist is the user's primary progress view. Phases: (1) contract, (2) consilium-setup, (3) milestone-loop, (4) resume, (5) delivery. **State-write gate**: a step has not STARTED until its `state.json` overwrite and `events.jsonl` entry are written. Write state FIRST, then do the step's work β€” never the reverse. A growing "updated Xm ago" on the task checklist means you are violating this contract. Relationship note: build = task / hours / user nearby; studio = mission / days / user absent. Accepted interpretation: supervision granularity inside the inner loop is per-batch. ## Arguments - **``** β€” what to build; required on a fresh run. If omitted, ask once, then proceed. - **`--resume`** β€” re-attach to an interrupted studio run; see Phase 4. ## Phase 1 β€” Contract ← STOP This is the only moment the studio contacts the client for decisions. Use AskUserQuestion for every enumerable choice in the interview (control scheme, scope options, limits); free-text prose only for genuinely open fields like the mission statement. Conduct a deep interview covering six topics, in this order: 1. **Mission** β€” what outcome must exist in the world when the run finishes? 2. **Acceptance Criteria** β€” ask "done means…" for each deliverable; push for observable, testable answers. 3. **Preferences** β€” tone, technology choices, naming conventions, any taste worth preserving. 4. **Constraints** β€” hard limits: budget, runtime, forbidden dependencies, compliance rules. 5. **Delegation** β€” record this clause verbatim: *"All decisions not listed above are the studio's to make."* 6. **Limits** β€” optional: time box, cost ceiling, maximum milestone count. Write `.claude/octo/run/contract.md` with six top-level sections matching those headings: Mission / Acceptance Criteria / Preferences / Constraints / Delegation / Limits. Present the draft to the client. On acceptance, the run is sealed: - **Zero further questions** β€” any ambiguity that arises is resolved by the consilium (Phase 2), never by the client. - **One exception**: corrupt or missing state on `--resume` halts the run and reports to the client before any work begins (Phase 4). Initialize run state: - Write `.claude/octo/run/state.json`: `{"mode":"studio","mission":"","phase":"contract","milestones":[],"updated":""}`. - Append to `.claude/octo/run/events.jsonl`: `{"ts":"","type":"start","mode":"studio","mission":""}`. ## Phase 2 β€” Consilium Whenever execution would otherwise pause for a user decision β€” a design fork, a missing requirement, a scope question, a dependency choice β€” convene a consilium panel instead. Dispatch three seats **in one message** (parallel tool-use blocks): | Seat | Mandate | |------|---------| | **Client advocate** | Argues from `contract.md` β€” what did the client actually ask for? | | **Pragmatist** | Proposes the simplest option that ships and is safe to reverse. | | **Risk** | Identifies what breaks later if this choice is wrong. | After all three seats report, dispatch the **architect** as judge. Seat votes are advisory; the architect rules on the merits of the arguments, not by majority count. The ruling is one of: `ACCEPT`, `ACCEPT WITH CHANGES`, or `REJECT`. For anything other than a plain `ACCEPT`, the architect must list the specific conditions or blockers. Append every decision to `.claude/octo/run/decisions.md`: ``` ## D β€” Seats: - Client advocate: - Pragmatist: - Risk: Ruling: ACCEPT | ACCEPT WITH CHANGES | REJECT Rationale: Date: ``` Append to `.claude/octo/run/events.jsonl`: `{"ts":"","type":"decision","id":"D","question":"","ruling":""}`. Initialize `.claude/octo/run/decisions.md` (empty header) before the first milestone starts so the file is always present and appendable. ## Phase 3 β€” Milestone loop **Decompose** the mission into demoable milestones β€” each must produce a runnable, observable artifact that the verifier can exercise. Write `.claude/octo/run/board.md` (a markdown status table: `| ID | Title | Status |`) and update `.claude/octo/run/state.json` with the full milestone list, each at status `PENDING`. Milestones run sequentially by default β€” each builds on the last. Exception: when the architect marks milestones in the board as explicitly independent (disjoint file sets AND no demo dependency between them), the consilium may approve running those milestones as parallel build lanes. **Sync rule**: `board.md` and `state.json` must reflect the same status for every milestone at every transition. Write order: state.json first, then board.md. On resume, if the two disagree, state.json is authoritative β€” rewrite board.md from it and log a journal event. If state.json is missing while board.md exists, that is corrupt state: halt and report. For each milestone, in sequence: ### 3a β€” Start the milestone Set the milestone to `IN_PROGRESS` in both `board.md` and `.claude/octo/run/state.json`. Append to `.claude/octo/run/events.jsonl`: `{"ts":"","type":"milestone","id":"","title":"","status":"IN_PROGRESS"}`. ### 3b β€” Build inner loop Run `/octo:build` Steps 3–5 for this milestone's scope β€” implement with paired tests, targeted test loop (max 5 cycles), and review until clean (max 3 iterations). The unattended rule, residuals policy, and terminal blocked-event protocol from the build skill apply in full here; do not restate that detail, apply it; and suppress build's own `octo build` notify and blocked event on that path β€” studio emits its own notifications and events with the `octo studio` label. Any new ambiguity during this loop is resolved by the most reversible option (recorded as an `{"type": "assumption", "label": "SAFE|RISKY", ...}` event in `.claude/octo/run/events.jsonl`), or escalated to the consilium if the consequence is hard to reverse β€” never by asking the client. RISKY + hard-to-reverse goes to consilium instead. All recorded assumptions surface in the delivery report. At dispatch time, write each lane to `.claude/octo/run/state.json` (agent, task, started=now). After each completed batch, clear and rewrite lanes in `.claude/octo/run/state.json` and append to `.claude/octo/run/events.jsonl`: `{"ts":"<ISO>","type":"batch","milestone":"<id>","tasks":["<task-id>",...],"status":"done|partial"}`. If the inner loop exits blocked (tests red after 5 cycles, or HIGH/CRITICAL review residuals unresolved): proceed to Step 3c with a `FAIL` signal rather than halting the entire run. Inner-loop blocked exits emit no notify and no blocked event β€” they become the FAIL signal to 3c; only run-terminal blocks use the Shared Conventions notify. ### 3c β€” Verify, re-plan, or park Dispatch the **verifier** against the milestone's demo criteria. On `PASS`: 1. `git commit` all milestone work: `type(scope): <milestone title>`. 2. Set status `VERIFIED` in both `board.md` and `.claude/octo/run/state.json`. 3. `bash "$OCTO_ROOT/scripts/notify.sh" "octo studio" "milestone verified: <title>"`. 4. Append: `{"ts":"<ISO>","type":"milestone","id":"<id>","title":"<title>","status":"VERIFIED"}` to `.claude/octo/run/events.jsonl`. 5. Advance to the next milestone. On `FAIL`, `PARTIAL`, or a blocked inner loop: convene the consilium to decide whether and how to re-plan. If the ruling is `ACCEPT` or `ACCEPT WITH CHANGES`, apply the re-plan and restart from Step 3b β€” **maximum 2 re-plans per milestone total**. After 2 failed re-plans, or on a consilium `REJECT`: 1. Set status `PARKED` in both `board.md` and `.claude/octo/run/state.json`. 2. Append a decisions.md entry (D\<n\>) capturing the question, ruling, and reason for parking. 3. `bash "$OCTO_ROOT/scripts/notify.sh" "octo studio" "milestone parked: <title>"`. 4. Append: `{"ts":"<ISO>","type":"milestone","id":"<id>","title":"<title>","status":"PARKED"}` to `.claude/octo/run/events.jsonl`. 5. Continue to the next milestone β€” parked milestones appear in the delivery report. ## Phase 4 β€” Resume & atomicity When invoked with `--resume`: 1. Read `.claude/octo/run/contract.md`, `.claude/octo/run/board.md`, `.claude/octo/run/decisions.md`, and `.claude/octo/run/state.json`. 2. If any file is **missing or malformed**: halt immediately. Report exactly which file failed and why β€” this is the one allowed post-contract contact with the client. Do no work until the client resolves the state corruption. 3. Never re-interview. The contract file is the sole source of mission truth. 4. Find the first milestone with status `IN_PROGRESS`. Revert any uncommitted changes in that milestone's scope to the last git commit, then restart from Step 3b. Never resume from half-written files. 5. If no `IN_PROGRESS` milestone exists, continue from the first `PENDING` milestone. 6. If no milestone is `IN_PROGRESS` or `PENDING` and no delivery report exists, proceed directly to Phase 5 (delivery). Append to `.claude/octo/run/events.jsonl`: `{"ts":"<ISO>","type":"resume","last_phase":"<phase from state.json>"}`. ## Phase 5 β€” Delivery When all milestones are `VERIFIED` or `PARKED`: If ALL milestones are `PARKED`, skip the verifier and go straight to the INCOMPLETE report (the INCOMPLETE path's notify applies here too). 1. Dispatch the **verifier** against the contract's Acceptance Criteria in full (not per-milestone). 2. On acceptance pass, produce the delivery report. Write the full report to `.claude/octo/reports/YYYY-MM-DD-studio-<slug>.md` (sections: acceptance-criteria checklist, What was built, How to run it, Decision minutes, Parked items, Recorded assumptions, Known limitations); share the path in chat. **Chat output** β€” in chat, show only: - Acceptance-criteria checklist (βœ…/❌ per criterion from the contract). - **How to run it** β€” exact commands from the project's CLAUDE.md or detected conventions. - **Parked items** β€” title and reason, one line each. Full detail (decision minutes, recorded assumptions, known limitations) is in the report file. End the chat output with a **Try it** block produced from verifier evidence: the exact command(s) the user can run to see the result working, plus the verifier's observed output (one–two lines). No delivery without a try-it. Then: `bash "$OCTO_ROOT/scripts/notify.sh" "octo studio" "delivery ready: <mission>"`; append `{"ts":"<ISO>","type":"delivery","mission":"<mission>","milestones_verified":<N>,"milestones_parked":<N>}` to `.claude/octo/run/events.jsonl`. On acceptance fail: produce the same delivery report but headline it **INCOMPLETE** β€” what was built, which acceptance criteria are unmet and why, parked milestones, recommended next runs. `bash "$OCTO_ROOT/scripts/notify.sh" "octo studio" "delivery incomplete: <mission>"`. Never present an incomplete run as delivered. The client reviews the delivery report and either accepts or files change requests. Change requests become a **new, smaller studio run** β€” the current run is closed as-is. --- ## Shared Conventions - Commits: conventional format `type(scope): brief description` β€” no AI attribution, no `Co-Authored-By` lines of any kind. - Never push directly to protected branches (protected branches β€” see the octo guard's list). - Never use `--no-verify` or force-push. - Parallel-first: dispatches that do not consume each other's output MUST go in a single message. Dispatching sequentially what could run concurrently is a defect, not a style choice. Cap β‰ˆ10 concurrent lanes; more work than lanes β†’ batch waves. - On any blocked event: `bash "$OCTO_ROOT/scripts/notify.sh" "octo studio" "blocked: <reason>"`, overwrite `.claude/octo/run/state.json` with the current phase, append `{"ts":"<ISO>","type":"blocked","reason":"<reason>"}` to `.claude/octo/run/events.jsonl`, and report. - Reader-first output: lead with the outcome in one sentence; keep the visible reply short and dev-readable β€” only what changes the reader's next action. Full detail (complete reports, evidence, logs) goes to a file under `.claude/octo/reports/YYYY-MM-DD-<skill>-<slug>.md` with the path given in chat β€” never dumped into the conversation.