opencode-onboard 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +304 -301
- package/content/.agents/agents/basic-engineer.md +4 -2
- package/content/.agents/agents/devops-manager.md +123 -123
- package/content/.agents/skills/ob-default/SKILL.md +25 -21
- package/content/.agents/skills/ob-generic-guardrails/SKILL.md +36 -32
- package/content/.agents/skills/ob-global/SKILL.md +92 -49
- package/content/.agents/skills/ob-pullrequest-az/SKILL.md +168 -160
- package/content/.agents/skills/ob-pullrequest-gh/SKILL.md +140 -136
- package/content/.opencode/commands/create-engineer.md +109 -0
- package/content/.opencode/commands/init.md +1 -1
- package/content/.opencode/commands/main.md +1 -1
- package/content/.opencode/commands/opsx-apply.md +131 -70
- package/content/.opencode/commands/plan.md +1 -1
- package/content/.opencode/plugins/session-log.js +523 -519
- package/content/.opencode/skills/openspec-apply-change/SKILL.md +86 -64
- package/content/AGENTS.md +67 -39
- package/package.json +1 -1
- package/src/commands/join.js +3 -3
- package/src/commands/single.js +2 -0
- package/src/commands/wizard.js +124 -99
- package/src/presets/browser.json +22 -18
- package/src/presets/optimization.json +27 -22
- package/src/presets/source.json +7 -1
- package/src/steps/browser/browser.test.js +115 -81
- package/src/steps/browser/index.js +62 -54
- package/src/steps/clean/index.js +108 -107
- package/src/steps/copy/agents.js +28 -0
- package/src/steps/copy/copy.test.js +1 -0
- package/src/steps/copy/index.js +2 -1
- package/src/steps/metadata/index.js +63 -61
- package/src/steps/models/format.js +61 -60
- package/src/steps/models/write.test.js +117 -117
- package/src/steps/openspec/ensemble.js +30 -7
- package/src/steps/openspec/ensemble.test.js +79 -79
- package/src/steps/openspec/index.js +121 -32
- package/src/steps/openspec/index.test.js +63 -0
- package/src/steps/optimization/caveman.js +34 -29
- package/src/steps/optimization/codegraph.js +52 -0
- package/src/steps/optimization/global.js +88 -64
- package/src/steps/optimization/global.test.js +99 -0
- package/src/steps/optimization/index.js +109 -101
- package/src/steps/optimization/optimization.test.js +101 -93
- package/src/steps/optimization/quota.js +84 -84
- package/src/steps/source/index.js +48 -0
- package/src/steps/source/source.test.js +124 -91
- package/src/utils/__tests__/copy.test.js +117 -117
- package/src/utils/exec-spinner.js +47 -47
- package/src/utils/exec.js +134 -131
- package/src/utils/terminal.js +6 -0
|
@@ -92,71 +92,90 @@ Implement tasks from an OpenSpec change using the ensemble agent team.
|
|
|
92
92
|
DO NOT call team_claim yourself, only agents claim tasks.
|
|
93
93
|
DO NOT proceed to 6d until team_tasks_add succeeds.
|
|
94
94
|
|
|
95
|
-
**Step 6d.** Discover available agents, assign
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
95
|
+
**Step 6d.** Discover available agents, assign an INITIAL BATCH of tasks, then spawn workers.
|
|
96
|
+
|
|
97
|
+
**ROLLING BATCH MODEL:**
|
|
98
|
+
Agents do NOT receive all their tasks upfront. Instead:
|
|
99
|
+
- Assign each agent an initial batch of up to 3 unblocked tasks.
|
|
100
|
+
- 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.
|
|
101
|
+
- Repeat until no pending tasks remain on the board.
|
|
102
|
+
- Only shut down an agent when the board has no more tasks for its domain.
|
|
103
|
+
|
|
104
|
+
Agent discovery and assignment rule:
|
|
105
|
+
- Read `.agents/agents/*.md` and use each agent's `description` and `## Abilities` to understand specialization.
|
|
106
|
+
- For each task ID, choose the best-fit agent based on task domain (backend, frontend, infra, testing, etc.).
|
|
107
|
+
- Prefer specialized agents when available; use `basic-engineer` as fallback only.
|
|
108
|
+
- Only spawn agents that have assigned task IDs.
|
|
109
|
+
|
|
110
|
+
REQUIRED assignment algorithm (do not skip):
|
|
111
|
+
1. Build candidate list from `.agents/agents/*.md` excluding `devops-manager`.
|
|
112
|
+
2. Classify each task by domain using task text (api/backend, ui/frontend, infra/devops, testing/qa).
|
|
113
|
+
3. For each task, score every candidate agent:
|
|
114
|
+
- +3 if agent description explicitly matches domain
|
|
115
|
+
- +2 if agent `## Abilities` include domain-relevant skills
|
|
116
|
+
- +1 if prior tasks of same domain already assigned to that agent (cohesion)
|
|
117
|
+
4. Assign task to highest-score agent.
|
|
118
|
+
5. Use `basic-engineer` ONLY when no specialized agent has positive score.
|
|
119
|
+
6. If all tasks go to `basic-engineer`, you MUST explain why no specialist matched.
|
|
120
|
+
|
|
121
|
+
HARD RULES:
|
|
122
|
+
- NEVER assign a task to `basic-engineer` if a specialized agent has higher score.
|
|
123
|
+
- NEVER skip agent discovery from `.agents/agents/*.md`.
|
|
124
|
+
- ALWAYS include assignment rationale in spawn prompt: "Selected because <domain match>".
|
|
125
|
+
|
|
126
|
+
Skill loading is worker-driven:
|
|
127
|
+
- The spawned agent MUST load `@ob-global` first.
|
|
128
|
+
- Then it MUST load skills from its own `## Abilities` for the claimed task domain.
|
|
129
|
+
|
|
130
|
+
Each team_spawn MUST include the agent field (required, causes NOT NULL error if omitted).
|
|
131
|
+
|
|
132
|
+
The spawn prompt must contain exactly:
|
|
133
|
+
1. Their name and role on this team
|
|
134
|
+
1.1 Why they were selected for those tasks (domain/abilities match)
|
|
135
|
+
2. Their initial batch of tasks (up to 3): list the LITERAL task IDs and content from the board.
|
|
136
|
+
3. Key context they need (summarized from context files, do NOT tell them to read files themselves)
|
|
137
|
+
4. The 6 OpenCode tools they have available (these are OpenCode tools, NOT shell commands, call them directly as tools, never via bash):
|
|
138
|
+
team_claim, team_tasks_complete, team_tasks_list, team_tasks_add, team_message, team_broadcast
|
|
139
|
+
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 listed tasks are done, then call team_message tool to notify lead with results. Lead may assign more tasks, do NOT shut down until lead confirms no more tasks.
|
|
140
|
+
6. Which skills to load: list the skill names and paths they MUST read before implementing. Example: "Before starting, read `.agents/skills/next-best-practices/SKILL.md` and follow its rules for all Next.js code."
|
|
141
|
+
|
|
142
|
+
Keep spawn prompts under 600 tokens. Do not describe team internals or how ensemble works.
|
|
143
|
+
Only spawn agents whose tasks are actually needed by this change. Skip agents with no tasks.
|
|
144
|
+
|
|
145
|
+
Spawn one or more best-fit workers (parallel when dependencies allow):
|
|
146
|
+
```
|
|
147
|
+
team_spawn name:"eng-1" agent:"backend-engineer" prompt:"..."
|
|
148
|
+
team_spawn name:"eng-2" agent:"frontend-engineer" prompt:"..."
|
|
149
|
+
team_spawn name:"eng-3" agent:"basic-engineer" prompt:"..."
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Then immediately send each spawned worker a start message with exact task IDs:
|
|
153
|
+
```
|
|
154
|
+
team_message to:"eng-1" text:"Start now. Load @ob-global first, then use your agent `## Abilities` for these tasks: [task-<id1>] ... Claim each task ID before starting."
|
|
155
|
+
team_message to:"eng-2" text:"Start now. Load @ob-global first, then use your agent `## Abilities` for these tasks: [task-<id2>] ... Claim each task ID before starting."
|
|
156
|
+
team_message to:"eng-3" text:"Start now. Load @ob-global first, then use your agent `## Abilities` for these tasks: [task-<id3>] ... Claim each task ID before starting."
|
|
157
|
+
```
|
|
151
158
|
|
|
152
159
|
**Step 6e.** After sending start messages, tell the user what is running, then STOP and wait.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
**Step 6f.** When a teammate messages back
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
Do NOT call team_results, team_status, or team_broadcast in a loop.
|
|
161
|
+
Teammates will message you when done or blocked. Wait for those messages.
|
|
162
|
+
|
|
163
|
+
**Step 6f.** When a teammate messages back (rolling re-assignment loop):
|
|
164
|
+
1. Call `team_results from:"<name>"` to read full message.
|
|
165
|
+
2. Call `team_tasks_list` to check remaining pending/unassigned tasks on the board.
|
|
166
|
+
3. **If there are more unassigned tasks matching this agent's domain:**
|
|
167
|
+
- Pick up to 3 unassigned, unblocked tasks for this agent's domain.
|
|
168
|
+
- Send them via `team_message to:"<name>" text:"Next tasks: [task-<id1>] <desc>, [task-<id2>] <desc>. Claim each with team_claim before starting."`
|
|
169
|
+
- Do NOT shut down the agent. Go back to waiting (step 6e).
|
|
170
|
+
4. **If no more tasks for this agent:**
|
|
171
|
+
- `team_shutdown member:"<name>"`
|
|
172
|
+
- `team_merge member:"<name>"`
|
|
173
|
+
- If team_merge blocks on local changes: `git stash`, retry merge, `git stash pop`.
|
|
174
|
+
5. **If ALL agents are shut down and tasks remain unassigned:**
|
|
175
|
+
- Spawn new agents for the remaining tasks (back to step 6d).
|
|
176
|
+
6. **If ALL tasks are done:** proceed to step 7.
|
|
177
|
+
|
|
178
|
+
**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.
|
|
160
179
|
|
|
161
180
|
7. **Verification check**
|
|
162
181
|
|
|
@@ -189,11 +208,14 @@ Implement tasks from an OpenSpec change using the ensemble agent team.
|
|
|
189
208
|
- NEVER call team_spawn before team_tasks_add, tasks must exist before agents are spawned
|
|
190
209
|
- NEVER poll team_results or team_status in a loop, wait for teammates to message you
|
|
191
210
|
- NEVER call team_claim or team_tasks_complete as lead, only agents call these tools
|
|
192
|
-
-
|
|
211
|
+
- NEVER leave pending tasks orphaned, always verify board is empty before proceeding to step 7
|
|
212
|
+
- 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
|
|
213
|
+
- ALWAYS call team_tasks_list after each agent reports done to check for remaining unassigned tasks
|
|
193
214
|
- NEVER edit files between team_spawn and team_merge, team_merge blocks on overlapping local changes
|
|
194
215
|
- ALWAYS add every task to the board with team_tasks_add before spawning
|
|
195
216
|
- ALWAYS spawn workers based on dependencies: parallel when safe, sequential when required
|
|
196
217
|
- ALWAYS instruct agents to call team_claim before each task and team_tasks_complete after
|
|
218
|
+
- ALWAYS shut down + merge agents only when no more tasks remain for their domain
|
|
197
219
|
- If teammates are stuck, use team_message to resend tasks, then wait, never implement directly
|
|
198
220
|
- Mark tasks complete in openspec AFTER worker implementation and verification finish, not before
|
|
199
221
|
- Pause on errors, blockers, or unclear requirements. Do not guess
|
package/content/AGENTS.md
CHANGED
|
@@ -63,13 +63,32 @@ The output must be a real, populated `ARCHITECTURE.md` based on what you found i
|
|
|
63
63
|
|
|
64
64
|
---
|
|
65
65
|
|
|
66
|
-
### Step 4,
|
|
66
|
+
### Step 4, Populate OpenSpec config
|
|
67
|
+
|
|
68
|
+
Write `openspec/config.yaml` with the real project information discovered during steps 1-3. Overwrite whatever is currently in the file. The output must contain `schema: spec-driven` and a populated `context:` block. Do not leave placeholder text.
|
|
69
|
+
|
|
70
|
+
```yaml
|
|
71
|
+
schema: spec-driven
|
|
72
|
+
|
|
73
|
+
context: |
|
|
74
|
+
Tech stack: <languages, frameworks, libraries found in the codebase>
|
|
75
|
+
Build system: <build tools, package managers>
|
|
76
|
+
Architecture: <monolith, microservices, monorepo, etc.>
|
|
77
|
+
Conventions: <coding style, commit conventions, branching strategy if found>
|
|
78
|
+
Domain: <what this project does, in one line>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Replace every `<…>` with real values from the codebase. Add a `rules:` section only if the codebase has clear conventions worth enforcing (e.g., max task size, proposal format). Do not invent rules that aren't evidenced by the codebase.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
### Step 5, Rewrite this file
|
|
67
86
|
|
|
68
87
|
Replace the entire contents of this file (`AGENTS.md`) with everything below the line `<!-- AGENTS-TEMPLATE-START -->` in this same file. Delete the bootstrap section and the template marker, the file should contain only the template content when done.
|
|
69
88
|
|
|
70
89
|
---
|
|
71
90
|
|
|
72
|
-
### Step
|
|
91
|
+
### Step 6, Confirm
|
|
73
92
|
|
|
74
93
|
Tell the user:
|
|
75
94
|
|
|
@@ -80,6 +99,7 @@ Tell the user:
|
|
|
80
99
|
|
|
81
100
|
- ARCHITECTURE.md generated
|
|
82
101
|
- DESIGN.md generated
|
|
102
|
+
- openspec/config.yaml populated
|
|
83
103
|
- Project history archived in openspec
|
|
84
104
|
- AGENTS.md updated with real guidance
|
|
85
105
|
|
|
@@ -98,7 +118,7 @@ After restarting you are ready to work.
|
|
|
98
118
|
- Do NOT create branches or PRs
|
|
99
119
|
- Do NOT modify any project source files
|
|
100
120
|
- Do NOT create CLI wrapper files or scripts
|
|
101
|
-
- Only read source files for analysis, write only to ARCHITECTURE.md, DESIGN.md, AGENTS.md, and openspec/
|
|
121
|
+
- Only read source files for analysis, write only to ARCHITECTURE.md, DESIGN.md, AGENTS.md, openspec/config.yaml, and openspec/
|
|
102
122
|
|
|
103
123
|
<!-- AGENTS-TEMPLATE-START -->
|
|
104
124
|
# AGENTS.md
|
|
@@ -138,18 +158,25 @@ Trigger patterns, I recognize ALL of these, exact wording does not matter:
|
|
|
138
158
|
|
|
139
159
|
**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.**
|
|
140
160
|
|
|
141
|
-
## Multi-Agent Execution, opencode-ensemble
|
|
142
|
-
|
|
143
|
-
Parallel execution uses the `opencode-ensemble` plugin (`team_create`, `team_spawn`, etc.).
|
|
144
|
-
Works on **all platforms** (Windows, macOS, Linux) via OpenCode's built-in worktree support.
|
|
145
|
-
|
|
146
|
-
Core tools used in this workflow:
|
|
147
|
-
- `team_create`, `team_spawn`, `team_shutdown`, `team_merge`, `team_cleanup`
|
|
148
|
-
- `team_tasks_add`, `team_tasks_list`, `team_claim`, `team_tasks_complete`
|
|
149
|
-
- `team_message`, `team_results`, `team_status`
|
|
161
|
+
## Multi-Agent Execution, opencode-ensemble
|
|
162
|
+
|
|
163
|
+
Parallel execution uses the `opencode-ensemble` plugin (`team_create`, `team_spawn`, etc.).
|
|
164
|
+
Works on **all platforms** (Windows, macOS, Linux) via OpenCode's built-in worktree support.
|
|
165
|
+
|
|
166
|
+
Core tools used in this workflow:
|
|
167
|
+
- `team_create`, `team_spawn`, `team_shutdown`, `team_merge`, `team_cleanup`
|
|
168
|
+
- `team_tasks_add`, `team_tasks_list`, `team_claim`, `team_tasks_complete`
|
|
169
|
+
- `team_message`, `team_results`, `team_status`
|
|
150
170
|
|
|
151
171
|
**Dashboard**: Monitor running agents at **http://localhost:4747/**
|
|
152
172
|
|
|
173
|
+
**Hard limits:**
|
|
174
|
+
- **Max {{MAX_CONCURRENT_AGENTS}} truly concurrent agents.** All {{MAX_CONCURRENT_AGENTS}} must be spawned and running simultaneously, not sequentially. Spawn in waves if more than {{MAX_CONCURRENT_AGENTS}} are needed. Wait for wave N to finish before spawning wave N+1.
|
|
175
|
+
- **Non-overlapping file domains.** Each agent owns exclusive directories. Two agents must NEVER touch the same file.
|
|
176
|
+
- **Immediate shutdown on completion.** The moment an agent's domain has no more pending tasks → `team_shutdown` → `team_merge`. Keep agents alive if more tasks in their domain are pending (rolling batch).
|
|
177
|
+
- **Rolling batch assignment.** Agents receive up to 3 tasks initially. When they complete a batch, lead assigns the next batch of up to 3 from the board. Never leave pending tasks orphaned.
|
|
178
|
+
- **Stall detection at 5 minutes.** No commits after 5 min → nudge message → 2 min grace → force shutdown + respawn.
|
|
179
|
+
|
|
153
180
|
**Progress inspection commands (tell user explicitly after spawning):**
|
|
154
181
|
- `team_status` for live team snapshot
|
|
155
182
|
- `team_tasks_list` for task board state
|
|
@@ -163,7 +190,7 @@ If a teammate stalls due to model quota/rate-limit exhaustion:
|
|
|
163
190
|
|
|
164
191
|
---
|
|
165
192
|
|
|
166
|
-
## Pipeline
|
|
193
|
+
## Pipeline
|
|
167
194
|
|
|
168
195
|
```
|
|
169
196
|
devops-manager (lead mode)
|
|
@@ -181,7 +208,7 @@ devops-manager (ship mode)
|
|
|
181
208
|
→ verify completion → commit → push → PR → post comment
|
|
182
209
|
```
|
|
183
210
|
|
|
184
|
-
### Phase 1, Parse & Propose
|
|
211
|
+
### Phase 1, Parse & Propose
|
|
185
212
|
|
|
186
213
|
```
|
|
187
214
|
1. Detect URL type → load matching skill (ob-userstory-gh or ob-userstory-az)
|
|
@@ -191,16 +218,17 @@ devops-manager (ship mode)
|
|
|
191
218
|
5. STOP. Ask user: "Ready to implement? (yes/no)", DO NOT proceed until confirmed.
|
|
192
219
|
```
|
|
193
220
|
|
|
194
|
-
### Phase 2, Implement
|
|
195
|
-
|
|
196
|
-
```
|
|
197
|
-
1. Run /opsx-apply.
|
|
198
|
-
- Lead adds all tasks to board.
|
|
199
|
-
- Lead spawns
|
|
200
|
-
- Each engineer
|
|
201
|
-
- Lead
|
|
202
|
-
|
|
203
|
-
|
|
221
|
+
### Phase 2, Implement
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
1. Run /opsx-apply.
|
|
225
|
+
- Lead adds all tasks to board.
|
|
226
|
+
- Lead spawns engineers with initial batch of up to 3 tasks each (rolling batch model).
|
|
227
|
+
- Each engineer claims tasks, implements, completes, messages lead.
|
|
228
|
+
- Lead assigns next batch (up to 3) to agents that report done. Repeat until board empty.
|
|
229
|
+
- Lead merges each engineer branch after shutdown, then marks tasks done in tasks.md.
|
|
230
|
+
2. Verify with tests/build/lint according to task scope.
|
|
231
|
+
```
|
|
204
232
|
|
|
205
233
|
### Phase 3, Ship
|
|
206
234
|
|
|
@@ -254,7 +282,7 @@ Default `basic-engineer` abilities:
|
|
|
254
282
|
- Infrastructure: @ob-default
|
|
255
283
|
```
|
|
256
284
|
|
|
257
|
-
## Skills
|
|
285
|
+
## Skills
|
|
258
286
|
|
|
259
287
|
Skills provide platform and tech-specific knowledge. Agents detect and load them automatically, **you never tell an agent which skill to use**.
|
|
260
288
|
|
|
@@ -273,10 +301,10 @@ Skills are located in `.agents/skills/`. Each skill has a `SKILL.md` with a desc
|
|
|
273
301
|
| `ob-pullrequest-gh` | Create PR on GitHub |
|
|
274
302
|
| `openspec-propose` | Propose change artifacts (proposal, specs, tasks) |
|
|
275
303
|
| `openspec-apply-change` | Implement change with agent team |
|
|
276
|
-
| `openspec-archive-change` | Archive completed change |
|
|
277
|
-
| `browser-automation` | Browser automation for localhost UI, screenshots, clicks, queries |
|
|
278
|
-
|
|
279
|
-
Execution rules live in skills. Keep AGENTS.md focused on orchestration and routing.
|
|
304
|
+
| `openspec-archive-change` | Archive completed change |
|
|
305
|
+
| `browser-automation` | Browser automation for localhost UI, screenshots, clicks, queries |
|
|
306
|
+
|
|
307
|
+
Execution rules live in skills. Keep AGENTS.md focused on orchestration and routing.
|
|
280
308
|
|
|
281
309
|
---
|
|
282
310
|
|
|
@@ -317,16 +345,16 @@ When `## Source Roots` lists multiple roots, each root is an independent git rep
|
|
|
317
345
|
|
|
318
346
|
---
|
|
319
347
|
|
|
320
|
-
## Guardrails
|
|
321
|
-
|
|
322
|
-
Guardrails are mandatory via `ob-global` and ability-loaded skills.
|
|
323
|
-
|
|
324
|
-
Minimal non-negotiables:
|
|
325
|
-
- Never commit or push to `main`.
|
|
326
|
-
- Never force push.
|
|
327
|
-
- Never expose or commit secrets.
|
|
328
|
-
- Use `gh`/`az` CLI for platform operations.
|
|
329
|
-
- In multi-repo source scope, run git operations per repository.
|
|
348
|
+
## Guardrails
|
|
349
|
+
|
|
350
|
+
Guardrails are mandatory via `ob-global` and ability-loaded skills.
|
|
351
|
+
|
|
352
|
+
Minimal non-negotiables:
|
|
353
|
+
- Never commit or push to `main`.
|
|
354
|
+
- Never force push.
|
|
355
|
+
- Never expose or commit secrets.
|
|
356
|
+
- Use `gh`/`az` CLI for platform operations.
|
|
357
|
+
- In multi-repo source scope, run git operations per repository.
|
|
330
358
|
|
|
331
359
|
---
|
|
332
360
|
|
package/package.json
CHANGED
package/src/commands/join.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
|
-
import { header, info } from '../utils/exec.js'
|
|
3
2
|
import { installBrowser } from '../steps/browser/index.js'
|
|
4
3
|
import { checkRtk } from '../steps/optimization/index.js'
|
|
5
|
-
import {
|
|
4
|
+
import { checkPlatform, choosePlatform } from '../steps/platform/index.js'
|
|
5
|
+
import { header, info } from '../utils/exec.js'
|
|
6
6
|
import { readOnboardConfig } from './shared.js'
|
|
7
7
|
|
|
8
8
|
export async function runJoin() {
|
|
9
9
|
const logo = chalk.hex('#fe3d57')
|
|
10
10
|
console.log()
|
|
11
11
|
console.log(logo(' 🤝 opencode-onboard join'))
|
|
12
|
-
console.log(chalk.dim(' New team member setup
|
|
12
|
+
console.log(chalk.dim(' New team member setup, checks & local installs only'))
|
|
13
13
|
console.log(chalk.dim(' This will NOT modify any project files.'))
|
|
14
14
|
console.log()
|
|
15
15
|
|
package/src/commands/single.js
CHANGED
|
@@ -17,6 +17,7 @@ export async function runSingleCommand(command) {
|
|
|
17
17
|
hasOpenspec: !!savedWizard?.preserved?.openspec,
|
|
18
18
|
sourceMode: savedWizard?.sourceMode ?? 'current',
|
|
19
19
|
sourceRoots: Array.isArray(savedWizard?.sourceRoots) ? savedWizard.sourceRoots : [],
|
|
20
|
+
maxConcurrentAgents: savedWizard?.maxConcurrentAgents ?? 4,
|
|
20
21
|
}
|
|
21
22
|
const platform = savedWizard?.platform
|
|
22
23
|
const resolvedPlatform = platform === 'azure' || platform === 'github' ? platform : 'github'
|
|
@@ -47,6 +48,7 @@ export async function runSingleCommand(command) {
|
|
|
47
48
|
await writeOnboardConfig({
|
|
48
49
|
...ctx,
|
|
49
50
|
platform: resolvedPlatform,
|
|
51
|
+
maxConcurrentAgents: savedWizard?.maxConcurrentAgents ?? 4,
|
|
50
52
|
additionalSkillsProvider: 'npx-skills',
|
|
51
53
|
planModel: savedWizard?.models?.plan ?? null,
|
|
52
54
|
buildModel: savedWizard?.models?.build ?? null,
|
package/src/commands/wizard.js
CHANGED
|
@@ -1,99 +1,124 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
logo('
|
|
17
|
-
logo('
|
|
18
|
-
logo('
|
|
19
|
-
logo('
|
|
20
|
-
logo('
|
|
21
|
-
logo('
|
|
22
|
-
logo('
|
|
23
|
-
logo('
|
|
24
|
-
logo('
|
|
25
|
-
logo(' ▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓ '),
|
|
26
|
-
logo('
|
|
27
|
-
'',
|
|
28
|
-
|
|
29
|
-
chalk.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
console.log()
|
|
34
|
-
console.log(
|
|
35
|
-
console.log('
|
|
36
|
-
console.log()
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
console.log()
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
process.stdin.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
1
|
+
import { select as wizardSelect } from '@inquirer/prompts'
|
|
2
|
+
import chalk from 'chalk'
|
|
3
|
+
import { chooseSourceScope } from '../steps/source/index.js'
|
|
4
|
+
import { cleanAiFiles } from '../steps/clean/index.js'
|
|
5
|
+
import { choosePlatform } from '../steps/platform/index.js'
|
|
6
|
+
import { copyContentStep } from '../steps/copy/index.js'
|
|
7
|
+
import { initOpenspec } from '../steps/openspec/index.js'
|
|
8
|
+
import { chooseModels } from '../steps/models/index.js'
|
|
9
|
+
import { tokenOptimizationStep } from '../steps/optimization/index.js'
|
|
10
|
+
import { installBrowser } from '../steps/browser/index.js'
|
|
11
|
+
import { writeOnboardConfig } from '../steps/metadata/index.js'
|
|
12
|
+
|
|
13
|
+
export async function runWizard(version) {
|
|
14
|
+
const logo = chalk.hex('#fe3d57')
|
|
15
|
+
const bannerLines = [
|
|
16
|
+
logo(' '),
|
|
17
|
+
logo(' ▒▒▒▒▒▒▒▒▒▒▒▒▒ '),
|
|
18
|
+
logo(' ▒▒▓ ▓▒▓ '),
|
|
19
|
+
logo(' ▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▓▓▒▒▒▒▒ '),
|
|
20
|
+
logo(' ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓ '),
|
|
21
|
+
logo(' ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓ '),
|
|
22
|
+
logo(' ▓▒▒▒▒░░░▒▒▒▒▒▒▒▒▒▒▒░░░▒▒▒▓▓ '),
|
|
23
|
+
logo(' ▓▓▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓▓▓ '),
|
|
24
|
+
logo(' ▓▓▒▒▒▒▒▒░▒▒▒▒▒▒▒░▒▒▒▒▒▒▓▓ '),
|
|
25
|
+
logo(' ▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓ '),
|
|
26
|
+
logo(' ▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓ '),
|
|
27
|
+
logo(' ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ '),
|
|
28
|
+
'',
|
|
29
|
+
chalk.bold(' 🧰 opencode-onboard') + chalk.dim(` v${version}`),
|
|
30
|
+
chalk.dim(' Prepare your codebase for AI agents'),
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
for (const line of bannerLines) console.log(line)
|
|
34
|
+
console.log()
|
|
35
|
+
console.log(' This tool will set up your project with a team of AI agents,')
|
|
36
|
+
console.log(' install skills, select models, and configure OpenCode.')
|
|
37
|
+
console.log()
|
|
38
|
+
|
|
39
|
+
// Only wait for Enter in a real interactive TTY
|
|
40
|
+
if (process.stdin.isTTY) {
|
|
41
|
+
console.log(chalk.bold(' Press Enter to begin...'))
|
|
42
|
+
console.log()
|
|
43
|
+
await new Promise(resolve => {
|
|
44
|
+
process.stdin.resume()
|
|
45
|
+
process.stdin.once('data', () => {
|
|
46
|
+
process.stdin.pause()
|
|
47
|
+
resolve()
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const scope = await chooseSourceScope()
|
|
53
|
+
|
|
54
|
+
const maxConcurrentAgents = await wizardSelect({
|
|
55
|
+
message: 'Max concurrent agents:',
|
|
56
|
+
default: 4,
|
|
57
|
+
choices: [
|
|
58
|
+
{ name: '2', value: 2, description: 'Conservative — lower resource usage' },
|
|
59
|
+
{ name: '3', value: 3, description: 'Moderate parallelism' },
|
|
60
|
+
{ name: '4 (default)', value: 4, description: 'Recommended for most projects' },
|
|
61
|
+
{ name: '5', value: 5, description: 'High parallelism — requires more resources' },
|
|
62
|
+
{ name: '6', value: 6, description: 'Maximum parallelism' },
|
|
63
|
+
],
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
const installScope = await wizardSelect({
|
|
67
|
+
message: 'Install dependencies:',
|
|
68
|
+
default: 'local',
|
|
69
|
+
choices: [
|
|
70
|
+
{ name: 'Locally (default)', value: 'local', description: 'Install tools project-locally where possible' },
|
|
71
|
+
{ name: 'Globally', value: 'global', description: 'Install tools globally (affects all projects on this machine)' },
|
|
72
|
+
],
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
const preserve = await cleanAiFiles()
|
|
76
|
+
const ctx = { ...preserve, ...scope, maxConcurrentAgents, installScope }
|
|
77
|
+
|
|
78
|
+
const platform = await choosePlatform()
|
|
79
|
+
|
|
80
|
+
await copyContentStep(platform, ctx)
|
|
81
|
+
|
|
82
|
+
const openspec = await initOpenspec()
|
|
83
|
+
|
|
84
|
+
const selectedModels = await chooseModels()
|
|
85
|
+
|
|
86
|
+
const tokenOpt = await tokenOptimizationStep({ ctx })
|
|
87
|
+
const { rtk, quota, caveman, cavemanGuidance } = tokenOpt
|
|
88
|
+
|
|
89
|
+
await installBrowser(ctx)
|
|
90
|
+
|
|
91
|
+
await writeOnboardConfig({
|
|
92
|
+
...ctx,
|
|
93
|
+
platform,
|
|
94
|
+
openspec,
|
|
95
|
+
maxConcurrentAgents,
|
|
96
|
+
installScope,
|
|
97
|
+
additionalSkillsProvider: 'npx-skills',
|
|
98
|
+
...selectedModels,
|
|
99
|
+
optionalTools: { rtk, quota, caveman },
|
|
100
|
+
cavemanGuidance,
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
const toGenerate = [
|
|
104
|
+
!ctx.hasDesign && 'DESIGN.md',
|
|
105
|
+
!ctx.hasArchitecture && 'ARCHITECTURE.md',
|
|
106
|
+
].filter(Boolean)
|
|
107
|
+
|
|
108
|
+
console.log()
|
|
109
|
+
console.log(chalk.bold.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
110
|
+
console.log(chalk.bold.green(' Onboarding complete!'))
|
|
111
|
+
console.log(chalk.bold.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
112
|
+
console.log()
|
|
113
|
+
console.log(' Open this project in OpenCode and type:')
|
|
114
|
+
console.log(chalk.bold(' "init"'))
|
|
115
|
+
console.log()
|
|
116
|
+
if (toGenerate.length > 0) {
|
|
117
|
+
console.log(` OpenCode will generate ${toGenerate.join(' and ')}`)
|
|
118
|
+
console.log(' from your actual codebase, then activate the agent team.')
|
|
119
|
+
} else {
|
|
120
|
+
console.log(' OpenCode will activate the agent team.')
|
|
121
|
+
}
|
|
122
|
+
console.log(` Source scope: ${ctx.sourceMode === 'parent-selected' ? ctx.sourceRoots.map(p => `../${p.split(/[/\\]/).pop()}`).join(', ') : 'current folder'}`)
|
|
123
|
+
console.log()
|
|
124
|
+
}
|