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.
- package/content/.agents/agents/back-engineer.md +10 -0
- package/content/.agents/agents/front-engineer.md +10 -0
- package/content/.agents/agents/quality-engineer.md +9 -0
- package/content/.opencode/commands/opsx-apply.md +170 -0
- package/content/.opencode/plugins/session-log.js +75 -6
- package/content/.opencode/skills/openspec-apply-change/SKILL.md +176 -0
- package/content/AGENTS.md +39 -25
- package/package.json +1 -1
- package/src/index.js +53 -33
- package/src/steps/check-platform.js +2 -2
- package/src/steps/check-rtk.js +1 -1
- package/src/steps/choose-models.js +8 -7
- package/src/steps/choose-platform.js +1 -1
- package/src/steps/choose-skills-provider.js +1 -1
- package/src/steps/choose-source-scope.js +81 -0
- package/src/steps/clean-ai-files.js +64 -30
- package/src/steps/copy-content.js +10 -3
- package/src/steps/init-openspec.js +84 -67
- package/src/steps/install-browser.js +1 -1
- package/src/steps/patch-agents-md.js +85 -0
- package/src/utils/copy.js +20 -6
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
85
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
170
|
-
2.
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
180
|
+
1. Detect URL type → load 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-propose → generates 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
|
-
|
|
187
|
-
|
|
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
|
-
|
|
194
|
-
|
|
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
|