@jiggai/recipes 0.3.1 → 0.3.2

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/README.md CHANGED
@@ -6,7 +6,9 @@
6
6
 
7
7
  ClawRecipes is an OpenClaw plugin that provides **CLI-first recipes** for scaffolding specialist agents and teams from Markdown.
8
8
 
9
- If you like durable workflows: ClawRecipes is built around a **file-first team workspace** (inbox/backlog/in-progress/testing/done) that plays nicely with git.
9
+ If you like durable workflows, ClawRecipes is built around a **file-first team workspace** (inbox/backlog/in-progress/testing/done) that plays nicely with git.
10
+
11
+ For those who prefer a beautiful user interface, install **[ClawKitchen](https://github.com/JIGGAI/ClawKitchen)** — our latest plugin where you can add, remove, update, and fully manage your teams in one place. It includes an agile workflow board, a goal tracker, and cron management for convenience.
10
12
 
11
13
  ## Quickstart
12
14
  ### 1) Install
@@ -54,16 +56,6 @@ openclaw recipes dispatch \
54
56
  --owner lead
55
57
  ```
56
58
 
57
- ## License
58
-
59
- ClawRecipes is licensed under **Apache-2.0**.
60
-
61
- Attribution requirement (practical): if you redistribute ClawRecipes (or a derivative work), you must retain the license and attribution notices (see `LICENSE` and `NOTICE`).
62
-
63
- Branding note: the license does not grant permission to use JIGGAI trademarks except as required for reasonable and customary attribution. See `TRADEMARK.md`.
64
-
65
- Contributions: we welcome PRs. By contributing, you agree that your contributions are licensed under the project’s Apache-2.0 license.
66
-
67
59
  ## Commands (high level)
68
60
  - `openclaw recipes list|show|status`
69
61
  - `openclaw recipes scaffold` (agent → `workspace-<agentId>` + writes workspace recipe `~/.openclaw/workspace/recipes/<agentId>.md` by default)
@@ -118,7 +110,9 @@ Run:
118
110
  - `npm run test:smoke` (or `npm run scaffold:smoke`)
119
111
 
120
112
  Notes:
121
- - Creates a temporary `workspace-smoke-<timestamp>-team` under `~/.openclaw/` and then deletes it.
113
+ - Creates a temporary `workspace-smoke-<timestamp>-team` under `~/.openclaw/`.
114
+ - If it does not delete cleanly (crash/interrupt), run cleanup:
115
+ - `openclaw recipes cleanup-workspaces --prefix smoke- --yes`
122
116
  - Exits non-zero on mismatch.
123
117
  - Requires OpenClaw and workspace config.
124
118
 
@@ -180,9 +174,20 @@ Most users should focus on:
180
174
  - running the file-first workflow (dispatch → backlog → in-progress → testing → done)
181
175
 
182
176
  ## Goals
183
- - Release Clawmarket, https://github.com/JIGGAI/ClawMarket, public url https://clawkitchen.ai
184
- - Release ClawKitchen, https://github.com/JIGGAI/ClawKitchen
185
- - Merge at least 1 community pull request
177
+ - ~~Release Clawmarket, https://github.com/JIGGAI/ClawMarket, public url https://clawkitchen.ai~~
178
+ - ~~Release ClawKitchen, https://github.com/JIGGAI/ClawKitchen~~
179
+ - ~~Merge at least 1 community pull request~~
186
180
  - Daily shipping/pull requests of ClawRecipes features
187
181
  - Improve recipes with more detailed agent files
188
- - Add ability to install skills for agents through ClawKitchen
182
+ - Add ability to install skills for agents through ClawKitchen
183
+ - Integrate ClawKitchen with ClawMarket to pull new recipes
184
+
185
+ ## License
186
+
187
+ ClawRecipes is licensed under **Apache-2.0**.
188
+
189
+ Attribution requirement (practical): if you redistribute ClawRecipes (or a derivative work), you must retain the license and attribution notices (see `LICENSE` and `NOTICE`).
190
+
191
+ Branding note: the license does not grant permission to use JIGGAI trademarks except as required for reasonable and customary attribution. See `TRADEMARK.md`.
192
+
193
+ Contributions: we welcome PRs. By contributing, you agree that your contributions are licensed under the project’s Apache-2.0 license.
@@ -59,6 +59,15 @@ openclaw cron list
59
59
  openclaw cron run <jobId>
60
60
  ```
61
61
 
62
+ ## Cleanup (important)
63
+ These verification commands create temporary `workspace-<teamId>` directories.
64
+
65
+ After you finish (or between runs), clean up test workspaces so they don’t accumulate:
66
+
67
+ ```bash
68
+ openclaw recipes cleanup-workspaces --prefix smoke- --prefix qa- --prefix tmp- --prefix test- --yes
69
+ ```
70
+
62
71
  ## What to record
63
72
  - Any recipe that fails to scaffold
64
73
  - Any cron job install/update errors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jiggai/recipes",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "ClawRecipes plugin for OpenClaw (markdown recipes -> scaffold agents/teams)",
5
5
  "main": "index.ts",
6
6
  "type": "commonjs",
@@ -2,292 +2,334 @@
2
2
  id: stock-trader-team
3
3
  name: Stock Trader Team
4
4
  version: 0.1.0
5
- description: A trading support team (research, signals, risk, journaling, ops) coordinated via a shared workspace.
5
+ description: A trading support team (research, signals, risk, journaling, ops) coordinated
6
+ via a shared workspace.
6
7
  kind: team
7
8
  cronJobs:
8
- - id: lead-triage-loop
9
- name: "Lead triage loop"
10
- schedule: "*/30 7-23 * * 1-5"
11
- timezone: "America/New_York"
12
- message: "Automated lead triage loop (Stock Trader): triage research/tickets, assign work, and update notes/status.md."
13
- enabledByDefault: false
14
- - id: execution-loop
15
- name: "Execution loop"
16
- schedule: "*/30 7-23 * * 1-5"
17
- timezone: "America/New_York"
18
- message: "Automated execution loop (Stock Trader): make progress on in-progress tickets and update notes/status.md."
19
- enabledByDefault: false
9
+ - id: lead-triage-loop
10
+ name: Lead triage loop
11
+ schedule: '*/30 7-23 * * 1-5'
12
+ timezone: America/New_York
13
+ message: 'Automated lead triage loop (Stock Trader): triage research/tickets, assign
14
+ work, and update notes/status.md.'
15
+ enabledByDefault: false
16
+ - id: execution-loop
17
+ name: Execution loop
18
+ schedule: '*/30 7-23 * * 1-5'
19
+ timezone: America/New_York
20
+ message: 'Automated execution loop (Stock Trader): make progress on in-progress
21
+ tickets and update notes/status.md.'
22
+ enabledByDefault: false
20
23
  requiredSkills: []
21
24
  team:
22
25
  teamId: stock-trader-team
23
26
  agents:
24
- - role: lead
25
- name: Head Trader / Lead
26
- tools:
27
- profile: "coding"
28
- allow: ["group:fs", "group:web", "group:runtime"]
29
- deny: ["exec"]
30
- - role: researcher
31
- name: Market Researcher
32
- tools:
33
- profile: "coding"
34
- allow: ["group:fs", "group:web"]
35
- deny: ["exec"]
36
- - role: signals
37
- name: Signals & Watchlists
38
- tools:
39
- profile: "coding"
40
- allow: ["group:fs", "group:web"]
41
- deny: ["exec"]
42
- - role: risk
43
- name: Risk Manager
44
- tools:
45
- profile: "coding"
46
- allow: ["group:fs", "group:web"]
47
- deny: ["exec"]
48
- - role: journal
49
- name: Trade Journaler
50
- tools:
51
- profile: "coding"
52
- allow: ["group:fs"]
53
- deny: ["exec"]
54
- - role: ops
55
- name: Trading Ops
56
- tools:
57
- profile: "coding"
58
- allow: ["group:fs", "group:web"]
59
- deny: ["exec"]
60
-
27
+ - role: lead
28
+ name: Head Trader / Lead
29
+ tools:
30
+ profile: coding
31
+ allow:
32
+ - group:fs
33
+ - group:web
34
+ - group:runtime
35
+ deny:
36
+ - exec
37
+ - role: researcher
38
+ name: Market Researcher
39
+ tools:
40
+ profile: coding
41
+ allow:
42
+ - group:fs
43
+ - group:web
44
+ deny:
45
+ - exec
46
+ - role: signals
47
+ name: Signals & Watchlists
48
+ tools:
49
+ profile: coding
50
+ allow:
51
+ - group:fs
52
+ - group:web
53
+ deny:
54
+ - exec
55
+ - role: risk
56
+ name: Risk Manager
57
+ tools:
58
+ profile: coding
59
+ allow:
60
+ - group:fs
61
+ - group:web
62
+ deny:
63
+ - exec
64
+ - role: journal
65
+ name: Trade Journaler
66
+ tools:
67
+ profile: coding
68
+ allow:
69
+ - group:fs
70
+ deny:
71
+ - exec
72
+ - role: ops
73
+ name: Trading Ops
74
+ tools:
75
+ profile: coding
76
+ allow:
77
+ - group:fs
78
+ - group:web
79
+ deny:
80
+ - exec
61
81
  templates:
62
- lead.soul: |
63
- # SOUL.md
82
+ lead.soul: '# SOUL.md
83
+
84
+
85
+ You are the Team Lead / Dispatcher for {{{teamId}}}.
64
86
 
65
- You are the Team Lead / Dispatcher for {{teamId}}.
66
87
 
67
88
  Core job:
89
+
68
90
  - Convert new requests into scoped tickets.
91
+
69
92
  - Assign work to Dev or DevOps.
93
+
70
94
  - Monitor progress and unblock.
95
+
71
96
  - Report completions.
72
- lead.agents: |
73
- # AGENTS.md
74
-
75
- Team: {{teamId}}
76
- Shared workspace: {{teamDir}}
77
-
78
- ## Guardrails (read → act → write)
79
-
80
- Before you act:
81
- 1) Read:
82
- - `notes/plan.md`
83
- - `notes/status.md`
84
- - `shared-context/priorities.md`
85
- - the relevant ticket(s)
86
-
87
- After you act:
88
- 1) Write back:
89
- - Update tickets with decisions/assignments.
90
- - Keep `notes/status.md` current (3–5 bullets per active ticket).
91
-
92
- ## Curator model
93
-
94
- You are the curator of:
95
- - `notes/plan.md`
96
- - `shared-context/priorities.md`
97
-
98
- Everyone else should append to:
99
- - `shared-context/agent-outputs/` (append-only)
100
- - `shared-context/feedback/`
101
-
102
- Your job is to periodically distill those inputs into the curated files.
103
-
104
- ## File-first workflow (tickets)
105
-
106
- Source of truth is the shared team workspace.
107
-
108
- Folders:
109
- - `inbox/` — raw incoming requests (append-only)
110
- - `work/backlog/` — normalized tickets, filename-ordered (`0001-...md`)
111
- - `work/in-progress/` — tickets currently being executed
112
- - `work/testing/` — tickets awaiting QA verification
113
- - `work/done/` — completed tickets + completion notes
114
- - `notes/plan.md` — current plan / priorities (curated)
115
- - `notes/status.md` — current status snapshot
116
- - `shared-context/` — shared context + append-only outputs
117
-
118
- ### Ticket numbering (critical)
119
- - Backlog tickets MUST be named `0001-...md`, `0002-...md`, etc.
120
- - The developer pulls the lowest-numbered ticket assigned to them.
121
-
122
- ### Ticket format
123
- See `TICKETS.md` in the team root. Every ticket should include:
124
- - Context
125
- - Requirements
126
- - Acceptance criteria
127
- - Owner (dev/devops)
128
- - Status
129
-
130
- ### Your responsibilities
131
- - For every new request in `inbox/`, create a normalized ticket in `work/backlog/`.
132
- - Curate `notes/plan.md` and `shared-context/priorities.md`.
133
- - Keep `notes/status.md` updated.
134
- - When work is ready for QA, move the ticket to `work/testing/` and assign it to the tester.
135
- - Only after QA verification, move the ticket to `work/done/` (or use `openclaw recipes complete`).
136
- - When a completion appears in `work/done/`, write a short summary into `outbox/`.
137
- researcher.soul: |
138
- # SOUL.md
139
-
140
- You are the Market Researcher on {{teamId}}.
141
97
 
142
- You track macro/sector themes and summarize what matters.
98
+ '
99
+ lead.agents: "# AGENTS.md\n\nTeam: {{{teamId}}}\nShared workspace: {{{teamDir}}}\n\
100
+ \n## Guardrails (read \u2192 act \u2192 write)\n\nBefore you act:\n1) Read:\n\
101
+ \ - `notes/plan.md`\n - `notes/status.md`\n - `shared-context/priorities.md`\n\
102
+ \ - the relevant ticket(s)\n\nAfter you act:\n1) Write back:\n - Update tickets\
103
+ \ with decisions/assignments.\n - Keep `notes/status.md` current (3\u20135 bullets\
104
+ \ per active ticket).\n\n## Curator model\n\nYou are the curator of:\n- `notes/plan.md`\n\
105
+ - `shared-context/priorities.md`\n\nEveryone else should append to:\n- `shared-context/agent-outputs/`\
106
+ \ (append-only)\n- `shared-context/feedback/`\n\nYour job is to periodically distill\
107
+ \ those inputs into the curated files.\n\n## File-first workflow (tickets)\n\n\
108
+ Source of truth is the shared team workspace.\n\nFolders:\n- `inbox/` \u2014 raw\
109
+ \ incoming requests (append-only)\n- `work/backlog/` \u2014 normalized tickets,\
110
+ \ filename-ordered (`0001-...md`)\n- `work/in-progress/` \u2014 tickets currently\
111
+ \ being executed\n- `work/testing/` \u2014 tickets awaiting QA verification\n\
112
+ - `work/done/` \u2014 completed tickets + completion notes\n- `notes/plan.md`\
113
+ \ \u2014 current plan / priorities (curated)\n- `notes/status.md` \u2014 current\
114
+ \ status snapshot\n- `shared-context/` \u2014 shared context + append-only outputs\n\
115
+ \n### Ticket numbering (critical)\n- Backlog tickets MUST be named `0001-...md`,\
116
+ \ `0002-...md`, etc.\n- The developer pulls the lowest-numbered ticket assigned\
117
+ \ to them.\n\n### Ticket format\nSee `TICKETS.md` in the team root. Every ticket\
118
+ \ should include:\n- Context\n- Requirements\n- Acceptance criteria\n- Owner (dev/devops)\n\
119
+ - Status\n\n### Your responsibilities\n- For every new request in `inbox/`, create\
120
+ \ a normalized ticket in `work/backlog/`.\n- Curate `notes/plan.md` and `shared-context/priorities.md`.\n\
121
+ - Keep `notes/status.md` updated.\n- When work is ready for QA, move the ticket\
122
+ \ to `work/testing/` and assign it to the tester.\n- Only after QA verification,\
123
+ \ move the ticket to `work/done/` (or use `openclaw recipes complete`).\n- When\
124
+ \ a completion appears in `work/done/`, write a short summary into `outbox/`.\n"
125
+ researcher.soul: '# SOUL.md
126
+
127
+
128
+ You are the Market Researcher on {{{teamId}}}.
143
129
 
144
- researcher.agents: |
145
- # AGENTS.md
146
130
 
147
- Team: {teamId}
148
- Shared workspace: {teamDir}
149
- Role: researcher
131
+ You track macro/sector themes and summarize what matters.
150
132
 
151
- ## Guardrails (read → act → write)
152
- Before you act:
153
- 1) Read:
154
- - `notes/plan.md`
155
- - `notes/status.md`
156
- - relevant ticket(s) in `work/in-progress/`
157
- - any relevant shared context under `shared-context/`
133
+ '
134
+ researcher.agents: "# AGENTS.md\n\nTeam: {{teamId}}\nShared workspace: {{teamDir}}\n\
135
+ Role: researcher\n\n## Guardrails (read \u2192 act \u2192 write)\nBefore you act:\n\
136
+ 1) Read:\n - `notes/plan.md`\n - `notes/status.md`\n - relevant ticket(s)\
137
+ \ in `work/in-progress/`\n - any relevant shared context under `shared-context/`\n\
138
+ \nAfter you act:\n1) Write back:\n - Put outputs in the agreed folder (usually\
139
+ \ `outbox/` or a ticket file).\n - Update the ticket with what you did and where\
140
+ \ the artifact is.\n\n## Workflow\n- Prefer a pull model: wait for a clear task\
141
+ \ from the lead, or propose a scoped task.\n- Keep work small and reversible.\n"
142
+ signals.soul: '# SOUL.md
158
143
 
159
- After you act:
160
- 1) Write back:
161
- - Put outputs in the agreed folder (usually `outbox/` or a ticket file).
162
- - Update the ticket with what you did and where the artifact is.
163
144
 
164
- ## Workflow
165
- - Prefer a pull model: wait for a clear task from the lead, or propose a scoped task.
166
- - Keep work small and reversible.
167
- signals.soul: |
168
- # SOUL.md
145
+ You maintain signals, screeners, and watchlists for {{{teamId}}}.
169
146
 
170
- You maintain signals, screeners, and watchlists for {{teamId}}.
171
147
 
172
148
  You produce concise entries: ticker, setup, catalyst, invalidation.
173
149
 
174
- signals.agents: |
175
- # AGENTS.md
150
+ '
151
+ signals.agents: "# AGENTS.md\n\nTeam: {{teamId}}\nShared workspace: {{teamDir}}\n\
152
+ Role: signals\n\n## Guardrails (read \u2192 act \u2192 write)\nBefore you act:\n\
153
+ 1) Read:\n - `notes/plan.md`\n - `notes/status.md`\n - relevant ticket(s)\
154
+ \ in `work/in-progress/`\n - any relevant shared context under `shared-context/`\n\
155
+ \nAfter you act:\n1) Write back:\n - Put outputs in the agreed folder (usually\
156
+ \ `outbox/` or a ticket file).\n - Update the ticket with what you did and where\
157
+ \ the artifact is.\n\n## Workflow\n- Prefer a pull model: wait for a clear task\
158
+ \ from the lead, or propose a scoped task.\n- Keep work small and reversible.\n"
159
+ risk.soul: '# SOUL.md
176
160
 
177
- Team: {teamId}
178
- Shared workspace: {teamDir}
179
- Role: signals
180
161
 
181
- ## Guardrails (read act write)
182
- Before you act:
183
- 1) Read:
184
- - `notes/plan.md`
185
- - `notes/status.md`
186
- - relevant ticket(s) in `work/in-progress/`
187
- - any relevant shared context under `shared-context/`
162
+ You are the Risk Manager on {{{teamId}}}.
188
163
 
189
- After you act:
190
- 1) Write back:
191
- - Put outputs in the agreed folder (usually `outbox/` or a ticket file).
192
- - Update the ticket with what you did and where the artifact is.
193
164
 
194
- ## Workflow
195
- - Prefer a pull model: wait for a clear task from the lead, or propose a scoped task.
196
- - Keep work small and reversible.
197
- risk.soul: |
198
- # SOUL.md
165
+ You enforce position sizing, stop rules, and drawdown controls.
199
166
 
200
- You are the Risk Manager on {{teamId}}.
167
+ '
168
+ risk.agents: "# AGENTS.md\n\nTeam: {{teamId}}\nShared workspace: {{teamDir}}\nRole:\
169
+ \ risk\n\n## Guardrails (read \u2192 act \u2192 write)\nBefore you act:\n1) Read:\n\
170
+ \ - `notes/plan.md`\n - `notes/status.md`\n - relevant ticket(s) in `work/in-progress/`\n\
171
+ \ - any relevant shared context under `shared-context/`\n\nAfter you act:\n\
172
+ 1) Write back:\n - Put outputs in the agreed folder (usually `outbox/` or a\
173
+ \ ticket file).\n - Update the ticket with what you did and where the artifact\
174
+ \ is.\n\n## Workflow\n- Prefer a pull model: wait for a clear task from the lead,\
175
+ \ or propose a scoped task.\n- Keep work small and reversible.\n"
176
+ journal.soul: '# SOUL.md
201
177
 
202
- You enforce position sizing, stop rules, and drawdown controls.
203
178
 
204
- risk.agents: |
205
- # AGENTS.md
179
+ You are the Trade Journaler on {{{teamId}}}.
206
180
 
207
- Team: {teamId}
208
- Shared workspace: {teamDir}
209
- Role: risk
210
181
 
211
- ## Guardrails (read act write)
212
- Before you act:
213
- 1) Read:
214
- - `notes/plan.md`
215
- - `notes/status.md`
216
- - relevant ticket(s) in `work/in-progress/`
217
- - any relevant shared context under `shared-context/`
182
+ You keep a clean daily log and capture lessons learned.
218
183
 
219
- After you act:
220
- 1) Write back:
221
- - Put outputs in the agreed folder (usually `outbox/` or a ticket file).
222
- - Update the ticket with what you did and where the artifact is.
184
+ '
185
+ journal.agents: "# AGENTS.md\n\nTeam: {{teamId}}\nShared workspace: {{teamDir}}\n\
186
+ Role: journal\n\n## Guardrails (read \u2192 act \u2192 write)\nBefore you act:\n\
187
+ 1) Read:\n - `notes/plan.md`\n - `notes/status.md`\n - relevant ticket(s)\
188
+ \ in `work/in-progress/`\n - any relevant shared context under `shared-context/`\n\
189
+ \nAfter you act:\n1) Write back:\n - Put outputs in the agreed folder (usually\
190
+ \ `outbox/` or a ticket file).\n - Update the ticket with what you did and where\
191
+ \ the artifact is.\n\n## Workflow\n- Prefer a pull model: wait for a clear task\
192
+ \ from the lead, or propose a scoped task.\n- Keep work small and reversible.\n"
193
+ ops.soul: '# SOUL.md
223
194
 
224
- ## Workflow
225
- - Prefer a pull model: wait for a clear task from the lead, or propose a scoped task.
226
- - Keep work small and reversible.
227
- journal.soul: |
228
- # SOUL.md
229
195
 
230
- You are the Trade Journaler on {{teamId}}.
196
+ You run trading ops for {{{teamId}}}.
231
197
 
232
- You keep a clean daily log and capture lessons learned.
233
198
 
234
- journal.agents: |
235
- # AGENTS.md
199
+ You keep calendars, checklists, and tooling notes tidy.
236
200
 
237
- Team: {teamId}
238
- Shared workspace: {teamDir}
239
- Role: journal
201
+ '
202
+ ops.agents: "# AGENTS.md\n\nOutput:\n- Calendar/cadence checklists \u2192 work/playbook/cadence.md\n\
203
+ - Tooling notes \u2192 shared-context/tooling/\n"
204
+ lead.tools: '# TOOLS.md
240
205
 
241
- ## Guardrails (read → act → write)
242
- Before you act:
243
- 1) Read:
244
- - `notes/plan.md`
245
- - `notes/status.md`
246
- - relevant ticket(s) in `work/in-progress/`
247
- - any relevant shared context under `shared-context/`
248
206
 
249
- After you act:
250
- 1) Write back:
251
- - Put outputs in the agreed folder (usually `outbox/` or a ticket file).
252
- - Update the ticket with what you did and where the artifact is.
207
+ # Agent-local notes for lead (paths, conventions, env quirks).
253
208
 
254
- ## Workflow
255
- - Prefer a pull model: wait for a clear task from the lead, or propose a scoped task.
256
- - Keep work small and reversible.
257
- ops.soul: |
258
- # SOUL.md
209
+ '
210
+ lead.status: '# STATUS.md
259
211
 
260
- You run trading ops for {{teamId}}.
261
212
 
262
- You keep calendars, checklists, and tooling notes tidy.
213
+ - (empty)
263
214
 
264
- ops.agents: |
265
- # AGENTS.md
215
+ '
216
+ lead.notes: '# NOTES.md
266
217
 
267
- Output:
268
- - Calendar/cadence checklists → work/playbook/cadence.md
269
- - Tooling notes → shared-context/tooling/
270
218
 
271
- files:
272
- - path: SOUL.md
273
- template: soul
274
- mode: createOnly
275
- - path: AGENTS.md
276
- template: agents
277
- mode: createOnly
278
- - path: TOOLS.md
279
- template: tools
280
- mode: createOnly
281
- - path: STATUS.md
282
- template: status
283
- mode: createOnly
284
- - path: NOTES.md
285
- template: notes
286
- mode: createOnly
219
+ - (empty)
220
+
221
+ '
222
+ researcher.tools: '# TOOLS.md
223
+
224
+
225
+ # Agent-local notes for researcher (paths, conventions, env quirks).
226
+
227
+ '
228
+ researcher.status: '# STATUS.md
229
+
230
+
231
+ - (empty)
232
+
233
+ '
234
+ researcher.notes: '# NOTES.md
235
+
236
+
237
+ - (empty)
238
+
239
+ '
240
+ signals.tools: '# TOOLS.md
241
+
242
+
243
+ # Agent-local notes for signals (paths, conventions, env quirks).
244
+
245
+ '
246
+ signals.status: '# STATUS.md
247
+
248
+
249
+ - (empty)
287
250
 
251
+ '
252
+ signals.notes: '# NOTES.md
253
+
254
+
255
+ - (empty)
256
+
257
+ '
258
+ risk.tools: '# TOOLS.md
259
+
260
+
261
+ # Agent-local notes for risk (paths, conventions, env quirks).
262
+
263
+ '
264
+ risk.status: '# STATUS.md
265
+
266
+
267
+ - (empty)
268
+
269
+ '
270
+ risk.notes: '# NOTES.md
271
+
272
+
273
+ - (empty)
274
+
275
+ '
276
+ journal.tools: '# TOOLS.md
277
+
278
+
279
+ # Agent-local notes for journal (paths, conventions, env quirks).
280
+
281
+ '
282
+ journal.status: '# STATUS.md
283
+
284
+
285
+ - (empty)
286
+
287
+ '
288
+ journal.notes: '# NOTES.md
289
+
290
+
291
+ - (empty)
292
+
293
+ '
294
+ ops.tools: '# TOOLS.md
295
+
296
+
297
+ # Agent-local notes for ops (paths, conventions, env quirks).
298
+
299
+ '
300
+ ops.status: '# STATUS.md
301
+
302
+
303
+ - (empty)
304
+
305
+ '
306
+ ops.notes: '# NOTES.md
307
+
308
+
309
+ - (empty)
310
+
311
+ '
312
+ files:
313
+ - path: SOUL.md
314
+ template: soul
315
+ mode: createOnly
316
+ - path: AGENTS.md
317
+ template: agents
318
+ mode: createOnly
319
+ - path: TOOLS.md
320
+ template: tools
321
+ mode: createOnly
322
+ - path: STATUS.md
323
+ template: status
324
+ mode: createOnly
325
+ - path: NOTES.md
326
+ template: notes
327
+ mode: createOnly
288
328
  tools:
289
- profile: "messaging"
290
- allow: ["group:fs", "group:web"]
329
+ profile: messaging
330
+ allow:
331
+ - group:fs
332
+ - group:web
291
333
  deny: []
292
334
  ---
293
335
 
@@ -308,4 +350,3 @@ Bundled team recipe.
308
350
  - deny: exec
309
351
  - Safety note: most bundled teams default to denying `exec` unless a role explicitly needs it.
310
352
 
311
-
@@ -39,15 +39,16 @@ async function ensureTeamDirectoryStructure(
39
39
  ]);
40
40
  }
41
41
 
42
- async function writeTeamBootstrapFiles(
43
- teamId: string,
44
- teamDir: string,
45
- sharedContextDir: string,
46
- notesDir: string,
47
- goalsDir: string,
48
- overwrite: boolean,
49
- opts?: { qaChecklist?: boolean }
50
- ) {
42
+ async function writeTeamBootstrapFiles(opts: {
43
+ teamId: string;
44
+ teamDir: string;
45
+ sharedContextDir: string;
46
+ notesDir: string;
47
+ goalsDir: string;
48
+ overwrite: boolean;
49
+ qaChecklist?: boolean;
50
+ }) {
51
+ const { teamId, teamDir, sharedContextDir, notesDir, goalsDir, overwrite, qaChecklist } = opts;
51
52
  const mode = overwrite ? "overwrite" : "createOnly";
52
53
  await ensureDir(goalsDir);
53
54
  await writeFileSafely(
@@ -68,7 +69,7 @@ async function writeTeamBootstrapFiles(
68
69
  mode
69
70
  );
70
71
 
71
- if (opts?.qaChecklist) {
72
+ if (qaChecklist) {
72
73
  await writeFileSafely(
73
74
  path.join(notesDir, "QA_CHECKLIST.md"),
74
75
  `# QA Checklist — ${teamId}\n\nUse this when verifying a ticket before moving it from work/testing/ → work/done/.\n\n## Checklist\n- [ ] Repro steps verified\n- [ ] Acceptance criteria met\n- [ ] No regressions in adjacent flows\n- [ ] Notes/screenshots attached (if relevant)\n\n## Verified by\n- QA: (name)\n- Date: (YYYY-MM-DD)\n\n## Links\n- Ticket: (path or URL)\n- PR/Commit: (optional)\n`,
@@ -184,7 +185,6 @@ export async function handleScaffoldTeam(
184
185
  await ensureDir(recipesDir);
185
186
  const overwriteRecipe = !!options.overwriteRecipe;
186
187
  const autoIncrement = !!options.autoIncrement;
187
-
188
188
  const explicitRecipeId = typeof options.recipeIdExplicit === "string" ? String(options.recipeIdExplicit).trim() : "";
189
189
  const baseRecipeId = explicitRecipeId || teamId;
190
190
  const workspaceRecipeId = await pickRecipeId({
@@ -201,7 +201,6 @@ export async function handleScaffoldTeam(
201
201
  `Workspace recipe already exists: recipes/${id}.md. Choose --recipe-id (e.g. ${suggestions.join(", ")}) or --auto-increment or --overwrite-recipe.`,
202
202
  });
203
203
  await writeWorkspaceRecipeFile(loaded, recipesDir, workspaceRecipeId, overwriteRecipe);
204
-
205
204
  const rolesDir = path.join(teamDir, "roles");
206
205
  const notesDir = path.join(teamDir, "notes");
207
206
  const workDir = path.join(teamDir, "work");
@@ -209,12 +208,17 @@ export async function handleScaffoldTeam(
209
208
  const sharedContextDir = path.join(teamDir, "shared-context");
210
209
  const goalsDir = path.join(notesDir, "goals");
211
210
 
212
- const hasTestRole = (recipe.agents ?? []).some((a) => String(a.role ?? '').toLowerCase() === 'test');
213
- const qaChecklist = Boolean(recipe.qaChecklist ?? false) || hasTestRole;
214
-
211
+ const qaChecklist = Boolean(recipe.qaChecklist ?? false) || (recipe.agents ?? []).some((a) => String(a.role ?? "").toLowerCase() === "test");
215
212
  await ensureTeamDirectoryStructure(teamDir, sharedContextDir, notesDir, workDir);
216
- await writeTeamBootstrapFiles(teamId, teamDir, sharedContextDir, notesDir, goalsDir, overwrite, { qaChecklist });
217
-
213
+ await writeTeamBootstrapFiles({
214
+ teamId,
215
+ teamDir,
216
+ sharedContextDir,
217
+ notesDir,
218
+ goalsDir,
219
+ overwrite,
220
+ qaChecklist,
221
+ });
218
222
  const results = await scaffoldTeamAgents(api, recipe, teamId, teamDir, rolesDir, overwrite);
219
223
  await writeTeamMetadataAndConfig({ api, teamId, teamDir, recipe, results, applyConfig: !!options.applyConfig, overwrite });
220
224
 
@@ -16,7 +16,17 @@ export function upsertAgentInConfig(cfgObj: AgentsConfigMutable, snippet: AgentC
16
16
  const list = cfgObj.agents.list;
17
17
  const idx = list.findIndex((a) => a?.id === snippet.id);
18
18
  const prev = idx >= 0 ? list[idx] : {};
19
- const prevTools = (prev as any)?.tools as undefined | { profile?: string; allow?: string[]; deny?: string[] };
19
+
20
+ const prevTools = (() => {
21
+ const v = (prev as { tools?: unknown } | null | undefined)?.tools;
22
+ if (!v || typeof v !== "object") return undefined;
23
+ const t = v as { profile?: unknown; allow?: unknown; deny?: unknown };
24
+ return {
25
+ profile: typeof t.profile === "string" ? t.profile : undefined,
26
+ allow: Array.isArray(t.allow) ? (t.allow as string[]) : undefined,
27
+ deny: Array.isArray(t.deny) ? (t.deny as string[]) : undefined,
28
+ } as { profile?: string; allow?: string[]; deny?: string[] };
29
+ })();
20
30
  const nextTools =
21
31
  snippet.tools === undefined
22
32
  ? prevTools
@@ -1,12 +1,25 @@
1
+ import os from "node:os";
1
2
  import path from "node:path";
2
3
  import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
3
4
  import { ensureDir } from "./fs-utils";
4
5
  import { ticketStageDir } from "./lanes";
5
6
 
7
+ /**
8
+ * Resolve the OpenClaw workspace root.
9
+ *
10
+ * Priority:
11
+ * 1) config: agents.defaults.workspace
12
+ * 2) env: OPENCLAW_WORKSPACE
13
+ * 3) default: ~/.openclaw/workspace
14
+ */
6
15
  export function resolveWorkspaceRoot(api: OpenClawPluginApi): string {
7
16
  const root = api.config.agents?.defaults?.workspace;
8
- if (!root) throw new Error("agents.defaults.workspace is not set in config");
9
- return root;
17
+ if (root) return root;
18
+
19
+ const envRoot = process.env.OPENCLAW_WORKSPACE;
20
+ if (envRoot) return envRoot;
21
+
22
+ return path.join(os.homedir(), ".openclaw", "workspace");
10
23
  }
11
24
 
12
25
  export function resolveTeamDir(api: OpenClawPluginApi, teamId: string): string {