@guanlin4924/devflow-pi 0.1.94 → 0.1.96
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 +34 -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 +13 -2
- package/plugins/devflow-core/extensions/devflow-core.ts +432 -7
- package/plugins/devflow-core/runtime/hooks/hook_common.py +514 -0
- package/plugins/devflow-core/runtime/hooks/index_gate.py +47 -16
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/acceptance_test_runner.py +488 -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_draft.py +53 -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/extensions/devflow-intel.ts +1 -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 +63 -0
- package/plugins/devflow-quality/skills/workflow-release-closeout/SKILL.md +4 -4
- package/plugins/devflow-quality/skills/workflow-run-acceptance-tests/SKILL.md +17 -9
- package/src/approval-store.ts +340 -0
- package/src/cli.ts +10 -0
- package/src/constants.ts +1 -1
- package/src/doctor.ts +268 -2
- package/src/initialization-store.ts +48 -1
- package/src/mcp/auth.ts +103 -0
- package/src/mcp/core.ts +102 -0
- package/src/mcp/server.ts +193 -0
- package/src/mcp/types.ts +5 -0
- package/src/paths.ts +12 -1
- package/src/project-context.ts +24 -1
- package/templates/omp/hook-config.json +6 -0
|
@@ -1,190 +1,115 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Runtime DSL Contract (`devflow-test-dsl/v1`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`compile_dsl.py` 为每个冻结的自动化 `ui` / `api_flow` TC 写一个 DSL 文件:
|
|
4
4
|
|
|
5
|
-
```
|
|
6
|
-
{
|
|
7
|
-
"metadata": {
|
|
8
|
-
"feature": "Feature name",
|
|
9
|
-
"phase": "01-Feature",
|
|
10
|
-
"generated_by": "workflow-generate-mainflow-cases",
|
|
11
|
-
"project_id": 1
|
|
12
|
-
},
|
|
13
|
-
"cases": [
|
|
14
|
-
{
|
|
15
|
-
"project_id": 1,
|
|
16
|
-
"name": "Case name",
|
|
17
|
-
"description": "Positive mainflow purpose and traceability.",
|
|
18
|
-
"tags": ["api-mainflow"],
|
|
19
|
-
"dsl_json": {
|
|
20
|
-
"name": "Case name",
|
|
21
|
-
"description": "Same behavior summary.",
|
|
22
|
-
"tags": ["api-mainflow"],
|
|
23
|
-
"variables": {},
|
|
24
|
-
"steps": []
|
|
25
|
-
},
|
|
26
|
-
"source_evidence": [
|
|
27
|
-
{
|
|
28
|
-
"path": ".devflow/planning/features/Feature/后端技术方案.md",
|
|
29
|
-
"line": 120,
|
|
30
|
-
"reason": "API contract source"
|
|
31
|
-
}
|
|
32
|
-
]
|
|
33
|
-
}
|
|
34
|
-
]
|
|
35
|
-
}
|
|
5
|
+
```text
|
|
6
|
+
.devflow/planning/generated-cases/{feature}/TC-xxxx.json
|
|
36
7
|
```
|
|
37
8
|
|
|
38
|
-
|
|
9
|
+
DSL 是纯数据,由 Devflow Playwright Runtime 解释执行,Core 用同一份 Schema 校验。权威定义:`plugins/devflow-quality/runtime/playwright/devflow-test-dsl-v1.schema.json`(JSON Schema 2020-12,`additionalProperties: false`);Python 侧实现是 Core `dsl_v1.py`(Schema + 语义)与 `dsl_coverage.py`(`covers` 结构覆盖)。AI 不直接写这个文件,而是写 `case-descriptions.json`(`intermediate-format.md`),由编译器生成。
|
|
39
10
|
|
|
40
|
-
|
|
41
|
-
- `name`: non-empty string.
|
|
42
|
-
- `description`: optional string.
|
|
43
|
-
- `dsl_json`: object.
|
|
44
|
-
- `tags`: exactly one of `["api-mainflow"]` or `["ui-mainflow"]` unless the case is intentionally mixed UI flow with API setup; mixed UI flows still use `["ui-mainflow"]`.
|
|
11
|
+
## 文件与门禁的关系
|
|
45
12
|
|
|
46
|
-
|
|
13
|
+
- 一 TC 一文件,文件名必须是 `<tc_id>.json`,与 `acceptance-test-bindings.json` 里 `devflow_playwright` 绑定的 `dsl_file` 对应;
|
|
14
|
+
- `tc_sha256` = 冻结 TC `data` 的 JCS SHA-256(Core `tc_hash.py` 计算,编译器不接受 AI 提供的值);TC 变化后 DSL 必须重新编译;
|
|
15
|
+
- `dsl_sha256` = 该文件**原始字节**的 SHA-256。用户在 `/devflow` → “待审批”中批准的是这个具体文件:文件任何变化都会使对应 TC 的 `execution_plan` 批准失效;
|
|
16
|
+
- 没有有效 `execution_plan` 批准的 DSL 永远 `blocked(dsl_not_approved)`,不会执行、不会进入收口;
|
|
17
|
+
- 校验入口是整个 `generated-cases/{feature}` 目录(`validate_case_payloads.py`),目录里只有 `TC-xxxx.json` 被当作 DSL。`case-descriptions.json`、`codebase-discovery.json`、`source-map.md` 等是辅助文件,不是 DSL。
|
|
47
18
|
|
|
48
|
-
##
|
|
19
|
+
## 顶层结构
|
|
49
20
|
|
|
50
|
-
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"schema_version": "devflow-test-dsl/v1",
|
|
24
|
+
"tc_id": "TC-0001",
|
|
25
|
+
"tc_sha256": "<64 hex>",
|
|
26
|
+
"name": "登录后显示欢迎语",
|
|
27
|
+
"variables": {
|
|
28
|
+
"user": { "value": "qa-user" },
|
|
29
|
+
"password": { "secret": "QA_PASSWORD" }
|
|
30
|
+
},
|
|
31
|
+
"data": { "namespace": "${execution_id}", "setup": [], "cleanup": [] },
|
|
32
|
+
"steps": [ ]
|
|
33
|
+
}
|
|
34
|
+
```
|
|
51
35
|
|
|
52
|
-
-
|
|
53
|
-
- `
|
|
54
|
-
- `
|
|
55
|
-
- `
|
|
56
|
-
- `
|
|
57
|
-
- `depends_on`
|
|
58
|
-
- `assertions`
|
|
59
|
-
- `timeout_ms`
|
|
60
|
-
- `on_failure`
|
|
36
|
+
- 上述 7 个顶层键全部必填,不允许其他键;
|
|
37
|
+
- `variables`:`{ "value": <string|number|boolean>, "sensitive"?: bool }` 或 `{ "secret": "<ENV_KEY>" }`(运行时取自已批准 profile 的 `secret_env`,永远敏感)。不允许重定义内置变量 `execution_id`/`namespace`;
|
|
38
|
+
- `data.namespace` 必填,缺省由编译器写成 `${execution_id}`;`owner`、`accounts[]`、`repeatable` 可选;
|
|
39
|
+
- `data.setup[]` / `data.cleanup[]` **只允许 API 步骤**;`cleanup` 步骤不得带 `covers`;
|
|
40
|
+
- `steps[]`:1–200 个步骤,按序执行;任一步失败即停止主流程,cleanup 仍会执行,cleanup 失败使结果变为 blocked。
|
|
61
41
|
|
|
62
|
-
|
|
42
|
+
## 步骤
|
|
63
43
|
|
|
64
|
-
|
|
44
|
+
公共键:`id`(`[A-Za-z0-9][A-Za-z0-9_-]{0,63}`,全 DSL 唯一)、`driver`(`ui`|`api`)、`action`、`covers`、`timeout_ms`(100–600000)。
|
|
65
45
|
|
|
66
|
-
|
|
67
|
-
- `target`: non-empty unless `strategy.mode` is `ai_only`
|
|
46
|
+
### UI(`driver: "ui"`)
|
|
68
47
|
|
|
69
|
-
|
|
48
|
+
| action | 键 |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `goto` | `url` |
|
|
51
|
+
| `click`、`check`、`uncheck`、`assert_visible` | `target` |
|
|
52
|
+
| `fill` | `target`、`value`(字符串) |
|
|
53
|
+
| `select` | `target`、`value`(字符串或字符串数组) |
|
|
54
|
+
| `wait_for` | `target`、`state`(`visible`\|`hidden`\|`attached`\|`detached`);只做条件等待,无固定 sleep |
|
|
55
|
+
| `assert_text` | `target`、`match`(`exact`\|`contains`)、`expected`,可选 `normalize_whitespace`(缺省 true)、`case_sensitive`(缺省 true) |
|
|
56
|
+
| `assert_url` | `match`、`expected` |
|
|
57
|
+
| `screenshot` | 可选 `name`(`[A-Za-z0-9_-]{1,64}`)、`full_page` |
|
|
58
|
+
|
|
59
|
+
**不存在**:`hover`、`assert_url_contains`、`assert_any_visible`、固定等待、`evaluate_js`、任意脚本、`strategy`、`prompt`、`params`、`depends_on`、`on_failure`。
|
|
70
60
|
|
|
71
|
-
|
|
61
|
+
### target(六选一,strict:多于一个匹配即失败)
|
|
72
62
|
|
|
73
63
|
```json
|
|
74
|
-
{ "
|
|
64
|
+
{ "testid": "login-submit" }
|
|
65
|
+
{ "role": "button", "name": "登录", "exact": true }
|
|
66
|
+
{ "label": "用户名", "exact": true }
|
|
67
|
+
{ "placeholder": "请输入名称", "exact": true }
|
|
68
|
+
{ "text": "欢迎", "exact": true }
|
|
69
|
+
{ "css": "[data-qa='welcome']" }
|
|
75
70
|
```
|
|
76
71
|
|
|
77
|
-
|
|
72
|
+
`testid` 与 `css` 不带 `exact`。`xpath`、`near_text`、`by/value` 形式、AI 视觉定位均不存在。
|
|
78
73
|
|
|
79
|
-
|
|
80
|
-
{ "strategy": { "mode": "ai_only" } }
|
|
81
|
-
```
|
|
74
|
+
### API(`driver: "api"`, `action: "request"`)
|
|
82
75
|
|
|
83
76
|
```json
|
|
84
77
|
{
|
|
85
|
-
"id": "
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"prompt": "检查页面是否出现'操作成功'的提示消息,确认编辑操作已成功完成",
|
|
92
|
-
"depends_on": ["s05"],
|
|
93
|
-
"timeout_ms": 15000
|
|
78
|
+
"id": "a02", "driver": "api", "action": "request", "method": "GET",
|
|
79
|
+
"url": "/api/orders/${order_id}", "query": { "verbose": true },
|
|
80
|
+
"expect_status": 200,
|
|
81
|
+
"assertions": [ { "pointer": "/data/status", "op": "equals", "value": "created" } ],
|
|
82
|
+
"extract": { "order_id": { "pointer": "/data/id" } },
|
|
83
|
+
"covers": { "oracle": true }
|
|
94
84
|
}
|
|
95
85
|
```
|
|
96
86
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
`
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
| 场景 | 选哪个 key | 示例 | 原因 |
|
|
106
|
-
|---|---|---|---|
|
|
107
|
-
| 页面唯一按钮/菜单/tab | `label` + `exact` | `{"label": "新增项目库", "exact": true}` | 文本最稳定,不受CSS重构影响 |
|
|
108
|
-
| 表格行操作按钮(每行重复) | `css` 精确定位 | `{"css": "tr:nth-child(2) .edit-btn"}` | 必须定位到具体行,"编辑"不唯一 |
|
|
109
|
-
| 对话框底部确定/取消 | `css` 限定作用域 | `{"css": ".el-dialog__footer .el-button--primary"}` | 防止dialog外也有同名按钮 |
|
|
110
|
-
| 输入框(有唯一placeholder) | `placeholder` | `{"placeholder": "请输入后台名称"}` | 语义清晰,自动scope内唯一 |
|
|
111
|
-
| 表单项旁边控件 | `near_text` | `{"near_text": "后台名称"}` | label文本定位,控件自动匹配 |
|
|
112
|
-
| ARIA友好的按钮/组件 | `role` + `name` | `{"role": "button", "name": "确定"}` | 无障碍属性,可访问性最好 |
|
|
113
|
-
| 无他法定位时 | `xpath` | `{"xpath": "//button[text()='确定']"}` | 最后的结构化手段 |
|
|
114
|
-
| 以上均不稳定 | `ai_only` strategy | 不走target,用AI视觉识别 | 放弃结构化,交AI处理 |
|
|
87
|
+
- `method`:`GET`/`POST`/`PUT`/`PATCH`/`DELETE`;`url` 以 `/` 开头相对 profile 的 `api_base_url`(缺省 `base_url`),绝对 URL 的 origin 须在 profile `api_origins` 中;不自动跟随重定向;
|
|
88
|
+
- `headers`、`query`(标量)、`json`(任意 JSON,字符串叶子可引用变量);
|
|
89
|
+
- `expect_status`(100–599);`assertions[]` 的 `op` 为 `equals`/`not_equals`/`contains`/`exists`/`not_exists`,`pointer` 为 JSON Pointer,`exists`/`not_exists` 不带 `value`,其余必须带;
|
|
90
|
+
- `extract`:`{ name: { pointer, sensitive? } }`,之后的步骤可用 `${name}`,不得重定义已存在变量;
|
|
91
|
+
- `retry: { max_attempts: 2–5, on: [connection_error|timeout|rate_limited] }`,只重试传输失败;POST/PATCH 需 `idempotent: true`;默认不重试;
|
|
92
|
+
- 通过页面同一 BrowserContext 发送,与 UI 登录态共享 cookie;
|
|
93
|
+
- `Authorization`、`Cookie`、`X-Api-Key` 等敏感请求头只能由 secret/sensitive 变量拼成,如 `"Bearer ${auth_token}"`。
|
|
115
94
|
|
|
116
|
-
|
|
95
|
+
变量引用 `${name}` 必须已定义(内置、`variables`、先前 `extract`)。不得出现凭据字面量:真实密码、token、cookie 用 `{ "secret": ... }` 变量,`validate_case_payloads.py` 会拒绝形似密钥的字面值。
|
|
117
96
|
|
|
118
|
-
|
|
119
|
-
2. **再看作用域**:对话框内用 `css` 限定 `.el-dialog__footer .el-button--primary`
|
|
120
|
-
3. **input/textarea 优先用** `placeholder`
|
|
121
|
-
4. **表单项控件用** `near_text`
|
|
122
|
-
5. **都不行再用** `xpath` **或** `ai_only`
|
|
123
|
-
|
|
124
|
-
#### Correct Format Examples
|
|
97
|
+
## covers
|
|
125
98
|
|
|
126
99
|
```json
|
|
127
|
-
|
|
128
|
-
{ "label": "新增项目库", "exact": true }
|
|
129
|
-
|
|
130
|
-
// 表格行按钮 → css 精确定位
|
|
131
|
-
{ "css": "tr:nth-child(2) .edit-btn" }
|
|
132
|
-
|
|
133
|
-
// 对话框确定按钮 → css 限定作用域
|
|
134
|
-
{ "css": ".el-dialog__footer .el-button--primary" }
|
|
135
|
-
|
|
136
|
-
// 输入框 → placeholder
|
|
137
|
-
{ "placeholder": "请输入后台名称" }
|
|
100
|
+
{ "covers": { "preconditions": [1], "steps": [2, 3], "oracle": true } }
|
|
138
101
|
```
|
|
139
102
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
**API steps** (`driver: "api"`) use `assertions[]` with these types:
|
|
143
|
-
|
|
144
|
-
| Type | Behavior |
|
|
145
|
-
|---|---|
|
|
146
|
-
| `equals` | `actual == expected` |
|
|
147
|
-
| `status_code` | HTTP 状态码 |
|
|
148
|
-
| `contains` | `expected in actual` |
|
|
149
|
-
| `json_path_equals` | JSONPath 取值相等 |
|
|
150
|
-
| `json_path_exists` | JSONPath 路径存在 |
|
|
151
|
-
| `regex` | 正则匹配 |
|
|
152
|
-
| `not_equals` / `not_contains` / `greater_than` / `less_than` / `in` / `not_in` / `is_empty` / `is_not_empty` |
|
|
153
|
-
|
|
154
|
-
**`"text"` is NOT a valid assertion type.** It will raise `ValueError: unsupported assertion type: text`.
|
|
103
|
+
下标从 1 开始,指向冻结 TC 的 `preconditions[]` / `steps[]`。Core 硬校验:每个前置条件和步骤都被至少一个步骤覆盖;`oracle` 被至少一个非弱断言的主流程断言步骤覆盖(`wait_for`、`screenshot` 不是断言;弱断言指仅断言静态入口元素可见、断言自己刚操作的元素、仅检查 2xx 无响应体断言)。这只发现遗漏和明显弱断言,语义是否充分由独立 AI 审查(建议性)与人工批准(权威)判断。
|
|
155
104
|
|
|
156
|
-
|
|
105
|
+
## 校验命令
|
|
157
106
|
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
{
|
|
161
|
-
"id": "s06",
|
|
162
|
-
"name": "验证操作成功",
|
|
163
|
-
"driver": "ui",
|
|
164
|
-
"action": "act",
|
|
165
|
-
"target": { "label": "操作成功" },
|
|
166
|
-
"strategy": { "mode": "ai_only" },
|
|
167
|
-
"prompt": "检查页面是否出现'操作成功'的提示消息,确认操作已成功完成",
|
|
168
|
-
"depends_on": ["s05"],
|
|
169
|
-
"timeout_ms": 15000
|
|
170
|
-
}
|
|
107
|
+
```text
|
|
108
|
+
devflow_mainflow(action="validate", args=[".devflow/planning/generated-cases/{feature}", "--suite", ".devflow/planning/requirements/{feature}/tests.json", "--output", ".devflow/planning/generated-cases/{feature}/validation-report.md"])
|
|
171
109
|
```
|
|
172
110
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
For API steps, assertion example:
|
|
111
|
+
校验是纯数据操作,不 import、不执行被测项目的任何代码(`--discovery` 已废弃并被忽略)。检查项:Schema、语义(唯一 ID、变量作用域、重试安全、敏感头)、密钥字面量、`tc_id` 存在于冻结 suite、文件名与 `tc_id` 一致、`tc_sha256` 与冻结 TC 一致、`covers` 结构覆盖、每个 TC 至多一个 DSL。目录内缺少 DSL 的自动化 `ui`/`api_flow` TC 会以警告列出(它们会在门禁被 `dsl_not_approved` 阻断)。
|
|
176
112
|
|
|
177
|
-
|
|
178
|
-
{
|
|
179
|
-
"id": "api-login",
|
|
180
|
-
"driver": "api",
|
|
181
|
-
"action": "post",
|
|
182
|
-
"params": { "url": "${base_url}/auth/login", "json": { "userid": "${userid}", "password": "${password}" } },
|
|
183
|
-
"assertions": [
|
|
184
|
-
{ "type": "status_code", "expected": 200 },
|
|
185
|
-
{ "type": "json_path_exists", "path": "headers.X-Jwt-Token" }
|
|
186
|
-
]
|
|
187
|
-
}
|
|
188
|
-
```
|
|
113
|
+
## 旧 TestAgent 导入格式
|
|
189
114
|
|
|
190
|
-
|
|
115
|
+
旧的 TestAgent 导入载荷(`project_id` + `dsl_json`、`strategy`/Midscene、`params`、`depends_on`、xpath/near_text 等)**不是** Runtime DSL,不参与门禁,本 Skill 不再教授。仅当开发者明确要求 TestAgent 导入文件时,才运行 `scripts/export_legacy_testagent.py`;其产物不能绑定到 `devflow_playwright`、不能被批准为执行计划、不能计入验收结果,也不得写成 `TC-xxxx.json`。`case-import-payloads.json` 这个名字只属于该 legacy 导出,绝不是 Runtime DSL 产物。
|
|
@@ -1,110 +1,63 @@
|
|
|
1
1
|
# UI Mainflow Rules
|
|
2
2
|
|
|
3
|
-
UI
|
|
3
|
+
UI 用例把冻结的、自动化的 `execution_surface: ui` TC(含存量推导为 `ui` 的 `page` TC)落成确定性的 `devflow-test-dsl/v1`。AI 写 `case-descriptions.json`(格式见 `intermediate-format.md`),`compile_dsl.py` 生成 `TC-xxxx.json`(形状见 `project-dsl-contract.md`)。
|
|
4
4
|
|
|
5
5
|
## Hard Rule: Source-Backed Terminology
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**locator 与断言里的界面文本必须逐字来自源码。** 不得编造、翻译、猜测或“改进”。源码写“查询”就写“查询”,不写“搜索”“查找”。
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
9
|
+
- 模板/JSX:`<el-button>查询</el-button>` → `role:button:查询` 或 `text:查询`
|
|
10
|
+
- placeholder:`placeholder="请输入名称"` → `placeholder:请输入名称`
|
|
11
|
+
- `data-testid`:`data-testid="save-btn"` → `testid:save-btn`
|
|
12
|
+
- 提示/标题文案:`<el-dialog title="新增项目">` → `assert_text` 的 `expected: "新增项目"`
|
|
13
|
+
- 菜单/路由配置:`{ path: '/Project/List', meta: { title: '项目管理' } }` → `goto` 的 `url` 与断言文案
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
列表页“查询/筛选”(表格上方表单、不跳转)与全局“搜索”(header/侧边栏、触发路由)是不同模式,一律以源码文本为准,不按 URL 或行为重新命名。
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|---|---|---|---|
|
|
19
|
-
| 列表查询/筛选 | "查询" 或 "筛选" | `/List`, `/list`, `/index` | 表格上方表单,过滤不跳转 |
|
|
20
|
-
| 全局搜索 | "搜索" | header/侧边栏 | 触发路由跳转 |
|
|
17
|
+
## TC 忠实性
|
|
21
18
|
|
|
22
|
-
|
|
19
|
+
- 一个 TC 一个 case;TC 的每个 `preconditions[i]`、`steps[i]` 都必须被某个 DSL 步骤的 `covers` 覆盖,`oracle` 必须被断言步骤覆盖(`covers: ["oracle"]`)。DSL 不得增删或改写 TC 的步骤与 oracle,源码只用来补充入口 URL、locator、测试数据。
|
|
20
|
+
- oracle 断言要断言**结果**:`assert_text`(`match: exact` 或 `contains`)、`assert_url`、对流程刚产生的元素做 `assert_visible`。只断言静态入口元素可见、或断言自己刚点过的元素,会被 Core 判为弱断言而拒绝。
|
|
21
|
+
- 生成范围是正向主流程:打开路由、创建/编辑/执行主记录、查看成功结果、保存预期状态。异常、权限、响应式/a11y、空状态、浏览器兼容、性能、纯视觉判断、无稳定 locator 或无法准备/隔离数据的 TC 不生成 DSL,改为在绑定阶段降级为 `manual`(需 `mode_override` 批准)或 `blocked`,并向用户说明。
|
|
23
22
|
|
|
24
23
|
## Step Rules
|
|
25
24
|
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
- `
|
|
29
|
-
-
|
|
25
|
+
- 只用 v1 UI 动作:`goto`、`click`、`fill`、`select`、`check`、`uncheck`、`wait_for`、`assert_visible`、`assert_text`、`assert_url`、`screenshot`。没有 `hover`、`wait`(固定/加载等待)、`verify`、`act`、`assert_url_contains`、`inject_token`、`evaluate_js`。
|
|
26
|
+
- 动作后需要等待时用 `wait_for`(locator + `state`),不要用固定 sleep;“URL 包含 X”用 `assert_url` + `match: "contains"`。
|
|
27
|
+
- 需要预置数据或登录态时,用 `data.setup` 的 API 请求步骤,或显式 UI 登录步骤(`goto` + `fill` + `click`);没有 `auth` 快捷方式。凭据写成 `variables` 里的 `{ "secret": "ENV_KEY" }`,绝不写字面量。
|
|
28
|
+
- 需要清理时写 `data.cleanup` 的 API 步骤。测试数据使用 `${namespace}`/`${execution_id}` 命名,避免多次运行互相污染。
|
|
29
|
+
- API 步骤也可以穿插在 UI 主流程里做旁路校验(共享 BrowserContext cookie)。
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
## Locator 决策
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
顺序:`testid` → `role` → `label` / `placeholder` → `text` → `css`(最后手段)。
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
```json
|
|
42
|
-
{ "strategy": { "mode": "ai_only" } }
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
```json
|
|
46
|
-
// CORRECT: AI-only verification after critical action
|
|
47
|
-
{
|
|
48
|
-
"id": "s06",
|
|
49
|
-
"name": "验证编辑成功",
|
|
50
|
-
"driver": "ui",
|
|
51
|
-
"action": "act",
|
|
52
|
-
"target": { "label": "操作成功" },
|
|
53
|
-
"strategy": { "mode": "ai_only" },
|
|
54
|
-
"prompt": "检查页面上是否出现'操作成功'的提示消息,确认编辑操作已成功完成",
|
|
55
|
-
"depends_on": ["s05"],
|
|
56
|
-
"timeout_ms": 15000
|
|
57
|
-
}
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
Use `structured` only when runtime validation proves the locator is unique and stable. Do NOT use `structured` for verification steps.
|
|
35
|
+
1. 源码里有 `data-testid` 就用 `testid:`。没有而该元素是主流程的关键控件时,在 `source-map.md` 里记录“缺少 testid”,并建议开发者补上,不要靠猜。
|
|
36
|
+
2. 有明确 ARIA 角色和可访问名称:`role:button:确定`。
|
|
37
|
+
3. 表单控件:`label:用户名` 或 `placeholder:请输入名称`。
|
|
38
|
+
4. 页面内唯一的可见文本:`text:xxx`。
|
|
39
|
+
5. `css:` 只能用源码里确实存在的选择器,并在 `source-map.md` 注明出处;编译器对 `css` 及所有非 testid locator 打印警告。
|
|
61
40
|
|
|
62
|
-
|
|
41
|
+
locator 是 strict 的:匹配多个元素就失败。表格每行重复的“编辑/删除/查看”、对话框里的“确定/取消”这类文本,`text:`/`role:` 几乎一定多匹配,编译器会警告;应改用行级/对话框内的 `data-testid`。`xpath:`、`near:`、`scope: row:N`/`dialog` 均不支持。禁止编造 CSS(含 `%`、纯容器类如 `.el-form-item__content`、`:nth-child` 位置选择器、过短选择器都会被拒绝)。
|
|
63
42
|
|
|
64
|
-
|
|
43
|
+
## Assertion Rules
|
|
65
44
|
|
|
66
|
-
|
|
67
|
-
|---|---|---|
|
|
68
|
-
| 页面唯一按钮/菜单/tab | `label` + `exact` | `{"label": "新增项目库", "exact": true}` |
|
|
69
|
-
| 表格行操作按钮(每行重复) | `css` 精确定位 | `{"css": "tr:nth-child(2) .edit-btn"}` |
|
|
70
|
-
| 对话框底部确定/取消 | `css` 限定dialog | `{"css": ".el-dialog__footer .el-button--primary"}` |
|
|
71
|
-
| 输入框(有唯一placeholder) | `placeholder` | `{"placeholder": "请输入后台名称"}` |
|
|
72
|
-
| 表单项旁边控件 | `near_text` | `{"near_text": "后台名称"}` |
|
|
73
|
-
| ARIA友好的按钮/组件 | `role` + `name` | `{"role": "button", "name": "确定"}` |
|
|
74
|
-
| 无他法 | `xpath` 或 `ai_only` | `{"xpath": "//button[text()='确定']"}` |
|
|
75
|
-
|
|
76
|
-
**Decision rule**: 先看唯一性(page-level唯一用label,行级重复用css),再看作用域(dialog内用css限定),input优先placeholder。不存在 `{"by": "xxx", "value": "yyy"}` 这种格式。
|
|
77
|
-
|
|
78
|
-
### Assertion Rules
|
|
79
|
-
|
|
80
|
-
**Web/UI steps use assertion ACTIONS, not `assertions[]`:**
|
|
45
|
+
UI 断言只用断言动作,没有 `assertions[]`:
|
|
81
46
|
|
|
82
47
|
```json
|
|
83
|
-
|
|
84
|
-
{ "action": "
|
|
85
|
-
{ "action": "assert_visible", "
|
|
86
|
-
{ "action": "assert_url_contains", "params": { "text": "/sadmin/a/org/Project/Gift" } }
|
|
48
|
+
{ "action": "assert_text", "locator": "testid:toast", "match": "contains", "expected": "保存成功", "covers": ["oracle"] }
|
|
49
|
+
{ "action": "assert_url", "expected": "/projects/list", "match": "contains" }
|
|
50
|
+
{ "action": "assert_visible", "locator": "testid:result-panel" }
|
|
87
51
|
```
|
|
88
52
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
{ "assertions": [{ "type": "visible", "target": { "by": "css", "selector": ".el-dialog" } }] }
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Valid assertion actions: `assert_text`, `assert_visible`, `assert_url_contains`, `assert_any_visible`.
|
|
96
|
-
|
|
97
|
-
API steps use `assertions[]` with types: `equals`, `contains`, `status_code`, `json_path_equals`, `json_path_exists`, `regex`, etc. See `project-dsl-contract.md` for the full list.
|
|
53
|
+
- 确定性:断言期望必须是源码/需求给出的确切文案,不使用 AI 视觉判断(`ai_only`、Midscene、prompt 都不存在)。
|
|
54
|
+
- 短暂提示(toast)可能一闪而过:先 `wait_for` 它 `visible`,再 `assert_text`;或改为断言持久化的结果(列表行文本、URL、详情页字段)。
|
|
55
|
+
- `wait_for` 与 `screenshot` 不算断言。
|
|
98
56
|
|
|
99
57
|
## Source Evidence
|
|
100
58
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
- Planning: UI spec, frontend tech spec, feature breakdown, or change list.
|
|
104
|
-
- Code: router, page/view, API client, and relevant component/store/hook files.
|
|
105
|
-
|
|
106
|
-
## Positive Mainflow Boundary
|
|
59
|
+
每个 case 在 `source-map.md` 里至少引用一份规划产物(UI-SPEC、前端技术方案、功能点梳理或变更清单)和一份代码产物(路由、页面/视图、API client、相关组件/store)。证据放在 `source-map.md` 与 `source_evidence` 备注中;它不写入 DSL。
|
|
107
60
|
|
|
108
|
-
|
|
61
|
+
## After compile
|
|
109
62
|
|
|
110
|
-
|
|
63
|
+
编译通过后仍要:整个目录校验 → 独立 AI 审查每个 DSL(对照 TC oracle,建议性)→ 用 `devflow_approval` 提交 `execution_plan` → 用户在 `/devflow` → “待审批”逐 TC 批准。没有批准的 DSL 不会执行。见 `SKILL.md`。
|