From 9e6cde351ec0e51251466a5d3e1d34c5ddad61b5 Mon Sep 17 00:00:00 2001 From: Paul O'Reilly Date: Thu, 1 Oct 2026 19:49:46 +1300 Subject: [PATCH] Add /supervise skill: MiniMax supervisor loop with tick/report crons --- CLAUDE.md | 1 + README.md | 1 + skills/supervise/SKILL.md | 183 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 skills/supervise/SKILL.md diff --git a/CLAUDE.md b/CLAUDE.md index 96744dd..e8b4718 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -20,6 +20,7 @@ custom-claude-skills/ ├── linter/SKILL.md # Format/lint audit and execution ├── log/SKILL.md # End-of-session logging ├── orchestrate/SKILL.md # Container agent dispatch with git worktrees + ├── supervise/SKILL.md # MiniMax supervisor loop (tick/report crons) ├── reflect/SKILL.md # Milestone reflection ├── reflect-logs/SKILL.md # Process logs into memory ├── review-plan/SKILL.md # Review plan against best practices diff --git a/README.md b/README.md index 2d068ff..090c5ba 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ The install script creates symlinks from `~/.claude/skills/` to this repo, makin | housekeeping | `/housekeeping` | Cross-project health check: git status, unreflected logs, skill validation, pipeline recommendations | | decompose | `/decompose ` | Break a task into subtasks with dependency graph. Writes `.agent-tasks.json` for container agent orchestration. | | orchestrate | `/orchestrate` | Check task state, launch container agents in git worktrees. Use `/loop 2m /orchestrate` for auto-polling. | +| supervise | `/supervise` | Supervisor mode: 15-min tick dispatches/reaps MiniMax `mm-worktree-task` units, 30-min progress report. State in gitignored `.supervisor/`. | | spawn-session | `/spawn-session ` | Spawn a new detached tmux Claude Code session with Remote Control, named after the project (wraps `claude-tmux`). Attach later via `tmux attach` over VPN or drive from the Claude app. | ## Adding a New Skill diff --git a/skills/supervise/SKILL.md b/skills/supervise/SKILL.md new file mode 100644 index 0000000..88b148c --- /dev/null +++ b/skills/supervise/SKILL.md @@ -0,0 +1,183 @@ +--- +name: supervise +description: > + Run this session as a supervisor over MiniMax subagents: every 15 min a tick reaps + finished units, files new bugs, and dispatches mm-worktree-task units for the focus; + every 30 min a one-paragraph progress report. Keeps state in a gitignored .supervisor/ + folder and records itself in the project's CLAUDE.md. Pass a focus as arguments, or + run bare to pick one from the planner. Also: tick, report, focus, push, status, stop. +user_invocable: true +allowed-tools: Read, Write, Edit, Agent, SendMessage, ToolSearch, AskUserQuestion, Bash(date *), Bash(test *), Bash(ls *), Bash(cat *), Bash(mkdir *), Bash(python3 *), Bash(git status*), Bash(git rev-parse *), Bash(git log *), Bash(git diff *), Bash(git add *), Bash(git commit *), Bash(git merge *), Bash(git worktree *), Bash(git branch *), Bash(git -C *), Bash(mm-worktree-task *), Bash(review-minimax-run *), Bash(gac *) +--- + +supervise + +# /supervise Skill + +You are the **supervisor**. You preserve context, exercise judgement, and schedule +work. MiniMax subagents (via `mm-worktree-task`) do the implementation; you never +write code a MiniMax unit should write. There is no cap on units in flight — but at +most one per work item. + +Requires a planner-backed project (a `cp-cli planner` reference in its CLAUDE.md), +`mm-worktree-task` in `~/sbin`, and the MiniMax profile. Stop and say so if any is missing. + +## Pre-gathered context + +### Date +!`date +%Y-%m-%dT%H:%M:%S` + +### Repo +!`git rev-parse --show-toplevel` +!`git rev-parse --abbrev-ref HEAD` + +### Supervisor state (if any) +!`cat .supervisor/state.md 2>/dev/null || echo NO_STATE` + +## Arguments + +`$ARGUMENTS` — first word selects the mode: + +| Mode | Meaning | +|---|---| +| *(empty)* | `start`, focus chosen via the picker | +| `start [focus text]` or any other text | start with that focus | +| `tick` | one 15-min supervision pass (fired by cron) | +| `report` | one 30-min progress report (fired by cron) | +| `focus [text]` | change the focus (picker if no text); loops untouched | +| `push on\|off` | allow/forbid pushing merged work (default off) | +| `status` | print state + cron list, change nothing | +| `stop` | delete both crons, mark state stopped | + +## State: `.supervisor/state.md` + +Created at start, edited in place. The cron prompts carry no state, so this file is +the memory — re-read it at the top of every mode. Shape: + +``` +# Supervisor state +started: # session start; report counts are relative to this +status: running|stopped +focus: +push: off|on +suite: +cron_tick: +cron_report: + +## Ledger (every bug/feature item the supervisor has touched this session) +| item (uuid8) | title | kind | stage | notes | +stages: queued → in-flight → collected → gated → merged → closed | failed | blocked + +## In-flight +| item | slug | branch | worktree | dispatched | attempt | +``` + +Counts for reports come from the ledger, with "resolved" **verified against the +planner** (`items get ` state), not from the ledger's own claim. + +## Mode: start + +1. **State exists and `status: running`** → this is a resume. Keep focus and ledger; + go to step 5 (re-create crons only if `CronList` lacks them; the old ids are dead + after a restart). If `$ARGUMENTS` carries new focus text, treat it as `focus`. +2. **Bootstrap `.supervisor/`**: `mkdir -p .supervisor`; write `state.md` from the + shape above with `started` = now, `push: off`. +3. **Gitignore**: Read `.gitignore` (create it if absent). If no line equals + `.supervisor/` or `.supervisor`, append `.supervisor/`. Never use shell `grep` + for this check (exit 1 on no match) — Read and Edit. +4. **Amend the project CLAUDE.md** (repo root; create a minimal one if absent). + If it does not already contain ``, append: + ``` + + ## Supervisor (`/supervise`) + + This project may be worked under the `/supervise` skill: one session supervises + MiniMax units dispatched with `mm-worktree-task`, on 15-min tick and 30-min report + crons. Its working state lives in `.supervisor/` (gitignored — never commit it, + never hand-edit `state.md` while a supervisor is running). If `.supervisor/state.md` + says `status: running`, another session is supervising: do not dispatch units for + the same items or touch their worktrees (`.claude/worktrees/mm-*`, branches `mm/*`). + + ``` + Do not commit this edit; tell the user it is an uncommitted change to CLAUDE.md. +5. **Focus**: if given, use it. Otherwise run the picker (see Mode: focus). +6. **Suite command**: infer from the project's CLAUDE.md (test command). If unclear, + ask the user once. Stored in `state.md` as `suite:`. +7. **Crons**: load the tools with `ToolSearch select:CronCreate,CronList,CronDelete`, + then `CronCreate` two recurring jobs (off-minute schedules on purpose): + - `7,22,37,52 * * * *` → prompt `/supervise tick` + - `14,44 * * * *` → prompt `/supervise report` + Record both ids in `state.md`. Tell the user: crons are session-only and expire + after 7 days; after a restart run `/supervise` again to resume from state. +8. Run **one tick immediately** so work starts now, then say in one line what was + dispatched and how to change focus / stop. + +## Mode: tick (every 15 min) + +Re-read `state.md`. If `status: stopped`, do nothing and say so. Then, in order: + +1. **Reap.** For each In-flight row run `mm-worktree-task --slug --collect`. + - Still running → leave it. + - Finished → adjudicate. Never trust the agent's own "green": re-run `suite` in the + worktree **after the unit's last commit**; require a real-process test wherever + the code shells out; check any wire-shape change against the live server model; + inspect the diff. Optionally pre-filter with `/review-minimax` on large diffs. + Pass → merge into the base branch locally (`git merge --no-ff mm/`), re-run + `suite` on the merged tree, update the item in the planner, ledger → `merged`/`closed`. + Fail → ledger `failed`, re-dispatch once with the failure appended as `--focus` + (attempt 2); a second failure → `blocked`, surfaced in the next report. + - A unit that hit a permission prompt or asked for one: mark `blocked`. Never + work around it and never tell a unit to. + - Push only if `push: on`, after the SSH pre-flight in the root CLAUDE.md. Otherwise + leave merged work local and count it in the report as "merged, unpushed". +2. **Discover.** If reaped units or your own reading surfaced new bugs, file each as a + planner item (`items create`) and add it to the ledger as `queued`. New bugs join + the current work automatically; do not ask. +3. **Select.** Candidate items = unresolved items matching `focus` (planner `items list` + with the right label/state, plus any UUIDs named in focus), minus items already + In-flight, `blocked`, or `closed`. Skip an item whose likely files overlap an + in-flight unit — queue it for the next tick instead of creating merge conflicts. +4. **Dispatch.** For each selected item: + `mm-worktree-task --slug --gate ""` (detached; it returns at + once). Add an In-flight row. If nothing was in flight and nothing is dispatchable, + say "nothing to dispatch" and why (no open items vs all blocked). +5. **Write state.md**, then output **at most 4 lines**: reaped / dispatched / in-flight + count / anything needing the user. No narration. + +## Mode: report (every 30 min) + +Re-read `state.md`, refresh each ledger item's planner state, then output a very brief +summary and nothing else: + +- Bugs worked this session: N total; resolved: M; in flight: K; blocked: B + (merged-but-unpushed counted separately if `push: off`). +- Progress on the focus feature/epic: percent or `done/total` child items from the + planner, plus one phrase on the next blocker. + +## Mode: focus + +`focus ` → set `focus:` in `state.md`, done; the next tick uses it. With no text, +run the **picker**: query the planner for non-closed bugs and in-progress +features/epics (try `scripts/get_context` if the project has it; else +`items list --label bug` and `--state` for open/in-progress; labels come from the +project's planner schema). `AskUserQuestion`, multiSelect, header "Focus", up to 4 +options — e.g. "All open bugs (N)", the top feature/epic by activity, a cluster of +related bugs — each description naming counts. "Other" covers free text. Join the +answers into the `focus:` line. + +## Mode: push / status / stop + +- `push on|off` → edit `push:`. Turning it on: remind that pushes may trigger deploys. +- `status` → print state.md and `CronList`; change nothing. +- `stop` → `CronDelete` both ids, set `status: stopped`, print final totals as in + `report`, and list any In-flight worktrees still running. Leave `.supervisor/` and + the CLAUDE.md section in place. + +## Rules + +- Supervisor judges and schedules; MiniMax implements. No code-writing in-session + except a trivial fix to a merge conflict. +- One unit per item. Unlimited items in parallel. +- Every claimed-green result is re-run by you after the unit's last commit. +- Never put secrets in `.supervisor/` or in prompts to units. +- Keep tick and report output terse — they fire unattended and land in the transcript.