@guanlin4924/devflow-pi 0.1.94 → 0.1.95

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 (238) hide show
  1. package/README.md +4 -4
  2. package/node_modules/@playwright/test/LICENSE +202 -0
  3. package/node_modules/@playwright/test/NOTICE +5 -0
  4. package/node_modules/@playwright/test/README.md +318 -0
  5. package/node_modules/@playwright/test/cli.js +19 -0
  6. package/node_modules/@playwright/test/index.d.ts +18 -0
  7. package/node_modules/@playwright/test/index.js +17 -0
  8. package/node_modules/@playwright/test/index.mjs +18 -0
  9. package/node_modules/@playwright/test/package.json +35 -0
  10. package/node_modules/@playwright/test/reporter.d.ts +17 -0
  11. package/node_modules/@playwright/test/reporter.js +17 -0
  12. package/node_modules/@playwright/test/reporter.mjs +17 -0
  13. package/node_modules/playwright/LICENSE +202 -0
  14. package/node_modules/playwright/NOTICE +5 -0
  15. package/node_modules/playwright/README.md +318 -0
  16. package/node_modules/playwright/ThirdPartyNotices.txt +14 -0
  17. package/node_modules/playwright/cli.js +19 -0
  18. package/node_modules/playwright/index.d.ts +17 -0
  19. package/node_modules/playwright/index.js +17 -0
  20. package/node_modules/playwright/index.mjs +18 -0
  21. package/node_modules/playwright/jsx-runtime.js +42 -0
  22. package/node_modules/playwright/jsx-runtime.mjs +21 -0
  23. package/node_modules/playwright/lib/agents/agentParser.js +89 -0
  24. package/node_modules/playwright/lib/agents/copilot-setup-steps.yml +34 -0
  25. package/node_modules/playwright/lib/agents/generateAgents.js +395 -0
  26. package/node_modules/playwright/lib/agents/playwright-test-coverage.prompt.md +31 -0
  27. package/node_modules/playwright/lib/agents/playwright-test-generate.prompt.md +8 -0
  28. package/node_modules/playwright/lib/agents/playwright-test-generator.agent.md +88 -0
  29. package/node_modules/playwright/lib/agents/playwright-test-heal.prompt.md +6 -0
  30. package/node_modules/playwright/lib/agents/playwright-test-healer.agent.md +56 -0
  31. package/node_modules/playwright/lib/agents/playwright-test-plan.prompt.md +9 -0
  32. package/node_modules/playwright/lib/agents/playwright-test-planner.agent.md +74 -0
  33. package/node_modules/playwright/lib/cli/reportActions.js +78 -0
  34. package/node_modules/playwright/lib/cli/testActions.js +214 -0
  35. package/node_modules/playwright/lib/common/index.js +2923 -0
  36. package/node_modules/playwright/lib/common/index.js.txt +34 -0
  37. package/node_modules/playwright/lib/errorContext.js +129 -0
  38. package/node_modules/playwright/lib/globals.js +58 -0
  39. package/node_modules/playwright/lib/index.js +815 -0
  40. package/node_modules/playwright/lib/isomorphic.js +260 -0
  41. package/node_modules/playwright/lib/isomorphic.js.txt +9 -0
  42. package/node_modules/playwright/lib/loader/loaderProcessEntry.js +34 -0
  43. package/node_modules/playwright/lib/loader/loaderProcessEntry.js.txt +9 -0
  44. package/node_modules/playwright/lib/matchers/expect.js +13490 -0
  45. package/node_modules/playwright/lib/matchers/expect.js.LICENSE +640 -0
  46. package/node_modules/playwright/lib/matchers/expect.js.txt +67 -0
  47. package/node_modules/playwright/lib/mcp/test/browserBackend.js +135 -0
  48. package/node_modules/playwright/lib/mcp/test/generatorTools.js +122 -0
  49. package/node_modules/playwright/lib/mcp/test/plannerTools.js +150 -0
  50. package/node_modules/playwright/lib/mcp/test/seed.js +82 -0
  51. package/node_modules/playwright/lib/mcp/test/streams.js +44 -0
  52. package/node_modules/playwright/lib/mcp/test/testBackend.js +99 -0
  53. package/node_modules/playwright/lib/mcp/test/testContext.js +306 -0
  54. package/node_modules/playwright/lib/mcp/test/testTool.js +30 -0
  55. package/node_modules/playwright/lib/mcp/test/testTools.js +98 -0
  56. package/node_modules/playwright/lib/package.js +47 -0
  57. package/node_modules/playwright/lib/program.js +241 -0
  58. package/node_modules/playwright/lib/runner/index.js +8527 -0
  59. package/node_modules/playwright/lib/runner/index.js.txt +61 -0
  60. package/node_modules/playwright/lib/transform/babelBundle.js +72274 -0
  61. package/node_modules/playwright/lib/transform/babelBundle.js.LICENSE +2384 -0
  62. package/node_modules/playwright/lib/transform/babelBundle.js.txt +325 -0
  63. package/node_modules/playwright/lib/transform/esmLoader.js +8054 -0
  64. package/node_modules/playwright/lib/transform/esmLoader.js.LICENSE +355 -0
  65. package/node_modules/playwright/lib/transform/esmLoader.js.txt +60 -0
  66. package/node_modules/playwright/lib/util.js +373 -0
  67. package/node_modules/playwright/lib/worker/workerProcessEntry.js +1861 -0
  68. package/node_modules/playwright/lib/worker/workerProcessEntry.js.txt +19 -0
  69. package/node_modules/playwright/package.json +55 -0
  70. package/node_modules/playwright/test.d.ts +18 -0
  71. package/node_modules/playwright/test.js +24 -0
  72. package/node_modules/playwright/test.mjs +35 -0
  73. package/node_modules/playwright/types/test.d.ts +11074 -0
  74. package/node_modules/playwright/types/testReporter.d.ts +950 -0
  75. package/node_modules/playwright-core/LICENSE +202 -0
  76. package/node_modules/playwright-core/NOTICE +5 -0
  77. package/node_modules/playwright-core/README.md +3 -0
  78. package/node_modules/playwright-core/ThirdPartyNotices.txt +13 -0
  79. package/node_modules/playwright-core/bin/install_media_pack.ps1 +5 -0
  80. package/node_modules/playwright-core/bin/install_webkit_wsl.ps1 +33 -0
  81. package/node_modules/playwright-core/bin/reinstall_chrome_beta_linux.sh +42 -0
  82. package/node_modules/playwright-core/bin/reinstall_chrome_beta_mac.sh +13 -0
  83. package/node_modules/playwright-core/bin/reinstall_chrome_beta_win.ps1 +24 -0
  84. package/node_modules/playwright-core/bin/reinstall_chrome_stable_linux.sh +42 -0
  85. package/node_modules/playwright-core/bin/reinstall_chrome_stable_mac.sh +12 -0
  86. package/node_modules/playwright-core/bin/reinstall_chrome_stable_win.ps1 +24 -0
  87. package/node_modules/playwright-core/bin/reinstall_msedge_beta_linux.sh +48 -0
  88. package/node_modules/playwright-core/bin/reinstall_msedge_beta_mac.sh +11 -0
  89. package/node_modules/playwright-core/bin/reinstall_msedge_beta_win.ps1 +23 -0
  90. package/node_modules/playwright-core/bin/reinstall_msedge_dev_linux.sh +48 -0
  91. package/node_modules/playwright-core/bin/reinstall_msedge_dev_mac.sh +11 -0
  92. package/node_modules/playwright-core/bin/reinstall_msedge_dev_win.ps1 +23 -0
  93. package/node_modules/playwright-core/bin/reinstall_msedge_stable_linux.sh +48 -0
  94. package/node_modules/playwright-core/bin/reinstall_msedge_stable_mac.sh +11 -0
  95. package/node_modules/playwright-core/bin/reinstall_msedge_stable_win.ps1 +24 -0
  96. package/node_modules/playwright-core/browsers.json +52 -0
  97. package/node_modules/playwright-core/cli.js +21 -0
  98. package/node_modules/playwright-core/index.d.ts +17 -0
  99. package/node_modules/playwright-core/index.js +17 -0
  100. package/node_modules/playwright-core/index.mjs +28 -0
  101. package/node_modules/playwright-core/lib/bootstrap.js +88 -0
  102. package/node_modules/playwright-core/lib/coreBundle.js +75813 -0
  103. package/node_modules/playwright-core/lib/entry/cliDaemon.js +5 -0
  104. package/node_modules/playwright-core/lib/entry/dashboardApp.js +3 -0
  105. package/node_modules/playwright-core/lib/entry/mcp.js +10 -0
  106. package/node_modules/playwright-core/lib/entry/oopBrowserDownload.js +3 -0
  107. package/node_modules/playwright-core/lib/package.js +50 -0
  108. package/node_modules/playwright-core/lib/server/chromium/appIcon.png +0 -0
  109. package/node_modules/playwright-core/lib/server/electron/loader.js +116 -0
  110. package/node_modules/playwright-core/lib/serverRegistry.js +1939 -0
  111. package/node_modules/playwright-core/lib/serverRegistry.js.LICENSE +65 -0
  112. package/node_modules/playwright-core/lib/tools/cli-client/channelSessions.js +141 -0
  113. package/node_modules/playwright-core/lib/tools/cli-client/cli.js +6 -0
  114. package/node_modules/playwright-core/lib/tools/cli-client/help.json +721 -0
  115. package/node_modules/playwright-core/lib/tools/cli-client/minimist.js +128 -0
  116. package/node_modules/playwright-core/lib/tools/cli-client/output.js +351 -0
  117. package/node_modules/playwright-core/lib/tools/cli-client/program.js +418 -0
  118. package/node_modules/playwright-core/lib/tools/cli-client/registry.js +180 -0
  119. package/node_modules/playwright-core/lib/tools/cli-client/session.js +259 -0
  120. package/node_modules/playwright-core/lib/tools/dashboard/appIcon.png +0 -0
  121. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/SKILL.md +425 -0
  122. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/element-attributes.md +23 -0
  123. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/playwright-tests.md +39 -0
  124. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/request-mocking.md +87 -0
  125. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/running-code.md +241 -0
  126. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/session-management.md +225 -0
  127. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/storage-state.md +275 -0
  128. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/test-generation.md +433 -0
  129. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/tracing.md +139 -0
  130. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/video-recording.md +143 -0
  131. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/SKILL.md +136 -0
  132. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/gallery-spec.md +144 -0
  133. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/migration.md +89 -0
  134. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/react.md +69 -0
  135. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/typing.md +173 -0
  136. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/vue.md +77 -0
  137. package/node_modules/playwright-core/lib/tools/skills/playwright-trace/SKILL.md +174 -0
  138. package/node_modules/playwright-core/lib/tools/utils/extension.js +112 -0
  139. package/node_modules/playwright-core/lib/tools/utils/socketConnection.js +108 -0
  140. package/node_modules/playwright-core/lib/utilsBundle.js +85357 -0
  141. package/node_modules/playwright-core/lib/utilsBundle.js.LICENSE +1890 -0
  142. package/node_modules/playwright-core/lib/vite/dashboard/assets/codeMirrorModule--QdMvsKi.css +1 -0
  143. package/node_modules/playwright-core/lib/vite/dashboard/assets/codeMirrorModule-CQ8RZGBm.js +32 -0
  144. package/node_modules/playwright-core/lib/vite/dashboard/assets/codicon-DCmgc-ay.ttf +0 -0
  145. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-1bWoP6pv.svg +1 -0
  146. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-beta-k3eOH_eK.svg +1 -0
  147. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-nightly-Cp5nfeDT.svg +1 -0
  148. package/node_modules/playwright-core/lib/vite/dashboard/assets/index-AwgwcYie.css +1 -0
  149. package/node_modules/playwright-core/lib/vite/dashboard/assets/index-hRvO4yU2.js +12 -0
  150. package/node_modules/playwright-core/lib/vite/dashboard/assets/safari-na3_-uQk.svg +1 -0
  151. package/node_modules/playwright-core/lib/vite/dashboard/index.html +29 -0
  152. package/node_modules/playwright-core/lib/vite/dashboard/playwright-logo.svg +24 -0
  153. package/node_modules/playwright-core/lib/vite/htmlReport/index.html +16 -0
  154. package/node_modules/playwright-core/lib/vite/htmlReport/report.css +2 -0
  155. package/node_modules/playwright-core/lib/vite/htmlReport/report.js +32 -0
  156. package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule--QdMvsKi.css +1 -0
  157. package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule-CVQWJZAA.js +32 -0
  158. package/node_modules/playwright-core/lib/vite/recorder/assets/codicon-DCmgc-ay.ttf +0 -0
  159. package/node_modules/playwright-core/lib/vite/recorder/assets/index-BZpYJZ-P.css +1 -0
  160. package/node_modules/playwright-core/lib/vite/recorder/assets/index-hrlLqLtq.js +129 -0
  161. package/node_modules/playwright-core/lib/vite/recorder/index.html +29 -0
  162. package/node_modules/playwright-core/lib/vite/recorder/playwright-logo.svg +9 -0
  163. package/node_modules/playwright-core/lib/vite/traceViewer/assets/codeMirrorModule-BbkfBe3n.js +32 -0
  164. package/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-Ds6CBOo0.js +182 -0
  165. package/node_modules/playwright-core/lib/vite/traceViewer/assets/urlMatch-L3liM589.js +1 -0
  166. package/node_modules/playwright-core/lib/vite/traceViewer/assets/xtermModule-DywYcAf8.js +7 -0
  167. package/node_modules/playwright-core/lib/vite/traceViewer/codeMirrorModule.-QdMvsKi.css +1 -0
  168. package/node_modules/playwright-core/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
  169. package/node_modules/playwright-core/lib/vite/traceViewer/defaultSettingsView.Bqk9acqE.css +1 -0
  170. package/node_modules/playwright-core/lib/vite/traceViewer/index.B4cLoZK3.js +1 -0
  171. package/node_modules/playwright-core/lib/vite/traceViewer/index.B_TqY17P.css +1 -0
  172. package/node_modules/playwright-core/lib/vite/traceViewer/index.html +44 -0
  173. package/node_modules/playwright-core/lib/vite/traceViewer/manifest.webmanifest +16 -0
  174. package/node_modules/playwright-core/lib/vite/traceViewer/playwright-logo.svg +9 -0
  175. package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.B_Jk1wbt.js +1 -0
  176. package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.html +10 -0
  177. package/node_modules/playwright-core/lib/vite/traceViewer/sw.bundle.js +4 -0
  178. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CU5KtEkS.js +5 -0
  179. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CyMfwkXJ.css +1 -0
  180. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +18 -0
  181. package/node_modules/playwright-core/lib/vite/traceViewer/xtermModule.kHJ-D0s7.css +1 -0
  182. package/node_modules/playwright-core/lib/webp_codec.LICENSE +173 -0
  183. package/node_modules/playwright-core/lib/webp_codec.wasm +0 -0
  184. package/node_modules/playwright-core/lib/xdg-open +1267 -0
  185. package/node_modules/playwright-core/package.json +34 -0
  186. package/node_modules/playwright-core/types/protocol.d.ts +24645 -0
  187. package/node_modules/playwright-core/types/structs.d.ts +52 -0
  188. package/node_modules/playwright-core/types/types.d.ts +26632 -0
  189. package/package.json +12 -2
  190. package/plugins/devflow-core/extensions/devflow-core.ts +431 -7
  191. package/plugins/devflow-core/runtime/hooks/hook_common.py +269 -0
  192. package/plugins/devflow-core/runtime/hooks/index_gate.py +29 -16
  193. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/acceptance_test_runner.py +407 -71
  194. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/advance_state.rb +51 -0
  195. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/approval_pins.py +433 -0
  196. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/approval_store.py +137 -0
  197. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/dsl_coverage.py +87 -0
  198. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/dsl_v1.py +318 -0
  199. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/environment_profile.py +134 -0
  200. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/execution_contract.rb +1 -0
  201. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/execution_surface.py +138 -0
  202. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/playwright_adapter.py +515 -0
  203. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/tc_hash.py +132 -0
  204. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/test_command_policy.py +102 -8
  205. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/validate_state.rb +13 -0
  206. package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +13 -34
  207. package/plugins/devflow-core/skills/workflow-pipeline/SKILL.md +3 -1
  208. package/plugins/devflow-core/skills/workflow-pipeline/references/pipeline-flow.md +68 -140
  209. package/plugins/devflow-core/skills/workflow-project-context/scripts/validate_initialization_database.py +1 -1
  210. package/plugins/devflow-implementation/skills/workflow-execute-phase/references/execute-phase.md +3 -1
  211. package/plugins/devflow-intel/skills/workflow-code-index/scripts/code_index.py +23 -4
  212. package/plugins/devflow-quality/runtime/playwright/devflow-test-dsl-v1.schema.json +872 -0
  213. package/plugins/devflow-quality/runtime/playwright/playwright.config.mjs +46 -0
  214. package/plugins/devflow-quality/runtime/playwright/reporter.mjs +311 -0
  215. package/plugins/devflow-quality/runtime/playwright/runner.spec.mjs +1308 -0
  216. package/plugins/devflow-quality/runtime/playwright/runtime-manifest.json +11 -0
  217. package/plugins/devflow-quality/skills/workflow-acceptance-test-design/SKILL.md +3 -0
  218. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/SKILL.md +71 -58
  219. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/api-mainflow-rules.md +20 -15
  220. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/codebase-discovery.md +3 -1
  221. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/intermediate-format.md +115 -192
  222. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/mainflow-selection.md +27 -23
  223. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/project-dsl-contract.md +78 -153
  224. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/ui-mainflow-rules.md +36 -83
  225. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/compile_dsl.py +497 -556
  226. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/export_legacy_testagent.py +647 -0
  227. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/normalize_case_payloads.py +10 -3
  228. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/validate_case_payloads.py +165 -275
  229. package/plugins/devflow-quality/skills/workflow-human-acceptance/SKILL.md +61 -0
  230. package/plugins/devflow-quality/skills/workflow-release-closeout/SKILL.md +4 -4
  231. package/plugins/devflow-quality/skills/workflow-run-acceptance-tests/SKILL.md +15 -9
  232. package/src/approval-store.ts +340 -0
  233. package/src/constants.ts +1 -1
  234. package/src/doctor.ts +259 -2
  235. package/src/initialization-store.ts +48 -1
  236. package/src/paths.ts +12 -1
  237. package/src/project-context.ts +24 -1
  238. package/templates/omp/hook-config.json +6 -0
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env python3
2
+ """RFC 8785 JSON Canonicalization Scheme (JCS) and the single tc_sha256 implementation.
3
+
4
+ tc_sha256 = lowercase hex SHA-256 of JCS(node.data). Generators, validators and
5
+ approval pins must call this module; the Runtime only echoes the value back.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import argparse
10
+ import hashlib
11
+ import json
12
+ import math
13
+ import sys
14
+ from typing import Any
15
+
16
+
17
+ _ESCAPES = {'"': '\\"', "\\": "\\\\", "\b": "\\b", "\f": "\\f", "\n": "\\n", "\r": "\\r", "\t": "\\t"}
18
+
19
+
20
+ def _string(value: str) -> str:
21
+ out = ['"']
22
+ for char in value:
23
+ if char in _ESCAPES:
24
+ out.append(_ESCAPES[char])
25
+ elif ord(char) < 0x20:
26
+ out.append(f"\\u{ord(char):04x}")
27
+ elif 0xD800 <= ord(char) <= 0xDFFF:
28
+ raise ValueError("lone surrogate cannot be canonicalized")
29
+ else:
30
+ out.append(char)
31
+ out.append('"')
32
+ return "".join(out)
33
+
34
+
35
+ def _number(value: int | float) -> str:
36
+ """ECMAScript Number.prototype.toString for an IEEE-754 double (RFC 8785 §3.2.2.3)."""
37
+ if isinstance(value, int):
38
+ converted = float(value)
39
+ if int(converted) != value:
40
+ raise ValueError(f"integer {value} is not exactly representable as an IEEE-754 double")
41
+ value = converted
42
+ if math.isnan(value) or math.isinf(value):
43
+ raise ValueError("NaN and Infinity are not valid JSON numbers")
44
+ if value == 0:
45
+ return "0"
46
+ sign = "-" if value < 0 else ""
47
+ text = repr(abs(value)) # shortest round-trip digits
48
+ mantissa, _, exponent = text.partition("e")
49
+ integer, _, fraction = mantissa.partition(".")
50
+ raw = integer + fraction
51
+ leading = len(raw) - len(raw.lstrip("0"))
52
+ digits = raw.lstrip("0").rstrip("0")
53
+ point = len(integer) + int(exponent or 0) - leading # value = 0.digits * 10**point
54
+ count = len(digits)
55
+ if count <= point <= 21:
56
+ body = digits + "0" * (point - count)
57
+ elif 0 < point <= 21:
58
+ body = digits[:point] + "." + digits[point:]
59
+ elif -6 < point <= 0:
60
+ body = "0." + "0" * (-point) + digits
61
+ else:
62
+ power = point - 1
63
+ suffix = f"e{'+' if power >= 0 else '-'}{abs(power)}"
64
+ body = (digits if count == 1 else digits[0] + "." + digits[1:]) + suffix
65
+ return sign + body
66
+
67
+
68
+ def _utf16_key(key: str) -> list[int]:
69
+ encoded = key.encode("utf-16-be")
70
+ return [int.from_bytes(encoded[index:index + 2], "big") for index in range(0, len(encoded), 2)]
71
+
72
+
73
+ def _serialize(value: Any, out: list[str]) -> None:
74
+ if value is None:
75
+ out.append("null")
76
+ elif value is True:
77
+ out.append("true")
78
+ elif value is False:
79
+ out.append("false")
80
+ elif isinstance(value, (int, float)):
81
+ out.append(_number(value))
82
+ elif isinstance(value, str):
83
+ out.append(_string(value))
84
+ elif isinstance(value, (list, tuple)):
85
+ out.append("[")
86
+ for index, item in enumerate(value):
87
+ if index:
88
+ out.append(",")
89
+ _serialize(item, out)
90
+ out.append("]")
91
+ elif isinstance(value, dict):
92
+ if not all(isinstance(key, str) for key in value):
93
+ raise ValueError("object keys must be strings")
94
+ out.append("{")
95
+ for index, key in enumerate(sorted(value, key=_utf16_key)):
96
+ if index:
97
+ out.append(",")
98
+ out.append(_string(key))
99
+ out.append(":")
100
+ _serialize(value[key], out)
101
+ out.append("}")
102
+ else:
103
+ raise ValueError(f"unsupported JSON value type: {type(value).__name__}")
104
+
105
+
106
+ def canonicalize(value: Any) -> bytes:
107
+ out: list[str] = []
108
+ _serialize(value, out)
109
+ return "".join(out).encode("utf-8")
110
+
111
+
112
+ def jcs_sha256(value: Any) -> str:
113
+ return hashlib.sha256(canonicalize(value)).hexdigest()
114
+
115
+
116
+ def tc_sha256(data: Any) -> str:
117
+ if not isinstance(data, dict):
118
+ raise ValueError("TC data must be an object")
119
+ return jcs_sha256(data)
120
+
121
+
122
+ def main() -> int:
123
+ parser = argparse.ArgumentParser(description="Print tc_sha256 (JCS SHA-256) of a JSON document read from a file or stdin.")
124
+ parser.add_argument("path", nargs="?")
125
+ args = parser.parse_args()
126
+ text = open(args.path, encoding="utf-8").read() if args.path else sys.stdin.read()
127
+ print(jcs_sha256(json.loads(text)))
128
+ return 0
129
+
130
+
131
+ if __name__ == "__main__":
132
+ raise SystemExit(main())
@@ -6,18 +6,25 @@ from pathlib import Path
6
6
  from typing import Any
7
7
  import json
8
8
  import os
9
+ import re
9
10
  import sqlite3
10
11
 
12
+ from approval_store import devflow_home
11
13
 
12
- def database_toolchain(root: Path) -> list[str] | None:
14
+
15
+ PACKAGE_RUNNERS = {"npm", "pnpm", "yarn"}
16
+ RUNTIME_MARKERS = ("devflow-quality/runtime/playwright", "runtime-manifest.json", "runner.spec.mjs", "devflow-test-dsl-v1.schema.json")
17
+ MARKDOWN_ROW_RE = re.compile(r"^\|(.+)\|\s*$")
18
+
19
+
20
+ def database_toolchain_facts(root: Path) -> list[dict[str, Any]] | None:
13
21
  manifest_path = root / ".devflow" / "project.json"
14
22
  if not manifest_path.is_file():
15
23
  return None
16
24
  try:
17
25
  project_id = json.loads(manifest_path.read_text(encoding="utf-8"))["projectId"]
18
- data_home = Path(os.environ.get("DEVFLOW_HOME", Path.home() / ".devflow-pi"))
19
- database = data_home / "projects" / project_id / "control.db"
20
- connection = sqlite3.connect(f"file:{database}?mode=ro", uri=True)
26
+ database = devflow_home() / "projects" / project_id / "control.db"
27
+ connection = sqlite3.connect(f"{database.as_uri()}?mode=ro", uri=True)
21
28
  connection.row_factory = sqlite3.Row
22
29
  try:
23
30
  authority = connection.execute("SELECT authority FROM authority_state WHERE project_id=?", (project_id,)).fetchone()
@@ -32,13 +39,87 @@ def database_toolchain(root: Path) -> list[str] | None:
32
39
  ORDER BY c.revision DESC""",
33
40
  (project_id, str(root.resolve())),
34
41
  ).fetchall()
35
- return [str(json.loads(row["value_json"]).get("command", "")) for row in rows]
42
+ facts = [json.loads(row["value_json"]) for row in rows]
43
+ return [fact for fact in facts if isinstance(fact, dict)]
36
44
  finally:
37
45
  connection.close()
38
46
  except (OSError, KeyError, ValueError, json.JSONDecodeError, sqlite3.Error):
39
47
  return None
40
48
 
41
49
 
50
+ def database_toolchain(root: Path) -> list[str] | None:
51
+ facts = database_toolchain_facts(root)
52
+ return None if facts is None else [str(fact.get("command", "")) for fact in facts]
53
+
54
+
55
+ def _root_directory(value: Any) -> bool:
56
+ return value in (None, "", ".", "./")
57
+
58
+
59
+ def registered_scripts(root: Path, facts: list[dict[str, Any]] | None) -> tuple[set[str], str]:
60
+ """Package script names Core may run from the project root, and their source.
61
+
62
+ Toolchain facts (package-json@1) carry {name, command, workingDirectory};
63
+ the compatibility toolchain.md projects them as a 名称/工作目录 table. A
64
+ legacy free-form toolchain.md has no script names, so only then fall back
65
+ to the root package.json scripts.
66
+ """
67
+ if facts is not None:
68
+ return {str(fact["name"]) for fact in facts if isinstance(fact.get("name"), str) and "command" in fact and _root_directory(fact.get("workingDirectory"))}, "toolchain facts"
69
+ names: set[str] = set()
70
+ toolchain = root / ".devflow/planning" / "toolchain.md"
71
+ header: list[str] | None = None
72
+ if toolchain.is_file():
73
+ for line in toolchain.read_text(encoding="utf-8").splitlines():
74
+ match = MARKDOWN_ROW_RE.match(line.strip())
75
+ if not match:
76
+ header = None
77
+ continue
78
+ cells = [cell.strip() for cell in match.group(1).split("|")]
79
+ if header is None:
80
+ header = cells
81
+ elif "名称" in header and "命令" in header and not set("".join(cells)) <= set("-: "):
82
+ row = dict(zip(header, cells))
83
+ if row.get("名称") not in (None, "", "undefined") and row.get("命令") not in (None, "", "undefined") and _root_directory(row.get("工作目录")):
84
+ names.add(row["名称"])
85
+ if names:
86
+ return names, "toolchain.md"
87
+ try:
88
+ scripts = json.loads((root / "package.json").read_text(encoding="utf-8")).get("scripts", {})
89
+ return ({name for name in scripts if isinstance(name, str)} if isinstance(scripts, dict) else set()), "package.json"
90
+ except (OSError, ValueError, AttributeError):
91
+ return set(), "package.json"
92
+
93
+
94
+ def package_script(argv: list[str]) -> tuple[str | None, str | None]:
95
+ """Return (script name, error) for npm/pnpm/yarn test|run argv."""
96
+ if argv[1] == "test":
97
+ rest, name = argv[2:], "test"
98
+ else:
99
+ if len(argv) < 3 or argv[2].startswith("-"):
100
+ return None, f"{Path(argv[0]).name} run must name a script immediately after 'run' (options before the script name are rejected)"
101
+ rest, name = argv[3:], argv[2]
102
+ if rest and rest[0] != "--":
103
+ return None, f"{Path(argv[0]).name} {argv[1]} extra arguments must follow '--'"
104
+ return name, None
105
+
106
+
107
+ def reserved_reference(root: Path, argv: list[str]) -> str | None:
108
+ runtime_dirs: list[str] = []
109
+ try:
110
+ from dsl_v1 import runtime_dir_candidates
111
+ runtime_dirs = [str(path) for path in runtime_dir_candidates()]
112
+ except ImportError:
113
+ pass
114
+ for token in argv:
115
+ if "DEVFLOW_" in token:
116
+ return "test command must not reference DEVFLOW_ reserved variables"
117
+ normalized = token.replace("\\", "/")
118
+ if any(marker in normalized for marker in RUNTIME_MARKERS) or any(directory and directory in token for directory in runtime_dirs):
119
+ return "test command must not reference the Devflow Playwright Runtime; use the devflow_playwright adapter"
120
+ return None
121
+
122
+
42
123
  def runner_marker(argv: list[str]) -> str | None:
43
124
  if not argv:
44
125
  return None
@@ -73,18 +154,31 @@ def runner_marker(argv: list[str]) -> str | None:
73
154
  def validate_test_command(root: Path, argv: Any) -> str | None:
74
155
  if not isinstance(argv, list) or not argv or not all(isinstance(token, str) and token and "\x00" not in token for token in argv):
75
156
  return "test command must be a non-empty argv array"
157
+ reserved = reserved_reference(root, argv)
158
+ if reserved:
159
+ return reserved
76
160
  marker = runner_marker(argv)
77
161
  if marker is None:
162
+ if Path(argv[0]).name in PACKAGE_RUNNERS and len(argv) >= 2 and argv[1].startswith("-"):
163
+ return f"{Path(argv[0]).name} global options before the command are rejected (they can switch to another package)"
78
164
  return "test command runner is not in the Core allowlist"
79
- commands = database_toolchain(root)
80
- if commands is None:
165
+ facts = database_toolchain_facts(root)
166
+ if facts is None:
81
167
  toolchain = root / ".devflow/planning" / "toolchain.md"
82
168
  if not toolchain.is_file():
83
169
  return "initialized toolchain context (database or .devflow/planning/toolchain.md compatibility projection) is required before Core can execute a test command"
84
170
  content = toolchain.read_text(encoding="utf-8").lower()
85
171
  else:
86
- content = "\n".join(commands).lower()
172
+ content = "\n".join(str(fact.get("command", "")) for fact in facts).lower()
87
173
  aliases = {"pytest": ("pytest",), "unittest": ("unittest",), "bun test": ("bun test",), "npm": ("npm",), "pnpm": ("pnpm",), "yarn": ("yarn",), "go test": ("go test",), "newman": ("newman",), "playwright": ("playwright",), "vitest": ("vitest",)}
174
+ if marker in PACKAGE_RUNNERS:
175
+ script, error = package_script(argv)
176
+ if error:
177
+ return error
178
+ names, source = registered_scripts(root, facts)
179
+ if script not in names:
180
+ return f"package script '{script}' is not registered in the initialization toolchain ({source})"
181
+ return None
88
182
  if not any(alias in content for alias in aliases[marker]):
89
183
  return f"test runner '{marker}' was not discovered in the initialization toolchain snapshot"
90
184
  return None
@@ -44,10 +44,23 @@ module WorkflowStateValidator
44
44
  workflow_step_unknown
45
45
  phase_ownership_conflict
46
46
  ].freeze
47
+ # Acceptance-execution trust failures are never downgraded by soft gates.
48
+ ACCEPTANCE_HARD_VALIDATION_CODES = %w[
49
+ acceptance_results_not_passed
50
+ execution_surface_mismatch
51
+ approval_invalid
52
+ human_result_unapproved
53
+ dsl_not_approved
54
+ environment_profile_not_approved
55
+ runtime_integrity_error
56
+ acceptance_tests_not_passed
57
+ acceptance_tests_empty
58
+ ].freeze
47
59
 
48
60
  def self.hard_validation_code?(code)
49
61
  value = code.to_s
50
62
  return true if HARD_VALIDATION_CODES.include?(value)
63
+ return true if ACCEPTANCE_HARD_VALIDATION_CODES.include?(value)
51
64
  return true if value.start_with?("artifact_registry_", "parallel_", "PARALLEL_")
52
65
  return true if value.start_with?("duplicate_", "unknown_", "missing_tracked_step")
53
66
  return true if value.start_with?("step_in_", "completed_", "terminal_", "non_completed_")
@@ -1019,46 +1019,23 @@ steps:
1019
1019
  type: code-review-report
1020
1020
  required: true
1021
1021
 
1022
- - id: generate-mainflow-cases
1022
+ - id: human-acceptance
1023
1023
  order: 86
1024
- label: Generate mainflow cases
1025
- skill: workflow-generate-mainflow-cases
1024
+ label: Human acceptance and developer handoff
1025
+ skill: workflow-human-acceptance
1026
1026
  engine_evidence_gate: enforced
1027
1027
  depends_on:
1028
- - execute
1028
+ - code-review
1029
1029
  inputs:
1030
- - ".devflow/planning/STATE.md"
1031
- - ".devflow/planning/navigation/INDEX.md"
1032
- - ".devflow/context/spec/index.md"
1033
- - ".devflow/planning/requirements/baseline.md"
1034
- - ".devflow/planning/features/{feature}/功能点梳理.md"
1035
- - ".devflow/planning/features/{feature}/UI-SPEC.md"
1036
- - ".devflow/planning/features/{feature}/前端技术方案.md"
1037
- - ".devflow/planning/features/{feature}/后端技术方案.md"
1038
- - ".devflow/planning/features/{feature}/变更清单.md"
1039
- - ".devflow/planning/features/{feature}/PROGRESS.md"
1040
1030
  - ".devflow/planning/requirements/{feature}/tests.json"
1031
+ - ".devflow/planning/phases/{phase}/REVIEW.md"
1032
+ - ".devflow/planning/features/{feature}/验收测试设计.md"
1041
1033
  outputs:
1042
- - path: ".devflow/planning/generated-cases/{feature}/codebase-discovery.json"
1043
- type: mainflow-codebase-discovery
1044
- required: true
1045
- - path: ".devflow/planning/generated-cases/{feature}/source-map.md"
1046
- type: mainflow-source-map
1047
- required: true
1048
- - path: ".devflow/planning/generated-cases/{feature}/mainflow-analysis.md"
1049
- type: mainflow-analysis
1034
+ - path: ".devflow/planning/test-runs/{feature}/human-acceptance-results.json"
1035
+ type: human-acceptance-results
1050
1036
  required: true
1051
- - path: ".devflow/planning/generated-cases/{feature}/case-descriptions.json"
1052
- type: mainflow-case-descriptions
1053
- required: true
1054
- - path: ".devflow/planning/generated-cases/{feature}/case-import-payloads.json"
1055
- type: mainflow-case-import-payloads
1056
- required: true
1057
- - path: ".devflow/planning/generated-cases/{feature}/validation-report.md"
1058
- type: mainflow-case-validation
1059
- required: true
1060
- - path: ".devflow/planning/phases/{phase}/MAINFLOW-CASES.md"
1061
- type: mainflow-cases-summary
1037
+ - path: ".devflow/planning/test-runs/{feature}/developer-handoff.md"
1038
+ type: developer-acceptance-handoff
1062
1039
  required: true
1063
1040
 
1064
1041
  - id: run-acceptance-tests
@@ -1067,12 +1044,14 @@ steps:
1067
1044
  skill: workflow-run-acceptance-tests
1068
1045
  engine_evidence_gate: enforced
1069
1046
  depends_on:
1070
- - code-review
1047
+ - human-acceptance
1071
1048
  inputs:
1072
1049
  - ".devflow/planning/requirements/{feature}/tests.json"
1073
1050
  - ".devflow/planning/code-index/index.sqlite"
1074
1051
  - ".devflow/planning/code-index/relations.jsonl"
1075
1052
  - ".devflow/planning/phases/{phase}/REVIEW.md"
1053
+ - ".devflow/planning/test-runs/{feature}/human-acceptance-results.json"
1054
+ - ".devflow/planning/test-runs/{feature}/developer-handoff.md"
1076
1055
  outputs:
1077
1056
  - path: ".devflow/planning/features/{feature}/acceptance-test-bindings.json"
1078
1057
  type: acceptance-test-bindings
@@ -49,7 +49,7 @@ pipeline 本身不包含执行规则——所有门禁、CP 协议、失败分
49
49
  | 80 | execute | 代码执行 |
50
50
  | 84 | code-index-refresh | 刷新机器代码索引并审查 |
51
51
  | 85 | code-review | 代码审查(完成标准验证) |
52
- | 86 | generate-mainflow-cases | 主流程自动化用例生成 |
52
+ | 86 | human-acceptance | 人工验收与开发者同步 |
53
53
  | 88 | run-acceptance-tests | 冻结 TC 验收执行 |
54
54
  | 100 | release-closeout | 验收通过后的版本收口与里程碑归档 |
55
55
 
@@ -60,6 +60,8 @@ pipeline 本身不包含执行规则——所有门禁、CP 协议、失败分
60
60
 
61
61
  双轨制原则:API 契约是分叉前的共同事实,`integration-verify` 是合并前的强门禁。单轨只产出局部轨道文档,不代表完整交付。
62
62
 
63
+ `workflow-generate-mainflow-cases` 不是独立 workflow step,而是 `run-acceptance-tests` 绑定阶段的组成部分:对执行面为 `ui` / `api_flow` 且绑定为 `automated` 的 TC,必须先生成 v1 DSL 并经 `devflow_approval` 批准执行计划,否则该 TC 保持 blocked。人工 TC 结果同样只经 `human_result` 批准计入聚合门禁。
64
+
63
65
  如果提供了需求文档但未指定功能名,从文档标题自动提取功能名。
64
66
 
65
67
  ## 1. 需求入口前置路由
@@ -1,154 +1,82 @@
1
1
  # 研发交付全链路流程
2
2
 
3
+ `feature-development.yaml` 是步骤拓扑、checkpoint 和失败分支的规范来源。本文档只做人类可读投影;两者不一致时,以 workflow YAML 及 `.devflow/planning/STATE.md` 为准。
4
+
5
+ ## 规范链路
6
+
7
+ ```text
8
+ workflow-pipeline
9
+ → devflow_state(action="inspect")
10
+ → 缺少项目上下文时执行 workflow-project-context
11
+ → requirement-triage
12
+ → requirement-wayfinder
13
+ → domain-modeling
14
+ → requirement-feasibility-review
15
+ → requirement-baseline
16
+ → CP-1:需求基线确认
17
+ → wireframe-proposal
18
+ → wireframe-validate
19
+ → wireframe-render
20
+ → wireframe-review
21
+ → CP-WIREFRAME:线框确认
22
+ → api-contract
23
+ → CP-API:API 契约确认
24
+ → architecture-feasibility
25
+ → 双轨设计
26
+ ├─ Track A: backend-tech-spec → api-call-guide
27
+ └─ Track B: ui-spec → feature-breakdown → frontend-tech-spec → api-supplement
28
+ → integration-verify
29
+ → CP-2:双轨合并方案确认
30
+ → acceptance-test-design(编码前产生候选 TC-*)
31
+ → change-plan(任务绑定候选 TC-*)
32
+ → CP-3:确认变更计划并冻结验收套件
33
+ → phase-structure
34
+ → execute(代码与 TDD 证据)
35
+ → code-index-refresh
36
+ → code-review
37
+ → human-acceptance(人工 TC、问题反馈和开发者同步)
38
+ → run-acceptance-tests(执行冻结 TC-*)
39
+ → CP-4:验收结果确认
40
+ → release-closeout
41
+ → 完成
3
42
  ```
4
- workflow-pipeline 启动
5
- │
6
- ▼
7
- ┌─────────────────────────────────────┐
8
- │ Step 0: 断点检测 │
9
- │ 读取 STATE.md + inspector 恢复进度 │
10
- └─────────────────────────────────────┘
11
- │
12
- ▼
13
- ┌─────────────────────────────────────┐
14
- │ Step 1: 项目初始化 │
15
- │ workflow-project-context │
16
- │ 输出: .devflow/planning/PROJECT.md │
17
- └─────────────────────────────────────┘
18
- │
19
- ▼
20
- ┌─────────────────────────────────────┐
21
- │ Step 2: 需求完善 │
22
- │ workflow-requirement-baseline │
23
- │ 输出: .devflow/planning/requirements/baseline.md │
24
- │ 门禁: 冲突/复用/过度工程/替代方案已拍板 │
25
- └──────────────┬──────────────────────┘
26
- │ ↑
27
- ▼ │ 用户拒绝
28
- ┌─────────────────────────────────────┐
29
- │ 🔴 CP-1: 需求基线人工确认 │
30
- │ ask 强制暂停 │
31
- │ 确认: FP/BR/BC 准确完整 │
32
- └──────────────┬──────────────────────┘
33
- │ 用户确认
34
- ▼
35
- ┌─────────────────────────────────────┐
36
- │ Step 3: 三文档并行生成 │
37
- │ │
38
- │ ┌──────────┐ ┌──────────┐ ┌──────┐ │
39
- │ │ feature- │ │frontend- │ │back- │ │
40
- │ │breakdown │ │tech-spec │ │end- │ │
41
- │ │ │ │ │ │tech- │ │
42
- │ │ 功能点 │ │ 前端方案 │ │spec │ │
43
- │ │ 梳理.md │ │ .md │ │后端 │ │
44
- │ └──────────┘ └──────────┘ └──────┘ │
45
- └─────────────────────────────────────┘
46
- │ ↑
47
- ▼ │ 用户拒绝
48
- ┌─────────────────────────────────────┐
49
- │ 🟡 CP-2: 技术方案人工确认 │
50
- │ ask 强制暂停 │
51
- │ --no-review 可跳过 │
52
- │ 确认: DB/API/架构决策合理可行 │
53
- └──────────────┬──────────────────────┘
54
- │ 用户确认
55
- ▼
56
- ┌─────────────────────────────────────┐
57
- │ Step 4: 变更清单 │
58
- │ workflow-change-plan │
59
- │ 输入: 前端+后端技术方案 │
60
- │ 输出: .devflow/planning/features/{功能名}/变更清单.md │
61
- └──────────────┬──────────────────────┘
62
- │ ↑
63
- ▼ │ 用户拒绝
64
- ┌─────────────────────────────────────┐
65
- │ 🔴 CP-3: 变更清单人工确认 │
66
- │ ask 强制暂停 │
67
- │ 不可跳过 │
68
- │ 确认: DDL/代码/上线步骤可执行 │
69
- └──────────────┬──────────────────────┘
70
- │ 用户确认
71
- ▼
72
- ┌─────────────────────────────────────┐
73
- │ Step 4.5: Phase 结构初始化 │
74
- │ phase-init │
75
- │ 创建 ROADMAP.md + .devflow/planning/phases/ │
76
- │ 桥接 workflow 产物到 phase 结构 │
77
- └─────────────────────────────────────┘
78
- │
79
- ▼
80
- ┌─────────────────────────────────────┐
81
- │ Step 5: 代码执行 │
82
- │ workflow-execute-phase │
83
- │ Wave1: DDL → Wave2: Domain/Service │
84
- │ Wave3: API → Wave4: 前端 → Wave5: 联调│
85
- │ 输出: SUMMARY.md 写入 phases/ 目录 │
86
- └──────────────┬──────────────────────┘
87
- │ ↑
88
- ▼ │ 修复后重试
89
- ┌─────────────────────────────────────┐
90
- │ Step 5.5: 代码索引刷新 │
91
- │ workflow-code-index │
92
- │ 刷新 Symbol/Relation/Call Graph │
93
- │ 输出 .devflow/planning/code-index/ + AUDIT │
94
- └──────────────┬──────────────────────┘
95
- │ ↑
96
- ▼ │ 索引审查失败
97
- ┌─────────────────────────────────────┐
98
- │ Step 5.6: 代码审查 + 主流程用例 │
99
- │ code-review + generate-mainflow-cases│
100
- │ 基于 code-index + 源码 evidence │
101
- └──────────────┬──────────────────────┘
102
- │ ↑
103
- ▼ │ 审查失败/用例生成失败
104
- ┌─────────────────────────────────────┐
105
- │ Step 6: 需求验收测试执行 │
106
- │ workflow-run-acceptance-tests │
107
- │ 执行冻结的 TC-* │
108
- │ 失败/阻塞 → 修复 → 重跑 │
109
- └──────────────┬──────────────────────┘
110
- │ ↑
111
- ▼ │ 用户拒绝
112
- ┌─────────────────────────────────────┐
113
- │ 🔴 CP-4: 验收结果确认 │
114
- │ ask 强制暂停 │
115
- │ 不可跳过 │
116
- │ 确认: TC-* 全部通过,允许版本收口 │
117
- └──────────────┬──────────────────────┘
118
- │ 用户确认
119
- ▼
120
- ┌─────────────────────────────────────┐
121
- │ Step 7: 版本收口与里程碑归档 │
122
- │ workflow-release-closeout │
123
- │ 校验 TC/code-index → 归档 → 更新状态 │
124
- └─────────────────────────────────────┘
125
- │
126
- ▼
127
- 完成 ✓
43
+
44
+ `workflow-generate-mainflow-cases` 不参与独立排序,而是 `run-acceptance-tests` 绑定阶段的组成部分:automated 的 ui / api_flow TC 需要先生成 v1 DSL 并批准执行计划。人工验收结果(经 `human_result` 批准)会与自动执行结果聚合,验收失败是硬门禁。
45
+
46
+ ## 双轨与 Checkpoint 规则
47
+
48
+ - 双轨设计支持时最多并行两个步骤;不支持时按 workflow 声明顺序串行降级。
49
+ - `CP-1`、`CP-WIREFRAME`、`CP-API`、`CP-2`、`CP-3` 和 `CP-4` 都会暂停链路,等待用户审查当前产物。
50
+ - `--no-review` 仅保留参数位,不会跳过 `CP-2`;`integration-verify` Merge Gate 不可跳过。
51
+ - 用户拒绝或提出修改意见时,流程保持在当前步骤,不会自动推进。
52
+ - 单轨 `--track A` / `--track B` 只产出对应轨道文档,不会越过 `integration-verify` 进入完整实施。
53
+
54
+ ## 失败分支
55
+
56
+ `run-acceptance-tests` 失败、阻塞或验收结果被拒绝时,进入 `acceptance-failed-remediation`:
57
+
58
+ ```text
59
+ 验收失败 → 诊断/修复 → 刷新代码索引 → 重跑原冻结 TC-* → CP-4
128
60
  ```
129
61
 
130
62
  ## 断点续接
131
63
 
132
- 每次启动时,workflow-pipeline 通过 `devflow_state(action="inspect")` 读取规范状态文件 `.devflow/planning/STATE.md`,由 inspector 返回当前动作和下一节点:
64
+ Pipeline 通过 `devflow_state(action="inspect")` 读取 `.devflow/planning/STATE.md`,并根据 inspector 返回的 `action` 路由到下一步、当前步骤、checkpoint、失败分支或并行窗口。
133
65
 
134
- ```
135
- 1. 校验 `.devflow/planning/STATE.md` 的 YAML front matter、workflow 配置和 artifact registry
136
- 2. 根据 inspector 返回的 `action` 路由到下一步、当前步骤、确认、失败分支或并行窗口
137
- 3. 如果控制面缺失或校验失败,报告阻塞并提示运行 `init_workflow.rb --write`、`init_state.rb --write` 修复
138
- 4. `.devflow/planning/pipeline-state.md` 已废弃,不作为恢复状态来源
139
- ```
66
+ 1. 校验 `STATE.md` 的 YAML front matter、workflow 配置和 artifact registry。
67
+ 2. 如果控制面缺失或校验失败,报告阻塞并通过专用 Core 恢复链路处理。
68
+ 3. `.devflow/planning/pipeline-state.md` 已废弃,不作为恢复状态来源。
140
69
 
141
- ## 简化流程门禁
70
+ ## 需求基线门禁
142
71
 
143
- 只有单文件/单方法/单文档、无跨层影响、无未拍板需求决策时,才允许向用户提议简化流程。用户未明确同意时,继续完整 pipeline。
72
+ `requirement-baseline` 完成后必须检查:
144
73
 
145
- ## 需求拍板门禁
74
+ - `.devflow/planning/requirements/baseline.md` 中的待确认事项、反向审视与下游输入契约。
75
+ - `.devflow/planning/requirements/baseline.meta.json` 的 `review_status` 必须为 `passed`。
76
+ - `blocking_pending_count`、`critical_image_missing_count`、`challenge_pending_count` 和 `code_reality_missing_count` 必须全为 `0`。
146
77
 
147
- Step 2 之后必须检查 `.devflow/planning/requirements/baseline.md`:
78
+ 影响 scope、语义、归属、兼容性或实现成本的未确认项是阻塞项,不得将其当作已确认范围传入技术方案或变更清单。
148
79
 
149
- - `待确认事项`
150
- - `反向审视与用户拍板`
151
- - `下游输入契约`
152
- - `.devflow/planning/requirements/baseline.meta.json` 中 `review_status` 必须为 `passed`,且 `blocking_pending_count`、`critical_image_missing_count`、`challenge_pending_count`、`code_reality_missing_count` 必须全为 0
80
+ ## 简化流程
153
81
 
154
- 影响 scope、语义、归属、兼容性或实现成本的未确认项是阻塞项。不能把它们传入技术方案或变更清单当成已确认范围。
82
+ 只有单文件、单方法或单文档变更,且无跨层影响、无未拍板需求决策时,才能向用户提议简化流程。用户未明确同意时,继续完整 Pipeline。
@@ -32,7 +32,7 @@ def validate(database: Path, project_id: str, workspace_id: str | None = None, r
32
32
  connection.row_factory = sqlite3.Row
33
33
  try:
34
34
  version = connection.execute("SELECT version FROM schema_meta LIMIT 1").fetchone()
35
- if not version or version["version"] != 2:
35
+ if not version or version["version"] != 3:
36
36
  errors.append(f"unsupported initialization schema: {version['version'] if version else 'missing'}")
37
37
  if not connection.execute("SELECT 1 FROM projects WHERE id=?", (project_id,)).fetchone():
38
38
  errors.append("project identity is not registered in the database")
@@ -63,12 +63,14 @@
63
63
  ```text
64
64
  execute-phase
65
65
  → code-review
66
- → workflow-generate-mainflow-cases(如适用)
66
+ → workflow-human-acceptance
67
67
  → workflow-run-acceptance-tests
68
68
  → CP-4 验收结果确认
69
69
  → workflow-release-closeout
70
70
  ```
71
71
 
72
+ `workflow-generate-mainflow-cases` 不是独立主链步骤,而是 `workflow-run-acceptance-tests` 绑定阶段的组成部分:automated 的 ui / api_flow TC 需要先生成 v1 DSL 并批准执行计划才能执行。
73
+
72
74
  `workflow-run-acceptance-tests` 只消费冻结的 `TC-*`。每个已确认验收条件都必须覆盖;异常、边界、权限、兼容和架构风险用例不能被主流程用例替代。验收结果保存在 `.devflow/planning/test-runs/{feature}/acceptance-results.json`。
73
75
 
74
76
  只有当所有冻结 `TC-*` 已执行且通过、无 `failed`/`blocked`,且代码索引审计通过时,才允许进入 `workflow-release-closeout`。版本收口负责生成项目自己的里程碑收口记录并更新项目状态;它不生成旧式人工验收或独立验证报告。