@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,574 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ usage() {
5
+ cat <<'USAGE'
6
+ Usage:
7
+ superflow-state.sh init <change-dir> [workflow|phase] [phase]
8
+ superflow-state.sh status <change-dir>
9
+ superflow-state.sh set <change-dir> <key> <value>
10
+ superflow-state.sh get <change-dir> <key>
11
+ superflow-state.sh phase <change-dir>
12
+ superflow-state.sh transition <change-dir> <docs-complete|design-complete|implement-complete|verify-pass|verify-fail|archive-reopen|archived>
13
+ superflow-state.sh next <change-dir>
14
+ superflow-state.sh recover <change-dir>
15
+ superflow-state.sh scale <change-dir>
16
+ superflow-state.sh task-checkoff <file> <task-text>
17
+
18
+ State is stored at <change-dir>/.sdd/state.yaml.
19
+ USAGE
20
+ }
21
+
22
+ die() {
23
+ printf 'superflow-state: %s\n' "$*" >&2
24
+ exit 1
25
+ }
26
+
27
+ today_utc() {
28
+ date -u '+%Y-%m-%d'
29
+ }
30
+
31
+ now_utc() {
32
+ date -u '+%Y-%m-%dT%H:%M:%SZ'
33
+ }
34
+
35
+ state_file() {
36
+ printf '%s/.sdd/state.yaml' "$1"
37
+ }
38
+
39
+ ensure_change_dir() {
40
+ [[ -d "$1" ]] || die "change dir not found: $1"
41
+ }
42
+
43
+ normalize_null() {
44
+ local value="${1:-}"
45
+ if [[ -z "$value" || "$value" == "null" ]]; then
46
+ printf 'null'
47
+ else
48
+ printf '%s' "$value"
49
+ fi
50
+ }
51
+
52
+ yaml_value_from_file() {
53
+ local file="$1"
54
+ local key="$2"
55
+ [[ -f "$file" ]] || return 1
56
+ awk -F':' -v k="$key" '
57
+ $1 == k {
58
+ value = $0
59
+ sub("^[^:]*:[[:space:]]*", "", value)
60
+ sub("[[:space:]]+#.*$", "", value)
61
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
62
+ gsub(/^"|"$/, "", value)
63
+ gsub(/^'\''|'\''$/, "", value)
64
+ print value
65
+ found=1
66
+ }
67
+ END { exit found ? 0 : 1 }
68
+ ' "$file"
69
+ }
70
+
71
+ project_root_for_change() {
72
+ if git -C "$CHANGE_DIR" rev-parse --show-toplevel >/dev/null 2>&1; then
73
+ git -C "$CHANGE_DIR" rev-parse --show-toplevel
74
+ else
75
+ dirname "$(dirname "$CHANGE_DIR")"
76
+ fi
77
+ }
78
+
79
+ sdd_config_value() {
80
+ local key="$1"
81
+ local default="$2"
82
+ local env_name="$3"
83
+ local root value
84
+
85
+ if [[ -n "${!env_name:-}" ]]; then
86
+ printf '%s\n' "${!env_name}"
87
+ return
88
+ fi
89
+
90
+ if value="$(yaml_value_from_file "$CHANGE_DIR/.sdd/config.yaml" "$key" 2>/dev/null)"; then
91
+ [[ -n "$value" ]] && { printf '%s\n' "$value"; return; }
92
+ fi
93
+
94
+ root="$(project_root_for_change)"
95
+ if value="$(yaml_value_from_file "$root/.sdd/config.yaml" "$key" 2>/dev/null)"; then
96
+ [[ -n "$value" ]] && { printf '%s\n' "$value"; return; }
97
+ fi
98
+
99
+ printf '%s\n' "$default"
100
+ }
101
+
102
+ review_mode_default() {
103
+ local value
104
+ value="$(sdd_config_value review_mode null SUPERFLOW_REVIEW_MODE)"
105
+ if [[ "$value" == "null" && -n "${SDD_REVIEW_MODE:-}" ]]; then
106
+ value="$SDD_REVIEW_MODE"
107
+ fi
108
+ validate_config_enum review_mode "$value" "null off standard thorough"
109
+ printf '%s\n' "$value"
110
+ }
111
+
112
+ validate_config_enum() {
113
+ local key="$1"
114
+ local value="$2"
115
+ local allowed="$3"
116
+ local item
117
+ for item in $allowed; do
118
+ [[ "$value" == "$item" ]] && return
119
+ done
120
+ die "invalid $key: $value (expected: $allowed)"
121
+ }
122
+
123
+ field_value() {
124
+ local key="$1"
125
+ [[ -f "$STATE_FILE" ]] || return 1
126
+ awk -F':' -v k="$key" '
127
+ $1 == k {
128
+ value = $0
129
+ sub("^[^:]*:[[:space:]]*", "", value)
130
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
131
+ print value
132
+ found=1
133
+ }
134
+ END { exit found ? 0 : 1 }
135
+ ' "$STATE_FILE"
136
+ }
137
+
138
+ replace_field() {
139
+ local key="$1"
140
+ local value="$2"
141
+ local tmp
142
+ tmp="$(mktemp)"
143
+
144
+ if grep -q "^${key}:" "$STATE_FILE" 2>/dev/null; then
145
+ awk -v k="$key" -v v="$value" '
146
+ index($0, k ":") == 1 { print k ": " v; next }
147
+ { print }
148
+ ' "$STATE_FILE" > "$tmp"
149
+ else
150
+ cat "$STATE_FILE" > "$tmp"
151
+ printf '%s: %s\n' "$key" "$value" >> "$tmp"
152
+ fi
153
+
154
+ awk -v now="$(now_utc)" '
155
+ /^updated_at:/ { print "updated_at: " now; seen=1; next }
156
+ { print }
157
+ END { if (!seen) print "updated_at: " now }
158
+ ' "$tmp" > "$STATE_FILE"
159
+ rm -f "$tmp"
160
+ }
161
+
162
+ cmd_init() {
163
+ local workflow_or_phase="${3:-full}"
164
+ local phase="${4:-}"
165
+ local workflow
166
+ local base_ref="null"
167
+ local context_compression auto_transition review_mode
168
+
169
+ case "$workflow_or_phase" in
170
+ docs|design|implement|verify|archive|done)
171
+ workflow="full"
172
+ phase="$workflow_or_phase"
173
+ ;;
174
+ full|hotfix|tweak)
175
+ workflow="$workflow_or_phase"
176
+ phase="${phase:-docs}"
177
+ ;;
178
+ sdd)
179
+ workflow="full"
180
+ phase="${phase:-docs}"
181
+ ;;
182
+ *)
183
+ die "invalid workflow or phase: $workflow_or_phase"
184
+ ;;
185
+ esac
186
+
187
+ mkdir -p "$(dirname "$STATE_FILE")"
188
+ context_compression="$(sdd_config_value context_compression off SDD_CONTEXT_COMPRESSION)"
189
+ auto_transition="$(sdd_config_value auto_transition true SDD_AUTO_TRANSITION)"
190
+ validate_config_enum context_compression "$context_compression" "off beta"
191
+ validate_config_enum auto_transition "$auto_transition" "true false"
192
+ if [[ "$workflow" == "hotfix" || "$workflow" == "tweak" ]]; then
193
+ review_mode="off"
194
+ else
195
+ review_mode="$(review_mode_default)"
196
+ fi
197
+
198
+ if git -C "$CHANGE_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
199
+ if base_ref_candidate="$(git -C "$CHANGE_DIR" rev-parse --verify HEAD 2>/dev/null)"; then
200
+ base_ref="$base_ref_candidate"
201
+ fi
202
+ fi
203
+
204
+ if [[ ! -f "$STATE_FILE" ]]; then
205
+ cat > "$STATE_FILE" <<EOF
206
+ workflow: $workflow
207
+ phase: $phase
208
+ canonical_spec: openspec-sdd
209
+ context_compression: $context_compression
210
+ design_doc: null
211
+ technical_design: null
212
+ plan: null
213
+ base_ref: $base_ref
214
+ build_mode: null
215
+ build_pause: null
216
+ subagent_dispatch: null
217
+ tdd_mode: null
218
+ review_mode: $review_mode
219
+ isolation: null
220
+ verify_mode: null
221
+ auto_transition: $auto_transition
222
+ verify_result: pending
223
+ verification_report: null
224
+ branch_status: pending
225
+ archived: false
226
+ direct_override: false
227
+ build_command: null
228
+ verify_command: null
229
+ handoff_context: null
230
+ handoff_hash: null
231
+ superpower_strategy: null
232
+ implementation_prompt: null
233
+ worktree_ports: null
234
+ created_at: $(today_utc)
235
+ verified_at: null
236
+ updated_at: $(now_utc)
237
+ EOF
238
+ fi
239
+
240
+ printf '%s\n' "$STATE_FILE"
241
+ }
242
+
243
+ cmd_set() {
244
+ local key="${3:-}"
245
+ local value="${4:-}"
246
+ [[ -n "$key" ]] || die "missing key"
247
+ [[ -f "$STATE_FILE" ]] || cmd_init init "$CHANGE_DIR" docs >/dev/null
248
+
249
+ case "$key" in
250
+ phase)
251
+ if [[ "${SUPERFLOW_FORCE_PHASE:-0}" != "1" && "${SDD_FORCE_PHASE:-0}" != "1" ]]; then
252
+ die "setting phase directly is blocked; use superflow-state.sh transition <change-dir> <event> or set SUPERFLOW_FORCE_PHASE=1 for repair"
253
+ fi
254
+ ;;
255
+ workflow|canonical_spec|context_compression|design_doc|technical_design|plan|base_ref|build_mode|build_pause|subagent_dispatch|tdd_mode|review_mode|isolation|verify_mode|auto_transition|verify_result|verification_report|branch_status|archived|direct_override|build_command|verify_command|handoff_context|handoff_hash|superpower_strategy|implementation_prompt|worktree_ports|created_at|verified_at|updated_at) ;;
256
+ *) die "unknown state key: $key" ;;
257
+ esac
258
+
259
+ replace_field "$key" "$(normalize_null "$value")"
260
+ }
261
+
262
+ cmd_get() {
263
+ local key="${3:-}"
264
+ [[ -n "$key" ]] || die "missing key"
265
+ [[ -f "$STATE_FILE" ]] || die "state not found: $STATE_FILE"
266
+ field_value "$key"
267
+ }
268
+
269
+ require_phase() {
270
+ local expected="$1"
271
+ local current
272
+ current="$(field_value phase 2>/dev/null || true)"
273
+ [[ "$current" == "$expected" ]] || die "expected phase '$expected', got '${current:-missing}'"
274
+ }
275
+
276
+ require_file_value_exists() {
277
+ local key="$1"
278
+ local value
279
+ value="$(field_value "$key" 2>/dev/null || true)"
280
+ value="$(normalize_null "$value")"
281
+ [[ "$value" != "null" ]] || die "$key is not set"
282
+ [[ -f "$CHANGE_DIR/$value" || -f "$value" ]] || die "$key path does not exist: $value"
283
+ }
284
+
285
+ require_implement_decisions() {
286
+ local workflow build_mode isolation tdd_mode review_mode subagent_dispatch direct_override
287
+ workflow="$(field_value workflow 2>/dev/null || printf 'full')"
288
+ build_mode="$(field_value build_mode 2>/dev/null || printf 'null')"
289
+ isolation="$(field_value isolation 2>/dev/null || printf 'null')"
290
+ tdd_mode="$(field_value tdd_mode 2>/dev/null || printf 'null')"
291
+ review_mode="$(field_value review_mode 2>/dev/null || printf 'null')"
292
+ subagent_dispatch="$(field_value subagent_dispatch 2>/dev/null || printf 'null')"
293
+ direct_override="$(field_value direct_override 2>/dev/null || printf 'false')"
294
+
295
+ case "$isolation" in branch|worktree|null) ;; *) die "invalid isolation: $isolation" ;; esac
296
+ [[ "$isolation" != "null" ]] || die "isolation must be branch or worktree before verify"
297
+
298
+ case "$build_mode" in subagent-driven-development|executing-plans|team-prompt|direct|null) ;; *) die "invalid build_mode: $build_mode" ;; esac
299
+ [[ "$build_mode" != "null" ]] || die "build_mode must be selected before verify"
300
+
301
+ if [[ "$build_mode" == "subagent-driven-development" && "$subagent_dispatch" != "confirmed" ]]; then
302
+ die "subagent_dispatch must be confirmed for subagent-driven-development"
303
+ fi
304
+
305
+ if [[ "$workflow" == "full" ]]; then
306
+ case "$tdd_mode" in tdd|direct) ;; *) die "tdd_mode must be tdd or direct for full workflow" ;; esac
307
+ case "$review_mode" in off|standard|thorough) ;; *) die "review_mode must be off, standard, or thorough for full workflow" ;; esac
308
+ if [[ "$build_mode" == "direct" && "$direct_override" != "true" ]]; then
309
+ die "full workflow direct build requires direct_override=true"
310
+ fi
311
+ fi
312
+ }
313
+
314
+ cmd_transition() {
315
+ local event="${3:-}"
316
+ [[ -f "$STATE_FILE" ]] || die "state not found: $STATE_FILE"
317
+
318
+ case "$event" in
319
+ docs-complete)
320
+ require_phase docs
321
+ require_file_value_exists handoff_context
322
+ workflow="$(field_value workflow 2>/dev/null || printf 'full')"
323
+ if [[ "$workflow" == "full" ]]; then
324
+ replace_field phase design
325
+ else
326
+ replace_field phase implement
327
+ fi
328
+ ;;
329
+ design-complete)
330
+ require_phase design
331
+ require_file_value_exists technical_design
332
+ replace_field phase implement
333
+ ;;
334
+ implement-complete)
335
+ require_phase implement
336
+ require_implement_decisions
337
+ replace_field phase verify
338
+ replace_field verify_result pending
339
+ replace_field branch_status pending
340
+ ;;
341
+ verify-pass)
342
+ require_phase verify
343
+ require_file_value_exists verification_report
344
+ replace_field verify_result pass
345
+ replace_field verified_at "$(today_utc)"
346
+ replace_field phase archive
347
+ ;;
348
+ verify-fail)
349
+ require_phase verify
350
+ replace_field verify_result fail
351
+ replace_field phase implement
352
+ ;;
353
+ archive-reopen)
354
+ require_phase archive
355
+ replace_field phase verify
356
+ replace_field archived false
357
+ ;;
358
+ archived)
359
+ require_phase archive
360
+ replace_field archived true
361
+ replace_field phase done
362
+ ;;
363
+ *)
364
+ die "unknown transition event: $event"
365
+ ;;
366
+ esac
367
+ }
368
+
369
+ cmd_status() {
370
+ [[ -f "$STATE_FILE" ]] || die "state not found: $STATE_FILE"
371
+ cat "$STATE_FILE"
372
+ }
373
+
374
+ cmd_next() {
375
+ [[ -f "$STATE_FILE" ]] || die "state not found: $STATE_FILE"
376
+ local phase workflow auto archived skill
377
+ phase="$(field_value phase 2>/dev/null || printf 'docs')"
378
+ workflow="$(field_value workflow 2>/dev/null || printf 'full')"
379
+ auto="$(field_value auto_transition 2>/dev/null || printf 'true')"
380
+ archived="$(field_value archived 2>/dev/null || printf 'false')"
381
+
382
+ if [[ "$archived" == "true" || "$phase" == "done" ]]; then
383
+ printf 'NEXT: done\n'
384
+ printf 'HINT: SDD lifecycle is complete.\n'
385
+ return
386
+ fi
387
+
388
+ case "$phase" in
389
+ docs) skill="superflow-docs" ;;
390
+ design) skill="superflow-design" ;;
391
+ implement) skill="superflow-implement" ;;
392
+ verify) skill="superflow-verify" ;;
393
+ archive) skill="superflow-archive" ;;
394
+ *) skill="superflow-pipeline" ;;
395
+ esac
396
+
397
+ if [[ "$workflow" == "hotfix" && "$phase" == "implement" ]]; then
398
+ skill="superflow-hotfix"
399
+ elif [[ "$workflow" == "tweak" && "$phase" == "implement" ]]; then
400
+ skill="superflow-tweak"
401
+ fi
402
+
403
+ if [[ "$auto" == "false" ]]; then
404
+ printf 'NEXT: manual\n'
405
+ else
406
+ printf 'NEXT: auto\n'
407
+ fi
408
+ printf 'SKILL: %s\n' "$skill"
409
+ printf 'PHASE: %s\n' "$phase"
410
+ printf 'HINT: continue with $%s for phase %s.\n' "$skill" "$phase"
411
+ }
412
+
413
+ cmd_recover() {
414
+ [[ -f "$STATE_FILE" ]] || die "state not found: $STATE_FILE"
415
+ local phase handoff hash prompt report verify_result archived technical_design
416
+ local build_pause build_mode isolation plan subagent_dispatch review_mode
417
+ phase="$(field_value phase 2>/dev/null || printf 'docs')"
418
+ handoff="$(field_value handoff_context 2>/dev/null || printf 'null')"
419
+ hash="$(field_value handoff_hash 2>/dev/null || printf 'null')"
420
+ prompt="$(field_value implementation_prompt 2>/dev/null || printf 'null')"
421
+ technical_design="$(field_value technical_design 2>/dev/null || printf 'null')"
422
+ report="$(field_value verification_report 2>/dev/null || printf 'null')"
423
+ verify_result="$(field_value verify_result 2>/dev/null || printf 'pending')"
424
+ archived="$(field_value archived 2>/dev/null || printf 'false')"
425
+ build_pause="$(field_value build_pause 2>/dev/null || printf 'null')"
426
+ build_mode="$(field_value build_mode 2>/dev/null || printf 'null')"
427
+ isolation="$(field_value isolation 2>/dev/null || printf 'null')"
428
+ plan="$(field_value plan 2>/dev/null || printf 'null')"
429
+ subagent_dispatch="$(field_value subagent_dispatch 2>/dev/null || printf 'null')"
430
+ review_mode="$(field_value review_mode 2>/dev/null || printf 'null')"
431
+
432
+ printf 'SDD Recovery\n'
433
+ printf 'phase: %s\n' "$phase"
434
+ printf 'handoff_context: %s\n' "$handoff"
435
+ printf 'handoff_hash: %s\n' "$hash"
436
+ printf 'implementation_prompt: %s\n' "$prompt"
437
+ printf 'technical_design: %s\n' "$technical_design"
438
+ printf 'plan: %s\n' "$plan"
439
+ printf 'build_pause: %s\n' "$build_pause"
440
+ printf 'build_mode: %s\n' "$build_mode"
441
+ printf 'isolation: %s\n' "$isolation"
442
+ printf 'subagent_dispatch: %s\n' "$subagent_dispatch"
443
+ printf 'review_mode: %s\n' "$review_mode"
444
+ printf 'verification_report: %s\n' "$report"
445
+ printf 'verify_result: %s\n' "$verify_result"
446
+ printf 'archived: %s\n' "$archived"
447
+
448
+ case "$phase" in
449
+ docs)
450
+ printf 'Recovery action: read current OpenSpec/SDD contract docs and handoff, regenerate handoff if docs changed, then run superflow-guard docs.\n'
451
+ ;;
452
+ design)
453
+ printf 'Recovery action: read .sdd/handoff/sdd-context.md, api.md, design.md, tests.md, brainstorm-summary.md when present, then use superflow-design to create or refresh technical_design before superflow-guard design.\n'
454
+ ;;
455
+ implement)
456
+ if [[ "$build_pause" == "plan-ready" && "$isolation" != "null" && "$build_mode" != "null" ]]; then
457
+ printf 'Recovery action: stale plan-ready pause detected; run superflow-state.sh set <change-dir> build_pause null, then resume from the first unchecked task using build_mode=%s.\n' "$build_mode"
458
+ elif [[ "$build_pause" == "plan-ready" && "$plan" != "null" ]]; then
459
+ if [[ -f "$CHANGE_DIR/$plan" || -f "$plan" ]]; then
460
+ printf 'Recovery action: plan-ready pause is active; do not regenerate the plan. Ask the user to choose isolation/build_mode/tdd_mode, record decisions, then continue implementation.\n'
461
+ else
462
+ printf 'Recovery action: plan-ready pause is corrupt because plan is missing. Return to superflow-implement to repair or regenerate the plan before coding.\n'
463
+ fi
464
+ elif [[ "$build_mode" == "subagent-driven-development" ]]; then
465
+ printf 'Recovery action: act as coordinator only; reload Superpowers subagent-driven-development, read .sdd/subagent-progress.md, and resume the exact checkpoint without coding in the main session.\n'
466
+ else
467
+ printf 'Recovery action: read .sdd/handoff/sdd-context.md plus api.md/design.md/tests.md and technical_design, verify prompt hash, then continue implementation prompt/worktree from the first incomplete batch.\n'
468
+ fi
469
+ ;;
470
+ verify)
471
+ printf 'Recovery action: read test-report.md, rerun required hook scripts, set verification_report, then run superflow-guard verify.\n'
472
+ ;;
473
+ archive)
474
+ if [[ "$archived" == "true" ]]; then
475
+ printf 'Recovery action: archive already marked complete; do not rerun archive.\n'
476
+ else
477
+ printf 'Recovery action: verification passed; ask user for archive confirmation before marking archived.\n'
478
+ fi
479
+ ;;
480
+ done)
481
+ printf 'Recovery action: lifecycle complete; no further action.\n'
482
+ ;;
483
+ esac
484
+ }
485
+
486
+ cmd_scale() {
487
+ [[ -f "$STATE_FILE" ]] || cmd_init init "$CHANGE_DIR" docs >/dev/null
488
+ local task_count capability_count changed_files risk_hits mode
489
+
490
+ task_count="$(grep -RE '^- \[[ xX]\]' "$CHANGE_DIR"/*.md "$CHANGE_DIR"/**/*.md 2>/dev/null | wc -l | tr -d ' ')"
491
+ capability_count="$(find "$CHANGE_DIR" -path '*/specs/*/spec.md' -type f 2>/dev/null | wc -l | tr -d ' ')"
492
+ changed_files=0
493
+ if git -C "$CHANGE_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
494
+ changed_files="$(git -C "$CHANGE_DIR" diff --name-only HEAD 2>/dev/null | wc -l | tr -d ' ')"
495
+ fi
496
+
497
+ risk_hits="$(grep -REi 'api|接口|curl|SQL|数据库|Mapper|XML|跨仓|状态字段|枚举|真实入口|payment|refund|MQ|定时任务|第三方|SDK' "$CHANGE_DIR"/*.md "$CHANGE_DIR"/**/*.md 2>/dev/null | wc -l | tr -d ' ')"
498
+
499
+ mode="light"
500
+ if [[ "$task_count" -gt 3 || "$capability_count" -gt 1 || "$changed_files" -gt 4 || "$risk_hits" -gt 0 ]]; then
501
+ mode="full"
502
+ fi
503
+
504
+ replace_field verify_mode "$mode"
505
+ printf 'verify_mode: %s\n' "$mode"
506
+ printf 'task_count: %s\n' "$task_count"
507
+ printf 'capability_count: %s\n' "$capability_count"
508
+ printf 'changed_files: %s\n' "$changed_files"
509
+ printf 'sdd_risk_hits: %s\n' "$risk_hits"
510
+ }
511
+
512
+ cmd_task_checkoff() {
513
+ local file="${2:-}"
514
+ local task_text="${3:-}"
515
+ [[ -n "$file" && -n "$task_text" ]] || die "usage: superflow-state.sh task-checkoff <file> <task-text>"
516
+ [[ -f "$file" ]] || die "task file not found: $file"
517
+
518
+ awk -v task="$task_text" '
519
+ index($0, task) > 0 {
520
+ count++
521
+ if ($0 ~ /^[[:space:]]*-[[:space:]]+\[[xX]\]/) checked++
522
+ last=$0
523
+ }
524
+ END {
525
+ if (count == 0) {
526
+ printf "task-checkoff failed: task text not found: %s\n", task > "/dev/stderr"
527
+ exit 1
528
+ }
529
+ if (count > 1) {
530
+ printf "task-checkoff failed: task text is not unique (%d matches): %s\n", count, task > "/dev/stderr"
531
+ exit 1
532
+ }
533
+ if (checked != 1) {
534
+ printf "task-checkoff failed: task is not checked: %s\n", last > "/dev/stderr"
535
+ exit 1
536
+ }
537
+ printf "task-checkoff passed: %s\n", task
538
+ }
539
+ ' "$file"
540
+ }
541
+
542
+ CMD="${1:-}"
543
+ CHANGE_DIR="${2:-}"
544
+
545
+ [[ -n "$CMD" && "$CMD" != "-h" && "$CMD" != "--help" ]] || {
546
+ usage
547
+ exit 0
548
+ }
549
+
550
+ if [[ "$CMD" == "task-checkoff" ]]; then
551
+ cmd_task_checkoff "$@"
552
+ exit 0
553
+ fi
554
+
555
+ [[ -n "$CHANGE_DIR" ]] || die "missing change dir"
556
+ ensure_change_dir "$CHANGE_DIR"
557
+ CHANGE_DIR="$(cd "$CHANGE_DIR" && pwd)"
558
+ STATE_FILE="$(state_file "$CHANGE_DIR")"
559
+
560
+ case "$CMD" in
561
+ init) cmd_init "$@" ;;
562
+ status) cmd_status ;;
563
+ set) cmd_set "$@" ;;
564
+ get) cmd_get "$@" ;;
565
+ phase) cmd_get get "$CHANGE_DIR" phase ;;
566
+ transition) cmd_transition "$@" ;;
567
+ next) cmd_next ;;
568
+ recover) cmd_recover ;;
569
+ scale) cmd_scale ;;
570
+ *)
571
+ usage
572
+ exit 1
573
+ ;;
574
+ esac