@rpamis/comet 0.3.7 → 0.3.9
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/LICENSE +21 -21
- package/README.md +557 -539
- package/assets/manifest.json +41 -34
- package/assets/skills/comet/SKILL.md +282 -329
- 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 +59 -59
- 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 +123 -0
- package/assets/skills/comet/rules/comet-phase-guard.md +125 -90
- package/assets/skills/comet/scripts/comet-guard.sh +27 -1
- package/assets/skills/comet/scripts/comet-hook-guard.sh +121 -45
- package/assets/skills/comet/scripts/comet-state.sh +162 -7
- package/assets/skills/comet/scripts/comet-yaml-validate.sh +3 -1
- package/assets/skills/comet-archive/SKILL.md +100 -106
- package/assets/skills/comet-build/SKILL.md +304 -316
- package/assets/skills/comet-design/SKILL.md +263 -272
- package/assets/skills/comet-hotfix/SKILL.md +204 -211
- package/assets/skills/comet-open/SKILL.md +220 -186
- package/assets/skills/comet-tweak/SKILL.md +180 -179
- package/assets/skills/comet-verify/SKILL.md +234 -240
- package/assets/skills-zh/comet/SKILL.md +269 -332
- package/assets/skills-zh/comet/reference/auto-transition.md +27 -0
- package/assets/skills-zh/comet/reference/comet-yaml-fields.md +71 -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 +59 -59
- package/assets/skills-zh/comet/reference/file-structure.md +28 -0
- package/assets/skills-zh/comet/reference/subagent-dispatch.md +120 -0
- package/assets/skills-zh/comet-archive/SKILL.md +100 -106
- package/assets/skills-zh/comet-build/SKILL.md +317 -316
- package/assets/skills-zh/comet-design/SKILL.md +264 -273
- package/assets/skills-zh/comet-hotfix/SKILL.md +200 -207
- package/assets/skills-zh/comet-open/SKILL.md +220 -186
- package/assets/skills-zh/comet-tweak/SKILL.md +176 -175
- package/assets/skills-zh/comet-verify/SKILL.md +232 -238
- package/bin/comet.js +3 -3
- package/dist/cli/index.js +21 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +5 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/i18n.d.ts +4 -0
- package/dist/commands/i18n.d.ts.map +1 -0
- package/dist/commands/i18n.js +154 -0
- package/dist/commands/i18n.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +127 -75
- 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 +132 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.d.ts +3 -2
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +105 -68
- package/dist/commands/update.js.map +1 -1
- package/dist/core/codegraph.d.ts +4 -7
- package/dist/core/codegraph.d.ts.map +1 -1
- package/dist/core/codegraph.js +63 -41
- package/dist/core/codegraph.js.map +1 -1
- package/dist/core/detect.d.ts +13 -1
- package/dist/core/detect.d.ts.map +1 -1
- package/dist/core/detect.js +68 -12
- package/dist/core/detect.js.map +1 -1
- package/dist/core/openspec.d.ts +2 -2
- package/dist/core/openspec.d.ts.map +1 -1
- package/dist/core/openspec.js +51 -22
- package/dist/core/openspec.js.map +1 -1
- package/dist/core/platforms.d.ts.map +1 -1
- package/dist/core/platforms.js +14 -1
- package/dist/core/platforms.js.map +1 -1
- package/dist/core/skills.d.ts +3 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +151 -66
- package/dist/core/skills.js.map +1 -1
- package/dist/core/superpowers.d.ts +1 -1
- package/dist/core/superpowers.d.ts.map +1 -1
- package/dist/core/superpowers.js +5 -1
- 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 -64
- package/scripts/postinstall.js +44 -44
|
@@ -1,90 +1,125 @@
|
|
|
1
|
-
# Comet 阶段感知(防漂移规则)
|
|
2
|
-
|
|
3
|
-
> 此规则每轮注入,防止长上下文时遗忘 Comet 流程状态。
|
|
4
|
-
> Hook 平台额外执行 `comet-hook-guard.sh` 进行硬性拦截;
|
|
5
|
-
> 此 Rule 是所有平台通用的软性防线。
|
|
6
|
-
|
|
7
|
-
## 全局规则
|
|
8
|
-
|
|
9
|
-
### 阶段感知(最高优先级)
|
|
10
|
-
|
|
11
|
-
有活跃 comet change 时(`openspec/changes/<name>/.comet.yaml` 存在),**每次开始执行操作前**必须读取 `phase` 字段确认当前阶段。
|
|
12
|
-
|
|
13
|
-
**阶段与允许操作:**
|
|
14
|
-
|
|
15
|
-
| 阶段 | 允许 | 禁止 |
|
|
16
|
-
|------|------|------|
|
|
17
|
-
| `open` | 创建 proposal/design/tasks, 运行 guard | 写源代码 |
|
|
18
|
-
| `design` | brainstorming, 创建 Design Doc, 运行 guard | 写源代码 |
|
|
19
|
-
| `build` | 写源代码、测试、执行计划 | 跳过用户确认点 |
|
|
20
|
-
| `verify` | 验证、branch handling | 跳过失败处理 |
|
|
21
|
-
| `archive` | 确认归档、运行归档脚本 | 写源代码 |
|
|
22
|
-
|
|
23
|
-
###
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
###
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
- **
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
##
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
1
|
+
# Comet 阶段感知(防漂移规则)
|
|
2
|
+
|
|
3
|
+
> 此规则每轮注入,防止长上下文时遗忘 Comet 流程状态。
|
|
4
|
+
> Hook 平台额外执行 `comet-hook-guard.sh` 进行硬性拦截;
|
|
5
|
+
> 此 Rule 是所有平台通用的软性防线。
|
|
6
|
+
|
|
7
|
+
## 全局规则
|
|
8
|
+
|
|
9
|
+
### 阶段感知(最高优先级)
|
|
10
|
+
|
|
11
|
+
有活跃 comet change 时(`openspec/changes/<name>/.comet.yaml` 存在),**每次开始执行操作前**必须读取 `phase` 字段确认当前阶段。
|
|
12
|
+
|
|
13
|
+
**阶段与允许操作:**
|
|
14
|
+
|
|
15
|
+
| 阶段 | 允许 | 禁止 |
|
|
16
|
+
|------|------|------|
|
|
17
|
+
| `open` | 创建 proposal/design/tasks, 运行 guard | 写源代码 |
|
|
18
|
+
| `design` | brainstorming, 创建 Design Doc, 运行 guard | 写源代码 |
|
|
19
|
+
| `build` | 写源代码、测试、执行计划 | 跳过用户确认点 |
|
|
20
|
+
| `verify` | 验证、branch handling | 跳过失败处理 |
|
|
21
|
+
| `archive` | 确认归档、运行归档脚本 | 写源代码 |
|
|
22
|
+
|
|
23
|
+
### 阶段进入自洽性校验(写源代码前必查)
|
|
24
|
+
|
|
25
|
+
仅看 `phase` 字段不够——还必须确认"是如何到达这个阶段的"。每次准备写源代码前,先用下表自检 `.comet.yaml` 是否处于**非法空跳**状态(绕过了前置阶段)。命中任一行,立即停止写源代码,按动作回到对应阶段补齐产物,不得信任 `phase` 字段直接续跑。
|
|
26
|
+
|
|
27
|
+
| 检测到 | 判定 | 动作 |
|
|
28
|
+
|--------|------|------|
|
|
29
|
+
| `phase: build` + `workflow: full` + `design_doc` 为空/null | 绕过 design 空跳 | 停止写源代码,运行 `/comet-design` 补 Design Doc 并过 guard |
|
|
30
|
+
| `phase: build/verify` + proposal/design/tasks 任一缺失或为空 | 绕过 open 空跳 | 回 `/comet-open` 补齐三件套 |
|
|
31
|
+
| `phase: archive` + `verify_result` ≠ `pass` | 绕过 verify 空跳 | 回 `/comet-verify` 完成验证 |
|
|
32
|
+
|
|
33
|
+
预设例外:`workflow: hotfix/tweak` 本就跳过 design,`design_doc` 为空属正常,不算非法。
|
|
34
|
+
|
|
35
|
+
### Skill 调用(不可用普通对话替代)
|
|
36
|
+
|
|
37
|
+
以下操作必须通过 Skill 工具加载,Skill 不可用时应停止流程并提示安装:
|
|
38
|
+
|
|
39
|
+
- **brainstorming** — design 阶段、build 阶段中等规模 spec 变更
|
|
40
|
+
- **writing-plans** — build 阶段创建实现计划
|
|
41
|
+
- **executing-plans** / **subagent-driven-development** — build 阶段执行
|
|
42
|
+
- **test-driven-development** — `executing-plans` 由主会话在第一个 task 前加载;`subagent-driven-development` 由每个后台 implementer 和修复 agent 加载
|
|
43
|
+
- **systematic-debugging** — 遇到崩溃/测试失败/构建失败时
|
|
44
|
+
- **verification-before-completion** — verify 阶段
|
|
45
|
+
- **using-git-worktrees** — build 阶段选择 worktree 隔离时
|
|
46
|
+
|
|
47
|
+
### 脚本执行(不可跳过)
|
|
48
|
+
|
|
49
|
+
- **阶段退出**: `comet-guard <name> <phase> --apply`(必须看到 ALL CHECKS PASSED)
|
|
50
|
+
- **压缩恢复**: `comet-state check <name> <phase> --recover`
|
|
51
|
+
- **状态更新**: 关键操作后通过 `comet-state set` 更新字段,禁止手工编辑 .comet.yaml
|
|
52
|
+
- **阶段推进只能经 guard/transition**: 禁止用 `comet-state set <name> phase <值>` 手动跳阶段(会绕过证据校验,脚本已硬拦截);确需修复畸形状态时才用 `COMET_FORCE_PHASE=1` 逃生阀
|
|
53
|
+
- **handoff 生成**: `comet-handoff <name> design --write`(禁止手写摘要)
|
|
54
|
+
|
|
55
|
+
### 用户确认(不可自动跳过)
|
|
56
|
+
|
|
57
|
+
以下决策点必须暂停等待用户明确选择,不得根据推荐规则自动填写:
|
|
58
|
+
|
|
59
|
+
- **open**: 需求澄清完成确认、artifact 评审确认
|
|
60
|
+
- **design**: brainstorming 方案确认(确认前不得创建 Design Doc)
|
|
61
|
+
- **build**: plan-ready 暂停、isolation/build_mode/tdd_mode 选择、spec 大规模变更确认
|
|
62
|
+
- **verify**: 验证失败处理策略、branch handling 选择
|
|
63
|
+
- **archive**: 归档前最终确认
|
|
64
|
+
|
|
65
|
+
## Design 阶段专项
|
|
66
|
+
|
|
67
|
+
1. 第一个脚本操作 = `comet-handoff <name> design --write`(未生成 handoff 禁止加载 brainstorming)
|
|
68
|
+
2. brainstorming in progress: incrementally update brainstorm-summary.md(每轮澄清或方案迭代后增量更新恢复检查点,未确认内容标注为待确认/候选)
|
|
69
|
+
3. brainstorming 完成后下一步 = brainstorm-summary.md 定稿 → Design Doc → guard
|
|
70
|
+
4. active compaction gate: brainstorm-summary.md 定稿后、创建 Design Doc 前,优先触发宿主平台原生上下文压缩;无法程序化触发时暂停提示用户手动压缩或确认继续
|
|
71
|
+
5. **绝对不能直接开始写实现代码** — 必须先创建 Design Doc 并通过 guard
|
|
72
|
+
|
|
73
|
+
## Build 阶段专项
|
|
74
|
+
|
|
75
|
+
1. plan 创建后必须询问用户选择继续或暂停(`build_pause` 机制)
|
|
76
|
+
2. 每个 task 验收后必须: tasks.md 打勾 → git commit(不得积攒)。`subagent-driven-development` 必须等 spec compliance 与 code quality 两个审查都通过,再由协调者按任务唯一文本定向勾选和验证;不得用未完成任务总表代替当前任务验证
|
|
77
|
+
3. 遇到失败必须加载 **systematic-debugging** skill,根因未定位前不得提出源码修复
|
|
78
|
+
4. spec 变更分级: 小改直接编辑 | 中改加载 brainstorming | 大改暂停等用户确认拆分
|
|
79
|
+
|
|
80
|
+
## Verify 阶段专项
|
|
81
|
+
|
|
82
|
+
1. 第一步运行 `comet-state scale <name>` 确定验证级别
|
|
83
|
+
2. 验证失败后列出失败项等用户选择,CRITICAL 必须修
|
|
84
|
+
3. 连续 3 次失败后必须让用户选择接受偏差或继续修
|
|
85
|
+
|
|
86
|
+
## 上下文压缩恢复
|
|
87
|
+
|
|
88
|
+
如果怀疑发生上下文压缩(之前对话被摘要、找不到之前讨论的内容),立即运行:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
"$COMET_BASH" "$COMET_STATE" check <name> <phase> --recover
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
按脚本输出的 **Recovery action** 决定下一步。
|
|
95
|
+
|
|
96
|
+
恢复后必须先用「阶段进入自洽性校验」表复查一遍:若发现 `phase` 与产物不自洽(design_doc/三件套/verify_result 任一不匹配),按非法空跳处理,回对应阶段补齐,不得信任 `phase` 字段直接续跑。
|
|
97
|
+
|
|
98
|
+
**特别注意 `build_mode`**:若恢复脚本输出 `build_mode: subagent-driven-development`,你是协调者,不是执行者。必须:
|
|
99
|
+
1. 使用 Skill 工具重新加载 Superpowers `subagent-driven-development` 技能 (Use the Skill tool to reload the Superpowers `subagent-driven-development` skill)
|
|
100
|
+
2. 读取 `comet/reference/subagent-dispatch.md` 获取 Comet 专属扩展 (re-read `comet/reference/subagent-dispatch.md` for Comet-specific extensions)
|
|
101
|
+
3. 读取 `openspec/changes/<name>/.comet/subagent-progress.md` 恢复精确阶段、证据和审查-修复轮次 (Read `openspec/changes/<name>/.comet/subagent-progress.md` to recover the exact stage, evidence, and review-fix round)
|
|
102
|
+
4. 禁止在主会话中直接执行 task (Do not execute the pending task directly in the main window)
|
|
103
|
+
5. 按检查点恢复;缺失或不匹配时才从第一个未勾选 task 开始
|
|
104
|
+
6. 已提交但未通过双审查的 task 保持未勾选,继续审查/修复循环
|
|
105
|
+
7. task 通过双审查和定向勾选验证后立即继续下一个 task,不得总结或询问是否继续
|
|
106
|
+
|
|
107
|
+
## 阶段退出后自动过渡
|
|
108
|
+
|
|
109
|
+
guard `--apply` 成功后,不得在本规则中硬编码下一阶段 skill。必须先运行:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
comet-state next <change-name>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
若已通过 `comet-env.sh` 定位脚本,等价运行:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
"$COMET_BASH" "$COMET_STATE" next <change-name>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
按脚本输出决定下一步:
|
|
122
|
+
|
|
123
|
+
- `NEXT: auto` → 使用 Skill 工具加载 `SKILL` 指向的 skill
|
|
124
|
+
- `NEXT: manual` → 不加载下一 skill,按 `HINT` 提示用户手动继续
|
|
125
|
+
- `NEXT: done` → 流程已完成,无需继续
|
|
@@ -427,6 +427,26 @@ tdd_mode_selected() {
|
|
|
427
427
|
esac
|
|
428
428
|
}
|
|
429
429
|
|
|
430
|
+
review_mode_selected() {
|
|
431
|
+
local workflow review_mode
|
|
432
|
+
workflow=$(yaml_field_value "workflow" 2>/dev/null || true)
|
|
433
|
+
review_mode=$(yaml_field_value "review_mode" 2>/dev/null || true)
|
|
434
|
+
|
|
435
|
+
case "$workflow" in
|
|
436
|
+
hotfix|tweak) return 0 ;;
|
|
437
|
+
esac
|
|
438
|
+
|
|
439
|
+
case "$review_mode" in
|
|
440
|
+
off|standard|thorough) return 0 ;;
|
|
441
|
+
*)
|
|
442
|
+
echo "review_mode must be off, standard, or thorough before leaving build, got '${review_mode:-null}'" >&2
|
|
443
|
+
echo "Next: ask the user to choose code review mode, then run:" >&2
|
|
444
|
+
echo " \"\$COMET_BASH\" \"\$COMET_STATE\" set $CHANGE review_mode <off|standard|thorough>" >&2
|
|
445
|
+
return 1
|
|
446
|
+
;;
|
|
447
|
+
esac
|
|
448
|
+
}
|
|
449
|
+
|
|
430
450
|
verify_result_is_pass() {
|
|
431
451
|
local result
|
|
432
452
|
result=$(yaml_field_value "verify_result" 2>/dev/null || true)
|
|
@@ -609,8 +629,13 @@ archived_is_true() {
|
|
|
609
629
|
guard_open() {
|
|
610
630
|
echo "=== Guard: open → next ===" >&2
|
|
611
631
|
|
|
632
|
+
local workflow
|
|
633
|
+
workflow=$(yaml_field_value "workflow" 2>/dev/null || true)
|
|
634
|
+
|
|
612
635
|
check "proposal.md exists and non-empty" file_nonempty "$CHANGE_DIR/proposal.md"
|
|
613
|
-
|
|
636
|
+
if [ "$workflow" = "full" ]; then
|
|
637
|
+
check "design.md exists and non-empty" file_nonempty "$CHANGE_DIR/design.md"
|
|
638
|
+
fi
|
|
614
639
|
check "tasks.md exists and non-empty" file_nonempty "$CHANGE_DIR/tasks.md"
|
|
615
640
|
check "tasks.md has at least one task" tasks_has_any
|
|
616
641
|
}
|
|
@@ -665,6 +690,7 @@ guard_build() {
|
|
|
665
690
|
check "build_mode allowed for workflow" build_mode_allowed_for_workflow
|
|
666
691
|
check "subagent dispatch confirmed" subagent_dispatch_confirmed
|
|
667
692
|
check "tdd_mode selected" tdd_mode_selected
|
|
693
|
+
check "review_mode selected" review_mode_selected
|
|
668
694
|
check "tasks.md all tasks checked" tasks_all_done
|
|
669
695
|
check "Superpowers plan all tasks checked" plan_tasks_all_done
|
|
670
696
|
check "proposal.md exists" file_nonempty "$CHANGE_DIR/proposal.md"
|
|
@@ -50,41 +50,6 @@ fi
|
|
|
50
50
|
# Normalize to forward slashes, collapse doubles from JSON escaping (\\ → //)
|
|
51
51
|
TARGET=$(printf '%s' "$TARGET" | sed 's|\\|/|g' | sed 's|///*|/|g')
|
|
52
52
|
|
|
53
|
-
# ── Find active Comet change ─────────────────────────────────────
|
|
54
|
-
|
|
55
|
-
YAML_FILE=""
|
|
56
|
-
if [ -d "openspec/changes" ]; then
|
|
57
|
-
for dir in openspec/changes/*/; do
|
|
58
|
-
[ -d "$dir" ] || continue
|
|
59
|
-
# Skip archived changes
|
|
60
|
-
case "$dir" in
|
|
61
|
-
*/archive/*) continue ;;
|
|
62
|
-
esac
|
|
63
|
-
if [ -f "${dir}.comet.yaml" ]; then
|
|
64
|
-
YAML_FILE="${dir}.comet.yaml"
|
|
65
|
-
break
|
|
66
|
-
fi
|
|
67
|
-
done
|
|
68
|
-
fi
|
|
69
|
-
|
|
70
|
-
# No active change — allow all writes
|
|
71
|
-
if [ -z "$YAML_FILE" ]; then
|
|
72
|
-
echo "[COMET-HOOK] allowed: no active comet change" >&2
|
|
73
|
-
exit 0
|
|
74
|
-
fi
|
|
75
|
-
|
|
76
|
-
# ── Read current phase ───────────────────────────────────────────
|
|
77
|
-
|
|
78
|
-
PHASE=$(grep "^phase:" "$YAML_FILE" 2>/dev/null \
|
|
79
|
-
| awk '{print $2}' \
|
|
80
|
-
| tr -d '[:space:][:cntrl:]' \
|
|
81
|
-
|| true)
|
|
82
|
-
|
|
83
|
-
if [ -z "$PHASE" ]; then
|
|
84
|
-
echo "[COMET-HOOK] allowed: no phase in .comet.yaml" >&2
|
|
85
|
-
exit 0
|
|
86
|
-
fi
|
|
87
|
-
|
|
88
53
|
# ── Resolve to project-relative path ─────────────────────────────
|
|
89
54
|
|
|
90
55
|
# Normalize helper: forward slashes only
|
|
@@ -120,6 +85,95 @@ case "$RELPATH" in
|
|
|
120
85
|
;;
|
|
121
86
|
esac
|
|
122
87
|
|
|
88
|
+
# ── Helpers to read .comet.yaml fields ───────────────────────────
|
|
89
|
+
|
|
90
|
+
is_archived() {
|
|
91
|
+
grep "^archived:" "$1" 2>/dev/null \
|
|
92
|
+
| awk '{print $2}' | tr -d '[:space:][:cntrl:]' || true
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
read_phase() {
|
|
96
|
+
grep "^phase:" "$1" 2>/dev/null \
|
|
97
|
+
| awk '{print $2}' | tr -d '[:space:][:cntrl:]' || true
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
read_field() {
|
|
101
|
+
grep "^$1:" "$2" 2>/dev/null \
|
|
102
|
+
| head -1 | awk '{print $2}' | tr -d '[:space:][:cntrl:]' || true
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
# ── Determine the governing Comet change + phase ─────────────────
|
|
106
|
+
#
|
|
107
|
+
# A write targeting a specific change directory (openspec/changes/<name>/...)
|
|
108
|
+
# must be governed by THAT change's own phase — never by an unrelated
|
|
109
|
+
# active change. Otherwise a change left in the `archive` phase would
|
|
110
|
+
# wrongly block artifact writes for a brand-new change created alongside it.
|
|
111
|
+
|
|
112
|
+
PHASE=""
|
|
113
|
+
# Path to the .comet.yaml that governs this write (used for deeper invariant checks)
|
|
114
|
+
GOV_YAML=""
|
|
115
|
+
|
|
116
|
+
case "$RELPATH" in
|
|
117
|
+
openspec/changes/*/*)
|
|
118
|
+
_rest="${RELPATH#openspec/changes/}"
|
|
119
|
+
_own_change="${_rest%%/*}"
|
|
120
|
+
if [ -n "$_own_change" ] && [ "$_own_change" != "archive" ]; then
|
|
121
|
+
_own_yaml="openspec/changes/${_own_change}/.comet.yaml"
|
|
122
|
+
if [ -f "$_own_yaml" ]; then
|
|
123
|
+
if [ "$(is_archived "$_own_yaml")" = "true" ]; then
|
|
124
|
+
# This change is already archived — its own writes are unrestricted
|
|
125
|
+
echo "[COMET-HOOK] allowed: $RELPATH (own change archived)" >&2
|
|
126
|
+
exit 0
|
|
127
|
+
fi
|
|
128
|
+
PHASE=$(read_phase "$_own_yaml")
|
|
129
|
+
GOV_YAML="$_own_yaml"
|
|
130
|
+
else
|
|
131
|
+
# Change directory exists but state file not yet written
|
|
132
|
+
# (artifacts are created before .comet.yaml during /comet-open).
|
|
133
|
+
# Treat as `open` so proposal/design/tasks/specs are allowed.
|
|
134
|
+
PHASE="open"
|
|
135
|
+
fi
|
|
136
|
+
fi
|
|
137
|
+
;;
|
|
138
|
+
esac
|
|
139
|
+
|
|
140
|
+
# Fallback: writes outside a specific change directory are governed by
|
|
141
|
+
# the first active (non-archived) change.
|
|
142
|
+
if [ -z "$PHASE" ]; then
|
|
143
|
+
YAML_FILE=""
|
|
144
|
+
if [ -d "openspec/changes" ]; then
|
|
145
|
+
for dir in openspec/changes/*/; do
|
|
146
|
+
[ -d "$dir" ] || continue
|
|
147
|
+
# Skip archived changes directory
|
|
148
|
+
case "$dir" in
|
|
149
|
+
*/archive/*) continue ;;
|
|
150
|
+
esac
|
|
151
|
+
if [ -f "${dir}.comet.yaml" ]; then
|
|
152
|
+
# Skip changes already marked as archived
|
|
153
|
+
if [ "$(is_archived "${dir}.comet.yaml")" = "true" ]; then
|
|
154
|
+
continue
|
|
155
|
+
fi
|
|
156
|
+
YAML_FILE="${dir}.comet.yaml"
|
|
157
|
+
break
|
|
158
|
+
fi
|
|
159
|
+
done
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
# No active change — allow all writes
|
|
163
|
+
if [ -z "$YAML_FILE" ]; then
|
|
164
|
+
echo "[COMET-HOOK] allowed: no active comet change" >&2
|
|
165
|
+
exit 0
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
PHASE=$(read_phase "$YAML_FILE")
|
|
169
|
+
GOV_YAML="$YAML_FILE"
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
if [ -z "$PHASE" ]; then
|
|
173
|
+
echo "[COMET-HOOK] allowed: no phase in .comet.yaml" >&2
|
|
174
|
+
exit 0
|
|
175
|
+
fi
|
|
176
|
+
|
|
123
177
|
# ── Whitelist: phase-aware allowed paths ─────────────────────────
|
|
124
178
|
|
|
125
179
|
case "$RELPATH" in
|
|
@@ -222,6 +276,28 @@ esac
|
|
|
222
276
|
|
|
223
277
|
case "$PHASE" in
|
|
224
278
|
build|verify)
|
|
279
|
+
# Full workflow must have a Design Doc before any source write in build/verify.
|
|
280
|
+
# Catches illegal open→build / design→build jumps that skipped the design phase
|
|
281
|
+
# (e.g. misclassified preset, direct `set phase`, or bare transition).
|
|
282
|
+
if [ -n "$GOV_YAML" ]; then
|
|
283
|
+
_wf=$(read_field "workflow" "$GOV_YAML")
|
|
284
|
+
_dd=$(read_field "design_doc" "$GOV_YAML")
|
|
285
|
+
if [ "$_wf" = "full" ] && { [ -z "$_dd" ] || [ "$_dd" = "null" ]; }; then
|
|
286
|
+
echo "" >&2
|
|
287
|
+
echo "╔══════════════════════════════════════════╗" >&2
|
|
288
|
+
echo "║ COMET PHASE GUARD — WRITE BLOCKED ║" >&2
|
|
289
|
+
echo "╚══════════════════════════════════════════╝" >&2
|
|
290
|
+
echo "" >&2
|
|
291
|
+
echo " Current phase: $PHASE (workflow: full), but design_doc is empty" >&2
|
|
292
|
+
echo " Target file: $RELPATH" >&2
|
|
293
|
+
echo "" >&2
|
|
294
|
+
echo " ❌ Illegal phase jump detected: full workflow entered $PHASE without a Design Doc" >&2
|
|
295
|
+
echo " ✅ Correct flow: create the Design Doc in design phase, then run comet-guard design --apply" >&2
|
|
296
|
+
echo " 💡 Run /comet-design to fill the missing design; for repair, set design_doc with comet-state" >&2
|
|
297
|
+
echo "" >&2
|
|
298
|
+
exit 2
|
|
299
|
+
fi
|
|
300
|
+
fi
|
|
225
301
|
# Code writes allowed in build and verify
|
|
226
302
|
echo "[COMET-HOOK] allowed: $RELPATH (phase: $PHASE)" >&2
|
|
227
303
|
exit 0
|
|
@@ -232,23 +308,23 @@ case "$PHASE" in
|
|
|
232
308
|
echo "║ COMET PHASE GUARD — WRITE BLOCKED ║" >&2
|
|
233
309
|
echo "╚══════════════════════════════════════════╝" >&2
|
|
234
310
|
echo "" >&2
|
|
235
|
-
echo "
|
|
236
|
-
echo "
|
|
311
|
+
echo " Current phase: $PHASE" >&2
|
|
312
|
+
echo " Target file: $RELPATH" >&2
|
|
237
313
|
echo "" >&2
|
|
238
314
|
case "$PHASE" in
|
|
239
315
|
open)
|
|
240
|
-
echo " ❌ open
|
|
241
|
-
echo " ✅
|
|
242
|
-
echo " 💡
|
|
316
|
+
echo " ❌ open phase does not allow source code writes" >&2
|
|
317
|
+
echo " ✅ Allowed: create proposal/design/tasks and run guard" >&2
|
|
318
|
+
echo " 💡 After clarification and artifact creation, run guard --apply" >&2
|
|
243
319
|
;;
|
|
244
320
|
design)
|
|
245
|
-
echo " ❌ design
|
|
246
|
-
echo " ✅
|
|
247
|
-
echo " 💡
|
|
321
|
+
echo " ❌ design phase does not allow source code writes" >&2
|
|
322
|
+
echo " ✅ Allowed: brainstorming, create the Design Doc, and run guard" >&2
|
|
323
|
+
echo " 💡 After the Design Doc is ready, run comet-guard design --apply to enter build" >&2
|
|
248
324
|
;;
|
|
249
325
|
archive)
|
|
250
|
-
echo " ❌ archive
|
|
251
|
-
echo " ✅
|
|
326
|
+
echo " ❌ archive phase does not allow source code writes" >&2
|
|
327
|
+
echo " ✅ Allowed: confirm archive intent and run the archive script" >&2
|
|
252
328
|
;;
|
|
253
329
|
esac
|
|
254
330
|
echo "" >&2
|