@rpamis/comet 0.3.6 → 0.3.7

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 (53) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +175 -63
  3. package/assets/manifest.json +11 -1
  4. package/assets/skills/comet/SKILL.md +44 -16
  5. package/assets/skills/comet/reference/dirty-worktree.md +1 -0
  6. package/assets/skills/comet/rules/comet-phase-guard.md +90 -0
  7. package/assets/skills/comet/scripts/comet-archive.sh +71 -55
  8. package/assets/skills/comet/scripts/comet-guard.sh +174 -18
  9. package/assets/skills/comet/scripts/comet-handoff.sh +133 -6
  10. package/assets/skills/comet/scripts/comet-hook-guard.sh +260 -0
  11. package/assets/skills/comet/scripts/comet-state.sh +300 -25
  12. package/assets/skills/comet/scripts/comet-yaml-validate.sh +24 -1
  13. package/assets/skills/comet-archive/SKILL.md +43 -10
  14. package/assets/skills/comet-build/SKILL.md +117 -22
  15. package/assets/skills/comet-design/SKILL.md +119 -13
  16. package/assets/skills/comet-hotfix/SKILL.md +51 -9
  17. package/assets/skills/comet-open/SKILL.md +86 -13
  18. package/assets/skills/comet-tweak/SKILL.md +33 -8
  19. package/assets/skills/comet-verify/SKILL.md +48 -9
  20. package/assets/skills-zh/comet/SKILL.md +47 -16
  21. package/assets/skills-zh/comet/reference/dirty-worktree.md +2 -1
  22. package/assets/skills-zh/comet-archive/SKILL.md +44 -11
  23. package/assets/skills-zh/comet-build/SKILL.md +120 -25
  24. package/assets/skills-zh/comet-design/SKILL.md +123 -16
  25. package/assets/skills-zh/comet-hotfix/SKILL.md +47 -9
  26. package/assets/skills-zh/comet-open/SKILL.md +87 -14
  27. package/assets/skills-zh/comet-tweak/SKILL.md +29 -8
  28. package/assets/skills-zh/comet-verify/SKILL.md +49 -12
  29. package/bin/comet.js +3 -3
  30. package/dist/commands/doctor.d.ts.map +1 -1
  31. package/dist/commands/doctor.js +22 -0
  32. package/dist/commands/doctor.js.map +1 -1
  33. package/dist/commands/init.d.ts +5 -1
  34. package/dist/commands/init.d.ts.map +1 -1
  35. package/dist/commands/init.js +64 -9
  36. package/dist/commands/init.js.map +1 -1
  37. package/dist/commands/update.d.ts.map +1 -1
  38. package/dist/commands/update.js +60 -1
  39. package/dist/commands/update.js.map +1 -1
  40. package/dist/core/codegraph.d.ts +9 -0
  41. package/dist/core/codegraph.d.ts.map +1 -0
  42. package/dist/core/codegraph.js +96 -0
  43. package/dist/core/codegraph.js.map +1 -0
  44. package/dist/core/platforms.d.ts +10 -0
  45. package/dist/core/platforms.d.ts.map +1 -1
  46. package/dist/core/platforms.js +163 -15
  47. package/dist/core/platforms.js.map +1 -1
  48. package/dist/core/skills.d.ts +34 -1
  49. package/dist/core/skills.d.ts.map +1 -1
  50. package/dist/core/skills.js +360 -1
  51. package/dist/core/skills.js.map +1 -1
  52. package/package.json +3 -1
  53. package/scripts/postinstall.js +44 -44
@@ -34,18 +34,26 @@ validate_change_name() {
34
34
  fi
35
35
  }
36
36
 
37
- validate_change_name "$1"
38
-
39
- CHANGE="$1"
40
- PHASE="$2"
41
- APPLY=0
42
- SCRIPT_DIR="$(dirname "$(readlink -f "$0" 2>/dev/null || echo "$0")" 2>/dev/null || dirname "$0")"
43
- if [[ "${3:-}" == "--apply" ]]; then
44
- APPLY=1
45
- fi
46
- CHANGE_DIR="openspec/changes/$CHANGE"
47
- if [ "$PHASE" = "archive" ] && [ ! -d "$CHANGE_DIR" ] && [ -d "openspec/changes/archive/$CHANGE" ]; then
48
- CHANGE_DIR="openspec/changes/archive/$CHANGE"
37
+ if [ "${COMET_GUARD_SOURCE_ONLY:-0}" = "1" ]; then
38
+ CHANGE="${CHANGE:-}"
39
+ PHASE="${PHASE:-}"
40
+ APPLY="${APPLY:-0}"
41
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd -P)"
42
+ CHANGE_DIR="${CHANGE_DIR:-}"
43
+ else
44
+ validate_change_name "$1"
45
+
46
+ CHANGE="$1"
47
+ PHASE="$2"
48
+ APPLY=0
49
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
50
+ if [[ "${3:-}" == "--apply" ]]; then
51
+ APPLY=1
52
+ fi
53
+ CHANGE_DIR="openspec/changes/$CHANGE"
54
+ if [ "$PHASE" = "archive" ] && [ ! -d "$CHANGE_DIR" ] && [ -d "openspec/changes/archive/$CHANGE" ]; then
55
+ CHANGE_DIR="openspec/changes/archive/$CHANGE"
56
+ fi
49
57
  fi
50
58
 
51
59
  BLOCK=0
@@ -94,6 +102,27 @@ tasks_has_any() {
94
102
  [ -f "$tasks" ] && grep -q '\- \[' "$tasks"
95
103
  }
96
104
 
105
+ plan_tasks_all_done() {
106
+ local plan
107
+ plan=$(yaml_field_value "plan" 2>/dev/null || true)
108
+
109
+ if [ -z "$plan" ] || [ "$plan" = "null" ]; then
110
+ return 0
111
+ fi
112
+ if [ ! -f "$plan" ]; then
113
+ echo "plan file is missing at $plan" >&2
114
+ echo "Next: restore the Superpowers plan file or update .comet.yaml plan before leaving build." >&2
115
+ return 1
116
+ fi
117
+ if grep -q '^[[:space:]]*- \[ \]' "$plan"; then
118
+ echo "Unfinished Superpowers plan tasks:" >&2
119
+ grep -n '^[[:space:]]*- \[ \]' "$plan" >&2 || true
120
+ echo "Next: check off corresponding completed plan tasks, then commit the plan update." >&2
121
+ return 1
122
+ fi
123
+ return 0
124
+ }
125
+
97
126
  yaml_field_value() {
98
127
  local field="$1"
99
128
  local yaml="$CHANGE_DIR/.comet.yaml"
@@ -182,6 +211,17 @@ is_windows_bash() {
182
211
 
183
212
  run_command_string() {
184
213
  local command="$1"
214
+ if [ -z "$command" ]; then
215
+ red "ERROR: build/verify command is empty" >&2
216
+ return 1
217
+ fi
218
+ # Basic command injection guard: reject dangerous shell metacharacters
219
+ # Quotes are allowed to support paths with spaces (e.g. Windows)
220
+ if [[ "$command" =~ [\;\|\&\$\`] ]]; then
221
+ red "ERROR: build/verify command contains shell metacharacters: $command" >&2
222
+ red "Allowed: alphanumeric, spaces, hyphens, underscores, dots, colons, forward slashes, quotes" >&2
223
+ return 1
224
+ fi
185
225
  echo "+ $command" >&2
186
226
  "$COMET_BASH" -lc "$command"
187
227
  }
@@ -219,12 +259,14 @@ handoff_source_files() {
219
259
  }
220
260
 
221
261
  compute_handoff_hash() {
222
- handoff_source_files | while IFS= read -r file; do
262
+ local hash_input
263
+ hash_input=$(handoff_source_files | while IFS= read -r file; do
223
264
  if [ -f "$file" ]; then
224
265
  printf 'path:%s\n' "$file"
225
266
  printf 'sha256:%s\n' "$(hash_file "$file")"
226
267
  fi
227
- done | hash_stream
268
+ done)
269
+ printf '%s' "$hash_input" | hash_stream
228
270
  }
229
271
 
230
272
  preflight() {
@@ -344,6 +386,47 @@ build_mode_allowed_for_workflow() {
344
386
  esac
345
387
  }
346
388
 
389
+ subagent_dispatch_confirmed() {
390
+ local build_mode subagent_dispatch
391
+ build_mode=$(yaml_field_value "build_mode" 2>/dev/null || true)
392
+ subagent_dispatch=$(yaml_field_value "subagent_dispatch" 2>/dev/null || true)
393
+
394
+ if [ "$build_mode" != "subagent-driven-development" ]; then
395
+ return 0
396
+ fi
397
+
398
+ if [ "$subagent_dispatch" = "confirmed" ]; then
399
+ return 0
400
+ fi
401
+
402
+ echo "subagent_dispatch must be confirmed before using build_mode=subagent-driven-development" >&2
403
+ echo "Next: confirm the current platform has a real background subagent/Task/multi-agent dispatcher, then run:" >&2
404
+ echo " \"\$COMET_BASH\" \"\$COMET_STATE\" set $CHANGE subagent_dispatch confirmed" >&2
405
+ echo "Or ask the user to switch to executing-plans and run:" >&2
406
+ echo " \"\$COMET_BASH\" \"\$COMET_STATE\" set $CHANGE build_mode executing-plans" >&2
407
+ return 1
408
+ }
409
+
410
+ tdd_mode_selected() {
411
+ local workflow tdd_mode
412
+ workflow=$(yaml_field_value "workflow" 2>/dev/null || true)
413
+ tdd_mode=$(yaml_field_value "tdd_mode" 2>/dev/null || true)
414
+
415
+ case "$workflow" in
416
+ hotfix|tweak) return 0 ;;
417
+ esac
418
+
419
+ case "$tdd_mode" in
420
+ tdd|direct) return 0 ;;
421
+ *)
422
+ echo "tdd_mode must be tdd or direct for full workflow, got '${tdd_mode:-null}'" >&2
423
+ echo "Next: ask the user to choose TDD enforcement level, then run:" >&2
424
+ echo " \"\$COMET_BASH\" \"\$COMET_STATE\" set $CHANGE tdd_mode <tdd|direct>" >&2
425
+ return 1
426
+ ;;
427
+ esac
428
+ }
429
+
347
430
  verify_result_is_pass() {
348
431
  local result
349
432
  result=$(yaml_field_value "verify_result" 2>/dev/null || true)
@@ -416,7 +499,7 @@ design_handoff_markdown_traceable() {
416
499
  echo "handoff markdown is missing Generated-by marker" >&2
417
500
  missing=1
418
501
  }
419
- grep -Eq '^- Mode: (compact|full)$' "$markdown" || {
502
+ grep -Eq '^- Mode: (compact|full|beta)$' "$markdown" || {
420
503
  echo "handoff markdown is missing Mode marker" >&2
421
504
  missing=1
422
505
  }
@@ -435,6 +518,47 @@ design_handoff_markdown_traceable() {
435
518
  [ "$missing" -eq 0 ]
436
519
  }
437
520
 
521
+ context_compression_mode() {
522
+ local mode
523
+ mode=$(yaml_field_value "context_compression" 2>/dev/null || true)
524
+ printf '%s\n' "${mode:-off}"
525
+ }
526
+
527
+ beta_spec_json_structurally_valid() {
528
+ local context missing=0
529
+ if [ "$(context_compression_mode)" != "beta" ]; then
530
+ return 0
531
+ fi
532
+
533
+ context=$(yaml_field_value "handoff_context" 2>/dev/null || true)
534
+ if [ -z "$context" ] || [ "$context" = "null" ]; then
535
+ echo "handoff_context is missing from .comet.yaml" >&2
536
+ return 1
537
+ fi
538
+ if [ ! -s "$context" ]; then
539
+ echo "spec-context.json is missing or empty: $context" >&2
540
+ return 1
541
+ fi
542
+
543
+ # Validate required JSON fields
544
+ grep -q '"change"' "$context" || { echo "spec-context.json missing 'change' field" >&2; return 1; }
545
+ grep -q '"phase"' "$context" || { echo "spec-context.json missing 'phase' field" >&2; return 1; }
546
+ grep -q '"mode": "beta"' "$context" || { echo "spec-context.json mode is not beta" >&2; return 1; }
547
+ grep -q '"files"' "$context" || { echo "spec-context.json missing 'files' field" >&2; return 1; }
548
+ grep -q '"context_hash"' "$context" || { echo "spec-context.json missing 'context_hash' field" >&2; return 1; }
549
+
550
+ # Verify all source files are referenced in the JSON
551
+ handoff_source_files | while IFS= read -r file; do
552
+ [ -f "$file" ] || continue
553
+ if ! grep -qF "$file" "$context"; then
554
+ echo "spec-context.json missing source file reference: $file" >&2
555
+ exit 2
556
+ fi
557
+ done || missing=1
558
+
559
+ [ "$missing" -eq 0 ]
560
+ }
561
+
438
562
  design_doc_frontmatter_has() {
439
563
  local design_doc="$1"
440
564
  local field="$2"
@@ -494,32 +618,55 @@ guard_open() {
494
618
  guard_design() {
495
619
  echo "=== Guard: design → build ===" >&2
496
620
 
497
- local design_doc
621
+ local design_doc workflow
498
622
  design_doc=$(yaml_field_value "design_doc" 2>/dev/null || true)
623
+ workflow=$(yaml_field_value "workflow" 2>/dev/null || true)
499
624
 
500
625
  check "proposal.md exists" file_nonempty "$CHANGE_DIR/proposal.md"
501
626
  check "design.md exists" file_nonempty "$CHANGE_DIR/design.md"
502
627
  check "tasks.md exists" file_nonempty "$CHANGE_DIR/tasks.md"
503
628
  check "design handoff context exists" design_handoff_context_valid
504
629
  check "design handoff markdown is traceable" design_handoff_markdown_traceable
630
+ if [ "$(context_compression_mode)" = "beta" ]; then
631
+ check "beta spec-context.json is structurally valid" beta_spec_json_structurally_valid
632
+ fi
633
+
634
+ if [ "$workflow" = "full" ]; then
635
+ # Full workflow: design_doc is REQUIRED
636
+ check "design_doc is recorded for full workflow" design_doc_recorded
637
+ fi
505
638
 
506
639
  if [ -n "$design_doc" ] && [ "$design_doc" != "null" ]; then
507
640
  check "Design Doc ($design_doc) exists" file_nonempty "$design_doc"
508
641
  check "Design Doc frontmatter links current change" design_doc_links_current_change
509
642
  check "Design Doc declares technical design role" design_doc_declares_technical_role
510
643
  check "Design Doc declares OpenSpec as canonical spec" design_doc_declares_canonical_spec
511
- else
512
- warn " [WARN] No design_doc recorded in .comet.yaml"
644
+ elif [ "$workflow" != "full" ]; then
645
+ warn " [WARN] No design_doc recorded in .comet.yaml (optional for hotfix/tweak)"
513
646
  fi
514
647
  }
515
648
 
649
+ design_doc_recorded() {
650
+ local design_doc
651
+ design_doc=$(yaml_field_value "design_doc" 2>/dev/null || true)
652
+ if [ -n "$design_doc" ] && [ "$design_doc" != "null" ] && [ -f "$design_doc" ]; then
653
+ return 0
654
+ fi
655
+ echo "design_doc must point to an existing Superpowers Design Doc for full workflow before leaving design." >&2
656
+ echo "Next: create the Design Doc and run: \"\$COMET_BASH\" \"\$COMET_STATE\" set $CHANGE design_doc <path>" >&2
657
+ return 1
658
+ }
659
+
516
660
  guard_build() {
517
661
  echo "=== Guard: build → verify ===" >&2
518
662
 
519
663
  check "isolation selected" isolation_selected
520
664
  check "build_mode selected" build_mode_selected
521
665
  check "build_mode allowed for workflow" build_mode_allowed_for_workflow
666
+ check "subagent dispatch confirmed" subagent_dispatch_confirmed
667
+ check "tdd_mode selected" tdd_mode_selected
522
668
  check "tasks.md all tasks checked" tasks_all_done
669
+ check "Superpowers plan all tasks checked" plan_tasks_all_done
523
670
  check "proposal.md exists" file_nonempty "$CHANGE_DIR/proposal.md"
524
671
  check "Build passes" build_passes
525
672
  }
@@ -538,6 +685,7 @@ guard_archive() {
538
685
 
539
686
  check "archived is true" archived_is_true
540
687
  check "proposal.md exists" file_nonempty "$CHANGE_DIR/proposal.md"
688
+ check "design.md exists" file_nonempty "$CHANGE_DIR/design.md"
541
689
  check "tasks.md all tasks checked" tasks_all_done
542
690
  }
543
691
 
@@ -560,6 +708,14 @@ apply_state_update() {
560
708
 
561
709
  # --- Main ---
562
710
 
711
+ if [ "${COMET_GUARD_SOURCE_ONLY:-0}" = "1" ]; then
712
+ return 0 2>/dev/null
713
+ # shellcheck disable=SC2317 # unreachable if sourced; fallback for direct execution
714
+ red "ERROR: COMET_GUARD_SOURCE_ONLY=1 is only for sourcing, not direct execution" >&2
715
+ # shellcheck disable=SC2317
716
+ exit 1
717
+ fi
718
+
563
719
  case "$PHASE" in
564
720
  open) preflight ; guard_open ;;
565
721
  design) preflight ; guard_design ;;
@@ -1,6 +1,7 @@
1
1
  #!/bin/bash
2
2
  # Comet Handoff — creates machine-owned context packages between phases
3
3
  # Usage: comet-handoff.sh <change-name> design --write [--full]
4
+ # comet-handoff.sh <change-name> --hash-only
4
5
 
5
6
  set -euo pipefail
6
7
 
@@ -8,6 +9,7 @@ COMET_BASH="${COMET_BASH:-${BASH:-bash}}"
8
9
 
9
10
  red() { echo -e "\033[31m$1\033[0m" >&2; }
10
11
  green() { echo -e "\033[32m$1\033[0m" >&2; }
12
+ warn() { echo -e "\033[33m$1\033[0m" >&2; }
11
13
 
12
14
  validate_change_name() {
13
15
  local name="$1"
@@ -103,12 +105,14 @@ source_files() {
103
105
  }
104
106
 
105
107
  compute_context_hash() {
106
- source_files | while IFS= read -r file; do
108
+ local hash_input
109
+ hash_input=$(source_files | while IFS= read -r file; do
107
110
  if [ -f "$file" ]; then
108
111
  printf 'path:%s\n' "$file"
109
112
  printf 'sha256:%s\n' "$(hash_file "$file")"
110
113
  fi
111
- done | hash_stream
114
+ done)
115
+ printf '%s' "$hash_input" | hash_stream
112
116
  }
113
117
 
114
118
  json_escape() {
@@ -196,6 +200,86 @@ write_json_context() {
196
200
  } > "$output"
197
201
  }
198
202
 
203
+ write_spec_projection_for_file() {
204
+ local file="$1"
205
+ echo "## $file"
206
+ echo ""
207
+ echo "- Source: $file"
208
+ echo "- Lines: 1-$(file_line_count "$file")"
209
+ echo "- SHA256: $(hash_file "$file")"
210
+ echo ""
211
+ echo '```md'
212
+ cat "$file"
213
+ echo '```'
214
+ echo ""
215
+ }
216
+
217
+ write_spec_markdown_context() {
218
+ local output="$1"
219
+ {
220
+ echo "# Comet Spec Context"
221
+ echo ""
222
+ echo "- Change: $CHANGE"
223
+ echo "- Phase: design"
224
+ echo "- Mode: beta"
225
+ echo "- Context hash: $CONTEXT_HASH"
226
+ echo ""
227
+ echo "Generated-by: comet-handoff.sh"
228
+ echo ""
229
+ echo "OpenSpec remains the canonical capability spec. This beta context pack verbatim-projects spec files and references supporting artifacts by hash, not an agent-authored summary."
230
+ echo ""
231
+ echo "## Source References"
232
+ echo ""
233
+ source_files | while IFS= read -r file; do
234
+ [ -f "$file" ] || continue
235
+ echo "- Source: $file"
236
+ echo "- SHA256: $(hash_file "$file")"
237
+ done
238
+ echo ""
239
+ echo "## Acceptance Projection"
240
+ echo ""
241
+ if [ -d "$CHANGE_DIR/specs" ]; then
242
+ find "$CHANGE_DIR/specs" -path '*/spec.md' -type f 2>/dev/null | sort | while IFS= read -r file; do
243
+ write_spec_projection_for_file "$file"
244
+ done
245
+ else
246
+ echo "No delta spec files found."
247
+ echo ""
248
+ fi
249
+ echo "Full source files remain canonical. If a required heading or scenario is missing here, regenerate the handoff or read the source spec directly. Supporting files (proposal, design, tasks) are referenced by hash only."
250
+ } > "$output"
251
+ }
252
+
253
+ write_spec_json_context() {
254
+ local output="$1"
255
+ {
256
+ echo "{"
257
+ echo " \"change\": \"$(json_escape "$CHANGE")\","
258
+ echo " \"phase\": \"design\","
259
+ echo " \"mode\": \"beta\","
260
+ echo " \"canonical_spec\": \"openspec\","
261
+ echo " \"generated_by\": \"comet-handoff.sh\","
262
+ echo " \"context_hash\": \"$CONTEXT_HASH\","
263
+ echo " \"files\": ["
264
+ local first_file=1
265
+ while IFS= read -r file; do
266
+ [ -f "$file" ] || continue
267
+ local role="supporting"
268
+ case "$file" in
269
+ */specs/*/spec.md) role="spec" ;;
270
+ esac
271
+ if [ "$first_file" -eq 0 ]; then
272
+ echo ","
273
+ fi
274
+ first_file=0
275
+ printf ' { "path": "%s", "sha256": "%s", "role": "%s" }' "$(json_escape "$file")" "$(hash_file "$file")" "$role"
276
+ done < <(source_files)
277
+ echo ""
278
+ echo " ]"
279
+ echo "}"
280
+ } > "$output"
281
+ }
282
+
199
283
  CHANGE="${1:-}"
200
284
  PHASE="${2:-}"
201
285
  MODE="${3:-}"
@@ -203,6 +287,25 @@ FULL_FLAG="${4:-}"
203
287
 
204
288
  validate_change_name "$CHANGE"
205
289
 
290
+ # --hash-only: compute and output context hash without generating handoff files
291
+ if [ "${PHASE:-}" = "--hash-only" ]; then
292
+ CHANGE_DIR="openspec/changes/$CHANGE"
293
+ if [ ! -d "$CHANGE_DIR" ]; then
294
+ red "ERROR: change directory not found: $CHANGE_DIR"
295
+ exit 1
296
+ fi
297
+ for required in proposal.md design.md tasks.md; do
298
+ if [ ! -s "$CHANGE_DIR/$required" ]; then
299
+ red "ERROR: required file missing or empty: $CHANGE_DIR/$required"
300
+ exit 1
301
+ fi
302
+ done
303
+ CONTEXT_HASH="$(compute_context_hash)"
304
+ printf '%s
305
+ ' "$CONTEXT_HASH"
306
+ exit 0
307
+ fi
308
+
206
309
  if [ "$PHASE" != "design" ] || [ "$MODE" != "--write" ]; then
207
310
  red "Usage: comet-handoff.sh <change-name> design --write [--full]"
208
311
  exit 1
@@ -242,13 +345,37 @@ for required in proposal.md design.md tasks.md; do
242
345
  done
243
346
 
244
347
  HANDOFF_DIR="$CHANGE_DIR/.comet/handoff"
245
- CONTEXT_JSON="$HANDOFF_DIR/design-context.json"
246
- CONTEXT_MD="$HANDOFF_DIR/design-context.md"
348
+ CONTEXT_COMPRESSION="$(yaml_field_value context_compression 2>/dev/null || true)"
349
+ CONTEXT_COMPRESSION="${CONTEXT_COMPRESSION:-off}"
350
+ case "$CONTEXT_COMPRESSION" in
351
+ off)
352
+ CONTEXT_JSON="$HANDOFF_DIR/design-context.json"
353
+ CONTEXT_MD="$HANDOFF_DIR/design-context.md"
354
+ ;;
355
+ beta)
356
+ if [ "$HANDOFF_MODE" = "full" ]; then
357
+ warn "[HANDOFF] --full is ignored in beta mode; spec files are projected verbatim"
358
+ fi
359
+ HANDOFF_MODE="beta"
360
+ CONTEXT_JSON="$HANDOFF_DIR/spec-context.json"
361
+ CONTEXT_MD="$HANDOFF_DIR/spec-context.md"
362
+ ;;
363
+ *)
364
+ red "ERROR: invalid context_compression: $CONTEXT_COMPRESSION"
365
+ red "Valid values: off, beta"
366
+ exit 1
367
+ ;;
368
+ esac
247
369
  mkdir -p "$HANDOFF_DIR"
248
370
 
249
371
  CONTEXT_HASH="$(compute_context_hash)"
250
- write_markdown_context "$CONTEXT_MD"
251
- write_json_context "$CONTEXT_JSON"
372
+ if [ "$CONTEXT_COMPRESSION" = "beta" ]; then
373
+ write_spec_markdown_context "$CONTEXT_MD"
374
+ write_spec_json_context "$CONTEXT_JSON"
375
+ else
376
+ write_markdown_context "$CONTEXT_MD"
377
+ write_json_context "$CONTEXT_JSON"
378
+ fi
252
379
 
253
380
  if [ -x "$STATE_SH" ] || [ -f "$STATE_SH" ]; then
254
381
  "$COMET_BASH" "$STATE_SH" set "$CHANGE" handoff_context "$CONTEXT_JSON" >/dev/null