@tea-agent/loop-agent 0.20.1-beta.0 → 0.20.1

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 (50) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/application/dag/args.js +29 -0
  3. package/dist/application/dag/run-dag.js +3 -1
  4. package/dist/cli/command-definitions.js +15 -1
  5. package/dist/cli/program.js +11 -1
  6. package/dist/commands/dag-rerun-task.js +19 -0
  7. package/dist/commands/dag-rerun.js +111 -0
  8. package/dist/shared/operator/capabilities.js +54 -0
  9. package/dist/worker/console/index.js +1 -1
  10. package/dist/worker/console/inspect-split.js +82 -0
  11. package/dist/worker/console/operation-runner.js +3 -1
  12. package/dist/worker/console/operation-store.js +1 -0
  13. package/dist/worker/console/operator-actions.js +153 -2
  14. package/dist/worker/console/operator-user-error.js +10 -0
  15. package/dist/worker/console/pi-readiness.js +4 -0
  16. package/dist/worker/console/recovery-cta.js +116 -5
  17. package/dist/worker/console/recovery-selection.js +107 -0
  18. package/dist/worker/console/resolve-dag-run-for-task.js +50 -11
  19. package/dist/worker/console/routes.js +20 -0
  20. package/dist/worker/console/sibling-controller.js +12 -7
  21. package/dist/worker/console/static/assets/index-CUDke82y.js +18 -0
  22. package/dist/worker/console/static/assets/index-wSEksVSO.css +1 -0
  23. package/dist/worker/console/static/index.html +2 -2
  24. package/dist/worker/observability/read-model.js +60 -0
  25. package/dist/worker/observe/static/index.html +1 -1
  26. package/dist/worker/run-task/run-task.js +7 -0
  27. package/dist/workflows/dag/frontend-test-result-contract.js +64 -0
  28. package/dist/workflows/dag/init-hybrid.js +90 -48
  29. package/dist/workflows/dag/node-execution.js +40 -6
  30. package/dist/workflows/dag/output-protocol.js +76 -0
  31. package/dist/workflows/dag/rerun-plan.js +611 -0
  32. package/dist/workflows/dag/rerun-run.js +497 -0
  33. package/dist/workflows/dag/rerun-task.js +284 -0
  34. package/dist/workflows/dag/retry-policy.js +20 -1
  35. package/dist/workflows/dag/runner.js +50 -0
  36. package/dist/workflows/dag/skill-snapshot.js +22 -3
  37. package/dist/workflows/dag/types.js +7 -0
  38. package/dist/workflows/dag/validate.js +11 -0
  39. package/dist/workflows/dag/workspace-checkpoint.js +163 -0
  40. package/docs/README.md +1 -0
  41. package/docs/templates/agent-dag.schema.json +17 -2
  42. package/docs/templates/frontend-test-case-checklist.md +16 -1
  43. package/docs/templates/frontend-test-dag.generate-cases.prompt.md +26 -2
  44. package/docs/templates/frontend-test-dag.json +65 -6
  45. package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +4 -1
  46. package/package.json +1 -1
  47. package/skills/loop-agent/references/command-reference.md +3 -0
  48. package/skills/playwright-cli-case-generator/SKILL.md +35 -7
  49. package/dist/worker/console/static/assets/index-3vsjZJHq.js +0 -16
  50. package/dist/worker/console/static/assets/index-i1wV4LrY.css +0 -1
package/docs/README.md CHANGED
@@ -58,6 +58,7 @@
58
58
  - `design/agent-worker-fullstack-workflow-integration.md` — workflow routing、Task Outcome、artifact-aware Ready、`fullstack-v1` 与 Verification Bundle
59
59
  - `design/fullstack-end-to-end-delivery-optimization-roadmap.md` — 全栈端到端优化收敛路线图(release train / Delivery / Final Verification)
60
60
  - `design/2026-07-22-console-observe-unified-operator-surface.md` — Observe 深度融合进 Console(Wave 1–3 已实现,目标 0.18.0)
61
+ - `design/2026-07-23-operator-task-rerun-and-node-retry.md` — Operator 自动节点重试、从节点重跑、standalone 完整任务重跑与 Worker Task 重排队(**Wave 1–2 已落地**;Wave 3–4 仍分波;优先解决 LLM/provider 不稳定;Inspect 只读 / Operate mutation)
61
62
  - `design/local-operator-console-from-pi-web.md` — Operator Console 设计输入;MVP 已随 `0.17.0`–`0.17.2` 发布;统一 surface 见上条
62
63
  - `design/taskspec-to-loop-agent-mapping.md` — TaskSpec → loop-agent task 兼容契约(文档镜像;runtime 真源在代码)
63
64
 
@@ -402,10 +402,10 @@
402
402
  "retryCategories": {
403
403
  "type": "array",
404
404
  "items": {
405
- "enum": ["timeout", "network", "rate-limit", "unavailable", "output-too-large"]
405
+ "enum": ["timeout", "network", "rate-limit", "unavailable", "output-too-large", "protocol-invalid"]
406
406
  },
407
407
  "default": ["timeout", "network", "rate-limit", "unavailable"],
408
- "description": "Failure categories eligible for retry. quota is never eligible. output-too-large is reserved for explicit structured-required nodes and is not part of the default retry set."
408
+ "description": "Failure categories eligible for retry. quota is never eligible. output-too-large is reserved for explicit structured-required nodes. protocol-invalid is for nodes that declare outputProtocol with retryOnInvalid."
409
409
  }
410
410
  }
411
411
  },
@@ -496,6 +496,21 @@
496
496
  "minLength": 1,
497
497
  "description": "Optional protocol prefix whose first matching Pi assistant-output line is promoted to the canonical first line. Missing matches are not synthesized."
498
498
  },
499
+ "outputProtocol": {
500
+ "type": "object",
501
+ "additionalProperties": false,
502
+ "required": ["type", "validLines"],
503
+ "description": "Machine-readable output protocol for safe read-only Pi nodes. Phase 1 supports first-line-enum only (e.g. VERDICT lines). Invalid output may auto-retry when retryOnInvalid is true.",
504
+ "properties": {
505
+ "type": { "const": "first-line-enum" },
506
+ "validLines": {
507
+ "type": "array",
508
+ "items": { "type": "string", "minLength": 1 },
509
+ "minItems": 1
510
+ },
511
+ "retryOnInvalid": { "type": "boolean", "default": true }
512
+ }
513
+ },
499
514
  "allowedPaths": {
500
515
  "type": "array",
501
516
  "items": { "type": "string", "minLength": 1 },
@@ -9,9 +9,24 @@ LLM review (when `frontendTest.reviewMode=blocking`) must not invent blocking ru
9
9
  |---|---|
10
10
  | `open-prefix` | Each case body includes `playwright-cli open --browser=chrome --headed <absolute-http(s)-url>` |
11
11
  | `production-url` | Open URL must not look like a production host |
12
- | `ac-mapping` | Manifest entry has non-empty `acIds` |
12
+ | `ac-mapping` | Manifest entry has non-empty `acIds` (**acceptance** ids, not case ids) |
13
+ | `ac-id-shape` | Each `acIds[]` entry matches `AC-*` / `AC-FE-*` |
14
+ | `ac-id-is-case` | `acIds` must not contain `FE-*` case ids |
15
+ | `unknown-ac` | When task `sourceBinding.requirementIds` lists ACs, every `acIds` entry must be in that set |
16
+ | `case-id-shape` | `caseId` matches `FE-<FEATURE>-<NNN>-...` (never `AC-FE-*`) |
17
+ | `case-id-is-ac` | Do not use acceptance id as `caseId` / filename |
18
+ | `case-path-mismatch` | `casePath === testcase/frontend/cases/{caseId}.md` |
13
19
  | `case-file-missing` | `casePath` exists |
14
20
  | `no-test-source` | Case text must not introduce pytest / Playwright test source (`pytest`, `playwright.test`, `@playwright/test`) |
21
+ | `playwright-cli-only` | Case steps may only use repo skill `playwright-cli` declared commands; bare `playwright` / `npx playwright` / `playwright test` / `@playwright/test` / Node Playwright API are forbidden |
22
+
23
+ ### ID 对照(避免混用)
24
+
25
+ | 字段 | 正确示例 | 错误示例 |
26
+ |---|---|---|
27
+ | `caseId` | `FE-LOGIN-001-core` | `AC-FE-001` |
28
+ | `acIds` | `["AC-FE-001"]` | `["FE-LOGIN-001-core"]` |
29
+ | 文件名 | `FE-LOGIN-001-core.md` | `AC-FE-001.md` |
15
30
 
16
31
  ## Non-blocking (notes only)
17
32
 
@@ -1,8 +1,20 @@
1
1
  # Generate frontend functional cases
2
2
 
3
- Use `playwright-cli-case-generator`. Read only `testcase/frontend/rag/context.md`, `coverage-map.md`, and existing `testcase/frontend/cases/`; write only that cases directory. Produce Markdown cases, `index.md`, and schema-version-1 `manifest.json`. Do not generate pytest or Playwright source code.
3
+ Use `playwright-cli-case-generator`. Read only `testcase/frontend/rag/context.md`, `coverage-map.md`, and existing `testcase/frontend/cases/`; write only that cases directory. Produce Markdown cases, `index.md`, and schema-version-1 `manifest.draft.json` (materialize promotes to `manifest.json`). Do not generate pytest or Playwright source code.
4
4
 
5
- Each case is independently executable and includes AC mapping, preconditions, cleanup, UI assertions, and its isolated evidence path. Use dimensions `core`, `boundary`, `flow`, or `backend`. Never guess API fields, constraints, SLA, credentials, or unrecorded data.
5
+ ## HARD ID contract (frequent failure)
6
+
7
+ | Concept | Field | Shape | Example |
8
+ |---|---|---|---|
9
+ | Test case id | `caseId` + filename | `FE-<FEATURE>-<NNN>-<dimension>` | `FE-LOGIN-001-core` |
10
+ | Acceptance criteria | `acIds[]` | `AC-FE-*` / `AC-*` | `AC-FE-001` |
11
+
12
+ - **Never** set `caseId` to `AC-FE-001` or name the file `AC-FE-001.md`.
13
+ - **Never** put `FE-LOGIN-001-core` into `acIds`.
14
+ - `casePath` must be `testcase/frontend/cases/<caseId>.md`.
15
+ - `evidenceDir` must be `testcase/frontend/evidence/<caseId>/`.
16
+
17
+ Each case is independently executable and includes AC mapping (`acIds`), preconditions, cleanup, UI assertions, and its isolated evidence path. Use dimensions `core`, `boundary`, `flow`, or `backend`. Never guess API fields, constraints, SLA, credentials, or unrecorded data.
6
18
 
7
19
  Every case must use the **resolved** absolute base URL from `testcase/frontend/rag/context.md` (field `baseUrl` / base URL line). Do not leave a `<base-url>` placeholder. Resolution policy (already applied by retrieve-context): prefer `config.md` frontend URL; else default `http://localhost:5173`.
8
20
 
@@ -14,6 +26,18 @@ playwright-cli open --browser=chrome --headed <resolved-base-url-from-context.md
14
26
 
15
27
  Do not put a session flag before `open`. Every later Playwright CLI command must stay in that same default browser session: do **not** emit `-s=<case-id>`, `-s=...`, or assume an undocumented named-session binding.
16
28
 
29
+ ## playwright-cli-only (hard)
30
+
31
+ Every browser step must use only commands declared by the repo-local `playwright-cli` skill. Forbidden with **no fallback**: bare `playwright`, `npx playwright`, `playwright test`, `@playwright/test`, Node Playwright API, or generating Playwright/Pytest source. If `playwright-cli` is unavailable, the case must require blocked evidence with `blockedReason: playwright-cli-unavailable` and must not open a browser.
32
+
33
+ ## U/D data ownership (hard for modify/delete)
34
+
35
+ 1. Only mutate data whose ownership is proven by the **current login identity** plus observable UI/API owner fields — never by name, guessed id, or list order alone.
36
+ 2. If the current user has no suitable data, create tagged, cleanable data in the current-user context, then modify/delete, then cleanup and verify cleanup.
37
+ 3. If safe create is impossible, only task-authorized Mock may construct data, and the case must label it as Mock (not real backend proof).
38
+ 4. If ownership is unverifiable and create/Mock are unavailable: require blocked evidence with one of `current-user-data-unavailable`, `data-ownership-unverifiable`, `safe-test-data-setup-unavailable` — never risk cross-user data.
39
+ 5. Never touch other users' data, shared fixtures, production data, or non-cleanable data.
40
+
17
41
  For every executable sub-scenario, state the fixture/reset operation, UI reset operation, a fresh snapshot before using element references, and the exact evidence write point. If the isolated environment is unavailable, require writing blocked evidence before any browser command; do not open or connect to a browser.
18
42
 
19
43
  Each case must require the executor to persist, even when blocked:
@@ -15,7 +15,10 @@
15
15
  "Case children execute serially. Persist each case result, logs and browser evidence before the next child starts.",
16
16
  "A token threshold is a post-case stop check, not a model hard token cap; unstarted cases must be recorded as blocked: token-budget-exhausted.",
17
17
  "Default pipeline acceptance is the final retrospect report under testcase/frontend/reports/; case full green is optional quality (frontendTest.strictOutcomeGate).",
18
- "Default frontendTest.reviewMode=off uses mechanical checklist-shell before materialize; set reviewMode=blocking for legacy dual LLM review gate."
18
+ "Default frontendTest.reviewMode=off uses mechanical checklist-shell before materialize; set reviewMode=blocking for legacy dual LLM review gate.",
19
+ "playwright-cli-only: generators and executors may call only skill-declared playwright-cli commands; bare playwright / npx playwright / @playwright/test / Playwright source are forbidden with no native Playwright fallback.",
20
+ "Environment preflight must curl-probe the frozen non-production baseUrl before generate; unreachable or curl-unavailable ends preflight as blocked (frontend-base-url-unreachable|curl-unavailable) so generate/map do not run.",
21
+ "U/D cases must prove current-user data ownership or create cleanable current-user data or authorized Mock; otherwise blocked (current-user-data-unavailable|data-ownership-unverifiable|safe-test-data-setup-unavailable) without cross-user mutation."
19
22
  ],
20
23
  "tasks": [
21
24
  {
@@ -24,7 +27,7 @@
24
27
  "executor": "pi",
25
28
  "role": "planner",
26
29
  "toolProfile": "write",
27
- "complexity": "HIGH",
30
+ "complexity": "MED",
28
31
  "writePolicy": "exclusive",
29
32
  "writeSet": [
30
33
  "testcase/frontend/rag/**"
@@ -37,14 +40,43 @@
37
40
  ".harness/**",
38
41
  "artifacts/**"
39
42
  ],
40
- "outputContract": "RAG context.md and coverage-map.md.",
43
+ "outputContract": "RAG context.md and coverage-map.md with baseUrl, baseUrlSource, environmentProbe=pending.",
41
44
  "subtask_prompt_markdown": "./frontend-test-dag.retrieve-context.prompt.md"
42
45
  },
43
46
  {
44
- "id": "generate-frontend-functional-cases-pi",
47
+ "id": "materialize-frontend-test-execution-shell",
45
48
  "depends_on": [
46
49
  "retrieve-frontend-test-context-pi"
47
50
  ],
51
+ "executor": "shell",
52
+ "role": "verifier",
53
+ "complexity": "LOW",
54
+ "writePolicy": "exclusive",
55
+ "writeSet": [
56
+ "testcase/frontend/rag/**"
57
+ ],
58
+ "allowedPaths": [
59
+ "testcase/frontend/rag/**"
60
+ ],
61
+ "forbiddenPaths": [
62
+ ".harness/**",
63
+ "artifacts/**"
64
+ ],
65
+ "outputContract": "Fail-closed environment preflight: absolute non-production baseUrl + curl HTTP reachability; writes environmentProbe facts; unreachable => blockedReason frontend-base-url-unreachable (node ERROR so generate/map do not run).",
66
+ "subtask_prompt": "Parse frozen baseUrl from context.md (config.md preferred, else http://localhost:5173). Reject production / non-http(s). Probe with curl (HEAD then GET fallback; connect/max-time; no auth/cookie). 2xx/3xx => reachable and continue. 4xx/5xx/DNS/timeout/connection refused/TLS => blockedReason frontend-base-url-unreachable. Missing curl => blockedReason curl-unavailable. Do not start the app. Runtime hybrid generator embeds the authoritative probe script.",
67
+ "shell": {
68
+ "commands": [
69
+ "node -e \"console.log('template placeholder: runtime hybrid DAG embeds curl preflight; do not use this static command as source of truth')\""
70
+ ],
71
+ "cwd": ".",
72
+ "timeoutMs": 60000
73
+ }
74
+ },
75
+ {
76
+ "id": "generate-frontend-functional-cases-pi",
77
+ "depends_on": [
78
+ "materialize-frontend-test-execution-shell"
79
+ ],
48
80
  "executor": "pi",
49
81
  "role": "implementer",
50
82
  "toolProfile": "write",
@@ -202,7 +234,7 @@
202
234
  "dependsPolicy": "all-or-condition-skip"
203
235
  },
204
236
  {
205
- "id": "materialize-frontend-case-manifest-shell",
237
+ "id": "frontend-case-checklist-shell",
206
238
  "depends_on": [
207
239
  "final-frontend-case-review-gate-shell"
208
240
  ],
@@ -210,6 +242,33 @@
210
242
  "role": "verifier",
211
243
  "complexity": "LOW",
212
244
  "writePolicy": "read-only",
245
+ "allowedPaths": [
246
+ "testcase/frontend/rag/**",
247
+ "testcase/frontend/cases/**"
248
+ ],
249
+ "forbiddenPaths": [
250
+ ".harness/**",
251
+ "artifacts/**"
252
+ ],
253
+ "outputContract": "Mechanical checklist: open-prefix, non-prod absolute URL, acIds, playwright-cli-only, no pytest/playwright test source; emit structured ruleId issues on failure.",
254
+ "subtask_prompt": "Scan generated cases/manifest against the shared blocking checklist. Runtime hybrid embeds the authoritative script.",
255
+ "shell": {
256
+ "commands": [
257
+ "node -e \"console.log('template placeholder: runtime hybrid embeds checklist')\""
258
+ ],
259
+ "cwd": ".",
260
+ "timeoutMs": 120000
261
+ }
262
+ },
263
+ {
264
+ "id": "materialize-frontend-case-manifest-shell",
265
+ "depends_on": [
266
+ "frontend-case-checklist-shell"
267
+ ],
268
+ "executor": "shell",
269
+ "role": "verifier",
270
+ "complexity": "LOW",
271
+ "writePolicy": "read-only",
213
272
  "allowedPaths": [
214
273
  "testcase/frontend/cases/**"
215
274
  ],
@@ -217,7 +276,7 @@
217
276
  ".harness/**",
218
277
  "artifacts/**"
219
278
  ],
220
- "outputContract": "Validated frontend manifest payload { cases: [...] }; shell command echo is permitted only as the prefix before exactly one final JSON line.",
279
+ "outputContract": "Validated frontend manifest payload { cases: [...] }; ruleId-tagged fail-closed validation; atomically materialize testcase/frontend/cases/manifest.json via temp+rename then delete draft; stdout is exactly one final JSON line {cases}.",
221
280
  "subtask_prompt": "Validate and materialize the generated frontend case manifest.",
222
281
  "shell": {
223
282
  "commands": [
@@ -10,5 +10,8 @@ Resolve a single absolute browser base URL and record it explicitly in `context.
10
10
  2. If no usable absolute `http://` / `https://` URL is found in `config.md` (or equivalent source facts), default to `http://localhost:5173`.
11
11
  3. Never use production hosts. Prefer local / isolated non-production URLs.
12
12
  4. Also record `baseUrlSource: config.md|<path>` or `baseUrlSource: default-localhost-5173` so later nodes can audit the choice.
13
- 5. Include the exact browser start prefix that generators must copy:
13
+ 5. Write `environmentProbe: pending`. The environment preflight shell will replace this with `reachable`, `unreachable`, or `curl-unavailable` plus a structured `blockedReason` (for example `frontend-base-url-unreachable`).
14
+ 6. Include the exact browser start prefix that generators must copy:
14
15
  `playwright-cli open --browser=chrome --headed <resolved-base-url>`.
16
+
17
+ Do not claim the environment is reachable until preflight completes. Preflight does not start the application.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tea-agent/loop-agent",
3
- "version": "0.20.1-beta.0",
3
+ "version": "0.20.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "loop-agent": "bin/loop-agent.js",
@@ -303,6 +303,9 @@ loop-agent dag report [--run-id <run-id>] [--lifecycle active|paused|completed|a
303
303
  loop-agent dag reconcile-run --run-id <run-id> # 只读检查 effectiveStatus 与恢复/收口资格
304
304
  loop-agent dag reconcile-run --run-id <run-id> --action supersede --reason "..." # 显式保留证据并标记为任务已另行完成
305
305
  loop-agent dag reconcile-run --run-id <run-id> --action abandon --reason "..." # 显式保留证据并收口为已放弃
306
+ loop-agent dag rerun --run-id <run-id> --from-node <node-id> --plan [--json] # 从节点重跑资格预检(不执行)
307
+ loop-agent dag rerun --run-id <run-id> --from-node <node-id> --plan-hash <sha256> --request-id <key> --reason "..." [--json] # 安全子图 continuation
308
+ loop-agent dag rerun-task --run-id <run-id> --reason "..." --request-id <key> [--profile auto] [--task-id <id>] [--json] # standalone 完整任务重跑
306
309
  loop-agent dag reconcile-tasks --glob '<pattern>' # 仅报告的 task/run/artifact/verify drift audit
307
310
  loop-agent dag final-verification <task-id> # 生成 closeout DAG,closeout artifact 后再 final verify
308
311
  loop-agent dag decision inspect --run-id <run-id> [--node-id <node-id>] # dry-run envelope 重解析;除 run 缺失外 exit 0
@@ -20,10 +20,20 @@ Playwright/Pytest 源码,也不修改被测应用。
20
20
 
21
21
  ## 输出
22
22
 
23
- - 写 `index.md`、`manifest.json` 与独立 case 文件
23
+ - 写 `index.md`、`manifest.draft.json`(生成阶段;materialize 会写成
24
+ `manifest.json`)与独立 case 文件
24
25
  `FE-<FEATURE>-<NNN>-<dimension>.md`;`dimension` 仅为 `core`、`boundary`、
25
26
  `flow` 或 `backend`。
26
- - `manifest.json` 使用 `schemaVersion: 1`,每项只含 `caseId`、`casePath`、
27
+ - **ID 契约(高频失败点,禁止混用)**:
28
+ - `caseId` / 文件名 = **用例 ID**,形态 `FE-<FEATURE>-<NNN>-<dimension>`
29
+ (例:`FE-LOGIN-001-core`)。**禁止**把验收标准写成 caseId
30
+ (错误:`AC-FE-001.md` / `caseId: "AC-FE-001"`)。
31
+ - `acIds` = **验收标准 ID 列表**,形态 `AC-FE-*` / `AC-*`
32
+ (例:`["AC-FE-001"]`)。**禁止**把用例 ID 放进 acIds
33
+ (错误:`acIds: ["FE-LOGIN-001-core"]`)。
34
+ - `casePath` 必须等于 `testcase/frontend/cases/<caseId>.md`;
35
+ `evidenceDir` 必须等于 `testcase/frontend/evidence/<caseId>/`。
36
+ - `manifest` 使用 `schemaVersion: 1`,每项只含 `caseId`、`casePath`、
27
37
  `dimension`、`acIds`、`evidenceDir`。所有 ID、路径和 evidenceDir 必须唯一,
28
38
  并位于 `testcase/frontend/` 内。
29
39
  - `index.md` 按功能点列出 case、维度、AC、数据依赖、API 映射和预期执行状态。
@@ -31,9 +41,9 @@ Playwright/Pytest 源码,也不修改被测应用。
31
41
  每个 case 必须包含:
32
42
 
33
43
  1. 元信息:功能、CRUD 分类、维度、关联 AC、RAG 来源、API 映射状态与数据策略。
34
- 2. 前置条件:独立 `-s=<case-id>` session、登录状态、fixture/存量数据、清理责任。
35
- 3. 可独立执行的命令序列:使用 RAG `context.md` 中已解析的绝对 `baseUrl`(优先来自任务源 `config.md`;缺失时默认 `http://localhost:5173`),写成
36
- `open --browser=chrome --headed <resolved-base-url>`,禁止保留 `<base-url>` 占位符;再按需登录/数据准备、
44
+ 2. 前置条件:默认浏览器 session 中的登录状态、fixture/存量数据、清理责任;不得用 `-s=<case-id>` 建立 named session
45
+ 3. 可独立执行的命令序列:使用 RAG `context.md` 中已解析的绝对 `baseUrl`(优先来自任务源 `config.md`;缺失时默认 `http://localhost:5173`),必须以
46
+ `playwright-cli open --browser=chrome --headed <resolved-base-url>` 开始,禁止保留 `<base-url>` 占位符,也不得使用 `-s=<case-id>` 或其他 named session;再按需登录/数据准备、
37
47
  `snapshot` 后优先使用元素引用、操作、UI 断言、可选 API 断言、cleanup、`close`。
38
48
  4. 明确的 UI/API 预期与数据清理结果;无法满足的环境或数据依赖必须写为 `blocked`。
39
49
 
@@ -42,6 +52,14 @@ Playwright/Pytest 源码,也不修改被测应用。
42
52
  `playwright-cli` skill 已声明的接口;不要生成 `requests --clear`、
43
53
  `request-body` 或 `response-body`。
44
54
 
55
+ ### playwright-cli-only(硬约束)
56
+
57
+ - 用例步骤只能使用 `playwright-cli` skill 已声明的命令语法。
58
+ - **禁止**裸 `playwright`、`npx playwright`、`playwright test`、`@playwright/test`、
59
+ Node Playwright API 或生成 Playwright/Pytest 源码。
60
+ - `playwright-cli` 不可用时不得降级到原生 Playwright;应写 blocked evidence,
61
+ `blockedReason: playwright-cli-unavailable`。
62
+
45
63
  ## 覆盖矩阵
46
64
 
47
65
  | CRUD 类型 | 必选 | 条件 |
@@ -63,8 +81,18 @@ Playwright/Pytest 源码,也不修改被测应用。
63
81
 
64
82
  - C-新增优先使用需求中给出的测试数据;仅在已授权 API 映射存在时才描述临时构造
65
83
  与清理。
66
- - R/U/D 优先使用知识包登记的 fixture 或 test-data;不足时只能使用已授权的
67
- 测试环境 API 注入并清理。
84
+ - R 查询优先使用知识包登记的 fixture 或当前用户可见数据。
85
+ - **U/D 修改删除归属顺序(硬约束)**:
86
+ 1. 仅操作可由**当前登录用户身份**与 UI/API 可观测归属字段共同证明的数据;
87
+ 禁止只凭名称、猜测 ID 或列表顺序认定归属。
88
+ 2. 当前用户无可用数据时,优先在当前用户上下文创建带 run/case 可追踪标记、
89
+ 可清理的数据,再执行 U/D,并在 cleanup 中验证清理。
90
+ 3. 无法安全创建时,仅可使用任务源/RAG 已确认且受路径/环境约束的 Mock,
91
+ 并明确标注为 Mock(不得声称真实后端验证)。
92
+ 4. 既无法证明归属、也无法安全创建或 Mock 时,写 `blocked` evidence,
93
+ `blockedReason` 使用:`current-user-data-unavailable` |
94
+ `data-ownership-unverifiable` | `safe-test-data-setup-unavailable`,不执行 U/D。
95
+ 5. 禁止修改/删除其他用户数据、共享 fixture、生产数据或无法确认可清理的数据。
68
96
  - 禁止使用生产 URL、真实用户凭据或不可清理的数据写入。无法证明隔离与清理时,
69
97
  case 必须为 `blocked`。
70
98