opencode-onboard 0.1.13 → 0.2.3

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.
@@ -63,8 +63,18 @@ Rules:
63
63
  - Do not force push
64
64
  - Report blockers immediately rather than working around them
65
65
 
66
+ ## Workflow
67
+
68
+ When spawned by the lead:
69
+ 1. For each assigned task: call `team_claim task_id:<id>` before starting
70
+ 2. Implement the task
71
+ 3. Call `team_tasks_complete task_id:<id>` after finishing
72
+ 4. When all tasks are done or blocked, send results to lead via `team_message`
73
+
66
74
  ## Output Format
67
75
 
76
+ Send via `team_message` to lead when done:
77
+
68
78
  ```
69
79
  ## Back Engineer, Done
70
80
 
@@ -62,8 +62,18 @@ Rules:
62
62
  - Do not force push
63
63
  - Report blockers immediately rather than working around them
64
64
 
65
+ ## Workflow
66
+
67
+ When spawned by the lead:
68
+ 1. For each assigned task: call `team_claim task_id:<id>` before starting
69
+ 2. Implement the task
70
+ 3. Call `team_tasks_complete task_id:<id>` after finishing
71
+ 4. When all tasks are done or blocked, send results to lead via `team_message`
72
+
65
73
  ## Output Format
66
74
 
75
+ Send via `team_message` to lead when done:
76
+
67
77
  ```
68
78
  ## Front Engineer, Done
69
79
 
@@ -60,8 +60,17 @@ Rules:
60
60
  - Do not force push
61
61
  - Report all failures, do not silently skip failing tests
62
62
 
63
+ ## Workflow
64
+
65
+ When spawned by the lead:
66
+ 1. Read the task list and context files provided in the spawn prompt
67
+ 2. Run tests, build, lint, and verify acceptance criteria
68
+ 3. When done, send results to lead via `team_message`
69
+
63
70
  ## Output Format
64
71
 
72
+ Send via `team_message` to lead when done:
73
+
65
74
  ```
66
75
  ## Quality Engineer, Done
67
76
 
@@ -0,0 +1,170 @@
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 `rtk 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
+ rtk 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
+ rtk 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 specialists 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.
75
+ 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.
77
+ ```
78
+ team_tasks_add tasks:[
79
+ { 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...
83
+ ]
84
+ ```
85
+ Save the task IDs returned. Pass them to agents in step 6d.
86
+ DO NOT call team_claim yourself, only agents claim tasks.
87
+ DO NOT proceed to 6d until team_tasks_add succeeds.
88
+
89
+ **Step 6d.** Spawn all needed specialists, then kick them off in parallel.
90
+
91
+ Each team_spawn MUST include the agent field (required, causes NOT NULL error if omitted).
92
+
93
+ The spawn prompt must contain exactly:
94
+ 1. Their name and role on this team
95
+ 2. Which tasks are theirs, list the task IDs and content from the board
96
+ 3. Key context they need (summarized from context files, do NOT tell them to read files themselves)
97
+ 4. The 6 OpenCode tools they have available (these are OpenCode tools, NOT shell commands, call them directly as tools, never via bash):
98
+ team_claim, team_tasks_complete, team_tasks_list, team_tasks_add, team_message, team_broadcast
99
+ 5. How to proceed: call team_claim tool with the task_id to claim a task before starting it, call team_tasks_complete tool after finishing it, repeat until all their tasks are done, then call team_message tool to notify lead with results or blockers
100
+
101
+ Keep spawn prompts under 500 tokens. Do not describe team internals or how ensemble works.
102
+ Only spawn agents whose tasks are actually needed by this change. Skip agents with no tasks.
103
+
104
+ First spawn all agents (wait for each team_spawn to confirm before the next):
105
+ ```
106
+ team_spawn name:"back" agent:"back-engineer" prompt:"..."
107
+ (wait for result)
108
+ team_spawn name:"front" agent:"front-engineer" prompt:"..."
109
+ (wait for result)
110
+ team_spawn name:"infra" agent:"infra-engineer" prompt:"..."
111
+ (wait for result)
112
+ ```
113
+
114
+ Then immediately send each spawned agent a start message to kick them off:
115
+ ```
116
+ team_message to:"back" text:"Start now. Claim your first task with team_claim and begin implementing."
117
+ team_message to:"front" text:"Start now. Claim your first task with team_claim and begin implementing."
118
+ team_message to:"infra" text:"Start now. Claim your first task with team_claim and begin implementing."
119
+ ```
120
+
121
+ **Step 6e.** After sending start messages, tell the user what is running, then STOP and wait.
122
+ Do NOT call team_results, team_status, or team_broadcast in a loop.
123
+ Teammates will message you when done or blocked. Wait for those messages.
124
+
125
+ **Step 6f.** When a teammate messages back, you receive a ping only, the full content is NOT in the notification.
126
+ Call team_results to read the full message and mark it read. Then for each teammate: team_shutdown → team_merge.
127
+ If team_merge blocks ("overlapping local changes"), commit or stash your local changes first, then retry.
128
+ Fix any other blockers reported.
129
+
130
+ 7. **Quality check**
131
+
132
+ Spawn quality engineer with worktree:false (read-only, no file edits):
133
+ ```
134
+ team_spawn name:"quality" agent:"quality-engineer" worktree:false prompt:"<task list, context summary, run tests + build + lint + verify acceptance criteria, send results to lead when done>"
135
+ ```
136
+ Wait for message → team_results → fix blockers → team_shutdown (no team_merge needed, worktree:false)
137
+
138
+ 8. **Mark tasks complete in openspec**
139
+
140
+ Update tasks.md: `- [ ]` → `- [x]` for each completed task.
141
+ Run `rtk openspec status --change "<name>" --json` to confirm.
142
+
143
+ 9. **Show status, then cleanup**
144
+
145
+ Display:
146
+ - Tasks completed this session
147
+ - Overall progress: "N/M tasks complete"
148
+ - If all done: suggest archive with `/opsx-archive`
149
+ - If paused: explain why and wait for guidance
150
+
151
+ Then run `team_cleanup`.
152
+
153
+ **Guardrails**
154
+ - NEVER skip or reorder steps 6a-6f
155
+ - NEVER implement tasks directly. Always use team_create + team_spawn, no exceptions
156
+ - NEVER touch source files before team_create is called, not even one edit
157
+ - NEVER call team_spawn without the agent field, it is required and will fail without it
158
+ - NEVER call team_spawn before team_tasks_add, tasks must exist before agents are spawned
159
+ - NEVER poll team_results or team_status in a loop, wait for teammates to message you
160
+ - NEVER call team_claim or team_tasks_complete as lead, only agents call these tools
161
+ - ALWAYS pass the task IDs returned by team_tasks_add to each agent's spawn prompt
162
+ - NEVER edit files between team_spawn and team_merge, team_merge blocks on overlapping local changes
163
+ - ALWAYS add every task to the board with team_tasks_add before spawning
164
+ - ALWAYS spawn agents sequentially (wait for each team_spawn result before the next), then send start messages to all of them together
165
+ - ALWAYS instruct agents to call team_claim before each task and team_tasks_complete after
166
+ - If teammates are stuck, use team_message to resend tasks, then wait, never implement directly
167
+ - Mark tasks complete in openspec AFTER specialists finish, not before
168
+ - Pause on errors, blockers, or unclear requirements. Do not guess
169
+ - Use contextFiles from CLI output, do not assume specific file paths
170
+ - Use `rtk` wrapper for ALL CLI commands. Never run openspec, git, gh, or az directly
@@ -3,7 +3,7 @@ import path from "node:path"
3
3
 
4
4
  const LOG_FILE = ".agents/session-log.json"
5
5
 
6
- // Per-session state: editCount and skills loaded
6
+ // Per-session state: editCount and loaded skills
7
7
  const sessionState = new Map()
8
8
 
9
9
  function ts() {
@@ -32,6 +32,45 @@ function resolveAgentName(session) {
32
32
  return "lead"
33
33
  }
34
34
 
35
+ function addSkillToState(state, skillName) {
36
+ if (!skillName || !state) return false
37
+ if (!state.skills) state.skills = new Set()
38
+ if (state.skills.has(skillName)) return false
39
+ state.skills.add(skillName)
40
+ return true
41
+ }
42
+
43
+ function buildTeamSkillsSummary() {
44
+ const byAgent = {}
45
+ for (const state of sessionState.values()) {
46
+ if (!state?.agentName) continue
47
+ if (!byAgent[state.agentName]) byAgent[state.agentName] = new Set()
48
+ for (const skill of state.skills ?? []) byAgent[state.agentName].add(skill)
49
+ }
50
+
51
+ const summary = {}
52
+ for (const [agent, skills] of Object.entries(byAgent)) {
53
+ summary[agent] = Array.from(skills).sort()
54
+ }
55
+ return summary
56
+ }
57
+
58
+ // Maps ensemble tool name → function that extracts the log entry fields from args
59
+ const ENSEMBLE_TOOL_HANDLERS = {
60
+ team_create: (args) => ({ action: "team-created", team: args.name }),
61
+ team_spawn: (args) => ({ action: "teammate-spawned", name: args.name, agentType: args.agent }),
62
+ team_shutdown: (args) => ({ action: "teammate-shutdown", name: args.name }),
63
+ team_merge: (args) => ({ action: "teammate-merged", name: args.name }),
64
+ team_cleanup: () => ({ action: "team-cleanup" }),
65
+ team_status: () => ({ action: "team-status-checked" }),
66
+ team_results: (args) => ({ action: "team-results-read", from: args.from }),
67
+ team_message: (args) => ({ action: "team-message", to: args.to ?? "lead", preview: String(args.text ?? "").slice(0, 120) }),
68
+ team_broadcast: (args) => ({ action: "team-broadcast", preview: String(args.text ?? "").slice(0, 120) }),
69
+ team_tasks_add: (args) => ({ action: "tasks-added", count: Array.isArray(args.tasks) ? args.tasks.length : "?" }),
70
+ team_tasks_complete: (args) => ({ action: "task-completed", taskId: args.task_id }),
71
+ team_claim: (args) => ({ action: "task-claimed", taskId: args.task_id }),
72
+ }
73
+
35
74
  export const SessionLogPlugin = async ({ client, directory }) => {
36
75
  return {
37
76
  event: async ({ event }) => {
@@ -44,7 +83,7 @@ export const SessionLogPlugin = async ({ client, directory }) => {
44
83
  const session = res?.data
45
84
  const agentName = resolveAgentName(session)
46
85
 
47
- sessionState.set(sessionId, { agentName, editCount: 0, skills: [] })
86
+ sessionState.set(sessionId, { agentName, editCount: 0, skills: new Set() })
48
87
  appendEntry(directory, { ts: ts(), agent: agentName, action: "started", sessionId })
49
88
  }
50
89
 
@@ -61,7 +100,8 @@ export const SessionLogPlugin = async ({ client, directory }) => {
61
100
  const state = sessionState.get(sessionId)
62
101
  if (!state) return
63
102
 
64
- const { agentName, editCount, skills } = state
103
+ const { agentName, editCount } = state
104
+ const skills = Array.from(state.skills ?? []).sort()
65
105
  appendEntry(directory, { ts: ts(), agent: agentName, action: "completed", filesEdited: editCount, skills })
66
106
  sessionState.delete(sessionId)
67
107
  }
@@ -76,14 +116,43 @@ export const SessionLogPlugin = async ({ client, directory }) => {
76
116
  const state = sessionState.get(sessionId)
77
117
  if (!state) return
78
118
 
79
- if (input?.tool === "read") {
119
+ const tool = input?.tool
120
+
121
+ // Track skill loads via skill tool (primary)
122
+ if (tool === "skill") {
123
+ const skillName = input?.args?.name
124
+ const added = addSkillToState(state, skillName)
125
+ if (added) {
126
+ appendEntry(directory, { ts: ts(), agent: state.agentName, action: "skill-loaded", skill: skillName, source: "skill-tool" })
127
+ }
128
+ return
129
+ }
130
+
131
+ // Track skill loads via reading SKILL.md (fallback)
132
+ if (tool === "read") {
80
133
  const filePath = input?.args?.filePath ?? ""
81
134
  const match = filePath.match(/[/\\]skills[/\\]([^/\\]+)[/\\]SKILL\.md$/i)
82
135
  if (match) {
83
136
  const skillName = match[1]
84
- if (!state.skills.includes(skillName)) state.skills.push(skillName)
85
- appendEntry(directory, { ts: ts(), agent: state.agentName, action: "skill-loaded", skill: skillName })
137
+ const added = addSkillToState(state, skillName)
138
+ if (added) {
139
+ appendEntry(directory, { ts: ts(), agent: state.agentName, action: "skill-loaded", skill: skillName, source: "read-skill-file" })
140
+ }
86
141
  }
142
+ return
143
+ }
144
+
145
+ const args = input?.args ?? {}
146
+
147
+ // Track ensemble tool calls
148
+ const ensembleHandler = ENSEMBLE_TOOL_HANDLERS[tool]
149
+ if (!ensembleHandler) return
150
+
151
+ const entry = { ts: ts(), agent: state.agentName, ...ensembleHandler(args) }
152
+ appendEntry(directory, entry)
153
+
154
+ if (tool === "team_cleanup") {
155
+ appendEntry(directory, { ts: ts(), agent: state.agentName, action: "team-skills-summary", byAgent: buildTeamSkillsSummary() })
87
156
  }
88
157
  } catch (_) {}
89
158
  },
@@ -0,0 +1,176 @@
1
+ ---
2
+ name: openspec-apply-change
3
+ description: Implement tasks from an OpenSpec change via ensemble agent team. Use when the user wants to start implementing, continue implementation, or work through tasks.
4
+ license: MIT
5
+ compatibility: Requires openspec CLI and opencode-ensemble plugin.
6
+ metadata:
7
+ author: openspec-onboard
8
+ version: "2.0"
9
+ ---
10
+
11
+ Implement tasks from an OpenSpec change using the ensemble agent team.
12
+
13
+ **Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
14
+
15
+ **Steps**
16
+
17
+ 1. **Select the change**
18
+
19
+ If a name is provided, use it. Otherwise:
20
+ - Infer from conversation context if the user mentioned a change
21
+ - Auto-select if only one active change exists
22
+ - If ambiguous, run `rtk openspec list --json` to get available changes and use the **AskUserQuestion tool** to let the user select
23
+
24
+ Always announce: "Using change: <name>" and how to override (e.g., `/opsx-apply <other>`).
25
+
26
+ 2. **Check status to understand the schema**
27
+
28
+ ```bash
29
+ rtk openspec status --change "<name>" --json
30
+ ```
31
+
32
+ Parse the JSON to understand:
33
+ - `schemaName`: The workflow being used (e.g., "spec-driven")
34
+ - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others)
35
+
36
+ 3. **Get apply instructions**
37
+
38
+ ```bash
39
+ rtk openspec instructions apply --change "<name>" --json
40
+ ```
41
+
42
+ This returns:
43
+ - `contextFiles`: artifact ID -> array of concrete file paths (varies by schema - could be proposal/specs/design/tasks or spec/tests/implementation/docs)
44
+ - Progress (total, complete, remaining)
45
+ - Task list with status
46
+ - Dynamic instruction based on current state
47
+
48
+ **Handle states:**
49
+ - If `state: "blocked"` (missing artifacts): show message, suggest using openspec-continue-change
50
+ - If `state: "all_done"`: congratulate, suggest archive with `/opsx-archive`
51
+ - Otherwise: proceed to implementation
52
+
53
+ 4. **Read context files**
54
+
55
+ Read every file path listed under `contextFiles` from the apply instructions output.
56
+ Do NOT tell agents to read files themselves, summarize the content here and pass it in spawn prompts.
57
+
58
+ 5. **Show current progress**
59
+
60
+ Display:
61
+ - Schema being used
62
+ - Progress: "N/M tasks complete"
63
+ - Remaining tasks overview
64
+
65
+ 6. **Implement via ensemble team**
66
+
67
+ NEVER implement tasks directly. Always delegate to specialists via ensemble.
68
+ Do NOT touch any source files before the team is running, not even a single edit.
69
+
70
+ Steps MUST be followed in order. Do not skip any step.
71
+
72
+ **Step 6a.** Create feature branch if not already on one: `feature/{id}-{slug}`
73
+
74
+ **Step 6b.** Create the team:
75
+ ```
76
+ team_create "<change-name>-<random 4 digit number>"
77
+ ```
78
+ Announce: "Team running. Monitor at http://localhost:4747/"
79
+
80
+ **Step 6c.** Add ALL tasks to the shared board BEFORE spawning anyone.
81
+ Schema: { content: string, priority: "high"|"medium"|"low", depends_on?: string[] }
82
+ Use depends_on to block tasks that require other tasks first, pass the IDs returned by team_tasks_add.
83
+ ```
84
+ team_tasks_add tasks:[
85
+ { content: "1.1 <exact task text from tasks.md>", priority: "high" },
86
+ { content: "1.2 <exact task text>", priority: "high" },
87
+ { content: "3.1 <task that needs 1.x done first>", priority: "medium", depends_on: ["<id-of-1.1>"] },
88
+ ...every task, one entry each...
89
+ ]
90
+ ```
91
+ Save the task IDs returned. Pass them to agents in step 6d.
92
+ DO NOT call team_claim yourself, only agents claim tasks.
93
+ DO NOT proceed to 6d until team_tasks_add succeeds.
94
+
95
+ **Step 6d.** Spawn all needed specialists, then kick them off in parallel.
96
+
97
+ Each team_spawn MUST include the agent field (required, causes NOT NULL error if omitted).
98
+
99
+ The spawn prompt must contain exactly:
100
+ 1. Their name and role on this team
101
+ 2. Which tasks are theirs, list the task IDs and content from the board
102
+ 3. Key context they need (summarized from context files, do NOT tell them to read files themselves)
103
+ 4. The 6 OpenCode tools they have available (these are OpenCode tools, NOT shell commands, call them directly as tools, never via bash):
104
+ team_claim, team_tasks_complete, team_tasks_list, team_tasks_add, team_message, team_broadcast
105
+ 5. How to proceed: call team_claim tool with the task_id to claim a task before starting it, call team_tasks_complete tool after finishing it, repeat until all their tasks are done, then call team_message tool to notify lead with results or blockers
106
+
107
+ Keep spawn prompts under 500 tokens. Do not describe team internals or how ensemble works.
108
+ Only spawn agents whose tasks are actually needed by this change. Skip agents with no tasks.
109
+
110
+ First spawn all agents (wait for each team_spawn to confirm before the next):
111
+ ```
112
+ team_spawn name:"back" agent:"back-engineer" prompt:"..."
113
+ (wait for result)
114
+ team_spawn name:"front" agent:"front-engineer" prompt:"..."
115
+ (wait for result)
116
+ team_spawn name:"infra" agent:"infra-engineer" prompt:"..."
117
+ (wait for result)
118
+ ```
119
+
120
+ Then immediately send each spawned agent a start message to kick them off:
121
+ ```
122
+ team_message to:"back" text:"Start now. Claim your first task with team_claim and begin implementing."
123
+ team_message to:"front" text:"Start now. Claim your first task with team_claim and begin implementing."
124
+ team_message to:"infra" text:"Start now. Claim your first task with team_claim and begin implementing."
125
+ ```
126
+
127
+ **Step 6e.** After sending start messages, tell the user what is running, then STOP and wait.
128
+ Do NOT call team_results, team_status, or team_broadcast in a loop.
129
+ Teammates will message you when done or blocked. Wait for those messages.
130
+
131
+ **Step 6f.** When a teammate messages back, you receive a ping only, the full content is NOT in the notification.
132
+ Call team_results to read the full message and mark it read. Then for each teammate: team_shutdown → team_merge.
133
+ If team_merge blocks ("overlapping local changes"), commit or stash your local changes first, then retry.
134
+ Fix any other blockers reported.
135
+
136
+ 7. **Quality check**
137
+
138
+ Spawn quality engineer with worktree:false (read-only, no file edits):
139
+ ```
140
+ team_spawn name:"quality" agent:"quality-engineer" worktree:false prompt:"<task list, context summary, run tests + build + lint + verify acceptance criteria, send results to lead when done>"
141
+ ```
142
+ Wait for message → team_results → fix blockers → team_shutdown (no team_merge needed, worktree:false)
143
+
144
+ 8. **Mark tasks complete in openspec**
145
+
146
+ Update tasks.md: `- [ ]` → `- [x]` for each completed task.
147
+ Run `rtk openspec status --change "<name>" --json` to confirm.
148
+
149
+ 9. **Show status, then cleanup**
150
+
151
+ Display:
152
+ - Tasks completed this session
153
+ - Overall progress: "N/M tasks complete"
154
+ - If all done: suggest archive with `/opsx-archive`
155
+ - If paused: explain why and wait for guidance
156
+
157
+ Then run `team_cleanup`.
158
+
159
+ **Guardrails**
160
+ - NEVER skip or reorder steps 6a-6f
161
+ - NEVER implement tasks directly. Always use team_create + team_spawn, no exceptions
162
+ - NEVER touch source files before team_create is called, not even one edit
163
+ - NEVER call team_spawn without the agent field, it is required and will fail without it
164
+ - NEVER call team_spawn before team_tasks_add, tasks must exist before agents are spawned
165
+ - NEVER poll team_results or team_status in a loop, wait for teammates to message you
166
+ - NEVER call team_claim or team_tasks_complete as lead, only agents call these tools
167
+ - ALWAYS pass the task IDs returned by team_tasks_add to each agent's spawn prompt
168
+ - NEVER edit files between team_spawn and team_merge, team_merge blocks on overlapping local changes
169
+ - ALWAYS add every task to the board with team_tasks_add before spawning
170
+ - ALWAYS spawn agents sequentially (wait for each team_spawn result before the next), then send start messages to all of them together
171
+ - ALWAYS instruct agents to call team_claim before each task and team_tasks_complete after
172
+ - If teammates are stuck, use team_message to resend tasks, then wait, never implement directly
173
+ - Mark tasks complete in openspec AFTER specialists finish, not before
174
+ - Pause on errors, blockers, or unclear requirements. Do not guess
175
+ - Use contextFiles from CLI output, do not assume specific file paths
176
+ - Use `rtk` wrapper for ALL CLI commands. Never run openspec, git, gh, or az directly
package/content/AGENTS.md CHANGED
@@ -40,7 +40,7 @@ openspec archive "project-history"
40
40
  1. **Read `DESIGN.md` now** using a file read tool. The file contains a prompt with instructions and an output format.
41
41
  2. **Store the full prompt text** in your context.
42
42
  3. **Overwrite `DESIGN.md` with an empty string** (zero bytes). Do this before generating any content.
43
- 4. **Analyze the actual codebase**: read CSS files, Tailwind config, component files, token definitions. Do not rely on prior knowledge, read the files.
43
+ 4. **Analyze the actual codebase**: use `.agents/source-roots.json` as source roots when present, then read CSS files, Tailwind config, component files, token definitions. Do not rely on prior knowledge, read the files.
44
44
  5. **Write the result into `DESIGN.md`** following exactly the format and sections described in the stored prompt.
45
45
 
46
46
  The output must be a real, populated `DESIGN.md` based on what you found in the codebase, not from memory or assumptions.
@@ -54,7 +54,7 @@ The output must be a real, populated `DESIGN.md` based on what you found in the
54
54
  1. **Read `ARCHITECTURE.md` now** using a file read tool. The file contains a prompt with instructions and an output format.
55
55
  2. **Store the full prompt text** in your context.
56
56
  3. **Overwrite `ARCHITECTURE.md` with an empty string** (zero bytes). Do this before generating any content.
57
- 4. **Analyze the actual codebase**: read folder structure, config files, route definitions, data models, integration points. Do not rely on prior knowledge, read the files.
57
+ 4. **Analyze the actual codebase**: use `.agents/source-roots.json` as source roots when present, then read folder structure, config files, route definitions, data models, integration points. Do not rely on prior knowledge, read the files.
58
58
  5. **Write the result into `ARCHITECTURE.md`** following exactly the format and sections described in the stored prompt.
59
59
 
60
60
  The output must be a real, populated `ARCHITECTURE.md` based on what you found in the codebase, covering all sections the prompt describes.
@@ -72,14 +72,20 @@ Replace the entire contents of this file (`AGENTS.md`) with everything below the
72
72
  Tell the user:
73
73
 
74
74
  ```
75
- Initialization complete.
75
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
76
+ Initialization complete.
77
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
76
78
 
77
79
  - ARCHITECTURE.md generated
78
80
  - DESIGN.md generated
79
81
  - Project history archived in openspec
80
82
  - AGENTS.md updated with real guidance
81
83
 
82
- You're ready to work.
84
+ !! RESTART OPENCODE NOW !!
85
+
86
+ Quit and reopen OpenCode before doing anything else.
87
+ Nothing will work correctly until you do.
88
+ After restarting you are ready to work.
83
89
  ```
84
90
 
85
91
  ---
@@ -108,13 +114,15 @@ This is the agent orchestration layer for your project. It provides:
108
114
 
109
115
  ## I Am the Lead, Full Workflow Ownership
110
116
 
111
- When the user provides a work item URL, says "implement the plan", or "I've added comments to the PR", **I own the full lifecycle**. I load the appropriate skill and use ensemble tools (`team_create`, `team_spawn`, etc.) to coordinate the agent team.
117
+ When the user provides a work item URL or says "implement the plan" or "I've added comments to the PR", **I own the full lifecycle**. I load the appropriate skill and use ensemble tools to coordinate the agent team.
118
+
119
+ Trigger patterns, I recognize ALL of these, exact wording does not matter:
120
+ - User pastes or mentions a GitHub Issue URL → load `ob-userstory-gh` skill → parse issue → run `/opsx-propose` → confirm with user → run `/opsx-apply` → ship
121
+ - User pastes or mentions an Azure DevOps URL → load `ob-userstory-az` skill → parse work item → run `/opsx-propose` → confirm with user → run `/opsx-apply` → ship
122
+ - `implement the plan` / `implement` / `start` / `go` → run `/opsx-apply` → ship
123
+ - `I've added comments to the PR` → read PR comments → fix → update PR
112
124
 
113
- Trigger patterns:
114
- - `work on this <azure-devops-url>` → spawn `devops-manager` in read mode → propose OpenSpec → **confirm with user** → implement → ship
115
- - `work on this <github-url>` → spawn `devops-manager` in read mode → propose OpenSpec → **confirm with user** → implement → ship
116
- - `implement the plan` → run `/opsx-apply` (ensemble orchestration is built into the command) → ship
117
- - `I've added comments to the PR` → spawn `devops-manager` in feedback mode → fix → update PR
125
+ **A GitHub or Azure DevOps URL anywhere in the user's message is always a trigger, regardless of surrounding words.**
118
126
 
119
127
  **Never delegate without a plan. Never write implementation code directly, always spawn specialists, no exceptions. "Small feature", "faster to do it directly", or "environment issues" are not valid reasons to skip ensemble.**
120
128
 
@@ -130,11 +138,14 @@ Works on **all platforms** (Windows, macOS, Linux) via OpenCode's built-in workt
130
138
  | `team_shutdown` | Stop a teammate, preserve their branch |
131
139
  | `team_merge` | Merge a teammate's branch into working dir |
132
140
  | `team_cleanup` | Tear down the team |
133
- | `team_results` | Retrieve full message from a teammate |
134
- | `team_message` | Send a direct message to a teammate |
141
+ | `team_results` | Retrieve full message content (delivery is a ping only) |
142
+ | `team_message` | Send a direct message to a teammate or lead |
135
143
  | `team_broadcast` | Message all teammates |
144
+ | `team_status` | View all members and task summary |
145
+ | `team_tasks_list` | View the shared task board |
136
146
  | `team_tasks_add` | Add tasks to shared board |
137
- | `team_tasks_complete` | Mark task done |
147
+ | `team_tasks_complete` | Mark task done, auto-unblocks dependents |
148
+ | `team_claim` | Atomically claim a pending task (teammates use this) |
138
149
 
139
150
  **Dashboard**: Monitor running agents at **http://localhost:4747/**
140
151
 
@@ -151,12 +162,12 @@ devops-manager (read mode)
151
162
 
152
163
  [confirm with user]
153
164
 
154
- front-engineer + back-engineer + infra-engineer ← parallel, only spawn what the task needs
165
+ back-engineer front-engineer infra-engineer ← sequential, one at a time, only spawn what the task needs
155
166
 
156
- quality-engineer
167
+ quality-engineer (worktree:false)
157
168
  → tests, build, lint, acceptance criteria
158
169
 
159
- security-auditor
170
+ security-auditor (worktree:false)
160
171
  → vulnerability audit, secrets, auth gaps
161
172
 
162
173
  devops-manager (ship mode)
@@ -166,32 +177,35 @@ devops-manager (ship mode)
166
177
  ### Phase 1, Parse & Propose
167
178
 
168
179
  ```
169
- 1. team_spawn devops-manager (read mode) fetch work item via skill, output summary
170
- 2. Load skill: openspec-propose generate proposal.md, specs/, tasks.md
171
- - team_create spawn design + specs in parallel → merge → write tasks.md
172
- 3. Show the plan: change name, schema, total tasks, task list summary
173
- 4. STOP. Ask user: "Ready to implement? (yes/no)", DO NOT proceed until confirmed.
180
+ 1. Detect URL typeload matching skill (ob-userstory-gh or ob-userstory-az)
181
+ 2. Follow skill steps: fetch issue/work item via CLI, create OpenSpec change
182
+ 3. Run /opsx-proposegenerates proposal.md, specs/, design.md, tasks.md
183
+ 4. Show the plan: change name, total tasks, task list summary
184
+ 5. STOP. Ask user: "Ready to implement? (yes/no)", DO NOT proceed until confirmed.
174
185
  ```
175
186
 
176
187
  ### Phase 2, Implement
177
188
 
178
189
  ```
179
190
  1. Run /opsx-apply, handles context reading, ensemble orchestration, and task marking.
191
+ - Lead adds all tasks to board, then spawns specialists ONE AT A TIME (not parallel)
192
+ - Each specialist claims tasks, implements, completes tasks, messages lead when done
193
+ - Lead merges each branch after shutdown, then marks tasks done in tasks.md
180
194
  2. After /opsx-apply completes, proceed to quality check.
181
195
  ```
182
196
 
183
197
  ### Phase 3, Quality
184
198
 
185
199
  ```
186
- 7. team_spawn name:quality agent:quality-engineer → tests, build, lint
187
- 8. Wait → team_results → fix any blockers → team_shutdown
200
+ 3. team_spawn name:quality agent:quality-engineer worktree:false → tests, build, lint
201
+ 4. Wait → team_results → fix any blockers → team_shutdown (no merge, worktree:false)
188
202
  ```
189
203
 
190
204
  ### Phase 4, Security
191
205
 
192
206
  ```
193
- 9. team_spawn name:security agent:security-auditor → audit full change
194
- 10. Wait → team_results → fix Critical findings → team_shutdown
207
+ 5. team_spawn name:security agent:security-auditor worktree:false → audit full change
208
+ 6. Wait → team_results → fix Critical findings → team_shutdown (no merge, worktree:false)
195
209
  ```
196
210
 
197
211
  ### Phase 5, Ship