@rpamis/comet 0.1.6 → 0.1.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 CHANGED
@@ -90,12 +90,14 @@ After `comet init`, three groups of skills are installed to the selected platfor
90
90
  | `/comet-hotfix` | Preset: Quick bug fix (skips brainstorming) |
91
91
  | `/comet-tweak` | Preset: Small change (skips brainstorming and full plan) |
92
92
 
93
- ### Guard Scripts
93
+ ### Guard & Automation Scripts
94
94
 
95
95
  | Script | Purpose |
96
96
  |--------|---------|
97
- | `comet-guard.sh` | Phase transition guard — validates exit conditions before phase transitions |
97
+ | `comet-guard.sh` | Phase transition guard — validates exit conditions, `--apply` auto-updates `.comet.yaml` |
98
+ | `comet-archive.sh` | One-command archive — validates state, syncs specs, moves to archive, updates status |
98
99
  | `comet-yaml-validate.sh` | Schema validator — validates `.comet.yaml` structure and field values |
100
+ | `comet-state.sh` | Unified state management — init/set/get/check/scale, agents' exclusive YAML interface |
99
101
 
100
102
  ### OpenSpec Skills
101
103
 
@@ -153,28 +155,37 @@ Comet uses a decoupled state architecture with separate YAML files:
153
155
  - `design_doc`: Path to Superpowers Design Doc
154
156
  - `plan`: Path to implementation plan
155
157
  - `build_mode`: `subagent-driven-development`, `executing-plans`, or `direct`
158
+ - `isolation`: `branch` or `worktree`, workspace isolation method
156
159
  - `verify_mode`: `light` or `full`
157
160
  - `verify_result`: `pending`, `pass`, or `fail`
158
161
  - `archived`: Boolean indicating if change is archived
159
162
 
160
163
  ### Reliability Features
161
164
 
162
- Comet includes three-layer defense to ensure agent execution reliability:
165
+ Comet ensures agent execution reliability through automated state transitions:
163
166
 
164
167
  1. **Entry Verification** — Each phase validates preconditions before execution
165
168
  - Checks file existence, state consistency, and phase transitions
166
169
  - Outputs `[HARD STOP]` with actionable suggestions if validation fails
167
170
 
168
- 2. **Write-Then-Verify** — Every state write is immediately verified
169
- - After updating `.comet.yaml`, agents must verify field values
170
- - Automatic retry mechanism (up to 2 attempts) on mismatch
171
+ 2. **Automated State Transitions** — `comet-guard.sh --apply` updates `.comet.yaml` automatically
172
+ - All phase transitions (design build → verify archive) use `guard --apply`
173
+ - No manual state editing required eliminates write-verification errors
174
+ - `comet-state.sh` is the agents' exclusive interface for state operations
175
+ - Guard and archive scripts use `comet-state.sh` internally for state management
171
176
 
172
177
  3. **Schema Validation** — `comet-yaml-validate.sh` ensures data integrity
173
- - Validates required fields (9 fields)
174
- - Validates enum values (6 enum types)
178
+ - Validates required fields (10 fields)
179
+ - Validates enum values (7 enum types)
175
180
  - Validates referenced file paths exist
176
181
  - Detects unknown/typos fields
177
182
 
183
+ 4. **Archive Automation** — `comet-archive.sh` handles the full archive flow in one command
184
+ - Validates entry state, syncs delta specs to main specs
185
+ - Annotates design doc and plan frontmatter
186
+ - Moves change to archive directory and updates `archived: true`
187
+ - Supports `--dry-run` for preview
188
+
178
189
  **Security**: Path traversal protection on all change name inputs
179
190
 
180
191
  ## Project Structure
@@ -184,8 +195,10 @@ your-project/
184
195
  ├── .claude/skills/ # Platform skills dir (Comet + OpenSpec + Superpowers)
185
196
  │ ├── comet/SKILL.md
186
197
  │ │ └── scripts/
187
- │ │ ├── comet-guard.sh # Phase transition guard
188
- │ │ └── comet-yaml-validate.sh # Schema validator
198
+ │ │ ├── comet-guard.sh # Phase transition guard (--apply auto-updates state)
199
+ │ │ ├── comet-archive.sh # One-command archive automation
200
+ │ │ ├── comet-yaml-validate.sh # Schema validator
201
+ │ │ └── comet-state.sh # Unified state management (init/set/get/check/scale)
189
202
  │ ├── comet-*/SKILL.md
190
203
  │ ├── openspec-*/SKILL.md
191
204
  │ └── brainstorming/SKILL.md
@@ -208,7 +221,7 @@ your-project/
208
221
 
209
222
  ```bash
210
223
  # Clone
211
- git clone https://github.com/benym/comet.git
224
+ git clone https://github.com/rpamis/comet
212
225
  cd comet
213
226
 
214
227
  # Install dependencies
@@ -161,7 +161,7 @@ If metadata conflicts with file state, use verifiable file state as source of tr
161
161
 
162
162
  ### Script Location
163
163
 
164
- Comet phase guard script `comet-guard.sh` is distributed with the skill package, located in `comet/scripts/` directory.
164
+ Comet phase guard script `comet-guard.sh` and archive script `comet-archive.sh` are distributed with the skill package, located in `comet/scripts/` directory.
165
165
  **Do not hardcode platform paths**, self-locate at runtime with:
166
166
 
167
167
  ```bash
@@ -169,6 +169,19 @@ COMET_GUARD=$(find . -path '*/comet/scripts/comet-guard.sh' -type f -print -quit
169
169
  bash "$COMET_GUARD" <change-name> <phase>
170
170
  ```
171
171
 
172
+ **Auto state update**: Guard supports `--apply` flag, automatically updating `.comet.yaml` state fields after checks pass:
173
+
174
+ ```bash
175
+ bash "$COMET_GUARD" <change-name> <phase> --apply
176
+ ```
177
+
178
+ **Archive script**: Complete all archive steps in one command:
179
+
180
+ ```bash
181
+ COMET_ARCHIVE=$(find . -path '*/comet/scripts/comet-archive.sh' -type f -print -quit)
182
+ bash "$COMET_ARCHIVE" <change-name>
183
+ ```
184
+
172
185
  In subsequent documentation, `bash $COMET_GUARD <change> <phase>` refers to this command. After loading comet, agents should cache `COMET_GUARD` path in shell environment to avoid repeated `find`.
173
186
 
174
187
  ### File Structure
@@ -185,7 +198,7 @@ openspec/ # OpenSpec — WHAT
185
198
  │ │ ├── specs/<capability>/spec.md # Delta capability spec
186
199
  │ │ └── tasks.md # Task checklist
187
200
  │ └── archive/YYYY-MM-DD-<name>/ # Archived
188
- └── specs/<capability>/spec.md # Main specs (sync from delta at archive)
201
+ └── specs/<capability>/spec.md # Main specs (overwritten from delta at archive)
189
202
 
190
203
  docs/superpowers/ # Superpowers — HOW
191
204
  ├── specs/YYYY-MM-DD-<topic>-design.md # Design doc (technical RFC, mark status at archive)
@@ -202,5 +215,5 @@ docs/superpowers/ # Superpowers — HOW
202
215
  6. **Classify incremental updates** — Small edits, medium brainstorming, large new changes
203
216
  7. **Plan must associate with change** — File header contains `change:` and `design-doc:` metadata
204
217
  8. **Archive closure** — design doc and plan must mark `archived-with` status
205
- 9. **Incremental modification of existing features** — Create delta spec baseline based on main spec, not from scratch
218
+ 9. **Modifying existing features** — Just open a new change; brainstorming reads existing specs as context naturally
206
219
  10. **Preset has limits** — Switch to full workflow promptly when hotfix/tweak meet upgrade conditions
@@ -0,0 +1,258 @@
1
+ #!/bin/bash
2
+ # Comet Archive — automates the archive phase in one command
3
+ # Usage: comet-archive.sh <change-name> [--dry-run]
4
+ # Exit 0 = archive complete, exit 1 = fatal error
5
+
6
+ set -euo pipefail
7
+
8
+ red() { echo -e "\033[31m$1\033[0m" >&2; }
9
+ green() { echo -e "\033[32m$1\033[0m" >&2; }
10
+ yellow() { echo -e "\033[33m$1\033[0m" >&2; }
11
+
12
+ DRY_RUN=0
13
+ if [[ "${2:-}" == "--dry-run" ]]; then
14
+ DRY_RUN=1
15
+ fi
16
+
17
+ # Input validation
18
+ validate_change_name() {
19
+ local name="$1"
20
+ if [ -z "$name" ]; then
21
+ red "FATAL: Change name cannot be empty"
22
+ exit 1
23
+ fi
24
+ if [[ ! "$name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
25
+ red "FATAL: Invalid change name: '$name'"
26
+ red "Valid characters: a-z, A-Z, 0-9, -, _"
27
+ exit 1
28
+ fi
29
+ if [[ "$name" =~ \.\. ]]; then
30
+ red "FATAL: Change name cannot contain '..'"
31
+ exit 1
32
+ fi
33
+ }
34
+
35
+ CHANGE="$1"
36
+ validate_change_name "$CHANGE"
37
+
38
+ CHANGE_DIR="openspec/changes/$CHANGE"
39
+ YAML="$CHANGE_DIR/.comet.yaml"
40
+ SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "$0" 2>/dev/null || echo "$0")" 2>/dev/null || dirname "$0")" && pwd)"
41
+ STATE_SH="$SCRIPT_DIR/comet-state.sh"
42
+ TODAY=$(date +%Y-%m-%d)
43
+ ARCHIVE_NAME="${TODAY}-${CHANGE}"
44
+ ARCHIVE_DIR="openspec/changes/archive/${ARCHIVE_NAME}"
45
+
46
+ STEPS_OK=0
47
+ STEPS_TOTAL=0
48
+
49
+ step_ok() {
50
+ green " [OK] $1"
51
+ STEPS_OK=$((STEPS_OK + 1))
52
+ STEPS_TOTAL=$((STEPS_TOTAL + 1))
53
+ }
54
+
55
+ step_fail() {
56
+ red " [FAIL] $1"
57
+ STEPS_TOTAL=$((STEPS_TOTAL + 1))
58
+ }
59
+
60
+ echo "=== Comet Archive: $CHANGE ===" >&2
61
+
62
+ # --- Step 1: Read .comet.yaml, extract paths ---
63
+
64
+ yaml_field() {
65
+ local field="$1"
66
+ if [ -f "$STATE_SH" ]; then
67
+ bash "$STATE_SH" get "$CHANGE" "$field" 2>/dev/null
68
+ else
69
+ if [ -f "$YAML" ]; then
70
+ grep "^${field}:" "$YAML" | sed "s/^${field}: *//" | tr -d '"' | tr -d "'"
71
+ fi
72
+ fi
73
+ }
74
+
75
+ if [ ! -f "$YAML" ]; then
76
+ red "FATAL: .comet.yaml not found in $CHANGE_DIR/"
77
+ exit 1
78
+ fi
79
+
80
+ DESIGN_DOC=$(yaml_field "design_doc")
81
+ PLAN_PATH=$(yaml_field "plan")
82
+
83
+ # --- Step 2: Validate entry state ---
84
+
85
+ PHASE_VAL=$(yaml_field "phase")
86
+ VERIFY_VAL=$(yaml_field "verify_result")
87
+ ARCHIVED_VAL=$(yaml_field "archived")
88
+
89
+ if [ "$PHASE_VAL" != "archive" ]; then
90
+ red "FATAL: phase is '$PHASE_VAL', expected 'archive'"
91
+ exit 1
92
+ fi
93
+
94
+ if [ "$VERIFY_VAL" != "pass" ]; then
95
+ red "FATAL: verify_result is '$VERIFY_VAL', expected 'pass'. Run comet-verify first."
96
+ exit 1
97
+ fi
98
+
99
+ if [ "$ARCHIVED_VAL" = "true" ]; then
100
+ red "FATAL: change already archived"
101
+ exit 1
102
+ fi
103
+
104
+ step_ok "Entry state verified"
105
+
106
+ # --- Step 3: Check archive target ---
107
+
108
+ if [ -d "$ARCHIVE_DIR" ]; then
109
+ red "FATAL: archive target already exists: $ARCHIVE_DIR"
110
+ exit 1
111
+ fi
112
+
113
+ step_ok "Archive target available"
114
+
115
+ # --- Step 4: Sync delta specs → main specs ---
116
+
117
+ sync_delta_specs() {
118
+ local delta_root="$CHANGE_DIR/specs"
119
+ if [ ! -d "$delta_root" ]; then
120
+ return 0
121
+ fi
122
+
123
+ for delta_spec_dir in "$delta_root"/*/; do
124
+ [ -d "$delta_spec_dir" ] || continue
125
+ local capability
126
+ capability=$(basename "$delta_spec_dir")
127
+ local delta_spec="$delta_spec_dir/spec.md"
128
+ local main_spec="openspec/specs/$capability/spec.md"
129
+
130
+ if [ ! -f "$delta_spec" ]; then
131
+ continue
132
+ fi
133
+
134
+ STEPS_TOTAL=$((STEPS_TOTAL + 1))
135
+
136
+ if [ "$DRY_RUN" -eq 1 ]; then
137
+ yellow " [DRY-RUN] Would sync: $capability → $main_spec"
138
+ STEPS_OK=$((STEPS_OK + 1))
139
+ continue
140
+ fi
141
+
142
+ if [ ! -f "$main_spec" ]; then
143
+ mkdir -p "openspec/specs/$capability"
144
+ fi
145
+ cp "$delta_spec" "$main_spec"
146
+
147
+ step_ok "Delta spec synced: $capability → openspec/specs/$capability/spec.md"
148
+ done
149
+ }
150
+
151
+ sync_delta_specs
152
+
153
+ # --- Step 5: Annotate design doc frontmatter ---
154
+
155
+ annotate_frontmatter() {
156
+ local file="$1"
157
+ local extra_fields="$2"
158
+
159
+ if [ ! -f "$file" ]; then
160
+ return 0
161
+ fi
162
+
163
+ STEPS_TOTAL=$((STEPS_TOTAL + 1))
164
+
165
+ if [ "$DRY_RUN" -eq 1 ]; then
166
+ yellow " [DRY-RUN] Would annotate: $file"
167
+ STEPS_OK=$((STEPS_OK + 1))
168
+ return 0
169
+ fi
170
+
171
+ if head -1 "$file" | grep -q '^---'; then
172
+ local tmp_file
173
+ tmp_file=$(mktemp)
174
+ awk -v archive="$ARCHIVE_NAME" -v extra="$extra_fields" '
175
+ /^archived-with:/ { next }
176
+ NR==1 && /^---/ { print; next }
177
+ /^---/ && NR>1 {
178
+ print "archived-with: " archive
179
+ if (extra != "") print extra
180
+ print; next
181
+ }
182
+ { print }
183
+ ' "$file" > "$tmp_file"
184
+ mv "$tmp_file" "$file"
185
+ else
186
+ local tmp_file
187
+ tmp_file=$(mktemp)
188
+ {
189
+ echo "---"
190
+ echo "archived-with: $ARCHIVE_NAME"
191
+ if [ -n "$extra_fields" ]; then
192
+ echo "$extra_fields"
193
+ fi
194
+ echo "status: final"
195
+ echo "---"
196
+ cat "$file"
197
+ } > "$tmp_file"
198
+ mv "$tmp_file" "$file"
199
+ fi
200
+
201
+ step_ok "Annotated: $file"
202
+ }
203
+
204
+ if [ -n "$DESIGN_DOC" ] && [ "$DESIGN_DOC" != "null" ]; then
205
+ annotate_frontmatter "$DESIGN_DOC" "status: final"
206
+ fi
207
+
208
+ # --- Step 6: Annotate plan frontmatter ---
209
+
210
+ if [ -n "$PLAN_PATH" ] && [ "$PLAN_PATH" != "null" ]; then
211
+ annotate_frontmatter "$PLAN_PATH" ""
212
+ fi
213
+
214
+ # --- Step 7: Move change to archive ---
215
+
216
+ STEPS_TOTAL=$((STEPS_TOTAL + 1))
217
+
218
+ if [ "$DRY_RUN" -eq 1 ]; then
219
+ yellow " [DRY-RUN] Would move: $CHANGE_DIR → $ARCHIVE_DIR"
220
+ STEPS_OK=$((STEPS_OK + 1))
221
+ else
222
+ mkdir -p "openspec/changes/archive"
223
+ mv "$CHANGE_DIR" "$ARCHIVE_DIR"
224
+ step_ok "Moved to: $ARCHIVE_DIR"
225
+ fi
226
+
227
+ # --- Step 8: Update archived: true in .comet.yaml ---
228
+
229
+ STEPS_TOTAL=$((STEPS_TOTAL + 1))
230
+
231
+ ARCHIVE_YAML="$ARCHIVE_DIR/.comet.yaml"
232
+
233
+ if [ "$DRY_RUN" -eq 1 ]; then
234
+ yellow " [DRY-RUN] Would set archived: true in $ARCHIVE_YAML"
235
+ STEPS_OK=$((STEPS_OK + 1))
236
+ else
237
+ if [ -f "$ARCHIVE_YAML" ]; then
238
+ sed -i 's/^archived:.*/archived: true/' "$ARCHIVE_YAML"
239
+ step_ok "archived: true"
240
+ else
241
+ step_fail "archived: true (.comet.yaml not found after move)"
242
+ fi
243
+ fi
244
+
245
+ # --- Step 9: Print summary ---
246
+
247
+ echo "" >&2
248
+ if [ "$DRY_RUN" -eq 1 ]; then
249
+ yellow "Dry run complete. $STEPS_OK/$STEPS_TOTAL steps would succeed."
250
+ else
251
+ green "Archive complete. $STEPS_OK/$STEPS_TOTAL steps succeeded."
252
+ fi
253
+
254
+ if [ "$STEPS_OK" -lt "$STEPS_TOTAL" ]; then
255
+ exit 1
256
+ fi
257
+
258
+ exit 0
@@ -1,6 +1,6 @@
1
1
  #!/bin/bash
2
2
  # Comet Phase Guard — validates exit conditions before phase transitions
3
- # Usage: comet-guard.sh <change-name> <from-phase>
3
+ # Usage: comet-guard.sh <change-name> <current-phase> [--apply]
4
4
  # Phases: open, design, build, verify, archive
5
5
  # Exit 0 = all checks pass, exit 1 = blocked (reasons printed to stderr)
6
6
 
@@ -35,6 +35,10 @@ validate_change_name "$1"
35
35
 
36
36
  CHANGE="$1"
37
37
  PHASE="$2"
38
+ APPLY=0
39
+ if [[ "${3:-}" == "--apply" ]]; then
40
+ APPLY=1
41
+ fi
38
42
  CHANGE_DIR="openspec/changes/$CHANGE"
39
43
 
40
44
  BLOCK=0
@@ -177,6 +181,43 @@ guard_archive() {
177
181
  check "tasks.md all tasks checked" tasks_all_done
178
182
  }
179
183
 
184
+ apply_state_update() {
185
+ local state_sh="$SCRIPT_DIR/comet-state.sh"
186
+ local p="$1"
187
+
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
219
+ }
220
+
180
221
  # --- Main ---
181
222
 
182
223
  case "$PHASE" in
@@ -199,5 +240,14 @@ if [ "$BLOCK" -eq 1 ]; then
199
240
  else
200
241
  echo "" >&2
201
242
  green "ALL CHECKS PASSED — ready for next phase"
243
+ if [ "$APPLY" -eq 1 ]; then
244
+ apply_state_update "$PHASE"
245
+ case "$PHASE" in
246
+ open) green " [APPLY] .comet.yaml updated: phase=design" ;;
247
+ design) green " [APPLY] .comet.yaml updated: phase=build" ;;
248
+ build) green " [APPLY] .comet.yaml updated: phase=verify, verify_result=pending" ;;
249
+ verify) green " [APPLY] .comet.yaml updated: phase=archive, verify_result=pass" ;;
250
+ esac
251
+ fi
202
252
  exit 0
203
253
  fi