@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.
- package/README.md +4 -4
- package/node_modules/@playwright/test/LICENSE +202 -0
- package/node_modules/@playwright/test/NOTICE +5 -0
- package/node_modules/@playwright/test/README.md +318 -0
- package/node_modules/@playwright/test/cli.js +19 -0
- package/node_modules/@playwright/test/index.d.ts +18 -0
- package/node_modules/@playwright/test/index.js +17 -0
- package/node_modules/@playwright/test/index.mjs +18 -0
- package/node_modules/@playwright/test/package.json +35 -0
- package/node_modules/@playwright/test/reporter.d.ts +17 -0
- package/node_modules/@playwright/test/reporter.js +17 -0
- package/node_modules/@playwright/test/reporter.mjs +17 -0
- package/node_modules/playwright/LICENSE +202 -0
- package/node_modules/playwright/NOTICE +5 -0
- package/node_modules/playwright/README.md +318 -0
- package/node_modules/playwright/ThirdPartyNotices.txt +14 -0
- package/node_modules/playwright/cli.js +19 -0
- package/node_modules/playwright/index.d.ts +17 -0
- package/node_modules/playwright/index.js +17 -0
- package/node_modules/playwright/index.mjs +18 -0
- package/node_modules/playwright/jsx-runtime.js +42 -0
- package/node_modules/playwright/jsx-runtime.mjs +21 -0
- package/node_modules/playwright/lib/agents/agentParser.js +89 -0
- package/node_modules/playwright/lib/agents/copilot-setup-steps.yml +34 -0
- package/node_modules/playwright/lib/agents/generateAgents.js +395 -0
- package/node_modules/playwright/lib/agents/playwright-test-coverage.prompt.md +31 -0
- package/node_modules/playwright/lib/agents/playwright-test-generate.prompt.md +8 -0
- package/node_modules/playwright/lib/agents/playwright-test-generator.agent.md +88 -0
- package/node_modules/playwright/lib/agents/playwright-test-heal.prompt.md +6 -0
- package/node_modules/playwright/lib/agents/playwright-test-healer.agent.md +56 -0
- package/node_modules/playwright/lib/agents/playwright-test-plan.prompt.md +9 -0
- package/node_modules/playwright/lib/agents/playwright-test-planner.agent.md +74 -0
- package/node_modules/playwright/lib/cli/reportActions.js +78 -0
- package/node_modules/playwright/lib/cli/testActions.js +214 -0
- package/node_modules/playwright/lib/common/index.js +2923 -0
- package/node_modules/playwright/lib/common/index.js.txt +34 -0
- package/node_modules/playwright/lib/errorContext.js +129 -0
- package/node_modules/playwright/lib/globals.js +58 -0
- package/node_modules/playwright/lib/index.js +815 -0
- package/node_modules/playwright/lib/isomorphic.js +260 -0
- package/node_modules/playwright/lib/isomorphic.js.txt +9 -0
- package/node_modules/playwright/lib/loader/loaderProcessEntry.js +34 -0
- package/node_modules/playwright/lib/loader/loaderProcessEntry.js.txt +9 -0
- package/node_modules/playwright/lib/matchers/expect.js +13490 -0
- package/node_modules/playwright/lib/matchers/expect.js.LICENSE +640 -0
- package/node_modules/playwright/lib/matchers/expect.js.txt +67 -0
- package/node_modules/playwright/lib/mcp/test/browserBackend.js +135 -0
- package/node_modules/playwright/lib/mcp/test/generatorTools.js +122 -0
- package/node_modules/playwright/lib/mcp/test/plannerTools.js +150 -0
- package/node_modules/playwright/lib/mcp/test/seed.js +82 -0
- package/node_modules/playwright/lib/mcp/test/streams.js +44 -0
- package/node_modules/playwright/lib/mcp/test/testBackend.js +99 -0
- package/node_modules/playwright/lib/mcp/test/testContext.js +306 -0
- package/node_modules/playwright/lib/mcp/test/testTool.js +30 -0
- package/node_modules/playwright/lib/mcp/test/testTools.js +98 -0
- package/node_modules/playwright/lib/package.js +47 -0
- package/node_modules/playwright/lib/program.js +241 -0
- package/node_modules/playwright/lib/runner/index.js +8527 -0
- package/node_modules/playwright/lib/runner/index.js.txt +61 -0
- package/node_modules/playwright/lib/transform/babelBundle.js +72274 -0
- package/node_modules/playwright/lib/transform/babelBundle.js.LICENSE +2384 -0
- package/node_modules/playwright/lib/transform/babelBundle.js.txt +325 -0
- package/node_modules/playwright/lib/transform/esmLoader.js +8054 -0
- package/node_modules/playwright/lib/transform/esmLoader.js.LICENSE +355 -0
- package/node_modules/playwright/lib/transform/esmLoader.js.txt +60 -0
- package/node_modules/playwright/lib/util.js +373 -0
- package/node_modules/playwright/lib/worker/workerProcessEntry.js +1861 -0
- package/node_modules/playwright/lib/worker/workerProcessEntry.js.txt +19 -0
- package/node_modules/playwright/package.json +55 -0
- package/node_modules/playwright/test.d.ts +18 -0
- package/node_modules/playwright/test.js +24 -0
- package/node_modules/playwright/test.mjs +35 -0
- package/node_modules/playwright/types/test.d.ts +11074 -0
- package/node_modules/playwright/types/testReporter.d.ts +950 -0
- package/node_modules/playwright-core/LICENSE +202 -0
- package/node_modules/playwright-core/NOTICE +5 -0
- package/node_modules/playwright-core/README.md +3 -0
- package/node_modules/playwright-core/ThirdPartyNotices.txt +13 -0
- package/node_modules/playwright-core/bin/install_media_pack.ps1 +5 -0
- package/node_modules/playwright-core/bin/install_webkit_wsl.ps1 +33 -0
- package/node_modules/playwright-core/bin/reinstall_chrome_beta_linux.sh +42 -0
- package/node_modules/playwright-core/bin/reinstall_chrome_beta_mac.sh +13 -0
- package/node_modules/playwright-core/bin/reinstall_chrome_beta_win.ps1 +24 -0
- package/node_modules/playwright-core/bin/reinstall_chrome_stable_linux.sh +42 -0
- package/node_modules/playwright-core/bin/reinstall_chrome_stable_mac.sh +12 -0
- package/node_modules/playwright-core/bin/reinstall_chrome_stable_win.ps1 +24 -0
- package/node_modules/playwright-core/bin/reinstall_msedge_beta_linux.sh +48 -0
- package/node_modules/playwright-core/bin/reinstall_msedge_beta_mac.sh +11 -0
- package/node_modules/playwright-core/bin/reinstall_msedge_beta_win.ps1 +23 -0
- package/node_modules/playwright-core/bin/reinstall_msedge_dev_linux.sh +48 -0
- package/node_modules/playwright-core/bin/reinstall_msedge_dev_mac.sh +11 -0
- package/node_modules/playwright-core/bin/reinstall_msedge_dev_win.ps1 +23 -0
- package/node_modules/playwright-core/bin/reinstall_msedge_stable_linux.sh +48 -0
- package/node_modules/playwright-core/bin/reinstall_msedge_stable_mac.sh +11 -0
- package/node_modules/playwright-core/bin/reinstall_msedge_stable_win.ps1 +24 -0
- package/node_modules/playwright-core/browsers.json +52 -0
- package/node_modules/playwright-core/cli.js +21 -0
- package/node_modules/playwright-core/index.d.ts +17 -0
- package/node_modules/playwright-core/index.js +17 -0
- package/node_modules/playwright-core/index.mjs +28 -0
- package/node_modules/playwright-core/lib/bootstrap.js +88 -0
- package/node_modules/playwright-core/lib/coreBundle.js +75813 -0
- package/node_modules/playwright-core/lib/entry/cliDaemon.js +5 -0
- package/node_modules/playwright-core/lib/entry/dashboardApp.js +3 -0
- package/node_modules/playwright-core/lib/entry/mcp.js +10 -0
- package/node_modules/playwright-core/lib/entry/oopBrowserDownload.js +3 -0
- package/node_modules/playwright-core/lib/package.js +50 -0
- package/node_modules/playwright-core/lib/server/chromium/appIcon.png +0 -0
- package/node_modules/playwright-core/lib/server/electron/loader.js +116 -0
- package/node_modules/playwright-core/lib/serverRegistry.js +1939 -0
- package/node_modules/playwright-core/lib/serverRegistry.js.LICENSE +65 -0
- package/node_modules/playwright-core/lib/tools/cli-client/channelSessions.js +141 -0
- package/node_modules/playwright-core/lib/tools/cli-client/cli.js +6 -0
- package/node_modules/playwright-core/lib/tools/cli-client/help.json +721 -0
- package/node_modules/playwright-core/lib/tools/cli-client/minimist.js +128 -0
- package/node_modules/playwright-core/lib/tools/cli-client/output.js +351 -0
- package/node_modules/playwright-core/lib/tools/cli-client/program.js +418 -0
- package/node_modules/playwright-core/lib/tools/cli-client/registry.js +180 -0
- package/node_modules/playwright-core/lib/tools/cli-client/session.js +259 -0
- package/node_modules/playwright-core/lib/tools/dashboard/appIcon.png +0 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-cli/SKILL.md +425 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/element-attributes.md +23 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/playwright-tests.md +39 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/request-mocking.md +87 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/running-code.md +241 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/session-management.md +225 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/storage-state.md +275 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/test-generation.md +433 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/tracing.md +139 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/video-recording.md +143 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/SKILL.md +136 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/gallery-spec.md +144 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/migration.md +89 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/react.md +69 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/typing.md +173 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/vue.md +77 -0
- package/node_modules/playwright-core/lib/tools/skills/playwright-trace/SKILL.md +174 -0
- package/node_modules/playwright-core/lib/tools/utils/extension.js +112 -0
- package/node_modules/playwright-core/lib/tools/utils/socketConnection.js +108 -0
- package/node_modules/playwright-core/lib/utilsBundle.js +85357 -0
- package/node_modules/playwright-core/lib/utilsBundle.js.LICENSE +1890 -0
- package/node_modules/playwright-core/lib/vite/dashboard/assets/codeMirrorModule--QdMvsKi.css +1 -0
- package/node_modules/playwright-core/lib/vite/dashboard/assets/codeMirrorModule-CQ8RZGBm.js +32 -0
- package/node_modules/playwright-core/lib/vite/dashboard/assets/codicon-DCmgc-ay.ttf +0 -0
- package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-1bWoP6pv.svg +1 -0
- package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-beta-k3eOH_eK.svg +1 -0
- package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-nightly-Cp5nfeDT.svg +1 -0
- package/node_modules/playwright-core/lib/vite/dashboard/assets/index-AwgwcYie.css +1 -0
- package/node_modules/playwright-core/lib/vite/dashboard/assets/index-hRvO4yU2.js +12 -0
- package/node_modules/playwright-core/lib/vite/dashboard/assets/safari-na3_-uQk.svg +1 -0
- package/node_modules/playwright-core/lib/vite/dashboard/index.html +29 -0
- package/node_modules/playwright-core/lib/vite/dashboard/playwright-logo.svg +24 -0
- package/node_modules/playwright-core/lib/vite/htmlReport/index.html +16 -0
- package/node_modules/playwright-core/lib/vite/htmlReport/report.css +2 -0
- package/node_modules/playwright-core/lib/vite/htmlReport/report.js +32 -0
- package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule--QdMvsKi.css +1 -0
- package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule-CVQWJZAA.js +32 -0
- package/node_modules/playwright-core/lib/vite/recorder/assets/codicon-DCmgc-ay.ttf +0 -0
- package/node_modules/playwright-core/lib/vite/recorder/assets/index-BZpYJZ-P.css +1 -0
- package/node_modules/playwright-core/lib/vite/recorder/assets/index-hrlLqLtq.js +129 -0
- package/node_modules/playwright-core/lib/vite/recorder/index.html +29 -0
- package/node_modules/playwright-core/lib/vite/recorder/playwright-logo.svg +9 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/assets/codeMirrorModule-BbkfBe3n.js +32 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-Ds6CBOo0.js +182 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/assets/urlMatch-L3liM589.js +1 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/assets/xtermModule-DywYcAf8.js +7 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/codeMirrorModule.-QdMvsKi.css +1 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/defaultSettingsView.Bqk9acqE.css +1 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/index.B4cLoZK3.js +1 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/index.B_TqY17P.css +1 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/index.html +44 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/manifest.webmanifest +16 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/playwright-logo.svg +9 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.B_Jk1wbt.js +1 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.html +10 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/sw.bundle.js +4 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CU5KtEkS.js +5 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CyMfwkXJ.css +1 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +18 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/xtermModule.kHJ-D0s7.css +1 -0
- package/node_modules/playwright-core/lib/webp_codec.LICENSE +173 -0
- package/node_modules/playwright-core/lib/webp_codec.wasm +0 -0
- package/node_modules/playwright-core/lib/xdg-open +1267 -0
- package/node_modules/playwright-core/package.json +34 -0
- package/node_modules/playwright-core/types/protocol.d.ts +24645 -0
- package/node_modules/playwright-core/types/structs.d.ts +52 -0
- package/node_modules/playwright-core/types/types.d.ts +26632 -0
- package/package.json +12 -2
- package/plugins/devflow-core/extensions/devflow-core.ts +431 -7
- package/plugins/devflow-core/runtime/hooks/hook_common.py +269 -0
- package/plugins/devflow-core/runtime/hooks/index_gate.py +29 -16
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/acceptance_test_runner.py +407 -71
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/advance_state.rb +51 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/approval_pins.py +433 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/approval_store.py +137 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/dsl_coverage.py +87 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/dsl_v1.py +318 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/environment_profile.py +134 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/execution_contract.rb +1 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/execution_surface.py +138 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/playwright_adapter.py +515 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/tc_hash.py +132 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/test_command_policy.py +102 -8
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/validate_state.rb +13 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +13 -34
- package/plugins/devflow-core/skills/workflow-pipeline/SKILL.md +3 -1
- package/plugins/devflow-core/skills/workflow-pipeline/references/pipeline-flow.md +68 -140
- package/plugins/devflow-core/skills/workflow-project-context/scripts/validate_initialization_database.py +1 -1
- package/plugins/devflow-implementation/skills/workflow-execute-phase/references/execute-phase.md +3 -1
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/code_index.py +23 -4
- package/plugins/devflow-quality/runtime/playwright/devflow-test-dsl-v1.schema.json +872 -0
- package/plugins/devflow-quality/runtime/playwright/playwright.config.mjs +46 -0
- package/plugins/devflow-quality/runtime/playwright/reporter.mjs +311 -0
- package/plugins/devflow-quality/runtime/playwright/runner.spec.mjs +1308 -0
- package/plugins/devflow-quality/runtime/playwright/runtime-manifest.json +11 -0
- package/plugins/devflow-quality/skills/workflow-acceptance-test-design/SKILL.md +3 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/SKILL.md +71 -58
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/api-mainflow-rules.md +20 -15
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/codebase-discovery.md +3 -1
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/intermediate-format.md +115 -192
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/mainflow-selection.md +27 -23
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/project-dsl-contract.md +78 -153
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/ui-mainflow-rules.md +36 -83
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/compile_dsl.py +497 -556
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/export_legacy_testagent.py +647 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/normalize_case_payloads.py +10 -3
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/validate_case_payloads.py +165 -275
- package/plugins/devflow-quality/skills/workflow-human-acceptance/SKILL.md +61 -0
- package/plugins/devflow-quality/skills/workflow-release-closeout/SKILL.md +4 -4
- package/plugins/devflow-quality/skills/workflow-run-acceptance-tests/SKILL.md +15 -9
- package/src/approval-store.ts +340 -0
- package/src/constants.ts +1 -1
- package/src/doctor.ts +259 -2
- package/src/initialization-store.ts +48 -1
- package/src/paths.ts +12 -1
- package/src/project-context.ts +24 -1
- 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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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
|
-
|
|
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
|
-
|
|
80
|
-
if
|
|
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(
|
|
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_")
|
package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml
CHANGED
|
@@ -1019,46 +1019,23 @@ steps:
|
|
|
1019
1019
|
type: code-review-report
|
|
1020
1020
|
required: true
|
|
1021
1021
|
|
|
1022
|
-
- id:
|
|
1022
|
+
- id: human-acceptance
|
|
1023
1023
|
order: 86
|
|
1024
|
-
label:
|
|
1025
|
-
skill: workflow-
|
|
1024
|
+
label: Human acceptance and developer handoff
|
|
1025
|
+
skill: workflow-human-acceptance
|
|
1026
1026
|
engine_evidence_gate: enforced
|
|
1027
1027
|
depends_on:
|
|
1028
|
-
-
|
|
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/
|
|
1043
|
-
type:
|
|
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/
|
|
1052
|
-
type:
|
|
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
|
-
-
|
|
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 |
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
64
|
+
Pipeline 通过 `devflow_state(action="inspect")` 读取 `.devflow/planning/STATE.md`,并根据 inspector 返回的 `action` 路由到下一步、当前步骤、checkpoint、失败分支或并行窗口。
|
|
133
65
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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"] !=
|
|
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")
|
package/plugins/devflow-implementation/skills/workflow-execute-phase/references/execute-phase.md
CHANGED
|
@@ -63,12 +63,14 @@
|
|
|
63
63
|
```text
|
|
64
64
|
execute-phase
|
|
65
65
|
→ code-review
|
|
66
|
-
→ workflow-
|
|
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`。版本收口负责生成项目自己的里程碑收口记录并更新项目状态;它不生成旧式人工验收或独立验证报告。
|