@rpamis/comet 0.3.6 → 0.3.8
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 +575 -443
- package/assets/manifest.json +41 -24
- package/assets/skills/comet/SKILL.md +282 -301
- package/assets/skills/comet/reference/auto-transition.md +27 -0
- package/assets/skills/comet/reference/comet-yaml-fields.md +68 -0
- package/assets/skills/comet/reference/context-recovery.md +35 -0
- package/assets/skills/comet/reference/debug-gate.md +17 -0
- package/assets/skills/comet/reference/decision-point.md +20 -0
- package/assets/skills/comet/reference/dirty-worktree.md +1 -0
- package/assets/skills/comet/reference/file-structure.md +28 -0
- package/assets/skills/comet/reference/subagent-dispatch.md +113 -0
- package/assets/skills/comet/rules/comet-phase-guard.en.md +99 -0
- package/assets/skills/comet/rules/comet-phase-guard.md +99 -0
- package/assets/skills/comet/scripts/comet-archive.sh +71 -55
- package/assets/skills/comet/scripts/comet-guard.sh +174 -18
- package/assets/skills/comet/scripts/comet-handoff.sh +133 -6
- package/assets/skills/comet/scripts/comet-hook-guard.sh +260 -0
- package/assets/skills/comet/scripts/comet-state.sh +362 -25
- package/assets/skills/comet/scripts/comet-yaml-validate.sh +24 -1
- package/assets/skills/comet-archive/SKILL.md +100 -73
- package/assets/skills/comet-build/SKILL.md +304 -221
- package/assets/skills/comet-design/SKILL.md +263 -166
- package/assets/skills/comet-hotfix/SKILL.md +204 -169
- package/assets/skills/comet-open/SKILL.md +203 -113
- package/assets/skills/comet-tweak/SKILL.md +180 -154
- package/assets/skills/comet-verify/SKILL.md +234 -201
- package/assets/skills-zh/comet/SKILL.md +269 -301
- package/assets/skills-zh/comet/reference/auto-transition.md +27 -0
- package/assets/skills-zh/comet/reference/comet-yaml-fields.md +68 -0
- package/assets/skills-zh/comet/reference/context-recovery.md +35 -0
- package/assets/skills-zh/comet/reference/debug-gate.md +17 -0
- package/assets/skills-zh/comet/reference/decision-point.md +20 -0
- package/assets/skills-zh/comet/reference/dirty-worktree.md +2 -1
- package/assets/skills-zh/comet/reference/file-structure.md +28 -0
- package/assets/skills-zh/comet/reference/subagent-dispatch.md +113 -0
- package/assets/skills-zh/comet-archive/SKILL.md +100 -73
- package/assets/skills-zh/comet-build/SKILL.md +304 -221
- package/assets/skills-zh/comet-design/SKILL.md +264 -166
- package/assets/skills-zh/comet-hotfix/SKILL.md +200 -169
- package/assets/skills-zh/comet-open/SKILL.md +203 -113
- package/assets/skills-zh/comet-tweak/SKILL.md +176 -154
- package/assets/skills-zh/comet-verify/SKILL.md +232 -201
- package/dist/cli/index.js +19 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +22 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +5 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +64 -9
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/uninstall.d.ts +9 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +113 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.d.ts +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +120 -32
- package/dist/commands/update.js.map +1 -1
- package/dist/core/codegraph.d.ts +4 -0
- package/dist/core/codegraph.d.ts.map +1 -0
- package/dist/core/codegraph.js +63 -0
- package/dist/core/codegraph.js.map +1 -0
- package/dist/core/detect.d.ts +8 -1
- package/dist/core/detect.d.ts.map +1 -1
- package/dist/core/detect.js +41 -2
- package/dist/core/detect.js.map +1 -1
- package/dist/core/openspec.d.ts +1 -1
- package/dist/core/openspec.d.ts.map +1 -1
- package/dist/core/openspec.js +40 -17
- package/dist/core/openspec.js.map +1 -1
- package/dist/core/platforms.d.ts +10 -0
- package/dist/core/platforms.d.ts.map +1 -1
- package/dist/core/platforms.js +177 -16
- package/dist/core/platforms.js.map +1 -1
- package/dist/core/skills.d.ts +36 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +451 -15
- package/dist/core/skills.js.map +1 -1
- package/dist/core/superpowers.d.ts.map +1 -1
- package/dist/core/superpowers.js +1 -0
- package/dist/core/superpowers.js.map +1 -1
- package/dist/core/uninstall.d.ts +28 -0
- package/dist/core/uninstall.d.ts.map +1 -0
- package/dist/core/uninstall.js +421 -0
- package/dist/core/uninstall.js.map +1 -0
- package/dist/core/version.d.ts +31 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +111 -0
- package/dist/core/version.js.map +1 -0
- package/dist/utils/file-system.d.ts +23 -0
- package/dist/utils/file-system.d.ts.map +1 -1
- package/dist/utils/file-system.js +100 -5
- package/dist/utils/file-system.js.map +1 -1
- package/package.json +69 -62
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
# check <change-name> <phase> — Verify entry requirements for a phase
|
|
11
11
|
# check <change-name> <phase> --recover — Output structured recovery context for compaction resume
|
|
12
12
|
# scale <change-name> — Assess and set verification mode based on metrics
|
|
13
|
+
# task-checkoff <file> <task-text> — Verify one unique task is checked
|
|
13
14
|
#
|
|
14
15
|
# Workflows: full, hotfix, tweak
|
|
15
16
|
# Phases for check: open, design, build, verify, archive
|
|
@@ -65,6 +66,26 @@ validate_enum() {
|
|
|
65
66
|
exit 1
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
validate_path_field() {
|
|
70
|
+
local value="$1"
|
|
71
|
+
local field="$2"
|
|
72
|
+
# null and empty are acceptable (means "not set")
|
|
73
|
+
if [ -z "$value" ] || [ "$value" = "null" ]; then
|
|
74
|
+
return 0
|
|
75
|
+
fi
|
|
76
|
+
# Reject absolute paths and home-directory references
|
|
77
|
+
case "$value" in
|
|
78
|
+
/*|~*|[A-Za-z]:*|\\*)
|
|
79
|
+
red "ERROR: $field must be a relative path within the repo: '$value'" >&2
|
|
80
|
+
exit 1
|
|
81
|
+
;;
|
|
82
|
+
esac
|
|
83
|
+
if [[ "$value" =~ \.\. ]]; then
|
|
84
|
+
red "ERROR: $field cannot contain '..' (path traversal not allowed): '$value'" >&2
|
|
85
|
+
exit 1
|
|
86
|
+
fi
|
|
87
|
+
}
|
|
88
|
+
|
|
68
89
|
# --- Helper functions ---
|
|
69
90
|
|
|
70
91
|
yaml_field() {
|
|
@@ -126,9 +147,17 @@ replace_yaml_field() {
|
|
|
126
147
|
local tmp_file
|
|
127
148
|
|
|
128
149
|
tmp_file=$(mktemp)
|
|
150
|
+
chmod 600 "$tmp_file"
|
|
151
|
+
# Replace the target field, then deduplicate all fields keeping only the
|
|
152
|
+
# last occurrence of each key. Prevents stale earlier values from
|
|
153
|
+
# persisting when a field is set multiple times.
|
|
129
154
|
awk -v field="$field" -v value="$value" '
|
|
130
|
-
index($0, field ":") == 1 {
|
|
131
|
-
{
|
|
155
|
+
index($0, field ":") == 1 { $0 = field ": " value }
|
|
156
|
+
{ buf[NR] = $0; keys[NR] = $0; sub(/:.*$/, "", keys[NR]); n = NR }
|
|
157
|
+
END {
|
|
158
|
+
for (i = 1; i <= n; i++) last[keys[i]] = i
|
|
159
|
+
for (i = 1; i <= n; i++) if (last[keys[i]] == i) print buf[i]
|
|
160
|
+
}
|
|
132
161
|
' "$yaml_file" > "$tmp_file"
|
|
133
162
|
mv "$tmp_file" "$yaml_file"
|
|
134
163
|
}
|
|
@@ -155,6 +184,57 @@ yaml_file_for() {
|
|
|
155
184
|
echo "$change_dir/.comet.yaml"
|
|
156
185
|
}
|
|
157
186
|
|
|
187
|
+
project_context_compression() {
|
|
188
|
+
local value="off"
|
|
189
|
+
local source="default"
|
|
190
|
+
if [ -n "${COMET_CONTEXT_COMPRESSION:-}" ]; then
|
|
191
|
+
value="$COMET_CONTEXT_COMPRESSION"
|
|
192
|
+
source="COMET_CONTEXT_COMPRESSION"
|
|
193
|
+
elif [ -f ".comet/config.yaml" ]; then
|
|
194
|
+
value=$(yaml_field "context_compression" ".comet/config.yaml")
|
|
195
|
+
value="${value:-off}"
|
|
196
|
+
source=".comet/config.yaml"
|
|
197
|
+
fi
|
|
198
|
+
|
|
199
|
+
case "$value" in
|
|
200
|
+
off|beta)
|
|
201
|
+
printf '%s\n' "$value"
|
|
202
|
+
;;
|
|
203
|
+
*)
|
|
204
|
+
red "ERROR: Invalid context_compression from ${source}: '$value'" >&2
|
|
205
|
+
red "Valid values: off, beta" >&2
|
|
206
|
+
exit 1
|
|
207
|
+
;;
|
|
208
|
+
esac
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
project_auto_transition_default() {
|
|
212
|
+
local value="true"
|
|
213
|
+
local source="default"
|
|
214
|
+
if [ -n "${COMET_AUTO_TRANSITION:-}" ]; then
|
|
215
|
+
value="$COMET_AUTO_TRANSITION"
|
|
216
|
+
source="COMET_AUTO_TRANSITION"
|
|
217
|
+
elif [ -f ".comet/config.yaml" ]; then
|
|
218
|
+
local raw
|
|
219
|
+
raw=$(yaml_field "auto_transition" ".comet/config.yaml" 2>/dev/null || true)
|
|
220
|
+
if [ -n "$raw" ]; then
|
|
221
|
+
value="$raw"
|
|
222
|
+
source=".comet/config.yaml"
|
|
223
|
+
fi
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
case "$value" in
|
|
227
|
+
true|false)
|
|
228
|
+
printf '%s\n' "$value"
|
|
229
|
+
;;
|
|
230
|
+
*)
|
|
231
|
+
red "ERROR: Invalid auto_transition from ${source}: '$value'" >&2
|
|
232
|
+
red "Valid values: true, false" >&2
|
|
233
|
+
exit 1
|
|
234
|
+
;;
|
|
235
|
+
esac
|
|
236
|
+
}
|
|
237
|
+
|
|
158
238
|
# --- Subcommands ---
|
|
159
239
|
|
|
160
240
|
cmd_init() {
|
|
@@ -178,17 +258,21 @@ cmd_init() {
|
|
|
178
258
|
mkdir -p "$change_dir"
|
|
179
259
|
|
|
180
260
|
# Set workflow-appropriate defaults
|
|
181
|
-
local phase build_mode isolation verify_mode
|
|
261
|
+
local phase build_mode isolation verify_mode context_compression auto_transition
|
|
182
262
|
phase="open"
|
|
263
|
+
context_compression=$(project_context_compression)
|
|
264
|
+
auto_transition="$(project_auto_transition_default)"
|
|
183
265
|
|
|
184
266
|
case "$workflow" in
|
|
185
267
|
full)
|
|
186
268
|
build_mode="null"
|
|
269
|
+
tdd_mode="null"
|
|
187
270
|
isolation="null"
|
|
188
271
|
verify_mode="null"
|
|
189
272
|
;;
|
|
190
273
|
hotfix|tweak)
|
|
191
274
|
build_mode="direct"
|
|
275
|
+
tdd_mode="direct"
|
|
192
276
|
isolation="branch"
|
|
193
277
|
verify_mode="light"
|
|
194
278
|
;;
|
|
@@ -204,17 +288,21 @@ cmd_init() {
|
|
|
204
288
|
cat > "$yaml_file" <<EOF
|
|
205
289
|
workflow: $workflow
|
|
206
290
|
phase: $phase
|
|
291
|
+
context_compression: $context_compression
|
|
207
292
|
build_mode: $build_mode
|
|
208
293
|
build_pause: null
|
|
294
|
+
subagent_dispatch: null
|
|
295
|
+
tdd_mode: $tdd_mode
|
|
209
296
|
isolation: $isolation
|
|
210
297
|
verify_mode: $verify_mode
|
|
298
|
+
auto_transition: $auto_transition
|
|
211
299
|
base_ref: $base_ref
|
|
212
300
|
design_doc: null
|
|
213
301
|
plan: null
|
|
214
302
|
verify_result: pending
|
|
215
303
|
verification_report: null
|
|
216
304
|
branch_status: pending
|
|
217
|
-
created_at: $(date +%Y-%m-%d)
|
|
305
|
+
created_at: $(date -u +%Y-%m-%d)
|
|
218
306
|
verified_at: null
|
|
219
307
|
archived: false
|
|
220
308
|
EOF
|
|
@@ -240,6 +328,9 @@ cmd_get() {
|
|
|
240
328
|
# Read and output the field value
|
|
241
329
|
local value
|
|
242
330
|
value=$(yaml_field "$field" "$yaml_file")
|
|
331
|
+
if [ "$field" = "auto_transition" ] && { [ -z "$value" ] || [ "$value" = "null" ]; }; then
|
|
332
|
+
value="$(project_auto_transition_default)"
|
|
333
|
+
fi
|
|
243
334
|
echo "${value:-}"
|
|
244
335
|
}
|
|
245
336
|
|
|
@@ -265,14 +356,14 @@ cmd_set() {
|
|
|
265
356
|
yellow "WARNING: Setting 'phase' directly bypasses state machine constraints." >&2
|
|
266
357
|
yellow " Consider using: comet-state.sh transition <change-name> <event>" >&2
|
|
267
358
|
;;
|
|
268
|
-
workflow|build_mode|build_pause|isolation|verify_mode|verify_result|verification_report|branch_status|archived|design_doc|plan|verified_at|created_at|direct_override|build_command|verify_command|handoff_context|handoff_hash|base_ref)
|
|
359
|
+
workflow|context_compression|build_mode|build_pause|subagent_dispatch|tdd_mode|isolation|verify_mode|auto_transition|verify_result|verification_report|branch_status|archived|design_doc|plan|verified_at|created_at|direct_override|build_command|verify_command|handoff_context|handoff_hash|base_ref)
|
|
269
360
|
# Valid field
|
|
270
361
|
;;
|
|
271
362
|
*)
|
|
272
363
|
red "ERROR: Unknown field: '$field'" >&2
|
|
273
364
|
red "Valid fields:" >&2
|
|
274
|
-
red " workflow, phase, design_doc, plan, build_mode, build_pause, isolation," >&2
|
|
275
|
-
red " verify_mode, verify_result, verification_report, branch_status," >&2
|
|
365
|
+
red " workflow, phase, context_compression, design_doc, plan, build_mode, build_pause, subagent_dispatch, tdd_mode, isolation," >&2
|
|
366
|
+
red " verify_mode, auto_transition, verify_result, verification_report, branch_status," >&2
|
|
276
367
|
red " verified_at, created_at, archived, base_ref, direct_override," >&2
|
|
277
368
|
red " build_command, verify_command, handoff_context, handoff_hash" >&2
|
|
278
369
|
exit 1
|
|
@@ -284,6 +375,9 @@ cmd_set() {
|
|
|
284
375
|
workflow)
|
|
285
376
|
validate_enum "$value" "full" "hotfix" "tweak"
|
|
286
377
|
;;
|
|
378
|
+
context_compression)
|
|
379
|
+
validate_enum "$value" "off" "beta"
|
|
380
|
+
;;
|
|
287
381
|
phase)
|
|
288
382
|
validate_enum "$value" "open" "design" "build" "verify" "archive"
|
|
289
383
|
;;
|
|
@@ -293,12 +387,21 @@ cmd_set() {
|
|
|
293
387
|
build_pause)
|
|
294
388
|
validate_enum "$value" "null" "plan-ready"
|
|
295
389
|
;;
|
|
390
|
+
subagent_dispatch)
|
|
391
|
+
validate_enum "$value" "null" "confirmed"
|
|
392
|
+
;;
|
|
393
|
+
tdd_mode)
|
|
394
|
+
validate_enum "$value" "tdd" "direct"
|
|
395
|
+
;;
|
|
296
396
|
isolation)
|
|
297
397
|
validate_enum "$value" "branch" "worktree"
|
|
298
398
|
;;
|
|
299
399
|
verify_mode)
|
|
300
400
|
validate_enum "$value" "light" "full"
|
|
301
401
|
;;
|
|
402
|
+
auto_transition)
|
|
403
|
+
validate_enum "$value" "true" "false"
|
|
404
|
+
;;
|
|
302
405
|
verify_result)
|
|
303
406
|
validate_enum "$value" "pending" "pass" "fail"
|
|
304
407
|
;;
|
|
@@ -311,8 +414,11 @@ cmd_set() {
|
|
|
311
414
|
direct_override)
|
|
312
415
|
validate_enum "$value" "true" "false"
|
|
313
416
|
;;
|
|
314
|
-
design_doc|plan|verification_report|
|
|
315
|
-
|
|
417
|
+
design_doc|plan|verification_report|handoff_context|handoff_hash)
|
|
418
|
+
validate_path_field "$value" "$field"
|
|
419
|
+
;;
|
|
420
|
+
verified_at|created_at|build_command|verify_command)
|
|
421
|
+
# No validation for date fields or project command strings
|
|
316
422
|
;;
|
|
317
423
|
esac
|
|
318
424
|
|
|
@@ -357,11 +463,13 @@ require_verification_evidence() {
|
|
|
357
463
|
|
|
358
464
|
require_build_decisions() {
|
|
359
465
|
local change_name="$1"
|
|
360
|
-
local workflow build_mode isolation direct_override
|
|
466
|
+
local workflow build_mode isolation direct_override subagent_dispatch tdd_mode
|
|
361
467
|
workflow=$(cmd_get "$change_name" "workflow")
|
|
362
468
|
build_mode=$(cmd_get "$change_name" "build_mode")
|
|
363
469
|
isolation=$(cmd_get "$change_name" "isolation")
|
|
364
470
|
direct_override=$(cmd_get "$change_name" "direct_override" 2>/dev/null || true)
|
|
471
|
+
subagent_dispatch=$(cmd_get "$change_name" "subagent_dispatch" 2>/dev/null || true)
|
|
472
|
+
tdd_mode=$(cmd_get "$change_name" "tdd_mode" 2>/dev/null || true)
|
|
365
473
|
|
|
366
474
|
case "$isolation" in
|
|
367
475
|
branch|worktree) ;;
|
|
@@ -383,6 +491,16 @@ require_build_decisions() {
|
|
|
383
491
|
red "ERROR: Cannot transition '$change_name': build_mode=direct is only allowed for hotfix/tweak unless direct_override=true" >&2
|
|
384
492
|
exit 1
|
|
385
493
|
fi
|
|
494
|
+
|
|
495
|
+
if [ "$build_mode" = "subagent-driven-development" ] && [ "$subagent_dispatch" != "confirmed" ]; then
|
|
496
|
+
red "ERROR: Cannot transition '$change_name': subagent_dispatch must be confirmed before using build_mode=subagent-driven-development" >&2
|
|
497
|
+
exit 1
|
|
498
|
+
fi
|
|
499
|
+
|
|
500
|
+
if [ "$workflow" = "full" ] && { [ "$tdd_mode" = "null" ] || [ -z "$tdd_mode" ]; }; then
|
|
501
|
+
red "ERROR: Cannot transition '$change_name': tdd_mode must be selected before leaving build (full workflow)" >&2
|
|
502
|
+
exit 1
|
|
503
|
+
fi
|
|
386
504
|
}
|
|
387
505
|
|
|
388
506
|
cmd_transition() {
|
|
@@ -390,7 +508,7 @@ cmd_transition() {
|
|
|
390
508
|
local event="$2"
|
|
391
509
|
|
|
392
510
|
validate_change_name "$change_name"
|
|
393
|
-
validate_enum "$event" "open-complete" "design-complete" "build-complete" "verify-pass" "verify-fail" "archived"
|
|
511
|
+
validate_enum "$event" "open-complete" "design-complete" "build-complete" "verify-pass" "verify-fail" "archive-reopen" "archived"
|
|
394
512
|
|
|
395
513
|
case "$event" in
|
|
396
514
|
open-complete)
|
|
@@ -410,23 +528,41 @@ cmd_transition() {
|
|
|
410
528
|
build-complete)
|
|
411
529
|
require_phase "$change_name" "build"
|
|
412
530
|
require_build_decisions "$change_name"
|
|
531
|
+
local current_verify_result
|
|
532
|
+
current_verify_result=$(cmd_get "$change_name" "verify_result")
|
|
413
533
|
cmd_set "$change_name" phase verify
|
|
414
534
|
cmd_set "$change_name" verify_result pending
|
|
415
|
-
|
|
416
|
-
|
|
535
|
+
# Preserve verification evidence on re-verify (verify-fail → build → build-complete)
|
|
536
|
+
# so the fix can reference the original failure report
|
|
537
|
+
if [ "$current_verify_result" != "fail" ]; then
|
|
538
|
+
cmd_set "$change_name" verification_report null
|
|
539
|
+
cmd_set "$change_name" branch_status pending
|
|
540
|
+
fi
|
|
417
541
|
;;
|
|
418
542
|
verify-pass)
|
|
419
543
|
require_phase "$change_name" "verify"
|
|
420
544
|
require_verification_evidence "$change_name"
|
|
421
545
|
cmd_set "$change_name" verify_result pass
|
|
422
546
|
cmd_set "$change_name" phase archive
|
|
423
|
-
cmd_set "$change_name" verified_at "$(date +%Y-%m-%d)"
|
|
547
|
+
cmd_set "$change_name" verified_at "$(date -u +%Y-%m-%d)"
|
|
424
548
|
;;
|
|
425
549
|
verify-fail)
|
|
426
550
|
require_phase "$change_name" "verify"
|
|
427
551
|
cmd_set "$change_name" verify_result fail
|
|
428
552
|
cmd_set "$change_name" phase build
|
|
429
|
-
|
|
553
|
+
# Preserve branch_status so re-verify doesn't require re-handling branches
|
|
554
|
+
;;
|
|
555
|
+
archive-reopen)
|
|
556
|
+
require_phase "$change_name" "archive"
|
|
557
|
+
local archived
|
|
558
|
+
archived=$(cmd_get "$change_name" "archived")
|
|
559
|
+
if [ "$archived" = "true" ]; then
|
|
560
|
+
red "ERROR: Cannot transition '$change_name': already archived" >&2
|
|
561
|
+
exit 1
|
|
562
|
+
fi
|
|
563
|
+
cmd_set "$change_name" verify_result pending
|
|
564
|
+
cmd_set "$change_name" phase verify
|
|
565
|
+
cmd_set "$change_name" verified_at null
|
|
430
566
|
;;
|
|
431
567
|
archived)
|
|
432
568
|
require_phase "$change_name" "archive"
|
|
@@ -636,7 +772,7 @@ cmd_recover() {
|
|
|
636
772
|
|
|
637
773
|
# Read all relevant fields
|
|
638
774
|
local design_doc plan verify_result verify_mode verification_report
|
|
639
|
-
local branch_status handoff_context handoff_hash isolation build_mode build_pause direct_override
|
|
775
|
+
local branch_status handoff_context handoff_hash isolation build_mode build_pause subagent_dispatch tdd_mode direct_override
|
|
640
776
|
design_doc=$(cmd_get "$change_name" "design_doc")
|
|
641
777
|
plan=$(cmd_get "$change_name" "plan")
|
|
642
778
|
verify_result=$(cmd_get "$change_name" "verify_result")
|
|
@@ -648,6 +784,8 @@ cmd_recover() {
|
|
|
648
784
|
isolation=$(cmd_get "$change_name" "isolation")
|
|
649
785
|
build_mode=$(cmd_get "$change_name" "build_mode")
|
|
650
786
|
build_pause=$(cmd_get "$change_name" "build_pause" 2>/dev/null || true)
|
|
787
|
+
subagent_dispatch=$(cmd_get "$change_name" "subagent_dispatch" 2>/dev/null || true)
|
|
788
|
+
tdd_mode=$(cmd_get "$change_name" "tdd_mode" 2>/dev/null || true)
|
|
651
789
|
direct_override=$(cmd_get "$change_name" "direct_override" 2>/dev/null || true)
|
|
652
790
|
|
|
653
791
|
echo "State fields:"
|
|
@@ -656,15 +794,23 @@ cmd_recover() {
|
|
|
656
794
|
case "$phase" in
|
|
657
795
|
open)
|
|
658
796
|
echo " Artifacts:"
|
|
797
|
+
local artifacts_done=0
|
|
659
798
|
for f in proposal.md design.md tasks.md; do
|
|
660
799
|
if file_nonempty "$change_dir/$f"; then
|
|
661
800
|
echo " - ${f}: DONE"
|
|
801
|
+
artifacts_done=$((artifacts_done + 1))
|
|
662
802
|
else
|
|
663
803
|
echo " - ${f}: PENDING"
|
|
664
804
|
fi
|
|
665
805
|
done
|
|
666
806
|
echo ""
|
|
667
|
-
|
|
807
|
+
if [ "$artifacts_done" -eq 3 ]; then
|
|
808
|
+
echo "Recovery action: All artifacts complete. Run /comet-open user confirmation, then guard to transition."
|
|
809
|
+
elif [ "$artifacts_done" -eq 0 ]; then
|
|
810
|
+
echo "Recovery action: No artifacts created yet. Start from /comet-open Step 1 (explore and clarify)."
|
|
811
|
+
else
|
|
812
|
+
echo "Recovery action: Some artifacts incomplete. Resume /comet-open from the first missing artifact."
|
|
813
|
+
fi
|
|
668
814
|
;;
|
|
669
815
|
design)
|
|
670
816
|
echo " Artifacts:"
|
|
@@ -694,6 +840,10 @@ cmd_recover() {
|
|
|
694
840
|
field_status "isolation" "$isolation"
|
|
695
841
|
field_status "build_mode" "$build_mode"
|
|
696
842
|
field_status "build_pause" "$build_pause"
|
|
843
|
+
field_status "tdd_mode" "$tdd_mode"
|
|
844
|
+
if [ "$build_mode" = "subagent-driven-development" ] || { [ -n "$subagent_dispatch" ] && [ "$subagent_dispatch" != "null" ]; }; then
|
|
845
|
+
field_status "subagent_dispatch" "$subagent_dispatch"
|
|
846
|
+
fi
|
|
697
847
|
if [ "$build_mode" = "direct" ] && [ "$workflow" != "hotfix" ] && [ "$workflow" != "tweak" ]; then
|
|
698
848
|
field_status "direct_override" "$direct_override"
|
|
699
849
|
fi
|
|
@@ -704,29 +854,72 @@ cmd_recover() {
|
|
|
704
854
|
# Count completed vs pending tasks
|
|
705
855
|
local tasks_file="$change_dir/tasks.md"
|
|
706
856
|
local total=0 done=0 pending=0
|
|
857
|
+
local plan_total=0 plan_done=0 plan_pending=0
|
|
707
858
|
if [ -f "$tasks_file" ]; then
|
|
708
|
-
total=$(grep -c '
|
|
709
|
-
done=$(grep -c '
|
|
859
|
+
total=$(grep -c '^[[:space:]]*- \[' "$tasks_file" 2>/dev/null || true)
|
|
860
|
+
done=$(grep -c '^[[:space:]]*- \[x\]' "$tasks_file" 2>/dev/null || true)
|
|
861
|
+
total="${total:-0}"
|
|
862
|
+
done="${done:-0}"
|
|
710
863
|
pending=$((total - done))
|
|
711
864
|
echo " Tasks: ${done}/${total} done, ${pending} pending"
|
|
712
865
|
else
|
|
713
866
|
echo " Tasks: tasks.md MISSING"
|
|
714
867
|
fi
|
|
868
|
+
if [ -n "$plan" ] && [ "$plan" != "null" ] && [ -f "$plan" ]; then
|
|
869
|
+
plan_total=$(grep -c '^[[:space:]]*- \[' "$plan" 2>/dev/null || true)
|
|
870
|
+
plan_done=$(grep -c '^[[:space:]]*- \[x\]' "$plan" 2>/dev/null || true)
|
|
871
|
+
plan_total="${plan_total:-0}"
|
|
872
|
+
plan_done="${plan_done:-0}"
|
|
873
|
+
plan_pending=$((plan_total - plan_done))
|
|
874
|
+
if [ "$plan_total" -gt 0 ]; then
|
|
875
|
+
echo " Plan tasks: ${plan_done}/${plan_total} done, ${plan_pending} pending"
|
|
876
|
+
fi
|
|
877
|
+
fi
|
|
715
878
|
echo ""
|
|
716
879
|
if [ "$build_pause" = "plan-ready" ] && [ -n "$plan" ] && [ "$plan" != "null" ] && [ -f "$plan" ] && { [ "$isolation" = "null" ] || [ -z "$isolation" ] || [ "$build_mode" = "null" ] || [ -z "$build_mode" ]; }; then
|
|
717
880
|
echo "Recovery action: Plan-ready pause detected. Ask the user whether to continue, then choose isolation and build mode without regenerating the plan."
|
|
718
881
|
elif [ "$build_pause" = "plan-ready" ] && { [ -z "$plan" ] || [ "$plan" = "null" ] || [ ! -f "$plan" ]; }; then
|
|
719
882
|
echo "Recovery action: Plan-ready pause is recorded, but the plan file is missing. Restore the plan file or rerun writing-plans before choosing execution."
|
|
720
883
|
elif [ "$build_pause" = "plan-ready" ]; then
|
|
721
|
-
|
|
884
|
+
if [ "$build_mode" = "subagent-driven-development" ] && { [ "$pending" -gt 0 ] || [ "$plan_pending" -gt 0 ]; }; then
|
|
885
|
+
if [ "$subagent_dispatch" = "confirmed" ]; then
|
|
886
|
+
echo "Recovery action: Plan-ready pause is stale because build decisions are already selected. Clear build_pause to null, then inspect the first unchecked task (OpenSpec or plan additions) against recent git history/diff. If implemented, check it off; otherwise dispatch a real background subagent. Do not execute the pending task directly in the main window."
|
|
887
|
+
else
|
|
888
|
+
echo "Recovery action: Plan-ready pause is stale and subagent dispatch is not confirmed. Confirm a real background subagent/Task/multi-agent dispatcher and set subagent_dispatch to confirmed, or set build_mode to executing-plans before continuing."
|
|
889
|
+
fi
|
|
890
|
+
elif [ "$pending" -gt 0 ] || [ "$plan_pending" -gt 0 ]; then
|
|
891
|
+
echo "Recovery action: Plan-ready pause is stale because build decisions are already selected. Clear build_pause to null, then continue from the first unchecked task."
|
|
892
|
+
else
|
|
893
|
+
echo "Recovery action: Plan-ready pause is stale and all tasks are done. Clear build_pause to null, then run guard to transition to verify."
|
|
894
|
+
fi
|
|
722
895
|
elif [ "$isolation" = "null" ] || [ -z "$isolation" ]; then
|
|
723
|
-
echo "Recovery action: Isolation not selected. Use
|
|
896
|
+
echo "Recovery action: Isolation not selected. Use the current platform's user confirmation mechanism to ask user for branch/worktree choice."
|
|
724
897
|
elif [ "$build_mode" = "null" ] || [ -z "$build_mode" ]; then
|
|
725
|
-
echo "Recovery action: Build mode not selected. Use
|
|
898
|
+
echo "Recovery action: Build mode not selected. Use the current platform's user confirmation mechanism to ask user for execution method."
|
|
899
|
+
elif [ -z "$tdd_mode" ] || [ "$tdd_mode" = "null" ]; then
|
|
900
|
+
echo "Recovery action: TDD mode not selected. Use the current platform's user confirmation mechanism to ask user for tdd or direct."
|
|
726
901
|
elif [ ! -f "$tasks_file" ]; then
|
|
727
902
|
echo "Recovery action: tasks.md missing. Verify change directory integrity."
|
|
728
903
|
elif [ "$pending" -gt 0 ]; then
|
|
729
|
-
|
|
904
|
+
if [ "$build_mode" = "subagent-driven-development" ]; then
|
|
905
|
+
if [ "$subagent_dispatch" = "confirmed" ]; then
|
|
906
|
+
echo "Recovery action: Read tasks.md and the Superpowers plan (which may include additions beyond OpenSpec), then inspect the first unchecked task against recent git history/diff. If implemented, check it off; otherwise dispatch a real background subagent. Do not execute the pending task directly in the main window."
|
|
907
|
+
else
|
|
908
|
+
echo "Recovery action: Subagent dispatch is not confirmed. Confirm a real background subagent/Task/multi-agent dispatcher and set subagent_dispatch to confirmed, or set build_mode to executing-plans before continuing."
|
|
909
|
+
fi
|
|
910
|
+
else
|
|
911
|
+
echo "Recovery action: Read tasks.md and continue from first unchecked task."
|
|
912
|
+
fi
|
|
913
|
+
elif [ "$plan_pending" -gt 0 ]; then
|
|
914
|
+
if [ "$build_mode" = "subagent-driven-development" ]; then
|
|
915
|
+
if [ "$subagent_dispatch" = "confirmed" ]; then
|
|
916
|
+
echo "Recovery action: Read the Superpowers plan, then inspect the first unchecked Superpowers plan task against recent git history/diff. If implemented, check it off; otherwise dispatch a real background subagent. Do not execute the pending task directly in the main window."
|
|
917
|
+
else
|
|
918
|
+
echo "Recovery action: Subagent dispatch is not confirmed. Confirm a real background subagent/Task/multi-agent dispatcher and set subagent_dispatch to confirmed, or set build_mode to executing-plans before continuing."
|
|
919
|
+
fi
|
|
920
|
+
else
|
|
921
|
+
echo "Recovery action: Read the Superpowers plan and continue from the first unchecked plan task."
|
|
922
|
+
fi
|
|
730
923
|
else
|
|
731
924
|
echo "Recovery action: All tasks done. Run guard to transition to verify."
|
|
732
925
|
fi
|
|
@@ -799,7 +992,7 @@ cmd_scale() {
|
|
|
799
992
|
local plan_file base_ref=""
|
|
800
993
|
plan_file=$(cmd_get "$change_name" "plan" 2>/dev/null || true)
|
|
801
994
|
if [ -n "$plan_file" ] && [ "$plan_file" != "null" ] && [ -f "$plan_file" ]; then
|
|
802
|
-
base_ref=$(grep '^base-ref:' "$plan_file" 2>/dev/null | head -1 | sed 's/^base-ref: *//')
|
|
995
|
+
base_ref=$(grep '^base-ref:' "$plan_file" 2>/dev/null | head -1 | sed 's/^base-ref: *//' || true)
|
|
803
996
|
fi
|
|
804
997
|
# Fallback to base_ref stored in .comet.yaml (set during init)
|
|
805
998
|
if [ -z "$base_ref" ] || [ "$base_ref" = "null" ]; then
|
|
@@ -832,6 +1025,134 @@ cmd_scale() {
|
|
|
832
1025
|
green "[SCALE] verify_mode=$result"
|
|
833
1026
|
}
|
|
834
1027
|
|
|
1028
|
+
cmd_task_checkoff() {
|
|
1029
|
+
local task_file="$1"
|
|
1030
|
+
local task_text="$2"
|
|
1031
|
+
|
|
1032
|
+
validate_path_field "$task_file" "task file"
|
|
1033
|
+
|
|
1034
|
+
if [ -z "$task_text" ]; then
|
|
1035
|
+
red "ERROR: Task text cannot be empty" >&2
|
|
1036
|
+
exit 1
|
|
1037
|
+
fi
|
|
1038
|
+
|
|
1039
|
+
if [ ! -f "$task_file" ]; then
|
|
1040
|
+
red "ERROR: Task file not found: $task_file" >&2
|
|
1041
|
+
exit 1
|
|
1042
|
+
fi
|
|
1043
|
+
|
|
1044
|
+
local counts
|
|
1045
|
+
counts=$(TASK_TEXT="$task_text" awk '
|
|
1046
|
+
BEGIN {
|
|
1047
|
+
task = ENVIRON["TASK_TEXT"]
|
|
1048
|
+
}
|
|
1049
|
+
{
|
|
1050
|
+
sub(/\r$/, "")
|
|
1051
|
+
if ($0 == "- [ ] " task || $0 == "- [x] " task || $0 == "- [X] " task) {
|
|
1052
|
+
total++
|
|
1053
|
+
}
|
|
1054
|
+
if ($0 == "- [x] " task || $0 == "- [X] " task) {
|
|
1055
|
+
checked++
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
END {
|
|
1059
|
+
printf "%d %d\n", total + 0, checked + 0
|
|
1060
|
+
}
|
|
1061
|
+
' "$task_file")
|
|
1062
|
+
|
|
1063
|
+
local total="${counts%% *}"
|
|
1064
|
+
local checked="${counts##* }"
|
|
1065
|
+
|
|
1066
|
+
if [ "$total" -ne 1 ]; then
|
|
1067
|
+
red "ERROR: task text must appear exactly once in $task_file (found $total): $task_text" >&2
|
|
1068
|
+
exit 1
|
|
1069
|
+
fi
|
|
1070
|
+
|
|
1071
|
+
if [ "$checked" -ne 1 ]; then
|
|
1072
|
+
red "ERROR: task is not checked in $task_file: $task_text" >&2
|
|
1073
|
+
exit 1
|
|
1074
|
+
fi
|
|
1075
|
+
|
|
1076
|
+
echo "TASK_CHECKOFF: PASS"
|
|
1077
|
+
echo "FILE: $task_file"
|
|
1078
|
+
echo "TASK: $task_text"
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
# Resolve the next workflow step after a guard --apply phase advance.
|
|
1082
|
+
# Reads the (already advanced) phase, workflow, and auto_transition, then emits
|
|
1083
|
+
# a deterministic next-step contract so skills don't hardcode the next skill name.
|
|
1084
|
+
#
|
|
1085
|
+
# Output contract (stdout):
|
|
1086
|
+
# NEXT: auto|manual|done
|
|
1087
|
+
# SKILL: <skill-name> (omitted when NEXT=done)
|
|
1088
|
+
# HINT: <message> (only when NEXT=manual)
|
|
1089
|
+
cmd_next() {
|
|
1090
|
+
local change_name="$1"
|
|
1091
|
+
validate_change_name "$change_name"
|
|
1092
|
+
|
|
1093
|
+
local change_dir="openspec/changes/$change_name"
|
|
1094
|
+
local yaml_file="$change_dir/.comet.yaml"
|
|
1095
|
+
if [ ! -f "$yaml_file" ]; then
|
|
1096
|
+
red "ERROR: .comet.yaml not found at $yaml_file" >&2
|
|
1097
|
+
exit 1
|
|
1098
|
+
fi
|
|
1099
|
+
|
|
1100
|
+
local phase workflow auto_transition archived
|
|
1101
|
+
phase=$(cmd_get "$change_name" "phase" 2>/dev/null || true)
|
|
1102
|
+
workflow=$(cmd_get "$change_name" "workflow" 2>/dev/null || true)
|
|
1103
|
+
auto_transition=$(cmd_get "$change_name" "auto_transition" 2>/dev/null || true)
|
|
1104
|
+
archived=$(cmd_get "$change_name" "archived" 2>/dev/null || true)
|
|
1105
|
+
|
|
1106
|
+
# Change-level auto_transition overrides project-level; fall back to project default
|
|
1107
|
+
if [ -z "$auto_transition" ] || [ "$auto_transition" = "null" ]; then
|
|
1108
|
+
auto_transition="$(project_auto_transition_default)"
|
|
1109
|
+
fi
|
|
1110
|
+
|
|
1111
|
+
# Terminal state: archived change has no next step.
|
|
1112
|
+
if [ "$archived" = "true" ]; then
|
|
1113
|
+
echo "NEXT: done"
|
|
1114
|
+
return 0
|
|
1115
|
+
fi
|
|
1116
|
+
|
|
1117
|
+
# Map the current (post-advance) phase to the skill that owns it.
|
|
1118
|
+
local skill=""
|
|
1119
|
+
case "$phase" in
|
|
1120
|
+
open)
|
|
1121
|
+
skill="comet-open"
|
|
1122
|
+
;;
|
|
1123
|
+
design)
|
|
1124
|
+
skill="comet-design"
|
|
1125
|
+
;;
|
|
1126
|
+
build)
|
|
1127
|
+
case "$workflow" in
|
|
1128
|
+
hotfix) skill="comet-hotfix" ;;
|
|
1129
|
+
tweak) skill="comet-tweak" ;;
|
|
1130
|
+
*) skill="comet-build" ;;
|
|
1131
|
+
esac
|
|
1132
|
+
;;
|
|
1133
|
+
verify)
|
|
1134
|
+
skill="comet-verify"
|
|
1135
|
+
;;
|
|
1136
|
+
archive)
|
|
1137
|
+
skill="comet-archive"
|
|
1138
|
+
;;
|
|
1139
|
+
*)
|
|
1140
|
+
red "ERROR: Cannot resolve next step for '$change_name': unknown phase '${phase:-null}'" >&2
|
|
1141
|
+
exit 1
|
|
1142
|
+
;;
|
|
1143
|
+
esac
|
|
1144
|
+
|
|
1145
|
+
# auto_transition=false pauses the next skill invocation only; phase is already advanced.
|
|
1146
|
+
if [ "$auto_transition" = "false" ]; then
|
|
1147
|
+
echo "NEXT: manual"
|
|
1148
|
+
echo "SKILL: $skill"
|
|
1149
|
+
echo "HINT: phase is '$phase'; run /$skill manually to continue"
|
|
1150
|
+
else
|
|
1151
|
+
echo "NEXT: auto"
|
|
1152
|
+
echo "SKILL: $skill"
|
|
1153
|
+
fi
|
|
1154
|
+
}
|
|
1155
|
+
|
|
835
1156
|
# --- Main ---
|
|
836
1157
|
|
|
837
1158
|
SUBCOMMAND="${1:-}"
|
|
@@ -863,7 +1184,7 @@ case "$SUBCOMMAND" in
|
|
|
863
1184
|
transition)
|
|
864
1185
|
if [ $# -lt 2 ]; then
|
|
865
1186
|
red "Usage: comet-state.sh transition <change-name> <event>" >&2
|
|
866
|
-
red "Events: open-complete, design-complete, build-complete, verify-pass, verify-fail, archived" >&2
|
|
1187
|
+
red "Events: open-complete, design-complete, build-complete, verify-pass, verify-fail, archive-reopen, archived" >&2
|
|
867
1188
|
exit 1
|
|
868
1189
|
fi
|
|
869
1190
|
cmd_transition "$@"
|
|
@@ -888,6 +1209,20 @@ case "$SUBCOMMAND" in
|
|
|
888
1209
|
fi
|
|
889
1210
|
cmd_scale "$@"
|
|
890
1211
|
;;
|
|
1212
|
+
task-checkoff)
|
|
1213
|
+
if [ $# -lt 2 ]; then
|
|
1214
|
+
red "Usage: comet-state.sh task-checkoff <file> <task-text>" >&2
|
|
1215
|
+
exit 1
|
|
1216
|
+
fi
|
|
1217
|
+
cmd_task_checkoff "$@"
|
|
1218
|
+
;;
|
|
1219
|
+
next)
|
|
1220
|
+
if [ $# -lt 1 ]; then
|
|
1221
|
+
red "Usage: comet-state.sh next <change-name>" >&2
|
|
1222
|
+
exit 1
|
|
1223
|
+
fi
|
|
1224
|
+
cmd_next "$@"
|
|
1225
|
+
;;
|
|
891
1226
|
*)
|
|
892
1227
|
red "Unknown subcommand: $SUBCOMMAND" >&2
|
|
893
1228
|
echo "" >&2
|
|
@@ -900,6 +1235,8 @@ case "$SUBCOMMAND" in
|
|
|
900
1235
|
echo " transition <change-name> <event> — Apply a validated state transition" >&2
|
|
901
1236
|
echo " check <change-name> <phase> — Verify entry requirements for a phase" >&2
|
|
902
1237
|
echo " scale <change-name> — Assess and set verification mode based on metrics" >&2
|
|
1238
|
+
echo " task-checkoff <file> <task-text> — Verify one unique task is checked" >&2
|
|
1239
|
+
echo " next <change-name> — Resolve the next workflow step (auto/manual/done)" >&2
|
|
903
1240
|
echo "" >&2
|
|
904
1241
|
echo "Workflows: full, hotfix, tweak" >&2
|
|
905
1242
|
echo "Phases for check: open, design, build, verify, archive" >&2
|