@chenmk/superflow 0.4.0 → 0.5.1

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 (242) hide show
  1. package/INSTALL.en.md +58 -12
  2. package/INSTALL.md +62 -33
  3. package/README.md +181 -54
  4. package/README.zh-CN.md +158 -51
  5. package/assets/brand/managed-review-loop.png +0 -0
  6. package/assets/manifest.json +10 -5
  7. package/assets/scripts/superflow-coding-ready.mjs +135 -0
  8. package/assets/scripts/superflow-dependency-update-hook.sh +81 -8
  9. package/assets/scripts/superflow-document-audit.mjs +240 -0
  10. package/assets/scripts/superflow-environment-preflight.mjs +398 -0
  11. package/assets/scripts/superflow-hook-guard.sh +40 -1
  12. package/assets/scripts/superflow-managed-command-guard.py +309 -0
  13. package/assets/scripts/superflow-managed-executor-preflight.mjs +421 -0
  14. package/assets/scripts/superflow-managed-owner-verification.sh +117 -0
  15. package/assets/scripts/superflow-managed-work-check.mjs +287 -26
  16. package/assets/scripts/superflow-managed-work-guard.sh +6 -92
  17. package/assets/skills/superflow-clarify/SKILL.md +14 -0
  18. package/assets/skills/superflow-design/SKILL.md +38 -13
  19. package/assets/skills/superflow-docs/SKILL.md +93 -2
  20. package/assets/skills/superflow-pipeline/SKILL.md +167 -10
  21. package/assets/skills/superflow-pipeline/references/batch-prompt-template.md +17 -9
  22. package/assets/skills/superflow-pipeline/references/document-readiness.md +157 -0
  23. package/assets/skills/superflow-pipeline/references/document-templates.md +9 -5
  24. package/assets/skills/superflow-pipeline/references/feature-gated-workflow.md +14 -0
  25. package/assets/skills/superflow-pipeline/references/implementation-prompt-template.md +20 -11
  26. package/assets/skills/superflow-pipeline/references/managed-work.md +123 -15
  27. package/assets/skills/superflow-pipeline/references/orchestration.md +2 -2
  28. package/assets/skills/superflow-pipeline/references/p0-baseline-template.md +3 -2
  29. package/assets/skills/superflow-pipeline/references/quality-gate.md +7 -5
  30. package/assets/skills/superflow-pipeline/references/reviewer-checklist.md +7 -0
  31. package/assets/skills/superflow-pipeline/scripts/superflow-guard.sh +205 -9
  32. package/assets/skills/superflow-pipeline/scripts/superflow-handoff.sh +7 -4
  33. package/assets/skills/superflow-requirement-review/SKILL.md +178 -0
  34. package/assets/skills/superflow-requirement-review/agents/openai.yaml +4 -0
  35. package/assets/skills-en/superflow-clarify/SKILL.md +17 -0
  36. package/assets/skills-en/superflow-design/SKILL.md +31 -12
  37. package/assets/skills-en/superflow-docs/SKILL.md +99 -0
  38. package/assets/skills-en/superflow-pipeline/SKILL.md +163 -9
  39. package/assets/skills-en/superflow-pipeline/references/batch-prompt-template.md +4 -0
  40. package/assets/skills-en/superflow-pipeline/references/document-readiness.md +125 -0
  41. package/assets/skills-en/superflow-pipeline/references/document-templates.md +10 -0
  42. package/assets/skills-en/superflow-pipeline/references/feature-gated-workflow.md +7 -0
  43. package/assets/skills-en/superflow-pipeline/references/implementation-prompt-template.md +7 -0
  44. package/assets/skills-en/superflow-pipeline/references/managed-work.md +160 -10
  45. package/assets/skills-en/superflow-pipeline/references/quality-gate.md +12 -0
  46. package/assets/skills-en/superflow-pipeline/references/reviewer-checklist.md +7 -0
  47. package/assets/skills-en/superflow-pipeline/scripts/superflow-guard.sh +205 -9
  48. package/assets/skills-en/superflow-pipeline/scripts/superflow-handoff.sh +7 -4
  49. package/assets/skills-en/superflow-requirement-review/SKILL.md +99 -0
  50. package/assets/skills-en/superflow-requirement-review/agents/openai.yaml +4 -0
  51. package/dist/app/cli.js +64 -9
  52. package/dist/app/cli.js.map +1 -1
  53. package/dist/app/commands/change-guard.js +19 -2
  54. package/dist/app/commands/change-guard.js.map +1 -1
  55. package/dist/app/commands/check.js +107 -45
  56. package/dist/app/commands/check.js.map +1 -1
  57. package/dist/app/commands/docs.js +7 -3
  58. package/dist/app/commands/docs.js.map +1 -1
  59. package/dist/app/commands/doctor.js +174 -198
  60. package/dist/app/commands/doctor.js.map +1 -1
  61. package/dist/app/commands/eval.js +64 -0
  62. package/dist/app/commands/eval.js.map +1 -0
  63. package/dist/app/commands/implement.js +7 -3
  64. package/dist/app/commands/implement.js.map +1 -1
  65. package/dist/app/commands/init.js +12 -24
  66. package/dist/app/commands/init.js.map +1 -1
  67. package/dist/app/commands/mcp.js +167 -0
  68. package/dist/app/commands/mcp.js.map +1 -0
  69. package/dist/app/commands/pipeline.js +652 -18
  70. package/dist/app/commands/pipeline.js.map +1 -1
  71. package/dist/app/commands/requirement-review.js +6 -0
  72. package/dist/app/commands/requirement-review.js.map +1 -0
  73. package/dist/app/commands/status.js +66 -3
  74. package/dist/app/commands/status.js.map +1 -1
  75. package/dist/app/commands/uninstall.js +3 -3
  76. package/dist/app/commands/uninstall.js.map +1 -1
  77. package/dist/app/commands/update.js +83 -9
  78. package/dist/app/commands/update.js.map +1 -1
  79. package/dist/domains/agent.js +3 -11
  80. package/dist/domains/agent.js.map +1 -1
  81. package/dist/domains/config/cli-help.js +54 -12
  82. package/dist/domains/config/cli-help.js.map +1 -1
  83. package/dist/domains/config/i18n.js +6 -8
  84. package/dist/domains/config/i18n.js.map +1 -1
  85. package/dist/domains/config/manifest.js +0 -3
  86. package/dist/domains/config/manifest.js.map +1 -1
  87. package/dist/domains/deps.js +68 -7
  88. package/dist/domains/deps.js.map +1 -1
  89. package/dist/domains/managed-work/completion-policy.js +174 -0
  90. package/dist/domains/managed-work/completion-policy.js.map +1 -0
  91. package/dist/domains/managed-work/context-manifest.js +208 -0
  92. package/dist/domains/managed-work/context-manifest.js.map +1 -0
  93. package/dist/domains/managed-work/contract.js +135 -4
  94. package/dist/domains/managed-work/contract.js.map +1 -1
  95. package/dist/domains/managed-work/control-signals.js +34 -0
  96. package/dist/domains/managed-work/control-signals.js.map +1 -0
  97. package/dist/domains/managed-work/control.js +628 -0
  98. package/dist/domains/managed-work/control.js.map +1 -0
  99. package/dist/domains/managed-work/evaluation.js +497 -0
  100. package/dist/domains/managed-work/evaluation.js.map +1 -0
  101. package/dist/domains/managed-work/evidence-path.js +14 -0
  102. package/dist/domains/managed-work/evidence-path.js.map +1 -0
  103. package/dist/domains/managed-work/execution-contract.js +167 -0
  104. package/dist/domains/managed-work/execution-contract.js.map +1 -0
  105. package/dist/domains/managed-work/executor-policy.js +65 -0
  106. package/dist/domains/managed-work/executor-policy.js.map +1 -0
  107. package/dist/domains/managed-work/failure.js +65 -0
  108. package/dist/domains/managed-work/failure.js.map +1 -0
  109. package/dist/domains/managed-work/host-review.js +77 -0
  110. package/dist/domains/managed-work/host-review.js.map +1 -0
  111. package/dist/domains/managed-work/human-messages.js +31 -0
  112. package/dist/domains/managed-work/human-messages.js.map +1 -0
  113. package/dist/domains/managed-work/input.js +29 -3
  114. package/dist/domains/managed-work/input.js.map +1 -1
  115. package/dist/domains/managed-work/journal.js +77 -3
  116. package/dist/domains/managed-work/journal.js.map +1 -1
  117. package/dist/domains/managed-work/lock.js +67 -1
  118. package/dist/domains/managed-work/lock.js.map +1 -1
  119. package/dist/domains/managed-work/notifications.js +0 -15
  120. package/dist/domains/managed-work/notifications.js.map +1 -1
  121. package/dist/domains/managed-work/pair-admission.js +108 -0
  122. package/dist/domains/managed-work/pair-admission.js.map +1 -0
  123. package/dist/domains/managed-work/prompts.js +257 -22
  124. package/dist/domains/managed-work/prompts.js.map +1 -1
  125. package/dist/domains/managed-work/redaction.js +90 -0
  126. package/dist/domains/managed-work/redaction.js.map +1 -0
  127. package/dist/domains/managed-work/review-convergence.js +41 -0
  128. package/dist/domains/managed-work/review-convergence.js.map +1 -0
  129. package/dist/domains/managed-work/review-facts.js +181 -0
  130. package/dist/domains/managed-work/review-facts.js.map +1 -0
  131. package/dist/domains/managed-work/rule-selection.js +84 -0
  132. package/dist/domains/managed-work/rule-selection.js.map +1 -0
  133. package/dist/domains/managed-work/runner.js +1967 -175
  134. package/dist/domains/managed-work/runner.js.map +1 -1
  135. package/dist/domains/managed-work/schemas.js +72 -2
  136. package/dist/domains/managed-work/schemas.js.map +1 -1
  137. package/dist/domains/managed-work/service.js +82 -13
  138. package/dist/domains/managed-work/service.js.map +1 -1
  139. package/dist/domains/managed-work/state.js +195 -5
  140. package/dist/domains/managed-work/state.js.map +1 -1
  141. package/dist/domains/managed-work/storage.js +66 -24
  142. package/dist/domains/managed-work/storage.js.map +1 -1
  143. package/dist/domains/managed-work/types.js +12 -9
  144. package/dist/domains/managed-work/types.js.map +1 -1
  145. package/dist/domains/managed-work/verification-categories.js +39 -0
  146. package/dist/domains/managed-work/verification-categories.js.map +1 -0
  147. package/dist/domains/managed-work/verification-policy.js +116 -0
  148. package/dist/domains/managed-work/verification-policy.js.map +1 -0
  149. package/dist/domains/managed-work/wait.js +21 -3
  150. package/dist/domains/managed-work/wait.js.map +1 -1
  151. package/dist/domains/managed-work/workspace-binding.js +133 -0
  152. package/dist/domains/managed-work/workspace-binding.js.map +1 -0
  153. package/dist/domains/sdd-readiness.js +44 -0
  154. package/dist/domains/sdd-readiness.js.map +1 -0
  155. package/dist/domains/skill/deploy.js +0 -6
  156. package/dist/domains/skill/deploy.js.map +1 -1
  157. package/dist/domains/skill/scripts.js +0 -8
  158. package/dist/domains/skill/scripts.js.map +1 -1
  159. package/dist/domains/state.js +1 -2
  160. package/dist/domains/state.js.map +1 -1
  161. package/dist/mcp/runtime-identity.js +21 -0
  162. package/dist/mcp/runtime-identity.js.map +1 -0
  163. package/dist/mcp/server.js +369 -0
  164. package/dist/mcp/server.js.map +1 -0
  165. package/dist/platform/agent-process.js +499 -38
  166. package/dist/platform/agent-process.js.map +1 -1
  167. package/dist/platform/executable.js +28 -0
  168. package/dist/platform/executable.js.map +1 -0
  169. package/dist/platform/paths.js +1 -17
  170. package/dist/platform/paths.js.map +1 -1
  171. package/dist/platform/process-tree.js +44 -0
  172. package/dist/platform/process-tree.js.map +1 -0
  173. package/dist/platform/process.js +1 -1
  174. package/dist/platform/process.js.map +1 -1
  175. package/package.json +17 -7
  176. package/scripts/check-design-principles.mjs +107 -0
  177. package/scripts/check-managed-work-design.mjs +507 -0
  178. package/scripts/clean-dist.js +9 -0
  179. package/scripts/ensure-bin-modes.js +11 -0
  180. package/scripts/preinstall.js +57 -0
  181. package/dist/cli/index.js +0 -193
  182. package/dist/cli/index.js.map +0 -1
  183. package/dist/commands/archive.js +0 -6
  184. package/dist/commands/archive.js.map +0 -1
  185. package/dist/commands/clarify.js +0 -6
  186. package/dist/commands/clarify.js.map +0 -1
  187. package/dist/commands/design.js +0 -28
  188. package/dist/commands/design.js.map +0 -1
  189. package/dist/commands/docs.js +0 -6
  190. package/dist/commands/docs.js.map +0 -1
  191. package/dist/commands/doctor.js +0 -494
  192. package/dist/commands/doctor.js.map +0 -1
  193. package/dist/commands/implement.js +0 -6
  194. package/dist/commands/implement.js.map +0 -1
  195. package/dist/commands/init.js +0 -520
  196. package/dist/commands/init.js.map +0 -1
  197. package/dist/commands/pipeline.js +0 -6
  198. package/dist/commands/pipeline.js.map +0 -1
  199. package/dist/commands/scan.js +0 -63
  200. package/dist/commands/scan.js.map +0 -1
  201. package/dist/commands/status.js +0 -173
  202. package/dist/commands/status.js.map +0 -1
  203. package/dist/commands/uninstall.js +0 -214
  204. package/dist/commands/uninstall.js.map +0 -1
  205. package/dist/commands/update.js +0 -193
  206. package/dist/commands/update.js.map +0 -1
  207. package/dist/commands/verify.js +0 -6
  208. package/dist/commands/verify.js.map +0 -1
  209. package/dist/core/assets.js +0 -27
  210. package/dist/core/assets.js.map +0 -1
  211. package/dist/core/cli-help.js +0 -98
  212. package/dist/core/cli-help.js.map +0 -1
  213. package/dist/core/context.js +0 -123
  214. package/dist/core/context.js.map +0 -1
  215. package/dist/core/dependencies.js +0 -146
  216. package/dist/core/dependencies.js.map +0 -1
  217. package/dist/core/detect.js +0 -64
  218. package/dist/core/detect.js.map +0 -1
  219. package/dist/core/i18n.js +0 -105
  220. package/dist/core/i18n.js.map +0 -1
  221. package/dist/core/integrity.js +0 -46
  222. package/dist/core/integrity.js.map +0 -1
  223. package/dist/core/manifest.js +0 -21
  224. package/dist/core/manifest.js.map +0 -1
  225. package/dist/core/prompts.js +0 -20
  226. package/dist/core/prompts.js.map +0 -1
  227. package/dist/core/registry.js +0 -134
  228. package/dist/core/registry.js.map +0 -1
  229. package/dist/core/rules.js +0 -17
  230. package/dist/core/rules.js.map +0 -1
  231. package/dist/core/scripts.js +0 -48
  232. package/dist/core/scripts.js.map +0 -1
  233. package/dist/core/skill-check.js +0 -32
  234. package/dist/core/skill-check.js.map +0 -1
  235. package/dist/core/skills.js +0 -62
  236. package/dist/core/skills.js.map +0 -1
  237. package/dist/core/state.js +0 -54
  238. package/dist/core/state.js.map +0 -1
  239. package/dist/utils/path.js +0 -11
  240. package/dist/utils/path.js.map +0 -1
  241. package/dist/utils/shell.js +0 -29
  242. package/dist/utils/shell.js.map +0 -1
@@ -1,34 +1,184 @@
1
1
  # Managed Work Rules
2
2
 
3
+ ## Design-constitution gate
4
+
5
+ Before changing Superflow managed work itself, read
6
+ `docs/managed-work-design-principles.en.md` and
7
+ `docs/managed-agent-protocol.en.md` completely. Before delivery, walk through
8
+ the constitution's mandatory change-review checklist and state whether the
9
+ change alters any principle.
10
+
11
+ Runner and scripts decide deterministic facts. Agents decide correctness,
12
+ reasonableness, risk, and evidence sufficiency. Scripts must not replace
13
+ semantic review with regexes, and Agents must not take ownership of hashes,
14
+ schemas, counters, or state transitions. A new long-term rule first updates the
15
+ Chinese and English constitutions, protocol, and tests.
16
+
17
+ Managed orchestration owns only dual-Agent dispatch, frozen context, state,
18
+ waiting, evidence, and review loops. API, database, concurrency, transaction,
19
+ and test design belongs to `api.md`, `design.md`, `tests.md`, and source-level
20
+ technical design. Executor prompts inherit rather than redesign. Audit every
21
+ managed-prompt change against this boundary.
22
+
3
23
  Managed work is built into `superflow-pipeline`. The user only says to use
4
24
  Superflow and provides an implementation prompt, change directory, or direct
5
25
  task. Direct tasks receive a minimal contract. SDD work freezes the generated
6
26
  implementation prompt and never substitutes `tasks.md` for the execution prompt.
7
27
 
8
- Always dispatch through:
28
+ Before start, the Host routes by input maturity: docs-only work stops at Coding
29
+ Ready without a managed Task; a user-approved change/prompt is frozen directly;
30
+ a bounded verbal task uses minimal or standard. If a verbal request has a
31
+ direction-changing API, data, concurrency, cross-repository, or owner choice,
32
+ return to clarification/documents instead of letting Runner regexes or Executor
33
+ improvisation replace Host judgment.
34
+
35
+ When MCP is installed, the current host must prefer the `superflow_managed_*`
36
+ tools for submission, waiting, user guidance, and review submission. MCP is a
37
+ channel to the local state machine rather than a third model. Direct host review
38
+ is the only supported mode, preventing a nested supervisor CLI from duplicating
39
+ context, tokens, and review time.
40
+
41
+ When MCP is unavailable, dispatch through:
9
42
 
10
43
  ```bash
11
44
  superflow pipeline "<implementation-prompt|change-dir|task>" --managed --project "<root>" \
12
- --supervisor <codex|claude> --executor <claude|codex> --language <en|zh>
45
+ --supervisor current --executor peer --language <en|zh>
13
46
  ```
14
47
 
15
- The command always starts the independent background service and follows the
16
- local event journal to a terminal state. Losing the follower does not stop the
17
- task. After return, the current agent reads the report and summarizes it in the
18
- original conversation.
48
+ `current/peer` resolves the host and its counterpart automatically. If host
49
+ detection is ambiguous, pass explicit `codex/claude` roles instead of guessing.
50
+ Legacy contracts with missing or retired supervision settings are migrated to
51
+ direct host review on resume. No entry point may spawn a background supervisor
52
+ CLI.
53
+ Keep a single foreground `pipeline`/`resume` waiter so the CLI reads local state;
54
+ never spend host model turns periodically invoking `superflow status`.
55
+ In MCP mode,
56
+ `superflow_managed_wait(taskId, afterSequence, timeoutSeconds=240)` defaults to
57
+ a Host-compatible transport window below common 300-second tool limits. Hosts
58
+ that support longer calls may explicitly request up to 43200 seconds. An active
59
+ request exposes stages and healthy checkpoints through standard MCP progress
60
+ notifications without waking the Host model. One healthy or idle checkpoint does
61
+ not complete wait; two consecutive checkpoints without an effective milestone
62
+ return attention. Ordinary window expiry immediately continues wait from the
63
+ compact snapshot's `latestSequence`, without status or Executor restart. Call
64
+ `superflow_managed_status` for full evidence only when the state requires Host
65
+ attention.
66
+
67
+ After executor delivery, the task enters `external_supervisor_review_required`.
68
+ The current host reads `host-review-N.md`, writes the review JSON, and resumes:
69
+
70
+ ```bash
71
+ superflow pipeline --resume-task <task-id> --submit-host-review <review.json>
72
+ ```
19
73
 
20
74
  Hard gates:
21
75
 
22
- - Claim the 5/7/12 budgets before an Agent call.
76
+ - Claim the 5/7/12 budgets before an Agent call. The default Executor circuit
77
+ also stops at two million cumulative token units. Provider-dollar accounting
78
+ is not comparable, so the default has no USD circuit and Claude receives no
79
+ `--max-budget-usd`.
23
80
  - Freeze the selected language into the contract; prompts, journals, reports, notifications, errors, and resumed rounds must use that same language.
24
81
  - Revalidate the frozen contract hash, non-overridable permissions, and 5/7/12 hard limits on every start and resume. Fail closed if persisted contract data changed.
82
+ - Runner uses filesystem snapshots for non-Git workspace changes. Executors must
83
+ never run `git init` for diff, preflight, or delivery, and must not create or
84
+ replace `.git`; repository-identity changes during a task still fail closed.
85
+ - The context manifest marks frozen requirements, designs, prompts, handoffs,
86
+ rules, and task facts as `immutable`, and task/test-report progress evidence
87
+ as `retain`. Immutable entries are read-only; retained entries may be updated
88
+ but never deleted. Native hooks block before mutation and every Host is still
89
+ verified by preflight/final gates.
90
+ - Cleanup separates runtime, workspace-temporary, delivery-artifacts, and
91
+ protected-contracts. Executor cleans only the first two and retains source,
92
+ SQL, tests, reports, and frozen contracts for Host review. Never use pkill,
93
+ killall, a bare kill, port/name-only cleanup, or rm -rf without owner-helper verification.
25
94
  - Resolve change directories through `.sdd/state.yaml` `implementation_prompt`; treat `tasks.md` as a checklist only. Copy the prompt into a managed snapshot and freeze its SHA-256 for both agents.
26
- - Persist and resume exact supervisor and executor session IDs.
95
+ - The first executor invocation automatically uses the frozen prompt as its task entry.
96
+ - For real-runtime work, the first prompt requires a repository-owned,
97
+ one-command, repeatable, failure-safe, portable acceptance entry covering
98
+ preflight, setup, build, startup, real calls, assertions, and cleanup,
99
+ including the success path and one representative setup/verification failure
100
+ cleanup with final zero residue. The Host reviews all properties together.
101
+ - Call the MCP runtime handshake before start. An installed-runtime change makes
102
+ the stale MCP fail closed before persistence and requires a Host restart.
103
+ Persist verbose logs and print bounded summaries and failure tails only.
104
+ - Verification has three levels: repairs use change-scoped checks; engineering/SDD
105
+ defaults to task-level real acceptance; only an explicit frozen prompt, an owner
106
+ helper/managed-orchestration change, or a new custom cleanup primitive uses
107
+ framework certification. The frozen contract may raise but never silently lower
108
+ the level, and historical evidence reruns only when the diff/finding invalidates it.
109
+ - A normal real-runtime Host review checks task PID/start-fingerprint binding,
110
+ deletion gates, one representative setup/assertion failure cleanup, and final
111
+ zero residue. Distinct business deletion paths and affected/cross-service
112
+ repositories still receive their own proof. It must not rerun shared-helper PID-reuse, non-owner, forged-state,
113
+ and every-signal disaster suites for each business task. Reuse the helper directly
114
+ through a configurable path instead of copying a cleanup framework. Record Host
115
+ usage or an explicit unavailable reason.
116
+ - Pass neither `--max-turns` nor `--max-budget-usd` to a Claude Executor. Do not
117
+ split normal work by a fixed tool-step count or an inaccurate provider-dollar
118
+ estimate. The defaults stop after 60 minutes with no output or a two-hour
119
+ single-invocation deadline; repeated provider failures, token/invocation
120
+ budgets, safety boundaries, and user pause still stop execution.
121
+ - Claude Executor defaults to the official
122
+ `CLAUDE_CODE_AUTO_COMPACT_WINDOW=200000` and
123
+ `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=70` settings for earlier long-session
124
+ compaction; explicit user values win. It reloads the frozen prompt and handoff
125
+ after compaction, and final `result.usage` is authoritative for the invocation.
126
+ - Network errors, closed connections, timeouts, and provider overloads share one
127
+ consecutive-failure counter and must open the circuit on the third failure;
128
+ only a complete Agent response resets it. Transient 429/529/overloaded calls
129
+ and connection refused/reset/close or socket failures confirmed before an Agent
130
+ response may be credited; permission, token-plan, quota, and billing failures
131
+ are not, and none may bypass the three-failure circuit.
132
+ - Keep the first invocation in one continuous session. Create a new session for
133
+ review repair or abnormal recovery and retain old IDs for audit; never guess
134
+ with `--last` or `--continue`. Generate `executor-handoff-N.md` for later
135
+ invocations with the prompt hash, task progress, local pending work, external
136
+ prerequisites, all findings, diff stat, and recent report. A new session must
137
+ read it and verify against the current workspace.
138
+ - Write safely discovered Java, Maven, Node, and npm executable paths into the
139
+ first executor policy so the Agent does not waste tool calls rediscovering the
140
+ basic toolchain.
141
+ - Handoff includes exact applicable rule files and a deterministic delivery
142
+ preflight. Executor runs it before returning and fixes line width, whitespace,
143
+ task checkboxes, and missing reports in the same session.
144
+ - The current host performs review in `external_host` mode; the background
145
+ service must not spawn a nested supervisor CLI.
27
146
  - Treat `progress.jsonl`, the task contract, review results, and evidence as truth.
28
147
  - Executor cannot edit managed state or commit, push, publish, deploy, or bypass sandbox.
29
148
  - Supervisor cannot modify target files.
30
- - Non-zero exits, invalid JSON, missing session IDs, and review-time workspace drift block pass.
149
+ - Invalid JSON, missing session IDs, and review-time workspace drift block pass. Absence checks use `assertion: negative` to express an expected exit 1/2 without guessing from command names or prose.
150
+ - Expected-failure and fault-injection checks must use a parent command that
151
+ asserts the child's non-zero outcome and itself exits 0. Raw non-zero outcomes
152
+ stay in logs. Invalid negative evidence goes directly to Host review and never
153
+ triggers a full Executor invocation merely to rewrite JSON.
31
154
  - Engineering and SDD tasks need successful command evidence from at least two categories among build, test, and runtime/real invocation. Compile-only or unit-test-only delivery cannot enter formal review.
32
155
  - Run `superflow-managed-work-check.mjs <root> <task-id>` before delivery-ready.
156
+ - `tasks.md` recognizes only local_required, environment_required, and release_required; untagged work is local. The Runner derives baseline evidence from the checklist, real workspace changes, test report, and successful commands. Executors add taskEvidence only for tasks that need distinct evidence.
157
+ - The Runner merges the complete changedFiles set and stores structured command categories. The same mechanical rejection gets one automatic repair, with at most two automatic repairs overall, then the current host reviews it. Three or more permission denials in one invocation suppress another executor retry.
158
+ - The Runner inherits valid startup, HTTP, test, and build commands across executor results. When the Host confirms complete historical evidence and only current structured metadata is invalid, it passes and promotes the artifact with an audit event instead of asking the Executor to rerun the environment or rewrite JSON.
159
+ - When successful Spring Boot evidence already covers startup, real HTTP/runtime,
160
+ and evidence paths, and only the `invocation` category is missing, this is
161
+ verification-category ambiguity. Runner escalates directly to Host; after a
162
+ pass it promotes with an audit event instead of launching a full Executor for
163
+ metadata repair.
164
+ - The Runner deterministically removes blank structured-array entries. A read-only
165
+ inspection with exit 1/2 that explicitly reports no process, listener,
166
+ container, or residue is a successful empty result; neither case launches the
167
+ Executor for metadata repair.
168
+ - Status separates physical calls, infrastructure credits, and effective
169
+ development calls. Provider switches resume through
170
+ `--provider-switched <reason>`, and stage changes notify the Host conversation
171
+ without waking it for ordinary heartbeat.
172
+ - Page/permission changes require frontend startup and Playwright/Cypress real-browser E2E. Cross-stack API changes require backend Controller and frontend request contracts plus an API-export snapshot.
33
173
  - Append the single `run.delivery_ready` event only after the integrity script passes. On failure, require human attention without leaving false delivery-ready evidence.
34
- - A passing run waits for explicit Git approval.
174
+ - A passing run enters a three-stage source/environment/release state and still requires explicit Git approval.
175
+
176
+ ## Recovery
177
+
178
+ After a background failure, recover from the task contract, event journal, run
179
+ state, and latest checks. Old session IDs are audit records, not recovery
180
+ dependencies. Plain `--resume-task` for a healthy `running` task is safe attach
181
+ and continued wait only: it cannot reset state or budgets or launch another
182
+ Executor. Only a recorded PID proven dead enters stale recovery; a missing PID
183
+ fails closed into attach-and-wait. An active MCP wait's progress notifications
184
+ are request-scoped, not autonomous callbacks after the Host turn ends.
@@ -13,6 +13,16 @@
13
13
  evidence, necessity, simplest implementation, removed/rejected complexity,
14
14
  counts of new tables/fields/APIs/services/caches/async flows/jobs/compatibility
15
15
  layers, and a PASS/BLOCKED verdict. Only PASS may leave docs/design.
16
+ - Full existing-system, DB/table, cross-repository, or real-entry changes have
17
+ `source-code-audit.md` with a Source Fact Freeze Card, all writers and real
18
+ callers, current/legacy/unmounted/data-model-only/owner-confirmed/blocked
19
+ classifications, DB check or skip reason, conflict audit, and owner boundary.
20
+ - Database changes have `release-sql.md` with `database_change: true`, an exact
21
+ placeholder-free `target_sql_path`, `copy_policy: verbatim`, a valid
22
+ `sql_sha256`, and exactly one complete executable SQL block with required
23
+ prechecks, DDL/DML, migration, and post-verification. Design, tasks, and the
24
+ quality gate state that implementation agents may only copy it verbatim;
25
+ omissions return to docs.
16
26
 
17
27
  ## Design Gate
18
28
 
@@ -51,6 +61,8 @@
51
61
  sum(other components)` instead of calculating and rounding every component
52
62
  independently.
53
63
  - SQL risk review exists for DB changes.
64
+ - Source-level design does not author or defer release SQL; it consumes the
65
+ already frozen `release-sql.md` contract.
54
66
  - No fallback or guesswork is allowed without explicit owner approval.
55
67
 
56
68
  ## Implementation Gate
@@ -22,6 +22,13 @@
22
22
  rounding explicit, without early rate rounding or synthesized inverses?
23
23
  - Are SQL changes reviewed and tied to total version SQL when needed?
24
24
  - Are RED/GREEN evidence and real-entry evidence present?
25
+ - For L3/L4 negative controls, does the raw malformed or forbidden payload reach
26
+ the intended parser/validation branch, rather than merely returning the same
27
+ status code?
28
+ - For task-owned resource cleanup, are every frozen identity field (nonce, PID,
29
+ port, signature, etc.) compared and mismatch refusal proven? An unchanged
30
+ certified helper needs integrity, task parameters, one failure cleanup, and
31
+ final zero residue only.
25
32
  - Are mock-only results clearly labeled?
26
33
  - Did workers stay inside allowed file boundaries?
27
34
  - Did hooks and guard scripts pass?
@@ -322,6 +322,103 @@ change_has_field_status_risk() {
322
322
  "$CHANGE_DIR"/*.md "$CHANGE_DIR"/**/*.md 2>/dev/null
323
323
  }
324
324
 
325
+ change_has_database_change() {
326
+ if grep -Eiq '^[[:space:]]*database:[[:space:]]*false([[:space:]]*#.*)?$' "$CHANGE_DIR/.openspec.yaml" 2>/dev/null; then
327
+ return 1
328
+ fi
329
+ if grep -Eiq '^[[:space:]]*database:[[:space:]]*true([[:space:]]*#.*)?$' "$CHANGE_DIR/.openspec.yaml" 2>/dev/null; then
330
+ return 0
331
+ fi
332
+ grep -RIEiq \
333
+ 'database_change[[:space:]]*:[[:space:]]*true|database[ -]change.{0,12}(required|true|yes)|ALTER[[:space:]]+TABLE|CREATE[[:space:]]+TABLE|ADD[[:space:]]+(COLUMN|INDEX|KEY|CONSTRAINT)|schema[ -]migration|database[ -]migration|historical data.{0,12}(migration|backfill)|seed data.{0,12}(migration|backfill)|add.{0,12}(table|column|index|constraint)' \
334
+ "$CHANGE_DIR/proposal.md" \
335
+ "$CHANGE_DIR/api.md" \
336
+ "$CHANGE_DIR/design.md" \
337
+ "$CHANGE_DIR/tasks.md" \
338
+ "$CHANGE_DIR/database-contract.md" \
339
+ "$CHANGE_DIR/spec.md" \
340
+ "$CHANGE_DIR"/specs/*/spec.md 2>/dev/null
341
+ }
342
+
343
+ require_frozen_release_sql() {
344
+ local release_sql="$CHANGE_DIR/release-sql.md"
345
+ local output
346
+
347
+ require_file release-sql.md
348
+ [[ -f "$release_sql" ]] || return 0
349
+
350
+ output="$(mktemp)"
351
+ if ! python3 - "$release_sql" >"$output" 2>&1 <<'PY'
352
+ import hashlib
353
+ import re
354
+ import sys
355
+ from pathlib import Path
356
+
357
+ path = Path(sys.argv[1])
358
+ text = path.read_text(encoding="utf-8")
359
+ errors = []
360
+
361
+ front_match = re.match(r"\A---\n(.*?)\n---(?:\n|\Z)", text, re.S)
362
+ front = front_match.group(1) if front_match else ""
363
+ if not front_match:
364
+ errors.append("front matter is missing")
365
+
366
+ def field(name):
367
+ match = re.search(rf"(?m)^{re.escape(name)}:\s*(.*?)\s*$", front)
368
+ return match.group(1).strip().strip('"\'') if match else ""
369
+
370
+ if field("database_change").lower() != "true":
371
+ errors.append("database_change must be true")
372
+
373
+ target = field("target_sql_path")
374
+ if not target or not target.lower().endswith(".sql"):
375
+ errors.append("target_sql_path must be an exact .sql path")
376
+ if re.search(r"[<>{}]|testN|version|pending|TBD", target, re.I):
377
+ errors.append("target_sql_path contains a placeholder")
378
+
379
+ if field("copy_policy").lower() != "verbatim":
380
+ errors.append("copy_policy must be verbatim")
381
+
382
+ declared_hash = field("sql_sha256").lower()
383
+ if not re.fullmatch(r"[0-9a-f]{64}", declared_hash):
384
+ errors.append("sql_sha256 must be a 64-character lowercase SHA-256")
385
+
386
+ blocks = re.findall(r"```sql[^\n]*\n(.*?)\n```", text, re.S | re.I)
387
+ if len(blocks) != 1:
388
+ errors.append("release-sql.md must contain exactly one sql code block")
389
+ else:
390
+ payload = blocks[0].replace("\r\n", "\n").replace("\r", "\n").rstrip("\n") + "\n"
391
+ actual_hash = hashlib.sha256(payload.encode("utf-8")).hexdigest()
392
+ if declared_hash and actual_hash != declared_hash:
393
+ errors.append(
394
+ f"sql_sha256 mismatch: declared={declared_hash} actual={actual_hash}"
395
+ )
396
+ executable = re.sub(r"/\*.*?\*/|--[^\n]*", "", payload, flags=re.S)
397
+ if not re.search(
398
+ r"\b(CREATE|ALTER|DROP|INSERT|UPDATE|DELETE|MERGE|TRUNCATE|CALL)\b",
399
+ executable,
400
+ re.I,
401
+ ):
402
+ errors.append("sql block has no executable schema/data change statement")
403
+ if not re.search(r"\b(SELECT|SHOW|CALL)\b", executable, re.I):
404
+ errors.append("sql block has no executable verification statement")
405
+
406
+ if errors:
407
+ print("; ".join(errors))
408
+ sys.exit(1)
409
+ PY
410
+ then
411
+ issues+=("frozen release SQL invalid: $(tr '\n' ' ' < "$output" | sed -E 's/[[:space:]]+/ /g')")
412
+ fi
413
+ rm -f "$output"
414
+
415
+ require_grep 'release-sql\.md' design.md "frozen release SQL design reference"
416
+ require_grep 'release-sql\.md' tasks.md "frozen release SQL task reference"
417
+ require_grep 'release-sql\.md' sdd-quality-gate.md "frozen release SQL quality-gate reference"
418
+ require_grep 'verbatim' tasks.md "verbatim SQL copy task"
419
+ require_grep 'verbatim' sdd-quality-gate.md "verbatim SQL copy quality gate"
420
+ }
421
+
325
422
  change_contract_docs_without_complexity_budget() {
326
423
  local path
327
424
  for path in proposal.md api.md design.md tests.md spec.md; do
@@ -340,6 +437,12 @@ change_all_docs_without_complexity_budget() {
340
437
  }
341
438
 
342
439
  change_has_external_config_risk() {
440
+ if grep -Eiq '^[[:space:]]*external_config:[[:space:]]*false([[:space:]]*#.*)?$' "$CHANGE_DIR/.openspec.yaml" 2>/dev/null; then
441
+ return 1
442
+ fi
443
+ if grep -Eiq '^[[:space:]]*external_config:[[:space:]]*true([[:space:]]*#.*)?$' "$CHANGE_DIR/.openspec.yaml" 2>/dev/null; then
444
+ return 0
445
+ fi
343
446
  local content
344
447
  content="$(change_contract_docs_without_complexity_budget)"
345
448
  grep -Eiq \
@@ -348,6 +451,12 @@ change_has_external_config_risk() {
348
451
  }
349
452
 
350
453
  change_has_concurrency_idempotency_risk() {
454
+ if grep -Eiq '^[[:space:]]*concurrency:[[:space:]]*false([[:space:]]*#.*)?$' "$CHANGE_DIR/.openspec.yaml" 2>/dev/null; then
455
+ return 1
456
+ fi
457
+ if grep -Eiq '^[[:space:]]*concurrency:[[:space:]]*true([[:space:]]*#.*)?$' "$CHANGE_DIR/.openspec.yaml" 2>/dev/null; then
458
+ return 0
459
+ fi
351
460
  grep -RIEiq \
352
461
  'concurren|idempoten|race condition|duplicate (request|callback|consumption|delivery)|atomic claim|batch (issue|activate|renew)' \
353
462
  "$CHANGE_DIR/proposal.md" \
@@ -359,6 +468,12 @@ change_has_concurrency_idempotency_risk() {
359
468
  }
360
469
 
361
470
  change_has_money_precision_risk() {
471
+ if grep -Eiq '^[[:space:]]*money:[[:space:]]*false([[:space:]]*#.*)?$' "$CHANGE_DIR/.openspec.yaml" 2>/dev/null; then
472
+ return 1
473
+ fi
474
+ if grep -Eiq '^[[:space:]]*money:[[:space:]]*true([[:space:]]*#.*)?$' "$CHANGE_DIR/.openspec.yaml" 2>/dev/null; then
475
+ return 0
476
+ fi
362
477
  grep -RIEiq \
363
478
  '(^|[^[:alnum:]_])(amount|fee|fees|price|discount|deduction|refund|payment|invoice|balance|proration|allocation|reconciliation|residual|precision|rounding)([^[:alnum:]_]|$)|revenue sharing|profit sharing|split payment|electricity fee|service fee|package settlement|serviceFee|chargeFee|totalAmount|actualAmount|payAmount|refundAmount|discountAmount|invoiceAmount|balanceAmount' \
364
479
  "$CHANGE_DIR/proposal.md" \
@@ -369,6 +484,53 @@ change_has_money_precision_risk() {
369
484
  "$CHANGE_DIR"/specs/*/spec.md 2>/dev/null
370
485
  }
371
486
 
487
+ change_has_source_fact_risk() {
488
+ grep -RIEiq \
489
+ 'existing|current behavior|legacy|database|table relationship|Mapper|XML|cross[- ](repo|service)|crosses services|real entry|mini[- ]program|H5' \
490
+ "$CHANGE_DIR/proposal.md" \
491
+ "$CHANGE_DIR/api.md" \
492
+ "$CHANGE_DIR/design.md" \
493
+ "$CHANGE_DIR/tests.md" \
494
+ "$CHANGE_DIR/spec.md" \
495
+ "$CHANGE_DIR"/specs/*/spec.md 2>/dev/null
496
+ }
497
+
498
+ change_has_cardinality_conflict_signal() {
499
+ grep -RIEiq \
500
+ 'List[<(]|orderIds|batchInsert|one[- ]to[- ]many|relation table' \
501
+ "$CHANGE_DIR"/*.md "$CHANGE_DIR"/**/*.md 2>/dev/null
502
+ }
503
+
504
+ require_source_fact_audit() {
505
+ require_file source-code-audit.md
506
+ require_grep 'Source Fact Freeze Card' source-code-audit.md "source fact freeze card"
507
+ require_grep 'Business conclusion' source-code-audit.md "source fact business conclusion"
508
+ require_grep 'understand.*locator' source-code-audit.md "understand-anything locator evidence"
509
+ require_grep 'Data model' source-code-audit.md "source fact data model"
510
+ require_grep 'All writers' source-code-audit.md "all writers inventory"
511
+ require_grep 'Real user entr' source-code-audit.md "real user entry"
512
+ require_grep 'Current callers' source-code-audit.md "current callers"
513
+ require_grep 'Legacy conflict' source-code-audit.md "legacy conflict"
514
+ require_grep 'DB (check|required|skip|reason)' source-code-audit.md "DB check or skip reason"
515
+ require_grep 'Conclusion level' source-code-audit.md "conclusion level"
516
+ require_grep 'owner.*decision' source-code-audit.md "owner decision boundary"
517
+ require_grep 'current' source-code-audit.md "current evidence classification"
518
+ require_grep 'legacy' source-code-audit.md "legacy evidence classification"
519
+ require_grep 'unmounted' source-code-audit.md "unmounted evidence classification"
520
+ require_grep 'data-model-only' source-code-audit.md "data-model-only evidence classification"
521
+ require_grep 'owner-confirmed' source-code-audit.md "owner-confirmed evidence classification"
522
+ require_grep 'blocked' source-code-audit.md "blocked evidence classification"
523
+ require_grep 'Evidence classifications.*current.*legacy.*unmounted.*data-model-only.*owner-confirmed.*blocked' source-code-audit.md "complete evidence classification set"
524
+ require_grep 'Question Eligibility Gate' source-code-audit.md "question eligibility gate"
525
+ require_grep 'Source search' source-code-audit.md "source search evidence"
526
+ require_grep 'Mapper.*SQL|SQL.*Mapper' source-code-audit.md "Mapper and SQL search evidence"
527
+ require_grep 'Frontend.*mini[- ]program.*H5' source-code-audit.md "frontend mini-program H5 caller search"
528
+ require_grep 'sibling.*repo' source-code-audit.md "sibling repository search"
529
+ if change_has_cardinality_conflict_signal; then
530
+ require_grep 'Conflict Audit' source-code-audit.md "cardinality conflict audit"
531
+ fi
532
+ }
533
+
372
534
  change_has_fx_precision_risk() {
373
535
  grep -RIEiq \
374
536
  '(^|[^[:alnum:]_])(exchange rate|fx rate|currency conversion|cross.currency|base currency|quote currency)([^[:alnum:]_]|$)' \
@@ -388,8 +550,10 @@ change_has_architecture_boundary_risk() {
388
550
  <<< "$content"
389
551
  }
390
552
 
391
- first_prompt_rel() {
392
- find "$CHANGE_DIR" -path '*/prompt/*.md' -type f | head -n 1 | sed "s#^$CHANGE_DIR/##"
553
+ prompt_rels() {
554
+ find "$CHANGE_DIR" -path '*/prompt/*.md' -type f -print \
555
+ | LC_ALL=C sort \
556
+ | sed "s#^$CHANGE_DIR/##"
393
557
  }
394
558
 
395
559
  require_any_prompt() {
@@ -399,7 +563,7 @@ require_any_prompt() {
399
563
  }
400
564
 
401
565
  require_prompt_set() {
402
- local task_count prompt_count non_index_prompt_count
566
+ local task_count prompt_count non_index_prompt_count prompt_rel document
403
567
  require_file prompt/implementation.md
404
568
  task_count="$(grep -E '^[[:space:]]*-[[:space:]]+\[[ xX]\]' "$CHANGE_DIR/tasks.md" 2>/dev/null | wc -l | tr -d ' ')"
405
569
  prompt_count="$(find "$CHANGE_DIR/prompt" -maxdepth 1 -type f -name '*.md' 2>/dev/null | wc -l | tr -d ' ')"
@@ -410,9 +574,15 @@ require_prompt_set() {
410
574
  if [[ "$prompt_count" -eq 0 ]]; then
411
575
  issues+=("missing prompt/*.md files")
412
576
  fi
413
- if [[ -f "$CHANGE_DIR/tasks.md" ]] && ! grep -Riq 'prompt/.*\.md' "$CHANGE_DIR/tasks.md" "$CHANGE_DIR/traceability-matrix.md" "$CHANGE_DIR/sdd-quality-gate.md" "$CHANGE_DIR/test-report.md" 2>/dev/null; then
414
- issues+=("prompt files are not cross-linked from tasks/traceability/quality gate/test-report")
415
- fi
577
+ for document in tasks.md traceability-matrix.md sdd-quality-gate.md test-report.md; do
578
+ [[ -f "$CHANGE_DIR/$document" ]] || continue
579
+ while IFS= read -r prompt_rel; do
580
+ if ! grep -Fq "]($prompt_rel)" "$CHANGE_DIR/$document" \
581
+ && ! grep -Fq "](./$prompt_rel)" "$CHANGE_DIR/$document"; then
582
+ issues+=("$document does not link $prompt_rel")
583
+ fi
584
+ done < <(prompt_rels)
585
+ done
416
586
  }
417
587
 
418
588
  require_money_precision_contract() {
@@ -548,11 +718,27 @@ case "$PHASE" in
548
718
  require_grep 'RED|red-green|GREEN' tests.md "RED/GREEN test contract"
549
719
  require_grep 'curl|Postman|Newman|pytest|RestAssured|automation command' tests.md "interface automation command"
550
720
  require_grep 'handoff_hash|sdd-context|context package|anti-drift' sdd-quality-gate.md "handoff/context-drift gate"
721
+ if change_has_database_change; then
722
+ require_frozen_release_sql
723
+ fi
551
724
  workflow="$(state_get workflow)"
552
725
  if [[ "$workflow" == "full" ]]; then
726
+ require_file requirement-review.md
727
+ require_grep '^review_verdict:[[:space:]]*PASS[[:space:]]*$' requirement-review.md "requirement reverse review PASS verdict"
728
+ require_grep '^implementation_readiness:[[:space:]]*READY[[:space:]]*$' requirement-review.md "requirement review implementation readiness"
729
+ require_grep '^open_blockers:[[:space:]]*0[[:space:]]*$' requirement-review.md "requirement reverse review has no open blockers"
730
+ require_grep '^open_external_contracts:[[:space:]]*0[[:space:]]*$' requirement-review.md "requirement review has no open external contracts"
731
+ require_grep '^open_source_investigations:[[:space:]]*0[[:space:]]*$' requirement-review.md "requirement review has no open source investigations"
732
+ require_grep '^open_owner_decisions:[[:space:]]*0[[:space:]]*$' requirement-review.md "requirement review has no open owner decisions"
733
+ require_grep 'Closure Matrix' requirement-review.md "requirement review closure matrix"
734
+ require_grep 'Review Findings' requirement-review.md "requirement review findings"
735
+ require_grep 'Open Blockers' requirement-review.md "requirement review open blocker ledger"
553
736
  require_minimal_design_review design.md "complexity reduction review"
554
737
  require_grep 'Minimal Design Review|Complexity Reduction Review' sdd-quality-gate.md "complexity reduction quality gate"
555
738
  require_minimal_design_pass sdd-quality-gate.md
739
+ if change_has_source_fact_risk; then
740
+ require_source_fact_audit
741
+ fi
556
742
  fi
557
743
  if change_has_money_precision_risk; then
558
744
  require_grep 'Money Precision Boundary' sdd-quality-gate.md "money precision quality gate"
@@ -583,6 +769,9 @@ case "$PHASE" in
583
769
  require_handoff_current
584
770
  require_beta_handoff_structure
585
771
  require_hash_recorded
772
+ if change_has_database_change; then
773
+ require_frozen_release_sql
774
+ fi
586
775
  workflow="$(state_get workflow)"
587
776
  if [[ "$workflow" == "full" ]]; then
588
777
  require_minimal_design_review design.md "complexity reduction review"
@@ -622,11 +811,14 @@ case "$PHASE" in
622
811
  require_handoff_current
623
812
  require_beta_handoff_structure
624
813
  require_hash_recorded
814
+ if change_has_database_change; then
815
+ require_frozen_release_sql
816
+ fi
625
817
  require_any_prompt
626
818
  require_prompt_set
627
819
  require_grep 'OpenSpec/SDD|canonical design source|canonical|source of truth' design.md "canonical source boundary"
628
- prompt_rel="$(first_prompt_rel)"
629
- if [[ -n "${prompt_rel:-}" ]]; then
820
+ while IFS= read -r prompt_rel; do
821
+ [[ -n "${prompt_rel:-}" ]] || continue
630
822
  require_grep 'Superpowers Technical Design inheritance|Superpowers execution strategy inheritance|technical_design|source-level HOW' "$prompt_rel" "prompt Superpower strategy inheritance"
631
823
  technical_design_rel="$(state_get technical_design)"
632
824
  if [[ -n "${technical_design_rel:-}" && "$technical_design_rel" != "null" ]]; then
@@ -645,7 +837,11 @@ case "$PHASE" in
645
837
  fi
646
838
  fi
647
839
  require_grep 'context anti-drift|handoff_hash|sdd-context' "$prompt_rel" "prompt context drift inheritance"
648
- fi
840
+ if change_has_database_change; then
841
+ require_grep 'release-sql\.md' "$prompt_rel" "prompt frozen release SQL reference"
842
+ require_grep 'verbatim|sql_sha256' "$prompt_rel" "prompt verbatim SQL copy contract"
843
+ fi
844
+ done < <(prompt_rels)
649
845
  require_state_value build_mode "build_mode"
650
846
  require_state_value isolation "isolation"
651
847
  require_state_value tdd_mode "tdd_mode"
@@ -244,10 +244,13 @@ sync_state() {
244
244
  "$state_sh" set "$CHANGE_DIR" context_compression "$context_compression"
245
245
  "$state_sh" set "$CHANGE_DIR" handoff_context .sdd/handoff/sdd-context.json
246
246
  "$state_sh" set "$CHANGE_DIR" handoff_hash "$context_hash"
247
- technical_design_rel="$(
248
- find "$CHANGE_DIR/docs/superpowers/specs" -maxdepth 1 -type f -name '*.md' 2>/dev/null \
249
- | sort | head -n 1 | sed "s#^$CHANGE_DIR/##"
250
- )"
247
+ technical_design_rel=""
248
+ if [[ -d "$CHANGE_DIR/docs/superpowers/specs" ]]; then
249
+ technical_design_rel="$(
250
+ find "$CHANGE_DIR/docs/superpowers/specs" -maxdepth 1 -type f -name '*.md' \
251
+ | sort | head -n 1 | sed "s#^$CHANGE_DIR/##"
252
+ )"
253
+ fi
251
254
  if [[ -n "$technical_design_rel" ]]; then
252
255
  "$state_sh" set "$CHANGE_DIR" technical_design "$technical_design_rel"
253
256
  fi