@chenmk/superflow 0.1.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.
Files changed (198) hide show
  1. package/INSTALL.en.md +106 -0
  2. package/INSTALL.md +664 -0
  3. package/LICENSE +21 -0
  4. package/README.md +142 -0
  5. package/README.zh-CN.md +117 -0
  6. package/assets/context-templates/business-rules.md +98 -0
  7. package/assets/context-templates/decisions.md +153 -0
  8. package/assets/context-templates/external-systems.md +166 -0
  9. package/assets/context-templates/incidents.md +89 -0
  10. package/assets/manifest.json +53 -0
  11. package/assets/prompts/superflow-archive.md +9 -0
  12. package/assets/prompts/superflow-clarify.md +10 -0
  13. package/assets/prompts/superflow-design.md +10 -0
  14. package/assets/prompts/superflow-docs.md +10 -0
  15. package/assets/prompts/superflow-implement.md +10 -0
  16. package/assets/prompts/superflow-pipeline.md +13 -0
  17. package/assets/prompts/superflow-verify.md +10 -0
  18. package/assets/rules/superflow-phase-guard.md +50 -0
  19. package/assets/scripts/claude-auto-backup-hook.sh +313 -0
  20. package/assets/scripts/codex-auto-backup-hook.sh +361 -0
  21. package/assets/scripts/install-sql-pre-commit.sh +44 -0
  22. package/assets/scripts/superflow-contract-hooks.sh +744 -0
  23. package/assets/scripts/superflow-delivery-check.sh +315 -0
  24. package/assets/scripts/superflow-dependency-update-hook.sh +161 -0
  25. package/assets/scripts/superflow-enforce-hook.sh +70 -0
  26. package/assets/scripts/superflow-hook-guard.sh +132 -0
  27. package/assets/scripts/superflow-integration-evidence-hook.sh +80 -0
  28. package/assets/scripts/superflow-sql-sync-hook.py +950 -0
  29. package/assets/scripts/superflow-test-report-lint.py +433 -0
  30. package/assets/scripts/superflow-verify-integration.sh +90 -0
  31. package/assets/scripts/sync-settings-json.py +52 -0
  32. package/assets/skills/api-doc-changelog/SKILL.md +193 -0
  33. package/assets/skills/openspec-apply-change/SKILL.md +156 -0
  34. package/assets/skills/openspec-archive-change/SKILL.md +114 -0
  35. package/assets/skills/openspec-explore/SKILL.md +288 -0
  36. package/assets/skills/openspec-propose/SKILL.md +110 -0
  37. package/assets/skills/superflow-archive/SKILL.md +61 -0
  38. package/assets/skills/superflow-clarify/SKILL.md +146 -0
  39. package/assets/skills/superflow-clarify/agents/openai.yaml +4 -0
  40. package/assets/skills/superflow-design/SKILL.md +83 -0
  41. package/assets/skills/superflow-design/agents/openai.yaml +4 -0
  42. package/assets/skills/superflow-docs/SKILL.md +316 -0
  43. package/assets/skills/superflow-docs/agents/openai.yaml +4 -0
  44. package/assets/skills/superflow-hotfix/SKILL.md +48 -0
  45. package/assets/skills/superflow-implement/SKILL.md +461 -0
  46. package/assets/skills/superflow-implement/agents/openai.yaml +4 -0
  47. package/assets/skills/superflow-pipeline/SKILL.md +844 -0
  48. package/assets/skills/superflow-pipeline/agents/openai.yaml +4 -0
  49. package/assets/skills/superflow-pipeline/references/api-design-template.md +431 -0
  50. package/assets/skills/superflow-pipeline/references/architecture-design-template.md +119 -0
  51. package/assets/skills/superflow-pipeline/references/batch-prompt-template.md +536 -0
  52. package/assets/skills/superflow-pipeline/references/batch-split-guide.md +140 -0
  53. package/assets/skills/superflow-pipeline/references/decision-point.md +30 -0
  54. package/assets/skills/superflow-pipeline/references/dirty-worktree.md +35 -0
  55. package/assets/skills/superflow-pipeline/references/document-templates.md +123 -0
  56. package/assets/skills/superflow-pipeline/references/feature-gated-workflow.md +124 -0
  57. package/assets/skills/superflow-pipeline/references/implementation-prompt-template.md +1056 -0
  58. package/assets/skills/superflow-pipeline/references/mock-strategy-guide.md +86 -0
  59. package/assets/skills/superflow-pipeline/references/openspec-format.md +57 -0
  60. package/assets/skills/superflow-pipeline/references/orchestration.md +639 -0
  61. package/assets/skills/superflow-pipeline/references/p0-baseline-template.md +174 -0
  62. package/assets/skills/superflow-pipeline/references/project-config.md +40 -0
  63. package/assets/skills/superflow-pipeline/references/prompt-usage-template.md +152 -0
  64. package/assets/skills/superflow-pipeline/references/quality-gate.md +299 -0
  65. package/assets/skills/superflow-pipeline/references/quality-standards.md +190 -0
  66. package/assets/skills/superflow-pipeline/references/reviewer-checklist.md +154 -0
  67. package/assets/skills/superflow-pipeline/references/sql-risk-review-checklist.md +323 -0
  68. package/assets/skills/superflow-pipeline/references/subagent-progress.md +90 -0
  69. package/assets/skills/superflow-pipeline/references/superpower-technical-design-template.md +125 -0
  70. package/assets/skills/superflow-pipeline/references/test-execution-template.md +220 -0
  71. package/assets/skills/superflow-pipeline/references/test-guide.md +30 -0
  72. package/assets/skills/superflow-pipeline/references/traceability-matrix.md +106 -0
  73. package/assets/skills/superflow-pipeline/references/validation-integrity.md +134 -0
  74. package/assets/skills/superflow-pipeline/scripts/superflow-archive.sh +178 -0
  75. package/assets/skills/superflow-pipeline/scripts/superflow-env.sh +118 -0
  76. package/assets/skills/superflow-pipeline/scripts/superflow-guard.sh +428 -0
  77. package/assets/skills/superflow-pipeline/scripts/superflow-handoff.sh +296 -0
  78. package/assets/skills/superflow-pipeline/scripts/superflow-state.sh +574 -0
  79. package/assets/skills/superflow-pipeline/scripts/superflow-status.sh +172 -0
  80. package/assets/skills/superflow-pipeline/scripts/superflow-yaml-validate.sh +138 -0
  81. package/assets/skills/superflow-table-impact-analysis/SKILL.md +77 -0
  82. package/assets/skills/superflow-tweak/SKILL.md +46 -0
  83. package/assets/skills/superflow-verify/SKILL.md +112 -0
  84. package/assets/skills-en/api-doc-changelog/SKILL.md +193 -0
  85. package/assets/skills-en/openspec-apply-change/SKILL.md +156 -0
  86. package/assets/skills-en/openspec-archive-change/SKILL.md +114 -0
  87. package/assets/skills-en/openspec-explore/SKILL.md +288 -0
  88. package/assets/skills-en/openspec-propose/SKILL.md +110 -0
  89. package/assets/skills-en/superflow-archive/SKILL.md +61 -0
  90. package/assets/skills-en/superflow-clarify/SKILL.md +146 -0
  91. package/assets/skills-en/superflow-clarify/agents/openai.yaml +4 -0
  92. package/assets/skills-en/superflow-design/SKILL.md +83 -0
  93. package/assets/skills-en/superflow-design/agents/openai.yaml +4 -0
  94. package/assets/skills-en/superflow-docs/SKILL.md +316 -0
  95. package/assets/skills-en/superflow-docs/agents/openai.yaml +4 -0
  96. package/assets/skills-en/superflow-hotfix/SKILL.md +48 -0
  97. package/assets/skills-en/superflow-implement/SKILL.md +461 -0
  98. package/assets/skills-en/superflow-implement/agents/openai.yaml +4 -0
  99. package/assets/skills-en/superflow-pipeline/SKILL.md +844 -0
  100. package/assets/skills-en/superflow-pipeline/agents/openai.yaml +4 -0
  101. package/assets/skills-en/superflow-pipeline/references/api-design-template.md +431 -0
  102. package/assets/skills-en/superflow-pipeline/references/architecture-design-template.md +119 -0
  103. package/assets/skills-en/superflow-pipeline/references/batch-prompt-template.md +536 -0
  104. package/assets/skills-en/superflow-pipeline/references/batch-split-guide.md +140 -0
  105. package/assets/skills-en/superflow-pipeline/references/decision-point.md +30 -0
  106. package/assets/skills-en/superflow-pipeline/references/dirty-worktree.md +35 -0
  107. package/assets/skills-en/superflow-pipeline/references/document-templates.md +123 -0
  108. package/assets/skills-en/superflow-pipeline/references/feature-gated-workflow.md +124 -0
  109. package/assets/skills-en/superflow-pipeline/references/implementation-prompt-template.md +1056 -0
  110. package/assets/skills-en/superflow-pipeline/references/mock-strategy-guide.md +86 -0
  111. package/assets/skills-en/superflow-pipeline/references/openspec-format.md +57 -0
  112. package/assets/skills-en/superflow-pipeline/references/orchestration.md +639 -0
  113. package/assets/skills-en/superflow-pipeline/references/p0-baseline-template.md +174 -0
  114. package/assets/skills-en/superflow-pipeline/references/project-config.md +40 -0
  115. package/assets/skills-en/superflow-pipeline/references/prompt-usage-template.md +152 -0
  116. package/assets/skills-en/superflow-pipeline/references/quality-gate.md +299 -0
  117. package/assets/skills-en/superflow-pipeline/references/quality-standards.md +190 -0
  118. package/assets/skills-en/superflow-pipeline/references/reviewer-checklist.md +154 -0
  119. package/assets/skills-en/superflow-pipeline/references/sql-risk-review-checklist.md +323 -0
  120. package/assets/skills-en/superflow-pipeline/references/subagent-progress.md +90 -0
  121. package/assets/skills-en/superflow-pipeline/references/superpower-technical-design-template.md +125 -0
  122. package/assets/skills-en/superflow-pipeline/references/test-execution-template.md +220 -0
  123. package/assets/skills-en/superflow-pipeline/references/test-guide.md +30 -0
  124. package/assets/skills-en/superflow-pipeline/references/traceability-matrix.md +106 -0
  125. package/assets/skills-en/superflow-pipeline/references/validation-integrity.md +134 -0
  126. package/assets/skills-en/superflow-pipeline/scripts/superflow-archive.sh +178 -0
  127. package/assets/skills-en/superflow-pipeline/scripts/superflow-env.sh +118 -0
  128. package/assets/skills-en/superflow-pipeline/scripts/superflow-guard.sh +428 -0
  129. package/assets/skills-en/superflow-pipeline/scripts/superflow-handoff.sh +296 -0
  130. package/assets/skills-en/superflow-pipeline/scripts/superflow-state.sh +574 -0
  131. package/assets/skills-en/superflow-pipeline/scripts/superflow-status.sh +172 -0
  132. package/assets/skills-en/superflow-pipeline/scripts/superflow-yaml-validate.sh +138 -0
  133. package/assets/skills-en/superflow-table-impact-analysis/SKILL.md +77 -0
  134. package/assets/skills-en/superflow-tweak/SKILL.md +46 -0
  135. package/assets/skills-en/superflow-verify/SKILL.md +112 -0
  136. package/dist/cli/index.js +186 -0
  137. package/dist/cli/index.js.map +1 -0
  138. package/dist/commands/archive.js +6 -0
  139. package/dist/commands/archive.js.map +1 -0
  140. package/dist/commands/clarify.js +6 -0
  141. package/dist/commands/clarify.js.map +1 -0
  142. package/dist/commands/design.js +6 -0
  143. package/dist/commands/design.js.map +1 -0
  144. package/dist/commands/docs.js +6 -0
  145. package/dist/commands/docs.js.map +1 -0
  146. package/dist/commands/doctor.js +473 -0
  147. package/dist/commands/doctor.js.map +1 -0
  148. package/dist/commands/implement.js +6 -0
  149. package/dist/commands/implement.js.map +1 -0
  150. package/dist/commands/init.js +471 -0
  151. package/dist/commands/init.js.map +1 -0
  152. package/dist/commands/pipeline.js +6 -0
  153. package/dist/commands/pipeline.js.map +1 -0
  154. package/dist/commands/scan.js +59 -0
  155. package/dist/commands/scan.js.map +1 -0
  156. package/dist/commands/status.js +173 -0
  157. package/dist/commands/status.js.map +1 -0
  158. package/dist/commands/uninstall.js +213 -0
  159. package/dist/commands/uninstall.js.map +1 -0
  160. package/dist/commands/update.js +187 -0
  161. package/dist/commands/update.js.map +1 -0
  162. package/dist/commands/verify.js +6 -0
  163. package/dist/commands/verify.js.map +1 -0
  164. package/dist/core/assets.js +27 -0
  165. package/dist/core/assets.js.map +1 -0
  166. package/dist/core/context.js +100 -0
  167. package/dist/core/context.js.map +1 -0
  168. package/dist/core/dependencies.js +146 -0
  169. package/dist/core/dependencies.js.map +1 -0
  170. package/dist/core/detect.js +71 -0
  171. package/dist/core/detect.js.map +1 -0
  172. package/dist/core/i18n.js +103 -0
  173. package/dist/core/i18n.js.map +1 -0
  174. package/dist/core/integrity.js +46 -0
  175. package/dist/core/integrity.js.map +1 -0
  176. package/dist/core/manifest.js +18 -0
  177. package/dist/core/manifest.js.map +1 -0
  178. package/dist/core/prompts.js +20 -0
  179. package/dist/core/prompts.js.map +1 -0
  180. package/dist/core/registry.js +134 -0
  181. package/dist/core/registry.js.map +1 -0
  182. package/dist/core/rules.js +17 -0
  183. package/dist/core/rules.js.map +1 -0
  184. package/dist/core/scripts.js +40 -0
  185. package/dist/core/scripts.js.map +1 -0
  186. package/dist/core/skill-check.js +31 -0
  187. package/dist/core/skill-check.js.map +1 -0
  188. package/dist/core/skills.js +56 -0
  189. package/dist/core/skills.js.map +1 -0
  190. package/dist/core/state.js +43 -0
  191. package/dist/core/state.js.map +1 -0
  192. package/dist/types.js +2 -0
  193. package/dist/types.js.map +1 -0
  194. package/dist/utils/path.js +11 -0
  195. package/dist/utils/path.js.map +1 -0
  196. package/dist/utils/shell.js +29 -0
  197. package/dist/utils/shell.js.map +1 -0
  198. package/package.json +60 -0
@@ -0,0 +1,315 @@
1
+ #!/bin/bash
2
+ # SuperBridge Flow delivery closeout verifier.
3
+ # Blocks implementation commits that forget to update the matching PXX
4
+ # delivery documents and test evidence.
5
+
6
+ set -u
7
+
8
+ MODE="${1:-}"
9
+
10
+ read_json_field() {
11
+ local field="$1"
12
+ python3 -c "
13
+ import json, os, sys
14
+ try:
15
+ data = json.load(sys.stdin)
16
+ except Exception:
17
+ print('')
18
+ raise SystemExit
19
+ tool_input = data.get('tool_input', {})
20
+ print(tool_input.get('$field') or tool_input.get('cmd') or '')
21
+ " 2>/dev/null
22
+ }
23
+
24
+ if [ "$MODE" = "--check-staged" ]; then
25
+ CWD="${2:-$(pwd)}"
26
+ else
27
+ INPUT=$(cat)
28
+ COMMAND=$(printf '%s' "$INPUT" | read_json_field command)
29
+ case "$COMMAND" in
30
+ *"git commit"*) ;;
31
+ *) exit 0 ;;
32
+ esac
33
+ CWD=$(printf '%s' "$INPUT" | python3 -c "
34
+ import json, os, sys
35
+ try:
36
+ data = json.load(sys.stdin)
37
+ except Exception:
38
+ print(os.getcwd())
39
+ raise SystemExit
40
+ tool_input = data.get('tool_input', {})
41
+ print(tool_input.get('cwd') or os.getcwd())
42
+ " 2>/dev/null)
43
+ fi
44
+
45
+ REPO_ROOT=$(git -C "$CWD" rev-parse --show-toplevel 2>/dev/null)
46
+ if [ $? -ne 0 ]; then
47
+ exit 0
48
+ fi
49
+
50
+ CHANGED=$(git -C "$REPO_ROOT" diff --cached --name-only)
51
+ if [ -z "$CHANGED" ]; then
52
+ exit 0
53
+ fi
54
+
55
+ SDD_ACTIVE=0
56
+ if [ -f "$REPO_ROOT/.sdd-enforced" ]; then
57
+ SDD_ACTIVE=1
58
+ fi
59
+
60
+ RUNTIME_CHANGED=$(printf '%s\n' "$CHANGED" | grep -E \
61
+ '(^|/)src/main/.*\.(java|xml|yml|yaml|properties)$|(^|/)mapper/.*\.xml$|(^|/)sql/.*\.sql$' || true)
62
+
63
+ CODE_RUNTIME_CHANGED=$(printf '%s\n' "$CHANGED" | grep -E \
64
+ '(^|/)src/main/.*\.(java|xml|yml|yaml|properties)$|(^|/)mapper/.*\.xml$' || true)
65
+
66
+ P_DIRS=$(printf '%s\n' "$CHANGED" | sed -nE \
67
+ 's#^(.*embedded-changes/(p[0-9]+[^/]*))/.*$#\1#p' | sort -u)
68
+
69
+ REPORTS=$(printf '%s\n' "$CHANGED" | grep -E \
70
+ '(^|/)embedded-changes/p[0-9][^/]*/test-report\.md$|(^|/)test-report\.md$' || true)
71
+
72
+ AGGREGATE_DOCS=$(printf '%s\n' "$CHANGED" | grep -E \
73
+ '(^|/)openspec/changes/[^/]+/(tasks|test-report|traceability-matrix|sdd-quality-gate|tests)\.md$|(^|/)doc/openspec/changes/[^/]+/(tasks|test-report|traceability-matrix|sdd-quality-gate|tests)\.md$' || true)
74
+
75
+ SDD_DOCS_CHANGED=$(printf '%s\n' "$CHANGED" | grep -E \
76
+ '(^|/)(doc/)?openspec/changes/|(^|/)embedded-changes/p[0-9]' || true)
77
+
78
+ AGGREGATE_ALLOWED=0
79
+ if [ -f "$REPO_ROOT/.sdd-aggregate-closeout" ]; then
80
+ AGGREGATE_ALLOWED=1
81
+ fi
82
+
83
+ if [ "$SDD_ACTIVE" -eq 0 ] && [ -z "$SDD_DOCS_CHANGED" ]; then
84
+ exit 0
85
+ fi
86
+
87
+ FAILED=0
88
+
89
+ fail() {
90
+ echo "FAIL $1"
91
+ FAILED=1
92
+ }
93
+
94
+ ok() {
95
+ echo "OK $1"
96
+ }
97
+
98
+ has_staged_file() {
99
+ local path="$1"
100
+ printf '%s\n' "$CHANGED" | grep -Fxq "$path"
101
+ }
102
+
103
+ check_no_open_placeholders() {
104
+ local file="$1"
105
+ if [ ! -f "$file" ]; then
106
+ fail "[$file] 文件不存在"
107
+ return
108
+ fi
109
+
110
+ if grep -Eiq '待执行|待补充|后续补测|后续测试|TODO|测试报告待更新|验证待回填' "$file"; then
111
+ fail "[$file] 仍包含待执行/待补充/TODO 类交付占位"
112
+ else
113
+ ok "[$file] 未发现明显交付占位"
114
+ fi
115
+ }
116
+
117
+ check_has_closeout_status() {
118
+ local file="$1"
119
+ if grep -Eiq 'Real integration passed|Partially verified|Partial real entry|Blocked|真实入口|真实接口|验证闭环|阻塞|部分验证' "$file"; then
120
+ ok "[$file] 包含交付结论"
121
+ else
122
+ fail "[$file] 缺少 Real integration passed / Partially verified / Blocked 等交付结论"
123
+ fi
124
+ }
125
+
126
+ check_context_drift_guard() {
127
+ local rel_dir="$1"
128
+ local abs_dir="$REPO_ROOT/$rel_dir"
129
+ local state_file="$abs_dir/.sdd/state.yaml"
130
+ local handoff_dir="$abs_dir/.sdd/handoff"
131
+ local hash_file="$handoff_dir/sdd-context.sha256"
132
+ local marker=""
133
+
134
+ if [ ! -d "$abs_dir" ]; then
135
+ return
136
+ fi
137
+
138
+ marker=$(grep -REi 'handoff_hash|sdd-context|上下文防漂移|防漂移' \
139
+ "$abs_dir/sdd-quality-gate.md" "$abs_dir/test-report.md" "$abs_dir/design.md" \
140
+ "$abs_dir/prompt" 2>/dev/null || true)
141
+
142
+ if [ -z "$marker" ] && [ ! -f "$hash_file" ]; then
143
+ return
144
+ fi
145
+
146
+ if [ ! -f "$state_file" ]; then
147
+ fail "[$rel_dir] 缺少 .sdd/state.yaml,上下文防漂移状态未初始化"
148
+ return
149
+ fi
150
+
151
+ if [ ! -f "$handoff_dir/sdd-context.md" ] \
152
+ || [ ! -f "$handoff_dir/sdd-context.json" ] \
153
+ || [ ! -f "$hash_file" ]; then
154
+ fail "[$rel_dir] 缺少 .sdd/handoff/sdd-context.{md,json,sha256}"
155
+ return
156
+ fi
157
+
158
+ local hash_value
159
+ hash_value=$(cat "$hash_file" 2>/dev/null | tr -d '[:space:]')
160
+ if [ -z "$hash_value" ]; then
161
+ fail "[$rel_dir] sdd-context.sha256 为空"
162
+ return
163
+ fi
164
+
165
+ if grep -Riq "$hash_value" \
166
+ "$abs_dir/sdd-quality-gate.md" "$abs_dir/test-report.md" "$abs_dir/design.md" \
167
+ "$abs_dir/prompt" 2>/dev/null; then
168
+ ok "[$rel_dir] handoff hash 已被质量门/报告/prompt 继承"
169
+ else
170
+ fail "[$rel_dir] handoff hash 未写入 design、quality gate、prompt 或 test-report"
171
+ fi
172
+ }
173
+
174
+ is_blocked_doc_freeze_report() {
175
+ local file="$1"
176
+ if [ ! -f "$file" ]; then
177
+ return 1
178
+ fi
179
+
180
+ grep -Eiq 'Blocked|阻塞' "$file" \
181
+ && grep -Eiq 'SDD 文档|文档阶段|范围收口|范围冻结|任务冻结|不包含代码实现|没有 Java 实现变更|未进入实现|当前报告记录可交付边界' "$file"
182
+ }
183
+
184
+ DOC_FREEZE_ALLOWED=0
185
+ for report in $REPORTS; do
186
+ if is_blocked_doc_freeze_report "$REPO_ROOT/$report"; then
187
+ DOC_FREEZE_ALLOWED=1
188
+ fi
189
+ done
190
+
191
+ if [ -n "$RUNTIME_CHANGED" ] && [ -z "$REPORTS" ]; then
192
+ fail "检测到运行时代码/SQL 变更,但本次提交没有 staged 当前任务的 test-report.md"
193
+ fi
194
+
195
+ if [ -n "$AGGREGATE_DOCS" ] && [ "$AGGREGATE_ALLOWED" -eq 0 ] && [ "$DOC_FREEZE_ALLOWED" -eq 0 ]; then
196
+ fail "检测到根级汇总 SDD 文档变更,但当前不是汇总收口 worktree"
197
+ printf '%s\n' "$AGGREGATE_DOCS" | sed 's/^/ - /'
198
+ cat <<'AGGREGATE_MSG'
199
+
200
+ 并行研发 agent 只允许更新自己的 embedded-changes/pXX-* 目录,避免多个
201
+ worktree 合并时反复冲突根级 test-report/tasks/traceability 文档。
202
+
203
+ 如果你是 Leader/集成收口 agent,需要统一汇总各 P 任务状态,请先执行:
204
+ touch .sdd-aggregate-closeout
205
+
206
+ 然后在单独的汇总提交中更新根级 SDD 文档。
207
+ AGGREGATE_MSG
208
+ fi
209
+
210
+ if [ -n "$P_DIRS" ]; then
211
+ for p_dir in $P_DIRS; do
212
+ rel_tasks="$p_dir/tasks.md"
213
+ rel_report="$p_dir/test-report.md"
214
+ rel_gate="$p_dir/sdd-quality-gate.md"
215
+
216
+ if [ -f "$REPO_ROOT/$rel_tasks" ]; then
217
+ if has_staged_file "$rel_tasks"; then
218
+ ok "[$rel_tasks] 已 staged"
219
+ else
220
+ fail "[$rel_tasks] 未 staged,当前 P 任务交付状态可能未同步"
221
+ fi
222
+ fi
223
+
224
+ if [ -f "$REPO_ROOT/$rel_report" ]; then
225
+ if has_staged_file "$rel_report"; then
226
+ ok "[$rel_report] 已 staged"
227
+ check_no_open_placeholders "$REPO_ROOT/$rel_report"
228
+ check_has_closeout_status "$REPO_ROOT/$rel_report"
229
+ if [ -x "$HOME/.codex/hooks/superflow-test-report-lint.py" ]; then
230
+ lint_args=(--repo-root "$REPO_ROOT")
231
+ if [ -f "$REPO_ROOT/$p_dir/tests.md" ]; then
232
+ lint_args+=(--tests "$REPO_ROOT/$p_dir/tests.md")
233
+ fi
234
+ "$HOME/.codex/hooks/superflow-test-report-lint.py" \
235
+ "${lint_args[@]}" "$REPO_ROOT/$rel_report"
236
+ if [ $? -ne 0 ]; then
237
+ FAILED=1
238
+ fi
239
+ fi
240
+ else
241
+ fail "[$rel_report] 未 staged,当前 P 任务测试报告未同步"
242
+ fi
243
+ else
244
+ fail "[$rel_report] 不存在,当前 P 任务缺少独立测试报告"
245
+ fi
246
+
247
+ if [ -f "$REPO_ROOT/$rel_gate" ]; then
248
+ if has_staged_file "$rel_gate"; then
249
+ ok "[$rel_gate] 已 staged"
250
+ check_no_open_placeholders "$REPO_ROOT/$rel_gate"
251
+ else
252
+ fail "[$rel_gate] 未 staged,当前 P 任务质量门禁可能未同步"
253
+ fi
254
+ fi
255
+
256
+ check_context_drift_guard "$p_dir"
257
+ done
258
+ fi
259
+
260
+ VERIFY_REPORTS=$(printf '%s\n' "$REPORTS" | grep -E \
261
+ '(^|/)embedded-changes/p[0-9][^/]*/test-report\.md$' || true)
262
+
263
+ if [ -n "$VERIFY_REPORTS" ] && [ -x "$HOME/.codex/hooks/superflow-verify-integration.sh" ]; then
264
+ VERIFY_ARGS=""
265
+ for report in $VERIFY_REPORTS; do
266
+ abs_report="$REPO_ROOT/$report"
267
+ if is_blocked_doc_freeze_report "$abs_report" && [ -z "$CODE_RUNTIME_CHANGED" ]; then
268
+ ok "[$report] 为 SDD 文档冻结 Blocked 报告,跳过真实集成验收脚本"
269
+ continue
270
+ fi
271
+ VERIFY_ARGS="$VERIFY_ARGS $abs_report"
272
+ done
273
+ if [ -n "$VERIFY_ARGS" ]; then
274
+ "$HOME/.codex/hooks/superflow-verify-integration.sh" $VERIFY_ARGS
275
+ if [ $? -ne 0 ]; then
276
+ FAILED=1
277
+ fi
278
+ fi
279
+ fi
280
+
281
+ ROOT_REPORTS=$(printf '%s\n' "$REPORTS" | grep -E \
282
+ '(^|/)openspec/changes/[^/]+/test-report\.md$|(^|/)doc/openspec/changes/[^/]+/test-report\.md$' || true)
283
+
284
+ if [ -n "$ROOT_REPORTS" ] && [ -x "$HOME/.codex/hooks/superflow-test-report-lint.py" ]; then
285
+ for report in $ROOT_REPORTS; do
286
+ root_lint_args=(--warn-only --repo-root "$REPO_ROOT")
287
+ root_tests="${report%/test-report.md}/tests.md"
288
+ if [ -f "$REPO_ROOT/$root_tests" ]; then
289
+ root_lint_args+=(--tests "$REPO_ROOT/$root_tests")
290
+ fi
291
+ "$HOME/.codex/hooks/superflow-test-report-lint.py" \
292
+ "${root_lint_args[@]}" "$REPO_ROOT/$report"
293
+ if [ $? -ne 0 ]; then
294
+ FAILED=1
295
+ fi
296
+ done
297
+ fi
298
+
299
+ if [ "$FAILED" -ne 0 ]; then
300
+ cat <<'BLOCK_MSG'
301
+
302
+ [SDD 交付完整性拦截]
303
+ 当前提交还没有形成可交付闭环。请补齐当前 P 任务的:
304
+ 1. tasks.md 状态
305
+ 2. test-report.md 真实验证证据
306
+ 3. sdd-quality-gate.md 质量门禁状态(如果存在)
307
+
308
+ 如果确实无法验证,请在 test-report.md 中写明 Blocked 或 Partially verified
309
+ 以及具体阻塞原因,不能用“后续补测/待补充”作为完成态。
310
+ BLOCK_MSG
311
+ exit 2
312
+ fi
313
+
314
+ echo "SDD 交付完整性检查通过"
315
+ exit 0
@@ -0,0 +1,161 @@
1
+ #!/bin/bash
2
+ # Session-scoped Superflow dependency update checker.
3
+ # Default mode checks and reports updates. Set SUPERFLOW_AUTO_UPDATE=apply to install.
4
+
5
+ set -u
6
+
7
+ INPUT=""
8
+ if [ ! -t 0 ]; then
9
+ INPUT=$(cat 2>/dev/null || true)
10
+ fi
11
+
12
+ MODE="${SUPERFLOW_AUTO_UPDATE:-check}"
13
+ case "$MODE" in
14
+ 0|off|false|none) exit 0 ;;
15
+ 1|true|yes|apply) MODE="apply" ;;
16
+ check|"") MODE="check" ;;
17
+ *) MODE="check" ;;
18
+ esac
19
+
20
+ if [ "$MODE" = "0" ]; then
21
+ exit 0
22
+ fi
23
+
24
+ STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/superflow"
25
+ mkdir -p "$STATE_DIR" 2>/dev/null || exit 0
26
+
27
+ SESSION_KEY=$(printf '%s' "$INPUT" | python3 -c '
28
+ import hashlib, json, os, sys
29
+ raw = sys.stdin.read()
30
+ try:
31
+ data = json.loads(raw) if raw.strip() else {}
32
+ except Exception:
33
+ data = {}
34
+ for key in ("session_id", "conversation_id", "thread_id", "transcript_path"):
35
+ value = data.get(key)
36
+ if value:
37
+ print(str(value))
38
+ raise SystemExit
39
+ cwd = data.get("cwd") or os.getcwd()
40
+ print("fallback:" + hashlib.sha256(cwd.encode()).hexdigest()[:16])
41
+ ' 2>/dev/null)
42
+
43
+ [ -n "$SESSION_KEY" ] || SESSION_KEY="unknown"
44
+ SESSION_HASH=$(printf '%s' "$SESSION_KEY" | shasum -a 256 2>/dev/null | awk '{print $1}')
45
+ if [ -z "$SESSION_HASH" ]; then
46
+ SESSION_HASH=$(printf '%s' "$SESSION_KEY" | sha256sum 2>/dev/null | awk '{print $1}')
47
+ fi
48
+ [ -n "$SESSION_HASH" ] || SESSION_HASH="unknown"
49
+
50
+ STAMP="$STATE_DIR/dependency-update-$SESSION_HASH.stamp"
51
+ GLOBAL_STAMP="$STATE_DIR/dependency-update-last.stamp"
52
+ LOG_FILE="$STATE_DIR/dependency-update.log"
53
+ LOCK_DIR="$STATE_DIR/dependency-update.lock"
54
+
55
+ now_epoch() {
56
+ date +%s
57
+ }
58
+
59
+ MIN_INTERVAL="${SUPERFLOW_UPDATE_MIN_INTERVAL_SECONDS:-21600}"
60
+ NOW=$(now_epoch)
61
+
62
+ if [ -f "$STAMP" ]; then
63
+ exit 0
64
+ fi
65
+
66
+ if [ -f "$GLOBAL_STAMP" ]; then
67
+ LAST=$(cat "$GLOBAL_STAMP" 2>/dev/null || printf '0')
68
+ case "$LAST" in
69
+ ''|*[!0-9]*) LAST=0 ;;
70
+ esac
71
+ if [ "$((NOW - LAST))" -lt "$MIN_INTERVAL" ]; then
72
+ printf '%s\n' "$NOW" > "$STAMP" 2>/dev/null || true
73
+ exit 0
74
+ fi
75
+ fi
76
+
77
+ if ! mkdir "$LOCK_DIR" 2>/dev/null; then
78
+ exit 0
79
+ fi
80
+ trap 'rmdir "$LOCK_DIR" 2>/dev/null || true' EXIT
81
+
82
+ printf '%s\n' "$NOW" > "$STAMP" 2>/dev/null || true
83
+ printf '%s\n' "$NOW" > "$GLOBAL_STAMP" 2>/dev/null || true
84
+
85
+ run_logged() {
86
+ printf '\n[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >> "$LOG_FILE" 2>/dev/null || true
87
+ "$@" >> "$LOG_FILE" 2>&1
88
+ }
89
+
90
+ latest_npm_version() {
91
+ npm view "$1" version 2>/dev/null | tail -n 1
92
+ }
93
+
94
+ installed_npm_version() {
95
+ local json
96
+ json="$(npm list -g "$1" --depth=0 --json 2>/dev/null || true)"
97
+ printf '%s' "$json" | python3 -c '
98
+ import json, sys
99
+ package_name = sys.argv[1]
100
+ try:
101
+ data = json.load(sys.stdin)
102
+ except Exception:
103
+ raise SystemExit
104
+ dep = (data.get("dependencies") or {}).get(package_name) or {}
105
+ version = dep.get("version")
106
+ if version:
107
+ print(version)
108
+ ' "$1"
109
+ }
110
+
111
+ update_npm_if_needed() {
112
+ local package_name="$1"
113
+ local current latest
114
+ command -v npm >/dev/null 2>&1 || return 0
115
+ latest="$(latest_npm_version "$package_name")"
116
+ [ -n "$latest" ] || return 0
117
+ current="$(installed_npm_version "$package_name")"
118
+ if [ "$current" != "$latest" ]; then
119
+ run_logged npm install -g "$package_name@latest" || true
120
+ fi
121
+ }
122
+
123
+ check_npm_package() {
124
+ local package_name="$1"
125
+ local current latest
126
+ command -v npm >/dev/null 2>&1 || return 0
127
+ latest="$(latest_npm_version "$package_name")"
128
+ [ -n "$latest" ] || return 0
129
+ current="$(installed_npm_version "$package_name")"
130
+ if [ -z "$current" ]; then
131
+ printf '%s latest=%s installed=missing\n' "$package_name" "$latest"
132
+ elif [ "$current" != "$latest" ]; then
133
+ printf '%s latest=%s installed=%s\n' "$package_name" "$latest" "$current"
134
+ fi
135
+ }
136
+
137
+ if [ "$MODE" = "apply" ]; then
138
+ update_npm_if_needed "@chenmk/superflow"
139
+ update_npm_if_needed "@fission-ai/openspec"
140
+
141
+ if command -v claude >/dev/null 2>&1; then
142
+ run_logged claude plugin install superpowers@superpowers-marketplace || true
143
+ fi
144
+
145
+ if command -v codex >/dev/null 2>&1; then
146
+ run_logged codex plugin add superpowers@openai-curated || true
147
+ fi
148
+ else
149
+ STATUS_FILE="$STATE_DIR/dependency-update-status.txt"
150
+ {
151
+ printf 'checked_at=%s\n' "$(date '+%Y-%m-%d %H:%M:%S')"
152
+ check_npm_package "@chenmk/superflow"
153
+ check_npm_package "@fission-ai/openspec"
154
+ printf 'superpowers=run superflow update --with-package to refresh selected agent plugins\n'
155
+ } > "$STATUS_FILE" 2>/dev/null || true
156
+ if grep -Eq '^@' "$STATUS_FILE" 2>/dev/null; then
157
+ printf '[Superflow] 有核心依赖更新,执行 superflow update --with-package 统一更新;详情:%s\n' "$STATUS_FILE" >&2
158
+ fi
159
+ fi
160
+
161
+ exit 0
@@ -0,0 +1,70 @@
1
+ #!/bin/bash
2
+ # SDD 强制门禁 Hook
3
+ # 拦截 Edit/Write 工具调用,确保:
4
+ # 1. 不在主工作树直接编辑(必须用 worktree)
5
+ # 2. 数据库结构已核查(必须有 .db-verified 标记)
6
+ #
7
+ # 触发条件:项目根目录存在 .sdd-enforced 文件
8
+ # 标记说明:
9
+ # .sdd-enforced - 由 SDD prompt 创建,表示当前有活跃的 SDD 任务
10
+ # .db-verified - 由研发 agent 数据库核查后创建
11
+ #
12
+ # 退出码:0=允许 2=拦截
13
+
14
+ INPUT=$(cat)
15
+
16
+ FILE_PATH=$(echo "$INPUT" | python3 -c "
17
+ import sys, json
18
+ d = json.load(sys.stdin)
19
+ print(d.get('tool_input', {}).get('file_path', ''))
20
+ " 2>/dev/null)
21
+
22
+ if [ -z "$FILE_PATH" ]; then
23
+ exit 0
24
+ fi
25
+
26
+ FILE_DIR=$(dirname "$FILE_PATH")
27
+
28
+ REPO_ROOT=$(git -C "$FILE_DIR" rev-parse --show-toplevel 2>/dev/null)
29
+ if [ $? -ne 0 ]; then
30
+ exit 0
31
+ fi
32
+
33
+ if [ ! -f "$REPO_ROOT/.sdd-enforced" ]; then
34
+ exit 0
35
+ fi
36
+
37
+ if [ -d "$REPO_ROOT/.git" ]; then
38
+ cat <<'BLOCK_MSG'
39
+ [SDD 门禁拦截] 检测到在主工作树直接编辑,已阻止。
40
+
41
+ 原因:SDD 任务要求在独立 worktree 分支中开发,禁止污染主工作树。
42
+
43
+ 请立即执行:
44
+ git worktree add -b feature/{任务分支名} ../{项目}-worktree HEAD
45
+ cd ../{项目}-worktree
46
+ # 在 worktree 内重新创建门禁标记:
47
+ touch .sdd-enforced
48
+
49
+ 完成后即可继续编辑。如需取消门禁,删除主仓库的 .sdd-enforced 文件。
50
+ BLOCK_MSG
51
+ exit 2
52
+ fi
53
+
54
+ if [ ! -f "$REPO_ROOT/.db-verified" ]; then
55
+ cat <<'BLOCK_MSG'
56
+ [SDD 门禁拦截] 数据库结构尚未核查,编辑已阻止。
57
+
58
+ 原因:写业务代码前必须先确认开发环境数据库结构与设计一致。
59
+
60
+ 请立即执行数据库前置门禁:
61
+ 1. 连接开发库执行 SHOW CREATE TABLE 确认表结构
62
+ 2. 如有缺失,从汇总 SQL 文件取脚本执行
63
+ 3. 确认后创建标记:touch .db-verified
64
+
65
+ 完成后即可继续编辑。如需跳过(不推荐),删除 .sdd-enforced 文件。
66
+ BLOCK_MSG
67
+ exit 2
68
+ fi
69
+
70
+ exit 0
@@ -0,0 +1,132 @@
1
+ #!/bin/bash
2
+ # SDD phase-aware hook guard.
3
+ # Blocks writes that conflict with .sdd/state.yaml when .sdd-enforced is active.
4
+
5
+ set -u
6
+
7
+ INPUT=""
8
+ if [ ! -t 0 ]; then
9
+ INPUT=$(cat 2>/dev/null || true)
10
+ fi
11
+
12
+ FILE_PATH="${FILE_PATH:-}"
13
+ if [ -z "$FILE_PATH" ] && [ -n "$INPUT" ]; then
14
+ FILE_PATH=$(printf '%s' "$INPUT" | python3 -c "
15
+ import json, sys
16
+ try:
17
+ data = json.load(sys.stdin)
18
+ except Exception:
19
+ print('')
20
+ raise SystemExit
21
+ tool_input = data.get('tool_input', {})
22
+ print(tool_input.get('file_path') or '')
23
+ " 2>/dev/null)
24
+ fi
25
+
26
+ if [ -z "$FILE_PATH" ]; then
27
+ exit 0
28
+ fi
29
+
30
+ FILE_PATH=$(printf '%s' "$FILE_PATH" | sed 's|\\|/|g')
31
+ FILE_DIR=$(dirname "$FILE_PATH")
32
+ while [ ! -d "$FILE_DIR" ] && [ "$FILE_DIR" != "." ] && [ "$FILE_DIR" != "/" ]; do
33
+ FILE_DIR=$(dirname "$FILE_DIR")
34
+ done
35
+ REPO_ROOT=$(git -C "$FILE_DIR" rev-parse --show-toplevel 2>/dev/null)
36
+ if [ $? -ne 0 ]; then
37
+ exit 0
38
+ fi
39
+
40
+ if [ ! -f "$REPO_ROOT/.sdd-enforced" ]; then
41
+ exit 0
42
+ fi
43
+
44
+ REL=$(python3 - "$REPO_ROOT" "$FILE_PATH" <<'PY'
45
+ import os, sys
46
+ root = os.path.abspath(sys.argv[1])
47
+ path = os.path.abspath(sys.argv[2])
48
+ try:
49
+ print(os.path.relpath(path, root).replace(os.sep, '/'))
50
+ except Exception:
51
+ print(path.replace(os.sep, '/'))
52
+ PY
53
+ )
54
+
55
+ STATE_FILE=""
56
+ case "$REL" in
57
+ *embedded-changes/*)
58
+ prefix=$(printf '%s\n' "$REL" | sed -nE 's#^(.*embedded-changes/[^/]+).*#\1#p')
59
+ [ -n "$prefix" ] && [ -f "$REPO_ROOT/$prefix/.sdd/state.yaml" ] && STATE_FILE="$REPO_ROOT/$prefix/.sdd/state.yaml"
60
+ ;;
61
+ *openspec/changes/*)
62
+ prefix=$(printf '%s\n' "$REL" | sed -nE 's#^(.*openspec/changes/[^/]+).*#\1#p')
63
+ [ -n "$prefix" ] && [ -f "$REPO_ROOT/$prefix/.sdd/state.yaml" ] && STATE_FILE="$REPO_ROOT/$prefix/.sdd/state.yaml"
64
+ ;;
65
+ esac
66
+
67
+ if [ -z "$STATE_FILE" ]; then
68
+ STATE_FILE=$(find "$REPO_ROOT" -path '*/.sdd/state.yaml' -type f 2>/dev/null | head -n 1)
69
+ fi
70
+
71
+ [ -n "$STATE_FILE" ] || exit 0
72
+
73
+ PHASE=$(awk -F':' '$1=="phase"{gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}' "$STATE_FILE" 2>/dev/null)
74
+ [ -n "$PHASE" ] || exit 0
75
+
76
+ is_sdd_doc_path() {
77
+ printf '%s\n' "$REL" | grep -Eq '(^|/)(openspec/changes|embedded-changes)/|(^|/)\.sdd/|(^|/)prompt/|(^|/)docs/superpowers/'
78
+ }
79
+
80
+ is_root_markdown_or_config() {
81
+ case "$REL" in
82
+ */*) return 1 ;;
83
+ *.md|.sdd-enforced|.db-verified) return 0 ;;
84
+ *) return 1 ;;
85
+ esac
86
+ }
87
+
88
+ case "$REL" in
89
+ *.java|*.xml|*.sql|*.yml|*.yaml|*.properties)
90
+ RUNTIME=1
91
+ ;;
92
+ *)
93
+ RUNTIME=0
94
+ ;;
95
+ esac
96
+
97
+ case "$PHASE" in
98
+ docs)
99
+ if is_sdd_doc_path || is_root_markdown_or_config; then
100
+ exit 0
101
+ fi
102
+ if [ "$RUNTIME" -eq 1 ]; then
103
+ cat <<'BLOCK_MSG' >&2
104
+ [SDD phase guard] 当前 phase=docs,禁止直接修改运行时代码。
105
+ 请先完成 SDD docs、handoff、state 和 docs guard,再进入 implement 阶段。
106
+ BLOCK_MSG
107
+ exit 2
108
+ fi
109
+ ;;
110
+ implement|verify)
111
+ exit 0
112
+ ;;
113
+ archive)
114
+ if printf '%s\n' "$REL" | grep -Eq '(^|/)\.sdd/state\.yaml$|(^|/)\.openspec\.yaml$'; then
115
+ exit 0
116
+ fi
117
+ cat <<'BLOCK_MSG' >&2
118
+ [SDD phase guard] 当前 SDD 已进入 archive,禁止继续修改运行时代码或交付文档。
119
+ 如需调整,请先执行 superflow-state.sh transition <change-dir> archive-reopen。
120
+ BLOCK_MSG
121
+ exit 2
122
+ ;;
123
+ done)
124
+ cat <<'BLOCK_MSG' >&2
125
+ [SDD phase guard] 当前 SDD 已进入 archive/done,禁止继续修改交付文件或代码。
126
+ 如需调整,请先执行 superflow-state.sh transition <change-dir> archive-reopen。
127
+ BLOCK_MSG
128
+ exit 2
129
+ ;;
130
+ esac
131
+
132
+ exit 0