@tea-agent/loop-agent 0.25.3 → 0.25.5

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 (49) hide show
  1. package/AGENTS.md +6 -0
  2. package/CHANGELOG.md +55 -0
  3. package/dist/application/dag/args.js +21 -1
  4. package/dist/application/dag/run-dag.js +1 -0
  5. package/dist/cli/command-definitions.js +1 -1
  6. package/dist/cli/program.js +82 -63
  7. package/dist/commands/client-recovery.js +209 -62
  8. package/dist/commands/init.js +206 -82
  9. package/dist/commands/run-dag-progress.js +109 -0
  10. package/dist/commands/run-dag.js +16 -5
  11. package/dist/executors/dag-pi-executor.js +80 -15
  12. package/dist/executors/model-routing.js +1 -1
  13. package/dist/executors/shell-executor.js +159 -0
  14. package/dist/executors/shell-write-guard.js +21 -7
  15. package/dist/worker/console/repo-fingerprint.js +7 -1
  16. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +964 -0
  17. package/dist/workflows/dag/backend-test-case-manifest.js +39 -1
  18. package/dist/workflows/dag/backend-test-markdown-workflow.js +306 -30
  19. package/dist/workflows/dag/backend-test-result-contract.js +35 -9
  20. package/dist/workflows/dag/convergence/controller.js +134 -9
  21. package/dist/workflows/dag/frontend-test-case-checklist.js +71 -0
  22. package/dist/workflows/dag/frontend-test-html-report.js +77 -0
  23. package/dist/workflows/dag/frontend-test-l5-report.js +138 -0
  24. package/dist/workflows/dag/frontend-test-result-contract.js +44 -1
  25. package/dist/workflows/dag/init-hybrid.js +267 -80
  26. package/dist/workflows/dag/node-execution.js +64 -11
  27. package/dist/workflows/dag/prompt.js +118 -4
  28. package/dist/workflows/dag/retry-policy.js +5 -4
  29. package/dist/workflows/dag/scheduler.js +32 -5
  30. package/dist/workflows/dag/types.js +10 -3
  31. package/dist/workflows/dag/validate.js +6 -3
  32. package/docs/architecture/dag-execution.md +7 -4
  33. package/docs/architecture/runtime-boundaries.md +1 -1
  34. package/docs/templates/agent-dag.base.json +1 -1
  35. package/docs/templates/agent-dag.final-verification.json +1 -1
  36. package/docs/templates/agent-dag.schema.json +6 -0
  37. package/docs/templates/agent-dag.supervised-implementation.json +1 -1
  38. package/docs/templates/backend-test-dag.json +40 -13
  39. package/docs/templates/backend-test-dag.review-cases.prompt.md +1 -1
  40. package/docs/templates/frontend-test-dag.json +62 -5
  41. package/docs/templates/hybrid-dag.json +1 -1
  42. package/examples/decision-gate-agent-dag.json +1 -1
  43. package/examples/example-dag.json +1 -1
  44. package/examples/hybrid-loop-agent-dag.json +1 -1
  45. package/harness.json +3 -2
  46. package/package.json +1 -1
  47. package/skills/loop-agent/references/command-reference.md +2 -1
  48. package/skills/loop-agent/references/hybrid-dag.md +2 -2
  49. package/skills/loop-agent/references/model-routing.md +1 -1
@@ -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 over only the safe scripts explicitly mapped by final Markdown cases.",
31
+ "backend-test-dag uses exactly 9 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, advisory Markdown validation, advisory traceability, pytest-html, HTML and execution facts are deterministic evidence. Nodes 4 and 6 record findings without blocking nodes 5, 7 or 8.",
33
+ "Environment, advisory Markdown validation/coverage, advisory traceability/correspondence, canonical manifest, pytest-html, HTML and execution facts are deterministic evidence. Nodes 4 and 6 record findings without blocking nodes 5, 7 or 8; node 7 partial/unavailable does not block node 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,7 +68,7 @@
68
68
  "executorModels": {
69
69
  "pi": {
70
70
  "LOW": "gpt-5.3-codex-spark",
71
- "MED": "glm-5.2",
71
+ "MED": "gpt-5.5",
72
72
  "HIGH": "gpt-5.5"
73
73
  }
74
74
  },
@@ -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>|<中文用例名称>`. 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\nName each module file with a stable lowercase business stem such as `testcase/md/health.md` or `testcase/md/resource_notes.md`. Do not use Case-ID-like module filenames such as `BE-HEALTH.md` or `BE-NOTES.md`. For every automatable case, `自动化映射` must name exactly `testcase/test_<module>.py`, where <module> is that Markdown filename without `.md`, lowercased, with non-alphanumeric characters replaced by underscores. Example: `testcase/md/health.md` → `testcase/test_health.py`; `testcase/md/resource_notes.md` → `testcase/test_resource_notes.py`. Never invent a different pytest path in Markdown than the module stem implies.\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, and keep the script path identical to the module one-to-one path above. 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\nBefore writing cases, build a mandatory machine-readable Coverage Matrix. Its section heading line must be exactly `## Coverage Matrix` with no numeric prefix/suffix. Use this exact header: `| Rule Key | Priority | Source | Endpoint/Field | Dimension | Rule | Required Test Points | Case IDs | Status |`. Every data row must contain exactly 9 pipe-delimited cells and must never omit `Dimension`; use concise dimensions such as requirement, operation, response-status, requiredness, enum, boundary, format, business-state or error. Use only P0/P1/P2 and COVERED/PARTIAL/GAP/CONFLICT. Use stable `TP-<UPPERCASE-HYPHENATED-ID>` test points separated by semicolons.\n\nEach Rule Key must appear in exactly one Matrix row. Preserve each AC/REQ/BR Rule Key as one row; if one product rule spans multiple dimensions, use a concise composite Dimension in that single row instead of duplicating the key. Derive OpenAPI Rule Keys exactly as the deterministic analyzer does: operation token is `<HTTP-METHOD>-<PATH>` with braces removed and every non-alphanumeric run replaced by a hyphen, uppercase (for example POST `/api/resource-notes` → `POST-API-RESOURCE-NOTES`); response statuses use `API-<OPERATION>-RESPONSE-STATUS`; body/parameter fields use `API-<OPERATION>-<FIELD>-REQUIRED|ENUM|MIN-LENGTH|MAX-LENGTH|MINIMUM|MAXIMUM|PATTERN|FORMAT`. Do not invent aliases such as API-CREATE-FIELDS when a deterministic key applies.\n\nCoverage priority is strict: P0 product requirements/task hard constraints first; P1 exhaustively supplements documented API operations, fields, business rules, statuses and errors; P2 adds bounded protocol robustness only when it does not invent product behavior. Conflicts or undefined expectations must stay visible as GAP/CONFLICT with precise source pointers, never guessed.\n\nFor uniqueness/lifecycle rules cover absent, active-existing, deleted-existing, create-delete-recreate, restore-then-recreate and documented scope/case-normalization states. For every enum cover every valid value plus bounded invalid equivalence classes (unknown, case variant, whitespace, empty, null/missing and wrong types as applicable). For every length/number rule cover min-1, min, nominal, max and max+1. For format rules cover each allowed class separately plus a valid mixed value, and representative forbidden classes including uppercase, internal/leading/trailing whitespace, tab/newline, unsupported punctuation, slash, emoji or control characters when the source contract supports that expectation.\n\nWrite each module as readable case cards. Every case starts with `## BE-<MODULE>-<NNN>|<中文用例名称>`. `<NNN>` is exactly three zero-padded digits (`001`, `002`, ...), never two digits (`01`) and never a bare number. Every case must include `### 覆盖规则`, `### 测试点`, `### 场景类型`, `### 前置条件`, `### 操作步骤`, `### 预期结果`, and `### 自动化映射`; `覆盖规则` and `测试点` must reference exact Matrix Rule Keys/Test Points. Add `测试目的`, `验收标准`, `需求依据`, and `测试数据` for readable evidence. Every automatable case explicitly names its target pytest script so traceability scans only that script.\n\nName each module file with a stable lowercase business stem such as `testcase/md/health.md` or `testcase/md/resource_notes.md`. Do not use Case-ID-like module filenames such as `BE-HEALTH.md` or `BE-NOTES.md`. For every automatable case, `自动化映射` must name exactly `testcase/test_<module>.py`, where <module> is that Markdown filename without `.md`, lowercased, with non-alphanumeric characters replaced by underscores. Example: `testcase/md/health.md` → `testcase/test_health.py`; `testcase/md/resource_notes.md` → `testcase/test_resource_notes.py`. Never invent a different pytest path in Markdown than the module stem implies.\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, and keep the script path identical to the module one-to-one path above. 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 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 ‘符合预期’, Case-ID-like module filenames (for example `BE-HEALTH.md`), and missing or drifted script/function mapping where it can be derived.\n\nCorrect testcase/md/** directly: add documented omissions, remove unsupported cases, rename module files to stable lowercase stems when needed, fix automation mappings so each case points at `testcase/test_<module>.py` derived from that module filename, 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\nIndependently reconstruct P0 product scenarios and P1 documented API rules from authoritative sources before trusting the generated Coverage Matrix. Check every lifecycle/uniqueness state (including deleted-existing), every valid enum value, bounded invalid enum classes, min-1/min/nominal/max/max+1, allowed/forbidden format classes, required/null/missing/wrong-type semantics, endpoint, status/error codes, auth and state transitions. Directly add omissions; undefined expectations remain GAP/CONFLICT rather than invented behavior.\n\nCheck AC completeness/meaning, endpoint, fields/shape, status/error codes, rules, states, documented boundaries/auth, positive/negative coverage, executable steps and assertable results. Require the exact unnumbered `## Coverage Matrix` heading, exact headers, exactly 9 cells in every data row (including a non-empty Dimension), deterministic OpenAPI Rule Keys, exactly one Matrix row per Rule Key (merge multi-dimension product rows), and bidirectional Matrix Rule/Test Point ↔ Case bindings. Directly repair malformed headings/rows/keys rather than merely commenting on them. Reject avoidable English prose, duplicated bilingual wording, repeated boilerplate, oversized unstructured sections, vague results such as ‘符合预期’, Case-ID-like module filenames (for example `BE-HEALTH.md`), and missing or drifted script/function mapping where it can be derived.\n\nCorrect testcase/md/** directly: add documented omissions, remove unsupported cases, rename module files to stable lowercase stems when needed, normalize every Case ID to hyphen-separated module segments plus exactly three zero-padded digits (`BE-RESOURCE_NOTES-01` → `BE-RESOURCE-NOTES-001`) consistently across headings/index/mappings, fix automation mappings so each case points at `testcase/test_<module>.py` derived from that module filename, 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 as exact machine-readable identifiers; only normalize Case ID separator/sequence formatting as specified above. 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 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.",
172
+ "outputContract": "Run-owned reports/backend-md-case-validation.md, reports/backend-test-case-coverage-analysis.md and contracts/backend-test-case-coverage-facts.json with PASS/FAIL/UNAVAILABLE advisory facts; downstream execution continues.",
173
+ "subtask_prompt": "Record advisory findings for Markdown structure and deterministically analyze the final README Coverage Matrix against final Case rule/test-point bindings. Detect missing product/API rules, enum values, invalid equivalence classes, boundaries, format classes, business lifecycle states, GAP/CONFLICT and bidirectional Matrix/Case drift. Do not validate source-reference existence. Write human and machine evidence from the same facts. Keep quality findings advisory, but fail closed after writing the report when secret-shaped values are detected. Coverage FAIL stays advisory.",
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. Each testcase/md/<module>.md (excluding README.md) maps one-to-one to testcase/test_<module>.py; never merge or split modules. No JSON and no pytest execution.",
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\nName each generated pytest file so it corresponds one-to-one with its source Markdown module file: for each `testcase/md/<module>.md` (excluding README.md), emit exactly one `testcase/test_<module>.py`. The <module> stem is the Markdown filename without the `.md` extension, lowercased and with non-alphanumeric characters replaced by underscores. For example, `testcase/md/resource_notes.md` maps to `testcase/test_resource_notes.py`, `testcase/md/health.md` maps to `testcase/test_health.py`, `testcase/md/BE-HEALTH.md` maps to `testcase/test_be_health.py`, and `testcase/md/order-api.md` maps to `testcase/test_order_api.py`. If Markdown automation mapping names a different path than this module stem path, still write the module stem path and do not invent prefixes such as `test_be_*` unless the module filename itself normalizes to that stem. Never merge multiple Markdown modules into one pytest file, never split one module across several files, and never invent pytest filenames unrelated to the Markdown modules.\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`."
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 exactly one primary 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. When a Case has multiple `测试点`, use one parameterized primary symbol with stable `pytest.param(..., id=\"TP-...\")` IDs matching every Markdown Test Point, or split the Markdown into independent Cases before generation; do not create duplicate symbols for one Case. Enumerate the exact IDs from that Case's `测试点` section before writing parameters: every Markdown Test Point must appear once and no parameter ID may be invented, renamed or omitted. Assertions come only from 预期结果 and setup comes only from 前置条件/测试数据/自动化映射.\n\nName each generated pytest file so it corresponds one-to-one with its source Markdown module file: for each `testcase/md/<module>.md` (excluding README.md), emit exactly one `testcase/test_<module>.py`. The <module> stem is the Markdown filename without the `.md` extension, lowercased and with non-alphanumeric characters replaced by underscores. For example, `testcase/md/resource_notes.md` maps to `testcase/test_resource_notes.py`, `testcase/md/health.md` maps to `testcase/test_health.py`, `testcase/md/BE-HEALTH.md` maps to `testcase/test_be_health.py`, and `testcase/md/order-api.md` maps to `testcase/test_order_api.py`. If Markdown automation mapping names a different path than this module stem path, still write the module stem path and do not invent prefixes such as `test_be_*` unless the module filename itself normalizes to that stem. Never merge multiple Markdown modules into one pytest file, never split one module across several files, and never invent pytest filenames unrelated to the Markdown modules.\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 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.",
226
+ "outputContract": "Run-owned reports/backend-test-traceability.md, reports/backend-test-markdown-pytest-correspondence.md and contracts/backend-test-markdown-pytest-correspondence-facts.json with PASS/FAIL/UNAVAILABLE correspondence facts.",
227
+ "subtask_prompt": "Deterministically scan only Markdown-mapped pytest scripts. Keep the existing traceability/logging checks and also produce a bidirectional Markdown module/Case/Test Point pytest file/primary symbol/parameter ID correspondence analysis. Report 1:1, 1:0, 1:N, 0:1, script mismatch, missing Case ID and missing/extra parameter IDs. Human and machine evidence must come from the same facts. Findings are advisory and never block pytest.",
228
228
  "shell": {
229
229
  "commands": [],
230
230
  "backendTestPipeline": "markdown-traceability",
@@ -233,7 +233,7 @@
233
233
  }
234
234
  },
235
235
  {
236
- "id": "execute-backend-pytest-and-html-report-shell",
236
+ "id": "backend-test-case-manifest-shell",
237
237
  "depends_on": [
238
238
  "backend-test-traceability-gate-shell"
239
239
  ],
@@ -250,8 +250,35 @@
250
250
  ".harness/dag-runs/**",
251
251
  "artifacts/**"
252
252
  ],
253
+ "outputContract": "Run-owned contracts/backend-test-case-manifest.json with materializationStatus, sourceFactsIssues, validated coverageSummary, ruleCoverageSummary and correspondenceSummary; this is the single machine input for L-5 and closeout.",
254
+ "subtask_prompt": "Materialize the canonical Backend Test Case Manifest only from contracts/backend-test-case-coverage-facts.json and contracts/backend-test-markdown-pytest-correspondence-facts.json. Validate schema, task binding, input hashes and freshness; never re-read source semantics, re-analyze Coverage Matrix, rescan pytest symbols or recompute a second set of metrics. Missing/stale/conflicting facts produce partial/unavailable diagnostics rather than fabricated zeros.",
255
+ "shell": {
256
+ "commands": [],
257
+ "backendTestPipeline": "markdown-manifest",
258
+ "cwd": ".",
259
+ "timeoutMs": 60000
260
+ }
261
+ },
262
+ {
263
+ "id": "execute-backend-pytest-and-html-report-shell",
264
+ "depends_on": [
265
+ "backend-test-case-manifest-shell"
266
+ ],
267
+ "role": "verifier",
268
+ "executor": "shell",
269
+ "complexity": "LOW",
270
+ "writePolicy": "read-only",
271
+ "allowedPaths": [
272
+ "testcase/**",
273
+ "docs/test-reports/**"
274
+ ],
275
+ "forbiddenPaths": [
276
+ ".harness/**",
277
+ ".harness/dag-runs/**",
278
+ "artifacts/**"
279
+ ],
253
280
  "outputContract": "One scoped pytest execution over Markdown-mapped scripts producing a valid pytest-html report with per-case captured output, self-contained reports/backend-test.html, reports/backend-test.md, reports/backend-test-facts.md, a deterministic self-contained reports/backend-test-l5-dashboard.html (machine-computed L-5 metrics, no JSON), and an optional contracts/code-coverage-v1.json when jacocoCoverage is configured (JaCoCo TCP dump → jacoco.xml → parsed; failure-safe); 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. Prefer the deterministic module one-to-one path when a mapped script is missing but the module stem file exists. Generate a native pytest-html self-contained report, then render the primary self-contained Chinese HTML report from the same pytest-html 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.",
281
+ "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. Prefer the deterministic module one-to-one path when a mapped script is missing but the module stem file exists. Generate a native pytest-html self-contained report, then render the primary self-contained Chinese HTML report from the same pytest-html plus final Markdown case metadata without rerun. Keep 测试结论 and quality status; make node 4 Markdown validation + case coverage and node 6 traceability + Markdown-to-pytest correspondence expandable to their full escaped details; show each failure overview item with its original pytest message plus deterministic evidence-based reason analysis; list failure/error case cards before the remaining cases while preserving stable order. Each polished per-case result card includes 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
282
  "shell": {
256
283
  "commands": [
257
284
  "mkdir -p \"${HARNESS_DAG_RUN_DIR}/reports\"; echo \"pytest targets are resolved at runtime from final Markdown 自动化映射\""
@@ -284,7 +311,7 @@
284
311
  "artifacts/**"
285
312
  ],
286
313
  "outputContract": "Final Markdown report and L-5 conclusion under docs/test-reports/**; the deterministic L-5 dashboard at reports/backend-test-l5-dashboard.html is the authoritative visualization and must be linked, not re-rendered; no JSON.",
287
- "subtask_prompt": "Generate the final Markdown report from upstream facts and run-owned environment, advisory case-validation, advisory traceability, pytest-html 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\nThe L-5 metrics and visualization are already produced deterministically by node 7 at reports/backend-test-l5-dashboard.html (rendered from computeL5ReportMetrics). Link to that dashboard as the authoritative L-5 view; do not recompute pass/AC/automation/coverage numbers or re-render an HTML dashboard yourself. Quote its L-5 decision verbatim.\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 availability, and L-5 READY/NOT READY.\n\nNever override Shell/pytest-html facts. L-5 requires pass=100%, AC=100%, automation>=90%, line>=80%, branch>=70%, skipped=0 and no blocking Critical risk.\n\nWrite only under docs/test-reports/**."
314
+ "subtask_prompt": "Generate the final Markdown report only from authoritative run-owned artifacts. Read node 1 reports/backend-test-environment.md; node 4 backend-md-case-validation.md and backend-test-case-coverage-analysis.md; node 6 backend-test-traceability.md and backend-test-markdown-pytest-correspondence.md; node 7 contracts/backend-test-case-manifest.json; and node 8 backend-test-result.json, backend-test-facts.md, pytest-html/HTML and L-5 dashboard. Do not use node 2/3/5 assistant prose as facts. 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\nThe L-5 metrics and visualization are produced deterministically by node 8 at reports/backend-test-l5-dashboard.html. Link to that dashboard as the authoritative L-5 view. Pytest execution facts come from node 8; coverage/correspondence numbers and materializationStatus come from node 7; detailed coverage findings come from node 4; detailed mapping findings come from node 6. Never recompute these values. If machine manifest and human reports disagree, report evidence inconsistency rather than silently choosing.\n\nAlways state the exact PASS/FAIL/UNAVAILABLE status and findings from node 4 case validation + coverage and node 6 traceability + correspondence. Their FAIL status does not block pytest, but it must remain visible 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 availability, and L-5 READY/NOT READY.\n\nNever override Shell/pytest-html facts. L-5 requires pass=100%, AC=100%, automation>=90%, line>=80%, branch>=70%, skipped=0 and no blocking Critical risk.\n\nWrite only under docs/test-reports/**."
288
315
  }
289
316
  ],
290
317
  "sourceBinding": {
@@ -11,7 +11,7 @@
11
11
  ### 阅读体验
12
12
 
13
13
  - `testcase/md/README.md` 是简洁入口,包含测试目标、环境、隔离/清理策略、模块汇总和可跳转的用例索引。
14
- - 模块文件采用中文用例卡片;每条以 `## BE-<MODULE>-<NNN>|<中文用例名称>` 开始。
14
+ - 模块文件采用中文用例卡片;每条以 `## BE-<MODULE>-<NNN>|<中文用例名称>` 开始;`<NNN>` 必须是三位补零序号(`001`,禁止 `01`)。Reviewer 发现两位序号或模块下划线时,必须在标题、README 索引与自动化映射中一致规范化(如 `BE-RESOURCE_NOTES-01` → `BE-RESOURCE-NOTES-001`)。
15
15
  - 新文档优先使用:`测试目的`、`验收标准`、`需求依据`、`前置条件`、`测试数据`、`操作步骤`、`预期结果`、`自动化映射`。
16
16
  - validator 同时接受上述中文分节和历史英文分节;机器 ID、HTTP 方法、路径、字段、枚举、文件名、函数名与 source citation 必须保持精确。
17
17
  - 步骤和预期可以用紧凑表格,也可以分别使用编号/项目列表;必须可执行、可独立断言。
@@ -251,11 +251,10 @@
251
251
  "artifacts/**"
252
252
  ],
253
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
- "subtask_prompt": "Scan generated cases/manifest against the shared blocking checklist. Runtime hybrid embeds the authoritative script.",
254
+ "subtask_prompt": "Run the native deterministic frontend case checklist without spawning Bash, PowerShell, or node -e.",
255
255
  "shell": {
256
- "commands": [
257
- "node -e \"console.log('template placeholder: runtime hybrid embeds checklist')\""
258
- ],
256
+ "commands": [],
257
+ "frontendTestCaseChecklist": {},
259
258
  "cwd": ".",
260
259
  "timeoutMs": 120000
261
260
  }
@@ -429,7 +428,8 @@
429
428
  {
430
429
  "id": "frontend-test-retrospect-pi",
431
430
  "depends_on": [
432
- "finalize-frontend-test-result-shell"
431
+ "finalize-frontend-test-result-shell",
432
+ "frontend-test-l5-report-shell"
433
433
  ],
434
434
  "executor": "pi",
435
435
  "role": "closeout",
@@ -448,6 +448,63 @@
448
448
  ],
449
449
  "outputContract": "Write testcase/frontend/reports/frontend-test-retrospect-<date>.md with coverage, pass/fail/blocked, execution evidence review, risks, findings, and A/B/C/D rating — even when outcome is failed/incomplete.",
450
450
  "subtask_prompt": "Write the frontend test retrospective under testcase/frontend/reports/ after result materialization (do not wait for outcome=pass). Combine AC→case→browser-evidence review with the closeout report. Blocked cases never count as passed. Do not write docs/**."
451
+ },
452
+ {
453
+ "id": "frontend-test-l5-report-shell",
454
+ "depends_on": [
455
+ "finalize-frontend-test-result-shell"
456
+ ],
457
+ "executor": "shell",
458
+ "role": "verifier",
459
+ "complexity": "LOW",
460
+ "writePolicy": "exclusive",
461
+ "writeSet": [
462
+ "testcase/frontend/reports/**"
463
+ ],
464
+ "allowedPaths": [
465
+ "testcase/frontend/**"
466
+ ],
467
+ "forbiddenPaths": [
468
+ ".harness/**",
469
+ "artifacts/**"
470
+ ],
471
+ "outputContract": "Deterministic frontend L-5 Markdown and self-contained HTML dashboard derived only from frontend-test-result-v1.",
472
+ "subtask_prompt": "Render the authoritative frontend L-5 report from frontend-test-result-v1. Do not use Pi prose or invent code coverage. Missing line/branch coverage remains unavailable and makes L-5 NOT READY.",
473
+ "shell": {
474
+ "commands": [],
475
+ "frontendTestL5Report": {},
476
+ "cwd": ".",
477
+ "timeoutMs": 120000
478
+ }
479
+ },
480
+ {
481
+ "id": "frontend-test-html-report-shell",
482
+ "depends_on": [
483
+ "frontend-test-retrospect-pi",
484
+ "frontend-test-l5-report-shell"
485
+ ],
486
+ "executor": "shell",
487
+ "role": "verifier",
488
+ "complexity": "LOW",
489
+ "writePolicy": "exclusive",
490
+ "writeSet": [
491
+ "testcase/frontend/reports/**"
492
+ ],
493
+ "allowedPaths": [
494
+ "testcase/frontend/**"
495
+ ],
496
+ "forbiddenPaths": [
497
+ ".harness/**",
498
+ "artifacts/**"
499
+ ],
500
+ "outputContract": "Write frontend-test-report.md and frontend-test-report.html containing only case execution results, case content, and failed/blocked error analysis.",
501
+ "subtask_prompt": "Render the formal frontend test report from frontend-test-result-v1 without evidence chains, advisory findings, suggestions, or ratings.",
502
+ "shell": {
503
+ "commands": [],
504
+ "frontendTestHtmlReport": {},
505
+ "cwd": ".",
506
+ "timeoutMs": 120000
507
+ }
451
508
  }
452
509
  ]
453
510
  }
@@ -55,7 +55,7 @@
55
55
  "executorModels": {
56
56
  "pi": {
57
57
  "LOW": "gpt-5.3-codex-spark",
58
- "MED": "glm-5.2",
58
+ "MED": "gpt-5.5",
59
59
  "HIGH": "gpt-5.5"
60
60
  }
61
61
  },
@@ -55,7 +55,7 @@
55
55
  "executorModels": {
56
56
  "pi": {
57
57
  "LOW": "gpt-5.3-codex-spark",
58
- "MED": "glm-5.2",
58
+ "MED": "gpt-5.5",
59
59
  "HIGH": "gpt-5.5"
60
60
  }
61
61
  },
@@ -4,7 +4,7 @@
4
4
  "executorModels": {
5
5
  "pi": {
6
6
  "LOW": "gpt-5.3-codex-spark",
7
- "MED": "glm-5.2",
7
+ "MED": "gpt-5.5",
8
8
  "HIGH": "gpt-5.5"
9
9
  }
10
10
  },
@@ -56,7 +56,7 @@
56
56
  "executorModels": {
57
57
  "pi": {
58
58
  "LOW": "gpt-5.3-codex-spark",
59
- "MED": "glm-5.2",
59
+ "MED": "gpt-5.5",
60
60
  "HIGH": "gpt-5.5"
61
61
  }
62
62
  },
package/harness.json CHANGED
@@ -58,8 +58,9 @@
58
58
  "executors": {
59
59
  "pi": {
60
60
  "description": "Pi planning, review, diagnosis, and bounded writing when DAG toolProfile=write",
61
- "LOW": "grok-4.5",
62
- "MED": "grok-4.5",
61
+ "defaultModel": "minimax-m3",
62
+ "LOW": "minimax-m3",
63
+ "MED": "gpt-5.5",
63
64
  "HIGH": "gpt-5.6-sol"
64
65
  }
65
66
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tea-agent/loop-agent",
3
- "version": "0.25.3",
3
+ "version": "0.25.5",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "loop-agent": "bin/loop-agent.js",
@@ -294,7 +294,8 @@ loop-agent dag validate --dag <temp-dir>/hybrid-dag.json --strict-governance --s
294
294
  loop-agent dag validate --dag ai_workspace/loop-agent/templates/agent-dag.supervised-implementation.json --strict-models --strict-governance # role=supervisor + write-set-gate topology
295
295
  cp ai_workspace/loop-agent/templates/agent-dag.supervised-implementation.json <temp-dir>/supervised-dag.json
296
296
  (npx vitest run test/dag-supervised-template.test.ts test/dag-validate.test.ts test/dag-shell-executor.test.ts --reporter=dot) # supervised template + shell.verdictGate runtime
297
- loop-agent run-dag --dag <temp-dir>/hybrid-dag.json --cwd <repo-root> # 执行 Agent DAG
297
+ loop-agent run-dag --dag <temp-dir>/hybrid-dag.json --cwd <repo-root> # 执行 Agent DAG;stderr 默认输出节点进度与 30s 心跳,stdout 保持最终 JSON
298
+ loop-agent run-dag --dag <temp-dir>/hybrid-dag.json --cwd <repo-root> --progress-interval-ms 60000 # 调整心跳;--quiet 可禁用
298
299
  loop-agent run-dag --dag <temp-dir>/hybrid-dag.json --init-only --canvas-path <temp-dir>/hybrid-dag.canvas.tsx # 可选 derived Canvas view
299
300
  bash scripts/run-dag-safe.sh --dag <temp-dir>/hybrid-dag.json --cwd <repo-root> [--timeout-secs 7200] # 后台运行 + 轮询,避免外层 bash timeout 杀进程(见 agent-dag-runner.md §Adaptive liveness)
300
301
  loop-agent dag init-hybrid <task-id> # 生成可审阅的 DAG draft
@@ -67,7 +67,7 @@ loop-agent run-dag --dag <temp-dir>/hybrid-dag.json --init-only --canvas-path <t
67
67
 
68
68
  - **常规 validation**:`dag validate --dag <path>` 做 schema/topology/ranks。JSON 输出含 `governanceProfile`(确定性 `minimal|standard|reviewed|supervised` 推断,含 `process` / `delivery` / `codeChange` signal 与 `reasons`),及 model-matrix drift、governance lint(如 read-only artifact-boundary drift 或 DAG 内 `check-repo.sh` shell env drift)的 warnings。手写临时 DAG spec 执行前用 `dag validate --dag <path> --strict-models`;governance warning 应 fail fast 时加 `--strict-governance`。含 `executor: "cursor"` 的旧 DAG 会在 schema 校验失败;默认生成 DAG 使用 `pi` read-only / Pi write profile / shell。仅当有意在 `.harness/dag-runs/active/` 要 active run snapshot 时用 `run-dag --dry-run`。
69
69
  - **Governance profile 推断与 routing(code vs skill 分工)**:`./src/workflows/dag/governance-profile.ts` 从 DAG 结构与 write scope 做 **硬确定性推断**。JSON 输出 **报告** `process` / `delivery` / `codeChange` signal 与人类可读 `reasons`;`profile` tier(`minimal|standard|reviewed|supervised`)仅由该模块 code rule 选择(如多个 exclusive writer、repair node、review-gate topology、`loop-agent-runtime-paths`、`scripts-ci-harness-paths`、weak post-implementation shell verification、supervised topology)。baseline `forbiddenPaths`(`.harness/**`、`.harness/dag-runs/**`、`artifacts/**`)是默认 governance,**本身不是** process-risk signal。skill prompt 与本 reference **解释** tier 并摘要 profile 选择原因;不替代 code 推断。`dag run-task` 转发 embedded validate step 的同一 candidate `governanceProfile`。`dag run-task --profile auto` 先将 candidate profile 经 `harness.json.workflowPolicy.dag.profileRouting` 映射,再在 candidate delivery signal 含 `loop-agent-runtime-paths`、`scripts-ci-harness-paths` 或 `public-contract-paths` 时应用 M4 `supervised-quality-gate` promotion;`profileRouting.routingReasons` 记录确定性 reason。无 profile `dag run-task <task-id>` 仍为 standard-compatible;显式 `--profile minimal|standard|reviewed|supervised` 与自动 promotion 记录治理强度,已识别的前端业务 workflow 仍使用前端专用模板。高风险 task 应用 `--profile auto` 或显式 `--profile supervised`,而非显式 `--profile reviewed`。
70
- - **Executor model routing**:DAG spec 选 `executor` 与 `complexity`,可通过 `executorModels.pi` 覆盖 model 名;不选 provider。默认 routing:Pi LOW=`gpt-5.3-codex-spark`、MED=`glm-5.2`、HIGH=`gpt-5.5`。`shell` 不用 model,忽略 `executorModels`。
70
+ - **Executor model routing**:DAG spec 选 `executor` 与 `complexity`,可通过 `executorModels.pi` 覆盖 model 名;不选 provider。默认 routing:Pi LOW=`gpt-5.3-codex-spark`、MED=`gpt-5.5`、HIGH=`gpt-5.5`。`shell` 不用 model,忽略 `executorModels`。
71
71
  - **Active visibility**:真实 `run-dag` execution 在 run/node 转换时写 active `state.json`,归档前 core runner 暴露 isolated `DagRunObserver` hook 供 derived view。`.harness/dag-runs/completed/<run-id>/` / `paused/<run-id>/` 仍是 source of truth;observer 输出非 canonical。
72
72
  - **可选 Canvas**:传 `--canvas-path <abs-path>` 或 `--canvas <name>` 输出 derived `.canvas.tsx` live view。省略 flag 行为不变。`--init-only` + Canvas 无需 `CURSOR_API_KEY`。
73
73
 
@@ -232,7 +232,7 @@ review-heavy DAG 中长 shell stdout 可能掩盖 proof 时,用 **evidence-sum
232
232
  | --- | ------- | -------- |
233
233
  | 1 | Topology | 优先 same-rank parallel read-only scout/review;仅 output 真正需要时加 `depends_on` |
234
234
  | 2 | Executor | 每个 task 显式声明 `executor`;`defaults.executor` 是 schema metadata,非 runtime fallback |
235
- | 3 | Model routing | 用 node `complexity` + `executorModels`;Pi MED(`glm-5.2`)quota 耗尽时提高 Pi node `complexity: HIGH`(`gpt-5.5`)— mutate canonical model matrix |
235
+ | 3 | Model routing | 用 node `complexity` + `executorModels`;Pi MED HIGH 当前都使用 `gpt-5.5`,切换 complexity 不会切换模型;provider 临时不可用时仅使用有记录、有限范围的 worker `--pi-model` smoke override,勿 mutate canonical model matrix |
236
236
  | 4 | Read-only output | read-only / Pi node 在 **node output** 返回发现;runner 归档于 `.harness/dag-runs/<run-id>/<node-id>/` |
237
237
  | 5 | Root `artifacts/**` | 非 read-only handoff target;持久记录去 `ai_workspace/loop-agent/reports/`、`ai_workspace/loop-agent/progress/`,或 narrow exclusive `writeSet` 写 legacy 摘要并记录迁移计划 |
238
238
  | 6 | DAG Cursor artifacts | 写入 `.harness/dag-runs/<state>/<run-id>/artifacts/<node-id>/`;不得写入 `./artifacts/**` |
@@ -22,7 +22,7 @@ Agent DAG node 的模型来自 DAG JSON 中的 `executorModels`,并由 `dag va
22
22
  ```json
23
23
  {
24
24
  "LOW": "gpt-5.3-codex-spark",
25
- "MED": "glm-5.2",
25
+ "MED": "gpt-5.5",
26
26
  "HIGH": "gpt-5.5"
27
27
  }
28
28
  ```