@aipper/aiws-spec 0.0.21 → 0.0.24

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 (89) 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-bugfix/SKILL.md +30 -7
  22. package/templates/workspace/.agents/skills/ws-commit/SKILL.md +23 -6
  23. package/templates/workspace/.agents/skills/ws-deliver/SKILL.md +61 -17
  24. package/templates/workspace/.agents/skills/ws-dev/SKILL.md +102 -2
  25. package/templates/workspace/.agents/skills/ws-finish/SKILL.md +96 -65
  26. package/templates/workspace/.agents/skills/ws-handoff/SKILL.md +31 -0
  27. package/templates/workspace/.agents/skills/ws-plan/SKILL.md +68 -1
  28. package/templates/workspace/.agents/skills/ws-push/SKILL.md +17 -12
  29. package/templates/workspace/.claude/commands/{aiws-change-archive.md → p-aiws-change-archive.md} +3 -1
  30. package/templates/workspace/.claude/commands/{aiws-change-finish.md → p-aiws-change-finish.md} +2 -0
  31. package/templates/workspace/.claude/commands/{aiws-change-list.md → p-aiws-change-list.md} +2 -0
  32. package/templates/workspace/.claude/commands/{aiws-change-new.md → p-aiws-change-new.md} +2 -0
  33. package/templates/workspace/.claude/commands/{aiws-change-next.md → p-aiws-change-next.md} +2 -0
  34. package/templates/workspace/.claude/commands/{aiws-change-start.md → p-aiws-change-start.md} +2 -0
  35. package/templates/workspace/.claude/commands/{aiws-change-status.md → p-aiws-change-status.md} +2 -0
  36. package/templates/workspace/.claude/commands/{aiws-change-sync.md → p-aiws-change-sync.md} +2 -0
  37. package/templates/workspace/.claude/commands/{aiws-change-templates-init.md → p-aiws-change-templates-init.md} +2 -0
  38. package/templates/workspace/.claude/commands/{aiws-change-templates-which.md → p-aiws-change-templates-which.md} +2 -0
  39. package/templates/workspace/.claude/commands/{aiws-change-validate.md → p-aiws-change-validate.md} +2 -0
  40. package/templates/workspace/.claude/commands/{aiws-hooks-install.md → p-aiws-hooks-install.md} +2 -0
  41. package/templates/workspace/.claude/commands/{aiws-hooks-status.md → p-aiws-hooks-status.md} +2 -0
  42. package/templates/workspace/.claude/commands/{aiws-init.md → p-aiws-init.md} +2 -1
  43. package/templates/workspace/.claude/commands/{aiws-rollback.md → p-aiws-rollback.md} +2 -1
  44. package/templates/workspace/.claude/commands/{aiws-update.md → p-aiws-update.md} +2 -1
  45. package/templates/workspace/.claude/commands/{aiws-validate.md → p-aiws-validate.md} +2 -1
  46. package/templates/workspace/.claude/commands/ws-bugfix.md +11 -6
  47. package/templates/workspace/.claude/commands/ws-commit.md +2 -1
  48. package/templates/workspace/.claude/commands/ws-deliver.md +6 -2
  49. package/templates/workspace/.claude/commands/ws-dev.md +7 -1
  50. package/templates/workspace/.claude/commands/ws-finish.md +19 -19
  51. package/templates/workspace/.claude/commands/ws-handoff.md +22 -0
  52. package/templates/workspace/.claude/commands/ws-plan.md +9 -5
  53. package/templates/workspace/.codex/prompts/ws-dev.md +5 -1
  54. package/templates/workspace/.githooks/commit-msg +109 -0
  55. package/templates/workspace/.iflow/commands/ws-commit.toml +2 -1
  56. package/templates/workspace/.iflow/commands/ws-deliver.toml +6 -2
  57. package/templates/workspace/.iflow/commands/ws-finish.toml +19 -19
  58. package/templates/workspace/.opencode/command/{aiws-change-archive.md → p-aiws-change-archive.md} +4 -2
  59. package/templates/workspace/.opencode/command/{aiws-change-finish.md → p-aiws-change-finish.md} +3 -1
  60. package/templates/workspace/.opencode/command/{aiws-change-list.md → p-aiws-change-list.md} +3 -1
  61. package/templates/workspace/.opencode/command/{aiws-change-new.md → p-aiws-change-new.md} +3 -1
  62. package/templates/workspace/.opencode/command/{aiws-change-next.md → p-aiws-change-next.md} +3 -1
  63. package/templates/workspace/.opencode/command/{aiws-change-start.md → p-aiws-change-start.md} +3 -1
  64. package/templates/workspace/.opencode/command/{aiws-change-status.md → p-aiws-change-status.md} +3 -1
  65. package/templates/workspace/.opencode/command/{aiws-change-sync.md → p-aiws-change-sync.md} +3 -1
  66. package/templates/workspace/.opencode/command/{aiws-change-templates-init.md → p-aiws-change-templates-init.md} +3 -1
  67. package/templates/workspace/.opencode/command/{aiws-change-templates-which.md → p-aiws-change-templates-which.md} +3 -1
  68. package/templates/workspace/.opencode/command/{aiws-change-validate.md → p-aiws-change-validate.md} +3 -1
  69. package/templates/workspace/.opencode/command/{aiws-hooks-install.md → p-aiws-hooks-install.md} +3 -1
  70. package/templates/workspace/.opencode/command/{aiws-hooks-status.md → p-aiws-hooks-status.md} +3 -1
  71. package/templates/workspace/.opencode/command/{aiws-init.md → p-aiws-init.md} +3 -1
  72. package/templates/workspace/.opencode/command/{aiws-rollback.md → p-aiws-rollback.md} +3 -1
  73. package/templates/workspace/.opencode/command/{aiws-update.md → p-aiws-update.md} +3 -1
  74. package/templates/workspace/.opencode/command/{aiws-validate.md → p-aiws-validate.md} +3 -1
  75. package/templates/workspace/.opencode/command/ws-bugfix.md +11 -6
  76. package/templates/workspace/.opencode/command/ws-commit.md +3 -2
  77. package/templates/workspace/.opencode/command/ws-deliver.md +6 -2
  78. package/templates/workspace/.opencode/command/ws-dev.md +7 -1
  79. package/templates/workspace/.opencode/command/ws-finish.md +19 -19
  80. package/templates/workspace/.opencode/command/ws-handoff.md +25 -0
  81. package/templates/workspace/.opencode/command/ws-plan.md +9 -5
  82. package/templates/workspace/.opencode/command/ws-review.md +1 -1
  83. package/templates/workspace/AGENTS.md +8 -4
  84. package/templates/workspace/AI_WORKSPACE.md +4 -4
  85. package/templates/workspace/changes/README.md +8 -2
  86. package/templates/workspace/manifest.json +173 -103
  87. package/templates/workspace/tools/ws_change_check.py +99 -0
  88. package/templates/workspace/tools/ws_resolve_sub_target.sh +47 -0
  89. package/templates/workspace/tools/ws_tasks_plan.py +137 -0
@@ -17,6 +17,7 @@
17
17
  "REQUIREMENTS.md",
18
18
  ".gitignore",
19
19
  ".aiws/manifest.json",
20
+ ".githooks/commit-msg",
20
21
  ".githooks/pre-commit",
21
22
  ".githooks/pre-push",
22
23
  "changes/README.md",
@@ -26,10 +27,11 @@
26
27
  ".agents/skills/**",
27
28
  "tools/ws_change_check.py",
28
29
  "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",
30
+ "tools/ws_tasks_plan.py",
31
+ ".claude/commands/p-aiws-init.md",
32
+ ".claude/commands/p-aiws-update.md",
33
+ ".claude/commands/p-aiws-validate.md",
34
+ ".claude/commands/p-aiws-rollback.md",
33
35
  ".claude/commands/ws-preflight.md",
34
36
  ".claude/commands/ws-migrate.md",
35
37
  ".claude/commands/ws-dev.md",
@@ -47,10 +49,10 @@
47
49
  ".claude/commands/ws-req-contract-sync.md",
48
50
  ".claude/commands/ws-req-contract-validate.md",
49
51
  ".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",
52
+ ".opencode/command/p-aiws-init.md",
53
+ ".opencode/command/p-aiws-update.md",
54
+ ".opencode/command/p-aiws-validate.md",
55
+ ".opencode/command/p-aiws-rollback.md",
54
56
  ".opencode/command/ws-preflight.md",
55
57
  ".opencode/command/ws-migrate.md",
56
58
  ".opencode/command/ws-dev.md",
@@ -106,37 +108,39 @@
106
108
  ".iflow/commands/ws-req-contract-sync.toml",
107
109
  ".iflow/commands/ws-req-contract-validate.toml",
108
110
  ".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",
111
+ ".claude/commands/p-aiws-change-archive.md",
112
+ ".claude/commands/p-aiws-change-finish.md",
113
+ ".claude/commands/p-aiws-change-list.md",
114
+ ".claude/commands/p-aiws-change-new.md",
115
+ ".claude/commands/p-aiws-change-next.md",
116
+ ".claude/commands/p-aiws-change-start.md",
117
+ ".claude/commands/p-aiws-change-status.md",
118
+ ".claude/commands/p-aiws-change-sync.md",
119
+ ".claude/commands/p-aiws-change-templates-init.md",
120
+ ".claude/commands/p-aiws-change-templates-which.md",
121
+ ".claude/commands/p-aiws-change-validate.md",
122
+ ".claude/commands/p-aiws-hooks-install.md",
123
+ ".claude/commands/p-aiws-hooks-status.md",
122
124
  ".claude/commands/ws-plan.md",
123
125
  ".claude/commands/ws-plan-verify.md",
126
+ ".claude/commands/ws-handoff.md",
124
127
  ".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",
128
+ ".opencode/command/p-aiws-change-archive.md",
129
+ ".opencode/command/p-aiws-change-finish.md",
130
+ ".opencode/command/p-aiws-change-list.md",
131
+ ".opencode/command/p-aiws-change-new.md",
132
+ ".opencode/command/p-aiws-change-next.md",
133
+ ".opencode/command/p-aiws-change-start.md",
134
+ ".opencode/command/p-aiws-change-status.md",
135
+ ".opencode/command/p-aiws-change-sync.md",
136
+ ".opencode/command/p-aiws-change-templates-init.md",
137
+ ".opencode/command/p-aiws-change-templates-which.md",
138
+ ".opencode/command/p-aiws-change-validate.md",
139
+ ".opencode/command/p-aiws-hooks-install.md",
140
+ ".opencode/command/p-aiws-hooks-status.md",
138
141
  ".opencode/command/ws-plan.md",
139
- ".opencode/command/ws-plan-verify.md"
142
+ ".opencode/command/ws-plan-verify.md",
143
+ ".opencode/command/ws-handoff.md"
140
144
  ],
141
145
  "optional": [
142
146
  ".iflow/agents/**",
@@ -149,19 +153,15 @@
149
153
  "tools/requirements_flow_gen.py",
150
154
  "tools/server_test_runner.py",
151
155
  "tools/iflow_watchdog.sh",
152
- "tools/install_iflow_watchdog_systemd_user.sh"
156
+ "tools/install_iflow_watchdog_systemd_user.sh",
157
+ "tools/ws_resolve_sub_target.sh"
153
158
  ],
154
159
  "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",
160
+ "remove": [
161
161
  ".agents/skills/aiws-init/SKILL.md",
162
- ".agents/skills/aiws-rollback/SKILL.md",
163
162
  ".agents/skills/aiws-update/SKILL.md",
164
163
  ".agents/skills/aiws-validate/SKILL.md",
164
+ ".agents/skills/aiws-rollback/SKILL.md",
165
165
  ".agents/skills/aiws-hooks-install/SKILL.md",
166
166
  ".agents/skills/aiws-hooks-status/SKILL.md",
167
167
  ".agents/skills/aiws-change-list/SKILL.md",
@@ -175,6 +175,68 @@
175
175
  ".agents/skills/aiws-change-archive/SKILL.md",
176
176
  ".agents/skills/aiws-change-templates-which/SKILL.md",
177
177
  ".agents/skills/aiws-change-templates-init/SKILL.md",
178
+ ".claude/commands/aiws-init.md",
179
+ ".claude/commands/aiws-update.md",
180
+ ".claude/commands/aiws-validate.md",
181
+ ".claude/commands/aiws-rollback.md",
182
+ ".claude/commands/aiws-hooks-install.md",
183
+ ".claude/commands/aiws-hooks-status.md",
184
+ ".claude/commands/aiws-change-list.md",
185
+ ".claude/commands/aiws-change-new.md",
186
+ ".claude/commands/aiws-change-start.md",
187
+ ".claude/commands/aiws-change-finish.md",
188
+ ".claude/commands/aiws-change-status.md",
189
+ ".claude/commands/aiws-change-next.md",
190
+ ".claude/commands/aiws-change-sync.md",
191
+ ".claude/commands/aiws-change-validate.md",
192
+ ".claude/commands/aiws-change-archive.md",
193
+ ".claude/commands/aiws-change-templates-which.md",
194
+ ".claude/commands/aiws-change-templates-init.md",
195
+ ".opencode/command/aiws-init.md",
196
+ ".opencode/command/aiws-update.md",
197
+ ".opencode/command/aiws-validate.md",
198
+ ".opencode/command/aiws-rollback.md",
199
+ ".opencode/command/aiws-hooks-install.md",
200
+ ".opencode/command/aiws-hooks-status.md",
201
+ ".opencode/command/aiws-change-list.md",
202
+ ".opencode/command/aiws-change-new.md",
203
+ ".opencode/command/aiws-change-start.md",
204
+ ".opencode/command/aiws-change-finish.md",
205
+ ".opencode/command/aiws-change-status.md",
206
+ ".opencode/command/aiws-change-next.md",
207
+ ".opencode/command/aiws-change-sync.md",
208
+ ".opencode/command/aiws-change-validate.md",
209
+ ".opencode/command/aiws-change-archive.md",
210
+ ".opencode/command/aiws-change-templates-which.md",
211
+ ".opencode/command/aiws-change-templates-init.md",
212
+ ".agents/skills/ws-tasks-plan/SKILL.md"
213
+ ],
214
+ "replace_file": [
215
+ ".aiws/manifest.json",
216
+ ".githooks/commit-msg",
217
+ ".githooks/pre-commit",
218
+ ".githooks/pre-push",
219
+ "tools/ws_change_check.py",
220
+ "tools/requirements_contract.py",
221
+ "tools/ws_tasks_plan.py",
222
+ "tools/ws_resolve_sub_target.sh",
223
+ ".agents/skills/p-aiws-init/SKILL.md",
224
+ ".agents/skills/p-aiws-rollback/SKILL.md",
225
+ ".agents/skills/p-aiws-update/SKILL.md",
226
+ ".agents/skills/p-aiws-validate/SKILL.md",
227
+ ".agents/skills/p-aiws-hooks-install/SKILL.md",
228
+ ".agents/skills/p-aiws-hooks-status/SKILL.md",
229
+ ".agents/skills/p-aiws-change-list/SKILL.md",
230
+ ".agents/skills/p-aiws-change-new/SKILL.md",
231
+ ".agents/skills/p-aiws-change-start/SKILL.md",
232
+ ".agents/skills/p-aiws-change-finish/SKILL.md",
233
+ ".agents/skills/p-aiws-change-status/SKILL.md",
234
+ ".agents/skills/p-aiws-change-next/SKILL.md",
235
+ ".agents/skills/p-aiws-change-sync/SKILL.md",
236
+ ".agents/skills/p-aiws-change-validate/SKILL.md",
237
+ ".agents/skills/p-aiws-change-archive/SKILL.md",
238
+ ".agents/skills/p-aiws-change-templates-which/SKILL.md",
239
+ ".agents/skills/p-aiws-change-templates-init/SKILL.md",
178
240
  ".agents/skills/ws-analyze/SKILL.md",
179
241
  ".agents/skills/ws-bugfix/SKILL.md",
180
242
  ".agents/skills/ws-commit/SKILL.md",
@@ -184,6 +246,8 @@
184
246
  ".agents/skills/ws-migrate/SKILL.md",
185
247
  ".agents/skills/ws-plan/SKILL.md",
186
248
  ".agents/skills/ws-plan-verify/SKILL.md",
249
+ ".agents/skills/p-tasks-plan/SKILL.md",
250
+ ".agents/skills/ws-handoff/SKILL.md",
187
251
  ".agents/skills/ws-pull/SKILL.md",
188
252
  ".agents/skills/ws-push/SKILL.md",
189
253
  ".agents/skills/ws-submodule-setup/SKILL.md",
@@ -233,35 +297,35 @@
233
297
  ".iflow/commands/ws-req-contract-sync.toml",
234
298
  ".iflow/commands/ws-req-contract-validate.toml",
235
299
  ".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",
300
+ ".claude/commands/p-aiws-change-archive.md",
301
+ ".claude/commands/p-aiws-change-finish.md",
302
+ ".claude/commands/p-aiws-change-list.md",
303
+ ".claude/commands/p-aiws-change-new.md",
304
+ ".claude/commands/p-aiws-change-next.md",
305
+ ".claude/commands/p-aiws-change-start.md",
306
+ ".claude/commands/p-aiws-change-status.md",
307
+ ".claude/commands/p-aiws-change-sync.md",
308
+ ".claude/commands/p-aiws-change-templates-init.md",
309
+ ".claude/commands/p-aiws-change-templates-which.md",
310
+ ".claude/commands/p-aiws-change-validate.md",
311
+ ".claude/commands/p-aiws-hooks-install.md",
312
+ ".claude/commands/p-aiws-hooks-status.md",
249
313
  ".claude/commands/ws-plan.md",
250
314
  ".claude/commands/ws-plan-verify.md",
251
315
  ".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",
316
+ ".opencode/command/p-aiws-change-archive.md",
317
+ ".opencode/command/p-aiws-change-finish.md",
318
+ ".opencode/command/p-aiws-change-list.md",
319
+ ".opencode/command/p-aiws-change-new.md",
320
+ ".opencode/command/p-aiws-change-next.md",
321
+ ".opencode/command/p-aiws-change-start.md",
322
+ ".opencode/command/p-aiws-change-status.md",
323
+ ".opencode/command/p-aiws-change-sync.md",
324
+ ".opencode/command/p-aiws-change-templates-init.md",
325
+ ".opencode/command/p-aiws-change-templates-which.md",
326
+ ".opencode/command/p-aiws-change-validate.md",
327
+ ".opencode/command/p-aiws-hooks-install.md",
328
+ ".opencode/command/p-aiws-hooks-status.md",
265
329
  ".opencode/command/ws-plan.md",
266
330
  ".opencode/command/ws-plan-verify.md"
267
331
  ],
@@ -281,16 +345,16 @@
281
345
  ".gitignore": [
282
346
  "gitignore"
283
347
  ],
284
- ".claude/commands/aiws-init.md": [
348
+ ".claude/commands/p-aiws-init.md": [
285
349
  "claude:aiws-init"
286
350
  ],
287
- ".claude/commands/aiws-update.md": [
351
+ ".claude/commands/p-aiws-update.md": [
288
352
  "claude:aiws-update"
289
353
  ],
290
- ".claude/commands/aiws-validate.md": [
354
+ ".claude/commands/p-aiws-validate.md": [
291
355
  "claude:aiws-validate"
292
356
  ],
293
- ".claude/commands/aiws-rollback.md": [
357
+ ".claude/commands/p-aiws-rollback.md": [
294
358
  "claude:aiws-rollback"
295
359
  ],
296
360
  ".claude/commands/ws-preflight.md": [
@@ -344,16 +408,16 @@
344
408
  ".claude/commands/ws-req-flow-sync.md": [
345
409
  "claude:ws-req-flow-sync"
346
410
  ],
347
- ".opencode/command/aiws-init.md": [
411
+ ".opencode/command/p-aiws-init.md": [
348
412
  "opencode:aiws-init"
349
413
  ],
350
- ".opencode/command/aiws-update.md": [
414
+ ".opencode/command/p-aiws-update.md": [
351
415
  "opencode:aiws-update"
352
416
  ],
353
- ".opencode/command/aiws-validate.md": [
417
+ ".opencode/command/p-aiws-validate.md": [
354
418
  "opencode:aiws-validate"
355
419
  ],
356
- ".opencode/command/aiws-rollback.md": [
420
+ ".opencode/command/p-aiws-rollback.md": [
357
421
  "opencode:aiws-rollback"
358
422
  ],
359
423
  ".opencode/command/ws-preflight.md": [
@@ -410,43 +474,43 @@
410
474
  ".opencode/command/ws-req-flow-sync.md": [
411
475
  "opencode:ws-req-flow-sync"
412
476
  ],
413
- ".claude/commands/aiws-change-archive.md": [
477
+ ".claude/commands/p-aiws-change-archive.md": [
414
478
  "claude:aiws-change-archive"
415
479
  ],
416
- ".claude/commands/aiws-change-finish.md": [
480
+ ".claude/commands/p-aiws-change-finish.md": [
417
481
  "claude:aiws-change-finish"
418
482
  ],
419
- ".claude/commands/aiws-change-list.md": [
483
+ ".claude/commands/p-aiws-change-list.md": [
420
484
  "claude:aiws-change-list"
421
485
  ],
422
- ".claude/commands/aiws-change-new.md": [
486
+ ".claude/commands/p-aiws-change-new.md": [
423
487
  "claude:aiws-change-new"
424
488
  ],
425
- ".claude/commands/aiws-change-next.md": [
489
+ ".claude/commands/p-aiws-change-next.md": [
426
490
  "claude:aiws-change-next"
427
491
  ],
428
- ".claude/commands/aiws-change-start.md": [
492
+ ".claude/commands/p-aiws-change-start.md": [
429
493
  "claude:aiws-change-start"
430
494
  ],
431
- ".claude/commands/aiws-change-status.md": [
495
+ ".claude/commands/p-aiws-change-status.md": [
432
496
  "claude:aiws-change-status"
433
497
  ],
434
- ".claude/commands/aiws-change-sync.md": [
498
+ ".claude/commands/p-aiws-change-sync.md": [
435
499
  "claude:aiws-change-sync"
436
500
  ],
437
- ".claude/commands/aiws-change-templates-init.md": [
501
+ ".claude/commands/p-aiws-change-templates-init.md": [
438
502
  "claude:aiws-change-templates-init"
439
503
  ],
440
- ".claude/commands/aiws-change-templates-which.md": [
504
+ ".claude/commands/p-aiws-change-templates-which.md": [
441
505
  "claude:aiws-change-templates-which"
442
506
  ],
443
- ".claude/commands/aiws-change-validate.md": [
507
+ ".claude/commands/p-aiws-change-validate.md": [
444
508
  "claude:aiws-change-validate"
445
509
  ],
446
- ".claude/commands/aiws-hooks-install.md": [
510
+ ".claude/commands/p-aiws-hooks-install.md": [
447
511
  "claude:aiws-hooks-install"
448
512
  ],
449
- ".claude/commands/aiws-hooks-status.md": [
513
+ ".claude/commands/p-aiws-hooks-status.md": [
450
514
  "claude:aiws-hooks-status"
451
515
  ],
452
516
  ".claude/commands/ws-plan.md": [
@@ -455,46 +519,49 @@
455
519
  ".claude/commands/ws-plan-verify.md": [
456
520
  "claude:ws-plan-verify"
457
521
  ],
522
+ ".claude/commands/ws-handoff.md": [
523
+ "claude:ws-handoff"
524
+ ],
458
525
  ".claude/commands/ws-bugfix.md": [
459
526
  "claude:ws-bugfix"
460
527
  ],
461
- ".opencode/command/aiws-change-archive.md": [
528
+ ".opencode/command/p-aiws-change-archive.md": [
462
529
  "opencode:aiws-change-archive"
463
530
  ],
464
- ".opencode/command/aiws-change-finish.md": [
531
+ ".opencode/command/p-aiws-change-finish.md": [
465
532
  "opencode:aiws-change-finish"
466
533
  ],
467
- ".opencode/command/aiws-change-list.md": [
534
+ ".opencode/command/p-aiws-change-list.md": [
468
535
  "opencode:aiws-change-list"
469
536
  ],
470
- ".opencode/command/aiws-change-new.md": [
537
+ ".opencode/command/p-aiws-change-new.md": [
471
538
  "opencode:aiws-change-new"
472
539
  ],
473
- ".opencode/command/aiws-change-next.md": [
540
+ ".opencode/command/p-aiws-change-next.md": [
474
541
  "opencode:aiws-change-next"
475
542
  ],
476
- ".opencode/command/aiws-change-start.md": [
543
+ ".opencode/command/p-aiws-change-start.md": [
477
544
  "opencode:aiws-change-start"
478
545
  ],
479
- ".opencode/command/aiws-change-status.md": [
546
+ ".opencode/command/p-aiws-change-status.md": [
480
547
  "opencode:aiws-change-status"
481
548
  ],
482
- ".opencode/command/aiws-change-sync.md": [
549
+ ".opencode/command/p-aiws-change-sync.md": [
483
550
  "opencode:aiws-change-sync"
484
551
  ],
485
- ".opencode/command/aiws-change-templates-init.md": [
552
+ ".opencode/command/p-aiws-change-templates-init.md": [
486
553
  "opencode:aiws-change-templates-init"
487
554
  ],
488
- ".opencode/command/aiws-change-templates-which.md": [
555
+ ".opencode/command/p-aiws-change-templates-which.md": [
489
556
  "opencode:aiws-change-templates-which"
490
557
  ],
491
- ".opencode/command/aiws-change-validate.md": [
558
+ ".opencode/command/p-aiws-change-validate.md": [
492
559
  "opencode:aiws-change-validate"
493
560
  ],
494
- ".opencode/command/aiws-hooks-install.md": [
561
+ ".opencode/command/p-aiws-hooks-install.md": [
495
562
  "opencode:aiws-hooks-install"
496
563
  ],
497
- ".opencode/command/aiws-hooks-status.md": [
564
+ ".opencode/command/p-aiws-hooks-status.md": [
498
565
  "opencode:aiws-hooks-status"
499
566
  ],
500
567
  ".opencode/command/ws-plan.md": [
@@ -502,6 +569,9 @@
502
569
  ],
503
570
  ".opencode/command/ws-plan-verify.md": [
504
571
  "opencode:ws-plan-verify"
572
+ ],
573
+ ".opencode/command/ws-handoff.md": [
574
+ "opencode:ws-handoff"
505
575
  ]
506
576
  }
507
577
  }
@@ -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,47 @@
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
+ if [[ "${_resolved_branch:-}" == "." ]]; then _resolved_branch="${base_branch}"; fi
32
+ else
33
+ # Priority 2: .gitmodules submodule.<name>.branch
34
+ local cfg_branch
35
+ cfg_branch="$(git config --file .gitmodules --get "submodule.${sub_name}.branch" 2>/dev/null || true)"
36
+ if [[ "${cfg_branch:-}" == "." ]]; then cfg_branch="${base_branch}"; fi
37
+ _resolved_branch="${cfg_branch}"
38
+ _resolved_remote="origin"
39
+ fi
40
+
41
+ if [[ -z "${_resolved_branch:-}" ]]; then
42
+ echo "error: cannot resolve target branch for submodule path=${sub_path}" >&2
43
+ echo "hint: add an entry to ${targets} (preferred for multi-channel), or set .gitmodules submodule.<name>.branch" >&2
44
+ return 2
45
+ fi
46
+ return 0
47
+ }