@aipper/aiws-spec 0.0.21 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/docs/spec-contract.md +5 -4
  2. package/package.json +1 -1
  3. package/templates/workspace/.agents/skills/{aiws-change-archive → p-aiws-change-archive}/SKILL.md +3 -2
  4. package/templates/workspace/.agents/skills/{aiws-change-finish → p-aiws-change-finish}/SKILL.md +2 -2
  5. package/templates/workspace/.agents/skills/{aiws-change-list → p-aiws-change-list}/SKILL.md +2 -2
  6. package/templates/workspace/.agents/skills/{aiws-change-new → p-aiws-change-new}/SKILL.md +2 -2
  7. package/templates/workspace/.agents/skills/{aiws-change-next → p-aiws-change-next}/SKILL.md +2 -2
  8. package/templates/workspace/.agents/skills/{aiws-change-start → p-aiws-change-start}/SKILL.md +2 -2
  9. package/templates/workspace/.agents/skills/{aiws-change-status → p-aiws-change-status}/SKILL.md +2 -2
  10. package/templates/workspace/.agents/skills/{aiws-change-sync → p-aiws-change-sync}/SKILL.md +2 -2
  11. package/templates/workspace/.agents/skills/{aiws-change-templates-init → p-aiws-change-templates-init}/SKILL.md +2 -2
  12. package/templates/workspace/.agents/skills/{aiws-change-templates-which → p-aiws-change-templates-which}/SKILL.md +2 -2
  13. package/templates/workspace/.agents/skills/{aiws-change-validate → p-aiws-change-validate}/SKILL.md +2 -2
  14. package/templates/workspace/.agents/skills/{aiws-hooks-install → p-aiws-hooks-install}/SKILL.md +2 -2
  15. package/templates/workspace/.agents/skills/{aiws-hooks-status → p-aiws-hooks-status}/SKILL.md +2 -2
  16. package/templates/workspace/.agents/skills/{aiws-init → p-aiws-init}/SKILL.md +2 -2
  17. package/templates/workspace/.agents/skills/{aiws-rollback → p-aiws-rollback}/SKILL.md +2 -2
  18. package/templates/workspace/.agents/skills/{aiws-update → p-aiws-update}/SKILL.md +2 -2
  19. package/templates/workspace/.agents/skills/{aiws-validate → p-aiws-validate}/SKILL.md +2 -2
  20. package/templates/workspace/.agents/skills/p-tasks-plan/SKILL.md +37 -0
  21. package/templates/workspace/.agents/skills/ws-commit/SKILL.md +21 -6
  22. package/templates/workspace/.agents/skills/ws-deliver/SKILL.md +38 -9
  23. package/templates/workspace/.agents/skills/ws-dev/SKILL.md +61 -2
  24. package/templates/workspace/.agents/skills/ws-finish/SKILL.md +39 -25
  25. package/templates/workspace/.agents/skills/ws-handoff/SKILL.md +31 -0
  26. package/templates/workspace/.agents/skills/ws-plan/SKILL.md +32 -0
  27. package/templates/workspace/.agents/skills/ws-push/SKILL.md +17 -12
  28. package/templates/workspace/.claude/commands/{aiws-change-archive.md → p-aiws-change-archive.md} +3 -1
  29. package/templates/workspace/.claude/commands/{aiws-change-finish.md → p-aiws-change-finish.md} +2 -0
  30. package/templates/workspace/.claude/commands/{aiws-change-list.md → p-aiws-change-list.md} +2 -0
  31. package/templates/workspace/.claude/commands/{aiws-change-new.md → p-aiws-change-new.md} +2 -0
  32. package/templates/workspace/.claude/commands/{aiws-change-next.md → p-aiws-change-next.md} +2 -0
  33. package/templates/workspace/.claude/commands/{aiws-change-start.md → p-aiws-change-start.md} +2 -0
  34. package/templates/workspace/.claude/commands/{aiws-change-status.md → p-aiws-change-status.md} +2 -0
  35. package/templates/workspace/.claude/commands/{aiws-change-sync.md → p-aiws-change-sync.md} +2 -0
  36. package/templates/workspace/.claude/commands/{aiws-change-templates-init.md → p-aiws-change-templates-init.md} +2 -0
  37. package/templates/workspace/.claude/commands/{aiws-change-templates-which.md → p-aiws-change-templates-which.md} +2 -0
  38. package/templates/workspace/.claude/commands/{aiws-change-validate.md → p-aiws-change-validate.md} +2 -0
  39. package/templates/workspace/.claude/commands/{aiws-hooks-install.md → p-aiws-hooks-install.md} +2 -0
  40. package/templates/workspace/.claude/commands/{aiws-hooks-status.md → p-aiws-hooks-status.md} +2 -0
  41. package/templates/workspace/.claude/commands/{aiws-init.md → p-aiws-init.md} +2 -1
  42. package/templates/workspace/.claude/commands/{aiws-rollback.md → p-aiws-rollback.md} +2 -1
  43. package/templates/workspace/.claude/commands/{aiws-update.md → p-aiws-update.md} +2 -1
  44. package/templates/workspace/.claude/commands/{aiws-validate.md → p-aiws-validate.md} +2 -1
  45. package/templates/workspace/.claude/commands/ws-dev.md +4 -1
  46. package/templates/workspace/.claude/commands/ws-handoff.md +22 -0
  47. package/templates/workspace/.opencode/command/{aiws-change-archive.md → p-aiws-change-archive.md} +4 -2
  48. package/templates/workspace/.opencode/command/{aiws-change-finish.md → p-aiws-change-finish.md} +3 -1
  49. package/templates/workspace/.opencode/command/{aiws-change-list.md → p-aiws-change-list.md} +3 -1
  50. package/templates/workspace/.opencode/command/{aiws-change-new.md → p-aiws-change-new.md} +3 -1
  51. package/templates/workspace/.opencode/command/{aiws-change-next.md → p-aiws-change-next.md} +3 -1
  52. package/templates/workspace/.opencode/command/{aiws-change-start.md → p-aiws-change-start.md} +3 -1
  53. package/templates/workspace/.opencode/command/{aiws-change-status.md → p-aiws-change-status.md} +3 -1
  54. package/templates/workspace/.opencode/command/{aiws-change-sync.md → p-aiws-change-sync.md} +3 -1
  55. package/templates/workspace/.opencode/command/{aiws-change-templates-init.md → p-aiws-change-templates-init.md} +3 -1
  56. package/templates/workspace/.opencode/command/{aiws-change-templates-which.md → p-aiws-change-templates-which.md} +3 -1
  57. package/templates/workspace/.opencode/command/{aiws-change-validate.md → p-aiws-change-validate.md} +3 -1
  58. package/templates/workspace/.opencode/command/{aiws-hooks-install.md → p-aiws-hooks-install.md} +3 -1
  59. package/templates/workspace/.opencode/command/{aiws-hooks-status.md → p-aiws-hooks-status.md} +3 -1
  60. package/templates/workspace/.opencode/command/{aiws-init.md → p-aiws-init.md} +3 -1
  61. package/templates/workspace/.opencode/command/{aiws-rollback.md → p-aiws-rollback.md} +3 -1
  62. package/templates/workspace/.opencode/command/{aiws-update.md → p-aiws-update.md} +3 -1
  63. package/templates/workspace/.opencode/command/{aiws-validate.md → p-aiws-validate.md} +3 -1
  64. package/templates/workspace/.opencode/command/ws-commit.md +1 -1
  65. package/templates/workspace/.opencode/command/ws-dev.md +4 -1
  66. package/templates/workspace/.opencode/command/ws-handoff.md +25 -0
  67. package/templates/workspace/.opencode/command/ws-review.md +1 -1
  68. package/templates/workspace/AGENTS.md +7 -4
  69. package/templates/workspace/manifest.json +171 -103
  70. package/templates/workspace/tools/ws_change_check.py +99 -0
  71. package/templates/workspace/tools/ws_resolve_sub_target.sh +46 -0
  72. package/templates/workspace/tools/ws_tasks_plan.py +137 -0
@@ -26,10 +26,11 @@
26
26
  ".agents/skills/**",
27
27
  "tools/ws_change_check.py",
28
28
  "tools/requirements_contract.py",
29
- ".claude/commands/aiws-init.md",
30
- ".claude/commands/aiws-update.md",
31
- ".claude/commands/aiws-validate.md",
32
- ".claude/commands/aiws-rollback.md",
29
+ "tools/ws_tasks_plan.py",
30
+ ".claude/commands/p-aiws-init.md",
31
+ ".claude/commands/p-aiws-update.md",
32
+ ".claude/commands/p-aiws-validate.md",
33
+ ".claude/commands/p-aiws-rollback.md",
33
34
  ".claude/commands/ws-preflight.md",
34
35
  ".claude/commands/ws-migrate.md",
35
36
  ".claude/commands/ws-dev.md",
@@ -47,10 +48,10 @@
47
48
  ".claude/commands/ws-req-contract-sync.md",
48
49
  ".claude/commands/ws-req-contract-validate.md",
49
50
  ".claude/commands/ws-req-flow-sync.md",
50
- ".opencode/command/aiws-init.md",
51
- ".opencode/command/aiws-update.md",
52
- ".opencode/command/aiws-validate.md",
53
- ".opencode/command/aiws-rollback.md",
51
+ ".opencode/command/p-aiws-init.md",
52
+ ".opencode/command/p-aiws-update.md",
53
+ ".opencode/command/p-aiws-validate.md",
54
+ ".opencode/command/p-aiws-rollback.md",
54
55
  ".opencode/command/ws-preflight.md",
55
56
  ".opencode/command/ws-migrate.md",
56
57
  ".opencode/command/ws-dev.md",
@@ -106,37 +107,39 @@
106
107
  ".iflow/commands/ws-req-contract-sync.toml",
107
108
  ".iflow/commands/ws-req-contract-validate.toml",
108
109
  ".iflow/commands/ws-req-flow-sync.toml",
109
- ".claude/commands/aiws-change-archive.md",
110
- ".claude/commands/aiws-change-finish.md",
111
- ".claude/commands/aiws-change-list.md",
112
- ".claude/commands/aiws-change-new.md",
113
- ".claude/commands/aiws-change-next.md",
114
- ".claude/commands/aiws-change-start.md",
115
- ".claude/commands/aiws-change-status.md",
116
- ".claude/commands/aiws-change-sync.md",
117
- ".claude/commands/aiws-change-templates-init.md",
118
- ".claude/commands/aiws-change-templates-which.md",
119
- ".claude/commands/aiws-change-validate.md",
120
- ".claude/commands/aiws-hooks-install.md",
121
- ".claude/commands/aiws-hooks-status.md",
110
+ ".claude/commands/p-aiws-change-archive.md",
111
+ ".claude/commands/p-aiws-change-finish.md",
112
+ ".claude/commands/p-aiws-change-list.md",
113
+ ".claude/commands/p-aiws-change-new.md",
114
+ ".claude/commands/p-aiws-change-next.md",
115
+ ".claude/commands/p-aiws-change-start.md",
116
+ ".claude/commands/p-aiws-change-status.md",
117
+ ".claude/commands/p-aiws-change-sync.md",
118
+ ".claude/commands/p-aiws-change-templates-init.md",
119
+ ".claude/commands/p-aiws-change-templates-which.md",
120
+ ".claude/commands/p-aiws-change-validate.md",
121
+ ".claude/commands/p-aiws-hooks-install.md",
122
+ ".claude/commands/p-aiws-hooks-status.md",
122
123
  ".claude/commands/ws-plan.md",
123
124
  ".claude/commands/ws-plan-verify.md",
125
+ ".claude/commands/ws-handoff.md",
124
126
  ".claude/commands/ws-bugfix.md",
125
- ".opencode/command/aiws-change-archive.md",
126
- ".opencode/command/aiws-change-finish.md",
127
- ".opencode/command/aiws-change-list.md",
128
- ".opencode/command/aiws-change-new.md",
129
- ".opencode/command/aiws-change-next.md",
130
- ".opencode/command/aiws-change-start.md",
131
- ".opencode/command/aiws-change-status.md",
132
- ".opencode/command/aiws-change-sync.md",
133
- ".opencode/command/aiws-change-templates-init.md",
134
- ".opencode/command/aiws-change-templates-which.md",
135
- ".opencode/command/aiws-change-validate.md",
136
- ".opencode/command/aiws-hooks-install.md",
137
- ".opencode/command/aiws-hooks-status.md",
127
+ ".opencode/command/p-aiws-change-archive.md",
128
+ ".opencode/command/p-aiws-change-finish.md",
129
+ ".opencode/command/p-aiws-change-list.md",
130
+ ".opencode/command/p-aiws-change-new.md",
131
+ ".opencode/command/p-aiws-change-next.md",
132
+ ".opencode/command/p-aiws-change-start.md",
133
+ ".opencode/command/p-aiws-change-status.md",
134
+ ".opencode/command/p-aiws-change-sync.md",
135
+ ".opencode/command/p-aiws-change-templates-init.md",
136
+ ".opencode/command/p-aiws-change-templates-which.md",
137
+ ".opencode/command/p-aiws-change-validate.md",
138
+ ".opencode/command/p-aiws-hooks-install.md",
139
+ ".opencode/command/p-aiws-hooks-status.md",
138
140
  ".opencode/command/ws-plan.md",
139
- ".opencode/command/ws-plan-verify.md"
141
+ ".opencode/command/ws-plan-verify.md",
142
+ ".opencode/command/ws-handoff.md"
140
143
  ],
141
144
  "optional": [
142
145
  ".iflow/agents/**",
@@ -149,19 +152,15 @@
149
152
  "tools/requirements_flow_gen.py",
150
153
  "tools/server_test_runner.py",
151
154
  "tools/iflow_watchdog.sh",
152
- "tools/install_iflow_watchdog_systemd_user.sh"
155
+ "tools/install_iflow_watchdog_systemd_user.sh",
156
+ "tools/ws_resolve_sub_target.sh"
153
157
  ],
154
158
  "update": {
155
- "replace_file": [
156
- ".aiws/manifest.json",
157
- ".githooks/pre-commit",
158
- ".githooks/pre-push",
159
- "tools/ws_change_check.py",
160
- "tools/requirements_contract.py",
159
+ "remove": [
161
160
  ".agents/skills/aiws-init/SKILL.md",
162
- ".agents/skills/aiws-rollback/SKILL.md",
163
161
  ".agents/skills/aiws-update/SKILL.md",
164
162
  ".agents/skills/aiws-validate/SKILL.md",
163
+ ".agents/skills/aiws-rollback/SKILL.md",
165
164
  ".agents/skills/aiws-hooks-install/SKILL.md",
166
165
  ".agents/skills/aiws-hooks-status/SKILL.md",
167
166
  ".agents/skills/aiws-change-list/SKILL.md",
@@ -175,6 +174,67 @@
175
174
  ".agents/skills/aiws-change-archive/SKILL.md",
176
175
  ".agents/skills/aiws-change-templates-which/SKILL.md",
177
176
  ".agents/skills/aiws-change-templates-init/SKILL.md",
177
+ ".claude/commands/aiws-init.md",
178
+ ".claude/commands/aiws-update.md",
179
+ ".claude/commands/aiws-validate.md",
180
+ ".claude/commands/aiws-rollback.md",
181
+ ".claude/commands/aiws-hooks-install.md",
182
+ ".claude/commands/aiws-hooks-status.md",
183
+ ".claude/commands/aiws-change-list.md",
184
+ ".claude/commands/aiws-change-new.md",
185
+ ".claude/commands/aiws-change-start.md",
186
+ ".claude/commands/aiws-change-finish.md",
187
+ ".claude/commands/aiws-change-status.md",
188
+ ".claude/commands/aiws-change-next.md",
189
+ ".claude/commands/aiws-change-sync.md",
190
+ ".claude/commands/aiws-change-validate.md",
191
+ ".claude/commands/aiws-change-archive.md",
192
+ ".claude/commands/aiws-change-templates-which.md",
193
+ ".claude/commands/aiws-change-templates-init.md",
194
+ ".opencode/command/aiws-init.md",
195
+ ".opencode/command/aiws-update.md",
196
+ ".opencode/command/aiws-validate.md",
197
+ ".opencode/command/aiws-rollback.md",
198
+ ".opencode/command/aiws-hooks-install.md",
199
+ ".opencode/command/aiws-hooks-status.md",
200
+ ".opencode/command/aiws-change-list.md",
201
+ ".opencode/command/aiws-change-new.md",
202
+ ".opencode/command/aiws-change-start.md",
203
+ ".opencode/command/aiws-change-finish.md",
204
+ ".opencode/command/aiws-change-status.md",
205
+ ".opencode/command/aiws-change-next.md",
206
+ ".opencode/command/aiws-change-sync.md",
207
+ ".opencode/command/aiws-change-validate.md",
208
+ ".opencode/command/aiws-change-archive.md",
209
+ ".opencode/command/aiws-change-templates-which.md",
210
+ ".opencode/command/aiws-change-templates-init.md",
211
+ ".agents/skills/ws-tasks-plan/SKILL.md"
212
+ ],
213
+ "replace_file": [
214
+ ".aiws/manifest.json",
215
+ ".githooks/pre-commit",
216
+ ".githooks/pre-push",
217
+ "tools/ws_change_check.py",
218
+ "tools/requirements_contract.py",
219
+ "tools/ws_tasks_plan.py",
220
+ "tools/ws_resolve_sub_target.sh",
221
+ ".agents/skills/p-aiws-init/SKILL.md",
222
+ ".agents/skills/p-aiws-rollback/SKILL.md",
223
+ ".agents/skills/p-aiws-update/SKILL.md",
224
+ ".agents/skills/p-aiws-validate/SKILL.md",
225
+ ".agents/skills/p-aiws-hooks-install/SKILL.md",
226
+ ".agents/skills/p-aiws-hooks-status/SKILL.md",
227
+ ".agents/skills/p-aiws-change-list/SKILL.md",
228
+ ".agents/skills/p-aiws-change-new/SKILL.md",
229
+ ".agents/skills/p-aiws-change-start/SKILL.md",
230
+ ".agents/skills/p-aiws-change-finish/SKILL.md",
231
+ ".agents/skills/p-aiws-change-status/SKILL.md",
232
+ ".agents/skills/p-aiws-change-next/SKILL.md",
233
+ ".agents/skills/p-aiws-change-sync/SKILL.md",
234
+ ".agents/skills/p-aiws-change-validate/SKILL.md",
235
+ ".agents/skills/p-aiws-change-archive/SKILL.md",
236
+ ".agents/skills/p-aiws-change-templates-which/SKILL.md",
237
+ ".agents/skills/p-aiws-change-templates-init/SKILL.md",
178
238
  ".agents/skills/ws-analyze/SKILL.md",
179
239
  ".agents/skills/ws-bugfix/SKILL.md",
180
240
  ".agents/skills/ws-commit/SKILL.md",
@@ -184,6 +244,8 @@
184
244
  ".agents/skills/ws-migrate/SKILL.md",
185
245
  ".agents/skills/ws-plan/SKILL.md",
186
246
  ".agents/skills/ws-plan-verify/SKILL.md",
247
+ ".agents/skills/p-tasks-plan/SKILL.md",
248
+ ".agents/skills/ws-handoff/SKILL.md",
187
249
  ".agents/skills/ws-pull/SKILL.md",
188
250
  ".agents/skills/ws-push/SKILL.md",
189
251
  ".agents/skills/ws-submodule-setup/SKILL.md",
@@ -233,35 +295,35 @@
233
295
  ".iflow/commands/ws-req-contract-sync.toml",
234
296
  ".iflow/commands/ws-req-contract-validate.toml",
235
297
  ".iflow/commands/ws-req-flow-sync.toml",
236
- ".claude/commands/aiws-change-archive.md",
237
- ".claude/commands/aiws-change-finish.md",
238
- ".claude/commands/aiws-change-list.md",
239
- ".claude/commands/aiws-change-new.md",
240
- ".claude/commands/aiws-change-next.md",
241
- ".claude/commands/aiws-change-start.md",
242
- ".claude/commands/aiws-change-status.md",
243
- ".claude/commands/aiws-change-sync.md",
244
- ".claude/commands/aiws-change-templates-init.md",
245
- ".claude/commands/aiws-change-templates-which.md",
246
- ".claude/commands/aiws-change-validate.md",
247
- ".claude/commands/aiws-hooks-install.md",
248
- ".claude/commands/aiws-hooks-status.md",
298
+ ".claude/commands/p-aiws-change-archive.md",
299
+ ".claude/commands/p-aiws-change-finish.md",
300
+ ".claude/commands/p-aiws-change-list.md",
301
+ ".claude/commands/p-aiws-change-new.md",
302
+ ".claude/commands/p-aiws-change-next.md",
303
+ ".claude/commands/p-aiws-change-start.md",
304
+ ".claude/commands/p-aiws-change-status.md",
305
+ ".claude/commands/p-aiws-change-sync.md",
306
+ ".claude/commands/p-aiws-change-templates-init.md",
307
+ ".claude/commands/p-aiws-change-templates-which.md",
308
+ ".claude/commands/p-aiws-change-validate.md",
309
+ ".claude/commands/p-aiws-hooks-install.md",
310
+ ".claude/commands/p-aiws-hooks-status.md",
249
311
  ".claude/commands/ws-plan.md",
250
312
  ".claude/commands/ws-plan-verify.md",
251
313
  ".claude/commands/ws-bugfix.md",
252
- ".opencode/command/aiws-change-archive.md",
253
- ".opencode/command/aiws-change-finish.md",
254
- ".opencode/command/aiws-change-list.md",
255
- ".opencode/command/aiws-change-new.md",
256
- ".opencode/command/aiws-change-next.md",
257
- ".opencode/command/aiws-change-start.md",
258
- ".opencode/command/aiws-change-status.md",
259
- ".opencode/command/aiws-change-sync.md",
260
- ".opencode/command/aiws-change-templates-init.md",
261
- ".opencode/command/aiws-change-templates-which.md",
262
- ".opencode/command/aiws-change-validate.md",
263
- ".opencode/command/aiws-hooks-install.md",
264
- ".opencode/command/aiws-hooks-status.md",
314
+ ".opencode/command/p-aiws-change-archive.md",
315
+ ".opencode/command/p-aiws-change-finish.md",
316
+ ".opencode/command/p-aiws-change-list.md",
317
+ ".opencode/command/p-aiws-change-new.md",
318
+ ".opencode/command/p-aiws-change-next.md",
319
+ ".opencode/command/p-aiws-change-start.md",
320
+ ".opencode/command/p-aiws-change-status.md",
321
+ ".opencode/command/p-aiws-change-sync.md",
322
+ ".opencode/command/p-aiws-change-templates-init.md",
323
+ ".opencode/command/p-aiws-change-templates-which.md",
324
+ ".opencode/command/p-aiws-change-validate.md",
325
+ ".opencode/command/p-aiws-hooks-install.md",
326
+ ".opencode/command/p-aiws-hooks-status.md",
265
327
  ".opencode/command/ws-plan.md",
266
328
  ".opencode/command/ws-plan-verify.md"
267
329
  ],
@@ -281,16 +343,16 @@
281
343
  ".gitignore": [
282
344
  "gitignore"
283
345
  ],
284
- ".claude/commands/aiws-init.md": [
346
+ ".claude/commands/p-aiws-init.md": [
285
347
  "claude:aiws-init"
286
348
  ],
287
- ".claude/commands/aiws-update.md": [
349
+ ".claude/commands/p-aiws-update.md": [
288
350
  "claude:aiws-update"
289
351
  ],
290
- ".claude/commands/aiws-validate.md": [
352
+ ".claude/commands/p-aiws-validate.md": [
291
353
  "claude:aiws-validate"
292
354
  ],
293
- ".claude/commands/aiws-rollback.md": [
355
+ ".claude/commands/p-aiws-rollback.md": [
294
356
  "claude:aiws-rollback"
295
357
  ],
296
358
  ".claude/commands/ws-preflight.md": [
@@ -344,16 +406,16 @@
344
406
  ".claude/commands/ws-req-flow-sync.md": [
345
407
  "claude:ws-req-flow-sync"
346
408
  ],
347
- ".opencode/command/aiws-init.md": [
409
+ ".opencode/command/p-aiws-init.md": [
348
410
  "opencode:aiws-init"
349
411
  ],
350
- ".opencode/command/aiws-update.md": [
412
+ ".opencode/command/p-aiws-update.md": [
351
413
  "opencode:aiws-update"
352
414
  ],
353
- ".opencode/command/aiws-validate.md": [
415
+ ".opencode/command/p-aiws-validate.md": [
354
416
  "opencode:aiws-validate"
355
417
  ],
356
- ".opencode/command/aiws-rollback.md": [
418
+ ".opencode/command/p-aiws-rollback.md": [
357
419
  "opencode:aiws-rollback"
358
420
  ],
359
421
  ".opencode/command/ws-preflight.md": [
@@ -410,43 +472,43 @@
410
472
  ".opencode/command/ws-req-flow-sync.md": [
411
473
  "opencode:ws-req-flow-sync"
412
474
  ],
413
- ".claude/commands/aiws-change-archive.md": [
475
+ ".claude/commands/p-aiws-change-archive.md": [
414
476
  "claude:aiws-change-archive"
415
477
  ],
416
- ".claude/commands/aiws-change-finish.md": [
478
+ ".claude/commands/p-aiws-change-finish.md": [
417
479
  "claude:aiws-change-finish"
418
480
  ],
419
- ".claude/commands/aiws-change-list.md": [
481
+ ".claude/commands/p-aiws-change-list.md": [
420
482
  "claude:aiws-change-list"
421
483
  ],
422
- ".claude/commands/aiws-change-new.md": [
484
+ ".claude/commands/p-aiws-change-new.md": [
423
485
  "claude:aiws-change-new"
424
486
  ],
425
- ".claude/commands/aiws-change-next.md": [
487
+ ".claude/commands/p-aiws-change-next.md": [
426
488
  "claude:aiws-change-next"
427
489
  ],
428
- ".claude/commands/aiws-change-start.md": [
490
+ ".claude/commands/p-aiws-change-start.md": [
429
491
  "claude:aiws-change-start"
430
492
  ],
431
- ".claude/commands/aiws-change-status.md": [
493
+ ".claude/commands/p-aiws-change-status.md": [
432
494
  "claude:aiws-change-status"
433
495
  ],
434
- ".claude/commands/aiws-change-sync.md": [
496
+ ".claude/commands/p-aiws-change-sync.md": [
435
497
  "claude:aiws-change-sync"
436
498
  ],
437
- ".claude/commands/aiws-change-templates-init.md": [
499
+ ".claude/commands/p-aiws-change-templates-init.md": [
438
500
  "claude:aiws-change-templates-init"
439
501
  ],
440
- ".claude/commands/aiws-change-templates-which.md": [
502
+ ".claude/commands/p-aiws-change-templates-which.md": [
441
503
  "claude:aiws-change-templates-which"
442
504
  ],
443
- ".claude/commands/aiws-change-validate.md": [
505
+ ".claude/commands/p-aiws-change-validate.md": [
444
506
  "claude:aiws-change-validate"
445
507
  ],
446
- ".claude/commands/aiws-hooks-install.md": [
508
+ ".claude/commands/p-aiws-hooks-install.md": [
447
509
  "claude:aiws-hooks-install"
448
510
  ],
449
- ".claude/commands/aiws-hooks-status.md": [
511
+ ".claude/commands/p-aiws-hooks-status.md": [
450
512
  "claude:aiws-hooks-status"
451
513
  ],
452
514
  ".claude/commands/ws-plan.md": [
@@ -455,46 +517,49 @@
455
517
  ".claude/commands/ws-plan-verify.md": [
456
518
  "claude:ws-plan-verify"
457
519
  ],
520
+ ".claude/commands/ws-handoff.md": [
521
+ "claude:ws-handoff"
522
+ ],
458
523
  ".claude/commands/ws-bugfix.md": [
459
524
  "claude:ws-bugfix"
460
525
  ],
461
- ".opencode/command/aiws-change-archive.md": [
526
+ ".opencode/command/p-aiws-change-archive.md": [
462
527
  "opencode:aiws-change-archive"
463
528
  ],
464
- ".opencode/command/aiws-change-finish.md": [
529
+ ".opencode/command/p-aiws-change-finish.md": [
465
530
  "opencode:aiws-change-finish"
466
531
  ],
467
- ".opencode/command/aiws-change-list.md": [
532
+ ".opencode/command/p-aiws-change-list.md": [
468
533
  "opencode:aiws-change-list"
469
534
  ],
470
- ".opencode/command/aiws-change-new.md": [
535
+ ".opencode/command/p-aiws-change-new.md": [
471
536
  "opencode:aiws-change-new"
472
537
  ],
473
- ".opencode/command/aiws-change-next.md": [
538
+ ".opencode/command/p-aiws-change-next.md": [
474
539
  "opencode:aiws-change-next"
475
540
  ],
476
- ".opencode/command/aiws-change-start.md": [
541
+ ".opencode/command/p-aiws-change-start.md": [
477
542
  "opencode:aiws-change-start"
478
543
  ],
479
- ".opencode/command/aiws-change-status.md": [
544
+ ".opencode/command/p-aiws-change-status.md": [
480
545
  "opencode:aiws-change-status"
481
546
  ],
482
- ".opencode/command/aiws-change-sync.md": [
547
+ ".opencode/command/p-aiws-change-sync.md": [
483
548
  "opencode:aiws-change-sync"
484
549
  ],
485
- ".opencode/command/aiws-change-templates-init.md": [
550
+ ".opencode/command/p-aiws-change-templates-init.md": [
486
551
  "opencode:aiws-change-templates-init"
487
552
  ],
488
- ".opencode/command/aiws-change-templates-which.md": [
553
+ ".opencode/command/p-aiws-change-templates-which.md": [
489
554
  "opencode:aiws-change-templates-which"
490
555
  ],
491
- ".opencode/command/aiws-change-validate.md": [
556
+ ".opencode/command/p-aiws-change-validate.md": [
492
557
  "opencode:aiws-change-validate"
493
558
  ],
494
- ".opencode/command/aiws-hooks-install.md": [
559
+ ".opencode/command/p-aiws-hooks-install.md": [
495
560
  "opencode:aiws-hooks-install"
496
561
  ],
497
- ".opencode/command/aiws-hooks-status.md": [
562
+ ".opencode/command/p-aiws-hooks-status.md": [
498
563
  "opencode:aiws-hooks-status"
499
564
  ],
500
565
  ".opencode/command/ws-plan.md": [
@@ -502,6 +567,9 @@
502
567
  ],
503
568
  ".opencode/command/ws-plan-verify.md": [
504
569
  "opencode:ws-plan-verify"
570
+ ],
571
+ ".opencode/command/ws-handoff.md": [
572
+ "opencode:ws-handoff"
505
573
  ]
506
574
  }
507
575
  }
@@ -26,6 +26,73 @@ def read_text(path: Path) -> str:
26
26
  return path.read_text(encoding="utf-8", errors="replace")
27
27
 
28
28
 
29
+ def list_submodules_from_gitmodules(root: Path) -> List[Tuple[str, str]]:
30
+ """Return [(name, sub_path), ...] from .gitmodules, or [] if none."""
31
+ gm = root / ".gitmodules"
32
+ if not gm.exists():
33
+ return []
34
+ try:
35
+ res = subprocess.run(
36
+ ["git", "-C", str(root), "config", "--file", ".gitmodules", "--get-regexp", r"^submodule\..*\.path$"],
37
+ check=False,
38
+ stdout=subprocess.PIPE,
39
+ stderr=subprocess.PIPE,
40
+ text=True,
41
+ )
42
+ except Exception:
43
+ return []
44
+ if res.returncode != 0:
45
+ return []
46
+ subs: List[Tuple[str, str]] = []
47
+ for raw in (res.stdout or "").splitlines():
48
+ line = raw.strip()
49
+ if not line:
50
+ continue
51
+ idx = line.find(" ")
52
+ if idx <= 0:
53
+ continue
54
+ key = line[:idx].strip()
55
+ sub_path = line[idx + 1 :].strip()
56
+ m = re.match(r"^submodule\.([^.]+)\.path$", key)
57
+ if not m:
58
+ continue
59
+ name = (m.group(1) or "").strip()
60
+ if name and sub_path:
61
+ subs.append((name, sub_path))
62
+ return subs
63
+
64
+
65
+ def parse_submodule_targets(path: Path) -> Tuple[Dict[str, Tuple[str, str]], List[str]]:
66
+ """Parse a submodules.targets file. Returns (parsed_dict, error_messages)."""
67
+ parsed: Dict[str, Tuple[str, str]] = {}
68
+ perr: List[str] = []
69
+ if not path.exists():
70
+ return parsed, perr
71
+ text = read_text(path)
72
+ for i, raw in enumerate(text.splitlines(), start=1):
73
+ line = raw.strip()
74
+ if not line or line.startswith("#"):
75
+ continue
76
+ parts = re.split(r"\s+", line)
77
+ if len(parts) < 2:
78
+ perr.append(f"{path.name}:{i} invalid line (expected: <path> <target_branch> [remote])")
79
+ continue
80
+ sub_path = parts[0].strip()
81
+ target_branch = parts[1].strip()
82
+ remote = (parts[2].strip() if len(parts) >= 3 else "origin") or "origin"
83
+ if not sub_path:
84
+ perr.append(f"{path.name}:{i} missing submodule path")
85
+ continue
86
+ if sub_path in parsed:
87
+ perr.append(f"{path.name}:{i} duplicate submodule path: {sub_path}")
88
+ continue
89
+ if not target_branch or target_branch in ("<fill-me>", "<fill_me>", "tbd", "TBD"):
90
+ perr.append(f"{path.name}:{i} missing/placeholder target_branch for {sub_path}")
91
+ continue
92
+ parsed[sub_path] = (target_branch, remote)
93
+ return parsed, perr
94
+
95
+
29
96
  def sha256(path: Path) -> str:
30
97
  h = hashlib.sha256()
31
98
  with path.open("rb") as f:
@@ -334,6 +401,38 @@ def validate_change(
334
401
  errors: List[str] = []
335
402
  warnings: List[str] = []
336
403
 
404
+ # Submodule targets constraint: when `.gitmodules` declares submodules, require a per-change target mapping.
405
+ # In strict mode this is an error (blocks delivery); in non-strict mode it's a warning (informational).
406
+ subs = list_submodules_from_gitmodules(root)
407
+ if subs:
408
+ targets_path = change_dir / "submodules.targets"
409
+ if not targets_path.exists() or targets_path.stat().st_size == 0:
410
+ msg = "missing/empty: changes/<change-id>/submodules.targets (required when .gitmodules declares submodules)"
411
+ hint = f"hint: create it under {change_dir} (format: <sub_path> <target_branch> [remote])"
412
+ if strict:
413
+ errors.append(msg)
414
+ errors.append(hint)
415
+ else:
416
+ warnings.append(msg)
417
+ warnings.append(hint)
418
+ else:
419
+ targets, perr = parse_submodule_targets(targets_path)
420
+ for pe in perr:
421
+ errors.append(pe)
422
+ declared_paths = {p for _, p in subs}
423
+ missing_paths = sorted([p for p in declared_paths if p not in targets])
424
+ if missing_paths:
425
+ msg = f"{targets_path.name} missing entries for submodules: {', '.join(missing_paths)}"
426
+ if strict:
427
+ errors.append(msg)
428
+ else:
429
+ warnings.append(msg)
430
+ extra_paths = sorted([p for p in targets.keys() if p not in declared_paths])
431
+ if extra_paths:
432
+ warnings.append(
433
+ f"{targets_path.name} includes unknown submodule paths (ignored): {', '.join(extra_paths)}"
434
+ )
435
+
337
436
  def file_state(rel: str) -> Optional[Path]:
338
437
  p = change_dir / rel
339
438
  if not p.exists():
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env bash
2
+ # ws_resolve_sub_target.sh — Resolve the target branch & remote for a submodule path.
3
+ #
4
+ # Usage:
5
+ # source tools/ws_resolve_sub_target.sh
6
+ # ws_resolve_sub_target <sub_path> <sub_name> <targets_file> <base_branch>
7
+ #
8
+ # Outputs two variables: _resolved_branch and _resolved_remote.
9
+ # Returns 0 on success, 2 on failure (with error printed to stderr).
10
+
11
+ ws_resolve_sub_target() {
12
+ local sub_path="$1" sub_name="$2" targets="$3" base_branch="$4"
13
+ _resolved_branch=""
14
+ _resolved_remote=""
15
+
16
+ # Priority 1: changes/<id>/submodules.targets (per-change override)
17
+ local override=""
18
+ if [[ -f "${targets}" ]]; then
19
+ override="$(awk -v p="${sub_path}" '
20
+ $1==p && $0 !~ /^[[:space:]]*#/ {
21
+ b=$2; r=$3;
22
+ if (r=="") r="origin";
23
+ if (b!="") { print b " " r; exit }
24
+ }
25
+ ' "${targets}" 2>/dev/null || true)"
26
+ fi
27
+
28
+ if [[ -n "${override:-}" ]]; then
29
+ _resolved_branch="${override%% *}"
30
+ _resolved_remote="${override#* }"
31
+ else
32
+ # Priority 2: .gitmodules submodule.<name>.branch
33
+ local cfg_branch
34
+ cfg_branch="$(git config --file .gitmodules --get "submodule.${sub_name}.branch" 2>/dev/null || true)"
35
+ if [[ "${cfg_branch:-}" == "." ]]; then cfg_branch="${base_branch}"; fi
36
+ _resolved_branch="${cfg_branch}"
37
+ _resolved_remote="origin"
38
+ fi
39
+
40
+ if [[ -z "${_resolved_branch:-}" ]]; then
41
+ echo "error: cannot resolve target branch for submodule path=${sub_path}" >&2
42
+ echo "hint: add an entry to ${targets} (preferred for multi-channel), or set .gitmodules submodule.<name>.branch" >&2
43
+ return 2
44
+ fi
45
+ return 0
46
+ }