@chenmk/superflow 0.3.0 → 0.4.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 (85) hide show
  1. package/README.md +20 -1
  2. package/README.zh-CN.md +16 -1
  3. package/assets/manifest.json +5 -4
  4. package/assets/prompts/superflow-design.md +3 -0
  5. package/assets/prompts/superflow-docs.md +4 -1
  6. package/assets/scripts/superflow-dependency-update-hook.sh +1 -1
  7. package/assets/scripts/superflow-managed-work-check.mjs +194 -0
  8. package/assets/scripts/superflow-managed-work-guard.sh +103 -0
  9. package/assets/skills/openspec-propose/SKILL.md +11 -0
  10. package/assets/skills/superflow-design/SKILL.md +18 -9
  11. package/assets/skills/superflow-docs/SKILL.md +16 -0
  12. package/assets/skills/superflow-pipeline/SKILL.md +46 -0
  13. package/assets/skills/superflow-pipeline/references/document-templates.md +8 -0
  14. package/assets/skills/superflow-pipeline/references/managed-work.md +58 -0
  15. package/assets/skills/superflow-pipeline/references/quality-gate.md +1 -0
  16. package/assets/skills/superflow-pipeline/references/superpower-technical-design-template.md +10 -0
  17. package/assets/skills/superflow-pipeline/scripts/superflow-archive.sh +1 -1
  18. package/assets/skills/superflow-pipeline/scripts/superflow-guard.sh +79 -9
  19. package/assets/skills-en/openspec-propose/SKILL.md +14 -0
  20. package/assets/skills-en/superflow-design/SKILL.md +18 -8
  21. package/assets/skills-en/superflow-docs/SKILL.md +16 -0
  22. package/assets/skills-en/superflow-pipeline/SKILL.md +48 -0
  23. package/assets/skills-en/superflow-pipeline/references/document-templates.md +5 -0
  24. package/assets/skills-en/superflow-pipeline/references/managed-work.md +34 -0
  25. package/assets/skills-en/superflow-pipeline/references/quality-gate.md +8 -0
  26. package/assets/skills-en/superflow-pipeline/references/superpower-technical-design-template.md +11 -0
  27. package/assets/skills-en/superflow-pipeline/scripts/superflow-archive.sh +1 -1
  28. package/assets/skills-en/superflow-pipeline/scripts/superflow-guard.sh +78 -9
  29. package/dist/app/cli.js +120 -102
  30. package/dist/app/cli.js.map +1 -1
  31. package/dist/app/commands/init.js +6 -2
  32. package/dist/app/commands/init.js.map +1 -1
  33. package/dist/app/commands/managed-service.js +5 -0
  34. package/dist/app/commands/managed-service.js.map +1 -0
  35. package/dist/app/commands/pipeline.js +123 -3
  36. package/dist/app/commands/pipeline.js.map +1 -1
  37. package/dist/app/commands/status.js +199 -77
  38. package/dist/app/commands/status.js.map +1 -1
  39. package/dist/app/commands/uninstall.js +5 -2
  40. package/dist/app/commands/uninstall.js.map +1 -1
  41. package/dist/app/commands/update.js +31 -6
  42. package/dist/app/commands/update.js.map +1 -1
  43. package/dist/domains/config/cli-help.js +103 -73
  44. package/dist/domains/config/cli-help.js.map +1 -1
  45. package/dist/domains/deps.js +2 -1
  46. package/dist/domains/deps.js.map +1 -1
  47. package/dist/domains/hook.js +71 -38
  48. package/dist/domains/hook.js.map +1 -1
  49. package/dist/domains/managed-work/contract.js +218 -0
  50. package/dist/domains/managed-work/contract.js.map +1 -0
  51. package/dist/domains/managed-work/i18n.js +12 -0
  52. package/dist/domains/managed-work/i18n.js.map +1 -0
  53. package/dist/domains/managed-work/input.js +111 -0
  54. package/dist/domains/managed-work/input.js.map +1 -0
  55. package/dist/domains/managed-work/journal.js +122 -0
  56. package/dist/domains/managed-work/journal.js.map +1 -0
  57. package/dist/domains/managed-work/lock.js +40 -0
  58. package/dist/domains/managed-work/lock.js.map +1 -0
  59. package/dist/domains/managed-work/notifications.js +53 -0
  60. package/dist/domains/managed-work/notifications.js.map +1 -0
  61. package/dist/domains/managed-work/paths.js +18 -0
  62. package/dist/domains/managed-work/paths.js.map +1 -0
  63. package/dist/domains/managed-work/prompts.js +218 -0
  64. package/dist/domains/managed-work/prompts.js.map +1 -0
  65. package/dist/domains/managed-work/runner.js +626 -0
  66. package/dist/domains/managed-work/runner.js.map +1 -0
  67. package/dist/domains/managed-work/schemas.js +85 -0
  68. package/dist/domains/managed-work/schemas.js.map +1 -0
  69. package/dist/domains/managed-work/service.js +121 -0
  70. package/dist/domains/managed-work/service.js.map +1 -0
  71. package/dist/domains/managed-work/state.js +90 -0
  72. package/dist/domains/managed-work/state.js.map +1 -0
  73. package/dist/domains/managed-work/storage.js +181 -0
  74. package/dist/domains/managed-work/storage.js.map +1 -0
  75. package/dist/domains/managed-work/types.js +16 -0
  76. package/dist/domains/managed-work/types.js.map +1 -0
  77. package/dist/domains/managed-work/wait.js +40 -0
  78. package/dist/domains/managed-work/wait.js.map +1 -0
  79. package/dist/platform/agent-process.js +308 -0
  80. package/dist/platform/agent-process.js.map +1 -0
  81. package/dist/platform/process-liveness.js +10 -0
  82. package/dist/platform/process-liveness.js.map +1 -0
  83. package/dist/platform/version-check.js +30 -9
  84. package/dist/platform/version-check.js.map +1 -1
  85. package/package.json +1 -1
package/README.md CHANGED
@@ -48,6 +48,11 @@ state, and dependency guards for Claude Code, Codex, and OpenCode.
48
48
 
49
49
  ## Highlights
50
50
 
51
+ - **Dual-Agent managed delivery.** The current Agent supervises while the peer
52
+ Agent develops, starts, and verifies through a non-interactive CLI. Repair
53
+ rounds resume exact sessions and are capped at 5 reviews, 7 executor calls,
54
+ and 12 total calls. Durable journals allow recovery after terminal or network
55
+ interruption, and passing work stops for explicit Git approval.
51
56
  - **9 catalogued failure modes, blocked at the gate.** Nine real ways AI breaks
52
57
  in production — swallowing the whole PRD then forgetting details, editing
53
58
  only the setter while missing consumers, SQL drift across dev/test/DB
@@ -141,12 +146,25 @@ superflow --language en --help
141
146
  SUPERFLOW_LANG=en superflow init
142
147
  ```
143
148
 
149
+ Manage an implementation prompt, OpenSpec change, or direct development task:
150
+
151
+ ```bash
152
+ superflow pipeline "<prompt path, change directory, or task>" --managed \
153
+ --project "<project root>"
154
+ ```
155
+
156
+ The selected language is frozen into the task contract and reused by Agent
157
+ prompts, reviews, journals, reports, notifications, and resumed rounds.
158
+
144
159
  ## What Init Installs
145
160
 
146
161
  `superflow init` installs and configures:
147
162
 
148
163
  - OpenSpec CLI, then runs `openspec init <project> --tools ...`
149
- - Superpowers for the selected agent tools
164
+ - Superpowers for the selected agent tools. Codex uses the official
165
+ `superpowers@openai-api-curated` plugin, including
166
+ `verification-before-completion`, `requesting-code-review`, and
167
+ `finishing-a-development-branch`.
150
168
  - SuperBridge Flow/OpenSpec skills
151
169
  - hooks, scripts, and anti-drift rules
152
170
  - Codex prompt aliases
@@ -170,6 +188,7 @@ best-effort and does not block initialization.
170
188
  | `superflow --language en --help` | Show English CLI help |
171
189
  | `superflow scan --language en` | Regenerate project context templates in English |
172
190
  | `superflow pipeline` | Check pipeline skill deployment |
191
+ | `superflow pipeline "<task>" --managed --project <path>` | Run Dual-Agent managed development to a terminal delivery state |
173
192
  | `superflow docs` | Check docs-phase skill deployment |
174
193
  | `superflow design` | Check design-phase skill deployment |
175
194
  | `superflow implement` | Check implement-phase skill deployment |
package/README.zh-CN.md CHANGED
@@ -43,6 +43,9 @@ CLI 会把 SuperBridge Flow 技能、配套 hook/command 脚本整合为单一 n
43
43
 
44
44
  ## 亮点
45
45
 
46
+ - **双 Agent 托管到真实交付。** 当前 Agent 负责监督,另一个 Agent 通过无交互 CLI
47
+ 持续开发、启动和验证;评审整改复用原会话,最多 5 轮评审、7 次执行、12 次总调用。
48
+ 状态和证据全部落盘,终端或网络中断后可恢复,最终停在等待 Git 批准。
46
49
  - **9 类翻车场景,沉淀成门禁。** 我们见过的 AI 翻车——需求一次吞、字段漏查消费者、SQL 漂移、mock-only 报告、跨服务只看到"能调"……9 种典型形态都被固化成 guard,AI 想跳过都不行。
47
50
  - **跨服务代码必须先答架构 6 问。** 涉及跨仓、跨服务、SDK、MQ、设备、回调、网关的改动,技术详设里必须先回答:owner 是谁、调用方向、新入口是否允许、禁止路径、证据锚点——答不全不让进入实现。
48
51
  - **改字段之前先填"字段与状态反向影响"矩阵。** 任何 schema、状态、枚举的改动,必须枚举写入点、读取点、过滤点、派生 / 同步点、跨模块消费者、测试覆盖,还要列反向恢复场景(下线后重上线、旧值不可用但上游没传字段、历史脏数据被新过滤条件消费)。
@@ -115,6 +118,15 @@ export SUPERFLOW_LANG=en
115
118
  superflow init
116
119
  ```
117
120
 
121
+ 托管一个 implementation prompt、OpenSpec change 或简单开发任务:
122
+
123
+ ```bash
124
+ superflow pipeline "<prompt 路径、change 目录或任务>" --managed \
125
+ --project "<项目根目录>"
126
+ ```
127
+
128
+ 语言会冻结进任务合同;执行 Prompt、评审、账本、报告、通知和恢复轮次保持一致。
129
+
118
130
  ## SDD 分工
119
131
 
120
132
  - OpenSpec/SDD 负责 WHAT 和合同:需求、API、DB、SQL、字段语义、tests、真实入口验收和质量门禁。
@@ -145,6 +157,7 @@ superflow init
145
157
  | `superflow design [change]` | 校验 SuperBridge Flow design 阶段技能部署 |
146
158
  | `superflow implement [task]` | 校验 SuperBridge Flow implement 阶段技能部署 |
147
159
  | `superflow pipeline` | 校验 SuperBridge Flow pipeline 阶段技能部署 |
160
+ | `superflow pipeline "<任务>" --managed --project <目录>` | 双 Agent 托管开发并等待交付终态 |
148
161
  | `superflow check <change>` | 对照 13 项必备文件清单检查文档完整性 |
149
162
  | `superflow config <change> --review-mode <mode>` | 设置代码审查强度(off/standard/thorough) |
150
163
  | `superflow config <change> --auto-transition <bool>` | 控制阶段自动流转(true/false) |
@@ -163,7 +176,9 @@ superflow init
163
176
  - Claude Code、Codex 或 OpenCode(按 `--agent` 选择)
164
177
  - 第三方(`superflow init` 自动装):
165
178
  - openspec CLI(硬依赖,npm 全局)并在当前项目执行 `openspec init --tools ...`
166
- - superpowers(Claude Code / Codex 为硬依赖;OpenCode 侧通过已部署 skills/commands 使用流程)
179
+ - superpowers(Claude Code / Codex 为硬依赖;Codex 自动安装官方
180
+ `superpowers@openai-api-curated`,确保包含验证、代码评审和分支收尾三个强制技能;
181
+ OpenCode 侧通过已部署 skills/commands 使用流程)
167
182
  - understand-anything(尽力安装,失败只警告)
168
183
  - api-doc-changelog(辅助 skill,复制到目标 agent skills 目录)
169
184
 
@@ -17,9 +17,7 @@
17
17
  "superflow-tweak",
18
18
  "superflow-verify"
19
19
  ],
20
- "rules": [
21
- "superflow-phase-guard.md"
22
- ],
20
+ "rules": ["superflow-phase-guard.md"],
23
21
  "scripts": [
24
22
  "superflow-verify-integration.sh",
25
23
  "superflow-delivery-check.sh",
@@ -31,6 +29,8 @@
31
29
  "superflow-integration-evidence-hook.sh",
32
30
  "superflow-archive-command-hook.sh",
33
31
  "superflow-test-report-lint.py",
32
+ "superflow-managed-work-check.mjs",
33
+ "superflow-managed-work-guard.sh",
34
34
  "install-sql-pre-commit.sh",
35
35
  "sync-settings-json.py"
36
36
  ],
@@ -47,7 +47,8 @@
47
47
  "superflow-sql-sync-hook.py",
48
48
  "superflow-delivery-check.sh",
49
49
  "superflow-integration-evidence-hook.sh",
50
- "superflow-archive-command-hook.sh"
50
+ "superflow-archive-command-hook.sh",
51
+ "superflow-managed-work-guard.sh"
51
52
  ],
52
53
  "agentHooks": {
53
54
  "claude": ["claude-auto-backup-hook.sh"],
@@ -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.
@@ -143,7 +143,7 @@ if [ "$MODE" = "apply" ]; then
143
143
  fi
144
144
 
145
145
  if command -v codex >/dev/null 2>&1; then
146
- run_logged codex plugin add superpowers@openai-curated || true
146
+ run_logged codex plugin add superpowers@openai-api-curated || true
147
147
  fi
148
148
  else
149
149
  STATUS_FILE="$STATE_DIR/dependency-update-status.txt"
@@ -0,0 +1,194 @@
1
+ #!/usr/bin/env node
2
+ import crypto from 'crypto';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+
6
+ const [projectArg = '.', taskId, mode] = process.argv.slice(2);
7
+ const beforeReadyEvent = mode === '--before-ready-event';
8
+ if (!taskId) {
9
+ console.error('用法: superflow-managed-work-check.mjs <project-root> <task-id>');
10
+ process.exit(2);
11
+ }
12
+
13
+ const projectRoot = path.resolve(projectArg);
14
+ const taskDir = path.join(projectRoot, '.superflow', 'tasks', taskId);
15
+ const taskFile = path.join(taskDir, 'task.json');
16
+ if (!fs.existsSync(taskFile)) fail(`缺少任务状态: ${taskFile}`);
17
+ const task = JSON.parse(fs.readFileSync(taskFile, 'utf8'));
18
+ verifyContract(task);
19
+ const runsDir = path.join(taskDir, 'runs');
20
+ const runs = fs.existsSync(runsDir)
21
+ ? fs.readdirSync(runsDir).filter((entry) => fs.statSync(path.join(runsDir, entry)).isDirectory())
22
+ : [];
23
+ if (runs.length !== 1) fail(`首版要求一个活动 run,实际 ${runs.length}`);
24
+
25
+ const runDir = path.join(runsDir, runs[0]);
26
+ const stateFile = path.join(runDir, 'run-state.json');
27
+ const journalFile = path.join(runDir, 'progress.jsonl');
28
+ const reportFile = path.join(runDir, 'task-report.md');
29
+ for (const file of [stateFile, journalFile, reportFile]) {
30
+ if (!fs.existsSync(file)) fail(`缺少必备运行产物: ${file}`);
31
+ }
32
+ const state = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
33
+
34
+ assertMax('reviewRound', state.reviewRound, 5);
35
+ assertMax('executorInvocations', state.executorInvocations, 7);
36
+ assertMax('totalAgentInvocations', state.totalAgentInvocations, 12);
37
+ assertMax('reviewInvocations', state.reviewInvocations, 5);
38
+ if (state.contractHash !== task.contractHash) fail('任务合同哈希与运行状态不一致');
39
+ if (state.status !== task.status) fail('任务合同状态与运行状态不一致');
40
+ if (state.executorInvocations > 0 && !state.executorSession?.sessionId) {
41
+ fail('已有执行调用但缺少执行会话编号');
42
+ }
43
+ if (state.reviewInvocations > 0 && !state.supervisorSession?.sessionId) {
44
+ fail('已有正式检查但缺少监督会话编号');
45
+ }
46
+ const events = verifyJournal(journalFile);
47
+
48
+ if (state.status === 'awaiting_git_approval') {
49
+ if (!state.lastExecutorResult || !fs.existsSync(state.lastExecutorResult)) {
50
+ fail('等待 Git 批准状态缺少最终执行结果');
51
+ }
52
+ if (!state.lastReviewResult || !fs.existsSync(state.lastReviewResult)) {
53
+ fail('等待 Git 批准状态缺少最终检查结果');
54
+ }
55
+ assertInsideRun(state.lastExecutorResult, runDir, '最终执行结果');
56
+ assertInsideRun(state.lastReviewResult, runDir, '最终检查结果');
57
+ const executor = JSON.parse(fs.readFileSync(state.lastExecutorResult, 'utf8'));
58
+ verifyExecutorEvidence(task, executor);
59
+ const review = JSON.parse(fs.readFileSync(state.lastReviewResult, 'utf8'));
60
+ if (review.result !== 'pass' || review.findings?.some((item) => item.blocking)) {
61
+ fail('等待 Git 批准状态与最终检查结论不一致');
62
+ }
63
+ const readyEvents = events.filter((event) => event.eventType === 'run.delivery_ready');
64
+ const expectedReadyEvents = beforeReadyEvent ? 0 : 1;
65
+ if (readyEvents.length !== expectedReadyEvents) {
66
+ fail(`交付就绪事件数量应为 ${expectedReadyEvents},实际 ${readyEvents.length}`);
67
+ }
68
+ }
69
+
70
+ console.log(`OK 托管任务状态完整: ${taskId} (${state.status})`);
71
+
72
+ function assertMax(name, value, max) {
73
+ if (!Number.isInteger(value) || value < 0 || value > max) {
74
+ fail(`${name}=${value} 超出范围 0..${max}`);
75
+ }
76
+ }
77
+
78
+ function verifyContract(contract) {
79
+ const budgets = contract.budgets ?? {};
80
+ assertPositiveMax('maxReviewRounds', budgets.maxReviewRounds, 5, true);
81
+ assertPositiveMax('maxExecutorInvocations', budgets.maxExecutorInvocations, 7, true);
82
+ assertPositiveMax('maxTotalAgentInvocations', budgets.maxTotalAgentInvocations, 12, true);
83
+ assertPositiveMax('maxActiveRunHours', budgets.maxActiveRunHours, 24, false);
84
+ assertPositiveMax('maxSingleInvocationHours', budgets.maxSingleInvocationHours, 3, false);
85
+ if (contract.supervisorAgent === contract.executorAgent) {
86
+ fail('监督 Agent 和执行 Agent 不能相同');
87
+ }
88
+ const permissions = contract.permissions ?? {};
89
+ for (const key of ['gitCommit', 'gitPush', 'productionWrites', 'bypassSandbox']) {
90
+ if (permissions[key] !== false) fail(`不可覆盖的权限边界被放宽: ${key}`);
91
+ }
92
+ if (contract.taskPrompt) {
93
+ const expectedSnapshot = path.join(
94
+ path.resolve(contract.projectRoot),
95
+ '.superflow',
96
+ 'tasks',
97
+ contract.taskId,
98
+ 'source-prompt.md',
99
+ );
100
+ if (path.resolve(contract.taskPrompt.snapshotPath) !== expectedSnapshot) {
101
+ fail('冻结 Prompt 快照路径不属于当前托管任务');
102
+ }
103
+ if (!fs.existsSync(expectedSnapshot)) fail('冻结 Prompt 快照不存在');
104
+ const promptHash = crypto.createHash('sha256')
105
+ .update(fs.readFileSync(expectedSnapshot, 'utf8'))
106
+ .digest('hex');
107
+ if (promptHash !== contract.taskPrompt.sha256) fail('冻结 Prompt 快照哈希不一致');
108
+ }
109
+ const immutable = {
110
+ schemaVersion: contract.schemaVersion,
111
+ taskId: contract.taskId,
112
+ request: contract.request,
113
+ source: contract.source,
114
+ projectRoot: path.resolve(contract.projectRoot),
115
+ relatedProjectRoots: contract.relatedProjectRoots.map((root) => path.resolve(root)),
116
+ profile: contract.profile,
117
+ ...(contract.language ? { language: contract.language } : {}),
118
+ objective: contract.objective,
119
+ doneCriteria: contract.doneCriteria,
120
+ taskPrompt: contract.taskPrompt,
121
+ supervisorAgent: contract.supervisorAgent,
122
+ executorAgent: contract.executorAgent,
123
+ permissions: contract.permissions,
124
+ budgets: contract.budgets,
125
+ };
126
+ const actual = crypto.createHash('sha256').update(JSON.stringify(immutable)).digest('hex');
127
+ if (actual !== contract.contractHash) fail('任务合同内容与冻结哈希不一致');
128
+ }
129
+
130
+ function assertPositiveMax(name, value, max, integer) {
131
+ if (!Number.isFinite(value) || value <= 0 || value > max || (integer && !Number.isInteger(value))) {
132
+ fail(`${name}=${value} 超出硬上限或格式非法`);
133
+ }
134
+ }
135
+
136
+ function verifyExecutorEvidence(task, result) {
137
+ if (result.status !== 'ready_for_review') fail('最终执行结果不是可检查状态');
138
+ if (!Array.isArray(result.commands) || result.commands.some((item) => item.exitCode !== 0)) {
139
+ fail('最终执行结果缺少成功命令证据或仍含失败命令');
140
+ }
141
+ if (Array.isArray(result.blockers) && result.blockers.length > 0) {
142
+ fail('最终执行结果仍含阻塞项');
143
+ }
144
+ if (task.profile === 'engineering' || task.profile === 'sdd') {
145
+ const categories = new Set(result.commands.flatMap((item) => verificationCategories(item.command)));
146
+ if (categories.size < 2) fail('工程任务缺少至少两类成功验证证据');
147
+ }
148
+ }
149
+
150
+ function verificationCategories(command = '') {
151
+ const value = command.toLowerCase();
152
+ const categories = [];
153
+ if (/(^|\s)(test|vitest|jest|pytest|phpunit|go\s+test|cargo\s+test)(\s|$)/.test(value)
154
+ || /(?:npm|pnpm|yarn)\s+(?:run\s+)?test/.test(value)
155
+ || /mvn(?:\s+[^\s]+)*\s+test/.test(value)
156
+ || /gradle\w*\s+test/.test(value)) categories.push('test');
157
+ if (/(?:npm|pnpm|yarn)\s+(?:run\s+)?build/.test(value)
158
+ || /(^|\s)(tsc|make|cmake|compile)(\s|$)/.test(value)
159
+ || /mvn(?:\s+[^\s]+)*\s+(?:compile|package|verify)/.test(value)
160
+ || /gradle\w*\s+(?:build|assemble)/.test(value)
161
+ || /cargo\s+build|go\s+build/.test(value)) categories.push('build');
162
+ if (/(?:npm|pnpm|yarn)\s+(?:run\s+)?(?:start|dev|serve)/.test(value)
163
+ || /spring-boot:run|docker\s+compose\s+up|(^|\s)(curl|wget)(\s|$)/.test(value)
164
+ || /health(?:check)?|integration|e2e/.test(value)) categories.push('runtime');
165
+ return categories;
166
+ }
167
+
168
+ function assertInsideRun(file, runDir, label) {
169
+ const relative = path.relative(path.resolve(runDir), path.resolve(file));
170
+ if (relative.startsWith('..') || path.isAbsolute(relative)) {
171
+ fail(`${label}不在当前运行目录内`);
172
+ }
173
+ }
174
+
175
+ function verifyJournal(file) {
176
+ const lines = fs.readFileSync(file, 'utf8').split(/\r?\n/).filter(Boolean);
177
+ let previous = null;
178
+ const events = lines.map((line, index) => {
179
+ const event = JSON.parse(line);
180
+ const { eventHash, ...base } = event;
181
+ const expected = crypto.createHash('sha256').update(JSON.stringify(base)).digest('hex');
182
+ if (event.sequence !== index + 1) fail(`事件序号断裂: ${event.sequence}`);
183
+ if (event.previousEventHash !== previous) fail(`事件前序哈希不一致: ${event.sequence}`);
184
+ if (eventHash !== expected) fail(`事件哈希不一致: ${event.sequence}`);
185
+ previous = eventHash;
186
+ return event;
187
+ });
188
+ return events;
189
+ }
190
+
191
+ function fail(message) {
192
+ console.error(`FAIL ${message}`);
193
+ process.exit(1);
194
+ }
@@ -0,0 +1,103 @@
1
+ #!/bin/bash
2
+ # Managed-work role guard. Active only inside a Superflow managed Agent process.
3
+
4
+ set -u
5
+
6
+ ROLE="${SUPERFLOW_MANAGED_ROLE:-}"
7
+ [ -n "$ROLE" ] || exit 0
8
+
9
+ block() {
10
+ echo "[Superflow 托管任务门禁] $1" >&2
11
+ exit 2
12
+ }
13
+
14
+ case "$ROLE" in
15
+ supervisor|executor) ;;
16
+ *) block "检测到非法托管角色,按失败关闭。" ;;
17
+ esac
18
+
19
+ INPUT=""
20
+ if [ ! -t 0 ]; then
21
+ INPUT=$(cat 2>/dev/null || true)
22
+ fi
23
+ [ -n "$INPUT" ] || block "Hook 没有收到工具调用数据,按失败关闭。"
24
+
25
+ VALID_JSON=$(printf '%s' "$INPUT" | python3 -c "
26
+ import json, sys
27
+ try:
28
+ value = json.load(sys.stdin)
29
+ print('yes' if isinstance(value, dict) else 'no')
30
+ except Exception:
31
+ print('no')
32
+ " 2>/dev/null)
33
+ [ "$VALID_JSON" = "yes" ] || block "Hook 输入不是有效 JSON,按失败关闭。"
34
+
35
+ read_field() {
36
+ local field="$1"
37
+ printf '%s' "$INPUT" | python3 -c "
38
+ import json, sys
39
+ try:
40
+ data = json.load(sys.stdin)
41
+ except Exception:
42
+ print('')
43
+ raise SystemExit
44
+ tool_input = data.get('tool_input', {})
45
+ print(tool_input.get('$field') or '')
46
+ " 2>/dev/null
47
+ }
48
+
49
+ TOOL_NAME=$(printf '%s' "$INPUT" | python3 -c "
50
+ import json, sys
51
+ try:
52
+ data = json.load(sys.stdin)
53
+ except Exception:
54
+ print('')
55
+ raise SystemExit
56
+ print(data.get('tool_name') or data.get('tool') or '')
57
+ " 2>/dev/null)
58
+ FILE_PATH=$(read_field file_path)
59
+ [ -n "$FILE_PATH" ] || FILE_PATH=$(read_field path)
60
+ [ -n "$FILE_PATH" ] || FILE_PATH=$(read_field file)
61
+ COMMAND=$(read_field command)
62
+ [ -n "$COMMAND" ] || COMMAND=$(read_field cmd)
63
+
64
+ normalize() {
65
+ printf '%s' "$1" | sed 's|\\|/|g'
66
+ }
67
+
68
+ FILE_PATH=$(normalize "$FILE_PATH")
69
+ COMMAND=$(printf '%s' "$COMMAND" | tr '\n' ' ')
70
+
71
+ if [ "$ROLE" = "supervisor" ]; then
72
+ case "$TOOL_NAME" in
73
+ Edit|Write|MultiEdit|NotebookEdit|apply_patch)
74
+ block "监督角色只允许检查,禁止修改目标文件。"
75
+ ;;
76
+ esac
77
+ if [ -n "$COMMAND" ] && printf '%s' "$COMMAND" | grep -Eiq \
78
+ '(^|[[:space:]])(rm|mv|cp|mkdir|touch|chmod|chown)([[:space:]]|$)|git[[:space:]]+(add|commit|push|tag|reset|checkout|restore)|npm[[:space:]]+publish|apply_patch|sed[[:space:]]+-i|(^|[^>])>[>|[:space:]]|tee[[:space:]]'; then
79
+ block "监督角色的 Bash 仅允许只读检查,检测到可能写入的命令。"
80
+ fi
81
+ fi
82
+
83
+ if [ "$ROLE" = "executor" ]; then
84
+ case "$TOOL_NAME" in
85
+ Edit|Write|MultiEdit|NotebookEdit|apply_patch)
86
+ [ -n "$FILE_PATH" ] || block "写入工具缺少目标路径,按失败关闭。"
87
+ ;;
88
+ esac
89
+ if [ -n "$FILE_PATH" ] && printf '%s' "$FILE_PATH" | grep -Eq \
90
+ '(^|/)\.superflow/tasks/'; then
91
+ block "执行角色禁止修改托管状态、事件、Prompt 和过程报告。"
92
+ fi
93
+ if [ -n "$COMMAND" ] && printf '%s' "$COMMAND" | grep -Eq \
94
+ '\.superflow/tasks/'; then
95
+ block "执行角色的 Bash 禁止直接访问托管运行目录,请使用提示词中提供的只读证据。"
96
+ fi
97
+ if [ -n "$COMMAND" ] && printf '%s' "$COMMAND" | grep -Eiq \
98
+ 'git[[:space:]]+(add|commit|push|tag)|npm[[:space:]]+publish|dangerously-(bypass|skip)|kubectl[[:space:]]+(apply|delete)|helm[[:space:]]+(install|upgrade)|DROP[[:space:]]+(DATABASE|TABLE)|TRUNCATE[[:space:]]+TABLE'; then
99
+ block "执行角色禁止自动 Git 提交/推送、发布、部署、绕过沙箱或高破坏数据库操作。"
100
+ fi
101
+ fi
102
+
103
+ exit 0
@@ -22,6 +22,17 @@ When ready to implement, run /opsx:apply
22
22
 
23
23
  **Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.
24
24
 
25
+ ### OpenSpec canonical change 目录(阻塞级)
26
+
27
+ - change 必须只有一个实体目录:`openspec/changes/<name>/`。
28
+ - 版本归属必须编码进 `<name>`,例如版本 `v1.1.1` 的账号权限需求使用
29
+ `v1-1-1-account-permission-optimization`。
30
+ - 禁止创建 `openspec/changes/v1.1.1/<feature>/` 这类嵌套版本目录。
31
+ - 禁止为了兼容 OpenSpec CLI 再创建扁平软链接、目录副本或第二套 canonical 文档。
32
+ - 创建、查询、校验和后续 apply 必须始终使用同一个 `<name>`:
33
+ `openspec new change`、`openspec status --change`、
34
+ `openspec validate <name> --strict` 的名称必须一致。
35
+
25
36
  **Steps**
26
37
 
27
38
  1. **If no clear input provided, ask what they want to build**
@@ -46,7 +46,16 @@ Superpowers own source-level HOW without weakening OpenSpec/SDD contracts.
46
46
  4. Write:
47
47
  `docs/superpowers/specs/YYYY-MM-DD-<change-id>-technical-design.md`
48
48
  using `../superflow-pipeline/references/superpower-technical-design-template.md`.
49
- 5. For cross-repository, service-to-service, SDK, MQ, scheduler, device,
49
+ 5. Complete `复杂度减法评审` before expanding source-level HOW. For every new
50
+ table, field, API, Service/component, abstraction, cache, async/MQ/event
51
+ flow, scheduled job, or compatibility layer, prove existing reuse options,
52
+ necessity, and why the simplest direct implementation is insufficient.
53
+ Prefer one owner, one write path, one transaction, and set-based operations
54
+ when they satisfy the contract. Remove speculative extension points,
55
+ duplicate DTO/API layers, derivable persistence, premature caches, and
56
+ async compensation without measured need. Record the retained and removed
57
+ counts; unresolved simpler alternatives keep the design blocked.
58
+ 6. For cross-repository, service-to-service, SDK, MQ, scheduler, device,
50
59
  callback, third-party, mini-program, gateway, or adapter changes, include
51
60
  `Architecture Boundary And Call Direction`. Prove owner module, call
52
61
  direction, existing entry/exit points, proposed entry/exit points, evidence
@@ -54,7 +63,7 @@ Superpowers own source-level HOW without weakening OpenSpec/SDD contracts.
54
63
  adapter/protocol translator/device gateway into a business-entry
55
64
  orchestrator, stop and return to `$superflow-docs` unless the OpenSpec/SDD
56
65
  contract explicitly grants that ownership with approval evidence.
57
- 6. For third-party platforms/tools, SDKs, MQ/Kafka, callbacks, payment
66
+ 7. For third-party platforms/tools, SDKs, MQ/Kafka, callbacks, payment
58
67
  gateways, cloud services, or other external integrations, include
59
68
  `External Integration Configuration And Deployment Contract`. Inventory
60
69
  every endpoint, app/tenant/project ID, Topic, Tag, Consumer Group,
@@ -66,7 +75,7 @@ Superpowers own source-level HOW without weakening OpenSpec/SDD contracts.
66
75
  auto-creation or pre-existing resources must not be treated as proof that
67
76
  production will provision them. Missing production provisioning evidence
68
77
  blocks design completion.
69
- 7. For concurrent requests, batch issue/activation/renewal, duplicate callbacks,
78
+ 8. For concurrent requests, batch issue/activation/renewal, duplicate callbacks,
70
79
  duplicate consumption, or repeated external delivery, include
71
80
  `Concurrency And Idempotency Ownership`. Use a stable business idempotency
72
81
  key and an application-layer atomic claim in a short transaction; persist
@@ -76,17 +85,17 @@ Superpowers own source-level HOW without weakening OpenSpec/SDD contracts.
76
85
  optional fallback with proven natural uniqueness, historical cleanup,
77
86
  NULL/soft-delete semantics, and a conflict contract. Check-then-insert,
78
87
  process-local locks, and random IDs alone are blocked.
79
- 8. For field/status/enum/sync changes, include `Field And Status Reverse
88
+ 9. For field/status/enum/sync changes, include `Field And Status Reverse
80
89
  Impact` and prove writers, readers, filters, derived sync paths, consumers,
81
90
  and tests. Direct setter-only design is blocked.
82
- 9. For third-party, SDK, BEM/parking, payment/refund, financial display,
91
+ 10. For third-party, SDK, BEM/parking, payment/refund, financial display,
83
92
  source/origin, status sync, or external dictionary fields, include
84
93
  `External Enum Binding`. Prove local source fields/enums, external fields,
85
94
  external enum values, display/business/financial meaning, source evidence,
86
95
  owner confirmation, unresolved handling, and test evidence. A request
87
96
  succeeding or a field being non-null is not enough; unconfirmed values are
88
97
  blockers and must be returned to `$superflow-docs` or the user.
89
- 10. For amount, fee, discount, deduction, refund, sharing, payment, invoice,
98
+ 11. For amount, fee, discount, deduction, refund, sharing, payment, invoice,
90
99
  balance, electricity fee, service fee, package settlement, proration,
91
100
  allocation, reconciliation, or financial display changes,
92
101
  include `Money Precision Boundary`. Prove calculation-state fields,
@@ -105,12 +114,12 @@ Impact` and prove writers, readers, filters, derived sync paths, consumers,
105
114
  level and policy source, deterministic residual strategy with stable
106
115
  tie-breaker, and positive/zero/negative evidence. For FX changes, freeze the
107
116
  directional rate metadata and one canonical conversion path.
108
- 11. Record state:
117
+ 12. Record state:
109
118
  ```bash
110
119
  ../superflow-pipeline/scripts/superflow-state.sh set <change-dir> technical_design docs/superpowers/specs/YYYY-MM-DD-<change-id>-technical-design.md
111
120
  ../superflow-pipeline/scripts/superflow-state.sh set <change-dir> design_doc design.md
112
121
  ```
113
- 12. Update `design.md` with `Superpowers Technical Design Handoff`, update
122
+ 13. Update `design.md` with `Superpowers Technical Design Handoff`, update
114
123
  `sdd-quality-gate.md` with the technical design path and hash, then run
115
124
  `../superflow-pipeline/scripts/superflow-handoff.sh <change-dir> --refresh`.
116
125
  If the guard reports a stale or missing hash, record the printed hash in
@@ -118,7 +127,7 @@ Impact` and prove writers, readers, filters, derived sync paths, consumers,
118
127
  `--refresh` again. Do not set `design_doc` to the Superpowers document;
119
128
  `design_doc` is the OpenSpec/SDD contract design, while `technical_design`
120
129
  is the Superpowers HOW document.
121
- 13. Run:
130
+ 14. Run:
122
131
 
123
132
  ```bash
124
133
  ../superflow-pipeline/scripts/superflow-yaml-validate.sh <change-dir>
@@ -112,6 +112,17 @@ Binding` with:
112
112
  chain, no-fallback/no-guessing boundary, and pre-coding agent self-check. If
113
113
  any gate is missing from `design.md`, `tests.md`, or quality gate, stop and
114
114
  complete the docs first.
115
+ - For full workflow changes, `design.md` must include `复杂度减法评审` before
116
+ docs freeze. Inventory every proposed table, field, API, Service/component,
117
+ cache, async/MQ/event flow, scheduled job, compatibility layer, and new
118
+ abstraction. For each item, record existing reuse evidence, necessity, the
119
+ simplest implementation, removed/rejected complexity, and blockers.
120
+ Prefer extending current modules and synchronous transactions. Do not retain
121
+ a new layer merely for future flexibility; without evidence, remove it.
122
+ - `sdd-quality-gate.md` must record the complexity review verdict as
123
+ `PASS` or `BLOCKED`; only `PASS` may leave docs/design. Missing reuse evidence, unexplained parallel APIs/models,
124
+ redundant persisted fields, speculative cache/async/compensation, or an
125
+ unresolved simpler option blocks docs completion.
115
126
  - `design.md` stays the OpenSpec/SDD design contract: requirement mapping,
116
127
  API/DB/field semantics, source facts, real-entry call chain, no-fallback
117
128
  boundary, risks, and acceptance hooks. It must not try to own all source-level
@@ -260,6 +271,11 @@ Use references only as needed:
260
271
  the relationship judgment as `确定/部分确定/不确定` when a bug fix hinges on
261
272
  existing data or call-chain behavior.
262
273
  - `design.md` must reference the frozen `api.md` fields and errors.
274
+ - `design.md` must include `复杂度减法评审` with:
275
+ `设计项 | 现有能力/复用证据 | 是否必要 | 最简实现 | 删除/拒绝项 | 证据/阻塞`.
276
+ It must also count new tables, fields, APIs, services/components, caches,
277
+ async flows, jobs, and compatibility layers. A zero count is valid and
278
+ preferable when existing capabilities close the contract.
263
279
  - `design.md` must include a "字段语义合同" table for every risky field:
264
280
  `字段 | 来源表/DTO/事件 | 真实语义 | 目标字段 | 目标语义 | 是否可等价 |
265
281
  证据锚点 | 禁止用法 | 不确定项/owner`.
@@ -7,6 +7,39 @@ description: SDD 总入口和路由技能。Use when the user says sdd, SDD 流
7
7
 
8
8
  This is the lightweight SDD router. Do not load the whole SDD process when a smaller phase skill is enough.
9
9
 
10
+ ## 托管任务与双 Agent 闭环
11
+
12
+ 当用户说“用 Superflow 托管完成”并给出 implementation prompt、change 目录或一个简单
13
+ 任务时,直接使用内建托管模式。不要要求用户说出 `superflow-pipeline`、角色参数或底层
14
+ CLI 命令:
15
+
16
+ ```bash
17
+ superflow pipeline "<implementation-prompt 路径、change 目录或简单任务>" --managed --project "<项目根目录>" \
18
+ --supervisor codex --executor claude --language zh
19
+ ```
20
+
21
+ 当前入口是 Claude 时交换两个角色。命令默认由独立后台服务执行,同时监听本地任务账本
22
+ 直到终态,再由当前 Agent 读取报告并在同一会话汇总。监听中断不影响后台任务。执行前
23
+ 必须阅读 `references/managed-work.md`,不得直接手工递归启动 peer CLI。
24
+
25
+ 硬规则:
26
+
27
+ - 每个任务固定监督会话和执行会话,后续轮次按明确 session ID 恢复。
28
+ - 任务合同、事件账本、检查结果和证据文件是事实源,不依赖聊天上下文。
29
+ - 正式检查最多 5 轮、执行最多 7 次、Agent 总调用最多 12 次。
30
+ - 每次启动和恢复都校验冻结合同与硬上限;工程任务只有一类验证证据时不得进入检查。
31
+ - 输入是 change 目录时必须从 `.sdd/state.yaml` 解析 `implementation_prompt`;输入是
32
+ `tasks.md` 时必须阻塞。执行前冻结 Prompt 快照和 SHA-256,两个 Agent 使用同一快照。
33
+ - 监督角色只读,执行角色禁止修改 `.superflow/tasks` 和自动 Git 提交/推送/发布。
34
+ - 最终通过后状态必须停在 `awaiting_git_approval`,当前主 Agent 汇总并获得用户批准后
35
+ 才能提交 Git。
36
+ - 使用 `superflow status <project-root>` 查看状态;不得通过模型轮询询问进度。
37
+ - 运行产物完整性必须通过 `superflow-managed-work-check.mjs`。
38
+ - 只有完整性脚本先通过,状态机才能记录唯一的交付就绪事件。
39
+ - 托管命令返回终态后,当前 Agent 必须读取任务报告并向用户汇总;不能只报告任务编号。
40
+ - 语言必须冻结进任务合同;执行 Prompt、恢复轮次、进度账本、任务报告、通知和错误提示
41
+ 必须继承合同语言,不能在中途切换。
42
+
10
43
  ## Choose The Right SDD Skill
11
44
 
12
45
  - Use `$openspec-explore` when the user is still thinking through a requirement,
@@ -80,6 +113,19 @@ When the router selects embedded deep clarification, follow these rules inside
80
113
 
81
114
  ## Non-Negotiable Rules
82
115
 
116
+ ### OpenSpec change 目录唯一性(阻塞级)
117
+
118
+ - Superflow 必须遵守 OpenSpec CLI 的单层目录规范:
119
+ `openspec/changes/<change-name>/`。
120
+ - 版本号属于 change name,不属于中间目录。`v1.1.1` 必须编码为
121
+ `v1-1-1-<feature-slug>`,不得生成 `changes/v1.1.1/<feature-slug>/`。
122
+ - 同一 change 只能保留一个实体目录;禁止生成兼容软链接、目录副本或第二套
123
+ canonical 文档。
124
+ - 生成文档前必须先执行 `openspec new change <change-name>`,后续 status、
125
+ instructions、validate、Superflow state/handoff/guard 全部复用该实体目录。
126
+ - 发现嵌套版本目录或软链接 change 时,停止文档生成并迁移为唯一的扁平实体目录,
127
+ 再运行 `openspec validate <change-name> --strict`。
128
+
83
129
  ### 上下文防漂移与状态门禁(阻塞级)
84
130
 
85
131
  SDD 的核心价值是可追溯事实链、接口验证、hook 质量监控、任务 prompt
@@ -43,6 +43,14 @@
43
43
  | Requirement | 修改文件 | 修改方法 | 变更类型 |
44
44
  |---|---|---|---|
45
45
 
46
+ ## 复杂度减法评审
47
+ | 设计项 | 现有能力/复用证据 | 是否必要 | 最简实现 | 删除/拒绝项 | 证据/阻塞 |
48
+ |---|---|---|---|---|---|
49
+ | <表/API/Service/组件/同步机制> | <源码、接口、表或依赖锚点> | <保留/删除/阻塞> | <能够闭环的最小方案> | <不新增的抽象、字段、缓存、异步、兼容层> | <证据或待确认项> |
50
+
51
+ 新增项统计:表 0;字段 0;API 0;Service/组件 0;缓存 0;MQ/事件 0;定时任务 0;兼容层 0。按实际设计替换数量,不适用时保留 0。
52
+ 能够复用、推导或同步完成的能力不得另建平行实现;没有证据证明需要时默认删除。
53
+
46
54
  ## Detailed Design
47
55
  详细设计
48
56