Add /supervise skill: MiniMax supervisor loop with tick/report crons

This commit is contained in:
Paul O'Reilly
2026-10-01 19:49:46 +13:00
parent 83882f1be8
commit 9e6cde351e
3 changed files with 185 additions and 0 deletions

View File

@@ -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

View File

@@ -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 <task>` | 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 <project>` | 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

183
skills/supervise/SKILL.md Normal file
View File

@@ -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 *)
---
<command-name>supervise</command-name>
# /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: <ISO time> # session start; report counts are relative to this
status: running|stopped
focus: <free text and/or item UUIDs>
push: off|on
suite: <command that runs the project's full test suite>
cron_tick: <job id>
cron_report: <job id>
## 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 <uuid>` 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 `<!-- supervisor:begin -->`, append:
```
<!-- supervisor:begin -->
## 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/*`).
<!-- supervisor:end -->
```
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 <uuid> --slug <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/<slug>`), 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 <uuid> --slug <short> --gate "<suite>"` (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 <text>` → 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.