@chenmk/superflow 0.5.9 → 0.5.11
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.
- package/INSTALL.en.md +7 -1
- package/INSTALL.md +12 -2
- package/README.md +12 -2
- package/README.zh-CN.md +12 -3
- package/assets/manifest.json +1 -0
- package/assets/scripts/superflow-coding-ready.mjs +88 -19
- package/assets/scripts/superflow-dependency-update-hook.sh +4 -17
- package/assets/scripts/superflow-document-audit.mjs +29 -5
- package/assets/scripts/superflow-hook-guard.sh +3 -14
- package/assets/scripts/superflow-review-coverage.mjs +258 -0
- package/assets/skills/superflow-docs/SKILL.md +5 -0
- package/assets/skills/superflow-pipeline/references/document-readiness.md +4 -0
- package/assets/skills/superflow-pipeline/references/document-review-coverage.md +82 -0
- package/assets/skills/superflow-requirement-review/SKILL.md +4 -0
- package/assets/skills/superflow-verify/SKILL.md +4 -0
- package/assets/skills-en/superflow-docs/SKILL.md +6 -0
- package/assets/skills-en/superflow-pipeline/references/document-readiness.md +4 -0
- package/assets/skills-en/superflow-pipeline/references/document-review-coverage.md +89 -0
- package/assets/skills-en/superflow-requirement-review/SKILL.md +5 -0
- package/assets/skills-en/superflow-verify/SKILL.md +5 -0
- package/dist/app/cli.js +1 -0
- package/dist/app/cli.js.map +1 -1
- package/dist/app/commands/doctor.js +9 -3
- package/dist/app/commands/doctor.js.map +1 -1
- package/dist/app/commands/update.js +22 -5
- package/dist/app/commands/update.js.map +1 -1
- package/dist/domains/config/cli-help.js +4 -2
- package/dist/domains/config/cli-help.js.map +1 -1
- package/dist/domains/deps.js +62 -30
- package/dist/domains/deps.js.map +1 -1
- package/dist/domains/sdd-readiness.js +9 -0
- package/dist/domains/sdd-readiness.js.map +1 -1
- package/package.json +1 -1
package/INSTALL.en.md
CHANGED
|
@@ -155,6 +155,12 @@ superflow update --with-package
|
|
|
155
155
|
|
|
156
156
|
Automatic checks are enabled by default but do not install updates:
|
|
157
157
|
|
|
158
|
+
Default checks query npm and remind you to refresh Superpowers. Manual update or
|
|
159
|
+
`apply` updates the plugins. Use `superflow update --agent codex --scope global --with-dependencies`
|
|
160
|
+
to refresh OpenSpec, Superpowers and host assets without reinstalling the CLI.
|
|
161
|
+
Codex plugin identity/version/enablement comes from native inventory (currently
|
|
162
|
+
`superpowers@openai-curated-remote`), not legacy config.toml entries or residual caches.
|
|
163
|
+
|
|
158
164
|
```bash
|
|
159
165
|
export SUPERFLOW_AUTO_UPDATE=check
|
|
160
166
|
export SUPERFLOW_AUTO_UPDATE=0
|
|
@@ -164,7 +170,7 @@ export SUPERFLOW_UPDATE_MIN_INTERVAL_SECONDS=21600
|
|
|
164
170
|
|
|
165
171
|
Team environments should keep `check`. Personal machines may choose `apply`.
|
|
166
172
|
In `apply` mode, package upgrades are followed by the newly installed CLI, which
|
|
167
|
-
redeploys Skills, Hooks, rules, scripts, and managed MCP registrations. Partial
|
|
173
|
+
updates OpenSpec/Superpowers and redeploys Skills, Hooks, rules, scripts, and managed MCP registrations. Partial
|
|
168
174
|
failure removes the throttle stamp and remains eligible for the next-session retry.
|
|
169
175
|
Restart the Agent after success to load the new MCP process.
|
|
170
176
|
|
package/INSTALL.md
CHANGED
|
@@ -517,7 +517,7 @@ Claude Code 里也可以直接用当前阶段命令继续,例如:
|
|
|
517
517
|
|
|
518
518
|
- `@chenmk/superflow`
|
|
519
519
|
- `@fission-ai/openspec`
|
|
520
|
-
-
|
|
520
|
+
- Superpowers 插件在手动更新或 `apply` 时刷新;默认检查仅提供刷新提示
|
|
521
521
|
|
|
522
522
|
同一会话只检查一次;默认只提示,不自动安装。至少间隔 6 小时才真正访问
|
|
523
523
|
npm/plugin 源,避免每次 prompt 都联网。可用:
|
|
@@ -540,12 +540,22 @@ export SUPERFLOW_UPDATE_MIN_INTERVAL_SECONDS=21600
|
|
|
540
540
|
`superflow update --with-package` 更新;个人机器如果接受自动升级风险,再设置
|
|
541
541
|
`SUPERFLOW_AUTO_UPDATE=apply`。
|
|
542
542
|
|
|
543
|
-
显式更新和 Hook `apply`
|
|
543
|
+
显式更新和 Hook `apply` 使用同一闭环:先升级 CLI 包,再由新版本 CLI 更新 OpenSpec、
|
|
544
|
+
从 Codex 原生目录发现官方 Superpowers(当前为 `openai-curated-remote`),并重新部署全部 Agent
|
|
544
545
|
资产并刷新 MCP 注册。任一步失败会记录日志、删除本轮节流戳并允许下次会话重试;成功后需
|
|
545
546
|
重启 Agent 才会加载新的 MCP 进程。
|
|
546
547
|
|
|
547
548
|
### 8.2 手动更新
|
|
548
549
|
|
|
550
|
+
仅更新 OpenSpec、Superpowers 和宿主资产(不重装 CLI):
|
|
551
|
+
|
|
552
|
+
```bash
|
|
553
|
+
superflow update --agent codex --scope global --with-dependencies
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
最新版远端插件启用状态以 `codex plugin list --json` 为准,不一定写入 config.toml;
|
|
557
|
+
doctor 检查当前启用版本的技能文件。旧缓存不能代替当前版本缺失的技能。
|
|
558
|
+
|
|
549
559
|
只刷新已安装技能、脚本、规则和 hook:
|
|
550
560
|
|
|
551
561
|
```bash
|
package/README.md
CHANGED
|
@@ -48,6 +48,11 @@ state, and dependency guards for Claude Code and Codex.
|
|
|
48
48
|
|
|
49
49
|
## Highlights
|
|
50
50
|
|
|
51
|
+
0.5.10 strengthens document delivery: requirement × real-entry coverage (including
|
|
52
|
+
exclusions), real-entry test contracts, and content-bound Coding Ready receipts.
|
|
53
|
+
Existing document receipts need [coverage migration and re-review](assets/skills-en/superflow-pipeline/references/document-review-coverage.md)
|
|
54
|
+
before new dispatch or source edits. Semantic correctness remains an Agent review responsibility.
|
|
55
|
+
|
|
51
56
|
- **Dual-Agent managed delivery.** The current host Agent reviews directly while
|
|
52
57
|
the peer Agent develops, starts, and verifies in one CLI session without a
|
|
53
58
|
tool-turn limit, then actively returns one structured result. A later session
|
|
@@ -301,7 +306,7 @@ Design and field evidence:
|
|
|
301
306
|
|
|
302
307
|
- OpenSpec CLI, then runs `openspec init <project> --tools ...`
|
|
303
308
|
- Superpowers for the selected agent tools. Codex uses the official
|
|
304
|
-
`superpowers@openai-
|
|
309
|
+
current `superpowers@openai-curated-remote` plugin, discovering versions from native inventory and checking
|
|
305
310
|
`verification-before-completion`, `requesting-code-review`, and
|
|
306
311
|
`finishing-a-development-branch`.
|
|
307
312
|
- SuperBridge Flow/OpenSpec skills
|
|
@@ -369,6 +374,10 @@ default.
|
|
|
369
374
|
Default behavior is **check only**. It reports available updates but does not
|
|
370
375
|
install them. Run this to update explicitly:
|
|
371
376
|
|
|
377
|
+
The default check queries npm versions; Superpowers receives a refresh reminder.
|
|
378
|
+
Manual update or `apply` refreshes plugins through native commands. To update only
|
|
379
|
+
OpenSpec, Superpowers and host assets, use `superflow update --agent codex --scope global --with-dependencies`.
|
|
380
|
+
|
|
372
381
|
```bash
|
|
373
382
|
superflow update --with-package
|
|
374
383
|
```
|
|
@@ -389,7 +398,8 @@ export SUPERFLOW_AUTO_UPDATE=apply
|
|
|
389
398
|
export SUPERFLOW_UPDATE_MIN_INTERVAL_SECONDS=21600
|
|
390
399
|
```
|
|
391
400
|
|
|
392
|
-
`apply`
|
|
401
|
+
`apply` resolves the newly installed CLI from the npm root, avoiding stale PATH shims,
|
|
402
|
+
then lets that runtime update OpenSpec/Superpowers and refresh all
|
|
393
403
|
detected Agent assets plus managed MCP registrations. A partial failure keeps its
|
|
394
404
|
log and removes the throttle stamp so the next session can retry. Restart the
|
|
395
405
|
Agent after success because an existing MCP process cannot hot-load the upgrade.
|
package/README.zh-CN.md
CHANGED
|
@@ -41,6 +41,11 @@ CLI 会把 SuperBridge Flow 技能、配套 hook/command 脚本整合为单一 n
|
|
|
41
41
|
|
|
42
42
|
## 亮点
|
|
43
43
|
|
|
44
|
+
0.5.10 加强文档交付:逐需求×真实入口核对(含排除项)、真实入口验收合同、
|
|
45
|
+
绑定内容指纹的 Coding Ready。旧文档凭证需先完成
|
|
46
|
+
[覆盖补齐与复审](assets/skills/superflow-pipeline/references/document-review-coverage.md),
|
|
47
|
+
才能新启动任务或编辑源码;业务语义正确性仍由智能体独立评审负责。
|
|
48
|
+
|
|
44
49
|
- **双 Agent 托管到真实交付。** 当前 Host Agent 直接监督,另一个 Agent 在一次不限制工具
|
|
45
50
|
轮数的 CLI 会话中持续开发、启动和验证,完成后主动返回结构化结果;只有评审整改、进程异常
|
|
46
51
|
或人工恢复才创建后续会话。工作区与落盘 finding 负责交接,默认最多 5 轮评审、7 次执行、
|
|
@@ -291,7 +296,8 @@ Agent 进程树;macOS/Linux 继续使用独立进程组。三端均不通过
|
|
|
291
296
|
- 第三方(`superflow init` 自动装):
|
|
292
297
|
- openspec CLI(硬依赖,npm 全局)并在当前项目执行 `openspec init --tools ...`
|
|
293
298
|
- superpowers(Claude Code / Codex 为硬依赖;Codex 自动安装官方
|
|
294
|
-
`superpowers@openai-
|
|
299
|
+
当前渠道 `superpowers@openai-curated-remote`;从原生插件清单发现版本并核验验证、
|
|
300
|
+
代码评审和分支收尾三个强制技能,不以旧 config.toml 条目或缓存存在代替可用性)
|
|
295
301
|
- understand-anything(尽力安装,失败只警告)
|
|
296
302
|
- api-doc-changelog(辅助 skill,复制到目标 agent skills 目录)
|
|
297
303
|
|
|
@@ -301,10 +307,12 @@ Agent 进程树;macOS/Linux 继续使用独立进程组。三端均不通过
|
|
|
301
307
|
|
|
302
308
|
- `@chenmk/superflow`
|
|
303
309
|
- `@fission-ai/openspec`
|
|
304
|
-
-
|
|
310
|
+
- Superpowers 在手动更新或 `apply` 时通过原生插件命令更新;默认 `check` 仅给出刷新提示
|
|
305
311
|
|
|
306
312
|
推荐策略是“自动检查,手动更新”:默认只提示,不自动安装;执行
|
|
307
313
|
`superflow update --with-package` 才会统一更新。
|
|
314
|
+
只更新 OpenSpec、Superpowers 和宿主资产、不重装 CLI 时,可执行
|
|
315
|
+
`superflow update --agent codex --scope global --with-dependencies`。
|
|
308
316
|
同一会话只检查一次,并且默认至少间隔 6 小时才真正访问 npm/plugin 源。
|
|
309
317
|
|
|
310
318
|
```bash
|
|
@@ -321,7 +329,8 @@ export SUPERFLOW_AUTO_UPDATE=apply
|
|
|
321
329
|
export SUPERFLOW_UPDATE_MIN_INTERVAL_SECONDS=21600
|
|
322
330
|
```
|
|
323
331
|
|
|
324
|
-
`apply`
|
|
332
|
+
`apply` 会在包升级后按 npm 根目录定位新版本 CLI(不受旧 PATH 启动器遮蔽),由新版本
|
|
333
|
+
统一更新 OpenSpec/Superpowers、所有已检测到的 Agent 资产和 MCP 注册。
|
|
325
334
|
任一步失败都会保留日志和下次会话重试资格,不会把半升级状态标记为成功。升级完成后需要
|
|
326
335
|
重启 Agent,旧会话不会热加载新的 MCP 运行时。
|
|
327
336
|
|
package/assets/manifest.json
CHANGED
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"superflow-test-report-lint.py",
|
|
33
33
|
"superflow-managed-work-check.mjs",
|
|
34
34
|
"superflow-document-audit.mjs",
|
|
35
|
+
"superflow-review-coverage.mjs",
|
|
35
36
|
"superflow-environment-preflight.mjs",
|
|
36
37
|
"superflow-coding-ready.mjs",
|
|
37
38
|
"superflow-managed-executor-preflight.mjs",
|
|
@@ -5,6 +5,7 @@ import fs from "node:fs";
|
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { fileHash, reviewPath } from "./superflow-review-coverage.mjs";
|
|
8
9
|
|
|
9
10
|
const args = process.argv.slice(2);
|
|
10
11
|
const changeArg = args.find((arg) => !arg.startsWith("--"));
|
|
@@ -18,12 +19,40 @@ const changeDir = fs.realpathSync(path.resolve(changeArg));
|
|
|
18
19
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
19
20
|
const pipelineScripts = resolvePipelineScripts(scriptDir);
|
|
20
21
|
const checks = [
|
|
21
|
-
[
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
[
|
|
22
|
+
[
|
|
23
|
+
"YAML 状态",
|
|
24
|
+
"bash",
|
|
25
|
+
[path.join(pipelineScripts, "superflow-yaml-validate.sh"), changeDir],
|
|
26
|
+
],
|
|
27
|
+
[
|
|
28
|
+
"docs 门禁",
|
|
29
|
+
"bash",
|
|
30
|
+
[path.join(pipelineScripts, "superflow-guard.sh"), changeDir, "docs"],
|
|
31
|
+
],
|
|
32
|
+
[
|
|
33
|
+
"design 门禁",
|
|
34
|
+
"bash",
|
|
35
|
+
[path.join(pipelineScripts, "superflow-guard.sh"), changeDir, "design"],
|
|
36
|
+
],
|
|
37
|
+
[
|
|
38
|
+
"implement 门禁",
|
|
39
|
+
"bash",
|
|
40
|
+
[path.join(pipelineScripts, "superflow-guard.sh"), changeDir, "implement"],
|
|
41
|
+
],
|
|
42
|
+
[
|
|
43
|
+
"文档交付审计",
|
|
44
|
+
process.execPath,
|
|
45
|
+
[path.join(scriptDir, "superflow-document-audit.mjs"), changeDir, "--json"],
|
|
46
|
+
],
|
|
47
|
+
[
|
|
48
|
+
"环境预检",
|
|
49
|
+
process.execPath,
|
|
50
|
+
[
|
|
51
|
+
path.join(scriptDir, "superflow-environment-preflight.mjs"),
|
|
52
|
+
changeDir,
|
|
53
|
+
"--json",
|
|
54
|
+
],
|
|
55
|
+
],
|
|
27
56
|
];
|
|
28
57
|
const issues = [];
|
|
29
58
|
const evidence = [];
|
|
@@ -40,17 +69,29 @@ for (const [label, command, commandArgs] of checks) {
|
|
|
40
69
|
}
|
|
41
70
|
}
|
|
42
71
|
|
|
43
|
-
const openspec = spawnSync(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
72
|
+
const openspec = spawnSync(
|
|
73
|
+
"openspec",
|
|
74
|
+
["validate", path.basename(changeDir), "--strict"],
|
|
75
|
+
{
|
|
76
|
+
cwd: projectRoot(changeDir),
|
|
77
|
+
encoding: "utf-8",
|
|
78
|
+
},
|
|
79
|
+
);
|
|
47
80
|
evidence.push({ label: "OpenSpec strict", exitCode: openspec.status ?? 1 });
|
|
48
81
|
if (openspec.status !== 0) {
|
|
49
|
-
issues.push(
|
|
82
|
+
issues.push(
|
|
83
|
+
`OpenSpec strict 失败:${tail(openspec.stderr || openspec.stdout)}`,
|
|
84
|
+
);
|
|
50
85
|
}
|
|
51
86
|
|
|
52
87
|
const handoffHash = readHandoffHash(changeDir, issues);
|
|
53
88
|
const reviewRounds = readReviewRounds(changeDir);
|
|
89
|
+
let reviewHash = "";
|
|
90
|
+
try {
|
|
91
|
+
reviewHash = fileHash(path.join(changeDir, reviewPath));
|
|
92
|
+
} catch {
|
|
93
|
+
issues.push("无法冻结文档评审凭证指纹");
|
|
94
|
+
}
|
|
54
95
|
const receipt = {
|
|
55
96
|
schemaVersion: "superflow.coding-ready.v1",
|
|
56
97
|
codingReady: issues.length === 0,
|
|
@@ -58,21 +99,28 @@ const receipt = {
|
|
|
58
99
|
environmentReadiness: issues.length === 0 ? "READY" : "BLOCKED",
|
|
59
100
|
reviewRounds,
|
|
60
101
|
handoffHash,
|
|
102
|
+
reviewHash,
|
|
61
103
|
checkedAt: new Date().toISOString(),
|
|
62
104
|
evidence,
|
|
63
105
|
ownerDecisions: 0,
|
|
64
106
|
issues,
|
|
65
107
|
};
|
|
66
108
|
|
|
67
|
-
if (issues.length > 0) fail(issues, receipt);
|
|
68
|
-
|
|
69
109
|
const receiptDir = path.join(changeDir, ".sdd", "readiness");
|
|
70
110
|
fs.mkdirSync(receiptDir, { recursive: true });
|
|
71
111
|
const target = path.join(receiptDir, "coding-ready.json");
|
|
72
|
-
const temporary = path.join(
|
|
73
|
-
|
|
112
|
+
const temporary = path.join(
|
|
113
|
+
receiptDir,
|
|
114
|
+
`.coding-ready-${process.pid}-${Date.now()}.tmp`,
|
|
115
|
+
);
|
|
116
|
+
fs.writeFileSync(temporary, `${JSON.stringify(receipt, null, 2)}\n`, {
|
|
117
|
+
mode: 0o600,
|
|
118
|
+
});
|
|
74
119
|
fs.renameSync(temporary, target);
|
|
75
120
|
|
|
121
|
+
// Persist BLOCKED too: a failed recheck must revoke an earlier READY receipt.
|
|
122
|
+
if (issues.length > 0) fail(issues, receipt);
|
|
123
|
+
|
|
76
124
|
if (jsonOutput) {
|
|
77
125
|
process.stdout.write(`${JSON.stringify(receipt, null, 2)}\n`);
|
|
78
126
|
} else {
|
|
@@ -81,9 +129,27 @@ if (jsonOutput) {
|
|
|
81
129
|
|
|
82
130
|
function resolvePipelineScripts(currentScriptDir) {
|
|
83
131
|
const candidates = [
|
|
84
|
-
path.resolve(
|
|
85
|
-
|
|
86
|
-
|
|
132
|
+
path.resolve(
|
|
133
|
+
currentScriptDir,
|
|
134
|
+
"..",
|
|
135
|
+
"skills",
|
|
136
|
+
"superflow-pipeline",
|
|
137
|
+
"scripts",
|
|
138
|
+
),
|
|
139
|
+
path.join(
|
|
140
|
+
os.homedir(),
|
|
141
|
+
".codex",
|
|
142
|
+
"skills",
|
|
143
|
+
"superflow-pipeline",
|
|
144
|
+
"scripts",
|
|
145
|
+
),
|
|
146
|
+
path.join(
|
|
147
|
+
os.homedir(),
|
|
148
|
+
".claude",
|
|
149
|
+
"skills",
|
|
150
|
+
"superflow-pipeline",
|
|
151
|
+
"scripts",
|
|
152
|
+
),
|
|
87
153
|
];
|
|
88
154
|
const found = candidates.find((candidate) =>
|
|
89
155
|
fs.existsSync(path.join(candidate, "superflow-guard.sh")),
|
|
@@ -123,7 +189,10 @@ function tail(value) {
|
|
|
123
189
|
return String(value).trim().split("\n").slice(-4).join(" | ").slice(0, 800);
|
|
124
190
|
}
|
|
125
191
|
|
|
126
|
-
function fail(
|
|
192
|
+
function fail(
|
|
193
|
+
targetIssues,
|
|
194
|
+
receipt = { codingReady: false, issues: targetIssues },
|
|
195
|
+
) {
|
|
127
196
|
if (jsonOutput) {
|
|
128
197
|
process.stderr.write(`${JSON.stringify(receipt, null, 2)}\n`);
|
|
129
198
|
} else {
|
|
@@ -104,7 +104,7 @@ run_logged() {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
latest_npm_version() {
|
|
107
|
-
npm view "$1" version 2>/dev/null | tail -n 1
|
|
107
|
+
npm view "$1" version --registry https://registry.npmjs.org 2>/dev/null | tail -n 1
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
installed_npm_version() {
|
|
@@ -143,7 +143,7 @@ update_npm_if_needed() {
|
|
|
143
143
|
fi
|
|
144
144
|
current="$(installed_npm_version "$package_name")"
|
|
145
145
|
if [ "$current" != "$latest" ]; then
|
|
146
|
-
run_logged npm install -g "$package_name@latest"
|
|
146
|
+
run_logged npm install -g "$package_name@latest" --registry https://registry.npmjs.org
|
|
147
147
|
fi
|
|
148
148
|
}
|
|
149
149
|
|
|
@@ -159,15 +159,12 @@ detected_agents() {
|
|
|
159
159
|
refresh_superflow_installation() {
|
|
160
160
|
local agents="$1"
|
|
161
161
|
[ -n "$agents" ] || return 1
|
|
162
|
-
|
|
163
|
-
run_logged superflow update --agent "$agents" --scope global
|
|
164
|
-
return $?
|
|
165
|
-
fi
|
|
162
|
+
# Always run the package just installed, not an older PATH shadow.
|
|
166
163
|
local npm_root cli
|
|
167
164
|
npm_root="$(npm root -g 2>/dev/null)" || return 1
|
|
168
165
|
cli="$npm_root/@chenmk/superflow/dist/app/cli.js"
|
|
169
166
|
[ -f "$cli" ] || return 1
|
|
170
|
-
run_logged node "$cli" update --agent "$agents" --scope global
|
|
167
|
+
run_logged node "$cli" update --agent "$agents" --scope global --with-dependencies
|
|
171
168
|
}
|
|
172
169
|
|
|
173
170
|
check_npm_package() {
|
|
@@ -187,16 +184,6 @@ check_npm_package() {
|
|
|
187
184
|
if [ "$MODE" = "apply" ]; then
|
|
188
185
|
APPLY_FAILED=0
|
|
189
186
|
update_npm_if_needed "@chenmk/superflow" || APPLY_FAILED=1
|
|
190
|
-
update_npm_if_needed "@fission-ai/openspec" || APPLY_FAILED=1
|
|
191
|
-
|
|
192
|
-
if command -v claude >/dev/null 2>&1; then
|
|
193
|
-
run_logged claude plugin install superpowers@superpowers-marketplace || APPLY_FAILED=1
|
|
194
|
-
fi
|
|
195
|
-
|
|
196
|
-
if command -v codex >/dev/null 2>&1; then
|
|
197
|
-
run_logged codex plugin add superpowers@openai-api-curated || APPLY_FAILED=1
|
|
198
|
-
fi
|
|
199
|
-
|
|
200
187
|
AGENT_VALUE="$(detected_agents)"
|
|
201
188
|
refresh_superflow_installation "$AGENT_VALUE" || APPLY_FAILED=1
|
|
202
189
|
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
|
+
import {
|
|
6
|
+
currentHandoffHash,
|
|
7
|
+
validateCoverage,
|
|
8
|
+
} from "./superflow-review-coverage.mjs";
|
|
5
9
|
|
|
6
10
|
const args = process.argv.slice(2);
|
|
7
11
|
const changeArg = args.find((arg) => !arg.startsWith("--"));
|
|
@@ -34,7 +38,9 @@ for (const document of aggregateDocuments) {
|
|
|
34
38
|
}
|
|
35
39
|
const links = markdownTargets(fs.readFileSync(documentPath, "utf-8"));
|
|
36
40
|
for (const prompt of prompts) {
|
|
37
|
-
const relativePrompt = path
|
|
41
|
+
const relativePrompt = path
|
|
42
|
+
.relative(changeDir, prompt)
|
|
43
|
+
.replaceAll("\\", "/");
|
|
38
44
|
if (!links.has(relativePrompt)) {
|
|
39
45
|
issues.push(`${document} 未链接 ${relativePrompt}`);
|
|
40
46
|
}
|
|
@@ -47,6 +53,14 @@ const review = readJson(
|
|
|
47
53
|
issues,
|
|
48
54
|
);
|
|
49
55
|
validateReview(review, handoffHash, issues);
|
|
56
|
+
validateCoverage(changeDir, review, issues);
|
|
57
|
+
try {
|
|
58
|
+
if (currentHandoffHash(changeDir) !== handoffHash) {
|
|
59
|
+
issues.push("冻结文档内容已变化,请刷新 handoff 并重新评审");
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
issues.push(error.message);
|
|
63
|
+
}
|
|
50
64
|
validateMermaid(changeDir, issues);
|
|
51
65
|
|
|
52
66
|
const result = {
|
|
@@ -67,7 +81,9 @@ print(result);
|
|
|
67
81
|
function validateReview(review, currentHash, targetIssues) {
|
|
68
82
|
if (!review) return;
|
|
69
83
|
if (review.schemaVersion !== "superflow.document-review.v1") {
|
|
70
|
-
targetIssues.push(
|
|
84
|
+
targetIssues.push(
|
|
85
|
+
"文档评审凭证 schemaVersion 必须为 superflow.document-review.v1",
|
|
86
|
+
);
|
|
71
87
|
}
|
|
72
88
|
if (review.handoffHash !== currentHash) {
|
|
73
89
|
targetIssues.push("文档评审凭证未绑定当前 handoff hash");
|
|
@@ -88,12 +104,18 @@ function validateReview(review, currentHash, targetIssues) {
|
|
|
88
104
|
"e2e-environment",
|
|
89
105
|
]);
|
|
90
106
|
for (const round of review.rounds) {
|
|
107
|
+
if (!round || !Array.isArray(round.findings)) {
|
|
108
|
+
targetIssues.push("评审轮必须显式提供 findings 数组");
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
91
111
|
requiredLenses.delete(round.lens);
|
|
92
112
|
if (round.inputHash !== currentHash) {
|
|
93
|
-
targetIssues.push(
|
|
113
|
+
targetIssues.push(
|
|
114
|
+
`第 ${round.round ?? "?"} 轮评审不是基于当前 handoff hash`,
|
|
115
|
+
);
|
|
94
116
|
}
|
|
95
117
|
const openFindings = (round.findings ?? []).filter(
|
|
96
|
-
(finding) => finding
|
|
118
|
+
(finding) => finding?.status !== "closed",
|
|
97
119
|
);
|
|
98
120
|
if (openFindings.length > 0) {
|
|
99
121
|
targetIssues.push(`第 ${round.round ?? "?"} 轮仍有未关闭评审发现`);
|
|
@@ -149,7 +171,9 @@ function validateMermaidBlock(block, targetIssues) {
|
|
|
149
171
|
if (arrows.length === 0) {
|
|
150
172
|
targetIssues.push("Mermaid sequenceDiagram 缺少有效消息箭头");
|
|
151
173
|
}
|
|
152
|
-
const openings = lines.filter((line) =>
|
|
174
|
+
const openings = lines.filter((line) =>
|
|
175
|
+
/^(alt|opt|loop|par|critical)\b/.test(line),
|
|
176
|
+
).length;
|
|
153
177
|
const endings = lines.filter((line) => line === "end").length;
|
|
154
178
|
if (openings !== endings) {
|
|
155
179
|
targetIssues.push("Mermaid sequenceDiagram 分支块未正确闭合");
|
|
@@ -107,20 +107,9 @@ superflow check <change> --level coding-ready
|
|
|
107
107
|
BLOCK_MSG
|
|
108
108
|
return 2
|
|
109
109
|
fi
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
with open(sys.argv[1], encoding="utf-8") as handle:
|
|
114
|
-
receipt = json.load(handle)
|
|
115
|
-
except Exception:
|
|
116
|
-
raise SystemExit(2)
|
|
117
|
-
if receipt.get("codingReady") is not True:
|
|
118
|
-
raise SystemExit(2)
|
|
119
|
-
if receipt.get("schemaVersion") != "superflow.coding-ready.v1":
|
|
120
|
-
raise SystemExit(2)
|
|
121
|
-
if receipt.get("handoffHash") != sys.argv[2]:
|
|
122
|
-
raise SystemExit(2)
|
|
123
|
-
PY
|
|
110
|
+
# Same validator as CLI/managed start. Source code is expected to change during
|
|
111
|
+
# implementation; only dispatch rechecks code snapshots, not every write.
|
|
112
|
+
node "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/superflow-review-coverage.mjs" "$change_dir"
|
|
124
113
|
if [ $? -ne 0 ]; then
|
|
125
114
|
cat <<'BLOCK_MSG' >&2
|
|
126
115
|
[SDD Coding Ready] 凭证已过期或与当前 handoff hash 不一致。
|