@rpamis/comet 0.1.7 → 0.2.0
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 +45 -13
- package/assets/manifest.json +2 -0
- package/assets/skills/comet/SKILL.md +214 -219
- package/assets/skills/comet/scripts/comet-archive.sh +8 -2
- package/assets/skills/comet/scripts/comet-guard.sh +32 -22
- package/assets/skills/comet/scripts/comet-state.sh +496 -0
- package/assets/skills/comet-archive/SKILL.md +6 -19
- package/assets/skills/comet-build/SKILL.md +16 -23
- package/assets/skills/comet-design/SKILL.md +7 -23
- package/assets/skills/comet-hotfix/SKILL.md +136 -167
- package/assets/skills/comet-open/SKILL.md +9 -31
- package/assets/skills/comet-tweak/SKILL.md +122 -154
- package/assets/skills/comet-verify/SKILL.md +11 -33
- package/assets/skills-zh/comet/SKILL.md +87 -92
- package/assets/skills-zh/comet-archive/SKILL.md +63 -76
- package/assets/skills-zh/comet-build/SKILL.md +153 -160
- package/assets/skills-zh/comet-design/SKILL.md +91 -107
- package/assets/skills-zh/comet-hotfix/SKILL.md +18 -49
- package/assets/skills-zh/comet-open/SKILL.md +70 -92
- package/assets/skills-zh/comet-tweak/SKILL.md +19 -51
- package/assets/skills-zh/comet-verify/SKILL.md +114 -136
- package/dist/cli/index.js +28 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +168 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +183 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/status.d.ts +6 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +89 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/update.d.ts +8 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +47 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/core/detect.d.ts +8 -0
- package/dist/core/detect.d.ts.map +1 -0
- package/dist/core/detect.js +73 -0
- package/dist/core/detect.js.map +1 -0
- package/dist/core/openspec.d.ts +5 -0
- package/dist/core/openspec.d.ts.map +1 -0
- package/dist/core/openspec.js +58 -0
- package/dist/core/openspec.js.map +1 -0
- package/dist/core/platforms.d.ts.map +1 -1
- package/dist/core/platforms.js +6 -1
- package/dist/core/platforms.js.map +1 -1
- package/dist/core/skills.d.ts +22 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +59 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/superpowers.d.ts +5 -0
- package/dist/core/superpowers.d.ts.map +1 -0
- package/dist/core/superpowers.js +60 -0
- package/dist/core/superpowers.js.map +1 -0
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/package.json +61 -50
- package/dist/core/init.d.ts +0 -14
- package/dist/core/init.d.ts.map +0 -1
- package/dist/core/init.js +0 -492
- package/dist/core/init.js.map +0 -1
|
@@ -182,30 +182,40 @@ guard_archive() {
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
apply_state_update() {
|
|
185
|
-
local
|
|
185
|
+
local state_sh="$SCRIPT_DIR/comet-state.sh"
|
|
186
186
|
local p="$1"
|
|
187
187
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
;;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
;;
|
|
208
|
-
|
|
188
|
+
if [ -f "$state_sh" ]; then
|
|
189
|
+
case "$p" in
|
|
190
|
+
open) bash "$state_sh" set "$CHANGE" phase design ;;
|
|
191
|
+
design) bash "$state_sh" set "$CHANGE" phase build ;;
|
|
192
|
+
build)
|
|
193
|
+
bash "$state_sh" set "$CHANGE" phase verify
|
|
194
|
+
bash "$state_sh" set "$CHANGE" verify_result pending
|
|
195
|
+
;;
|
|
196
|
+
verify)
|
|
197
|
+
bash "$state_sh" set "$CHANGE" phase archive
|
|
198
|
+
bash "$state_sh" set "$CHANGE" verify_result pass
|
|
199
|
+
bash "$state_sh" set "$CHANGE" verified_at "$(date +%Y-%m-%d)"
|
|
200
|
+
;;
|
|
201
|
+
esac
|
|
202
|
+
else
|
|
203
|
+
local yaml="$CHANGE_DIR/.comet.yaml"
|
|
204
|
+
case "$p" in
|
|
205
|
+
open) sed -i 's/^phase:.*/phase: design/' "$yaml" ;;
|
|
206
|
+
design) sed -i 's/^phase:.*/phase: build/' "$yaml" ;;
|
|
207
|
+
build) sed -i 's/^phase:.*/phase: verify/' "$yaml"; sed -i 's/^verify_result:.*/verify_result: pending/' "$yaml" ;;
|
|
208
|
+
verify)
|
|
209
|
+
sed -i 's/^phase:.*/phase: archive/' "$yaml"
|
|
210
|
+
sed -i 's/^verify_result:.*/verify_result: pass/' "$yaml"
|
|
211
|
+
if ! grep -q '^verified_at:' "$yaml" 2>/dev/null; then
|
|
212
|
+
echo "verified_at: $(date +%Y-%m-%d)" >> "$yaml"
|
|
213
|
+
else
|
|
214
|
+
sed -i "s/^verified_at:.*/verified_at: $(date +%Y-%m-%d)/" "$yaml"
|
|
215
|
+
fi
|
|
216
|
+
;;
|
|
217
|
+
esac
|
|
218
|
+
fi
|
|
209
219
|
}
|
|
210
220
|
|
|
211
221
|
# --- Main ---
|
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Comet State — unified interface for .comet.yaml state management
|
|
3
|
+
# Usage: comet-state.sh <subcommand> <change-name> [args...]
|
|
4
|
+
#
|
|
5
|
+
# Subcommands:
|
|
6
|
+
# init <change-name> <workflow> — Initialize .comet.yaml with workflow defaults
|
|
7
|
+
# get <change-name> <field> — Read a field value from .comet.yaml
|
|
8
|
+
# set <change-name> <field> <val> — Update a field value
|
|
9
|
+
# check <phase> <change-name> — Verify entry requirements for a phase
|
|
10
|
+
# scale <change-name> — Assess and set verification mode based on metrics
|
|
11
|
+
#
|
|
12
|
+
# Workflows: full, hotfix, tweak
|
|
13
|
+
# Phases for check: open, design, build, verify, archive
|
|
14
|
+
|
|
15
|
+
set -euo pipefail
|
|
16
|
+
|
|
17
|
+
# --- Color output helpers ---
|
|
18
|
+
|
|
19
|
+
red() { echo -e "\033[31m$1\033[0m" >&2; }
|
|
20
|
+
green() { echo -e "\033[32m$1\033[0m" >&2; }
|
|
21
|
+
yellow() { echo -e "\033[33m$1\033[0m" >&2; }
|
|
22
|
+
|
|
23
|
+
# --- Script location ---
|
|
24
|
+
|
|
25
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
26
|
+
|
|
27
|
+
# --- Input validation ---
|
|
28
|
+
|
|
29
|
+
validate_change_name() {
|
|
30
|
+
local name="$1"
|
|
31
|
+
# Reject empty names
|
|
32
|
+
if [ -z "$name" ]; then
|
|
33
|
+
red "ERROR: Change name cannot be empty" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
# Only allow alphanumeric, hyphens, and underscores
|
|
37
|
+
if [[ ! "$name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
|
38
|
+
red "ERROR: Invalid change name: '$name'" >&2
|
|
39
|
+
red "Valid characters: a-z, A-Z, 0-9, -, _" >&2
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
# Reject path traversal attempts
|
|
43
|
+
if [[ "$name" =~ \.\. ]]; then
|
|
44
|
+
red "ERROR: Change name cannot contain '..' (path traversal not allowed)" >&2
|
|
45
|
+
exit 1
|
|
46
|
+
fi
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
validate_enum() {
|
|
50
|
+
local value="$1"
|
|
51
|
+
shift
|
|
52
|
+
local valid_values=("$@")
|
|
53
|
+
|
|
54
|
+
for valid in "${valid_values[@]}"; do
|
|
55
|
+
if [ "$value" = "$valid" ]; then
|
|
56
|
+
return 0
|
|
57
|
+
fi
|
|
58
|
+
done
|
|
59
|
+
|
|
60
|
+
red "ERROR: Invalid value: '$value'" >&2
|
|
61
|
+
red "Valid values: ${valid_values[*]}" >&2
|
|
62
|
+
exit 1
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# --- Helper functions ---
|
|
66
|
+
|
|
67
|
+
yaml_field() {
|
|
68
|
+
local field="$1"
|
|
69
|
+
local yaml_file="$2"
|
|
70
|
+
if [ -f "$yaml_file" ]; then
|
|
71
|
+
grep "^${field}:" "$yaml_file" | sed "s/^${field}: *//" | tr -d '"' | tr -d "'"
|
|
72
|
+
fi
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
file_nonempty() {
|
|
76
|
+
[ -f "$1" ] && [ -s "$1" ]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# --- Subcommands ---
|
|
80
|
+
|
|
81
|
+
cmd_init() {
|
|
82
|
+
local change_name="$1"
|
|
83
|
+
local workflow="$2"
|
|
84
|
+
|
|
85
|
+
validate_change_name "$change_name"
|
|
86
|
+
validate_enum "$workflow" "full" "hotfix" "tweak"
|
|
87
|
+
|
|
88
|
+
local change_dir="openspec/changes/$change_name"
|
|
89
|
+
local yaml_file="$change_dir/.comet.yaml"
|
|
90
|
+
|
|
91
|
+
# Check if .comet.yaml already exists
|
|
92
|
+
if [ -f "$yaml_file" ]; then
|
|
93
|
+
red "ERROR: .comet.yaml already exists at $yaml_file"
|
|
94
|
+
exit 1
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# Create change directory if it doesn't exist
|
|
98
|
+
mkdir -p "$change_dir"
|
|
99
|
+
|
|
100
|
+
# Set workflow-appropriate defaults
|
|
101
|
+
local phase build_mode isolation verify_mode
|
|
102
|
+
|
|
103
|
+
case "$workflow" in
|
|
104
|
+
full)
|
|
105
|
+
phase="design"
|
|
106
|
+
build_mode="null"
|
|
107
|
+
isolation="null"
|
|
108
|
+
verify_mode="null"
|
|
109
|
+
;;
|
|
110
|
+
hotfix|tweak)
|
|
111
|
+
phase="build"
|
|
112
|
+
build_mode="direct"
|
|
113
|
+
isolation="branch"
|
|
114
|
+
verify_mode="light"
|
|
115
|
+
;;
|
|
116
|
+
esac
|
|
117
|
+
|
|
118
|
+
# Write .comet.yaml
|
|
119
|
+
cat > "$yaml_file" <<EOF
|
|
120
|
+
workflow: $workflow
|
|
121
|
+
phase: $phase
|
|
122
|
+
build_mode: $build_mode
|
|
123
|
+
isolation: $isolation
|
|
124
|
+
verify_mode: $verify_mode
|
|
125
|
+
design_doc: null
|
|
126
|
+
plan: null
|
|
127
|
+
verify_result: pending
|
|
128
|
+
verified_at: null
|
|
129
|
+
archived: false
|
|
130
|
+
EOF
|
|
131
|
+
|
|
132
|
+
green "Initialized: $yaml_file (workflow=$workflow)"
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
cmd_get() {
|
|
136
|
+
local change_name="$1"
|
|
137
|
+
local field="$2"
|
|
138
|
+
|
|
139
|
+
validate_change_name "$change_name"
|
|
140
|
+
|
|
141
|
+
local change_dir="openspec/changes/$change_name"
|
|
142
|
+
local yaml_file="$change_dir/.comet.yaml"
|
|
143
|
+
|
|
144
|
+
# Check if .comet.yaml exists
|
|
145
|
+
if [ ! -f "$yaml_file" ]; then
|
|
146
|
+
red "ERROR: .comet.yaml not found at $yaml_file"
|
|
147
|
+
exit 1
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
# Read and output the field value
|
|
151
|
+
local value
|
|
152
|
+
value=$(yaml_field "$field" "$yaml_file")
|
|
153
|
+
echo "${value:-}"
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
cmd_set() {
|
|
157
|
+
local change_name="$1"
|
|
158
|
+
local field="$2"
|
|
159
|
+
local value="$3"
|
|
160
|
+
|
|
161
|
+
validate_change_name "$change_name"
|
|
162
|
+
|
|
163
|
+
local change_dir="openspec/changes/$change_name"
|
|
164
|
+
local yaml_file="$change_dir/.comet.yaml"
|
|
165
|
+
|
|
166
|
+
# Check if .comet.yaml exists
|
|
167
|
+
if [ ! -f "$yaml_file" ]; then
|
|
168
|
+
red "ERROR: .comet.yaml not found at $yaml_file"
|
|
169
|
+
exit 1
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
# Validate field name
|
|
173
|
+
case "$field" in
|
|
174
|
+
workflow|phase|build_mode|isolation|verify_mode|verify_result|archived|design_doc|plan|verified_at)
|
|
175
|
+
# Valid field
|
|
176
|
+
;;
|
|
177
|
+
*)
|
|
178
|
+
red "ERROR: Unknown field: '$field'" >&2
|
|
179
|
+
red "Valid fields: workflow, phase, design_doc, plan, build_mode, isolation, verify_mode, verify_result, verified_at, archived" >&2
|
|
180
|
+
exit 1
|
|
181
|
+
;;
|
|
182
|
+
esac
|
|
183
|
+
|
|
184
|
+
# Validate enum values
|
|
185
|
+
case "$field" in
|
|
186
|
+
workflow)
|
|
187
|
+
validate_enum "$value" "full" "hotfix" "tweak"
|
|
188
|
+
;;
|
|
189
|
+
phase)
|
|
190
|
+
validate_enum "$value" "design" "build" "verify" "archive"
|
|
191
|
+
;;
|
|
192
|
+
build_mode)
|
|
193
|
+
validate_enum "$value" "subagent-driven-development" "executing-plans" "direct"
|
|
194
|
+
;;
|
|
195
|
+
isolation)
|
|
196
|
+
validate_enum "$value" "branch" "worktree"
|
|
197
|
+
;;
|
|
198
|
+
verify_mode)
|
|
199
|
+
validate_enum "$value" "light" "full"
|
|
200
|
+
;;
|
|
201
|
+
verify_result)
|
|
202
|
+
validate_enum "$value" "pending" "pass" "fail"
|
|
203
|
+
;;
|
|
204
|
+
archived)
|
|
205
|
+
validate_enum "$value" "true" "false"
|
|
206
|
+
;;
|
|
207
|
+
design_doc|plan|verified_at)
|
|
208
|
+
# No validation for path fields and date fields
|
|
209
|
+
;;
|
|
210
|
+
esac
|
|
211
|
+
|
|
212
|
+
# Write or update the field
|
|
213
|
+
if grep -q "^${field}:" "$yaml_file"; then
|
|
214
|
+
# Field exists, replace it
|
|
215
|
+
sed -i "s/^${field}:.*/${field}: ${value}/" "$yaml_file"
|
|
216
|
+
else
|
|
217
|
+
# Field doesn't exist, append it
|
|
218
|
+
echo "${field}: ${value}" >> "$yaml_file"
|
|
219
|
+
fi
|
|
220
|
+
|
|
221
|
+
green "[SET] ${field}=${value}"
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
# --- Check helpers for entry verification ---
|
|
225
|
+
|
|
226
|
+
CHECK_BLOCK=0
|
|
227
|
+
|
|
228
|
+
check_pass() {
|
|
229
|
+
local msg="$1"
|
|
230
|
+
echo " $(green "[PASS]") $msg"
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
check_fail() {
|
|
234
|
+
local msg="$1"
|
|
235
|
+
echo " $(red "[FAIL]") $msg"
|
|
236
|
+
CHECK_BLOCK=1
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
check_nonempty() {
|
|
240
|
+
local desc="$1"
|
|
241
|
+
local path="$1"
|
|
242
|
+
if file_nonempty "$path"; then
|
|
243
|
+
check_pass "$desc non-empty"
|
|
244
|
+
else
|
|
245
|
+
check_fail "$desc missing or empty"
|
|
246
|
+
fi
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
check_yaml_is() {
|
|
250
|
+
local field="$1"
|
|
251
|
+
local expected="$2"
|
|
252
|
+
local change_name="$3"
|
|
253
|
+
local actual
|
|
254
|
+
actual=$(cmd_get "$change_name" "$field")
|
|
255
|
+
if [ "$actual" = "$expected" ]; then
|
|
256
|
+
check_pass "${field}=${actual} (expected: ${expected})"
|
|
257
|
+
else
|
|
258
|
+
check_fail "${field}=${actual} (expected: ${expected})"
|
|
259
|
+
fi
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
check_yaml_empty() {
|
|
263
|
+
local field="$1"
|
|
264
|
+
local change_name="$2"
|
|
265
|
+
local value
|
|
266
|
+
value=$(cmd_get "$change_name" "$field")
|
|
267
|
+
if [ -z "$value" ] || [ "$value" = "null" ]; then
|
|
268
|
+
check_pass "${field} is empty/null"
|
|
269
|
+
else
|
|
270
|
+
check_fail "${field}=${value} (expected: empty/null)"
|
|
271
|
+
fi
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
check_file_not_exists() {
|
|
275
|
+
local desc="$1"
|
|
276
|
+
local path="$2"
|
|
277
|
+
if [ ! -f "$path" ]; then
|
|
278
|
+
check_pass "$desc does not exist"
|
|
279
|
+
else
|
|
280
|
+
check_fail "$desc exists (should not exist)"
|
|
281
|
+
fi
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
cmd_check() {
|
|
285
|
+
local phase="$1"
|
|
286
|
+
local change_name="$2"
|
|
287
|
+
|
|
288
|
+
validate_change_name "$change_name"
|
|
289
|
+
validate_enum "$phase" "open" "design" "build" "verify" "archive"
|
|
290
|
+
|
|
291
|
+
local change_dir="openspec/changes/$change_name"
|
|
292
|
+
local yaml_file="$change_dir/.comet.yaml"
|
|
293
|
+
local proposal_file="$change_dir/proposal.md"
|
|
294
|
+
local design_file="$change_dir/design.md"
|
|
295
|
+
local tasks_file="$change_dir/tasks.md"
|
|
296
|
+
|
|
297
|
+
echo "=== Entry Check: comet-${phase} ==="
|
|
298
|
+
|
|
299
|
+
# For non-open phases, .comet.yaml must exist
|
|
300
|
+
if [ "$phase" != "open" ]; then
|
|
301
|
+
if [ ! -f "$yaml_file" ]; then
|
|
302
|
+
red "ERROR: .comet.yaml not found at $yaml_file"
|
|
303
|
+
exit 1
|
|
304
|
+
fi
|
|
305
|
+
fi
|
|
306
|
+
|
|
307
|
+
# Phase-specific checks
|
|
308
|
+
case "$phase" in
|
|
309
|
+
open)
|
|
310
|
+
check_file_not_exists ".comet.yaml" "$yaml_file"
|
|
311
|
+
check_nonempty "proposal.md" "$proposal_file"
|
|
312
|
+
check_nonempty "design.md" "$design_file"
|
|
313
|
+
check_nonempty "tasks.md" "$tasks_file"
|
|
314
|
+
;;
|
|
315
|
+
design)
|
|
316
|
+
check_pass ".comet.yaml exists"
|
|
317
|
+
check_yaml_is "phase" "design" "$change_name"
|
|
318
|
+
check_yaml_is "workflow" "full" "$change_name"
|
|
319
|
+
check_yaml_empty "design_doc" "$change_name"
|
|
320
|
+
check_nonempty "proposal.md" "$proposal_file"
|
|
321
|
+
check_nonempty "design.md" "$design_file"
|
|
322
|
+
check_nonempty "tasks.md" "$tasks_file"
|
|
323
|
+
;;
|
|
324
|
+
build)
|
|
325
|
+
check_pass ".comet.yaml exists"
|
|
326
|
+
check_yaml_is "phase" "build" "$change_name"
|
|
327
|
+
# Check design_doc is non-null and file exists
|
|
328
|
+
local design_doc
|
|
329
|
+
design_doc=$(cmd_get "$change_name" "design_doc")
|
|
330
|
+
if [ -n "$design_doc" ] && [ "$design_doc" != "null" ] && [ -f "$change_dir/$design_doc" ]; then
|
|
331
|
+
check_pass "design_doc=${design_doc} (file exists)"
|
|
332
|
+
else
|
|
333
|
+
check_fail "design_doc=${design_doc} (expected: non-null and file exists)"
|
|
334
|
+
fi
|
|
335
|
+
check_nonempty "proposal.md" "$proposal_file"
|
|
336
|
+
check_nonempty "tasks.md" "$tasks_file"
|
|
337
|
+
;;
|
|
338
|
+
verify)
|
|
339
|
+
check_pass ".comet.yaml exists"
|
|
340
|
+
check_yaml_is "phase" "verify" "$change_name"
|
|
341
|
+
# Check verify_result is pending or null
|
|
342
|
+
local verify_result
|
|
343
|
+
verify_result=$(cmd_get "$change_name" "verify_result")
|
|
344
|
+
if [ "$verify_result" = "pending" ] || [ -z "$verify_result" ] || [ "$verify_result" = "null" ]; then
|
|
345
|
+
check_pass "verify_result=${verify_result} (expected: pending or null)"
|
|
346
|
+
else
|
|
347
|
+
check_fail "verify_result=${verify_result} (expected: pending or null)"
|
|
348
|
+
fi
|
|
349
|
+
;;
|
|
350
|
+
archive)
|
|
351
|
+
check_pass ".comet.yaml exists"
|
|
352
|
+
check_yaml_is "phase" "archive" "$change_name"
|
|
353
|
+
check_yaml_is "verify_result" "pass" "$change_name"
|
|
354
|
+
# Check archived is NOT true
|
|
355
|
+
local archived
|
|
356
|
+
archived=$(cmd_get "$change_name" "archived")
|
|
357
|
+
if [ "$archived" != "true" ]; then
|
|
358
|
+
check_pass "archived=${archived} (expected: not true)"
|
|
359
|
+
else
|
|
360
|
+
check_fail "archived=${archived} (expected: not true)"
|
|
361
|
+
fi
|
|
362
|
+
;;
|
|
363
|
+
*)
|
|
364
|
+
red "ERROR: Unknown phase for check: $phase"
|
|
365
|
+
exit 1
|
|
366
|
+
;;
|
|
367
|
+
esac
|
|
368
|
+
|
|
369
|
+
echo ""
|
|
370
|
+
if [ "$CHECK_BLOCK" -eq 1 ]; then
|
|
371
|
+
red "BLOCKED — fix failing checks before proceeding"
|
|
372
|
+
exit 1
|
|
373
|
+
else
|
|
374
|
+
green "ALL CHECKS PASSED — ready to proceed"
|
|
375
|
+
exit 0
|
|
376
|
+
fi
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
cmd_scale() {
|
|
380
|
+
local change_name="$1"
|
|
381
|
+
|
|
382
|
+
validate_change_name "$change_name"
|
|
383
|
+
|
|
384
|
+
local change_dir="openspec/changes/$change_name"
|
|
385
|
+
local yaml_file="$change_dir/.comet.yaml"
|
|
386
|
+
|
|
387
|
+
# Verify .comet.yaml exists
|
|
388
|
+
if [ ! -f "$yaml_file" ]; then
|
|
389
|
+
red "ERROR: .comet.yaml not found at $yaml_file"
|
|
390
|
+
exit 1
|
|
391
|
+
fi
|
|
392
|
+
|
|
393
|
+
# Read metrics
|
|
394
|
+
# 1. Task count: count lines matching `- [` in tasks.md
|
|
395
|
+
local tasks_file="$change_dir/tasks.md"
|
|
396
|
+
local task_count=0
|
|
397
|
+
if [ -f "$tasks_file" ]; then
|
|
398
|
+
task_count=$(grep -c '^\- \[' "$tasks_file" 2>/dev/null || echo "0")
|
|
399
|
+
fi
|
|
400
|
+
|
|
401
|
+
# 2. Delta spec count: count files named spec.md under specs/*/spec.md
|
|
402
|
+
local delta_spec_count=0
|
|
403
|
+
if [ -d "$change_dir/specs" ]; then
|
|
404
|
+
delta_spec_count=$(find "$change_dir/specs" -name "spec.md" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
405
|
+
fi
|
|
406
|
+
|
|
407
|
+
# 3. Changed files: from git diff --stat HEAD
|
|
408
|
+
local changed_files=0
|
|
409
|
+
if git rev-parse --git-dir > /dev/null 2>&1; then
|
|
410
|
+
# Extract the number before "file" in the last line
|
|
411
|
+
local stat_output
|
|
412
|
+
stat_output=$(git diff --stat HEAD 2>/dev/null | tail -1)
|
|
413
|
+
if [[ "$stat_output" =~ ([0-9]+)\ file ]]; then
|
|
414
|
+
changed_files="${BASH_REMATCH[1]}"
|
|
415
|
+
fi
|
|
416
|
+
fi
|
|
417
|
+
|
|
418
|
+
# Decision rules
|
|
419
|
+
local result="light"
|
|
420
|
+
if [ "$task_count" -gt 3 ] || [ "$delta_spec_count" -gt 1 ] || [ "$changed_files" -gt 5 ]; then
|
|
421
|
+
result="full"
|
|
422
|
+
fi
|
|
423
|
+
|
|
424
|
+
# Output assessment to stderr
|
|
425
|
+
echo "=== Scale Assessment: $change_name ===" >&2
|
|
426
|
+
echo " Tasks: $task_count (threshold: 3)" >&2
|
|
427
|
+
echo " Delta specs: $delta_spec_count capabilities (threshold: 1)" >&2
|
|
428
|
+
echo " Changed files: $changed_files (threshold: 5)" >&2
|
|
429
|
+
echo " → Result: $result" >&2
|
|
430
|
+
|
|
431
|
+
# Update verify_mode in .comet.yaml
|
|
432
|
+
sed -i "s/^verify_mode:.*/verify_mode: $result/" "$yaml_file"
|
|
433
|
+
|
|
434
|
+
green "[SCALE] verify_mode=$result"
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
# --- Main ---
|
|
438
|
+
|
|
439
|
+
SUBCOMMAND="${1:-}"
|
|
440
|
+
shift || true
|
|
441
|
+
|
|
442
|
+
case "$SUBCOMMAND" in
|
|
443
|
+
init)
|
|
444
|
+
if [ $# -lt 2 ]; then
|
|
445
|
+
red "Usage: comet-state.sh init <change-name> <workflow>" >&2
|
|
446
|
+
red "Workflows: full, hotfix, tweak" >&2
|
|
447
|
+
exit 1
|
|
448
|
+
fi
|
|
449
|
+
cmd_init "$@"
|
|
450
|
+
;;
|
|
451
|
+
get)
|
|
452
|
+
if [ $# -lt 2 ]; then
|
|
453
|
+
red "Usage: comet-state.sh get <change-name> <field>" >&2
|
|
454
|
+
exit 1
|
|
455
|
+
fi
|
|
456
|
+
cmd_get "$@"
|
|
457
|
+
;;
|
|
458
|
+
set)
|
|
459
|
+
if [ $# -lt 3 ]; then
|
|
460
|
+
red "Usage: comet-state.sh set <change-name> <field> <value>" >&2
|
|
461
|
+
exit 1
|
|
462
|
+
fi
|
|
463
|
+
cmd_set "$@"
|
|
464
|
+
;;
|
|
465
|
+
check)
|
|
466
|
+
if [ $# -lt 2 ]; then
|
|
467
|
+
red "Usage: comet-state.sh check <phase> <change-name>" >&2
|
|
468
|
+
red "Phases: open, design, build, verify, archive" >&2
|
|
469
|
+
exit 1
|
|
470
|
+
fi
|
|
471
|
+
cmd_check "$@"
|
|
472
|
+
;;
|
|
473
|
+
scale)
|
|
474
|
+
if [ $# -lt 1 ]; then
|
|
475
|
+
red "Usage: comet-state.sh scale <change-name>" >&2
|
|
476
|
+
exit 1
|
|
477
|
+
fi
|
|
478
|
+
cmd_scale "$@"
|
|
479
|
+
;;
|
|
480
|
+
*)
|
|
481
|
+
red "Unknown subcommand: $SUBCOMMAND" >&2
|
|
482
|
+
echo "" >&2
|
|
483
|
+
echo "Usage: comet-state.sh <subcommand> <change-name> [args...]" >&2
|
|
484
|
+
echo "" >&2
|
|
485
|
+
echo "Subcommands:" >&2
|
|
486
|
+
echo " init <change-name> <workflow> — Initialize .comet.yaml with workflow defaults" >&2
|
|
487
|
+
echo " get <change-name> <field> — Read a field value from .comet.yaml" >&2
|
|
488
|
+
echo " set <change-name> <field> <val> — Update a field value in .comet.yaml" >&2
|
|
489
|
+
echo " check <phase> <change-name> — Verify entry requirements for a phase" >&2
|
|
490
|
+
echo " scale <change-name> — Assess and set verification mode based on metrics" >&2
|
|
491
|
+
echo "" >&2
|
|
492
|
+
echo "Workflows: full, hotfix, tweak" >&2
|
|
493
|
+
echo "Phases for check: open, design, build, verify, archive" >&2
|
|
494
|
+
exit 1
|
|
495
|
+
;;
|
|
496
|
+
esac
|
|
@@ -15,34 +15,21 @@ description: "Comet Phase 5: Archive. Invoke with /comet-archive. Sync delta spe
|
|
|
15
15
|
|
|
16
16
|
### 0. Entry State Verification (Entry Check)
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Execute entry verification:
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
3. `verify_result` field value is `"pass"`
|
|
24
|
-
4. `archived` field is `"false"` or null (not yet archived)
|
|
25
|
-
|
|
26
|
-
**Verification method:**
|
|
27
|
-
- `cat openspec/changes/<name>/.comet.yaml` to read all fields
|
|
28
|
-
- If `verify_result` is not `"pass"`, must complete verification first
|
|
29
|
-
|
|
30
|
-
**Failure output:**
|
|
31
|
-
```
|
|
32
|
-
[HARD STOP] Entry check failed for comet-archive
|
|
33
|
-
Expected: phase=archive, verify_result=pass, archived=false|null
|
|
34
|
-
Actual: phase=<actual-value>, verify_result=<actual-value>, archived=<actual-value>
|
|
35
|
-
Suggestion: Run comet-verify first, or this change was already archived.
|
|
20
|
+
```bash
|
|
21
|
+
COMET_STATE="${COMET_STATE:-$(find . -path '*/comet/scripts/comet-state.sh' -type f -print -quit)}"
|
|
22
|
+
bash "$COMET_STATE" check <name> archive
|
|
36
23
|
```
|
|
37
24
|
|
|
38
|
-
Proceed to Step 1
|
|
25
|
+
Proceed to Step 1 after verification passes. The script outputs specific failure reasons when verification fails.
|
|
39
26
|
|
|
40
27
|
### 1. Execute Archive
|
|
41
28
|
|
|
42
29
|
Run the archive script to automatically complete all steps:
|
|
43
30
|
|
|
44
31
|
```bash
|
|
45
|
-
COMET_ARCHIVE
|
|
32
|
+
COMET_ARCHIVE="${COMET_ARCHIVE:-$(find . -path '*/comet/scripts/comet-archive.sh' -type f -print -quit)}"
|
|
46
33
|
bash "$COMET_ARCHIVE" "<change-name>"
|
|
47
34
|
```
|
|
48
35
|
|
|
@@ -14,29 +14,14 @@ description: "Comet Phase 3: Plan and Build. Invoke with /comet-build. Create pl
|
|
|
14
14
|
|
|
15
15
|
### 0. Entry State Verification (Entry Check)
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Execute entry verification:
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
3. `design_doc` field is non-null and non-empty
|
|
23
|
-
4. File referenced by `design_doc` exists (e.g., `docs/superpowers/specs/YYYY-MM-DD-topic-design.md`)
|
|
24
|
-
5. `openspec/changes/<name>/proposal.md` exists and is non-empty
|
|
25
|
-
6. `openspec/changes/<name>/tasks.md` exists and is non-empty
|
|
26
|
-
|
|
27
|
-
**Verification method:**
|
|
28
|
-
- `cat openspec/changes/<name>/.comet.yaml` to read all fields
|
|
29
|
-
- Use `ls` or `test -f` to confirm design_doc file exists
|
|
30
|
-
|
|
31
|
-
**Failure output:**
|
|
32
|
-
```
|
|
33
|
-
[HARD STOP] Entry check failed for comet-build
|
|
34
|
-
Expected: phase=build, design_doc=<path> exists
|
|
35
|
-
Actual: phase=<actual-value>, design_doc=<actual-value or file does not exist>
|
|
36
|
-
Suggestion: Run comet-design first, or verify design_doc file exists.
|
|
19
|
+
```bash
|
|
20
|
+
COMET_STATE="${COMET_STATE:-$(find . -path '*/comet/scripts/comet-state.sh' -type f -print -quit)}"
|
|
21
|
+
bash "$COMET_STATE" check <name> build
|
|
37
22
|
```
|
|
38
23
|
|
|
39
|
-
Proceed to Step 1
|
|
24
|
+
Proceed to Step 1 after verification passes. The script outputs specific failure reasons when verification fails.
|
|
40
25
|
|
|
41
26
|
### 1. Create Plan
|
|
42
27
|
|
|
@@ -59,7 +44,7 @@ design-doc: docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md
|
|
|
59
44
|
Record plan path:
|
|
60
45
|
|
|
61
46
|
```bash
|
|
62
|
-
|
|
47
|
+
bash "$COMET_STATE" set <name> plan docs/superpowers/plans/YYYY-MM-DD-feature.md
|
|
63
48
|
```
|
|
64
49
|
|
|
65
50
|
No manual phase update needed — guard auto-transitions when exit conditions are met.
|
|
@@ -77,7 +62,11 @@ Plan has been written to the current branch. Before starting execution, choose w
|
|
|
77
62
|
- Change involves ≤ 3 files → Recommend A
|
|
78
63
|
- Need parallel development, current branch has uncommitted work → Recommend B
|
|
79
64
|
|
|
80
|
-
After user selection, update `isolation`
|
|
65
|
+
After user selection, update `isolation` field. `isolation` only allows one of the following values:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
bash "$COMET_STATE" set <name> isolation <value>
|
|
69
|
+
```
|
|
81
70
|
|
|
82
71
|
- `branch`
|
|
83
72
|
- `worktree`
|
|
@@ -103,7 +92,11 @@ Present plan summary to user (task count, involved modules), then ask for execut
|
|
|
103
92
|
- Task count ≤ 2 and no cross-module dependencies → Recommend B
|
|
104
93
|
- From hotfix path → Recommend B
|
|
105
94
|
|
|
106
|
-
After user selection, update `build_mode`
|
|
95
|
+
After user selection, update `build_mode` field. `build_mode` only allows one of the following values:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
bash "$COMET_STATE" set <name> build_mode <value>
|
|
99
|
+
```
|
|
107
100
|
|
|
108
101
|
- `subagent-driven-development`
|
|
109
102
|
- `executing-plans`
|