@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,744 @@
1
+ #!/bin/bash
2
+ # SDD 契约检查 Hook
3
+ # 在 Edit/Write 时自动检查代码是否符合前端联调契约。
4
+ # 包含 8 个检查器(A-H),按触发条件精确匹配。
5
+ #
6
+ # 依赖:python3、grep
7
+ # 退出码:0=允许 2=拦截(fail 级别) 0+warning=允许但输出警告
8
+ #
9
+ # 环境变量:
10
+ # SDD_CONTRACT_HOOK_DEBUG=1 开启调试输出
11
+
12
+ INPUT=$(cat)
13
+
14
+ # 提取 file_path
15
+ FILE_PATH=$(echo "$INPUT" | python3 -c "
16
+ import sys, json
17
+ d = json.load(sys.stdin)
18
+ print(d.get('tool_input', {}).get('file_path', ''))
19
+ " 2>/dev/null)
20
+
21
+ if [ -z "$FILE_PATH" ]; then
22
+ exit 0
23
+ fi
24
+
25
+ # 只检查 Java 和 Markdown 文件
26
+ case "$FILE_PATH" in
27
+ *.java|*.md) ;;
28
+ *) exit 0 ;;
29
+ esac
30
+
31
+ # 只在 SDD 门禁激活时检查
32
+ FILE_DIR=$(dirname "$FILE_PATH")
33
+ REPO_ROOT=$(git -C "$FILE_DIR" rev-parse --show-toplevel 2>/dev/null)
34
+ if [ $? -ne 0 ]; then
35
+ exit 0
36
+ fi
37
+
38
+ if [ ! -f "$REPO_ROOT/.sdd-enforced" ]; then
39
+ exit 0
40
+ fi
41
+
42
+ # 数据库门禁未通过时,不做契约检查(由 superflow-enforce-hook.sh 拦截)
43
+ if [ ! -f "$REPO_ROOT/.db-verified" ]; then
44
+ exit 0
45
+ fi
46
+
47
+ DEBUG=""
48
+ if [ "$SDD_CONTRACT_HOOK_DEBUG" = "1" ]; then
49
+ DEBUG="1"
50
+ fi
51
+
52
+ # 提取 new_string(Edit)或 content(Write)用于分析
53
+ EDIT_CONTENT=$(echo "$INPUT" | python3 -c "
54
+ import sys, json
55
+ d = json.load(sys.stdin)
56
+ ti = d.get('tool_input', {})
57
+ # Edit 模式:提取 new_string
58
+ ns = ti.get('new_string', '')
59
+ if ns:
60
+ print(ns)
61
+ else:
62
+ # Write 模式:提取 content
63
+ print(ti.get('content', ''))
64
+ " 2>/dev/null)
65
+
66
+ if [ -z "$EDIT_CONTENT" ]; then
67
+ exit 0
68
+ fi
69
+
70
+ WARNINGS=""
71
+ HAS_FAIL=""
72
+
73
+ log_warning() {
74
+ WARNINGS="${WARNINGS}
75
+ ⚠️ [SDD 契约检查] WARNING: $1"
76
+ }
77
+
78
+ log_fail() {
79
+ HAS_FAIL="1"
80
+ WARNINGS="${WARNINGS}
81
+ 🚫 [SDD 契约检查] FAIL: $1"
82
+ }
83
+
84
+ log_debug() {
85
+ if [ "$DEBUG" = "1" ]; then
86
+ echo "[DEBUG] $1" >&2
87
+ fi
88
+ }
89
+
90
+ # 读取文件当前内容(如果文件存在)
91
+ FILE_CONTENT=""
92
+ if [ -f "$FILE_PATH" ]; then
93
+ FILE_CONTENT=$(cat "$FILE_PATH" 2>/dev/null)
94
+ fi
95
+
96
+ # 合并当前文件内容和编辑内容用于检查
97
+ CHECK_CONTENT="${FILE_CONTENT}
98
+ ${EDIT_CONTENT}"
99
+
100
+ ###############################################################################
101
+ # Hook A:文件流接口检查
102
+ #
103
+ # 触发条件:
104
+ # - 变更的 Controller 方法中,路径或方法名包含:
105
+ # export / download / template / 导出 / 下载 / 模板
106
+ # - 或 @ApiOperation 包含"导出""下载模板""模板下载"
107
+ #
108
+ # 排除条件:
109
+ # - 路径包含 status/progress/result
110
+ # - 明确是 JSON 查询结果
111
+ # - 方法注释写明"返回 JSON"
112
+ #
113
+ # 检查规则:
114
+ # - 如果是成功文件接口,不应返回 Response<T>
115
+ # - 应包含 HttpServletResponse
116
+ # - 应设置 Content-Type
117
+ # - 应设置 Content-Disposition
118
+ # - tests.md 或单测应验证 header / 文件流 / 文件可打开
119
+ #
120
+ # 严重级别:
121
+ # - 路径包含 /export 且返回 Response:fail
122
+ # - 其他缺失:warning
123
+ ###############################################################################
124
+
125
+ hook_a_file_stream() {
126
+ # 只检查 Java Controller 文件
127
+ case "$FILE_PATH" in
128
+ *Controller*.java|*controller*.java) ;;
129
+ *) return ;;
130
+ esac
131
+
132
+ # 检查是否包含导出/下载相关关键词
133
+ local is_file_interface=0
134
+ local method_names=$(echo "$EDIT_CONTENT" | grep -oiE '(export|download|template|导出|下载|模板)' || true)
135
+ local api_op=$(echo "$EDIT_CONTENT" | grep -oiE '@ApiOperation.*"(.*导出.*|.*下载.*|.*模板.*)"' || true)
136
+
137
+ if [ -z "$method_names" ] && [ -z "$api_op" ]; then
138
+ return
139
+ fi
140
+
141
+ log_debug "Hook A: 检测到文件接口关键词"
142
+
143
+ # 排除条件:status/progress/result 或 "返回 JSON"
144
+ local exclude=$(echo "$EDIT_CONTENT" | grep -oiE '(status|progress|result|返回 JSON|返回JSON)' || true)
145
+ if [ -n "$exclude" ]; then
146
+ log_debug "Hook A: 命中排除条件,跳过"
147
+ return
148
+ fi
149
+
150
+ # 检查是否返回 Response<T>
151
+ local returns_response=$(echo "$EDIT_CONTENT" | grep -oiE 'Response<[^>]*>' | head -1 || true)
152
+ local has_servlet_response=$(echo "$EDIT_CONTENT" | grep -oi 'HttpServletResponse' || true)
153
+ local has_content_type=$(echo "$EDIT_CONTENT" | grep -oi 'Content-Type\|setContentType\|contentType' || true)
154
+ local has_disposition=$(echo "$EDIT_CONTENT" | grep -oi 'Content-Disposition\|setContentDisposition\|setHeader.*attachment' || true)
155
+
156
+ local is_export=$(echo "$EDIT_CONTENT" | grep -oi '/export' || true)
157
+
158
+ if [ -n "$is_export" ] && [ -n "$returns_response" ] && [ -z "$has_servlet_response" ]; then
159
+ log_fail "Hook A [文件流接口]: 路径含 /export 且返回 Response<T>,应直接操作 HttpServletResponse 返回文件流"
160
+ else
161
+ if [ -n "$method_names" ] || [ -n "$api_op" ]; then
162
+ if [ -z "$has_servlet_response" ]; then
163
+ log_warning "Hook A [文件流接口]: 疑似文件流接口但未使用 HttpServletResponse"
164
+ fi
165
+ if [ -z "$has_content_type" ]; then
166
+ log_warning "Hook A [文件流接口]: 文件流接口未设置 Content-Type"
167
+ fi
168
+ if [ -z "$has_disposition" ]; then
169
+ log_warning "Hook A [文件流接口]: 文件流接口未设置 Content-Disposition"
170
+ fi
171
+ fi
172
+ fi
173
+ }
174
+
175
+ ###############################################################################
176
+ # Hook B:导入失败码检查
177
+ #
178
+ # 触发条件:
179
+ # - Controller 方法路径包含 /import
180
+ # - 且返回类型或方法体出现 ImportResult
181
+ # - 或 data 中有 failureCount/failureRows
182
+ #
183
+ # 排除条件:
184
+ # - 普通异步导入任务创建接口,不直接返回导入结果
185
+ # - 只返回任务 ID 的接口
186
+ #
187
+ # 检查规则:
188
+ # - 不允许无条件 Response.ok(result)
189
+ # - 必须存在 failureCount > 0 时返回非 0 业务 code 的分支
190
+ # - 文档必须说明失败行时前端如何判断失败
191
+ #
192
+ # 严重级别:
193
+ # - 有 failureCount 且无失败码分支:fail
194
+ ###############################################################################
195
+
196
+ hook_b_import_failure_code() {
197
+ case "$FILE_PATH" in
198
+ *Controller*.java|*controller*.java|*Service*.java|*service*.java|*ServiceImpl*.java) ;;
199
+ *) return ;;
200
+ esac
201
+
202
+ # 触发条件:包含 /import 或 ImportResult 或 failureCount
203
+ local has_import_path=$(echo "$EDIT_CONTENT" | grep -oi '/import' || true)
204
+ local has_import_result=$(echo "$EDIT_CONTENT" | grep -oi 'ImportResult\|ImportResp\|failureCount\|failureRows' || true)
205
+
206
+ if [ -z "$has_import_path" ] && [ -z "$has_import_result" ]; then
207
+ return
208
+ fi
209
+
210
+ log_debug "Hook B: 检测到导入接口关键词"
211
+
212
+ # 排除条件:只返回任务 ID
213
+ local task_only=$(echo "$EDIT_CONTENT" | grep -oiE '(taskId|task_id|任务ID|异步导入)' || true)
214
+ if [ -n "$task_only" ] && [ -z "$has_import_result" ]; then
215
+ log_debug "Hook B: 只返回任务 ID,跳过"
216
+ return
217
+ fi
218
+
219
+ # 检查是否有 failureCount 但无条件返回 Response.ok
220
+ local has_failure_count=$(echo "$EDIT_CONTENT" | grep -oi 'failureCount' || true)
221
+ local has_ok_unconditional=$(echo "$EDIT_CONTENT" | grep -oiE 'Response\.ok\(.*result' || true)
222
+ local has_failure_branch=$(echo "$EDIT_CONTENT" | grep -oiE '(failureCount\s*>\s*0|failureCount\s*!=\s*0|getFailureCount|hasFail)' || true)
223
+
224
+ if [ -n "$has_failure_count" ] && [ -z "$has_failure_branch" ]; then
225
+ log_fail "Hook B [导入失败码]: 存在 failureCount 但无失败码判断分支,failureCount > 0 时必须返回非 0 业务 code"
226
+ elif [ -n "$has_failure_count" ] && [ -n "$has_failure_branch" ]; then
227
+ log_debug "Hook B: 存在失败码分支,通过"
228
+ fi
229
+ }
230
+
231
+ ###############################################################################
232
+ # Hook C:Excel 日期格式检查
233
+ #
234
+ # 触发条件:
235
+ # - 变更文件含 @ExcelProperty
236
+ # - 且列名包含"时间""日期"
237
+ # - 或类名/文件名包含 Import/Excel/Template
238
+ #
239
+ # 排除条件:
240
+ # - 纯导出 DTO,不参与导入解析
241
+ # - 文档明确要求前端只能传完整时间且有前端校验证据
242
+ #
243
+ # 检查规则:
244
+ # - 日期解析应支持 yyyy-MM-dd,或文档明确说明不支持
245
+ # - tests.md 或单测必须覆盖 yyyy-MM-dd
246
+ # - 如果只有日期,应说明是否补 00:00:00
247
+ #
248
+ # 严重级别:
249
+ # - 导入字段含日期但无格式说明:warning
250
+ # - 已知前端模板为日期但后端只支持完整时间:fail
251
+ ###############################################################################
252
+
253
+ hook_c_excel_date() {
254
+ case "$FILE_PATH" in
255
+ *.java) ;;
256
+ *) return ;;
257
+ esac
258
+
259
+ # 触发条件
260
+ local has_excel_prop=$(echo "$EDIT_CONTENT" | grep -oi '@ExcelProperty' || true)
261
+ local has_date_col=$(echo "$EDIT_CONTENT" | grep -oiE '(时间|日期|date|time|Date|Time)' || true)
262
+ local has_import_name=$(echo "$FILE_PATH" | grep -oiE '(Import|Excel|Template)' || true)
263
+
264
+ if [ -z "$has_excel_prop" ]; then
265
+ return
266
+ fi
267
+
268
+ if [ -z "$has_date_col" ] && [ -z "$has_import_name" ]; then
269
+ return
270
+ fi
271
+
272
+ log_debug "Hook C: 检测到 Excel 日期字段"
273
+
274
+ # 排除条件:纯导出 DTO
275
+ local is_export_only=$(echo "$FILE_PATH" | grep -oiE '(Export|导出)' || true)
276
+ local has_export_annotation=$(echo "$EDIT_CONTENT" | grep -oi 'class.*Export.*DTO\|class.*Export.*Vo\|class.*Export.*Model' || true)
277
+ if [ -n "$is_export_only" ] || [ -n "$has_export_annotation" ]; then
278
+ log_debug "Hook C: 纯导出 DTO,跳过"
279
+ return
280
+ fi
281
+
282
+ # 检查日期格式是否兼容
283
+ local has_short_date=$(echo "$EDIT_CONTENT" | grep -oi 'yyyy-MM-dd[^-]' || true)
284
+ local has_full_date=$(echo "$EDIT_CONTENT" | grep -oi 'yyyy-MM-dd HH:mm:ss' || true)
285
+ local has_date_format_annotation=$(echo "$EDIT_CONTENT" | grep -oiE '@DateTimeFormat|@JsonFormat|DateTimeFormatter|SimpleDateFormat' || true)
286
+
287
+ if [ -n "$has_date_col" ] && [ -n "$has_import_name" ]; then
288
+ if [ -z "$has_date_format_annotation" ]; then
289
+ log_warning "Hook C [Excel 日期]: 导入 DTO 含日期字段但未指定日期格式,应至少兼容 yyyy-MM-dd 和 yyyy-MM-dd HH:mm:ss"
290
+ elif [ -n "$has_full_date" ] && [ -z "$has_short_date" ]; then
291
+ log_fail "Hook C [Excel 日期]: 后端只支持 yyyy-MM-dd HH:mm:ss,但 Excel 默认日期格式为 yyyy-MM-dd,应兼容两种格式"
292
+ fi
293
+ elif [ -n "$has_date_col" ]; then
294
+ log_warning "Hook C [Excel 日期]: @ExcelProperty 含日期/时间列,确认日期格式是否兼容 yyyy-MM-dd"
295
+ fi
296
+ }
297
+
298
+ ###############################################################################
299
+ # Hook D:Excel 模板列头一致性检查
300
+ #
301
+ # 触发条件:
302
+ # - 变更包含 EasyExcel.write 或 EasyExcel.read
303
+ # - 或变更包含 @ExcelProperty
304
+ #
305
+ # 排除条件:
306
+ # - 与 Excel 无关的普通 DTO
307
+ #
308
+ # 检查规则:
309
+ # - 模板下载 DTO 和导入解析 DTO 的列头应一致
310
+ # - api.md/tests.md 应列出列头
311
+ # - 不得出现隐藏字段、内部 ID、状态列等已明确禁止字段
312
+ #
313
+ # 严重级别:
314
+ # - 模板列头和导入列头明显不一致:fail
315
+ # - 文档未列头:warning
316
+ ###############################################################################
317
+
318
+ hook_d_excel_header_consistency() {
319
+ case "$FILE_PATH" in
320
+ *.java) ;;
321
+ *) return ;;
322
+ esac
323
+
324
+ local has_excel_prop=$(echo "$EDIT_CONTENT" | grep -oi '@ExcelProperty' || true)
325
+ local has_easyexcel=$(echo "$EDIT_CONTENT" | grep -oi 'EasyExcel' || true)
326
+
327
+ if [ -z "$has_excel_prop" ] && [ -z "$has_easyexcel" ]; then
328
+ return
329
+ fi
330
+
331
+ log_debug "Hook D: 检测到 EasyExcel 或 @ExcelProperty"
332
+
333
+ # 检查是否有内部字段(不应出现在模板中的)
334
+ local has_internal_id=$(echo "$EDIT_CONTENT" | grep -oiE '@ExcelProperty.*"(id|ID|状态|status|内部|internal)"' || true)
335
+ local has_hidden_field=$(echo "$EDIT_CONTENT" | grep -oiE '@ExcelProperty.*"(create_time|update_time|create_by|update_by|deleted|is_deleted)"' || true)
336
+
337
+ if [ -n "$has_internal_id" ] || [ -n "$has_hidden_field" ]; then
338
+ log_warning "Hook D [Excel 列头]: @ExcelProperty 包含内部字段(id/status/create_time 等),确认是否应出现在导入模板中"
339
+ fi
340
+
341
+ # 如果是模板 DTO,检查是否有对应的导入 DTO
342
+ local is_template=$(echo "$FILE_PATH" | grep -oiE '(Template|模板)' || true)
343
+ local is_import=$(echo "$FILE_PATH" | grep -oiE '(Import|导入)' || true)
344
+
345
+ if [ -n "$is_template" ] || [ -n "$is_import" ]; then
346
+ # 提取列头
347
+ local headers=$(echo "$EDIT_CONTENT" | grep -oiE '@ExcelProperty\("([^"]+)"' | sed 's/.*"\([^"]*\)".*/\1/' | sort | tr '\n' ',' || true)
348
+ if [ -n "$headers" ]; then
349
+ log_warning "Hook D [Excel 列头]: 检测到 DTO 列头: [${headers%,}],请确认模板下载 DTO 和导入解析 DTO 列头一致"
350
+ fi
351
+ fi
352
+ }
353
+
354
+ ###############################################################################
355
+ # Hook E:api.md 与 Controller 路由一致性检查
356
+ #
357
+ # 触发条件:
358
+ # - Controller 新增/修改 @GetMapping/@PostMapping/@PutMapping/@DeleteMapping
359
+ #
360
+ # 排除条件:
361
+ # - /internal/ 路径
362
+ # - 第三方回调
363
+ # - 注释标记 legacy/兼容/历史
364
+ #
365
+ # 检查规则:
366
+ # - Controller 新增 mapping 应能在 api.md 找到
367
+ # - 同一资源下存在固定路径和 {id} 时提示路由抢占风险
368
+ #
369
+ # 严重级别:
370
+ # - Controller 存在但 api.md 缺失:warning
371
+ # - {id} 抢占风险:warning
372
+ ###############################################################################
373
+
374
+ hook_e_route_consistency() {
375
+ case "$FILE_PATH" in
376
+ *Controller*.java|*controller*.java) ;;
377
+ *) return ;;
378
+ esac
379
+
380
+ # 检测新增的 mapping
381
+ local has_new_mapping=$(echo "$EDIT_CONTENT" | grep -oiE '@(Get|Post|Put|Delete|Patch|Request)Mapping' || true)
382
+ if [ -z "$has_new_mapping" ]; then
383
+ return
384
+ fi
385
+
386
+ log_debug "Hook E: 检测到 Controller mapping 变更"
387
+
388
+ # 排除条件
389
+ local is_internal=$(echo "$EDIT_CONTENT" | grep -oiE '/internal/' || true)
390
+ local is_callback=$(echo "$EDIT_CONTENT" | grep -oiE '(callback|回调|notify|通知)' || true)
391
+ local is_legacy=$(echo "$EDIT_CONTENT" | grep -oiE '(legacy|兼容|历史|deprecated)' || true)
392
+
393
+ if [ -n "$is_internal" ] || [ -n "$is_legacy" ]; then
394
+ log_debug "Hook E: 命中排除条件,跳过"
395
+ return
396
+ fi
397
+
398
+ # 提取路径
399
+ local paths=$(echo "$EDIT_CONTENT" | grep -oiE '@(Get|Post|Put|Delete)Mapping\s*\(\s*"?(/[^"]*)"?|value\s*=\s*"?(/[^"]*)"?|path\s*=\s*"?(/[^"]*)"?' | grep -oiE '/[^"]+' | sed 's/"//g;s/)$//' || true)
400
+
401
+ if [ -z "$paths" ]; then
402
+ return
403
+ fi
404
+
405
+ # 检查 {id} 与固定路径冲突
406
+ local has_id_path=$(echo "$paths" | grep -oi '{id}' || true)
407
+ local has_fixed_path=$(echo "$EDIT_CONTENT" | grep -oiE '@(Get|Post|Put|Delete)Mapping\s*\(\s*"?(/[a-zA-Z]+)"?' | grep -vi '{' || true)
408
+
409
+ if [ -n "$has_id_path" ] && [ -n "$has_fixed_path" ]; then
410
+ log_warning "Hook E [路由一致性]: 同一 Controller 下存在固定路径和 {id} 路径变量,存在路由抢占风险。建议固定路径排在 {id} 之前或使用正则约束"
411
+ fi
412
+
413
+ # 检查是否有对应的 api.md
414
+ local api_md_path=$(find "$REPO_ROOT/doc" -name "api.md" -type f 2>/dev/null | head -1)
415
+ if [ -n "$api_md_path" ] && [ -f "$api_md_path" ]; then
416
+ for p in $paths; do
417
+ local clean_path=$(echo "$p" | sed 's/[{}]//g' | sed 's/^\///')
418
+ local found=$(grep -oi "$clean_path" "$api_md_path" 2>/dev/null || true)
419
+ if [ -z "$found" ]; then
420
+ log_warning "Hook E [路由一致性]: Controller 新增路径 $p 未在 api.md 中找到对应定义,请补充接口文档"
421
+ fi
422
+ done
423
+ fi
424
+ }
425
+
426
+ ###############################################################################
427
+ # Hook F:数据权限决策检查(Data Permission Decision Check)
428
+ #
429
+ # 不判断具体字段名,不替用户决定是否需要数据权限。
430
+ # 只检查文档是否已做出三选一结论:
431
+ # - 需要数据权限,并说明复用模式
432
+ # - 不需要数据权限,并说明原因
433
+ # - 不确定,列入待确认问题并阻塞实现
434
+ #
435
+ # 触发条件:
436
+ # - Controller/Service/Mapper 改动
437
+ # - 且方法名/路径/注释含访问类动作关键词
438
+ #
439
+ # 排除条件:
440
+ # - 登录/验证码/健康检查/公开字典/枚举/静态配置
441
+ # - 文档明确说明由统一注解/AOP/网关处理
442
+ #
443
+ # 严重级别:
444
+ # - 无数据权限判断文档:warning
445
+ # - 写操作无权限迹象且无文档说明:high warning
446
+ # - 文档标记"不确定":info,提示阻塞实现
447
+ ###############################################################################
448
+
449
+ hook_f_permission_decision() {
450
+ case "$FILE_PATH" in
451
+ *Controller*.java|*controller*.java|*Service*.java|*service*.java|*ServiceImpl*.java|*.xml) ;;
452
+ *) return ;;
453
+ esac
454
+
455
+ # 触发条件:方法名/路径含访问类动作
456
+ local has_access_action=$(echo "$EDIT_CONTENT" | grep -oiE '(list|page|query|search|detail|get|export|update|delete|refund|approve|分页|列表|查询|详情|导出|编辑|删除|退款|审批)' || true)
457
+
458
+ if [ -z "$has_access_action" ]; then
459
+ return
460
+ fi
461
+
462
+ log_debug "Hook F: 检测到访问类动作关键词"
463
+
464
+ # 排除条件:公开接口、登录、健康检查等
465
+ # 注意:Java 方法声明中的 public 不是公开接口标记,需排除
466
+ local content_without_java_modifiers=$(echo "$EDIT_CONTENT" | sed 's/public\s\+class//g; s/public\s\+\(static\)\?//g; s/private\s\+//g; s/protected\s\+//g' 2>/dev/null)
467
+ local is_public=$(echo "$content_without_java_modifiers" | grep -oiE '(login|captcha|验证码|健康检查|health|dict|字典|enum|枚举|公开接口|no-data-scope)' || true)
468
+ if [ -n "$is_public" ]; then
469
+ log_debug "Hook F: 公开/登录/字典接口,跳过"
470
+ return
471
+ fi
472
+
473
+ # 提取接口方法名用于提示
474
+ local method_name=$(echo "$EDIT_CONTENT" | grep -oiE '(list[A-Z]\w+|page[A-Z]\w+|query[A-Z]\w+|search[A-Z]\w+|get[A-Z]\w+|detail[A-Z]\w+|export[A-Z]\w+|update[A-Z]\w+|delete[A-Z]\w+|refund[A-Z]\w+|approve[A-Z]\w+)' | head -1 || true)
475
+
476
+ # 检查是否为写操作
477
+ local is_write_op=$(echo "$EDIT_CONTENT" | grep -oiE '(update|delete|refund|approve|编辑|删除|退款|审批|@PostMapping|@PutMapping|@DeleteMapping)' || true)
478
+
479
+ # 查找 api.md 和 design.md
480
+ local api_md_path=$(find "$REPO_ROOT/doc" -name "api.md" -type f 2>/dev/null | head -1)
481
+ local design_md_path=$(find "$REPO_ROOT/doc" -name "design.md" -type f 2>/dev/null | head -1)
482
+
483
+ # 检查文档中是否有数据权限说明
484
+ local has_permission_doc=""
485
+ for md_file in "$api_md_path" "$design_md_path"; do
486
+ if [ -f "$md_file" ]; then
487
+ has_permission_doc=$(grep -oiE '(数据权限|权限边界|权限决策|角色.*范围|越权|待确认.*权限|不需要.*权限|统一.*AOP|统一.*注解|网关.*控制)' "$md_file" 2>/dev/null || true)
488
+ if [ -n "$has_permission_doc" ]; then
489
+ break
490
+ fi
491
+ fi
492
+ done
493
+
494
+ # 检查代码中是否使用了权限相关模式
495
+ local has_permission_code=$(echo "$EDIT_CONTENT" | grep -oiE '(DataScope|DataPermission|@RequiresPermissions|@PreAuthorize|@Secured|checkPermission|getDataScope|getCurrentUser|getLoginUser|SecurityUtils|UserContext|TenantContext|@DataFilter)' || true)
496
+
497
+ # 检查文档是否标记"不确定"
498
+ local has_pending=$(echo "$has_permission_doc" | grep -oi '待确认' || true)
499
+
500
+ if [ -n "$has_pending" ]; then
501
+ # 文档标记不确定,提示阻塞实现
502
+ log_warning "Hook F [数据权限决策]: api.md 已标记数据权限\"不确定\",实现应阻塞,等待用户确认角色数据范围"
503
+ return
504
+ fi
505
+
506
+ if [ -z "$has_permission_doc" ] && [ -z "$has_permission_code" ]; then
507
+ # 无文档也无代码权限迹象
508
+ if [ -n "$is_write_op" ]; then
509
+ # 写操作高风险
510
+ log_warning "Hook F [数据权限决策][HIGH] 检测到写操作接口 ${method_name:-未识别方法名}。
511
+ 未发现当前用户上下文、权限注解、归属校验或既有权限工具调用;
512
+ 文档也未说明由统一 AOP/网关控制。
513
+ 请确认是否存在越权风险;如由统一机制处理,请在 design.md/api.md 中注明。"
514
+ else
515
+ # 读操作普通风险
516
+ log_warning "Hook F [数据权限决策] 检测到新增接口 ${method_name:-未识别方法名}。
517
+ 未在 api.md/design.md 中找到数据权限说明。
518
+ 请确认:
519
+ 1. 该接口是否访问业务数据;
520
+ 2. 若访问业务数据,是否需要数据权限(需要/不需要/不确定);
521
+ 3. 若需要,复用当前仓库哪个已有权限模式;
522
+ 4. 若不确定,请列为待确认问题并询问用户。"
523
+ fi
524
+ fi
525
+ }
526
+
527
+ ###############################################################################
528
+ # Hook G:外部 SDK 参数契约检查
529
+ #
530
+ # 触发条件:
531
+ # - 变更包含 SDK client、RPC client、MQ client、第三方 API client
532
+ # - 或 pom 里 SDK 版本变化
533
+ #
534
+ # 排除条件:
535
+ # - 纯内部工具类
536
+ #
537
+ # 检查规则:
538
+ # - api.md/design.md 必须写 SDK 参数来源
539
+ # - tests.md 必须写真实响应或阻塞证据
540
+ # - SDK 版本变更必须记录原因
541
+ #
542
+ # 严重级别:
543
+ # - SDK 参数新增但无来源说明:warning
544
+ # - SDK 版本变更但无说明:warning
545
+ ###############################################################################
546
+
547
+ hook_g_sdk_contract() {
548
+ case "$FILE_PATH" in
549
+ *.java|*.xml|pom.xml|build.gradle) ;;
550
+ *) return ;;
551
+ esac
552
+
553
+ # 触发条件
554
+ local has_sdk=$(echo "$EDIT_CONTENT" | grep -oiE '(Client|Sdk|SDK|RPC|Feign|Dubbo|MQ|Kafka|RabbitMQ|RocketMQ|HttpClient|RestTemplate|WebClient)' || true)
555
+ local has_sdk_import=$(echo "$EDIT_CONTENT" | grep -oiE 'import.*\.(sdk|client|rpc|feign|dubbo|mq)' || true)
556
+
557
+ if [ -z "$has_sdk" ] && [ -z "$has_sdk_import" ]; then
558
+ return
559
+ fi
560
+
561
+ # 排除条件:纯内部工具类
562
+ local is_utility=$(echo "$FILE_PATH" | grep -oiE '(util|Utils|helper|Helper|tool|Tool)' || true)
563
+ if [ -n "$is_utility" ] && [ -z "$has_sdk_import" ]; then
564
+ log_debug "Hook G: 纯工具类,跳过"
565
+ return
566
+ fi
567
+
568
+ log_debug "Hook G: 检测到外部 SDK/RPC/MQ 调用"
569
+
570
+ # 检查参数来源说明
571
+ local has_param_source=$(echo "$EDIT_CONTENT" | grep -oiE '(参数来源|来源说明|param.*from|参数.*传)' || true)
572
+
573
+ # 检查 api.md/design.md
574
+ local api_md_path=$(find "$REPO_ROOT/doc" -name "api.md" -type f 2>/dev/null | head -1)
575
+ local design_md_path=$(find "$REPO_ROOT/doc" -name "design.md" -type f 2>/dev/null | head -1)
576
+
577
+ local sdk_doc_found=""
578
+ for md_file in "$api_md_path" "$design_md_path"; do
579
+ if [ -f "$md_file" ]; then
580
+ sdk_doc_found=$(grep -oi '外部依赖契约\|SDK.*参数来源\|SDK.*版本' "$md_file" 2>/dev/null || true)
581
+ if [ -n "$sdk_doc_found" ]; then
582
+ break
583
+ fi
584
+ fi
585
+ done
586
+
587
+ if [ -z "$sdk_doc_found" ]; then
588
+ log_warning "Hook G [SDK 契约]: 检测到外部 SDK/RPC/MQ 调用,但 api.md/design.md 未定义外部依赖契约(参数来源、SDK 版本、响应样例)"
589
+ fi
590
+
591
+ # 检查 pom.xml 版本变更
592
+ case "$FILE_PATH" in
593
+ *pom.xml*|*build.gradle*)
594
+ local version_change=$(echo "$EDIT_CONTENT" | grep -oiE '(version|<version>)' || true)
595
+ if [ -n "$version_change" ]; then
596
+ log_warning "Hook G [SDK 契约]: 检测到依赖版本变更,请确认是否有版本变更说明"
597
+ fi
598
+ ;;
599
+ esac
600
+ }
601
+
602
+ ###############################################################################
603
+ # Hook H:跨仓数据合同 / MyBatis-Plus 实体字段检查
604
+ #
605
+ # 触发条件:
606
+ # - Java/XML 变更包含 @TableName、BaseMapper、@TableField
607
+ # - 或包含 QueryWrapper/LambdaQueryWrapper/resultMap/列映射
608
+ # - 或文档声称真实链路/联调通过
609
+ #
610
+ # 检查规则:
611
+ # - MyBatis-Plus 实体字段必须能在真实表结构中找到
612
+ # - 旧字段应删除或 @TableField(exist = false)
613
+ # - 多仓共享表必须列出消费仓并做字段对账
614
+ # - mock/test controller 证据不能替代真实入口验收
615
+ #
616
+ # 严重级别:
617
+ # - warning/high warning,不直接全局失败;由 SDD quality gate 阻塞交付
618
+ ###############################################################################
619
+
620
+ hook_h_cross_schema_contract() {
621
+ case "$FILE_PATH" in
622
+ *.java|*.xml|*.md) ;;
623
+ *) return ;;
624
+ esac
625
+
626
+ local has_schema_mapping=$(echo "$EDIT_CONTENT" | grep -oiE '(@TableName|BaseMapper<|@TableField|LambdaQueryWrapper|QueryWrapper|resultMap|<result[[:space:]]+column=|<id[[:space:]]+column=)' || true)
627
+ local has_real_claim=$(echo "$EDIT_CONTENT" | grep -oiE '(真实链路通过|真实入口通过|联调通过|Passed|Real integration passed)' || true)
628
+ local has_mock_signal=$(echo "$EDIT_CONTENT" | grep -oiE '(mock|Mock|测试端点|test controller|绕过鉴权|bypass)' || true)
629
+
630
+ if [ -n "$has_schema_mapping" ]; then
631
+ log_warning "Hook H [跨仓数据合同][HIGH] 检测到 MyBatis/MyBatis-Plus 实体、Mapper 或查询条件变更。
632
+ 请完成跨仓数据合同对账:
633
+ 1. 明确表结构真源(版本总 SQL / database-contract / SHOW CREATE TABLE);
634
+ 2. 列出全部消费仓(当前服务、sibling service、互联互通、回调、定时任务、测试端点);
635
+ 3. 对照 @TableName 实体字段、BaseMapper 默认 SELECT、Mapper XML/resultMap、手写 SQL 与真实库字段;
636
+ 4. 不存在列必须删除或 @TableField(exist = false),不得给测试库补废弃字段绕过;
637
+ 5. 字段迁移后同步查询条件,例如状态字段派生、多站点 JSON 快照等。"
638
+ fi
639
+
640
+ case "$FILE_PATH" in
641
+ *.md)
642
+ if [ -n "$has_real_claim" ] && [ -n "$has_mock_signal" ]; then
643
+ log_warning "Hook H [真实入口验收][HIGH] 文档同时出现真实通过结论和 mock/测试端点证据。
644
+ 请把 Mock 验证、测试端点验证、真实入口验证分开记录;
645
+ 测试 Controller、mock endpoint、绕过鉴权端点只能证明局部路径;
646
+ 真实入口通过必须包含 payload、响应、trace 日志、DB 证据。"
647
+ fi
648
+ ;;
649
+ esac
650
+ }
651
+
652
+ ###############################################################################
653
+ # Hook I:Superpowers HOW/合同权责边界检查
654
+ #
655
+ # 触发条件:
656
+ # - Markdown 变更包含 superpower / Superpower
657
+ # - 尤其是 prompt 或 design 相关文档
658
+ #
659
+ # 检查规则:
660
+ # - OpenSpec/SDD 文档是 WHAT/API/DB/tests 合同事实源
661
+ # - Superpowers 可以接管源码级 HOW 技术详设
662
+ # - Superpowers 不得重写 design.md/api.md/tests 或覆盖 API/DB/字段语义合同
663
+ #
664
+ # 严重级别:
665
+ # - 明确要求 Superpowers 覆盖合同:fail
666
+ # - 使用 Superpowers 但缺少技术详设继承章节:warning
667
+ ###############################################################################
668
+
669
+ hook_i_superpower_design_boundary() {
670
+ case "$FILE_PATH" in
671
+ *.md) ;;
672
+ *) return ;;
673
+ esac
674
+
675
+ local has_superpower=$(echo "$CHECK_CONTENT" | grep -oiE 'superpower|Superpower' || true)
676
+ if [ -z "$has_superpower" ]; then
677
+ return
678
+ fi
679
+
680
+ local risky_line=$(echo "$CHECK_CONTENT" | python3 -c '
681
+ import re, sys
682
+ text = sys.stdin.read()
683
+ allow = re.compile(r"(禁止|不得|不允许|不能|事实源|canonical|must not|do not|forbid)", re.I)
684
+ risky = re.compile(
685
+ r"(superpower|Superpower).{0,40}(重写|替代|覆盖).{0,40}(design\.md|api\.md|tests\.md|API|DB|SQL|字段语义|合同|验收)"
686
+ r"|"
687
+ r"(重写|替代|覆盖).{0,40}(design\.md|api\.md|tests\.md|API|DB|SQL|字段语义|合同|验收).{0,40}(superpower|Superpower)",
688
+ re.I,
689
+ )
690
+ for line in text.splitlines():
691
+ if risky.search(line) and not allow.search(line):
692
+ print(line[:240])
693
+ break
694
+ ' 2>/dev/null)
695
+
696
+ if [ -n "$risky_line" ]; then
697
+ log_fail "Hook I [Superpowers 边界]: 检测到疑似让 Superpowers 覆盖 OpenSpec/SDD 合同的指令:$risky_line
698
+ OpenSpec/SDD 的 design.md、api.md、tests.md、SQL/DB、字段语义和验收门禁是合同事实源;
699
+ Superpowers 可以接管源码级 HOW 技术详设,但不能覆盖合同。"
700
+ fi
701
+
702
+ case "$FILE_PATH" in
703
+ */prompt/*.md|*prompt*.md)
704
+ local has_strategy=$(echo "$CHECK_CONTENT" | grep -oiE 'Superpower 技术详设继承|technical_design|Superpowers 技术详设|源码级 HOW|Superpower 执行策略继承' || true)
705
+ if [ -z "$has_strategy" ]; then
706
+ log_warning "Hook I [Superpowers 边界]: prompt 使用了 Superpowers,但未看到 'Superpower 技术详设继承' 或 technical_design 边界。
707
+ 请从 .sdd/state.yaml 的 technical_design 继承源码级 HOW,并声明 OpenSpec/SDD 合同不可覆盖。"
708
+ fi
709
+ local has_field_status_risk=$(echo "$CHECK_CONTENT" | grep -oiE '字段值|状态|枚举|online|offline|上线|下线|删除|恢复|同步标记|payment|refund|支付|退款|第三方状态|running_status|offline_time' || true)
710
+ local has_reverse_impact=$(echo "$CHECK_CONTENT" | grep -oiE '字段/状态反向影响面|Field And Status Reverse Impact|读取/过滤点|派生/同步点|跨模块消费方' || true)
711
+ if [ -n "$has_field_status_risk" ] && [ -z "$has_reverse_impact" ]; then
712
+ log_warning "Hook I [字段/状态反向影响面]: prompt 涉及字段/状态/枚举/同步值,但未看到反向影响面矩阵。
713
+ 请从 Superpowers technical_design 继承 writers/readers/filters/sync/consumer/test 矩阵,避免只改直接写入点。"
714
+ fi
715
+ ;;
716
+ esac
717
+ }
718
+
719
+ ###############################################################################
720
+ # 执行所有检查器
721
+ ###############################################################################
722
+
723
+ hook_a_file_stream
724
+ hook_b_import_failure_code
725
+ hook_c_excel_date
726
+ hook_d_excel_header_consistency
727
+ hook_e_route_consistency
728
+ hook_f_permission_decision
729
+ hook_g_sdk_contract
730
+ hook_h_cross_schema_contract
731
+ hook_i_superpower_design_boundary
732
+
733
+ # 输出结果
734
+ if [ -n "$WARNINGS" ]; then
735
+ echo "$WARNINGS"
736
+ echo ""
737
+ echo "[SDD 契约检查] 详细说明请参考 superflow-pipeline/references/api-design-template.md"
738
+ fi
739
+
740
+ if [ -n "$HAS_FAIL" ]; then
741
+ exit 2
742
+ fi
743
+
744
+ exit 0