@chenmk/superflow 0.3.0 → 0.5.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 (261) hide show
  1. package/INSTALL.en.md +54 -12
  2. package/INSTALL.md +59 -33
  3. package/README.md +192 -49
  4. package/README.zh-CN.md +166 -46
  5. package/assets/brand/managed-review-loop.png +0 -0
  6. package/assets/manifest.json +15 -9
  7. package/assets/prompts/superflow-design.md +3 -0
  8. package/assets/prompts/superflow-docs.md +4 -1
  9. package/assets/scripts/superflow-coding-ready.mjs +135 -0
  10. package/assets/scripts/superflow-dependency-update-hook.sh +81 -8
  11. package/assets/scripts/superflow-document-audit.mjs +240 -0
  12. package/assets/scripts/superflow-environment-preflight.mjs +398 -0
  13. package/assets/scripts/superflow-hook-guard.sh +40 -1
  14. package/assets/scripts/superflow-managed-command-guard.py +309 -0
  15. package/assets/scripts/superflow-managed-executor-preflight.mjs +421 -0
  16. package/assets/scripts/superflow-managed-owner-verification.sh +117 -0
  17. package/assets/scripts/superflow-managed-work-check.mjs +455 -0
  18. package/assets/scripts/superflow-managed-work-guard.sh +17 -0
  19. package/assets/skills/openspec-propose/SKILL.md +11 -0
  20. package/assets/skills/superflow-clarify/SKILL.md +14 -0
  21. package/assets/skills/superflow-design/SKILL.md +46 -12
  22. package/assets/skills/superflow-docs/SKILL.md +109 -2
  23. package/assets/skills/superflow-pipeline/SKILL.md +205 -2
  24. package/assets/skills/superflow-pipeline/references/batch-prompt-template.md +17 -9
  25. package/assets/skills/superflow-pipeline/references/document-readiness.md +157 -0
  26. package/assets/skills/superflow-pipeline/references/document-templates.md +17 -5
  27. package/assets/skills/superflow-pipeline/references/feature-gated-workflow.md +14 -0
  28. package/assets/skills/superflow-pipeline/references/implementation-prompt-template.md +20 -11
  29. package/assets/skills/superflow-pipeline/references/managed-work.md +166 -0
  30. package/assets/skills/superflow-pipeline/references/orchestration.md +2 -2
  31. package/assets/skills/superflow-pipeline/references/p0-baseline-template.md +3 -2
  32. package/assets/skills/superflow-pipeline/references/quality-gate.md +8 -5
  33. package/assets/skills/superflow-pipeline/references/reviewer-checklist.md +7 -0
  34. package/assets/skills/superflow-pipeline/references/superpower-technical-design-template.md +10 -0
  35. package/assets/skills/superflow-pipeline/scripts/superflow-archive.sh +1 -1
  36. package/assets/skills/superflow-pipeline/scripts/superflow-guard.sh +282 -16
  37. package/assets/skills/superflow-pipeline/scripts/superflow-handoff.sh +7 -4
  38. package/assets/skills/superflow-requirement-review/SKILL.md +178 -0
  39. package/assets/skills/superflow-requirement-review/agents/openai.yaml +4 -0
  40. package/assets/skills-en/openspec-propose/SKILL.md +14 -0
  41. package/assets/skills-en/superflow-clarify/SKILL.md +17 -0
  42. package/assets/skills-en/superflow-design/SKILL.md +40 -11
  43. package/assets/skills-en/superflow-docs/SKILL.md +115 -0
  44. package/assets/skills-en/superflow-pipeline/SKILL.md +202 -0
  45. package/assets/skills-en/superflow-pipeline/references/batch-prompt-template.md +4 -0
  46. package/assets/skills-en/superflow-pipeline/references/document-readiness.md +125 -0
  47. package/assets/skills-en/superflow-pipeline/references/document-templates.md +15 -0
  48. package/assets/skills-en/superflow-pipeline/references/feature-gated-workflow.md +7 -0
  49. package/assets/skills-en/superflow-pipeline/references/implementation-prompt-template.md +7 -0
  50. package/assets/skills-en/superflow-pipeline/references/managed-work.md +184 -0
  51. package/assets/skills-en/superflow-pipeline/references/quality-gate.md +20 -0
  52. package/assets/skills-en/superflow-pipeline/references/reviewer-checklist.md +7 -0
  53. package/assets/skills-en/superflow-pipeline/references/superpower-technical-design-template.md +11 -0
  54. package/assets/skills-en/superflow-pipeline/scripts/superflow-archive.sh +1 -1
  55. package/assets/skills-en/superflow-pipeline/scripts/superflow-guard.sh +279 -14
  56. package/assets/skills-en/superflow-pipeline/scripts/superflow-handoff.sh +7 -4
  57. package/assets/skills-en/superflow-requirement-review/SKILL.md +99 -0
  58. package/assets/skills-en/superflow-requirement-review/agents/openai.yaml +4 -0
  59. package/dist/app/cli.js +176 -103
  60. package/dist/app/cli.js.map +1 -1
  61. package/dist/app/commands/change-guard.js +19 -2
  62. package/dist/app/commands/change-guard.js.map +1 -1
  63. package/dist/app/commands/check.js +107 -45
  64. package/dist/app/commands/check.js.map +1 -1
  65. package/dist/app/commands/docs.js +7 -3
  66. package/dist/app/commands/docs.js.map +1 -1
  67. package/dist/app/commands/doctor.js +174 -198
  68. package/dist/app/commands/doctor.js.map +1 -1
  69. package/dist/app/commands/eval.js +64 -0
  70. package/dist/app/commands/eval.js.map +1 -0
  71. package/dist/app/commands/implement.js +7 -3
  72. package/dist/app/commands/implement.js.map +1 -1
  73. package/dist/app/commands/init.js +16 -24
  74. package/dist/app/commands/init.js.map +1 -1
  75. package/dist/app/commands/managed-service.js +5 -0
  76. package/dist/app/commands/managed-service.js.map +1 -0
  77. package/dist/app/commands/mcp.js +167 -0
  78. package/dist/app/commands/mcp.js.map +1 -0
  79. package/dist/app/commands/pipeline.js +757 -3
  80. package/dist/app/commands/pipeline.js.map +1 -1
  81. package/dist/app/commands/requirement-review.js +6 -0
  82. package/dist/app/commands/requirement-review.js.map +1 -0
  83. package/dist/app/commands/status.js +262 -77
  84. package/dist/app/commands/status.js.map +1 -1
  85. package/dist/app/commands/uninstall.js +8 -5
  86. package/dist/app/commands/uninstall.js.map +1 -1
  87. package/dist/app/commands/update.js +114 -15
  88. package/dist/app/commands/update.js.map +1 -1
  89. package/dist/domains/agent.js +3 -11
  90. package/dist/domains/agent.js.map +1 -1
  91. package/dist/domains/config/cli-help.js +145 -73
  92. package/dist/domains/config/cli-help.js.map +1 -1
  93. package/dist/domains/config/i18n.js +6 -8
  94. package/dist/domains/config/i18n.js.map +1 -1
  95. package/dist/domains/config/manifest.js +0 -3
  96. package/dist/domains/config/manifest.js.map +1 -1
  97. package/dist/domains/deps.js +70 -8
  98. package/dist/domains/deps.js.map +1 -1
  99. package/dist/domains/hook.js +71 -38
  100. package/dist/domains/hook.js.map +1 -1
  101. package/dist/domains/managed-work/completion-policy.js +174 -0
  102. package/dist/domains/managed-work/completion-policy.js.map +1 -0
  103. package/dist/domains/managed-work/context-manifest.js +208 -0
  104. package/dist/domains/managed-work/context-manifest.js.map +1 -0
  105. package/dist/domains/managed-work/contract.js +349 -0
  106. package/dist/domains/managed-work/contract.js.map +1 -0
  107. package/dist/domains/managed-work/control-signals.js +34 -0
  108. package/dist/domains/managed-work/control-signals.js.map +1 -0
  109. package/dist/domains/managed-work/control.js +628 -0
  110. package/dist/domains/managed-work/control.js.map +1 -0
  111. package/dist/domains/managed-work/evaluation.js +497 -0
  112. package/dist/domains/managed-work/evaluation.js.map +1 -0
  113. package/dist/domains/managed-work/evidence-path.js +14 -0
  114. package/dist/domains/managed-work/evidence-path.js.map +1 -0
  115. package/dist/domains/managed-work/execution-contract.js +167 -0
  116. package/dist/domains/managed-work/execution-contract.js.map +1 -0
  117. package/dist/domains/managed-work/executor-policy.js +65 -0
  118. package/dist/domains/managed-work/executor-policy.js.map +1 -0
  119. package/dist/domains/managed-work/failure.js +65 -0
  120. package/dist/domains/managed-work/failure.js.map +1 -0
  121. package/dist/domains/managed-work/host-review.js +77 -0
  122. package/dist/domains/managed-work/host-review.js.map +1 -0
  123. package/dist/domains/managed-work/human-messages.js +31 -0
  124. package/dist/domains/managed-work/human-messages.js.map +1 -0
  125. package/dist/domains/managed-work/i18n.js +12 -0
  126. package/dist/domains/managed-work/i18n.js.map +1 -0
  127. package/dist/domains/managed-work/input.js +137 -0
  128. package/dist/domains/managed-work/input.js.map +1 -0
  129. package/dist/domains/managed-work/journal.js +196 -0
  130. package/dist/domains/managed-work/journal.js.map +1 -0
  131. package/dist/domains/managed-work/lock.js +106 -0
  132. package/dist/domains/managed-work/lock.js.map +1 -0
  133. package/dist/domains/managed-work/notifications.js +38 -0
  134. package/dist/domains/managed-work/notifications.js.map +1 -0
  135. package/dist/domains/managed-work/pair-admission.js +108 -0
  136. package/dist/domains/managed-work/pair-admission.js.map +1 -0
  137. package/dist/domains/managed-work/paths.js +18 -0
  138. package/dist/domains/managed-work/paths.js.map +1 -0
  139. package/dist/domains/managed-work/prompts.js +453 -0
  140. package/dist/domains/managed-work/prompts.js.map +1 -0
  141. package/dist/domains/managed-work/redaction.js +90 -0
  142. package/dist/domains/managed-work/redaction.js.map +1 -0
  143. package/dist/domains/managed-work/review-convergence.js +41 -0
  144. package/dist/domains/managed-work/review-convergence.js.map +1 -0
  145. package/dist/domains/managed-work/review-facts.js +181 -0
  146. package/dist/domains/managed-work/review-facts.js.map +1 -0
  147. package/dist/domains/managed-work/rule-selection.js +84 -0
  148. package/dist/domains/managed-work/rule-selection.js.map +1 -0
  149. package/dist/domains/managed-work/runner.js +2418 -0
  150. package/dist/domains/managed-work/runner.js.map +1 -0
  151. package/dist/domains/managed-work/schemas.js +155 -0
  152. package/dist/domains/managed-work/schemas.js.map +1 -0
  153. package/dist/domains/managed-work/service.js +190 -0
  154. package/dist/domains/managed-work/service.js.map +1 -0
  155. package/dist/domains/managed-work/state.js +280 -0
  156. package/dist/domains/managed-work/state.js.map +1 -0
  157. package/dist/domains/managed-work/storage.js +223 -0
  158. package/dist/domains/managed-work/storage.js.map +1 -0
  159. package/dist/domains/managed-work/types.js +19 -0
  160. package/dist/domains/managed-work/types.js.map +1 -0
  161. package/dist/domains/managed-work/verification-categories.js +39 -0
  162. package/dist/domains/managed-work/verification-categories.js.map +1 -0
  163. package/dist/domains/managed-work/verification-policy.js +116 -0
  164. package/dist/domains/managed-work/verification-policy.js.map +1 -0
  165. package/dist/domains/managed-work/wait.js +58 -0
  166. package/dist/domains/managed-work/wait.js.map +1 -0
  167. package/dist/domains/managed-work/workspace-binding.js +133 -0
  168. package/dist/domains/managed-work/workspace-binding.js.map +1 -0
  169. package/dist/domains/sdd-readiness.js +44 -0
  170. package/dist/domains/sdd-readiness.js.map +1 -0
  171. package/dist/domains/skill/deploy.js +0 -6
  172. package/dist/domains/skill/deploy.js.map +1 -1
  173. package/dist/domains/skill/scripts.js +0 -8
  174. package/dist/domains/skill/scripts.js.map +1 -1
  175. package/dist/domains/state.js +1 -2
  176. package/dist/domains/state.js.map +1 -1
  177. package/dist/mcp/runtime-identity.js +21 -0
  178. package/dist/mcp/runtime-identity.js.map +1 -0
  179. package/dist/mcp/server.js +369 -0
  180. package/dist/mcp/server.js.map +1 -0
  181. package/dist/platform/agent-process.js +769 -0
  182. package/dist/platform/agent-process.js.map +1 -0
  183. package/dist/platform/executable.js +28 -0
  184. package/dist/platform/executable.js.map +1 -0
  185. package/dist/platform/paths.js +1 -17
  186. package/dist/platform/paths.js.map +1 -1
  187. package/dist/platform/process-liveness.js +10 -0
  188. package/dist/platform/process-liveness.js.map +1 -0
  189. package/dist/platform/process-tree.js +44 -0
  190. package/dist/platform/process-tree.js.map +1 -0
  191. package/dist/platform/process.js +1 -1
  192. package/dist/platform/process.js.map +1 -1
  193. package/dist/platform/version-check.js +30 -9
  194. package/dist/platform/version-check.js.map +1 -1
  195. package/package.json +16 -7
  196. package/scripts/check-design-principles.mjs +107 -0
  197. package/scripts/check-managed-work-design.mjs +507 -0
  198. package/scripts/clean-dist.js +9 -0
  199. package/scripts/ensure-bin-modes.js +11 -0
  200. package/dist/cli/index.js +0 -193
  201. package/dist/cli/index.js.map +0 -1
  202. package/dist/commands/archive.js +0 -6
  203. package/dist/commands/archive.js.map +0 -1
  204. package/dist/commands/clarify.js +0 -6
  205. package/dist/commands/clarify.js.map +0 -1
  206. package/dist/commands/design.js +0 -28
  207. package/dist/commands/design.js.map +0 -1
  208. package/dist/commands/docs.js +0 -6
  209. package/dist/commands/docs.js.map +0 -1
  210. package/dist/commands/doctor.js +0 -494
  211. package/dist/commands/doctor.js.map +0 -1
  212. package/dist/commands/implement.js +0 -6
  213. package/dist/commands/implement.js.map +0 -1
  214. package/dist/commands/init.js +0 -520
  215. package/dist/commands/init.js.map +0 -1
  216. package/dist/commands/pipeline.js +0 -6
  217. package/dist/commands/pipeline.js.map +0 -1
  218. package/dist/commands/scan.js +0 -63
  219. package/dist/commands/scan.js.map +0 -1
  220. package/dist/commands/status.js +0 -173
  221. package/dist/commands/status.js.map +0 -1
  222. package/dist/commands/uninstall.js +0 -214
  223. package/dist/commands/uninstall.js.map +0 -1
  224. package/dist/commands/update.js +0 -193
  225. package/dist/commands/update.js.map +0 -1
  226. package/dist/commands/verify.js +0 -6
  227. package/dist/commands/verify.js.map +0 -1
  228. package/dist/core/assets.js +0 -27
  229. package/dist/core/assets.js.map +0 -1
  230. package/dist/core/cli-help.js +0 -98
  231. package/dist/core/cli-help.js.map +0 -1
  232. package/dist/core/context.js +0 -123
  233. package/dist/core/context.js.map +0 -1
  234. package/dist/core/dependencies.js +0 -146
  235. package/dist/core/dependencies.js.map +0 -1
  236. package/dist/core/detect.js +0 -64
  237. package/dist/core/detect.js.map +0 -1
  238. package/dist/core/i18n.js +0 -105
  239. package/dist/core/i18n.js.map +0 -1
  240. package/dist/core/integrity.js +0 -46
  241. package/dist/core/integrity.js.map +0 -1
  242. package/dist/core/manifest.js +0 -21
  243. package/dist/core/manifest.js.map +0 -1
  244. package/dist/core/prompts.js +0 -20
  245. package/dist/core/prompts.js.map +0 -1
  246. package/dist/core/registry.js +0 -134
  247. package/dist/core/registry.js.map +0 -1
  248. package/dist/core/rules.js +0 -17
  249. package/dist/core/rules.js.map +0 -1
  250. package/dist/core/scripts.js +0 -48
  251. package/dist/core/scripts.js.map +0 -1
  252. package/dist/core/skill-check.js +0 -32
  253. package/dist/core/skill-check.js.map +0 -1
  254. package/dist/core/skills.js +0 -62
  255. package/dist/core/skills.js.map +0 -1
  256. package/dist/core/state.js +0 -54
  257. package/dist/core/state.js.map +0 -1
  258. package/dist/utils/path.js +0 -11
  259. package/dist/utils/path.js.map +0 -1
  260. package/dist/utils/shell.js +0 -29
  261. package/dist/utils/shell.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "0.1.2",
3
- "agents": ["claude", "codex", "opencode"],
3
+ "agents": ["claude", "codex"],
4
4
  "skills": [
5
5
  "openspec-apply-change",
6
6
  "openspec-archive-change",
@@ -13,13 +13,12 @@
13
13
  "superflow-hotfix",
14
14
  "superflow-implement",
15
15
  "superflow-pipeline",
16
+ "superflow-requirement-review",
16
17
  "superflow-table-impact-analysis",
17
18
  "superflow-tweak",
18
19
  "superflow-verify"
19
20
  ],
20
- "rules": [
21
- "superflow-phase-guard.md"
22
- ],
21
+ "rules": ["superflow-phase-guard.md"],
23
22
  "scripts": [
24
23
  "superflow-verify-integration.sh",
25
24
  "superflow-delivery-check.sh",
@@ -31,13 +30,20 @@
31
30
  "superflow-integration-evidence-hook.sh",
32
31
  "superflow-archive-command-hook.sh",
33
32
  "superflow-test-report-lint.py",
33
+ "superflow-managed-work-check.mjs",
34
+ "superflow-document-audit.mjs",
35
+ "superflow-environment-preflight.mjs",
36
+ "superflow-coding-ready.mjs",
37
+ "superflow-managed-executor-preflight.mjs",
38
+ "superflow-managed-owner-verification.sh",
39
+ "superflow-managed-command-guard.py",
40
+ "superflow-managed-work-guard.sh",
34
41
  "install-sql-pre-commit.sh",
35
42
  "sync-settings-json.py"
36
43
  ],
37
44
  "agentScripts": {
38
45
  "claude": ["claude-auto-backup-hook.sh"],
39
- "codex": ["codex-auto-backup-hook.sh"],
40
- "opencode": []
46
+ "codex": ["codex-auto-backup-hook.sh"]
41
47
  },
42
48
  "hooks": [
43
49
  "superflow-enforce-hook.sh",
@@ -47,11 +53,11 @@
47
53
  "superflow-sql-sync-hook.py",
48
54
  "superflow-delivery-check.sh",
49
55
  "superflow-integration-evidence-hook.sh",
50
- "superflow-archive-command-hook.sh"
56
+ "superflow-archive-command-hook.sh",
57
+ "superflow-managed-work-guard.sh"
51
58
  ],
52
59
  "agentHooks": {
53
60
  "claude": ["claude-auto-backup-hook.sh"],
54
- "codex": ["codex-auto-backup-hook.sh"],
55
- "opencode": []
61
+ "codex": ["codex-auto-backup-hook.sh"]
56
62
  }
57
63
  }
@@ -8,3 +8,6 @@ Use the `superflow-design` skill for this request.
8
8
  Let Superpowers handle source-level HOW: inspect real code, reverse impact,
9
9
  field references, TDD strategy, worker split, worktree and port planning. Do not
10
10
  rewrite OpenSpec contracts unless a conflict is found and returned to docs.
11
+ Complete the source-level Minimal Design Review before implementation planning:
12
+ prove reuse and necessity, choose the simplest implementation, and explicitly
13
+ remove or reject unsupported complexity.
@@ -7,4 +7,7 @@ Use the `superflow-docs` skill for this request.
7
7
 
8
8
  Keep OpenSpec as the source of WHAT and contracts. Ensure API, DB, tests,
9
9
  traceability, quality gates, and handoff files are complete before technical
10
- design starts.
10
+ design starts. For full workflows, require a Minimal Design Review in
11
+ `design.md` and a PASS/BLOCKED verdict in `sdd-quality-gate.md`; prefer reuse
12
+ and remove unsupported tables, fields, APIs, services, caches, async flows,
13
+ jobs, and compatibility layers.
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawnSync } from "node:child_process";
4
+ import fs from "node:fs";
5
+ import os from "node:os";
6
+ import path from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+
9
+ const args = process.argv.slice(2);
10
+ const changeArg = args.find((arg) => !arg.startsWith("--"));
11
+ const jsonOutput = args.includes("--json");
12
+
13
+ if (!changeArg) {
14
+ fail(["用法: superflow-coding-ready.mjs <change-dir> [--json]"]);
15
+ }
16
+
17
+ const changeDir = fs.realpathSync(path.resolve(changeArg));
18
+ const scriptDir = path.dirname(fileURLToPath(import.meta.url));
19
+ const pipelineScripts = resolvePipelineScripts(scriptDir);
20
+ const checks = [
21
+ ["YAML 状态", "bash", [path.join(pipelineScripts, "superflow-yaml-validate.sh"), changeDir]],
22
+ ["docs 门禁", "bash", [path.join(pipelineScripts, "superflow-guard.sh"), changeDir, "docs"]],
23
+ ["design 门禁", "bash", [path.join(pipelineScripts, "superflow-guard.sh"), changeDir, "design"]],
24
+ ["implement 门禁", "bash", [path.join(pipelineScripts, "superflow-guard.sh"), changeDir, "implement"]],
25
+ ["文档交付审计", process.execPath, [path.join(scriptDir, "superflow-document-audit.mjs"), changeDir, "--json"]],
26
+ ["环境预检", process.execPath, [path.join(scriptDir, "superflow-environment-preflight.mjs"), changeDir, "--json"]],
27
+ ];
28
+ const issues = [];
29
+ const evidence = [];
30
+
31
+ for (const [label, command, commandArgs] of checks) {
32
+ const result = spawnSync(command, commandArgs, {
33
+ cwd: projectRoot(changeDir),
34
+ encoding: "utf-8",
35
+ env: { ...process.env, SUPERFLOW_CODING_READY: "1" },
36
+ });
37
+ evidence.push({ label, exitCode: result.status ?? 1 });
38
+ if (result.status !== 0) {
39
+ issues.push(`${label}失败:${tail(result.stderr || result.stdout)}`);
40
+ }
41
+ }
42
+
43
+ const openspec = spawnSync("openspec", ["validate", path.basename(changeDir), "--strict"], {
44
+ cwd: projectRoot(changeDir),
45
+ encoding: "utf-8",
46
+ });
47
+ evidence.push({ label: "OpenSpec strict", exitCode: openspec.status ?? 1 });
48
+ if (openspec.status !== 0) {
49
+ issues.push(`OpenSpec strict 失败:${tail(openspec.stderr || openspec.stdout)}`);
50
+ }
51
+
52
+ const handoffHash = readHandoffHash(changeDir, issues);
53
+ const reviewRounds = readReviewRounds(changeDir);
54
+ const receipt = {
55
+ schemaVersion: "superflow.coding-ready.v1",
56
+ codingReady: issues.length === 0,
57
+ documentReadiness: issues.length === 0 ? "READY" : "BLOCKED",
58
+ environmentReadiness: issues.length === 0 ? "READY" : "BLOCKED",
59
+ reviewRounds,
60
+ handoffHash,
61
+ checkedAt: new Date().toISOString(),
62
+ evidence,
63
+ ownerDecisions: 0,
64
+ issues,
65
+ };
66
+
67
+ if (issues.length > 0) fail(issues, receipt);
68
+
69
+ const receiptDir = path.join(changeDir, ".sdd", "readiness");
70
+ fs.mkdirSync(receiptDir, { recursive: true });
71
+ const target = path.join(receiptDir, "coding-ready.json");
72
+ const temporary = path.join(receiptDir, `.coding-ready-${process.pid}-${Date.now()}.tmp`);
73
+ fs.writeFileSync(temporary, `${JSON.stringify(receipt, null, 2)}\n`, { mode: 0o600 });
74
+ fs.renameSync(temporary, target);
75
+
76
+ if (jsonOutput) {
77
+ process.stdout.write(`${JSON.stringify(receipt, null, 2)}\n`);
78
+ } else {
79
+ process.stdout.write(`Coding Ready 通过,凭证已写入 ${target}\n`);
80
+ }
81
+
82
+ function resolvePipelineScripts(currentScriptDir) {
83
+ const candidates = [
84
+ path.resolve(currentScriptDir, "..", "skills", "superflow-pipeline", "scripts"),
85
+ path.join(os.homedir(), ".codex", "skills", "superflow-pipeline", "scripts"),
86
+ path.join(os.homedir(), ".claude", "skills", "superflow-pipeline", "scripts"),
87
+ ];
88
+ const found = candidates.find((candidate) =>
89
+ fs.existsSync(path.join(candidate, "superflow-guard.sh")),
90
+ );
91
+ if (!found) {
92
+ fail(["找不到 superflow-pipeline 门禁脚本,请先执行 superflow update"]);
93
+ }
94
+ return found;
95
+ }
96
+
97
+ function projectRoot(root) {
98
+ return path.resolve(root, "..", "..", "..");
99
+ }
100
+
101
+ function readHandoffHash(root, targetIssues) {
102
+ const file = path.join(root, ".sdd", "handoff", "sdd-context.sha256");
103
+ const content = fs.existsSync(file) ? fs.readFileSync(file, "utf-8") : "";
104
+ const match = content.match(/[a-f0-9]{64}/i);
105
+ if (!match) {
106
+ targetIssues.push("缺少合法的当前 handoff hash");
107
+ return "";
108
+ }
109
+ return match[0].toLowerCase();
110
+ }
111
+
112
+ function readReviewRounds(root) {
113
+ const file = path.join(root, ".sdd", "reviews", "document-review.json");
114
+ try {
115
+ const review = JSON.parse(fs.readFileSync(file, "utf-8"));
116
+ return Array.isArray(review.rounds) ? review.rounds.length : 0;
117
+ } catch {
118
+ return 0;
119
+ }
120
+ }
121
+
122
+ function tail(value) {
123
+ return String(value).trim().split("\n").slice(-4).join(" | ").slice(0, 800);
124
+ }
125
+
126
+ function fail(targetIssues, receipt = { codingReady: false, issues: targetIssues }) {
127
+ if (jsonOutput) {
128
+ process.stderr.write(`${JSON.stringify(receipt, null, 2)}\n`);
129
+ } else {
130
+ process.stderr.write(
131
+ `Coding Ready 未通过:\n${targetIssues.map((item) => `- ${item}`).join("\n")}\n`,
132
+ );
133
+ }
134
+ process.exit(1);
135
+ }
@@ -24,6 +24,22 @@ fi
24
24
  STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/superflow"
25
25
  mkdir -p "$STATE_DIR" 2>/dev/null || exit 0
26
26
 
27
+ LANGUAGE="${SUPERFLOW_LANG:-}"
28
+ if [ -z "$LANGUAGE" ] && [ -f "$HOME/.sdd-state.json" ]; then
29
+ LANGUAGE=$(python3 -c '
30
+ import json, os
31
+ try:
32
+ with open(os.path.expanduser("~/.sdd-state.json"), encoding="utf-8") as f:
33
+ print((json.load(f).get("language") or "").strip())
34
+ except Exception:
35
+ pass
36
+ ' 2>/dev/null)
37
+ fi
38
+ case "${LANGUAGE%%_*}" in
39
+ en|en-*) LANGUAGE="en" ;;
40
+ *) LANGUAGE="zh" ;;
41
+ esac
42
+
27
43
  SESSION_KEY=$(printf '%s' "$INPUT" | python3 -c '
28
44
  import hashlib, json, os, sys
29
45
  raw = sys.stdin.read()
@@ -111,15 +127,49 @@ if version:
111
127
  update_npm_if_needed() {
112
128
  local package_name="$1"
113
129
  local current latest
114
- command -v npm >/dev/null 2>&1 || return 0
130
+ command -v npm >/dev/null 2>&1 || return 1
115
131
  latest="$(latest_npm_version "$package_name")"
116
- [ -n "$latest" ] || return 0
132
+ if [ -z "$latest" ]; then
133
+ if [ "$LANGUAGE" = "en" ]; then
134
+ printf '\n[%s] Cannot confirm the latest version of %s\n' \
135
+ "$(date '+%Y-%m-%d %H:%M:%S')" "$package_name" \
136
+ >> "$LOG_FILE" 2>/dev/null || true
137
+ else
138
+ printf '\n[%s] 无法确认 %s 的最新版本\n' \
139
+ "$(date '+%Y-%m-%d %H:%M:%S')" "$package_name" \
140
+ >> "$LOG_FILE" 2>/dev/null || true
141
+ fi
142
+ return 1
143
+ fi
117
144
  current="$(installed_npm_version "$package_name")"
118
145
  if [ "$current" != "$latest" ]; then
119
- run_logged npm install -g "$package_name@latest" || true
146
+ run_logged npm install -g "$package_name@latest"
120
147
  fi
121
148
  }
122
149
 
150
+ detected_agents() {
151
+ local agents=""
152
+ command -v codex >/dev/null 2>&1 && agents="codex"
153
+ if command -v claude >/dev/null 2>&1; then
154
+ agents="${agents:+$agents,}claude"
155
+ fi
156
+ printf '%s' "$agents"
157
+ }
158
+
159
+ refresh_superflow_installation() {
160
+ local agents="$1"
161
+ [ -n "$agents" ] || return 1
162
+ if command -v superflow >/dev/null 2>&1; then
163
+ run_logged superflow update --agent "$agents" --scope global
164
+ return $?
165
+ fi
166
+ local npm_root cli
167
+ npm_root="$(npm root -g 2>/dev/null)" || return 1
168
+ cli="$npm_root/@chenmk/superflow/dist/app/cli.js"
169
+ [ -f "$cli" ] || return 1
170
+ run_logged node "$cli" update --agent "$agents" --scope global
171
+ }
172
+
123
173
  check_npm_package() {
124
174
  local package_name="$1"
125
175
  local current latest
@@ -135,15 +185,34 @@ check_npm_package() {
135
185
  }
136
186
 
137
187
  if [ "$MODE" = "apply" ]; then
138
- update_npm_if_needed "@chenmk/superflow"
139
- update_npm_if_needed "@fission-ai/openspec"
188
+ APPLY_FAILED=0
189
+ update_npm_if_needed "@chenmk/superflow" || APPLY_FAILED=1
190
+ update_npm_if_needed "@fission-ai/openspec" || APPLY_FAILED=1
140
191
 
141
192
  if command -v claude >/dev/null 2>&1; then
142
- run_logged claude plugin install superpowers@superpowers-marketplace || true
193
+ run_logged claude plugin install superpowers@superpowers-marketplace || APPLY_FAILED=1
143
194
  fi
144
195
 
145
196
  if command -v codex >/dev/null 2>&1; then
146
- run_logged codex plugin add superpowers@openai-curated || true
197
+ run_logged codex plugin add superpowers@openai-api-curated || APPLY_FAILED=1
198
+ fi
199
+
200
+ AGENT_VALUE="$(detected_agents)"
201
+ refresh_superflow_installation "$AGENT_VALUE" || APPLY_FAILED=1
202
+
203
+ if [ "$APPLY_FAILED" -ne 0 ]; then
204
+ rm -f "$STAMP" "$GLOBAL_STAMP" 2>/dev/null || true
205
+ if [ "$LANGUAGE" = "en" ]; then
206
+ printf '[Superflow] Automatic update was incomplete and remains retryable; details: %s\n' "$LOG_FILE" >&2
207
+ else
208
+ printf '[Superflow] 自动升级未完整完成,已保留重试资格;详情:%s\n' "$LOG_FILE" >&2
209
+ fi
210
+ else
211
+ if [ "$LANGUAGE" = "en" ]; then
212
+ printf '[Superflow] Automatic update refreshed CLI, dependencies, Skills, Hooks, rules, and managed MCP; restart the Agent to load the new runtime.\n' >&2
213
+ else
214
+ printf '[Superflow] 自动升级已完整更新 CLI、依赖、Skills、Hooks、规则和托管 MCP;请重启 Agent 加载新运行时。\n' >&2
215
+ fi
147
216
  fi
148
217
  else
149
218
  STATUS_FILE="$STATE_DIR/dependency-update-status.txt"
@@ -154,7 +223,11 @@ else
154
223
  printf 'superpowers=run superflow update --with-package to refresh selected agent plugins\n'
155
224
  } > "$STATUS_FILE" 2>/dev/null || true
156
225
  if grep -Eq '^@' "$STATUS_FILE" 2>/dev/null; then
157
- printf '[Superflow] 有核心依赖更新,执行 superflow update --with-package 统一更新;详情:%s\n' "$STATUS_FILE" >&2
226
+ if [ "$LANGUAGE" = "en" ]; then
227
+ printf '[Superflow] Core dependency updates are available. Run superflow update --with-package; details: %s\n' "$STATUS_FILE" >&2
228
+ else
229
+ printf '[Superflow] 有核心依赖更新,执行 superflow update --with-package 统一更新;详情:%s\n' "$STATUS_FILE" >&2
230
+ fi
158
231
  fi
159
232
  fi
160
233
 
@@ -0,0 +1,240 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+
6
+ const args = process.argv.slice(2);
7
+ const changeArg = args.find((arg) => !arg.startsWith("--"));
8
+ const jsonOutput = args.includes("--json");
9
+
10
+ if (!changeArg) {
11
+ fail(["用法: superflow-document-audit.mjs <change-dir> [--json]"]);
12
+ }
13
+
14
+ const changeDir = fs.realpathSync(path.resolve(changeArg));
15
+ const issues = [];
16
+ const prompts = markdownFiles(path.join(changeDir, "prompt"));
17
+ const handoffHash = readHandoffHash(changeDir, issues);
18
+ const aggregateDocuments = [
19
+ "tasks.md",
20
+ "traceability-matrix.md",
21
+ "sdd-quality-gate.md",
22
+ "test-report.md",
23
+ ];
24
+
25
+ if (prompts.length === 0) {
26
+ issues.push("prompt/ 目录至少需要一份 Markdown 实现 Prompt");
27
+ }
28
+
29
+ for (const document of aggregateDocuments) {
30
+ const documentPath = path.join(changeDir, document);
31
+ if (!fs.existsSync(documentPath)) {
32
+ issues.push(`缺少文档: ${document}`);
33
+ continue;
34
+ }
35
+ const links = markdownTargets(fs.readFileSync(documentPath, "utf-8"));
36
+ for (const prompt of prompts) {
37
+ const relativePrompt = path.relative(changeDir, prompt).replaceAll("\\", "/");
38
+ if (!links.has(relativePrompt)) {
39
+ issues.push(`${document} 未链接 ${relativePrompt}`);
40
+ }
41
+ }
42
+ }
43
+
44
+ const review = readJson(
45
+ path.join(changeDir, ".sdd", "reviews", "document-review.json"),
46
+ "文档多轮评审凭证",
47
+ issues,
48
+ );
49
+ validateReview(review, handoffHash, issues);
50
+ validateMermaid(changeDir, issues);
51
+
52
+ const result = {
53
+ schemaVersion: "superflow.document-audit.v1",
54
+ ready: issues.length === 0,
55
+ handoffHash,
56
+ promptCount: prompts.length,
57
+ reviewRounds: Array.isArray(review?.rounds) ? review.rounds.length : 0,
58
+ issues,
59
+ };
60
+
61
+ if (issues.length > 0) {
62
+ fail(issues, result);
63
+ }
64
+
65
+ print(result);
66
+
67
+ function validateReview(review, currentHash, targetIssues) {
68
+ if (!review) return;
69
+ if (review.schemaVersion !== "superflow.document-review.v1") {
70
+ targetIssues.push("文档评审凭证 schemaVersion 必须为 superflow.document-review.v1");
71
+ }
72
+ if (review.handoffHash !== currentHash) {
73
+ targetIssues.push("文档评审凭证未绑定当前 handoff hash");
74
+ }
75
+ if (review.verdict !== "PASS") {
76
+ targetIssues.push("文档评审最终结论必须为 PASS");
77
+ }
78
+ if ((review.openOwnerDecisions?.length ?? 0) > 0) {
79
+ targetIssues.push("仍有 owner 决策未关闭,应集中询问用户后重新评审");
80
+ }
81
+ if (!Array.isArray(review.rounds) || review.rounds.length < 3) {
82
+ targetIssues.push("文档交付前至少三轮独立视角评审");
83
+ return;
84
+ }
85
+ const requiredLenses = new Set([
86
+ "source-contract",
87
+ "architecture-minimality",
88
+ "e2e-environment",
89
+ ]);
90
+ for (const round of review.rounds) {
91
+ requiredLenses.delete(round.lens);
92
+ if (round.inputHash !== currentHash) {
93
+ targetIssues.push(`第 ${round.round ?? "?"} 轮评审不是基于当前 handoff hash`);
94
+ }
95
+ const openFindings = (round.findings ?? []).filter(
96
+ (finding) => finding.status !== "closed",
97
+ );
98
+ if (openFindings.length > 0) {
99
+ targetIssues.push(`第 ${round.round ?? "?"} 轮仍有未关闭评审发现`);
100
+ }
101
+ }
102
+ if (requiredLenses.size > 0) {
103
+ targetIssues.push(`缺少评审视角: ${[...requiredLenses].join(", ")}`);
104
+ }
105
+ }
106
+
107
+ function validateMermaid(root, targetIssues) {
108
+ const configPath = path.join(root, ".openspec.yaml");
109
+ const config = fs.existsSync(configPath)
110
+ ? fs.readFileSync(configPath, "utf-8")
111
+ : "";
112
+ const required =
113
+ /^\s*mermaid:\s*required\s*$/m.test(config) ||
114
+ /^\s*complex_logic:\s*true\s*$/m.test(config) ||
115
+ /^\s*cross_repo:\s*true\s*$/m.test(config);
116
+ if (!required) return;
117
+
118
+ const markdown = ["design.md", "tests.md"]
119
+ .map((file) => path.join(root, file))
120
+ .filter((file) => fs.existsSync(file))
121
+ .map((file) => fs.readFileSync(file, "utf-8"))
122
+ .join("\n");
123
+ const blocks = [...markdown.matchAll(/```mermaid\s*\n([\s\S]*?)```/g)].map(
124
+ (match) => match[1].trim(),
125
+ );
126
+ for (const block of blocks) {
127
+ validateMermaidBlock(block, targetIssues);
128
+ }
129
+ if (!blocks.some((block) => /^sequenceDiagram\b/m.test(block))) {
130
+ targetIssues.push("复杂逻辑必须包含 Mermaid sequenceDiagram 端到端时序图");
131
+ }
132
+ if (
133
+ !blocks.some((block) =>
134
+ /^(flowchart\b|graph\b|stateDiagram(?:-v2)?\b)/m.test(block),
135
+ )
136
+ ) {
137
+ targetIssues.push("复杂逻辑必须包含 Mermaid flowchart 或 stateDiagram");
138
+ }
139
+ }
140
+
141
+ function validateMermaidBlock(block, targetIssues) {
142
+ const lines = block
143
+ .split("\n")
144
+ .map((line) => line.trim())
145
+ .filter((line) => line && !line.startsWith("%%"));
146
+ const directive = lines[0] ?? "";
147
+ if (/^sequenceDiagram\b/.test(directive)) {
148
+ const arrows = lines.filter((line) => /-{1,2}>>|--?>/.test(line));
149
+ if (arrows.length === 0) {
150
+ targetIssues.push("Mermaid sequenceDiagram 缺少有效消息箭头");
151
+ }
152
+ const openings = lines.filter((line) => /^(alt|opt|loop|par|critical)\b/.test(line)).length;
153
+ const endings = lines.filter((line) => line === "end").length;
154
+ if (openings !== endings) {
155
+ targetIssues.push("Mermaid sequenceDiagram 分支块未正确闭合");
156
+ }
157
+ return;
158
+ }
159
+ if (/^(flowchart|graph)\s+(TD|TB|BT|LR|RL)\b/.test(directive)) {
160
+ if (!lines.slice(1).some((line) => /-->|---|==>|-.->/.test(line))) {
161
+ targetIssues.push("Mermaid flowchart 缺少有效连线");
162
+ }
163
+ return;
164
+ }
165
+ if (/^stateDiagram(?:-v2)?\b/.test(directive)) {
166
+ if (!lines.slice(1).some((line) => /-->/.test(line))) {
167
+ targetIssues.push("Mermaid stateDiagram 缺少状态迁移");
168
+ }
169
+ return;
170
+ }
171
+ targetIssues.push(`不支持或不完整的 Mermaid 图声明: ${directive || "空图"}`);
172
+ }
173
+
174
+ function markdownFiles(directory) {
175
+ if (!fs.existsSync(directory)) return [];
176
+ return fs
177
+ .readdirSync(directory, { withFileTypes: true })
178
+ .flatMap((entry) => {
179
+ const target = path.join(directory, entry.name);
180
+ if (entry.isDirectory()) return markdownFiles(target);
181
+ return entry.isFile() && entry.name.endsWith(".md") ? [target] : [];
182
+ })
183
+ .sort();
184
+ }
185
+
186
+ function markdownTargets(content) {
187
+ return new Set(
188
+ [...content.matchAll(/\[[^\]]*\]\(([^)]+)\)/g)].map((match) =>
189
+ match[1].split("#", 1)[0].replace(/^\.\//, ""),
190
+ ),
191
+ );
192
+ }
193
+
194
+ function readHandoffHash(root, targetIssues) {
195
+ const hashPath = path.join(root, ".sdd", "handoff", "sdd-context.sha256");
196
+ if (!fs.existsSync(hashPath)) {
197
+ targetIssues.push("缺少当前 handoff hash");
198
+ return "";
199
+ }
200
+ const match = fs.readFileSync(hashPath, "utf-8").match(/[a-f0-9]{64}/i);
201
+ if (!match) {
202
+ targetIssues.push("handoff hash 格式不正确");
203
+ return "";
204
+ }
205
+ return match[0].toLowerCase();
206
+ }
207
+
208
+ function readJson(file, label, targetIssues) {
209
+ if (!fs.existsSync(file)) {
210
+ targetIssues.push(`缺少${label}: ${path.relative(changeDir, file)}`);
211
+ return null;
212
+ }
213
+ try {
214
+ return JSON.parse(fs.readFileSync(file, "utf-8"));
215
+ } catch {
216
+ targetIssues.push(`${label}不是合法 JSON`);
217
+ return null;
218
+ }
219
+ }
220
+
221
+ function print(result) {
222
+ if (jsonOutput) {
223
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
224
+ return;
225
+ }
226
+ process.stdout.write(
227
+ `文档交付审计通过:${result.reviewRounds} 轮评审,${result.promptCount} 份 Prompt\n`,
228
+ );
229
+ }
230
+
231
+ function fail(targetIssues, result = { ready: false, issues: targetIssues }) {
232
+ if (jsonOutput) {
233
+ process.stderr.write(`${JSON.stringify(result, null, 2)}\n`);
234
+ } else {
235
+ process.stderr.write(
236
+ `文档交付审计失败:\n${targetIssues.map((item) => `- ${item}`).join("\n")}\n`,
237
+ );
238
+ }
239
+ process.exit(1);
240
+ }