@chenmk/superflow 0.5.20 → 0.5.22

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 (90) hide show
  1. package/INSTALL.en.md +2 -0
  2. package/INSTALL.md +2 -0
  3. package/assets/scripts/superflow-delivery-check.sh +36 -6
  4. package/assets/scripts/superflow-review-coverage.mjs +34 -0
  5. package/assets/scripts/superflow-test-report-lint.py +125 -4
  6. package/assets/skill-registry.json +23 -8
  7. package/assets/skills/openspec-apply-change/SKILL.md +7 -0
  8. package/assets/skills/openspec-archive-change/SKILL.md +13 -1
  9. package/assets/skills/superflow-archive/SKILL.md +17 -0
  10. package/assets/skills/superflow-design/SKILL.md +15 -1
  11. package/assets/skills/superflow-docs/SKILL.md +11 -0
  12. package/assets/skills/superflow-implement/SKILL.md +22 -0
  13. package/assets/skills/superflow-pipeline/SKILL.md +6 -1
  14. package/assets/skills/superflow-pipeline/references/architecture-design-template.md +4 -2
  15. package/assets/skills/superflow-pipeline/references/batch-prompt-template.md +6 -1
  16. package/assets/skills/superflow-pipeline/references/document-review-coverage.md +26 -0
  17. package/assets/skills/superflow-pipeline/references/document-templates.md +7 -0
  18. package/assets/skills/superflow-pipeline/references/implementation-prompt-template.md +56 -35
  19. package/assets/skills/superflow-pipeline/references/managed-work.md +6 -0
  20. package/assets/skills/superflow-pipeline/references/mock-strategy-guide.md +28 -74
  21. package/assets/skills/superflow-pipeline/references/orchestration.md +43 -101
  22. package/assets/skills/superflow-pipeline/references/quality-gate.md +8 -4
  23. package/assets/skills/superflow-pipeline/references/reviewer-checklist.md +107 -3
  24. package/assets/skills/superflow-pipeline/references/superpower-technical-design-template.md +30 -0
  25. package/assets/skills/superflow-pipeline/references/test-execution-template.md +16 -12
  26. package/assets/skills/superflow-pipeline/references/test-guide.md +82 -30
  27. package/assets/skills/superflow-pipeline/scripts/superflow-archive.sh +57 -10
  28. package/assets/skills/superflow-pipeline/scripts/superflow-guard.sh +23 -6
  29. package/assets/skills/superflow-quick-dev/SKILL.md +3 -3
  30. package/assets/skills/superflow-verify/SKILL.md +28 -12
  31. package/assets/skills-en/openspec-apply-change/SKILL.md +8 -0
  32. package/assets/skills-en/openspec-archive-change/SKILL.md +17 -1
  33. package/assets/skills-en/superflow-archive/SKILL.md +20 -0
  34. package/assets/skills-en/superflow-design/SKILL.md +14 -1
  35. package/assets/skills-en/superflow-docs/SKILL.md +13 -0
  36. package/assets/skills-en/superflow-implement/SKILL.md +22 -0
  37. package/assets/skills-en/superflow-pipeline/SKILL.md +6 -0
  38. package/assets/skills-en/superflow-pipeline/references/architecture-design-template.md +3 -0
  39. package/assets/skills-en/superflow-pipeline/references/batch-prompt-template.md +7 -0
  40. package/assets/skills-en/superflow-pipeline/references/document-review-coverage.md +32 -0
  41. package/assets/skills-en/superflow-pipeline/references/document-templates.md +8 -0
  42. package/assets/skills-en/superflow-pipeline/references/implementation-prompt-template.md +33 -0
  43. package/assets/skills-en/superflow-pipeline/references/managed-work.md +10 -0
  44. package/assets/skills-en/superflow-pipeline/references/mock-strategy-guide.md +41 -11
  45. package/assets/skills-en/superflow-pipeline/references/orchestration.md +11 -0
  46. package/assets/skills-en/superflow-pipeline/references/quality-gate.md +9 -0
  47. package/assets/skills-en/superflow-pipeline/references/reviewer-checklist.md +132 -1
  48. package/assets/skills-en/superflow-pipeline/references/superpower-technical-design-template.md +36 -0
  49. package/assets/skills-en/superflow-pipeline/references/test-execution-template.md +5 -0
  50. package/assets/skills-en/superflow-pipeline/references/test-guide.md +106 -12
  51. package/assets/skills-en/superflow-pipeline/scripts/superflow-archive.sh +57 -10
  52. package/assets/skills-en/superflow-pipeline/scripts/superflow-guard.sh +23 -6
  53. package/assets/skills-en/superflow-quick-dev/SKILL.md +6 -3
  54. package/assets/skills-en/superflow-verify/SKILL.md +36 -12
  55. package/dist/app/cli.js +5 -5
  56. package/dist/app/cli.js.map +1 -1
  57. package/dist/app/commands/review-coverage.js +8 -3
  58. package/dist/app/commands/review-coverage.js.map +1 -1
  59. package/dist/app/commands/update.js +2 -0
  60. package/dist/app/commands/update.js.map +1 -1
  61. package/dist/build-info.json +1 -0
  62. package/dist/domains/config/cli-help.js +8 -0
  63. package/dist/domains/config/cli-help.js.map +1 -1
  64. package/dist/domains/managed-work/control.js.map +1 -1
  65. package/dist/domains/managed-work/failure.js +9 -0
  66. package/dist/domains/managed-work/failure.js.map +1 -1
  67. package/dist/domains/managed-work/prompts.js +29 -4
  68. package/dist/domains/managed-work/prompts.js.map +1 -1
  69. package/dist/domains/managed-work/runner.js +29 -24
  70. package/dist/domains/managed-work/runner.js.map +1 -1
  71. package/dist/domains/managed-work/service.js +147 -19
  72. package/dist/domains/managed-work/service.js.map +1 -1
  73. package/dist/domains/managed-work/types.js.map +1 -1
  74. package/dist/domains/quick-dev/gate.js +0 -2
  75. package/dist/domains/quick-dev/gate.js.map +1 -1
  76. package/dist/domains/review/coverage.js +12 -4
  77. package/dist/domains/review/coverage.js.map +1 -1
  78. package/dist/domains/review/report.js +67 -2
  79. package/dist/domains/review/report.js.map +1 -1
  80. package/dist/mcp/runtime-identity.js +19 -4
  81. package/dist/mcp/runtime-identity.js.map +1 -1
  82. package/dist/mcp/server.js +1 -1
  83. package/dist/mcp/server.js.map +1 -1
  84. package/dist/platform/agent-process.js +48 -9
  85. package/dist/platform/agent-process.js.map +1 -1
  86. package/dist/platform/process-liveness.js +46 -0
  87. package/dist/platform/process-liveness.js.map +1 -1
  88. package/package.json +2 -1
  89. package/scripts/ensure-bin-modes.js +37 -2
  90. package/scripts/verify-changed.mjs +321 -0
package/INSTALL.en.md CHANGED
@@ -183,3 +183,5 @@ superflow uninstall --agent claude --force
183
183
 
184
184
  This removes SuperBridge Flow managed assets only. It does not remove unrelated
185
185
  agent configuration.
186
+
187
+ `--agent` limits both current-scope and registered-project refreshes; selecting Codex does not add Claude. `--scope` selects the current entry scope. Existing registered projects still refresh the selected platforms at their recorded scope; the update plan lists every target.
package/INSTALL.md CHANGED
@@ -741,3 +741,5 @@ Claude Code:
741
741
 
742
742
  恢复时 SDD 会读取 `superflow status`、`.sdd/state.yaml` 和 `.sdd/handoff/`
743
743
  上下文包来判断当前 phase,用户不需要手动列出这些步骤。
744
+
745
+ `--agent` 同时限定当前作用域与已登记项目的刷新平台;选择 Codex 不会扩展为 Claude。`--scope` 决定当前入口的安装范围,既有受管项目仍按登记范围刷新所选平台,更新计划列出全部目标。
@@ -139,14 +139,31 @@ has_staged_file() {
139
139
  printf '%s\n' "$CHANGED" | grep -Fxq "$path"
140
140
  }
141
141
 
142
+ read_report_body() {
143
+ python3 - "$LINT" "$1" <<'PYBODY'
144
+ import runpy, sys
145
+ from pathlib import Path
146
+ module = runpy.run_path(sys.argv[1])
147
+ lines, ambiguous = module["markdown_body_lines"](Path(sys.argv[2]).read_text())
148
+ if ambiguous:
149
+ raise SystemExit("report Markdown body is ambiguous")
150
+ print("\n".join(lines))
151
+ PYBODY
152
+ }
153
+
142
154
  check_no_open_placeholders() {
143
155
  local file="$1"
156
+ local body
144
157
  if [ ! -f "$file" ]; then
145
158
  fail "[$file] 文件不存在"
146
159
  return
147
160
  fi
148
161
 
149
- if grep -Eiq '待执行|待补充|后续补测|后续测试|TODO|测试报告待更新|验证待回填' "$file"; then
162
+ if ! body="$(read_report_body "$file")"; then
163
+ fail "[$file] 无法确定报告正文,不能沿用交付结论"
164
+ return
165
+ fi
166
+ if printf '%s\n' "$body" | grep -Eiq '待执行|待补充|后续补测|后续测试|TODO|测试报告待更新|验证待回填'; then
150
167
  fail "[$file] 仍包含待执行/待补充/TODO 类交付占位"
151
168
  else
152
169
  ok "[$file] 未发现明显交付占位"
@@ -155,7 +172,12 @@ check_no_open_placeholders() {
155
172
 
156
173
  check_has_closeout_status() {
157
174
  local file="$1"
158
- if grep -Eiq 'Real integration passed|Partially verified|Partial real entry|Blocked|真实入口|真实接口|验证闭环|阻塞|部分验证' "$file"; then
175
+ local body
176
+ if ! body="$(read_report_body "$file")"; then
177
+ fail "[$file] 无法确定报告正文,不能沿用交付结论"
178
+ return
179
+ fi
180
+ if printf '%s\n' "$body" | grep -Eiq 'Real integration passed|Partially verified|Partial real entry|Blocked|真实入口|真实接口|验证闭环|阻塞|部分验证'; then
159
181
  ok "[$file] 包含交付结论"
160
182
  else
161
183
  fail "[$file] 缺少 Real integration passed / Partially verified / Blocked 等交付结论"
@@ -222,7 +244,10 @@ import runpy, sys
222
244
  from pathlib import Path
223
245
  module = runpy.run_path(sys.argv[1])
224
246
  text = Path(sys.argv[2]).read_text()
225
- lines = text.splitlines()
247
+ lines, ambiguous = module["markdown_body_lines"](text)
248
+ if ambiguous:
249
+ print("INVALID")
250
+ raise SystemExit
226
251
  header = next((i for i, line in enumerate(lines) if module["CASE_EVIDENCE_HEADER"].fullmatch(line.strip())), None)
227
252
  active_pass = False
228
253
  if header is not None:
@@ -233,9 +258,14 @@ if header is not None:
233
258
  print("CASE_PASS" if active_pass else module["final_report_result"](text))
234
259
  PYFINAL
235
260
  )" || return 1
236
- case "$final_result" in PASS|CONFLICT|CASE_PASS) return 1 ;; esac
237
- grep -Eiq 'Blocked|阻塞' "$file" \
238
- && grep -Eiq 'SDD 文档|文档阶段|范围收口|范围冻结|任务冻结|不包含代码实现|没有 Java 实现变更|未进入实现|当前报告记录可交付边界' "$file"
261
+ case "$final_result" in
262
+ BLOCKED|MISSING) ;;
263
+ *) return 1 ;;
264
+ esac
265
+ local body
266
+ body="$(read_report_body "$file")" || return 1
267
+ printf '%s\n' "$body" | grep -Eiq 'Blocked|阻塞' \
268
+ && printf '%s\n' "$body" | grep -Eiq 'SDD 文档|文档阶段|范围收口|范围冻结|任务冻结|不包含代码实现|没有 Java 实现变更|未进入实现|当前报告记录可交付边界'
239
269
  }
240
270
 
241
271
  DOC_FREEZE_ALLOWED=0
@@ -170,6 +170,40 @@ export function validateCoverage(root, review, issues, checkCode = true) {
170
170
  )
171
171
  issues.push(`用例 ${test.id} 的 evidenceKind 无效`);
172
172
 
173
+ if (Object.hasOwn(test, "executionContext")) {
174
+ const context = test.executionContext;
175
+ const environmentKeys = context?.environmentKeys;
176
+ const supported = [
177
+ "PATH",
178
+ "PATHEXT",
179
+ "NODE_ENV",
180
+ "NODE_OPTIONS",
181
+ "LANG",
182
+ "LC_ALL",
183
+ "TZ",
184
+ "JAVA_HOME",
185
+ ];
186
+ if (
187
+ !context ||
188
+ typeof context !== "object" ||
189
+ Array.isArray(context) ||
190
+ Object.keys(context).sort().join(",") !== "argv,cwd,environmentKeys" ||
191
+ !Array.isArray(context.argv) ||
192
+ !context.argv.length ||
193
+ context.argv.some((arg) => !nonempty(arg)) ||
194
+ !nonempty(context.cwd) ||
195
+ path.isAbsolute(context.cwd) ||
196
+ path.win32.isAbsolute(context.cwd) ||
197
+ /^[A-Za-z]:/.test(context.cwd) ||
198
+ !Array.isArray(environmentKeys) ||
199
+ environmentKeys.some((key) => !supported.includes(key)) ||
200
+ new Set(environmentKeys).size !== environmentKeys.length
201
+ )
202
+ issues.push(
203
+ `用例 ${test.id} 的 executionContext 必须冻结 argv、相对 cwd 与受支持的非秘密 environmentKeys`,
204
+ );
205
+ }
206
+
173
207
  const layer = test.testLayer;
174
208
  const realDatabase = ["database", "http-entry"].includes(layer);
175
209
  if (
@@ -16,6 +16,8 @@ from __future__ import annotations
16
16
  import argparse
17
17
  import hashlib
18
18
  import json
19
+ import ntpath
20
+ import os
19
21
  import re
20
22
  import subprocess
21
23
  import sys
@@ -262,13 +264,87 @@ def lint_against_tests_contract(report_path: Path, report_text: str, tests_path:
262
264
  return issues
263
265
 
264
266
 
267
+ def fence_container_line(line: str) -> tuple[str, list]:
268
+ prefixes = []
269
+ text = line
270
+ while True:
271
+ quote = re.match(r"^ {0,3}> ?", text)
272
+ item = re.match(r"^ {0,3}(?:[-+*]|\d{1,9}[.)]) +", text)
273
+ prefix = quote or item
274
+ if prefix is None:
275
+ return text, prefixes
276
+ prefixes.append("quote" if quote else len(prefix[0]))
277
+ text = text[len(prefix[0]):]
278
+
279
+
280
+ def closing_fence_line(line: str, prefixes: list) -> str | None:
281
+ text = line
282
+ for prefix in prefixes:
283
+ pattern = r"^ {0,3}> ?" if prefix == "quote" else r"^ {%d}" % prefix
284
+ match = re.match(pattern, text)
285
+ if match is None:
286
+ return None
287
+ text = text[len(match[0]):]
288
+ return text
289
+
290
+
291
+ def markdown_body_lines(text: str) -> tuple[list[str], bool]:
292
+ """Structural report content only; preserve original line positions."""
293
+ fence = None
294
+ prefixes = []
295
+ unsupported_tab = False
296
+ result = []
297
+ for line in text.splitlines():
298
+ if fence is not None:
299
+ candidate = closing_fence_line(line, prefixes)
300
+ marker = None if candidate is None else re.match(r"^ {0,3}(`{3,}|~{3,})(.*)$", candidate)
301
+ if (marker and marker[1][0] == fence[0]
302
+ and len(marker[1]) >= len(fence)
303
+ and not marker[2].strip(" \t")):
304
+ fence = None
305
+ result.append("")
306
+ continue
307
+ possible_container = re.match(r"^((?:[ \t]*>[ \t]*|[ \t]*(?:[-+*]|\d{1,9}[.)])[ \t]+)+)(`{3,}|~{3,})", line)
308
+ if possible_container and "\t" in possible_container[1]:
309
+ unsupported_tab = True
310
+ candidate, next_prefixes = fence_container_line(line)
311
+ marker = re.match(r"^ {0,3}(`{3,}|~{3,})(.*)$", candidate)
312
+ if marker and (marker[1][0] == "~" or "`" not in marker[2]):
313
+ fence = marker[1]
314
+ prefixes = next_prefixes
315
+ result.append("")
316
+ else:
317
+ result.append(line)
318
+ return result, unsupported_tab or (fence is not None and bool(prefixes))
319
+
320
+
265
321
  def final_report_result(text: str) -> str:
266
322
  # Only the latest explicit summary per language is authoritative. Historical
267
323
  # notes and fenced examples do not invalidate the final execution ledger.
268
- text = re.sub(r"```.*?```", "", text, flags=re.S)
324
+ return report_summary_result(text, {"验证结果": "zh", "验证结论": "zh",
325
+ "Verification Result": "en"},
326
+ {"通过": "PASS", "失败": "FAIL"})
327
+
328
+
329
+ def archive_readiness_result(text: str) -> str:
330
+ return report_summary_result(text, {"归档就绪": "zh", "Archive Readiness": "en"},
331
+ {"READY": "PASS", "通过": "PASS",
332
+ "就绪": "PASS", "失败": "FAIL"})
333
+
334
+
335
+ def report_summary_result(text: str, labels: dict[str, str], aliases: dict[str, str]) -> str:
336
+ lines, ambiguous = markdown_body_lines(text)
337
+ if ambiguous:
338
+ return "INVALID"
339
+ text = "\n".join(lines)
340
+ pattern = "|".join(re.escape(label) for label in labels)
341
+ label_keys = {label.lower(): key for label, key in labels.items()}
269
342
  results = {}
270
- for match in re.finditer(r"^(验证结果|Verification Result)\s*[::]\s*([A-Z_]+)\s*$", text, re.I | re.M):
271
- results[match[1].lower()] = match[2].upper()
343
+ for match in re.finditer(rf"^({pattern})[ \t]*[::][ \t]*([^\r\n]*)$", text, re.I | re.M):
344
+ value = match[2].strip().upper()
345
+ # MISSING denotes an absent summary, never an explicit unknown status.
346
+ value = "UNKNOWN" if not value or value == "MISSING" else value
347
+ results[label_keys[match[1].lower()]] = aliases.get(value, value)
272
348
  if len(set(results.values())) > 1:
273
349
  return "CONFLICT"
274
350
  return next(iter(results.values()), "MISSING")
@@ -367,6 +443,48 @@ def validate_database_receipt(receipt: dict, event: dict, case: dict,
367
443
  raise ValueError("数据库数据/影响行数/不变断言未达到冻结预期")
368
444
 
369
445
 
446
+ EXECUTION_ENV_KEYS = frozenset([
447
+ "PATH", "PATHEXT", "NODE_ENV", "NODE_OPTIONS", "LANG", "LC_ALL", "TZ", "JAVA_HOME",
448
+ ])
449
+
450
+
451
+ def validate_execution_context(receipt: dict, event: dict, case: dict, change: Path) -> None:
452
+ """Optional frozen bindings strengthen reuse without rewriting legacy proof."""
453
+ if "executionContext" not in case:
454
+ # Legacy extra metadata is retained, but never proves declared-context reuse.
455
+ return
456
+ binding = case["executionContext"]
457
+ if (not isinstance(binding, dict)
458
+ or set(binding) != {"argv", "cwd", "environmentKeys"}
459
+ or not isinstance(binding["argv"], list) or not binding["argv"]
460
+ or any(not isinstance(arg, str) or not arg.strip() for arg in binding["argv"])
461
+ or not isinstance(binding["cwd"], str) or not binding["cwd"].strip()
462
+ or Path(binding["cwd"]).is_absolute() or ntpath.isabs(binding["cwd"])
463
+ or bool(ntpath.splitdrive(binding["cwd"])[0])):
464
+ raise ValueError("executionContext 需要冻结 argv、相对 cwd 和 environmentKeys")
465
+ keys = binding["environmentKeys"]
466
+ if (not isinstance(keys, list)
467
+ or any(not isinstance(key, str) or key not in EXECUTION_ENV_KEYS for key in keys)
468
+ or len(set(keys)) != len(keys)):
469
+ raise ValueError("executionContext 环境项必须是受支持且不重复的非秘密运行配置")
470
+ context = receipt.get("executionContext")
471
+ if (not isinstance(context, dict) or set(context) != {"cwd", "environmentSha256"}
472
+ or not json_equal(event.get("executionContext"), context)):
473
+ raise ValueError("原始执行输出与凭证 executionContext 不一致或缺失")
474
+ if not json_equal(receipt["command"]["argv"], binding["argv"]):
475
+ raise ValueError("执行命令与冻结 executionContext.argv 不一致")
476
+ cwd = (change / binding["cwd"]).resolve()
477
+ if (not cwd.is_dir() or not isinstance(context["cwd"], str)
478
+ or context["cwd"] != str(cwd)):
479
+ raise ValueError("执行工作目录与冻结 executionContext.cwd 不一致")
480
+ expected = {
481
+ key: hashlib.sha256(json.dumps(os.environ.get(key), ensure_ascii=False).encode()).hexdigest()
482
+ for key in keys
483
+ }
484
+ if not json_equal(context["environmentSha256"], expected):
485
+ raise ValueError("绑定运行环境已变化或观测缺失;旧结果不能用于当前完整通过")
486
+
487
+
370
488
  def validate_execution_receipt(file: Path, case: dict, coverage: dict, change: Path) -> None:
371
489
  receipt = json.loads(file.read_text(encoding="utf-8"))
372
490
  if receipt.get("schemaVersion") != "superflow.execution-receipt.v1":
@@ -403,6 +521,7 @@ def validate_execution_receipt(file: Path, case: dict, coverage: dict, change: P
403
521
  raise ValueError(f"原始执行输出与凭证 {key} 不一致")
404
522
  if not json_equal(event.get("command"), {"argv": command["argv"], "exitCode": command["exitCode"]}):
405
523
  raise ValueError("原始执行命令与凭证不一致")
524
+ validate_execution_context(receipt, event, case, change)
406
525
  sources = receipt["sources"]
407
526
  if not isinstance(sources, list) or not sources:
408
527
  raise ValueError("缺少当前源码/构建指纹")
@@ -541,7 +660,9 @@ def lint_case_evidence(report_path: Path, report_text: str, review_path: Path, i
541
660
  }
542
661
  if final_report_result(report_text) == "CONFLICT":
543
662
  issues.append(Issue("FAIL", report_path, 0, "中英文最终验证结果冲突"))
544
- lines = report_text.splitlines()
663
+ lines, ambiguous = markdown_body_lines(report_text)
664
+ if ambiguous:
665
+ return [Issue("FAIL", report_path, 0, "列表/引用代码块结构无法确定;用空格缩进并明确闭合后再核验,不能沿用早期 PASS")]
545
666
  header_at = next(
546
667
  (i for i, line in enumerate(lines) if CASE_EVIDENCE_HEADER.fullmatch(line.strip())),
547
668
  None,
@@ -7,7 +7,9 @@
7
7
  "triggers": [
8
8
  "implement approved change"
9
9
  ],
10
- "excludes": [],
10
+ "excludes": [
11
+ "test plan design or signal selection; inherit frozen project/Superflow contracts"
12
+ ],
11
13
  "outputs": [
12
14
  "tasks.md progress"
13
15
  ],
@@ -19,11 +21,15 @@
19
21
  "triggers": [
20
22
  "archive completed change"
21
23
  ],
22
- "excludes": [],
24
+ "excludes": [
25
+ "change directory contains .sdd/state.yaml; SDD lifecycle closeout belongs to superflow-archive"
26
+ ],
23
27
  "outputs": [
24
28
  "archive result"
25
29
  ],
26
- "neighbors": []
30
+ "neighbors": [
31
+ "superflow-archive"
32
+ ]
27
33
  },
28
34
  {
29
35
  "name": "openspec-explore",
@@ -105,7 +111,9 @@
105
111
  "triggers": [
106
112
  "SDD contract documents"
107
113
  ],
108
- "excludes": [],
114
+ "excludes": [
115
+ "runtime execution or implementation prompt generation"
116
+ ],
109
117
  "outputs": [
110
118
  "api.md tests.md sdd-quality-gate.md"
111
119
  ],
@@ -133,7 +141,9 @@
133
141
  "triggers": [
134
142
  "generate implementation prompts"
135
143
  ],
136
- "excludes": [],
144
+ "excludes": [
145
+ "test strategy redesign; inherit tests.md"
146
+ ],
137
147
  "outputs": [
138
148
  "prompt/ test-report.md"
139
149
  ],
@@ -199,7 +209,8 @@
199
209
  ],
200
210
  "excludes": [
201
211
  "public API or database change",
202
- "cross-module change"
212
+ "cross-module change",
213
+ "application, database, or real-entry acceptance outside the approved Quick Spec"
203
214
  ],
204
215
  "outputs": [
205
216
  ".sdd/tasks/<date>-<slug>/spec.md",
@@ -214,9 +225,13 @@
214
225
  "name": "superflow-verify",
215
226
  "owner": "verify",
216
227
  "triggers": [
217
- "verify implementation"
228
+ "verify implementation",
229
+ "review code changes"
230
+ ],
231
+ "excludes": [
232
+ "implementation or environment execution; assess evidence read-only",
233
+ "requirement or test strategy redesign; inherit frozen contracts"
218
234
  ],
219
- "excludes": [],
220
235
  "outputs": [
221
236
  "verification report"
222
237
  ],
@@ -11,6 +11,13 @@ metadata:
11
11
 
12
12
  Implement tasks from an OpenSpec change.
13
13
 
14
+ ## Superflow 实施验证入口
15
+
16
+ 在 Superflow 工作流中,实施首个任务前读取
17
+ [测试指南](../superflow-pipeline/references/test-guide.md),加载已冻结的 tests.md 与项目测试。
18
+ 逐任务按既有用例执行 RED/GREEN 与必要真实验证,证据成立才勾选完成;缺合同回
19
+ superflow-docs,缺环境记录阻塞。普通 OpenSpec 使用项目自己的验证规则。
20
+
14
21
  **Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
15
22
 
16
23
  **Steps**
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: openspec-archive-change
3
- description: Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.
3
+ description: Use when the user wants to archive a completed pure OpenSpec change without .sdd/state.yaml.
4
4
  license: MIT
5
5
  compatibility: Requires openspec CLI.
6
6
  metadata:
@@ -13,6 +13,18 @@ Archive a completed change in the experimental workflow.
13
13
 
14
14
  **Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
15
15
 
16
+ ## SDD 归档分流(先执行)
17
+
18
+ 先确定目标 change 目录;目标不明确时沿下方选择步骤确认,再检查该目录的
19
+ `.sdd/state.yaml`。文件存在时立即加载 `$superflow-archive` 并停止本技能的后续步骤。
20
+ 验证未通过或任务未完成时,按该技能返回验证/实施;不能退回本技能继续归档。
21
+ SDD 变更不能使用下方的未完成任务确认、`Archive without syncing` 或 `mv` 捷径;
22
+ 归档门禁、确认、OpenSpec 合并和 state 收口均由 `superflow-archive` 持有。
23
+ 已搬迁的 SDD 目录也使用该 owner 的精确归档路径恢复流程。
24
+
25
+ 只有目标目录没有 `.sdd/state.yaml` 时,才执行下方纯 OpenSpec 流程。
26
+ 这属于 Agent 语义路由;命令 Hook 不是操作系统级拦截,不能假定它会阻止任意 `mv`。
27
+
16
28
  **Steps**
17
29
 
18
30
  1. **If no change name provided, prompt for selection**
@@ -39,6 +39,23 @@ do not mark archived until the user confirms final closeout.
39
39
  ~/.codex/skills/superflow-pipeline/scripts/superflow-archive.sh <change-dir> --apply
40
40
  ```
41
41
 
42
+ ## 归档搬迁后的恢复
43
+
44
+ OpenSpec 已移动目录但文档标注或 state 收口失败时,保留现场与原始错误。
45
+ 根据本次 archive 输出或实际操作记录确认精确 `openspec/changes/archive/<archive-name>`;
46
+ 不能凭同名选择旧日期目录,也不对失效的原路径重复归档。明确目标后运行原 helper:
47
+
48
+ ```bash
49
+ ~/.codex/skills/superflow-pipeline/scripts/superflow-archive.sh <explicit-archived-dir> --dry-run
50
+ # 核对摘要、原授权与当前未完成步骤后继续;不扩大原归档授权
51
+ ~/.codex/skills/superflow-pipeline/scripts/superflow-archive.sh <explicit-archived-dir> --apply
52
+ ```
53
+
54
+ 已移动目录只恢复剩余标注与原 state transition,仍需 validate/guard;done + archived 状态
55
+ 正确时只读幂等返回。非标准任务目录保留既有 state-only fallback。
56
+ 检查实际 `.sdd/state.yaml`、技术详设/设计/计划标注和输出;缺失或冲突记录阻塞。
57
+ 此恢复不自动 commit/push/merge,不重做已完成 OpenSpec 合并,不创建第二套收口状态机。
58
+
42
59
  ## Rules
43
60
 
44
61
  - Do not archive if verification failed or is only partially verified unless
@@ -44,6 +44,13 @@ Superpowers own source-level HOW without weakening OpenSpec/SDD contracts.
44
44
 
45
45
  1. Read `.sdd/handoff/sdd-context.md` plus original `api.md`, `design.md`,
46
46
  `tasks.md`, and `tests.md`.
47
+ Read applicable project rules and use the Host's normal skill discovery for
48
+ relevant skills referenced by those rules or applicable to the task. Read
49
+ each complete skill file and its relevant references before designing.
50
+ Do not scan personal skill directories, record personal absolute paths, or
51
+ copy user-level rule/skill text into project artifacts. Apply the discovered
52
+ content when designing; freeze only task-relevant constraints through the
53
+ existing `mandatoryEngineeringRules` handoff for implementation and review.
47
54
  2. If the change has any schema, index, constraint, seed-data, or historical
48
55
  migration impact, verify `release-sql.md` before source-level HOW design:
49
56
  - front matter sets `database_change: true`, an exact `target_sql_path`,
@@ -77,7 +84,14 @@ Superpowers own source-level HOW without weakening OpenSpec/SDD contracts.
77
84
  when they satisfy the contract. Remove speculative extension points,
78
85
  duplicate DTO/API layers, derivable persistence, premature caches, and
79
86
  async compensation without measured need. Record the retained and removed
80
- counts; unresolved simpler alternatives keep the design blocked.
87
+ counts; unresolved simpler alternatives keep the design blocked. For
88
+ data-intensive paths (large or growing collections, batch processing,
89
+ imports/exports, aggregation, repeated scans, or fan-out), also record
90
+ current/expected scale and growth boundary, work and primary cost per
91
+ request/job, alternatives considered, and evidence validating the choice.
92
+ Match evidence to risk: source/query analysis or representative functional
93
+ cases may suffice; do not require benchmarks for small tasks. Mark this not
94
+ applicable with a brief reason when data volume is not material.
81
95
  7. For cross-repository, service-to-service, SDK, MQ, scheduler, device,
82
96
  callback, third-party, mini-program, gateway, or adapter changes, include
83
97
  `Architecture Boundary And Call Direction`. Prove owner module, call
@@ -5,6 +5,12 @@ description: Use when confirmed OpenSpec artifacts need SDD contract docs such a
5
5
 
6
6
  # SDD Docs
7
7
 
8
+ ## 测试方案入口
9
+
10
+ 写 tests.md 前读取[测试指南](../superflow-pipeline/references/test-guide.md),先复用项目测试与环境,
11
+ 把受影响行为映射到验证信号,在本阶段冻结用例、实际后端、mockBoundary、命令和断言。
12
+ 实现阶段只继承;不能把必要数据库验证留到编码时临场决定。
13
+
8
14
  完整文档交付必须读取并执行
9
15
  [需求×真实入口评审](../superflow-pipeline/references/document-review-coverage.md):
10
16
  扩展现有三轮评审凭证,逐项核对原始需求、真实调用分支、EXCLUDED/VERIFY_EXISTING
@@ -15,6 +21,11 @@ created the base OpenSpec artifacts. This skill is an SDD contract-doc wrapper;
15
21
  it must not replace the installed OpenSpec skills for core artifact generation
16
22
  and must not generate implementation prompts.
17
23
 
24
+ 需要跨轮复用对命令/目录/调用环境敏感的检查时,本阶段按
25
+ [executionContext 合同](../superflow-pipeline/references/document-review-coverage.md#声明式执行上下文与证据复用)
26
+ 冻结 argv、相对 cwd 和已选非秘密环境项;历史未绑定证据不自动升级为新上下文完整通过。
27
+
28
+
18
29
  ## OpenSpec First
19
30
 
20
31
  For new OpenSpec document generation, invoke `$openspec-propose` first. The
@@ -5,11 +5,22 @@ description: SDD 实现阶段,基于已完成的 SDD 文档生成分批 implem
5
5
 
6
6
  # SDD Implement
7
7
 
8
+ ## 验证合同继承
9
+
10
+ 生成 Prompt 前读取[测试指南](../superflow-pipeline/references/test-guide.md),将 tests.md 的
11
+ 用例、命令、实际后端和断言逐项继承,并要求实施方开工前核对、逐项执行与回填。
12
+ 缺少信号或真实环境义务时返回 superflow-docs;本阶段不创建另一套测试策略。
13
+
8
14
  Use `$openspec-apply-change` as the primary path for implementing tasks from an
9
15
  OpenSpec change. Use this skill only after SDD docs exist and the user needs
10
16
  extra SDD-specific prompt splitting, P0/P1/P2 handoff, CR/Px follow-up prompts,
11
17
  review checklists, validation plans, or test-report updates.
12
18
 
19
+ Prompt 只继承已冻结的 executionContext;执行入口生成实际 cwd 与选中环境摘要,
20
+ 与原始事件/receipt 对账,不能由 Agent 手填预期观测。缺字段或环境错配回文档 owner
21
+ 或执行必要重跑,不改变原始成功记录。
22
+
23
+
13
24
  ## Preconditions
14
25
 
15
26
  - `proposal.md`, `api.md`, `design.md`, `tasks.md`, `tests.md`,
@@ -145,6 +156,17 @@ Before implementation phase can exit:
145
156
  compare the new hash. A stale or mismatched hash blocks coding and delivery.
146
157
  The prompt must also require `.sdd/state.yaml` phase evidence and
147
158
  `superflow-guard.sh <change-dir> implement` before moving to verification.
159
+ Identify applicable project rules through the frozen handoff and task-relevant
160
+ skills through the Host's normal skill discovery. The Host must read applicable
161
+ skill content and pass the relevant rule statements through the existing
162
+ `mandatoryEngineeringRules` input; do not pass skill names alone or scan
163
+ personal configuration directories. The Executor and Reviewer receive the
164
+ same frozen statements. Require both to read applicable project rule files
165
+ completely before acting. Do not copy personal rules into project artifacts.
166
+ - Data-intensive work must carry the technical design's data scale, growth
167
+ boundary, processing-cost trade-offs, and validation evidence into the prompt.
168
+ Keep this conditional and proportional to risk; simple work does not acquire
169
+ a mandatory benchmark.
148
170
  - Every implementation prompt must include a "状态机执行决策" section. It must
149
171
  record `build_mode`, `isolation`, `tdd_mode`, `review_mode`,
150
172
  `subagent_dispatch` when applicable, `implementation_prompt`, and the derived
@@ -3,6 +3,11 @@ name: superflow-pipeline
3
3
  description: SDD 总入口和路由技能。Use when the user says sdd, SDD 流程, OpenSpec 文档, 需求澄清, 生成 spec/design/tasks/tests, 生成任务 prompt, 进入开发, or asks which SDD/OpenSpec phase to use. Routes OpenSpec documents to openspec-propose, source-level technical design to superflow-design, implementation to openspec-apply-change, and uses SDD skills for quality gates, handoff, prompt splitting, and validation.
4
4
  ---
5
5
 
6
+ ## 测试指导唯一入口
7
+
8
+ 生成测试文档、准备实施或核验交付时,读取 [test-guide.md](references/test-guide.md)。
9
+ 文档阶段冻结必要信号;实施继承,评审核验。Mock 边界和示例不得覆盖规范数据库合同。
10
+
6
11
  # SDD Spec Pipeline
7
12
 
8
13
  This is the lightweight SDD router. Do not load the whole SDD process when a smaller phase skill is enough.
@@ -1045,7 +1050,7 @@ starter、connector 或任何被当前项目引用的外部项目时,必须把
1045
1050
  实现 prompt,必须同时落下三层门禁:
1046
1051
 
1047
1052
  1. **Prompt 完成定义**:明确"单元测试通过不等于完成",任务完成必须包含
1048
- 应用新进程启动、真实 curl/API 调用、数据库查询、日志检查和 test-report
1053
+ 当前待测构建的应用启动/身份核验、真实 curl/API 调用、数据库查询、日志检查和 test-report
1049
1054
  证据回填。
1050
1055
  2. **Hook 过程拦截**:启用 `.sdd-enforced` / `.db-verified`,禁止跳过
1051
1056
  worktree、数据库前置核查和版本总 SQL 收口;运行时代码提交前必须有
@@ -79,7 +79,7 @@ Order 1:N OrderItem
79
79
 
80
80
  | 外部依赖 | 实际能力 | Mock 方式 | 替代验证方式 |
81
81
  |----------|----------|-----------|-------------|
82
- | 支付网关 | 真实支付 | Spring MockBean | 固定返回 success |
82
+ | 支付网关 | 真实支付 | 合同允许隔离 PaymentClient | 真实 Service/Mapper 落库断言;不证明实际扣款 |
83
83
  | 短信服务 | 真实发送 | WireMock | 验证调用次数 |
84
84
  | 设备回调 | 硬件触发 | 本地模拟 HTTP 服务 | 手动调接口模拟 |
85
85
 
@@ -88,7 +88,7 @@ Order 1:N OrderItem
88
88
  ## 7. 部署架构
89
89
 
90
90
  ```
91
- 开发环境:本地 IDEA + H2/MySQL
91
+ 开发环境:本地 IDE + design/tests 冻结的生产同类型数据库引擎及兼容版本
92
92
  测试环境:Docker Compose(MySQL + Redis + App)
93
93
  生产环境:K8s / 物理机
94
94
  ```
@@ -117,3 +117,5 @@ ENTRYPOINT ["java", "-jar", "/app.jar"]
117
117
  | 日志 | SLF4J + Logback,结构化日志 |
118
118
  | 监控 | Actuator + 自定义指标 |
119
119
  | 异常 | 全局异常处理器,统一错误码 |
120
+
121
+ 测试信号按 [test-guide.md](test-guide.md)冻结;Mock 边界按 [mock-strategy-guide.md](mock-strategy-guide.md)声明,真实数据库不可用替代引擎关闭。
@@ -1,5 +1,10 @@
1
1
  # 分批 Implementation Prompt 模板
2
2
 
3
+ 验证方案只继承 tests.md,并先读 [test-guide.md](test-guide.md)。模板中的启动、
4
+ 接口、DB 和团队 checklist 按已冻结的适用项执行,不适用项给出源码依据;缺失必测
5
+ 环境保持阻塞。当前构建与健康实例一致时复用;新代码/配置必须加载后才可验证。
6
+ 独立核验原始证据,失效或合同要求的路径由实施方重跑,不能由角色切换触发重复环境。
7
+
3
8
  ## 模板结构
4
9
 
5
10
  每份 implementation prompt 必须包含以下全部章节。缺失任何一节都可能导致 agent 偏离设计。
@@ -347,7 +352,7 @@ curl -s -c /tmp/cookies.txt -b /tmp/cookies.txt \
347
352
 
348
353
  本批次涉及接口、CRUD、Mapper/XML、数据库字段或配置驱动行为时,必须同时满足:
349
354
 
350
- 1. **Prompt 完成定义**:编译、单测、应用新进程启动、真实 curl/API 调用、
355
+ 1. **Prompt 完成定义**:编译、单测、当前待测构建的应用启动/身份核验、真实 curl/API 调用、
351
356
  数据库查询、日志检查、test-report 回填全部完成。
352
357
  2. **Hook 过程拦截**:`.sdd-enforced` 和 `.db-verified` 保持激活,直到
353
358
  集成验收脚本通过;运行时代码提交必须同步提交 test-report 证据。
@@ -155,3 +155,29 @@ before 与 after 均须匹配冻结 expected。布尔成功标志不能替代快
155
155
  数组/对象中的字段同样适用;具体业务键与快照字段由文档与独立评审决定。
156
156
 
157
157
  Git 交付路径还会对 tracked 报告依赖(receipt、原始事件、构建、源码、schema/合同)核对标准化 index 对象;仅在工作树修正不能证明待提交快照。未受版本控制的私有证据不强制提交;当前源码/构建适用性仍由独立评审判断。
158
+
159
+ ## 声明式执行上下文与证据复用
160
+
161
+ 沿用 coverage/receipt v1;需要跨轮复用对命令、工作目录或调用环境敏感的检查时,
162
+ 由文档 owner 在 tests.md 与对应 case 中冻结
163
+ `executionContext={argv:[命令参数],cwd:相对change目录的工作目录,environmentKeys:[变量名]}`。
164
+ argv 必须非空且逐项明确;cwd 使用相对路径,不使用盘符或绝对路径。作用范围仍由任务授权
165
+ 和源码/合同决定,cwd 声明不授予额外读取权限。执行者不能临场改变此合同。
166
+
167
+ 当前支持的环境项仅为 PATH、PATHEXT、NODE_ENV、NODE_OPTIONS、LANG、LC_ALL、TZ、JAVA_HOME;
168
+ 只选择影响本条验证命令的项。密码、token、账号凭据和完整环境不进入合同或凭证。
169
+ 命令需使用项目验证入口并从运行时读取认证,不能为填写 argv 把秘密写进命令/文档。
170
+ 变量缺失与空值不同:每项摘要为 UTF-8 SHA-256(JSON.stringify(字符串值或 null));
171
+ receipt 和原始事件记录
172
+ `executionContext={cwd:实际规范绝对目录,environmentSha256:{已选变量名:摘要}}`。
173
+ 这些观测必须由实际执行入口生成,不由 Agent 根据预期手填。
174
+
175
+ 既有 lint 检查:实际 command.argv 与冻结 argv 相同;receipt/原始事件上下文相同;
176
+ cwd 对应当前 change 的冻结相对目录;已选环境摘要与运行 lint 的当前调用环境一致。
177
+ 因此复核应在 tests.md 的同一调用环境中执行。无关环境项变化不使证据失效;已选项、
178
+ 命令、目录、源码、构建或实际入口变化不能用旧结果关闭当前完整 PASS。
179
+ 此绑定不证明远端服务的启动环境;服务/数据库引擎、生产链与证据充分性仍须独立评审。
180
+
181
+ 未声明新字段的历史合同继续按已有源码/构建/入口规则核验,保留其原结论,不能声称
182
+ 已按此新增上下文要求核验。声明后缺观测、形状错误或错配必须补证据,不能把旧记录改成
183
+ 预期值。若需要修订冻结合同,返回文档 owner 重新评审,而非执行者放宽检查。
@@ -133,3 +133,10 @@
133
133
  - **自动化**: [自动化] / [需手工]
134
134
  - **关联**: spec.md Requirement N → Scenario X
135
135
  ```
136
+
137
+ ## tests.md:验证信号冻结
138
+
139
+ 按 [test-guide.md](test-guide.md)选择项目适用信号,使用已有测试层级编号。
140
+ 表头:`改动/风险 | 用例 ID | 验证信号 | 实际环境/后端 | 命令 | 断言 | 证据位置 | 不适用依据/阻塞`。
141
+ 数据库分层只继承 [document-review-coverage.md](document-review-coverage.md) 的
142
+ `testLayer` / `mockBoundary`;关键业务主流程和 Bug 复现优先复用项目场景回归资产。