Add /supervise skill: MiniMax supervisor loop with tick/report crons
This commit is contained in:
@@ -20,6 +20,7 @@ custom-claude-skills/
|
|||||||
├── linter/SKILL.md # Format/lint audit and execution
|
├── linter/SKILL.md # Format/lint audit and execution
|
||||||
├── log/SKILL.md # End-of-session logging
|
├── log/SKILL.md # End-of-session logging
|
||||||
├── orchestrate/SKILL.md # Container agent dispatch with git worktrees
|
├── orchestrate/SKILL.md # Container agent dispatch with git worktrees
|
||||||
|
├── supervise/SKILL.md # MiniMax supervisor loop (tick/report crons)
|
||||||
├── reflect/SKILL.md # Milestone reflection
|
├── reflect/SKILL.md # Milestone reflection
|
||||||
├── reflect-logs/SKILL.md # Process logs into memory
|
├── reflect-logs/SKILL.md # Process logs into memory
|
||||||
├── review-plan/SKILL.md # Review plan against best practices
|
├── review-plan/SKILL.md # Review plan against best practices
|
||||||
|
|||||||
@@ -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 |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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
|
## Adding a New Skill
|
||||||
|
|||||||
183
skills/supervise/SKILL.md
Normal file
183
skills/supervise/SKILL.md
Normal 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.
|
||||||
Reference in New Issue
Block a user