opencode-onboard 0.4.5 → 0.4.8

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.
Files changed (37) hide show
  1. package/README.md +58 -19
  2. package/content/.agents/agents/basic-engineer.md +5 -5
  3. package/content/.agents/agents/devops-manager.md +14 -10
  4. package/content/.agents/skills/ob-global/SKILL.md +9 -7
  5. package/content/.opencode/commands/ob-create-architecture.md +76 -0
  6. package/content/.opencode/commands/ob-create-design.md +53 -0
  7. package/content/.opencode/commands/{create-engineer.md → ob-create-engineer.md} +9 -8
  8. package/content/.opencode/commands/ob-init.md +8 -0
  9. package/content/.opencode/commands/{main.md → ob-main.md} +2 -2
  10. package/content/.opencode/commands/{plan.md → ob-plan.md} +2 -2
  11. package/content/.opencode/commands/opsx-apply.md +212 -193
  12. package/content/.opencode/skills/openspec-apply-change/SKILL.md +234 -176
  13. package/content/AGENTS.md +152 -49
  14. package/content/ARCHITECTURE.md +16 -327
  15. package/content/DESIGN.md +16 -26
  16. package/package.json +1 -1
  17. package/src/commands/join.js +6 -1
  18. package/src/commands/single.js +1 -1
  19. package/src/presets/models.json +2 -2
  20. package/src/presets/platforms.json +4 -0
  21. package/src/steps/copy/agents.js +200 -3
  22. package/src/steps/copy/agents.test.js +45 -0
  23. package/src/steps/copy/copy.test.js +15 -2
  24. package/src/steps/copy/index.js +2 -1
  25. package/src/steps/copy/skills.js +16 -0
  26. package/src/steps/metadata/index.js +6 -5
  27. package/src/steps/metadata/metadata.test.js +16 -8
  28. package/src/steps/models/write.js +17 -4
  29. package/src/steps/models/write.test.js +57 -56
  30. package/src/steps/openspec/ensemble.js +81 -54
  31. package/src/steps/openspec/ensemble.test.js +40 -8
  32. package/src/steps/optimization/caveman.js +2 -2
  33. package/src/steps/optimization/global.js +21 -1
  34. package/src/steps/optimization/global.test.js +3 -0
  35. package/src/steps/platform/index.js +8 -1
  36. package/src/steps/platform/platform.test.js +19 -0
  37. package/content/.opencode/commands/init.md +0 -8
@@ -1,132 +1,144 @@
1
- ---
2
- description: Implement tasks from an OpenSpec change via ensemble agent team
3
- ---
4
-
5
- Implement tasks from an OpenSpec change using the ensemble agent team.
6
-
7
- **Input**: Optionally specify a change name (e.g., `/opsx-apply add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
8
-
9
- **Steps**
10
-
11
- 1. **Select the change**
12
-
13
- If a name is provided, use it. Otherwise:
14
- - Infer from conversation context if the user mentioned a change
15
- - Auto-select if only one active change exists
16
- - If ambiguous, run `openspec list --json` to get available changes and use the **AskUserQuestion tool** to let the user select
17
-
18
- Always announce: "Using change: <name>" and how to override (e.g., `/opsx-apply <other>`).
19
-
20
- 2. **Check status to understand the schema**
21
-
22
- ```bash
23
- openspec status --change "<name>" --json
24
- ```
25
-
26
- Parse the JSON to understand:
27
- - `schemaName`: The workflow being used (e.g., "spec-driven")
28
- - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others)
29
-
30
- 3. **Get apply instructions**
31
-
32
- ```bash
33
- openspec instructions apply --change "<name>" --json
34
- ```
35
-
36
- This returns:
37
- - `contextFiles`: artifact ID -> array of concrete file paths (varies by schema)
38
- - Progress (total, complete, remaining)
39
- - Task list with status
40
- - Dynamic instruction based on current state
41
-
42
- **Handle states:**
43
- - If `state: "blocked"` (missing artifacts): show message, suggest using `/opsx-continue`
44
- - If `state: "all_done"`: congratulate, suggest archive with `/opsx-archive`
45
- - Otherwise: proceed to implementation
46
-
47
- 4. **Read context files**
48
-
49
- Read every file path listed under `contextFiles` from the apply instructions output.
50
- Do NOT tell agents to read files themselves, summarize the content here and pass it in spawn prompts.
51
-
52
- 5. **Show current progress**
53
-
54
- Display:
55
- - Schema being used
56
- - Progress: "N/M tasks complete"
57
- - Remaining tasks overview
58
-
59
- 6. **Implement via ensemble team**
60
-
61
- NEVER implement tasks directly. Always delegate to engineer workers via ensemble.
62
- Do NOT touch any source files before the team is running, not even a single edit.
63
-
64
- Steps MUST be followed in order. Do not skip any step.
65
-
66
- **Step 6a.** Create feature branch if not already on one: `feature/{id}-{slug}`
67
-
68
- **Step 6b.** Create the team:
69
- ```
70
- team_create "<change-name>-<random 4 digit number>"
71
- ```
72
- Announce: "Team running. Monitor at http://localhost:4747/"
73
-
74
- **Step 6c.** Add ALL tasks to the shared board BEFORE spawning anyone.
1
+ ---
2
+ description: Implement tasks from an OpenSpec change via ensemble agent team
3
+ ---
4
+
5
+ Implement tasks from an OpenSpec change using the ensemble agent team.
6
+
7
+ **Input**: Optionally specify a change name (e.g., `/opsx-apply add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
8
+
9
+ **Steps**
10
+
11
+ 1. **Select the change**
12
+
13
+ If a name is provided, use it. Otherwise:
14
+ - Infer from conversation context if the user mentioned a change
15
+ - Auto-select if only one active change exists
16
+ - If ambiguous, run `openspec list --json` to get available changes and use the **AskUserQuestion tool** to let the user select
17
+
18
+ Always announce: "Using change: <name>" and how to override (e.g., `/opsx-apply <other>`).
19
+
20
+ 2. **Check status to understand the schema**
21
+
22
+ ```bash
23
+ openspec status --change "<name>" --json
24
+ ```
25
+
26
+ Parse the JSON to understand:
27
+ - `schemaName`: The workflow being used (e.g., "spec-driven")
28
+ - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others)
29
+
30
+ 3. **Get apply instructions**
31
+
32
+ ```bash
33
+ openspec instructions apply --change "<name>" --json
34
+ ```
35
+
36
+ This returns:
37
+ - `contextFiles`: artifact ID -> array of concrete file paths (varies by schema)
38
+ - Progress (total, complete, remaining)
39
+ - Task list with status
40
+ - Dynamic instruction based on current state
41
+
42
+ **Handle states:**
43
+ - If `state: "blocked"` (missing artifacts): show message, suggest using `/opsx-continue`
44
+ - If `state: "all_done"`: congratulate, suggest archive with `/opsx-archive`
45
+ - Otherwise: proceed to implementation
46
+
47
+ 4. **Read context files**
48
+
49
+ Read every file path listed under `contextFiles` from the apply instructions output.
50
+ Do NOT tell agents to read files themselves, summarize the content here and pass it in spawn prompts.
51
+
52
+ 5. **Show current progress**
53
+
54
+ Display:
55
+ - Schema being used
56
+ - Progress: "N/M tasks complete"
57
+ - Remaining tasks overview
58
+
59
+ 5b. **Scope & cost confirmation gate**
60
+
61
+ Before spawning any agents, always run this check:
62
+
63
+ 1. Count remaining (incomplete) tasks from the apply instructions output.
64
+ 2. Classify cost tier:
65
+ - **Low**: 1–3 tasks — short session, fast models likely sufficient
66
+ - **Medium**: 4–7 tasks meaningful cost, consider splitting across sessions
67
+ - **High**: 8+ tasks — significant cost, strongly consider splitting the change
68
+ 3. Run `/quota` if the opencode-quota plugin is available to surface current budget state.
69
+ 4. **Always announce** before proceeding: cost tier, remaining task count, and current quota (if available).
70
+ 5. If cost tier is **Medium or High** (≥ 4 remaining tasks): use **AskUserQuestion tool** to ask the user: "About to spawn agents for N tasks (cost tier: MEDIUM/HIGH). Continue with implementation? (yes/no)"
71
+ - If **no**: stop here. Suggest splitting the change into smaller pieces with `openspec` or reducing scope. Do not proceed to step 6.
72
+ - If **yes**: proceed to step 6.
73
+ 6. If cost tier is **Low** (≤ 3 tasks): proceed automatically to step 6 (no confirmation needed).
74
+
75
+ 6. **Implement via ensemble team**
76
+
77
+ NEVER implement tasks directly. Always delegate to engineer workers via ensemble.
78
+ Do NOT touch any source files before the team is running, not even a single edit.
79
+
80
+ Steps MUST be followed in order. Do not skip any step.
81
+
82
+ **Step 6a.** Create feature branch if not already on one: `feature/{id}-{slug}`
83
+
84
+ **Step 6b.** Create the team:
85
+ ```
86
+ team_create "<change-name>-<random 4 digit number>"
87
+ ```
88
+ Announce: "Team running. Monitor at http://localhost:4747/"
89
+
90
+ **Step 6c.** Add ALL tasks to the shared board BEFORE spawning anyone, using as many `team_tasks_add` calls as needed to wire dependencies correctly.
75
91
  Schema: { content: string, priority: "high"|"medium"|"low", depends_on?: string[] }
76
- Use depends_on to block tasks that require other tasks first, pass the IDs returned by team_tasks_add.
92
+ You cannot reference returned task IDs until an earlier `team_tasks_add` call finishes, so add tasks in dependency order.
77
93
  ```
78
94
  team_tasks_add tasks:[
79
95
  { content: "1.1 <exact task text from tasks.md>", priority: "high" },
80
- { content: "1.2 <exact task text>", priority: "high" },
81
- { content: "3.1 <task that needs 1.x done first>", priority: "medium", depends_on: ["<id-of-1.1>"] },
82
- ...every task, one entry each...
96
+ { content: "1.2 <exact task text>", priority: "high" }
83
97
  ]
84
98
  ```
85
- Save the task IDs returned. Pass them to agents in step 6d.
99
+ Save the returned IDs for root tasks.
100
+ ```
101
+ team_tasks_add tasks:[
102
+ { content: "2.1 <task that depends on 1.1>", priority: "high", depends_on: ["<real-id-of-1.1>"] },
103
+ { content: "3.1 <task that depends on 1.2>", priority: "medium", depends_on: ["<real-id-of-1.2>"] }
104
+ ]
105
+ ```
106
+ Repeat until every OpenSpec task is on the board, then pass the literal IDs returned by those calls to agents in step 6d.
86
107
  DO NOT call team_claim yourself, only agents claim tasks.
87
108
  DO NOT proceed to 6d until team_tasks_add succeeds.
88
-
89
- **Step 6d.** Discover available agents, assign an INITIAL BATCH of tasks, then spawn workers.
90
-
91
- **CONCURRENCY LIMIT: Maximum {{MAX_CONCURRENT_AGENTS}} truly concurrent agents at a time.**
92
- All agents in a wave MUST be spawned and running simultaneously, not one-at-a-time sequentially.
109
+
110
+ **Step 6d.** Discover available engineers, assign an INITIAL BATCH of tasks, then spawn workers.
93
111
 
94
112
  **ROLLING BATCH MODEL:**
95
113
  Agents do NOT receive all their tasks upfront. Instead:
96
- - Assign each agent an initial batch of up to 3 tasks (respecting dependencies).
114
+ - Assign each agent an initial batch of up to 3 unblocked tasks.
97
115
  - When an agent completes its batch and messages back, the lead assigns the next batch of up to 3 unassigned tasks from the board that match the agent's domain.
98
116
  - Repeat until no pending tasks remain on the board.
99
117
  - Only shut down an agent when the board has no more tasks for its domain.
100
118
 
101
- This prevents agents from idling after one task, avoids overloading spawn prompts, and lets the lead adapt assignments based on progress.
102
-
103
- **FILE DOMAIN SEPARATION (mandatory):**
104
- Each agent MUST own a non-overlapping set of files/directories. Examples:
105
- - Agent A owns `src/backend/Application/Commands/`, Agent B owns `src/backend/Application/Queries/`
106
- - Agent A owns `src/frontend/app/(auth)/events/`, Agent B owns `src/frontend/app/(auth)/admin/`
107
- Never assign two agents tasks that touch the same file or controller.
108
-
109
- Agent discovery and assignment rule:
110
- - Read `.agents/agents/*.md` and use each agent's `description` and `## Abilities` to understand specialization.
111
- - For each task ID, choose the best-fit agent based on task domain (backend, frontend, infra, testing, etc.).
112
- - Prefer specialized agents when available; use `basic-engineer` as fallback only.
113
- - Only spawn agents that have assigned task IDs.
119
+ Before spawning:
120
+ - scan `.agents/agents/` and list the engineers that actually exist in this project
121
+ - exclude `devops-manager` from implementation selection
122
+ - read each engineer's description and abilities
123
+ - prefer the most specialized custom engineer whose description and abilities match the task
124
+ - use `basic-engineer` only when no custom engineer is a clear fit or as a recovery fallback
125
+ - never spawn an engineer name that is not present in `.agents/agents/`
114
126
 
115
127
  REQUIRED assignment algorithm (do not skip):
116
128
  1. Build candidate list from `.agents/agents/*.md` excluding `devops-manager`.
117
129
  2. Classify each task by domain using task text (api/backend, ui/frontend, infra/devops, testing/qa).
118
- 3. For each task, score every candidate agent:
119
- - +3 if agent description explicitly matches domain
120
- - +2 if agent `## Abilities` include domain-relevant skills
121
- - +1 if prior tasks of same domain already assigned to that agent (cohesion)
122
- 4. Assign task to highest-score agent.
123
- 5. Use `basic-engineer` ONLY when no specialized agent has positive score.
124
- 6. If all tasks go to `basic-engineer`, you MUST explain why no specialist matched.
125
-
130
+ 3. For each task, score every candidate agent:
131
+ - +3 if agent description explicitly matches domain
132
+ - +2 if agent `## Abilities` include domain-relevant skills
133
+ - +1 if prior tasks of same domain already assigned to that agent (cohesion)
134
+ 4. Assign task to highest-score agent.
135
+ 5. Use `basic-engineer` ONLY when no specialized agent has positive score.
136
+ 6. If all tasks go to `basic-engineer`, you MUST explain why no specialist matched.
137
+
126
138
  HARD RULES:
127
139
  - NEVER assign a task to `basic-engineer` if a specialized agent has higher score.
128
140
  - NEVER skip agent discovery from `.agents/agents/*.md`.
129
- - ALWAYS include assignment rationale in spawn prompt: "Selected because <domain match>".
141
+ - ALWAYS include assignment rationale only when it changes task routing or is needed to justify using `basic-engineer`.
130
142
 
131
143
  Skill loading is worker-driven:
132
144
  - The spawned agent MUST load `@ob-global` first.
@@ -134,122 +146,129 @@ Implement tasks from an OpenSpec change using the ensemble agent team.
134
146
 
135
147
  Each team_spawn MUST include the agent field (required, causes NOT NULL error if omitted).
136
148
 
137
- **Spawn prompt format (strict, max 400 tokens):**
149
+ The spawn prompt must be short and operational. It must contain:
150
+ 1. Their name and engineer file on this team
151
+ 2. Their initial batch of tasks (up to 3): include the LITERAL task IDs AND the task content. Copy them verbatim from the IDs returned by `team_tasks_add`. Do NOT paraphrase or omit IDs.
152
+ 3. Key context they need, summarized from context files
153
+ 4. Exact verification commands or acceptance checks
154
+ 5. Only the mandatory skill names or repo-specific rules they still need after claim
138
155
 
139
156
  ```
140
- You are {name}, {role}. Your file domain: {list of directories you own exclusively}.
141
-
142
- Initial tasks (claim each with team_claim before starting, team_tasks_complete after commit):
143
- - {task_id_1}: {one-line description}
144
- - {task_id_2}: {one-line description}
145
- - {task_id_3}: {one-line description}
146
-
147
- Context: {2-3 sentences of essential context from the specs, NOT full file contents}
148
-
149
- Build command: {e.g., "dotnet build TechEvents.slnx" or "pnpm build"}
150
- After each task: git add -A && git commit -m "feat: <description>"
151
-
152
- IMPORTANT: After completing all tasks above, message lead with results.
153
- Lead may assign you more tasks. Do NOT shut down until lead confirms no more tasks.
154
- Start with team_claim on your first task NOW. Do not read files or plan first.
157
+ You are <worker-name>, <engineer-file>.
158
+ Claim this task immediately as your first action:
159
+ - [task-<id1>] <task text>
160
+ <optional more tasks in the batch>
161
+
162
+ Key context:
163
+ - <short bullets>
164
+
165
+ After claiming:
166
+ 1. Load @ob-global
167
+ 2. Load only the relevant abilities/skills for this task
168
+ 3. Implement the task
169
+ 4. Call team_tasks_complete for the same task ID
170
+ 5. Send a short team_message with files changed and checks run
155
171
  ```
156
172
 
157
- DO NOT include:
158
- - Full file contents or code snippets in the prompt
159
- - Descriptions of how ensemble works
160
- - Lists of available tools (the agent already knows from its agent.md)
161
- - Instructions to "message lead when planning", agents should only message when DONE or BLOCKED
173
+ Keep spawn prompts short and concrete. Prefer 120-220 tokens. Do NOT paste a generic tool list or long workflow boilerplate the plugin and agent file already provide.
174
+ ALWAYS set `claim_task` to the first unblocked task in that agent's initial batch.
175
+ Only spawn agents whose tasks are actually needed by this change. Skip agents with no tasks.
162
176
 
163
- Spawn workers:
177
+ Spawn sequentially, waiting for each result:
164
178
  ```
165
- team_spawn name:"eng-1" agent:"backend-engineer" prompt:"..."
166
- team_spawn name:"eng-2" agent:"frontend-engineer" prompt:"..."
179
+ team_spawn name:"ui1" agent:"frontend-engineer" prompt:"..."
180
+ (wait for result)
181
+ team_spawn name:"api1" agent:"backend-engineer" prompt:"..."
182
+ (wait for result)
167
183
  ```
184
+ Replace example agent names with REAL engineers that exist in this project.
168
185
 
169
- Then immediately send each spawned worker a start message:
186
+ Then send each spawned worker a short start message that repeats their exact task IDs if needed:
170
187
  ```
171
- team_message to:"eng-1" text:"Start now. First action: team_claim {first_task_id}. Go."
172
- team_message to:"eng-2" text:"Start now. First action: team_claim {first_task_id}. Go."
188
+ team_message to:"ui1" text:"Claim now: [task-<id1>] <task text>."
173
189
  ```
174
-
175
- **Step 6e.** After sending start messages, tell the user what is running, then STOP and wait.
176
- Do NOT call team_results, team_status, or team_broadcast in a loop.
177
- Teammates will message you when done or blocked. Wait for those messages.
178
-
179
- Tell the user: "Agents spawned. Check dashboard at http://localhost:4747/. I'll report when they finish."
190
+ Never send a generic "claim your first task" message without the actual IDs.
191
+ If `claim_task` already covers the first task, keep the start message minimal. Use follow-up messages mainly for additional tasks in the batch or recovery.
192
+
193
+ **Step 6e.** After sending start messages, tell the user what is running, then STOP and wait.
194
+ Do NOT call team_results, team_status, or team_broadcast in a loop.
195
+ Teammates will message you when done or blocked. Wait for those messages.
196
+
197
+ Tell the user exactly how to inspect progress:
198
+ - `team_status` for team snapshot
199
+ - `team_tasks_list` for board state
200
+ - `team_view member:"<name>"` for a teammate live session
201
+ - `team_results from:"<name>"` for full teammate report text
180
202
 
181
203
  **Step 6f.** When a teammate messages back (rolling re-assignment loop):
182
204
  1. Call `team_results from:"<name>"` to read full message.
183
205
  2. Call `team_tasks_list` to check remaining pending/unassigned tasks on the board.
184
- 3. **If there are more unassigned tasks matching this agent's domain:**
206
+ 3. If the teammate is idle and has not claimed any assigned task:
207
+ - resend one short claim-only message with the same literal task IDs
208
+ - if they still do not claim, `team_shutdown member:"<name>" force:true`
209
+ - respawn once with a shorter prompt and the same first `claim_task`
210
+ - if the second spawn also stays idle, stop forcing ensemble for this change and continue in the main session or ask the user whether to retry later
211
+ 4. **If there are more unassigned tasks matching this agent's domain:**
185
212
  - Pick up to 3 unassigned, unblocked tasks for this agent's domain.
186
- - Send them via `team_message to:"<name>" text:"Next tasks: [task-<id1>] <desc>, [task-<id2>] <desc>, [task-<id3>] <desc>. Claim each with team_claim before starting."`
213
+ - Send them via `team_message to:"<name>" text:"Claim next: [task-<id1>] <desc>, [task-<id2>] <desc>."`
187
214
  - Do NOT shut down the agent. Go back to waiting (step 6e).
188
- 4. **If no more tasks for this agent:**
215
+ 5. **If no more tasks for this agent:**
189
216
  - `team_shutdown member:"<name>"`
190
217
  - `team_merge member:"<name>"`
191
- - If team_merge blocks on local changes: `git stash`, retry merge, `git stash pop`
192
- 5. **If ALL agents are shut down and tasks remain unassigned** (new domain, dependencies unblocked):
193
- - Spawn new agents for the remaining tasks (back to step 6d).
194
- 6. **If ALL tasks are done:** proceed to step 7.
195
-
196
- **IMMEDIATE SHUTDOWN RULE:** Never leave a finished agent running when there are no more tasks for it. But DO keep agents alive if more tasks in their domain are pending.
218
+ - If team_merge blocks on local changes: `git stash`, retry merge, `git stash pop`.
219
+ 6. **If ALL agents are shut down and tasks remain unassigned** (new domain, dependencies unblocked):
220
+ - Discover the remaining matching engineers from `.agents/agents/` and spawn a new wave (back to step 6d).
221
+ 7. **If ALL tasks are done:** proceed to step 7.
197
222
 
198
223
  **ZERO PENDING TASKS GUARANTEE:** Before proceeding to step 7, call `team_tasks_list` and verify EVERY task is either `done` or `blocked`. If any task is `pending` and unassigned, assign it to an agent or spawn a new one. Never leave pending tasks orphaned.
199
224
 
200
- **Step 6g. Stall detection (if agent has no commits after 5 minutes):**
201
- 1. `team_message to:"<name>" text:"Status? If stuck, report blocker. If not started, run team_claim {task_id} now."`
202
- 2. Wait 2 more minutes
203
- 3. If still no response: `team_shutdown member:"<name>" force:true`
204
- 4. Respawn with same tasks, fresh prompt
205
- 5. Log stall in session-log for post-mortem
206
-
207
225
  7. **Verification check**
208
226
 
209
- After ALL agents are merged, run verification on the lead branch directly:
210
- ```bash
211
- # Backend
212
- dotnet build <solution>
213
- # Frontend
214
- pnpm build
227
+ Spawn the best available verification-capable engineer with `worktree:false` (for example, a testing-focused custom engineer or `basic-engineer` if no better verifier exists):
215
228
  ```
216
- Fix any errors yourself (small fixes only). If large fixes needed, spawn one more agent.
217
-
218
- 8. **Mark tasks complete in openspec**
219
-
220
- Update tasks.md: `- [ ]` `- [x]` for each completed task.
221
- Run `openspec status --change "<name>" --json` to confirm.
222
-
223
- 9. **Show status, then cleanup**
224
-
225
- Display:
226
- - Tasks completed this session
227
- - Overall progress: "N/M tasks complete"
228
- - If all done: suggest archive with `/opsx-archive`
229
- - If paused: explain why and wait for guidance
230
-
231
- Then run `team_cleanup`.
232
-
233
- **Guardrails**
234
- - NEVER skip or reorder steps 6a-6f
235
- - NEVER implement tasks directly. Always use team_create + team_spawn, no exceptions
236
- - NEVER touch source files before team_create is called, not even one edit
237
- - NEVER call team_spawn without the agent field, it is required and will fail without it
238
- - NEVER call team_spawn before team_tasks_add, tasks must exist before agents are spawned
229
+ team_spawn name:"verify" agent:"<real-verifier-engineer>" worktree:false prompt:"<verification scope, context summary, run tests + build + lint + verify acceptance criteria, no task claiming required in this phase, send results to lead when done>"
230
+ ```
231
+ Wait for message -> team_results -> fix blockers -> team_shutdown (no team_merge needed, worktree:false)
232
+
233
+ 8. **Mark tasks complete in openspec**
234
+
235
+ Update tasks.md: `- [ ]` → `- [x]` for each completed task.
236
+ Run `openspec status --change "<name>" --json` to confirm.
237
+
238
+ 9. **Show status, then cleanup**
239
+
240
+ Display:
241
+ - Tasks completed this session
242
+ - Overall progress: "N/M tasks complete"
243
+ - If all done: suggest archive with `/opsx-archive`
244
+ - If paused: explain why and wait for guidance
245
+
246
+ Then run `team_cleanup`.
247
+
248
+ **Guardrails**
249
+ - NEVER skip or reorder steps 6a-6f
250
+ - NEVER skip step 5b scope & cost check before spawning
251
+ - NEVER spawn agents for Medium or High cost sessions (≥4 tasks) without explicit user confirmation from step 5b
252
+ - ALWAYS run `/quota` at session start (step 5b) when the opencode-quota plugin is available
253
+ - NEVER implement tasks directly. Always use team_create + team_spawn, no exceptions
254
+ - NEVER touch source files before team_create is called, not even one edit
255
+ - NEVER call team_spawn without the agent field, it is required and will fail without it
256
+ - NEVER call team_spawn before all tasks are on the board; use multiple `team_tasks_add` calls when dependencies require real IDs from earlier calls
239
257
  - NEVER poll team_results or team_status in a loop, wait for teammates to message you
240
258
  - NEVER call team_claim or team_tasks_complete as lead, only agents call these tools
241
259
  - NEVER edit files between team_spawn and team_merge, team_merge blocks on overlapping local changes
242
260
  - NEVER leave pending tasks orphaned, always verify board is empty before proceeding to step 7
243
- - ALWAYS add every task to the board with team_tasks_add before spawning
244
- - ALWAYS assign initial batch of up to 3 tasks per agent in spawn prompt
245
- - ALWAYS re-assign next batch (up to 3) via team_message when agent reports done, if more tasks exist for its domain
261
+ - ALWAYS pass the LITERAL task IDs returned by team_tasks_add into each agent's spawn prompt, copy the exact IDs, never paraphrase
262
+ - ALWAYS add every task to the board before spawning, using multiple `team_tasks_add` calls when dependency wiring requires it
263
+ - ALWAYS assign initial batch of up to 3 tasks per agent; re-assign next batch (up to 3) via team_message when agent reports done
246
264
  - ALWAYS call team_tasks_list after each agent reports done to check for remaining unassigned tasks
247
- - ALWAYS spawn workers based on dependencies: parallel when safe, sequential when required
248
- - ALWAYS instruct agents to call team_claim before each task and team_tasks_complete after
249
- - ALWAYS enforce max {{MAX_CONCURRENT_AGENTS}} truly concurrent agents (all running simultaneously, not sequentially)
250
- - ALWAYS enforce non-overlapping file domains per agent
265
+ - ALWAYS repeat the same literal task IDs in any task assignment message, never send a generic "claim your first task" without the actual IDs
266
+ - NEVER send a start message that omits task IDs; if a task ID is missing from the start message, the agent cannot claim
267
+ - ALWAYS discover engineers from `.agents/agents/` and prefer matching custom engineers over `basic-engineer`
268
+ - ALWAYS spawn agents sequentially (wait for each team_spawn result before the next), then send start messages to all of them together
269
+ - ALWAYS set `claim_task` for the first unblocked task in each initial batch and instruct agents to claim before any other work
251
270
  - ALWAYS shut down + merge agents only when no more tasks remain for their domain
252
- - If teammates are stuck, use team_message to nudge, then stall detection (step 6g)
271
+ - If teammates are stuck, use one short claim-only message, then one respawn with a shorter prompt. If repeated idle/stall continues, stop forcing ensemble and continue outside it.
253
272
  - Mark tasks complete in openspec AFTER worker implementation and verification finish, not before
254
273
  - Pause on errors, blockers, or unclear requirements. Do not guess
255
274
  - Use contextFiles from CLI output, do not assume specific file paths