@tea-agent/loop-agent 0.20.1 → 0.22.0

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 (61) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/bin/agent-worker.js +0 -0
  3. package/dist/adapters/loop-agent.js +52 -0
  4. package/dist/commands/init.js +104 -0
  5. package/dist/executors/dag-pi-executor.js +26 -0
  6. package/dist/executors/pi-executor.js +111 -36
  7. package/dist/executors/pi-sdk-executor.js +105 -29
  8. package/dist/executors/shell-executor.js +215 -29
  9. package/dist/shared/openspec-spec.js +49 -0
  10. package/dist/worker/loop-agent/loop-agent-client.js +43 -9
  11. package/dist/worker/observability/read-model.js +28 -2
  12. package/dist/worker/observe/spec-evidence.js +12 -15
  13. package/dist/worker/observe/static/constants.js +5 -0
  14. package/dist/worker/observe/static/dag-helpers.js +22 -0
  15. package/dist/worker/observe/static/format-pool.js +22 -3
  16. package/dist/worker/observe/static/styles.css +32 -3
  17. package/dist/worker/observe/static/views/dag-inspector.js +2 -2
  18. package/dist/worker/observe/static/views/dag.js +5 -0
  19. package/dist/worker/run-task/run-task.js +16 -6
  20. package/dist/workflows/dag/backend-test-markdown-workflow.js +328 -97
  21. package/dist/workflows/dag/backend-test-result-contract.js +10 -4
  22. package/dist/workflows/dag/frontend-implementation-contract.js +141 -32
  23. package/dist/workflows/dag/frontend-lint-baseline.js +471 -0
  24. package/dist/workflows/dag/frontend-prewrite-gate.js +79 -16
  25. package/dist/workflows/dag/frontend-project-capability.js +11 -8
  26. package/dist/workflows/dag/frontend-repair.js +6 -4
  27. package/dist/workflows/dag/frontend-review-context.js +67 -0
  28. package/dist/workflows/dag/frontend-test-case-quality.js +105 -0
  29. package/dist/workflows/dag/frontend-test-result-contract.js +71 -66
  30. package/dist/workflows/dag/frontend-verification-trace.js +31 -1
  31. package/dist/workflows/dag/frontend-worktree-diff.js +81 -6
  32. package/dist/workflows/dag/init-hybrid.js +370 -79
  33. package/dist/workflows/dag/lifecycle.js +60 -4
  34. package/dist/workflows/dag/liveness-policy.js +250 -0
  35. package/dist/workflows/dag/node-execution.js +49 -0
  36. package/dist/workflows/dag/runner.js +21 -1
  37. package/dist/workflows/dag/types.js +67 -1
  38. package/docs/README.md +5 -6
  39. package/docs/architecture/dag-execution.md +11 -0
  40. package/docs/architecture/facts-and-state.md +1 -0
  41. package/docs/architecture/worker-and-feature.md +10 -0
  42. package/docs/templates/agent-dag.schema.json +15 -5
  43. package/docs/templates/backend-test-dag.generate-pytest.prompt.md +5 -2
  44. package/docs/templates/backend-test-dag.json +15 -15
  45. package/docs/templates/frontend-implementation-contract.schema.json +4 -3
  46. package/docs/templates/frontend-test-case-checklist.md +6 -2
  47. package/docs/templates/frontend-test-dag.json +2 -2
  48. package/harness.json +1 -1
  49. package/package.json +1 -1
  50. package/skills/frontend-design-review/SKILL.md +12 -10
  51. package/skills/frontend-design-review/references/review-checklist.md +4 -4
  52. package/skills/frontend-implementation/SKILL.md +2 -2
  53. package/skills/frontend-implementation/references/code-standards.md +4 -3
  54. package/skills/frontend-implementation/references/design-spec.md +19 -14
  55. package/skills/frontend-implementation/references/node-contracts.md +2 -2
  56. package/skills/frontend-review/SKILL.md +15 -28
  57. package/skills/frontend-review/references/review-findings.md +16 -18
  58. package/skills/frontend-verification/SKILL.md +16 -13
  59. package/skills/frontend-verification/references/verification-checklist.md +18 -30
  60. package/skills/loop-agent/references/command-reference.md +2 -0
  61. package/skills/loop-agent/references/hybrid-dag.md +2 -2
@@ -17,6 +17,16 @@
17
17
 
18
18
  `shell: false` + 绝对 launch spec(见下)意味着 Worker 不走 PATH 重新解析,也不在当前进程内加载 CLI command 实现。
19
19
 
20
+ ### `run-dag` kernel-owned supervision vs explicit hard timeout
21
+
22
+ `run-task` 启动 `run-dag` 时默认把外层 `timeoutMs` 设为 `0`,由 DAG kernel 负责节点 liveness,**不再**无条件把 30 分钟当作 hard kill:
23
+
24
+ - 省略 `worker.timeout_ms` → Worker 不设置 wall-clock deadline,并等待 `run-dag` 产生可确认终态。
25
+ - 显式 `worker.timeout_ms` → hard kill(可 capped),观察到 exit 后可报 `timedOut`。
26
+ - 客户端 `onHeartbeat` 仍是监管心跳,不等于 Pi meaningful progress。
27
+
28
+ 设计真源:`docs/design/dag-adaptive-liveness-and-supervision.md`。
29
+
20
30
  ## controller identity(冻结的已发布 controller)
21
31
 
22
32
  每次写入型 Feature/batch/Task/final verification 在任何目标仓库或 Task Pool 状态写入前,`LoopAgentClient` 解析并冻结 schemaVersion 1 identity(`ControllerIdentityV1`,定义在 `src/shared/package-metadata.ts`):
@@ -173,6 +173,11 @@
173
173
  "items": { "type": "string" },
174
174
  "default": []
175
175
  },
176
+ "commandTexts": {
177
+ "type": "array",
178
+ "items": { "type": "string" },
179
+ "default": []
180
+ },
176
181
  "finalFullRequired": { "type": "boolean" }
177
182
  }
178
183
  },
@@ -306,7 +311,7 @@
306
311
  "frontendPrewriteGate": {
307
312
  "type": "object",
308
313
  "additionalProperties": false,
309
- "required": ["schemaVersion", "planFromNodeId", "reviewFromNodeId", "allowedMockStrategies", "artifactName", "outputDir"],
314
+ "required": ["schemaVersion", "planFromNodeId", "reviewFromNodeId", "allowedMockStrategies", "artifactName", "outputDir", "requireSourceFreshness"],
310
315
  "properties": {
311
316
  "schemaVersion": { "const": 1 },
312
317
  "planFromNodeId": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
@@ -316,7 +321,9 @@
316
321
  "requiredRequirementIds": { "type": "array", "items": { "type": "string", "pattern": "^(?:REQ|BR|AC)-[A-Z0-9]+(?:-[A-Z0-9]+)*$" } },
317
322
  "allowedMockStrategies": { "type": "array", "minItems": 1, "items": { "enum": ["native", "browser-intercept", "request-adapter", "not-needed"] } },
318
323
  "artifactName": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*\\.json$" },
319
- "outputDir": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" }
324
+ "outputDir": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
325
+ "requireSourceFreshness": { "const": true },
326
+ "implementationWriteSet": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 } }
320
327
  }
321
328
  },
322
329
  "frontendVerificationBundle": {
@@ -332,13 +339,16 @@
332
339
  "staticEvidence": { "$ref": "#/$defs/shellVerifyEvidence" },
333
340
  "behaviorEvidence": { "$ref": "#/$defs/shellVerifyEvidence" },
334
341
  "mode": { "enum": ["initial", "repair"] }
335
- }
342
+ },
343
+ "allOf": [
344
+ { "properties": { "staticEvidence": { "required": ["commandTexts"], "properties": { "commandTexts": { "minItems": 1 } } }, "behaviorEvidence": { "required": ["commandTexts"], "properties": { "commandTexts": { "minItems": 1 } } } } }
345
+ ]
336
346
  },
337
347
  "frontendReviewContext": {
338
348
  "type": "object",
339
349
  "additionalProperties": false,
340
- "required": ["schemaVersion"],
341
- "properties": { "schemaVersion": { "const": 1 } }
350
+ "required": ["schemaVersion", "requireBaseline"],
351
+ "properties": { "schemaVersion": { "const": 1 }, "requireBaseline": { "const": true } }
342
352
  },
343
353
  "backendTestPipeline": {
344
354
  "enum": ["contracts", "semantic-initial", "execute-parse-initial", "classification-result-context"]
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Purpose
4
4
 
5
- 供 `generate-backend-pytest-pi` 使用。该节点是 `executor: "pi"`、`role: "implementer"`、`toolProfile: "write"` 的受限 writer,只把已经通过 Markdown gate 的最终用例转换为 pytest 资产。
5
+ 供 `generate-backend-pytest-pi` 使用。该节点是 `executor: "pi"`、`role: "implementer"`、`toolProfile: "write"` 的受限 writer,只把经过独立 Review 和 advisory Markdown 校验的最终用例转换为 pytest 资产;第 4 节点报告为 FAIL 时仍继续,但不得据此发明缺失行为。
6
6
 
7
7
  ## 当前合同
8
8
 
@@ -19,7 +19,10 @@ class TestOrderApi:
19
19
  ...
20
20
  ```
21
21
 
22
- - 断言只来自 `### 预期结果` / `### Expected Results`;setup 只来自 `### 前置条件`、`### 测试数据`、`### 自动化映射` 或对应历史英文分节。
22
+ - 断言只来自 `### 预期结果` / `### Expected Results`;setup 只来自必选 `### 前置条件`,以及存在时的 `### 测试数据`、`### 自动化映射` 或对应历史英文分节。
23
+ - 每条可自动化 Case 应在 `自动化映射` / `Automation Notes` 明确写出目标 pytest 脚本;第 6 节点只扫描这些脚本,不递归扫描无关历史 `test_*.py`。
24
+ - 每次接口请求必须通过统一日志 helper 或等价 client wrapper 打印请求与响应诊断信息:请求日志至少包含 HTTP method、URL/path、query 与 JSON/body/payload 参数摘要;响应日志至少包含 status code 与 JSON/text/body 结果摘要。日志必须能出现在 pytest stdout/stderr,不能改变断言或把失败伪装成通过。
25
+ - 日志输出前必须递归脱敏 `authorization`、`proxy-authorization`、`cookie`、`set-cookie`、`token`、`password`、`secret`、`api key`、`credential` 等 key/header;禁止打印完整 Authorization/Cookie。序列化后的 request/response body 必须有明确长度上限和截断标识,避免大对象淹没 pytest/JUnit/报告证据。
23
26
  - 禁止 `skip` / `xfail`、吞断言、宽异常静默通过、mock 替代真实目标、删除用例或弱化断言。
24
27
  - best-effort 清理只能捕获所选 HTTP client 实际抛出的窄 transport exception,例如 `requests.RequestException` 或 `urllib.error.URLError`;禁止 `except:`、`except Exception`、`except BaseException` 后 `pass`。
25
28
  - 同一 Case ID 可以由多个 pytest 函数覆盖;额外映射会进入 traceability 报告,但不能伪造未在 Markdown 中定义的业务场景。
@@ -28,9 +28,9 @@
28
28
  "Root artifacts/ is reserved for explicit exclusive write nodes, not read-only scout/reviewer output",
29
29
  "exclusive implementer nodes must use narrow, concrete writeSet paths; never keep ** or repo root",
30
30
  "Replace REPLACE/WITH/NARROW/IMPLEMENT/PATHS/** with concrete paths before executing the implementation writer",
31
- "backend-test-dag uses exactly 8 real top-level tasks and executes pytest exactly once.",
31
+ "backend-test-dag uses exactly 8 real top-level tasks and executes pytest exactly once over only the safe scripts explicitly mapped by final Markdown cases.",
32
32
  "Model nodes produce Markdown and pytest assets, never backend-test business JSON envelopes.",
33
- "Environment, Markdown validation, traceability, JUnit, HTML and execution facts are deterministic fail-closed evidence.",
33
+ "Environment, advisory Markdown validation, advisory traceability, JUnit, HTML and execution facts are deterministic evidence. Nodes 4 and 6 record findings without blocking nodes 5, 7 or 8.",
34
34
  "Only Markdown case generation/review may read source facts; pytest generation must not read source/**.",
35
35
  "Functional case IDs use BE-<MODULE>-<NNN>; production code/config, skip/xfail, repair and rerun are forbidden."
36
36
  ],
@@ -68,8 +68,8 @@
68
68
  "executorModels": {
69
69
  "pi": {
70
70
  "LOW": "gpt-5.3-codex-spark",
71
- "MED": "grok-4.5",
72
- "HIGH": "gpt-5.6-sol"
71
+ "MED": "glm-5.2",
72
+ "HIGH": "gpt-5.5"
73
73
  }
74
74
  },
75
75
  "tasks": [
@@ -125,7 +125,7 @@
125
125
  "artifacts/**"
126
126
  ],
127
127
  "outputContract": "Write a Chinese, human-readable testcase/md/README.md plus module Markdown case cards using BE-<MODULE>-<NNN>; keep machine IDs/literals exact and do not execute pytest or modify production code/config.",
128
- "subtask_prompt": "Read the upstream environment report. Generate a Markdown-first backend test strategy and cases under testcase/md/**.\n\nWrite human-readable content in Simplified Chinese by default. Keep English only for machine-readable IDs and technical literals such as Case/AC/REQ/BR IDs, HTTP methods, paths, field names, enum values, commands, filenames, code symbols and exact source citations.\n\nCreate testcase/md/README.md as the concise entry page: test objective, target/environment, isolation/cleanup, module summary and a linked case index table with Case ID, Chinese case name, scenario type, endpoint and expected status/result. Avoid repeating every case body in README.\n\nWrite each module as readable case cards. Every case starts with `## BE-<MODULE>-<NNN>|<中文用例名称>` and uses these Chinese headings: `### 测试目的`, `### 验收标准`, `### 需求依据`, `### 前置条件`, optional `### 测试数据`, `### 操作步骤`, `### 预期结果`, and `### 自动化映射`. API metadata may use a compact table under the case heading. The deterministic validator also accepts legacy English headings, but new output should use this Chinese presentation.\n\nPlace steps and their expected results in a compact readable table when that improves clarity; otherwise keep numbered executable steps and numbered/bulleted independently assertable results. Every result must name the observable HTTP status, response field/value, state transition or membership condition, never vague wording such as ‘符合预期’.\n\nIn `自动化映射`, record the planned script path and pytest function name when known. Put implementation-only restrictions in a concise `<details>` block rather than dominating the main case flow. Use only environment-supported fixtures/targets/isolation, record evidence gaps in Chinese, and do not emit JSON, pytest, or execute commands.\n\n## Derived task contract: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Authoritative reference index\n\n[]\n\nFor each index entry, use `readPath` for Pi read-tool calls and copy `path` exactly into Markdown Source References. Bound files under .harness/tasks/<taskId>/source/** are read-only inputs: reading them is allowed even though writing .harness/** is forbidden. Never resolve `path` relative to the repository root, search for substitutes, or fall back to docs/** when a bound read fails.\n\nRead only precise indexed references needed for AC/API/field/rule evidence; references remain authoritative over derived text."
128
+ "subtask_prompt": "Read the upstream environment report. Generate a Markdown-first backend test strategy and cases under testcase/md/**.\n\nWrite human-readable content in Simplified Chinese by default. Keep English only for machine-readable IDs and technical literals such as Case/AC/REQ/BR IDs, HTTP methods, paths, field names, enum values, commands, filenames, code symbols and exact source citations.\n\nCreate testcase/md/README.md as the concise entry page: test objective, target/environment, isolation/cleanup, module summary and a linked case index table with Case ID, Chinese case name, scenario type, endpoint and expected status/result. Avoid repeating every case body in README.\n\nWrite each module as readable case cards. Every case starts with `## BE-<MODULE>-<NNN>|<中文用例名称>`. The only sections required by the deterministic validator are `### 前置条件`, `### 操作步骤`, and `### 预期结果` (legacy English aliases remain accepted). Add `测试目的`, `验收标准`, `需求依据`, `测试数据`, and `自动化映射` when useful for human readability; every automatable case should explicitly name its target pytest script under `自动化映射` so traceability can scan only that script.\n\nPlace steps and their expected results in a compact readable table when that improves clarity; otherwise keep numbered executable steps and numbered/bulleted independently assertable results. Every result must name the observable HTTP status, response field/value, state transition or membership condition, never vague wording such as ‘符合预期’.\n\nIn `自动化映射`, record the planned script path and pytest function name when known. Put implementation-only restrictions in a concise `<details>` block rather than dominating the main case flow. Use only environment-supported fixtures/targets/isolation, record evidence gaps in Chinese, and do not emit JSON, pytest, or execute commands.\n\n## Derived task contract: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Authoritative reference index\n\n[]\n\nFor each index entry, use `readPath` for Pi read-tool calls and copy `path` exactly into Markdown Source References. Bound files under .harness/tasks/<taskId>/source/** are read-only inputs: reading them is allowed even though writing .harness/** is forbidden. Never resolve `path` relative to the repository root, search for substitutes, or fall back to docs/** when a bound read fails.\n\nRead only precise indexed references needed for AC/API/field/rule evidence; references remain authoritative over derived text."
129
129
  },
130
130
  {
131
131
  "id": "review-and-revise-backend-md-cases-pi",
@@ -149,7 +149,7 @@
149
149
  "artifacts/**"
150
150
  ],
151
151
  "outputContract": "Review source fidelity and directly revise only testcase/md/**; return concise Markdown, never JSON.",
152
- "subtask_prompt": "Independently review generated Markdown cases against each case 需求依据 and environment evidence. Treat the files as human-facing test documentation: require a clear Chinese name and scenario/purpose, compact metadata, readable steps/results, and a concise automation mapping while preserving exact machine IDs and technical literals.\n\nCheck AC completeness/meaning, endpoint, fields/shape, status/error codes, rules, states, documented boundaries/auth, positive/negative coverage, executable steps and assertable results. Reject avoidable English prose, duplicated bilingual wording, repeated boilerplate, oversized unstructured sections, vague results such as ‘符合预期’, and missing script/function mapping where it can be derived.\n\nCorrect testcase/md/** directly: add documented omissions, remove unsupported cases, fix mappings/expectations, merge duplicates, improve navigation/tables/Chinese wording, or record gaps in Chinese. Keep Case IDs, AC/REQ/BR IDs, HTTP methods, paths, fields, enum values, filenames, code symbols and source citations exact. The validator accepts Chinese and legacy English section aliases; retain or converge to the Chinese human-readable headings without losing structure.\n\nRead only precise referenced source paths plus requirement sections needed for uncovered ACs. Do not scan the repository, modify source/**, generate pytest, execute tests, or emit JSON.\n\n## Derived task contract: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Authoritative reference index\n\n[]\n\nFor each index entry, use `readPath` for Pi read-tool calls and keep `path` as the exact Markdown Source References citation. Bound files under .harness/tasks/<taskId>/source/** are read-only inputs: reading them is allowed even though writing .harness/** is forbidden. Never resolve `path` relative to the repository root, search for substitutes, or fall back to docs/** when a bound read fails."
152
+ "subtask_prompt": "Independently review generated Markdown cases against the task requirements and environment evidence. Treat the files as human-facing test documentation: require clear preconditions, executable steps and assertable expected results; improve names, purpose, metadata and automation mapping where useful while preserving exact machine IDs and technical literals.\n\nCheck AC completeness/meaning, endpoint, fields/shape, status/error codes, rules, states, documented boundaries/auth, positive/negative coverage, executable steps and assertable results. Reject avoidable English prose, duplicated bilingual wording, repeated boilerplate, oversized unstructured sections, vague results such as ‘符合预期’, and missing script/function mapping where it can be derived.\n\nCorrect testcase/md/** directly: add documented omissions, remove unsupported cases, fix mappings/expectations, merge duplicates, improve navigation/tables/Chinese wording, or record gaps in Chinese. Keep Case IDs, AC/REQ/BR IDs, HTTP methods, paths, fields, enum values, filenames, code symbols and source citations exact. The validator accepts Chinese and legacy English section aliases; retain or converge to the Chinese human-readable headings without losing structure.\n\nRead only precise referenced source paths plus requirement sections needed for uncovered ACs. Do not scan the repository, modify source/**, generate pytest, execute tests, or emit JSON.\n\n## Derived task contract: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Authoritative reference index\n\n[]\n\nFor each index entry, use `readPath` for Pi read-tool calls and keep `path` as the exact Markdown Source References citation. Bound files under .harness/tasks/<taskId>/source/** are read-only inputs: reading them is allowed even though writing .harness/** is forbidden. Never resolve `path` relative to the repository root, search for substitutes, or fall back to docs/** when a bound read fails."
153
153
  },
154
154
  {
155
155
  "id": "validate-backend-md-cases-shell",
@@ -169,8 +169,8 @@
169
169
  ".harness/dag-runs/**",
170
170
  "artifacts/**"
171
171
  ],
172
- "outputContract": "Run-owned reports/backend-md-case-validation.md proving final Markdown quality and safety.",
173
- "subtask_prompt": "Fail closed on missing/duplicate IDs, sections, AC coverage, source references, executable steps, assertable results, placeholders or secret-shaped content.",
172
+ "outputContract": "Run-owned reports/backend-md-case-validation.md with PASS/FAIL advisory findings; downstream execution continues.",
173
+ "subtask_prompt": "Record advisory findings for missing/duplicate IDs, missing core sections (preconditions, steps, expected results), AC coverage, executable steps, assertable results or placeholders. Do not validate source-reference existence. Keep quality findings advisory, but fail closed after writing the report when secret-shaped values are detected so downstream pytest/report nodes cannot consume them.",
174
174
  "shell": {
175
175
  "commands": [],
176
176
  "backendTestPipeline": "markdown-cases",
@@ -203,7 +203,7 @@
203
203
  "artifacts/**"
204
204
  ],
205
205
  "outputContract": "Convert every final automatable Markdown case into pytest assets whose actual test function region contains the exact Case ID, preferably in the function name or docstring; no JSON and no pytest execution.",
206
- "subtask_prompt": "Convert validated testcase/md/** to pytest using upstream environment and validation evidence plus only bounded pytest config/conftest.\n\nEnsure every final Markdown Case ID appears in at least one real pytest test function or pytest test class method region, preferably as `test_BE_<MODULE>_<NNN>_<description>` and in that function/method docstring. Module-level functions and class-based pytest methods are both supported. Multiple test functions may cover one Case ID; assertions come only from 预期结果/Expected Results and setup comes only from 前置条件/测试数据/自动化映射 or their legacy English aliases.\n\nDo not read source/**, add cases, reassign ACs, modify conftest/config/production code, use skip/xfail, swallow assertions, execute pytest, or emit JSON. For best-effort cleanup, catch only the narrow transport exception actually raised by the selected HTTP client (for example `requests.RequestException` or `urllib.error.URLError`); never use bare `except`, `Exception`, or `BaseException` with `pass`."
206
+ "subtask_prompt": "Convert testcase/md/** to pytest using upstream environment and advisory validation evidence plus only bounded pytest config/conftest. A FAIL advisory report does not authorize inventing missing behavior; use the final Markdown facts that are present.\n\nEnsure every final Markdown Case ID appears in at least one real pytest test function or pytest test class method region, preferably as `test_BE_<MODULE>_<NNN>_<description>` and in that function/method docstring. Module-level functions and class-based pytest methods are both supported. Multiple test functions may cover one Case ID; assertions come only from 预期结果/Expected Results and setup comes only from 前置条件 plus any optional 测试数据/自动化映射 or their legacy English aliases.\n\nGenerate a reusable HTTP logging helper (or equivalent client wrapper) and call it for every interface request. The request log must include method, URL/path, and request parameters (query plus JSON/body/payload summary). The response log must include status code and response result (JSON/text/body summary), and both records must be visible in pytest stdout/stderr without changing assertions.\n\nCompare timestamps and other semantically equivalent protocol values by parsed meaning, not byte-for-byte serialization. In particular, normalize valid ISO-8601 instants before equality/order assertions so differences such as omitted trailing fractional seconds do not create TestBug failures; preserve exact-string assertions only when the Markdown explicitly requires representation equality.\n\nBefore logging, recursively redact sensitive keys and header values including authorization, proxy-authorization, cookie, set-cookie, token, password, secret, api key and credentials. Never print full Authorization/Cookie values. Apply bounded truncation to serialized request and response bodies (with an explicit truncation marker) so large payloads cannot flood pytest or report artifacts.\n\nDo not read source/**, add cases, reassign ACs, modify conftest/config/production code, use skip/xfail, swallow assertions, execute pytest, or emit JSON. For best-effort cleanup, catch only the narrow transport exception actually raised by the selected HTTP client (for example `requests.RequestException` or `urllib.error.URLError`); never use bare `except`, `Exception`, or `BaseException` with `pass`."
207
207
  },
208
208
  {
209
209
  "id": "backend-test-traceability-gate-shell",
@@ -223,8 +223,8 @@
223
223
  ".harness/dag-runs/**",
224
224
  "artifacts/**"
225
225
  ],
226
- "outputContract": "Run-owned reports/backend-test-traceability.md proving every real Markdown Case ID is covered by at least one pytest test function.",
227
- "subtask_prompt": "Fail closed only when a real Markdown case heading has no associated pytest test function or class method. Accept exact Case IDs in the function/method name or its decorator/body/docstring region; report multiple mappings and extra automation Case IDs without blocking. Continue to reject skip/xfail or swallowed exceptions.",
226
+ "outputContract": "Run-owned reports/backend-test-traceability.md with PASS/FAIL advisory findings for Markdown Case to mapped pytest script/symbol coverage.",
227
+ "subtask_prompt": "Record advisory findings when a real Markdown case heading has no associated pytest test function or class method in the script explicitly mapped by that Markdown case, or when a mapped HTTP test script lacks request parameters logging, response result logging, recursive redaction or bounded truncation evidence. Accept exact Case IDs in the function/method name or its decorator/body/docstring region. Do not scan unrelated test_*.py files and do not block pytest execution.",
228
228
  "shell": {
229
229
  "commands": [],
230
230
  "backendTestPipeline": "markdown-traceability",
@@ -250,11 +250,11 @@
250
250
  ".harness/dag-runs/**",
251
251
  "artifacts/**"
252
252
  ],
253
- "outputContract": "One pytest execution producing valid JUnit, self-contained HTML and reports/backend-test-facts.md; exit 0/1 with valid evidence continues.",
254
- "subtask_prompt": "Execute pytest exactly once. Validate JUnit, render the primary self-contained Chinese HTML report from the same JUnit plus final Markdown case metadata without rerun, list every case with name/scenario/script/function/result/duration, and preserve failure summaries plus expandable technical details as facts.",
253
+ "outputContract": "One scoped pytest execution over Markdown-mapped scripts producing valid JUnit with per-case captured output, self-contained HTML, reports/backend-test.md and reports/backend-test-facts.md; exit 0/1 with valid evidence continues.",
254
+ "subtask_prompt": "Resolve the final Markdown Automation Notes/自动化映射 to a unique, safe set of testcase/**/test_*.py targets and execute only those scripts exactly once. Validate JUnit, then render the primary self-contained Chinese HTML report from the same JUnit plus final Markdown case metadata without rerun. Keep 测试结论, quality status, failure overview, and a polished per-case result card with concise scenario, automation test name, result, duration, and redacted bounded HTTP request parameters/response results for both passed and failed cases. Do not render a technical/execution evidence section in HTML; retain auditable paths and hashes in facts.",
255
255
  "shell": {
256
256
  "commands": [
257
- "mkdir -p \"${HARNESS_DAG_RUN_DIR}/reports\"; PYTHONUTF8=1 PYTHONIOENCODING=utf-8 PYTHONDONTWRITEBYTECODE=1 python -m pytest testcase/ -v -p no:cacheprovider --junitxml=\"${HARNESS_DAG_RUN_DIR}/reports/backend-test.junit.xml\"; STATUS=$?; printf \"%s\" \"${STATUS}\" > \"${HARNESS_DAG_RUN_DIR}/reports/backend-test-pytest-exit.txt\"; if { [ \"${STATUS}\" -eq 0 ] || [ \"${STATUS}\" -eq 1 ]; } && [ -s \"${HARNESS_DAG_RUN_DIR}/reports/backend-test.junit.xml\" ]; then exit 0; fi; exit \"${STATUS}\""
257
+ "mkdir -p \"${HARNESS_DAG_RUN_DIR}/reports\"; echo \"pytest targets are resolved at runtime from final Markdown 自动化映射\""
258
258
  ],
259
259
  "backendTestPipeline": "markdown-execute-html",
260
260
  "cwd": ".",
@@ -284,7 +284,7 @@
284
284
  "artifacts/**"
285
285
  ],
286
286
  "outputContract": "Final Markdown report and L-5 conclusion under docs/test-reports/**; no JSON.",
287
- "subtask_prompt": "Generate the final Markdown report from upstream facts and run-owned environment, case-validation, traceability, JUnit and HTML evidence. Do not emit JSON.\n\nInclude environment, case quality/review, automation mapping, exact pytest facts, failure classification/analysis, risks, regression recommendations, evidence paths/hashes, coverage/stability availability, and L-5 READY/NOT READY.\n\nNever override Shell/JUnit facts. One run cannot prove FlakyTest. Missing coverage/stability is Unavailable. L-5 requires pass=100%, AC=100%, automation>=90%, stability>=95% n>=5, line>=80%, branch>=70%, skipped=0 and no blocking Critical risk.\n\nWrite only under docs/test-reports/**."
287
+ "subtask_prompt": "Generate the final Markdown report from upstream facts and run-owned environment, advisory case-validation, advisory traceability, JUnit and HTML evidence. Do not emit JSON.\n\nUse this exact human-facing section order: 测试结论 → 执行概览 → 质量校验 → 失败分析 → 风险与建议 → 证据与 L-5. Put the decision and key numbers first, use compact tables/bullets, and keep headings concise. Do not paste entire upstream reports, duplicate per-case tables already present in facts, or repeat the same evidence in multiple sections; link to paths/hashes and quote only the findings needed for the conclusion.\n\nAlways state the exact PASS/FAIL status and findings from nodes 4 and 6. Their FAIL status does not block pytest, but it must remain visible as a quality/traceability risk and must never be rewritten as PASS.\n\nInclude environment, case quality/review, automation mapping, exact pytest facts, failure classification/analysis, risks, regression recommendations, evidence paths/hashes, coverage/stability availability, and L-5 READY/NOT READY.\n\nNever override Shell/JUnit facts. One run cannot prove FlakyTest. Missing coverage/stability is Unavailable. L-5 requires pass=100%, AC=100%, automation>=90%, stability>=95% n>=5, line>=80%, branch>=70%, skipped=0 and no blocking Critical risk.\n\nWrite only under docs/test-reports/**."
288
288
  }
289
289
  ],
290
290
  "sourceBinding": {
@@ -10,14 +10,15 @@
10
10
  "sourceBinding": { "$ref": "#/$defs/sourceBinding" },
11
11
  "riskLevel": { "enum": ["small", "standard", "high-risk"] },
12
12
  "targets": { "type": "object", "additionalProperties": false, "required": ["files"], "properties": { "files": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/path" } }, "routes": { "type": "array", "items": { "type": "string", "pattern": "^/" } }, "publicApiChanges": { "type": "array", "items": { "type": "string", "minLength": 1 } } } },
13
- "requirements": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["id", "implementationTargets", "verificationTargetIds"], "properties": { "id": { "$ref": "#/$defs/requirementId" }, "implementationTargets": { "type": "array", "items": { "$ref": "#/$defs/path" } }, "verificationTargetIds": { "type": "array", "items": { "type": "string", "minLength": 1 } }, "evidenceGap": { "$ref": "#/$defs/gap" } } } },
14
- "uiStates": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["name", "applicable"], "properties": { "name": { "type": "string", "minLength": 1 }, "applicable": { "type": "boolean" }, "expectedBehavior": { "type": "string", "minLength": 1 }, "implementationTargets": { "type": "array", "items": { "$ref": "#/$defs/path" } }, "verificationTargetIds": { "type": "array", "items": { "type": "string", "minLength": 1 } }, "notApplicableReason": { "type": "string", "minLength": 1 } } } },
13
+ "requirements": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["id", "implementationTargets", "verificationTargetIds"], "properties": { "id": { "$ref": "#/$defs/requirementId" }, "implementationTargets": { "type": "array", "items": { "$ref": "#/$defs/path" } }, "verificationTargetIds": { "type": "array", "items": { "type": "string", "minLength": 1 } }, "evidenceGap": { "$ref": "#/$defs/gap" } } } },
14
+ "uiStates": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["name", "applicable"], "properties": { "name": { "type": "string", "minLength": 1 }, "applicable": { "type": "boolean" }, "expectedBehavior": { "type": "string", "minLength": 1 }, "implementationTargets": { "type": "array", "items": { "$ref": "#/$defs/path" } }, "verificationTargetIds": { "type": "array", "items": { "type": "string", "minLength": 1 } }, "notApplicableReason": { "type": "string", "minLength": 1 } } } },
15
15
  "interactions": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["name", "implementationTargets", "verificationTargetIds"], "properties": { "name": { "type": "string", "minLength": 1 }, "implementationTargets": { "type": "array", "items": { "$ref": "#/$defs/path" } }, "verificationTargetIds": { "type": "array", "items": { "type": "string" } } } } },
16
16
  "mockApi": { "type": "object", "additionalProperties": false, "required": ["strategy", "productionDefaultOff", "activation", "endpoints"], "properties": { "strategy": { "enum": ["native", "browser-intercept", "request-adapter", "not-needed"] }, "productionDefaultOff": { "const": true }, "activation": { "type": "string", "minLength": 1 }, "endpoints": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["method", "path"], "properties": { "method": { "enum": ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"] }, "path": { "type": "string", "pattern": "^/" }, "fixture": { "$ref": "#/$defs/path" }, "consumer": { "$ref": "#/$defs/path" } } } } } },
17
17
  "designEvidence": { "type": "object", "additionalProperties": false, "required": ["source", "paths", "conflicts"], "properties": { "source": { "type": "string", "minLength": 1 }, "paths": { "type": "array", "items": { "$ref": "#/$defs/path" } }, "conflicts": { "type": "array", "items": { "type": "string", "minLength": 1 } } } },
18
- "verificationTargets": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["id", "type", "commandLabel", "file", "requirementIds", "uiStates"], "properties": { "id": { "type": "string", "minLength": 1 }, "type": { "enum": ["static", "unit", "component", "integration", "mock"] }, "commandLabel": { "type": "string", "minLength": 1 }, "file": { "$ref": "#/$defs/path" }, "symbol": { "type": "string", "minLength": 1 }, "requirementIds": { "type": "array", "items": { "$ref": "#/$defs/requirementId" } }, "uiStates": { "type": "array", "items": { "type": "string", "minLength": 1 } } } } },
18
+ "verificationTargets": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["id", "type", "commandLabel", "file", "requirementIds", "uiStates"], "properties": { "id": { "type": "string", "minLength": 1 }, "type": { "enum": ["static", "unit", "component", "integration", "mock"] }, "commandLabel": { "type": "string", "minLength": 1 }, "file": { "$ref": "#/$defs/path" }, "symbol": { "type": "string", "minLength": 1 }, "requirementIds": { "type": "array", "items": { "$ref": "#/$defs/requirementId" } }, "uiStates": { "type": "array", "items": { "type": "string", "minLength": 1 } } } } },
19
19
  "evidenceGaps": { "type": "array", "items": { "$ref": "#/$defs/gap" } }
20
20
  },
21
+ "allOf": [{ "if": { "properties": { "mockApi": { "properties": { "strategy": { "enum": ["native", "browser-intercept", "request-adapter"] } } } } }, "then": { "properties": { "mockApi": { "properties": { "endpoints": { "minItems": 1, "items": { "required": ["method", "path", "fixture", "consumer"] } } } } } } }],
21
22
  "$defs": {
22
23
  "path": { "type": "string", "minLength": 1, "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\\\).+$" },
23
24
  "requirementId": { "type": "string", "pattern": "^(?:REQ|BR|AC)-[A-Z0-9]+(?:-[A-Z0-9]+)*$" },
@@ -17,8 +17,12 @@ LLM review (when `frontendTest.reviewMode=blocking`) must not invent blocking ru
17
17
  | `case-id-is-ac` | Do not use acceptance id as `caseId` / filename |
18
18
  | `case-path-mismatch` | `casePath === testcase/frontend/cases/{caseId}.md` |
19
19
  | `case-file-missing` | `casePath` exists |
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 |
20
+
21
+ ## Tool guidance (non-blocking)
22
+
23
+ - Browser execution should **strongly prefer `playwright-cli`** and the standard start command documented above.
24
+ - The fourth node does not scan for or block executable commands from other tools, including `pytest`, bare/native Playwright, `npx playwright`, `playwright test`, `@playwright/test`, or Node Playwright APIs.
25
+ - Tool-choice findings belong in later advisory/reporting stages rather than this structural hard gate.
22
26
 
23
27
  ### ID 对照(避免混用)
24
28
 
@@ -93,7 +93,7 @@
93
93
  ".harness/**",
94
94
  "artifacts/**"
95
95
  ],
96
- "outputContract": "Markdown cases, index.md and manifest.json schemaVersion 1; no test source code.",
96
+ "outputContract": "Markdown cases, index.md and manifest.draft.json schemaVersion 1; materialize promotes the validated draft to manifest.json; no test source code.",
97
97
  "subtask_prompt_markdown": "./frontend-test-dag.generate-cases.prompt.md"
98
98
  },
99
99
  {
@@ -250,7 +250,7 @@
250
250
  ".harness/**",
251
251
  "artifacts/**"
252
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.",
253
+ "outputContract": "Mechanical checklist: manifest/case paths, Case ID, non-production playwright-cli open prefix, and AC mapping; strongly recommend playwright-cli without blocking alternative executable tool commands.",
254
254
  "subtask_prompt": "Scan generated cases/manifest against the shared blocking checklist. Runtime hybrid embeds the authoritative script.",
255
255
  "shell": {
256
256
  "commands": [
package/harness.json CHANGED
@@ -59,7 +59,7 @@
59
59
  "pi": {
60
60
  "description": "Pi planning, review, diagnosis, and bounded writing when DAG toolProfile=write",
61
61
  "LOW": "gpt-5.3-codex-spark",
62
- "MED": "grok-4.5",
62
+ "MED": "glm-5.2",
63
63
  "HIGH": "gpt-5.6-sol"
64
64
  }
65
65
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tea-agent/loop-agent",
3
- "version": "0.20.1",
3
+ "version": "0.22.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "loop-agent": "bin/loop-agent.js",
@@ -11,10 +11,10 @@ references:
11
11
 
12
12
  For frontend design review nodes. Read the checklist; audit contract, scout, Mock
13
13
  strategy, effective plan, task bounds, and traceable design evidence.
14
- Knowledge base and `openspec/` are parallel specification sources. Query the
15
- knowledge-base connector when available; regardless of result, also search and
16
- read `<repoRoot>/openspec/**` before accepting repository conventions. The
17
- connector format is TODO: never invent results.
14
+ Knowledge base, OpenSpec, and `ai_workspace/` are parallel sources. Query the
15
+ knowledge-base connector when available; always search/read `openspec/schemas/**`,
16
+ `openspec/project-specs/**`, and `ai_workspace/**` before accepting conventions.
17
+ Connector format is TODO: never invent results.
18
18
 
19
19
  ## Verdict Contract
20
20
 
@@ -39,16 +39,17 @@ output fails closed.
39
39
 
40
40
  - Any criterion lacks implementation/verification; UI states lack reasons; a
41
41
  dependency lacks permission; confirmed primitives/rules are ignored; design claims
42
- lack knowledge-base or required `openspec/` evidence; paths cross write bounds;
43
- commands are missing/non-deterministic; or interaction, responsive, accessibility,
44
- data, or failure behavior requires guessing.
42
+ lack knowledge-base or required openspec specification evidence; paths cross
43
+ write bounds; commands are missing/non-deterministic; or
44
+ interaction, responsive, accessibility, data, or failure behavior requires guessing.
45
45
  - `MOCK_STRATEGY: blocked`; missing permitted target paths, endpoint/schema-to-fixture
46
46
  mapping, fixed verification, or dev/test-only activation; a second Mock framework;
47
47
  inline fake data; commented real requests; Mock-on production defaults; test-only
48
48
  production imports; or Mock evidence reported as real integration.
49
49
 
50
- Knowledge-base absence is advisory if relevant `openspec/` rules were read and
51
- applied. Block skipped fallback, unresolved conflict, or unresolved UI decisions.
50
+ Knowledge-base absence is advisory if relevant rules from either openspec
51
+ specification directory were read and applied. Block skipped fallback, unresolved
52
+ conflict, or unresolved UI decisions.
52
53
 
53
54
  ## Method And Output
54
55
 
@@ -59,7 +60,8 @@ or Advisory, and never edit files.
59
60
 
60
61
  Run `grep`/`find`, then explicit `read` calls for applicable specs/checklist. Only
61
62
  successful paired reads count as “已读取规范文件”; summaries do not. List each path/
62
- section in `Checked Items`; search/read `openspec/` before accepting conventions.
63
+ section in `Checked Items`; search/read both openspec specification directories
64
+ before accepting conventions.
63
65
 
64
66
  ```markdown
65
67
  VERDICT: pass
@@ -9,8 +9,8 @@
9
9
  ## Project Fit
10
10
 
11
11
  - Reuse components, hooks, API helpers, mocks, schemas, router patterns, tokens, and theme rules.
12
- - Cite knowledge base and `openspec/` as parallel sources; failed or empty
13
- knowledge queries must still search `<repoRoot>/openspec/**`.
12
+ - Cite knowledge base, `openspec/schemas/`, `openspec/project-specs/`, and `ai_workspace/` as parallel sources; failed or empty
13
+ knowledge queries must still search `<repoRoot>/openspec/schemas/`, `<repoRoot>/openspec/project-specs/`, and `<repoRoot>/ai_workspace/`.
14
14
  - Record source status, query terms, paths/headings, conflicts, authorized deps, and allowed paths for both.
15
15
 
16
16
  ## Interaction / Quality
@@ -36,6 +36,6 @@
36
36
 
37
37
  ## Verdict Matrix
38
38
 
39
- - Request revision for coverage gaps, unsafe scope, unauthorized deps, unresolved required interaction, missing required verification, skipped `openspec/` fallback, unsafe/missing Mock strategy, or Mock evidence presented as real integration.
40
- - Knowledge-base unavailable but relevant `openspec/` rules applied is advisory only.
39
+ - Request revision for coverage gaps, unsafe scope, unauthorized deps, unresolved required interaction, missing required verification, skipped local specification fallback (`openspec/schemas/`, `openspec/project-specs/`, or `ai_workspace/`), unsafe/missing Mock strategy, or Mock evidence presented as real integration.
40
+ - Knowledge-base unavailable but relevant OpenSpec or `ai_workspace/` rules applied is advisory only.
41
41
  - Optional cleanup that cannot affect acceptance is advisory.
@@ -23,8 +23,8 @@ Read all required references before running any listed frontend node.
23
23
  ## Source And Evidence Rules
24
24
 
25
25
  Use task sources/references, constraints, then `task.json`. Follow `design-spec.md`:
26
- knowledge base; `<repoRoot>/openspec/**` after unavailable/failed/empty; then repo
27
- evidence. Cite tight paths/symbols, label gaps/conflicts, and never invent APIs,
26
+ query the knowledge base when available and always inspect `openspec/schemas/`,
27
+ `openspec/project-specs/`, and `ai_workspace/`; then use repo evidence. Cite tight paths/symbols, and never invent APIs,
28
28
  rules, commands, or retrievals. Scout/planners locate and explicitly read applicable
29
29
  specs; only successful paired reads count. Lockfile-only, fixture-only, or unread
30
30
  search hits do not prove a reusable Mock service.
@@ -1,9 +1,10 @@
1
1
  # Frontend Code Standards
2
2
 
3
3
  Discover rules from task constraints, `design-spec.md` source order, config, code,
4
- tests, manifests, and generated types. After knowledge-base failure, applicable
5
- `<repoRoot>/openspec/**` rules are normative. Preferences are not rules, and docs do
6
- not override installed APIs without an explicit compatibility decision.
4
+ tests, manifests, and generated types. Regardless of knowledge-base results,
5
+ applicable `openspec/schemas/`, `openspec/project-specs/`, and `ai_workspace/` rules are normative.
6
+ Preferences are not rules, and docs do not override installed APIs without an
7
+ explicit compatibility decision.
7
8
 
8
9
  ## Discover And Cite
9
10
 
@@ -2,22 +2,22 @@
2
2
 
3
3
  ## Required Source Sequence
4
4
 
5
- Knowledge base and `openspec/` are parallel specification sources:
5
+ Knowledge base, OpenSpec, and `ai_workspace/` are parallel specification sources:
6
6
 
7
7
  1. Attempt the configured component/design knowledge-base query first when a
8
8
  connector is available in the execution environment.
9
9
  2. Regardless of knowledge-base success, failure, timeout, no match, or no
10
- configuration, also recursively search the project root's exact `openspec/`
11
- directory for index files and task-relevant specification content.
10
+ configuration, also recursively search `openspec/schemas/`,
11
+ `openspec/project-specs/`, and `ai_workspace/` for index files and relevant content.
12
12
  3. Treat relevant matches from both sources as the current project's
13
13
  specification for this run.
14
14
  4. Only then use component source, tokens, stories, tests, and pages as
15
15
  non-normative repository fallback.
16
16
 
17
- Never skip `openspec/` directly to neighboring-code conventions, even when a
18
- knowledge-base query returned results. Report source conflicts instead of
19
- combining them. Explicit task requirements remain the contract; flag conflicts
20
- with knowledge-base or `openspec/` rules.
17
+ Never skip local OpenSpec or `ai_workspace/` sources for neighboring-code
18
+ conventions, even when a knowledge-base query returned results. Report source
19
+ conflicts instead of combining them. Explicit task requirements remain the
20
+ contract; flag conflicts with knowledge-base or openspec specification rules.
21
21
 
22
22
  ## Knowledge Base Connection — TODO
23
23
 
@@ -25,15 +25,19 @@ Request format is undecided. TODO: define connector/owner, namespaces, secret-fr
25
25
  auth, query fields, result identity/version/time, and failure behavior.
26
26
 
27
27
  Attempt only a connector actually available in the execution environment. Otherwise
28
- record `not-configured` and run the `openspec/` fallback; never invent a connection.
28
+ record `not-configured` and run the openspec fallback; never invent a connection.
29
29
 
30
- ## `openspec/` Fallback Procedure
30
+ ## openspec Fallback Procedure
31
31
 
32
- - Confirm whether `<repoRoot>/openspec/` exists and enumerate its files recursively.
33
- - Read indexes first, then search names/content using task, route, component, interaction, theme, token, and state terms.
32
+ - Inspect `<repoRoot>/openspec/schemas/`, `<repoRoot>/openspec/project-specs/`,
33
+ and `<repoRoot>/ai_workspace/` when present; enumerate supported files recursively.
34
+ - Read indexes first, then search names/content using task, route, component,
35
+ interaction, theme, token, and state terms.
34
36
  - Read relevant matches in context; do not treat a filename-only hit as a rule.
35
- - Record search terms, inspected/matched paths, headings or tight line ranges, applied rules, and conflicts.
36
- - If the directory or relevant rules are absent, record that fact before using repository fallback.
37
+ - Record search terms, inspected/matched paths, headings or tight line ranges,
38
+ applied rules, and conflicts.
39
+ - If both directories or relevant rules are absent, record that fact before using
40
+ repository fallback.
37
41
 
38
42
  ## Retrieval Evidence
39
43
 
@@ -50,5 +54,6 @@ and conflicts. `openspec fallback` includes terms, paths/headings/lines, rules,
50
54
 
51
55
  - Reuse confirmed primitives unless a new pattern is authorized.
52
56
  - Define applicable states and responsive behavior before implementation.
53
- - Cite knowledge-base or `openspec/` evidence for component/token choices; label weaker repository fallback.
57
+ - Cite knowledge-base or openspec specification evidence for component/token
58
+ choices; label weaker repository fallback.
54
59
  - Make deviations and unresolved gaps explicit.
@@ -5,7 +5,7 @@ Pre-write nodes are read-only. Preserve IDs, labels, commands, language, require
5
5
  ## Core nodes
6
6
 
7
7
  - **`frontend-contract-pi`**: `Scope`, `Non-goals`, `Acceptance Criteria`, `UI States`, `Target Runtime Environment`, `Risks`, `Verification Expectations`. No guessed requirements.
8
- - **`frontend-scout-pi`**: routes, components, tokens, data/API/Mock, scripts, tests, assets. Fact vs inference vs gap. Knowledge base first; else search+read `<repoRoot>/openspec/**` before repo fallback. Output stack, routes, components, styling, conventions, state/data, test entry points, reuse, risks.
8
+ - **`frontend-scout-pi`**: routes, components, tokens, data/API/Mock, scripts, tests, assets. Fact vs inference vs gap. Query the knowledge base when available and always search+read `openspec/schemas/`, `openspec/project-specs/`, and `ai_workspace/` before repo fallback. Output stack, routes, components, styling, conventions, state/data, test entry points, reuse, risks.
9
9
  - **`frontend-plan-pi` + conditional design loop**: AC → steps, in-bound files, UI states, reuse, deps, Mock/API strategy, activation/rollback, frozen verify entrypoints, real-integration gap, and exactly one `frontend-implementation-contract-v1` JSON object. Prefer native Mock; browser intercept only with existing e2e; request-adapter only for a reversible seam. `auto` may select `not-needed` when no project Mock capability exists, while keeping real requests default and recording the gap; `required` cannot. Initial design pass uses the original plan; only exact `request-revision` runs read-only revision plus final review. Small-risk runs one design review only.
10
10
  - **`frontend-prewrite-gate-shell`**: the sole write authorization. Resolve effective plan/review, require exact pass, retain every REQ/BR/AC id, enforce Mock policy, validate schema/source binding, and materialize `contracts/frontend-implementation-contract.json`. Fallback is allowed only when a conditional primary is absent; an existing malformed primary fails closed. Generation-time blocked Mock produces one deterministic blocking shell node and no writer.
11
11
  - **`frontend-implement-pi`**: sole exclusive writer. Stay in `writeSet`; real requests default-on; Mock reversible, dev/test-only, production-off. Atomic handler/intercept/adapter with consumer+tests. Stop on forbidden paths or guesses. Output changed files, behavior, UI states, styling notes, verification attempted, residual risks. Optional mock-verify when frozen; static+behavior always; behavior must prove page consumption. Skipped-Mock `not-needed` keeps real integration pending unless the real backend path has fresh evidence.
@@ -22,4 +22,4 @@ Only `eligible=true` runs `frontend-repair-pi` (same writeSet as implement; no r
22
22
 
23
23
  ## Risk & capability (M4–M6)
24
24
 
25
- Deterministic risk (no model); high-risk beats small; supervised never small. Standard/high-risk contain 15 top-level nodes; small contains 13 by omitting revision and final review. Capability seed injects adapters; openspec/task sources outrank. A11y: static/component tools only when present; Browser a11y always not-run.
25
+ Deterministic risk (no model); high-risk beats small; supervised never small. Standard/high-risk contain 15 top-level nodes; small contains 13 by omitting revision and final review. Capability seed injects adapters; openspec specs and task sources outrank adapter guidance. A11y: static/component tools only when present; Browser a11y always not-run.
@@ -12,9 +12,8 @@ references:
12
12
  Use for `frontend-review-pi`; read the findings guide first. Required inputs are
13
13
  original task/reference material, effective plan/design branch, implementation summary,
14
14
  and `contracts/frontend-review-context.json`. That canonical context binds the validated
15
- implementation contract, effective initial-or-post-repair verification trace, repair
16
- assessment, and run-owned actual diff. Treat its diff as authoritative; never invent a
17
- diff from an implementation summary alone.
15
+ implementation contract, effective verification trace, repair assessment, optional
16
+ `frontend-lint-assessment-v1`, and run-owned diff. The diff is authoritative.
18
17
 
19
18
  ## Verdict Contract
20
19
 
@@ -27,42 +26,30 @@ required check, forbidden write, or unmet acceptance criterion forces revision.
27
26
  - Compare intent, contract, plan, diff, and evidence; report altered requirements.
28
27
  - Inspect every changed file against allowed, forbidden, and approved write scope.
29
28
  - Map criteria to behavior, applicable UI states, tests, and shell evidence.
30
- - Review state/data flow, validation, async/error behavior, components/design, responsive behavior, accessibility, dependencies, maintenance, and regression risk when applicable.
29
+ - Review state/data flow, validation, async/error behavior, design, responsive/a11y,
30
+ dependencies, maintenance, and regression risk when applicable.
31
31
  - Inspect static, behavior, and available Mock-specific artifacts directly. For Mock
32
32
  strategies, compare the endpoint matrix, handler/fixture/adapter and consumer diff;
33
33
  require the real request as default, contract-aligned fixtures, production isolation,
34
34
  and no false real-integration claim. `not-needed` needs applicable real/no-remote
35
35
  evidence, or an explicit default-auto skipped-Mock rationale with the Real
36
36
  Integration Gap preserved when no project Mock capability is confirmed.
37
- - Component/design claims require traceable evidence from two parallel sources:
38
- knowledge base and `<repoRoot>/openspec/**`. Query the knowledge-base connector
39
- when available; regardless of result, also read `<repoRoot>/openspec/**`.
40
- The connector format is TODO; never claim a query or fallback search without
41
- evidence. Execute explicit `grep`/`find` to locate spec files and `read` to
42
- load them before referencing their rules. Only successful `read` tool calls are
43
- observable as "已读取规范文件" in the spec-evidence inspector.
37
+ - Inspect lint assessment directly. `baseline-debt` requires intact evidence, only
38
+ baseline-matched diagnostics on unchanged files, and none on writer-changed files.
39
+ Report debt, never `lint passed`; `failed`/`unavailable` blocks. Typecheck, build,
40
+ and test still require successful final exits.
41
+ - Component/design claims need both knowledge-base and local openspec evidence. Query
42
+ the connector when available and always read task-relevant files under
43
+ `<repoRoot>/openspec/schemas/`, `<repoRoot>/openspec/project-specs/`, and `<repoRoot>/ai_workspace/`.
44
+ Connector format is TODO; never invent evidence. Only successful `read` calls are
45
+ observable as "已读取规范文件".
44
46
  - Treat shell exit status as authoritative. Do not edit files.
45
47
 
46
48
  ## Evidence And Output
47
49
 
48
50
  Findings cite a tight file location, exact command/result, or named DAG artifact.
49
- Separate confirmed defects, missing evidence, and residual risks.
50
-
51
- ```markdown
52
- VERDICT: request-revision
53
-
54
- ## Findings
55
- - [Important] `path:line` — issue, impact, and required correction.
56
-
57
- ## Verification Assessment
58
- - ...
59
-
60
- ## UX Assessment
61
- - ...
62
-
63
- ## Residual Risks
64
- - ...
65
- ```
51
+ Separate confirmed defects, missing evidence, and residual risks using Findings,
52
+ Verification Assessment, UX Assessment, and Residual Risks headings.
66
53
 
67
54
  A pass requires no Critical/Important findings and all required shell checks passed.
68
55
  Still report knowledge-source status and optional browser/manual gaps.