squadrant 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +268 -0
- package/dist/index.js +9154 -0
- package/dist/index.js.map +1 -0
- package/dist/squadrantd.js +3928 -0
- package/dist/squadrantd.js.map +1 -0
- package/package.json +68 -0
- package/plugin/.claude-plugin/plugin.json +5 -0
- package/plugin/skills/add-pick-crew-rule/SKILL.md +88 -0
- package/plugin/skills/captain-ops/SKILL.md +390 -0
- package/plugin/skills/command-ops/SKILL.md +157 -0
- package/plugin/skills/config-doctor/SKILL.md +46 -0
- package/plugin/skills/daily-log/SKILL.md +44 -0
- package/plugin/skills/karpathy-principles/SKILL.md +82 -0
- package/plugin/skills/set-effort/SKILL.md +59 -0
- package/plugin/skills/side-session/SKILL.md +113 -0
- package/plugin/skills/squadrant-effort/SKILL.md +8 -0
- package/plugin/skills/squadrant-new-project/SKILL.md +67 -0
- package/plugin/skills/squadrant-register-project/SKILL.md +60 -0
- package/plugin/skills/where-i-am/SKILL.md +102 -0
- package/plugin/skills/wiki-ops/SKILL.md +96 -0
- package/plugin/skills/wim/SKILL.md +8 -0
- package/scripts/acceptance-interactive-codex.sh +56 -0
- package/scripts/capture-skill.sh +32 -0
- package/scripts/claude-iv-smoke.mjs +133 -0
- package/scripts/fix-skill.sh +39 -0
- package/scripts/gen-codex-types.sh +18 -0
- package/scripts/mailbox-injector-smoke.mjs +124 -0
- package/scripts/mark-learning-useful.sh +22 -0
- package/scripts/migrate-to-squadrant.sh +158 -0
- package/scripts/notify-relay-placement-smoke.mjs +59 -0
- package/scripts/read-handoff.sh +22 -0
- package/scripts/record-learning.sh +31 -0
- package/scripts/record-side-handoff.sh +32 -0
- package/scripts/smoke-push-notify.mjs +147 -0
- package/scripts/spawn-crew-pane.sh +17 -0
- package/scripts/spawn-workspace.sh +206 -0
- package/scripts/wiki-ingest.sh +121 -0
- package/scripts/wiki-log.sh +20 -0
- package/scripts/wiki-query.sh +36 -0
- package/scripts/write-handoff.sh +31 -0
- package/templates/captain.claude.md +44 -0
- package/templates/captain.generic.md +45 -0
- package/templates/command.claude.md +32 -0
- package/templates/crew.claude.md +64 -0
- package/templates/crew.generic.md +51 -0
- package/templates/crew.opencode.md +51 -0
- package/templates/learnings.claude.md +40 -0
- package/templates/side.debug.claude.md +78 -0
- package/templates/side.research.claude.md +63 -0
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "squadrant",
|
|
3
|
+
"packageManager": "pnpm@10.30.3",
|
|
4
|
+
"version": "0.9.0",
|
|
5
|
+
"description": "Multi-project orchestration for your coding agents (Claude, Codex, opencode, Gemini)",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"squadrant": "./dist/index.js",
|
|
9
|
+
"squad": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist/",
|
|
13
|
+
"plugin/",
|
|
14
|
+
"scripts/",
|
|
15
|
+
"templates/"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc -b --force packages/shared packages/core packages/agents packages/workspaces packages/web packages/cli && tsup",
|
|
19
|
+
"dev": "tsup --watch",
|
|
20
|
+
"test": "vitest",
|
|
21
|
+
"lint": "tsc --noEmit",
|
|
22
|
+
"codex:gen-types": "bash scripts/gen-codex-types.sh"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"squadrant",
|
|
26
|
+
"multi-agent",
|
|
27
|
+
"agent",
|
|
28
|
+
"orchestration",
|
|
29
|
+
"cmux",
|
|
30
|
+
"obsidian"
|
|
31
|
+
],
|
|
32
|
+
"author": "",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"chalk": "^5.4.0",
|
|
39
|
+
"commander": "^13.0.0",
|
|
40
|
+
"gray-matter": "^4.0.3",
|
|
41
|
+
"jsonc-parser": "^3.3.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@squadrant/cli": "workspace:*",
|
|
45
|
+
"@squadrant/core": "workspace:*",
|
|
46
|
+
"@squadrant/agents": "workspace:*",
|
|
47
|
+
"@squadrant/shared": "workspace:*",
|
|
48
|
+
"@squadrant/workspaces": "workspace:*",
|
|
49
|
+
"@squadrant/web": "workspace:*",
|
|
50
|
+
"@types/node": "^22.0.0",
|
|
51
|
+
"tsup": "^8.5.1",
|
|
52
|
+
"typescript": "^5.7.0",
|
|
53
|
+
"vitest": "^3.0.0"
|
|
54
|
+
},
|
|
55
|
+
"pnpm": {
|
|
56
|
+
"onlyBuiltDependencies": [
|
|
57
|
+
"esbuild"
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
"repository": {
|
|
61
|
+
"type": "git",
|
|
62
|
+
"url": "git+https://github.com/tu11aa/squadrant.git"
|
|
63
|
+
},
|
|
64
|
+
"homepage": "https://github.com/tu11aa/squadrant#readme",
|
|
65
|
+
"bugs": {
|
|
66
|
+
"url": "https://github.com/tu11aa/squadrant/issues"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: add-pick-crew-rule
|
|
3
|
+
description: Add, edit, or remove a leveled crew routing rule in config.json without hand-editing JSON. Routing rules map task-text keywords to a tier → {agent, model}.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Manage Crew Routing Rules
|
|
7
|
+
|
|
8
|
+
Crew routing rules live in `defaults.crewRouting.rules` inside `~/.config/squadrant/config.json`.
|
|
9
|
+
Each rule has the shape:
|
|
10
|
+
|
|
11
|
+
```jsonc
|
|
12
|
+
{
|
|
13
|
+
"tier": "<label>", // human label, e.g. "extreme" / "hard" / "daily"
|
|
14
|
+
"match": "<regex>", // case-insensitive regex tested against the task text
|
|
15
|
+
"agent": "claude|codex|gemini|opencode",
|
|
16
|
+
"model": "opus|sonnet" // omit for codex/opencode (they use their own defaults)
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Rules are evaluated in order; the **first match wins**.
|
|
21
|
+
|
|
22
|
+
## Adding a rule
|
|
23
|
+
|
|
24
|
+
1. Read the current config:
|
|
25
|
+
```bash
|
|
26
|
+
cat ~/.config/squadrant/config.json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
2. Identify the `defaults.crewRouting.rules` array. If it is absent, add it.
|
|
30
|
+
|
|
31
|
+
3. Build the new rule object. Validate:
|
|
32
|
+
- `tier` is a non-empty string
|
|
33
|
+
- `match` is a valid regex (test it mentally against a sample task string)
|
|
34
|
+
- `agent` is one of `claude`, `codex`, `gemini`, `opencode`
|
|
35
|
+
- `model` is only set for claude rules (`opus` or `sonnet`); omit for other agents
|
|
36
|
+
|
|
37
|
+
4. Insert the rule at the correct position — **rules are evaluated in order**.
|
|
38
|
+
Higher-priority / more specific tiers (e.g. "extreme") belong before broader ones
|
|
39
|
+
(e.g. "hard"). Append low-priority catch-alls last.
|
|
40
|
+
|
|
41
|
+
5. Write the updated config back via the existing save path:
|
|
42
|
+
```typescript
|
|
43
|
+
// The saveConfig helper in src/config.ts handles atomic write + newline.
|
|
44
|
+
// If editing the live file directly, use JSON.stringify(config, null, 2) + "\n".
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
6. Verify the rule fires as expected:
|
|
48
|
+
```bash
|
|
49
|
+
# Quick smoke-test (no live crew spawned):
|
|
50
|
+
node -e "
|
|
51
|
+
const {loadConfig} = require(process.env.HOME + '/.config/squadrant/node_modules/...');
|
|
52
|
+
// or just log the matching rule manually
|
|
53
|
+
const rules = require(process.env.HOME + '/.config/squadrant/config.json')
|
|
54
|
+
.defaults?.crewRouting?.rules ?? [];
|
|
55
|
+
const task = 'YOUR TEST TASK HERE';
|
|
56
|
+
const hit = rules.find(r => new RegExp(r.match,'i').test(task));
|
|
57
|
+
console.log(hit ?? 'no match');
|
|
58
|
+
"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Editing an existing rule
|
|
62
|
+
|
|
63
|
+
Read → locate the rule by `tier` or `match` → update the field(s) → write back.
|
|
64
|
+
|
|
65
|
+
## Removing a rule
|
|
66
|
+
|
|
67
|
+
Read → filter out the rule by `tier` or `match` → write back.
|
|
68
|
+
|
|
69
|
+
## Precedence reminder
|
|
70
|
+
|
|
71
|
+
- Explicit `--agent` / `--model` on `squadrant crew spawn` **always** override routing.
|
|
72
|
+
- If no rule matches, the spawn falls through to `defaults.roles.crew` behavior (unchanged from pre-routing behavior).
|
|
73
|
+
|
|
74
|
+
## Example rules
|
|
75
|
+
|
|
76
|
+
```jsonc
|
|
77
|
+
// Route deep-reasoning work to the strongest model
|
|
78
|
+
{ "tier": "extreme", "match": "redesign|architect|rewrite|from scratch|deep reasoning", "agent": "claude", "model": "opus" }
|
|
79
|
+
|
|
80
|
+
// Route standard feature/refactor work to a faster model
|
|
81
|
+
{ "tier": "hard", "match": "refactor|migrate|implement|feature|daemon|control-plane", "agent": "claude", "model": "sonnet" }
|
|
82
|
+
|
|
83
|
+
// Route mobile tasks to codex (no model — uses codex default)
|
|
84
|
+
{ "tier": "mobile", "match": "mobile|ios|swift|android|kotlin|react native", "agent": "codex" }
|
|
85
|
+
|
|
86
|
+
// Route trivial edits to opencode (cheapest path)
|
|
87
|
+
{ "tier": "daily", "match": "typo|rename|bump|docs|comment|lint|format", "agent": "opencode" }
|
|
88
|
+
```
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: captain-ops
|
|
3
|
+
description: Complete captain playbook — session startup, crew spawning, status writing, group awareness, and learnings. Use this skill at session start and reference it throughout.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Captain Operations
|
|
7
|
+
|
|
8
|
+
## Session Startup
|
|
9
|
+
|
|
10
|
+
1. Read `~/.config/squadrant/config.json` — match your current working directory. Note your `spokeVault`, `group`, `groupRole`, and `maxCrew` (default: 5).
|
|
11
|
+
2. **Check for handoff from previous session:**
|
|
12
|
+
```bash
|
|
13
|
+
~/.config/squadrant/scripts/read-handoff.sh "{spokeVaultPath}"
|
|
14
|
+
```
|
|
15
|
+
If a handoff exists (`"exists"` is not false), read the context carefully:
|
|
16
|
+
- `currentState` — what was happening when the last session ended
|
|
17
|
+
- `openBranches` — branches with uncommitted/unmerged work
|
|
18
|
+
- `nextSteps` — what the previous session planned to do next
|
|
19
|
+
- `blockedItems` — unresolved blockers
|
|
20
|
+
- `decisions` — important decisions already made (don't re-decide)
|
|
21
|
+
The handoff file is auto-deleted after reading. Use this as your primary context source.
|
|
22
|
+
3. Search **claude-mem** (`mem-search` skill) for your project name to get additional continuity.
|
|
23
|
+
4. Check `{spokeVault}/daily-logs/` — read the most recent log if one exists.
|
|
24
|
+
5. Check `{spokeVault}/learnings/` — **selectively** load relevant learnings (see "Selective Loading" section below). Do NOT read all files — grep by task keywords and tags.
|
|
25
|
+
6. Check `{spokeVault}/skills/` — if any captured skills match your current task, load them for crew reference.
|
|
26
|
+
7. Check `{spokeVault}/wiki/` — query wiki for keywords related to your current task:
|
|
27
|
+
```bash
|
|
28
|
+
~/.config/squadrant/scripts/wiki-query.sh "{spokeVaultPath}" "{relevant-keyword}" --titles-only
|
|
29
|
+
```
|
|
30
|
+
If relevant pages exist, read them for context before starting work.
|
|
31
|
+
8. Crew lifecycle events (done / blocked / idle) are delivered to your captain pane automatically by the squadrant daemon via daemon-direct cmux delivery (#332). No relay setup required.
|
|
32
|
+
|
|
33
|
+
9. (Opt-in) Status writes are not required on every event. Only run `~/.config/squadrant/scripts/write-status.sh` when you have a meaningful note worth recording (a blocker, a deliberate "starting work on X", etc.) — not on a schedule.
|
|
34
|
+
|
|
35
|
+
## Crew Setup
|
|
36
|
+
|
|
37
|
+
You do NOT create an Agent Team. You spawn each crew session on demand as a **new tab** in your workspace via `squadrant crew spawn` (use `--direction right|down|...` to split into a pane instead). The surface is a fresh CLI session with the crew template loaded as system prompt — disposable, restartable, runtime-agnostic.
|
|
38
|
+
|
|
39
|
+
You don't need to create or persist anything up front. Each `squadrant crew spawn` call creates a new surface.
|
|
40
|
+
|
|
41
|
+
## Task Decomposition with Task Master
|
|
42
|
+
|
|
43
|
+
When you receive a **PRD, large feature request, or multi-step scope** from command, use **Task Master MCP** to decompose it before spawning crew.
|
|
44
|
+
|
|
45
|
+
### If a PRD file exists in the project:
|
|
46
|
+
```
|
|
47
|
+
mcp__task-master-ai__parse_prd(input: ".taskmaster/docs/prd.txt", projectRoot: "{projectPath}")
|
|
48
|
+
```
|
|
49
|
+
This generates `tasks.json` with structured tasks, dependencies, and complexity scores.
|
|
50
|
+
|
|
51
|
+
### Query tasks:
|
|
52
|
+
```
|
|
53
|
+
mcp__task-master-ai__get_tasks(projectRoot: "{projectPath}") # List all tasks
|
|
54
|
+
mcp__task-master-ai__next_task(projectRoot: "{projectPath}") # Get highest-priority unblocked task
|
|
55
|
+
mcp__task-master-ai__get_task(id: "1", projectRoot: "{projectPath}") # Get specific task details
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Update task status as crew works:
|
|
59
|
+
```
|
|
60
|
+
mcp__task-master-ai__set_task_status(id: "1", status: "in-progress", projectRoot: "{projectPath}")
|
|
61
|
+
mcp__task-master-ai__set_task_status(id: "1", status: "done", projectRoot: "{projectPath}")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Expand complex tasks into subtasks:
|
|
65
|
+
```
|
|
66
|
+
mcp__task-master-ai__expand_task(id: "1", projectRoot: "{projectPath}")
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Workflow:
|
|
70
|
+
1. Receive scope from command → **parse PRD** (or manually create tasks if no PRD file)
|
|
71
|
+
2. **get_tasks** to see the full dependency graph
|
|
72
|
+
3. **next_task** to find what's unblocked and highest priority
|
|
73
|
+
4. Spawn crew for that task
|
|
74
|
+
5. When crew finishes → **set_task_status** to "done" → **next_task** for the next one
|
|
75
|
+
6. Repeat until all tasks are done
|
|
76
|
+
|
|
77
|
+
**Note:** Task Master requires an AI provider API key (ANTHROPIC_API_KEY) for `parse_prd` and `expand_task`. If unavailable, create tasks manually using the project's task breakdown file (e.g., `pact-network-tasks.md`) and use Task Master only for status tracking.
|
|
78
|
+
|
|
79
|
+
## Spawning Crew
|
|
80
|
+
|
|
81
|
+
**You MUST spawn a crew session for ANY coding task** — even a one-line change. You are a coordinator. You plan, delegate, review, and merge. You do NOT write code yourself.
|
|
82
|
+
|
|
83
|
+
A crew is an **interactive Claude sub-session** running in a tab inside your workspace, named `crew-1`, `crew-2`, … (or a name you pick). It stays idle between turns waiting for your next message — same model as a Claude Agent Team subagent.
|
|
84
|
+
|
|
85
|
+
### Spawn a NEW crew
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
squadrant crew spawn <project> "<task description>" \
|
|
89
|
+
[--name <name>] \
|
|
90
|
+
[--direction tab|right|left|up|down] \
|
|
91
|
+
[--agent claude|codex|gemini|opencode]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
What it does:
|
|
95
|
+
1. Opens a new **tab** in the captain workspace (use `--direction right|left|up|down` to split into a pane instead).
|
|
96
|
+
2. Names the tab `🔧 <project>:<name>` — `--name` is optional; auto-picks the next free `crew-N`.
|
|
97
|
+
3. Boots an interactive Claude session (no `-p`) with `crew.<agent>.md` loaded as system prompt.
|
|
98
|
+
4. Sends your task as the first turn. The crew works on it and then **stays idle** waiting for follow-ups.
|
|
99
|
+
|
|
100
|
+
### Send a FOLLOW-UP to an existing crew
|
|
101
|
+
|
|
102
|
+
DO NOT spawn a new crew for every turn — that's how you get tab pollution. Use `send`:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
squadrant crew send <project> <name> "<message>"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Inspect & shutdown
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
squadrant crew list <project> # see all live crews for the project
|
|
112
|
+
squadrant crew tasks <project> # compact task listing (use --json for verbose)
|
|
113
|
+
squadrant crew tasks <project> --state-only <id> # fast state check (prints one word)
|
|
114
|
+
squadrant crew read <project> <name> # read tail of a crew's screen (~40 lines)
|
|
115
|
+
squadrant crew read <project> <name> --full # entire scrollback (may be large)
|
|
116
|
+
squadrant crew read <project> <name> --lines 100 # custom tail length
|
|
117
|
+
squadrant crew close <project> <name> # shutdown the crew (closes its tab)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Examples
|
|
121
|
+
|
|
122
|
+
Spawn a fresh crew (auto-named `crew-1`):
|
|
123
|
+
```bash
|
|
124
|
+
squadrant crew spawn brove "Add preinstall hook to package.json. Branch: feat/preinstall."
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Named crew for a specific work track:
|
|
128
|
+
```bash
|
|
129
|
+
squadrant crew spawn brove "Refactor src/api/handlers.ts" --name api-refactor --agent codex
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Send a follow-up turn:
|
|
133
|
+
```bash
|
|
134
|
+
squadrant crew send brove crew-1 "Also wire that into the install script"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Open as a side-by-side pane when you want live preview:
|
|
138
|
+
```bash
|
|
139
|
+
squadrant crew spawn brove "Fix typo in README" --direction right
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Leveled crew routing
|
|
143
|
+
|
|
144
|
+
When you spawn a crew without an explicit `--agent` or `--model`, squadrant automatically
|
|
145
|
+
consults the routing rules in `defaults.crewRouting.rules` (config.json) and picks the
|
|
146
|
+
right tier for the task:
|
|
147
|
+
|
|
148
|
+
| Tier | Matches | Routes to |
|
|
149
|
+
|------|---------|-----------|
|
|
150
|
+
| extreme | redesign, architect, rewrite, from scratch | claude/opus |
|
|
151
|
+
| hard | refactor, migrate, implement, feature | claude/sonnet |
|
|
152
|
+
| mobile | mobile, ios, swift, android, kotlin | codex |
|
|
153
|
+
| daily | typo, rename, bump, docs, lint | opencode |
|
|
154
|
+
|
|
155
|
+
The chosen route is printed as a dim one-liner before the spawn completes, e.g.:
|
|
156
|
+
```
|
|
157
|
+
routed: tier=hard → claude/sonnet (rule: "refactor|migrate|implement|feature|daemon|control-plane")
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Override at any time** — explicit flags always win over routing:
|
|
161
|
+
```bash
|
|
162
|
+
squadrant crew spawn brove "refactor auth" --agent codex # forces codex despite "hard" tier
|
|
163
|
+
squadrant crew spawn brove "fix typo" --model opus # forces opus despite "daily" tier
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
To add, edit, or remove routing rules: use the `squadrant:add-pick-crew-rule` skill.
|
|
167
|
+
|
|
168
|
+
### Effort mode
|
|
169
|
+
|
|
170
|
+
Before spawning a crew, read `defaults.effort` from `~/.config/squadrant/config.json` (run `squadrant effort` to check). Apply the following bias to your crew agent/model choice:
|
|
171
|
+
|
|
172
|
+
| Mode | Directive |
|
|
173
|
+
|------|-----------|
|
|
174
|
+
| **max** | Tokens are plentiful. Prefer claude/opus for crew spawns; don't downshift for cost. |
|
|
175
|
+
| **balance** | Normal. Use default crew routing rules unchanged. (Absent field = balance.) |
|
|
176
|
+
| **low** | Conserve tokens. Prefer opencode/sonnet for crews; reserve opus for work that genuinely needs it. |
|
|
177
|
+
|
|
178
|
+
**Effort is crew-only.** Captain, command, and side roles are unaffected — keep them at their configured model regardless of effort.
|
|
179
|
+
|
|
180
|
+
**Effort is the weakest signal.** An explicit `--agent` / `--model` on a spawn always wins. Effort only nudges your default choice when nothing more specific applies.
|
|
181
|
+
|
|
182
|
+
To change the effort dial: `squadrant effort <max|balance|low>` or use the `squadrant:set-effort` skill.
|
|
183
|
+
|
|
184
|
+
### Rules
|
|
185
|
+
|
|
186
|
+
- **Reuse with `send` before spawning a new one.** Same task track, same crew. New track = new crew.
|
|
187
|
+
- **Close crews you're done with** (`squadrant crew close ...`) so they don't accumulate.
|
|
188
|
+
- Crews run in **isolated worktrees by default** (parallel-safe, branch per crew). Pass `--shared` only for tiny/one-off tasks that don't need branch isolation. Never hand-run `git worktree add` — `squadrant crew spawn` handles it.
|
|
189
|
+
- Do NOT edit source code yourself — always delegate to crew.
|
|
190
|
+
- Respect `maxCrew` — don't exceed the configured concurrent crew count.
|
|
191
|
+
- **For complex multi-step tasks** (3+ steps, multiple files), tell the crew to use GSD inside the task prompt: *"This is a complex task. Use `/gsd:plan-phase` and `/gsd:execute-phase` for wave-based execution with fresh context per step."*
|
|
192
|
+
- **For simple tasks**, don't mention GSD — the crew will handle it directly.
|
|
193
|
+
|
|
194
|
+
> Non-Claude agents (codex / gemini) currently still launch in print-mode (one-shot) rather than as interactive sessions; `send` won't reach them yet. Prefer Claude crews when you want multi-turn dialogue.
|
|
195
|
+
|
|
196
|
+
## Task Coordination
|
|
197
|
+
|
|
198
|
+
**HARD RULE: Do NOT poll crew screens in a loop.** Crew lifecycle events (idle / done / blocked) are delivered to your captain pane automatically by the squadrant daemon — trust the daemon signal. Polling loops hang indefinitely, exhaust context, and mask real blockers.
|
|
199
|
+
|
|
200
|
+
You don't have an Agent Team or `TaskCreate`/`TaskUpdate` tools — those were Claude-specific. When you need crew status:
|
|
201
|
+
1. **Wait for the daemon to notify you.** When a crew finishes, signals blocked, or goes idle, the daemon delivers the event to your captain pane via daemon-direct cmux delivery. This is the primary mechanism — do not replace it with polling.
|
|
202
|
+
2. `squadrant crew read <project> <name>` — **on-demand spot-check only** (a single read when you have a specific reason, e.g. reviewing a finished diff). Never in a loop, never with `until`.
|
|
203
|
+
3. `squadrant crew tasks <project>` — **on-demand** compact task listing; `--id <prefix>` to filter; `--state-only <id>` for a single-word state check.
|
|
204
|
+
4. `squadrant crew list <project>` — see all live crews and pick the right one.
|
|
205
|
+
5. Inspecting the crew tab visually in cmux when you want richer context (you have its surface ref from the spawn output).
|
|
206
|
+
6. Asking the user to check the dashboard if you need a cross-project view (see issue #44).
|
|
207
|
+
|
|
208
|
+
If you ever need a bounded check (not a loop), use a fixed counter (≤ 3 attempts with a sleep between), or watch the mailbox seq — never an unbounded `until` loop.
|
|
209
|
+
|
|
210
|
+
### Handling CREW IDLE
|
|
211
|
+
|
|
212
|
+
CREW IDLE is **ambiguous** — the watchdog did not detect a heartbeat, which can happen when:
|
|
213
|
+
- **(a)** The crew finished but never ran `squadrant crew signal done` (issue #278 — common for claude/opencode before the completion-protocol fix).
|
|
214
|
+
- **(b)** The crew is genuinely waiting for the captain (asked a question or needs a decision).
|
|
215
|
+
- **(c)** The crew is still mid-task and the idle pulse was transient.
|
|
216
|
+
|
|
217
|
+
On CREW IDLE, do a **single on-demand spot-check** (allowed — not a polling loop), then classify:
|
|
218
|
+
|
|
219
|
+
| Spot-check shows | Captain action |
|
|
220
|
+
|-----------------|----------------|
|
|
221
|
+
| Completed work (PR opened, commits pushed, results reported) but no CREW DONE | Treat as the #278 case — review; if good, terminalize (`merge` + `crew close`). If not actually done, **re-task**: send the next instruction via `crew send` (the #148 re-open flow). |
|
|
222
|
+
| Crew asked a question or is waiting for a decision | Respond via `crew send`. Do NOT terminalize — it will signal done after the next turn. |
|
|
223
|
+
| Still mid-task / transient idle | Leave it; wait for the next daemon event. |
|
|
224
|
+
|
|
225
|
+
**Do not re-send the original task** if the crew appears to have completed it — that triggers a duplicate run. Read the crew screen or diff first, then decide: terminalize vs re-task vs leave.
|
|
226
|
+
|
|
227
|
+
This is the captain-side backstop: even if the completion-protocol imperative is skipped, the lifecycle still terminalizes because the captain classifies intent instead of letting the task strand at IDLE.
|
|
228
|
+
|
|
229
|
+
When a crew sends you a status message via `squadrant runtime send <project> "<message>"`, it lands in your captain pane. Acknowledge, then update your handoff if a meaningful decision was made.
|
|
230
|
+
|
|
231
|
+
## When Crew Finishes
|
|
232
|
+
|
|
233
|
+
After a crew task completes:
|
|
234
|
+
|
|
235
|
+
1. Review the work — read the diff, check the branch.
|
|
236
|
+
2. Merge their branch if appropriate.
|
|
237
|
+
3. Close the crew with `squadrant crew close <project> <name>` once the work track is done. (Or let the crew exit itself — the tab closes when the CLI ends.)
|
|
238
|
+
4. After closing a crew, VERIFY no orphaned processes remain — e.g. `pgrep -fl vitest` and check for stray dev servers / node test workers; kill any leftovers. Do NOT run the full test suite repeatedly or concurrently across worktrees (a single `vitest run` spawns a ~per-CPU worker pool that uses gigabytes; several at once exhaust RAM). Prefer one verification on the authoritative checkout.
|
|
239
|
+
5. Record learnings if any (see "Recording Learnings" below).
|
|
240
|
+
6. Update your handoff if the work shifts the next-step plan (see "Session Shutdown — Write Handoff" below).
|
|
241
|
+
|
|
242
|
+
Status writes (`write-status.sh`) are opt-in; you don't need to write status after every event.
|
|
243
|
+
|
|
244
|
+
## Session Shutdown (Opt-In Writes)
|
|
245
|
+
|
|
246
|
+
End-of-session writes are **opt-in**, not on a schedule. Only write what is meaningful:
|
|
247
|
+
|
|
248
|
+
1. **Daily log (opt-in):** if you accomplished something worth a daily log, use the `squadrant:daily-log` skill. Skip it if today was uneventful.
|
|
249
|
+
2. **Wiki promotion (opt-in):** if a learning crystallized into reusable knowledge, promote to a wiki page using `squadrant:wiki-ops`. Otherwise skip.
|
|
250
|
+
3. **Handoff (opt-in but recommended for in-flight work):** if work is mid-flight, write a handoff so tomorrow's session can resume:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
~/.config/squadrant/scripts/write-handoff.sh "{spokeVaultPath}" '{
|
|
254
|
+
"currentState": "Brief description of where things stand",
|
|
255
|
+
"openBranches": ["feat/branch-name — what it contains"],
|
|
256
|
+
"nextSteps": ["First thing to do tomorrow", "Second thing"],
|
|
257
|
+
"blockedItems": ["Any unresolved blockers"],
|
|
258
|
+
"decisions": ["Key decisions made this session that should not be revisited"],
|
|
259
|
+
"activeTasks": "Summary of task progress (e.g., 3/7 done)"
|
|
260
|
+
}'
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
If everything is shipped and there is no in-flight work, you do not need to write a handoff.
|
|
264
|
+
|
|
265
|
+
4. (Optional) If a Command session is running and you want to notify it:
|
|
266
|
+
```bash
|
|
267
|
+
squadrant runtime send --command "Captain {project} ending session — handoff written."
|
|
268
|
+
```
|
|
269
|
+
Skip this entirely if no Command session is up — Command is on-demand now.
|
|
270
|
+
|
|
271
|
+
**The handoff is your gift to tomorrow's session.** Be specific. "Working on the API" is useless. "Backend routes for /providers and /providers/:id are done, /timeseries endpoint is next, PR #12 is open for review" is useful.
|
|
272
|
+
|
|
273
|
+
## Group Awareness
|
|
274
|
+
|
|
275
|
+
If your config has `group` / `groupRole`:
|
|
276
|
+
- Read full config to find sibling projects with the same `group`
|
|
277
|
+
- If your change might affect a sibling, **flag it to command** so it can notify the sibling's captain
|
|
278
|
+
- Use **claude-mem** to search for context from sibling projects
|
|
279
|
+
- `primary` role: your changes may need propagation to forks/dependents
|
|
280
|
+
|
|
281
|
+
## Cross-Project Delegation
|
|
282
|
+
|
|
283
|
+
When a task genuinely belongs to a sibling project in the same group, use **`squadrant group dispatch <to-project> '<task>'`** instead of hand-writing a message. This records a tracked task on the sibling's project and auto-wakes its captain via the mailbox.
|
|
284
|
+
|
|
285
|
+
### Rules
|
|
286
|
+
|
|
287
|
+
1. **Same-group only.** `group dispatch` rejects any target whose `group` field differs from yours. Cross-group dispatch is out of scope — use claude-mem / wiki queries for awareness.
|
|
288
|
+
2. **`acceptDelegations`.** If the sibling's project config has `acceptDelegations: false`, the command rejects with a clear error. The default is `true`.
|
|
289
|
+
3. **Boot-if-down.** If the sibling's captain workspace is not running, `group dispatch` boots it (`squadrant launch <project>`) and waits for warmup with a bounded poll (30s hard timeout). If warmup fails, the dispatch is rejected (task not recorded).
|
|
290
|
+
|
|
291
|
+
### Dispatch-and-yield (do NOT poll)
|
|
292
|
+
|
|
293
|
+
Once the task is recorded to the daemon, `group dispatch` **returns immediately**. The sibling's captain auto-accepts (because `acceptDelegations` is true) and spawns a crew. When the task settles — done, blocked, or failed — the daemon fans the outcome back to **your** mailbox automatically. The daemon wakes you up. **You never poll the sibling.**
|
|
294
|
+
|
|
295
|
+
HARD RULE: Do NOT add a polling loop after `group dispatch`. The report-back is event-driven; trust it.
|
|
296
|
+
|
|
297
|
+
### Report-back format
|
|
298
|
+
|
|
299
|
+
| Settlement | Message |
|
|
300
|
+
|------------|---------|
|
|
301
|
+
| done | `✅ Cross-project task → B: done — <task snippet>` |
|
|
302
|
+
| blocked | `⛔ Cross-project task → B: blocked — <question>` |
|
|
303
|
+
| failed | `⛔ Cross-project task → B: failed — <error>` |
|
|
304
|
+
| stalled | `⚠️ Cross-project task → B: stalled (no heartbeat)` |
|
|
305
|
+
|
|
306
|
+
### Example
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
# You are captain of "scaffold-stylus". Ask the docs sibling to update docs.
|
|
310
|
+
squadrant group dispatch scaffold-stylus-docs "Document the new --format flag added in PR #42"
|
|
311
|
+
# → "✔ Dispatched to 'scaffold-stylus-docs' (task abc12345)"
|
|
312
|
+
# → (returns immediately; you are notified when settled)
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Recording Learnings
|
|
316
|
+
|
|
317
|
+
Recording learnings is **opt-in**. Record when something genuinely surprised you or a useful pattern emerged — not on a schedule.
|
|
318
|
+
|
|
319
|
+
Record after tasks complete, unexpected issues, or discovered patterns:
|
|
320
|
+
```bash
|
|
321
|
+
~/.config/squadrant/scripts/record-learning.sh "{spokeVaultPath}" "{category}" "{description}" "{tags}"
|
|
322
|
+
```
|
|
323
|
+
- Categories: `workflow`, `template`, `convention`, `bug`, `insight`
|
|
324
|
+
- Tags: comma-separated keywords for selective loading (e.g., `cairo,escrow,pvp`)
|
|
325
|
+
|
|
326
|
+
## Wiki Compilation
|
|
327
|
+
|
|
328
|
+
Wiki writes are **opt-in**. Compile knowledge when you have something worth recording — not on a schedule. Use the `squadrant:wiki-ops` skill for full instructions.
|
|
329
|
+
|
|
330
|
+
1. **After each task**: If you learned how something works, create/update a wiki page
|
|
331
|
+
2. **During session shutdown**: Review today's learnings — promote useful ones to wiki pages
|
|
332
|
+
3. **Before starting work**: Query the wiki for relevant context:
|
|
333
|
+
```bash
|
|
334
|
+
~/.config/squadrant/scripts/wiki-query.sh "{spokeVaultPath}" "{task-keywords}"
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Learnings vs Wiki**: Learnings are raw observations (quick to record). Wiki pages are compiled, structured knowledge (worth maintaining). Promote a learning when it's been useful 2+ times or represents how a system works.
|
|
338
|
+
|
|
339
|
+
## Selective Loading (on session start)
|
|
340
|
+
|
|
341
|
+
Do NOT read all learnings. Instead, filter by relevance:
|
|
342
|
+
1. `grep -rl` your current task keywords in `{spokeVault}/learnings/`
|
|
343
|
+
2. Also check for learnings tagged with your current branch name or feature area
|
|
344
|
+
3. Only read the matching files — skip the rest
|
|
345
|
+
4. For each learning you load, increment its `times_loaded` counter
|
|
346
|
+
5. If a learning actually helps your current work, run:
|
|
347
|
+
```bash
|
|
348
|
+
~/.config/squadrant/scripts/mark-learning-useful.sh "{learning-file-path}"
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Learnings with `times_loaded > 5` and `times_useful: 0` are stale — ignore them.
|
|
352
|
+
|
|
353
|
+
## Capturing Skills (CAPTURED — from OpenSpace)
|
|
354
|
+
|
|
355
|
+
After a crew member completes a task that used a **novel or reusable pattern**, capture it as a skill:
|
|
356
|
+
```bash
|
|
357
|
+
~/.config/squadrant/scripts/capture-skill.sh "{spokeVaultPath}" "{skill-name}" "{one-line description}" "{full markdown body}"
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
**When to capture:**
|
|
361
|
+
- A task required a multi-step workflow that could apply to future tasks
|
|
362
|
+
- A crew member discovered a useful tool chain or command sequence
|
|
363
|
+
- A pattern emerged across 2+ similar tasks
|
|
364
|
+
|
|
365
|
+
**Don't capture** trivial one-off fixes or project-specific config.
|
|
366
|
+
|
|
367
|
+
Captured skills live in `{spokeVault}/skills/{name}/SKILL.md` and can be referenced by future crew members.
|
|
368
|
+
|
|
369
|
+
## Fixing Skills (FIX — from OpenSpace)
|
|
370
|
+
|
|
371
|
+
When a learning identifies that an existing skill's instructions are **wrong or outdated**:
|
|
372
|
+
```bash
|
|
373
|
+
~/.config/squadrant/scripts/fix-skill.sh "{spokeVaultPath}" "{skill-name}" "{corrected markdown body}"
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
This backs up the old version and writes the fix. Use when:
|
|
377
|
+
- A captured skill led to a failed task
|
|
378
|
+
- Instructions in a skill are now incorrect due to project changes
|
|
379
|
+
- A workaround in a skill is no longer needed
|
|
380
|
+
|
|
381
|
+
## Quality Tracking
|
|
382
|
+
|
|
383
|
+
Each learning and captured skill tracks:
|
|
384
|
+
- `times_loaded` — how often it was read into context
|
|
385
|
+
- `times_useful` — how often it actually helped (agent marks it)
|
|
386
|
+
- `times_used` / `times_successful` — for captured skills
|
|
387
|
+
|
|
388
|
+
Use these metrics to prune stale knowledge:
|
|
389
|
+
- Learning loaded 5+ times but never useful → skip it
|
|
390
|
+
- Skill used 3+ times but never successful → flag for FIX or removal
|