@tea-agent/loop-agent 0.17.2 → 0.18.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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": 3,
2
+ "version": 4,
3
3
  "title": "Backend test DAG: Backend test template",
4
4
  "runtimeContract": {
5
5
  "schemaVersion": 1,
@@ -28,12 +28,11 @@
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 12 real top-level tasks and executes pytest exactly once.",
32
- "Case review is advisory evidence consumed by canonical context, retrospective, and L-5; it does not authorize or block the pytest writer.",
33
- "Deterministic traceability is the only generated-asset hard gate before pytest.",
34
- "Analysis, execution, manifest, case review, traceability, single-run result, classification, canonical context, retrospective and L-5 evidence remain run-owned and fail-closed.",
35
- "Functional test case IDs must use BE-<MODULE>-<NNN> format.",
36
- "pytest writers may only create the initially declared testcase assets; production code, config, skip/xfail, swallowed failures and mock substitution are forbidden."
31
+ "backend-test-dag uses exactly 8 real top-level tasks and executes pytest exactly once.",
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.",
34
+ "Only Markdown case generation/review may read source facts; pytest generation must not read source/**.",
35
+ "Functional case IDs use BE-<MODULE>-<NNN>; production code/config, skip/xfail, repair and rerun are forbidden."
37
36
  ],
38
37
  "defaults": {
39
38
  "executor": "pi",
@@ -75,11 +74,11 @@
75
74
  },
76
75
  "tasks": [
77
76
  {
78
- "id": "analyze-and-discover-backend-test-pi",
77
+ "id": "validate-backend-test-environment-shell",
79
78
  "depends_on": [],
80
- "role": "planner",
81
- "executor": "pi",
82
- "complexity": "MED",
79
+ "role": "verifier",
80
+ "executor": "shell",
81
+ "complexity": "LOW",
83
82
  "writePolicy": "read-only",
84
83
  "allowedPaths": [
85
84
  "testcase/**",
@@ -90,54 +89,50 @@
90
89
  ".harness/dag-runs/**",
91
90
  "artifacts/**"
92
91
  ],
93
- "outputContract": "Pure JSON envelope {analysis: Backend Test Analysis v2, execution: Backend Test Execution Contract v1}; no prose or writes.",
94
- "subtask_prompt": "Read the task source materials and return exactly one JSON object matching Backend Test Analysis v2.\n\nDo not wrap it in explanatory prose. A single fenced json block is tolerated, but pure JSON is preferred.\n\nCopy the sourceBinding object exactly from the JSON block below; do not infer, add, remove, or reclassify source paths.\n\nOnly kind=reference sources belong in referencePaths; kind=constraint sources MUST NOT be included in referencePaths.\n\n## Exact Backend Test Analysis sourceBinding JSON\n\n{\n \"taskId\": \"backend-test-template\",\n \"requirementPath\": \"source/需求.md\",\n \"requirementSha256\": \"e33ab9d1d3d6a785b8f429d8581d015a299adc093b0c9a7c0f9057f968a71837\",\n \"referencePaths\": [],\n \"requirementIds\": [\n \"AC-001\"\n ]\n}\n\nFor every endpoint, explicitly set responseBody.kind=array|object|scalar|empty|unknown and ordering=specified|unspecified|not-applicable. Add itemSchemaRef for arrays when documented.\n\nFor response fields, use comparison=exact|parseable-only|semantic when the source defines assertion semantics; date-time fields whose precision is unspecified should use parseable-only, not string equality.\n\nEndpoint sourceRefs and field sourceRefs must cite only requirement/reference evidence actually read. Empty sourceRefs are allowed only when normalizing legacy v1 input; newly generated v2 should cite evidence.\n\nFor externalDependencies and risks, emit canonical items with exactly description plus optional name and sourceRef. For a dependency target, put the target value in name. Do not emit type, target, kind, required, severity, mitigation, level, impact, sourceRefs, or custom keys in newly generated v2 output.\n\nUse empty arrays for categories not documented. Never include credentials, tokens, private keys, or secret values.\n\nRequired top-level keys: schemaVersion=2, sourceBinding, acceptanceCriteria, endpoints, dataModels, businessRules, stateTransitions, boundaryConstraints, externalDependencies, risks, evidenceGaps.\n\nRead-only: do not modify code, docs, artifacts, or repository files.\n\n## Task source: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Task config summary\n\n- taskId: backend-test-template\n\n- flow: auto\n\n- complexity: medium\n\n- contextProfile: full\n\n- allowedPaths: testcase/**, docs/test-reports/**\n\n- forbiddenPaths: (none)\n\n- Pi DAG nodes are read-only unless toolProfile=\"write\" is explicitly selected for a bounded writer node.\n\n- Agent DAG read-only nodes must not write root artifacts/**; root artifacts/ is not a per-node scratchpad.\n\n- source/references/* are immutable user/source facts; source/需求.md is the derived execution contract.\n\nAlso perform the read-only environment discovery described by Backend Test Execution Contract v1. Return exactly one JSON envelope with top-level keys analysis and execution; analysis must satisfy v2 and execution must satisfy v1.",
95
- "retryPolicy": {
96
- "maxAttempts": 3,
97
- "backoff": "exponential",
98
- "initialDelayMs": 2000,
99
- "maxDelayMs": 30000,
100
- "retryCategories": [
101
- "timeout",
102
- "network",
103
- "rate-limit",
104
- "unavailable"
105
- ]
92
+ "outputContract": "Run-owned reports/backend-test-environment.md with PASS/FAIL runtime, bounded project discovery, fixture and HTML-renderer facts; no secret values.",
93
+ "subtask_prompt": "Fail fast before model work when Python/pytest cannot run in the clean shell. Inspect only bounded common config, conftest, test-root and server-entry candidates; never read .env values or credentials.",
94
+ "shell": {
95
+ "commands": [
96
+ "python --version",
97
+ "python -m pytest --version",
98
+ "python -m pytest --help"
99
+ ],
100
+ "backendTestPipeline": "markdown-environment",
101
+ "cwd": ".",
102
+ "timeoutMs": 60000,
103
+ "envAllowlist": []
106
104
  }
107
105
  },
108
106
  {
109
- "id": "validate-backend-test-contracts-shell",
107
+ "id": "generate-backend-md-cases-pi",
110
108
  "depends_on": [
111
- "analyze-and-discover-backend-test-pi"
109
+ "validate-backend-test-environment-shell"
110
+ ],
111
+ "role": "implementer",
112
+ "executor": "pi",
113
+ "toolProfile": "write",
114
+ "complexity": "MED",
115
+ "writePolicy": "exclusive",
116
+ "writeSet": [
117
+ "testcase/md/**"
112
118
  ],
113
- "role": "verifier",
114
- "executor": "shell",
115
- "complexity": "LOW",
116
- "writePolicy": "read-only",
117
119
  "allowedPaths": [
118
- "testcase/**",
119
- "docs/test-reports/**"
120
+ "testcase/md/**"
120
121
  ],
121
122
  "forbiddenPaths": [
122
123
  ".harness/**",
123
124
  ".harness/dag-runs/**",
124
125
  "artifacts/**"
125
126
  ],
126
- "outputContract": "Materialize and validate contracts/backend-test-analysis.json and contracts/backend-test-execution.json.",
127
- "subtask_prompt": "Validate both backend-test intake contracts fail-closed.",
128
- "shell": {
129
- "commands": [],
130
- "backendTestPipeline": "contracts",
131
- "cwd": ".",
132
- "timeoutMs": 60000
133
- }
127
+ "outputContract": "Write testcase/md/README.md plus module Markdown cases using BE-<MODULE>-<NNN>. Use Chinese for human-readable content while preserving required machine-readable identifiers and section headings; no JSON, pytest execution, production code or config writes.",
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: document titles, case titles, strategy explanations, preconditions, test-data descriptions, step descriptions, expected-result descriptions, automation notes, table headers and evidence-gap explanations. Keep English only where it is part of a machine-readable contract or established technical literal, including Case IDs, AC/REQ/BR IDs, exact section headings, HTTP methods, paths, field names, enum values, commands, filenames, code symbols and source citations. Do not add an English translation when Chinese already conveys the meaning.\n\nEvery case heading is `## BE-<MODULE>-<NNN> <中文用例标题>` and contains these exact machine-readable headings: `### Acceptance Criteria`, `### Source References`, `### Preconditions`, `### Test Data`, `### Steps`, `### Expected Results`, and `### Automation Notes`. API cases also contain `### Endpoint` with Method and Path. Under those headings, write descriptions in Chinese while preserving exact IDs, values and protocol literals.\n\nCreate testcase/md/README.md in Chinese. It should concisely explain the test objective, environment/target, isolation and cleanup strategy, module index, traceability summary, assertion principles, evidence gaps and non-goals. Prefer readable Chinese tables and lists over repeated boilerplate.\n\nExpected Results must be concrete, independently assertable Chinese statements. Each result should name the observable HTTP status, response field/value, state transition or membership condition instead of vague phrases such as ‘works correctly’ or ‘符合预期’. Steps must be executable and ordered. Use only environment-supported fixtures/targets/isolation. Record evidence gaps in Chinese instead of inventing behavior or credentials. 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."
134
129
  },
135
130
  {
136
- "id": "generate-backend-cases-and-manifest-pi",
131
+ "id": "review-and-revise-backend-md-cases-pi",
137
132
  "depends_on": [
138
- "validate-backend-test-contracts-shell"
133
+ "generate-backend-md-cases-pi"
139
134
  ],
140
- "role": "implementer",
135
+ "role": "reviewer",
141
136
  "executor": "pi",
142
137
  "toolProfile": "write",
143
138
  "complexity": "MED",
@@ -153,13 +148,13 @@
153
148
  ".harness/dag-runs/**",
154
149
  "artifacts/**"
155
150
  ],
156
- "subtask_prompt": "Read both validated run-owned contracts before generating functional cases:\n\n- contracts/backend-test-analysis.json: authoritative requirements, AC IDs, endpoints, fields, rules, boundaries, risks, and evidence gaps.\n\n- contracts/backend-test-execution.json: pytest target mode, base URL env name, readiness, fixtures, and data-isolation constraints.\n\nGenerate cases from the analysis contract; use the execution contract only to keep preconditions and automation feasibility realistic.\n\nDo not proceed from the execution contract alone. Do not re-read source documents or fall back to free-form analysis.\n\n\n\n## Output Steps (do in order):\n\n1. First, output a brief summary: how many modules, how many cases planned per module\n\n2. Then write each test case file under testcase/md/\n\n\n\n## Format Rules:\n\n- Each test case ID: BE-<MODULE>-<NNN> (e.g. BE-ORDER-001) — always write the FULL id; never abbreviate as 002, 003 in matrices\n\n- Each file covers one module\n\n- Case structure: ID, Title, Acceptance Criteria, Business Rules, Precondition, Steps, Expected Result\n\n- Every emitted case MUST declare at least one semantically applicable explicit AC-* under Acceptance Criteria; list BR-* separately under Business Rules\n\n- If a BR-only scenario has no semantically valid in-scope AC, do not create a standalone case for it; record the limitation in the summary for the manifest evidenceGaps instead\n\n- Never relabel a negative/boundary/BR-only behavior as AC-002 or another unrelated AC merely to make acIds non-empty\n\n- Map each case to acceptance criteria (AC-xxx)\n\n\n\n## AC ↔ case consistency (CRITICAL — prevents review request-revision):\n\n- Every AC-xxx listed on a case body MUST appear only on cases that truly exercise that AC\n\n- Any AC-coverage matrix / summary table MUST list the same full BE-* case IDs that the case bodies claim — never 'all cases' / '全部用例' unless every case body maps that AC\n\n- Prefer one primary BE-* case for suite-level ACs (e.g. AC-008 pytest exit 0) rather than tagging every case\n\n- Out-of-scope ACs (Flyway, frontend e2e, mvn test, etc.) must NOT be claimed in MD; leave them for manifest evidenceGaps\n\n\n\n## Coverage Requirements:\n\n- Positive paths: happy path for each acceptance criterion\n\n- Negative paths: error scenarios (invalid input, not found, state violations)\n\n\n\n## Conditional Coverage (include ONLY if mentioned in upstream analysis):\n\n- Boundary conditions: include ONLY if upstream analyze-inputs-pi mentions value ranges, length limits, numeric bounds, or format constraints\n\n- State transitions: include ONLY if upstream analyze-inputs-pi mentions state machine\n\n- Authentication scenarios: include ONLY if upstream analyze-inputs-pi mentions auth mechanism\n\n- Timeout scenarios: include ONLY if upstream analyze-inputs-pi mentions timeout handling\n\n- Concurrency scenarios: include ONLY if upstream analyze-inputs-pi mentions concurrency/idempotency rules\n\n- If not mentioned, do NOT generate these test cases\n\n\n\n## Constraints:\n\n- Stay within writeSet: testcase/md/**\n\n- Do NOT re-read source documents or fall back to free-form analysis; use the two validated run-owned contracts only\n\n- Do not write root artifacts/**\n\nAfter writing Markdown, end assistant output with exactly one fenced json block containing Backend Test Case Manifest v1 derived from the written cases.\n\nThe final fenced JSON block is authoritative and MUST conform exactly to Backend Test Case Manifest v1.\n\nTop-level keys MUST be exactly: schemaVersion, sourceBinding, cases, evidenceGaps. Do NOT emit coverageSummary — the shell materializer always computes it from sourceBinding/cases/evidenceGaps. Set schemaVersion to numeric 1. Do NOT emit schemaId, manifestType, taskId, modules, acCoverage, brCoverage, dataIsolation, readiness, or other custom top-level keys.\n\nCopy sourceBinding exactly from contracts/backend-test-analysis.json: taskId, requirementPath, requirementSha256, referencePaths, requirementIds. Preserve Unicode paths exactly; never replace characters in source/需求.md or other paths.\n\nEach cases[] item MUST use exactly: caseId, non-empty acIds, title, category, automationStatus; optional endpointRef, ruleRefs, file, symbol, gapReason, evidenceRef. Do NOT use id, module, brIds, endpoint, or priority.\n\ncategory MUST be exactly one of: positive, negative, boundary, state-transition, auth, timeout, concurrency, other.\n\nBefore pytest generation, set automationStatus=planned. Use generated only with both file and symbol. Use skipped or unsupported only with gapReason.\n\nEach evidenceGaps[] item MUST use exactly: optional acId, optional caseId, required description, optional evidenceRef. Every gap requires at least acId or caseId. Do NOT use requirementId, relatedBrIds, or sourceRef.\n\nEvery case must map to at least one semantically applicable explicit AC-* in acIds. If no AC applies, omit that case and bind an evidence gap to the nearest applicable acId or caseId; never emit an unbound informational gap.\n\nacIds MUST exactly match the explicit AC-* values in the written case body; do not infer ACs from Business Rules or summary matrices.\n\nUse full BE-<MODULE>-<NNN> caseId strings. Do not invent coverage percentages and do not emit coverageSummary; shell always writes the canonical summary.\n\nMinimal shape example: {\"schemaVersion\":1,\"sourceBinding\":{\"taskId\":\"...\",\"requirementPath\":\"source/需求.md\",\"requirementSha256\":\"<64 lowercase hex>\",\"referencePaths\":[],\"requirementIds\":[\"AC-001\"]},\"cases\":[{\"caseId\":\"BE-MODULE-001\",\"acIds\":[\"AC-001\"],\"title\":\"...\",\"category\":\"positive\",\"automationStatus\":\"planned\",\"evidenceRef\":\"testcase/md/module.md\"}],\"evidenceGaps\":[]}",
157
- "outputContract": "Write testcase/md/** and end with one fenced json Backend Test Case Manifest v1 block matching the strict field contract."
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 Source References and environment evidence. Preserve and improve the Simplified Chinese presentation: human-readable titles, prose, table headers, steps, expected results and notes should be Chinese unless the token is a machine-readable ID, exact required heading, HTTP/API literal, field/enum value, path, filename, command or code symbol.\n\nCheck AC completeness/meaning, endpoint, fields/shape, status/error codes, rules, states, documented boundaries/auth, positive/negative coverage, executable steps and assertable results. Also reject avoidable English prose, duplicated bilingual wording, vague Chinese results such as ‘符合预期’, and literal translations that obscure the observable assertion.\n\nCorrect testcase/md/** directly: add documented omissions, remove unsupported cases, fix mappings/expectations, merge duplicates, improve unclear Chinese wording, or record gaps in Chinese. Do not translate or alter Case IDs, AC/REQ/BR IDs, exact required section headings, HTTP methods, paths, field names, enum values, filenames, code symbols or Source References. Avoid cosmetic rewrites that do not improve correctness or readability.\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."
158
153
  },
159
154
  {
160
- "id": "backend-test-case-manifest-shell",
155
+ "id": "validate-backend-md-cases-shell",
161
156
  "depends_on": [
162
- "generate-backend-cases-and-manifest-pi"
157
+ "review-and-revise-backend-md-cases-pi"
163
158
  ],
164
159
  "role": "verifier",
165
160
  "executor": "shell",
@@ -174,60 +169,19 @@
174
169
  ".harness/dag-runs/**",
175
170
  "artifacts/**"
176
171
  ],
177
- "outputContract": "Validated run-owned Backend Test Case Manifest v1 at contracts/backend-test-case-manifest.json (schemaId backend-test-case-manifest-v1) with deterministic AC coverage.",
178
- "subtask_prompt": "Materialize and validate Backend Test Case Manifest v1; fail closed on duplicate IDs, unknown AC, missing AC coverage without gap, or skipped without gapReason.",
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.",
179
174
  "shell": {
180
175
  "commands": [],
181
- "jsonArtifactGate": {
182
- "fromNodeId": "generate-backend-cases-and-manifest-pi",
183
- "schemaId": "backend-test-case-manifest-v1",
184
- "artifactName": "backend-test-case-manifest.json",
185
- "outputDir": "contracts"
186
- },
176
+ "backendTestPipeline": "markdown-cases",
187
177
  "cwd": ".",
188
178
  "timeoutMs": 60000
189
179
  }
190
180
  },
191
- {
192
- "id": "review-backend-cases-pi",
193
- "depends_on": [
194
- "backend-test-case-manifest-shell",
195
- "validate-backend-test-contracts-shell",
196
- "generate-backend-pytest-pi"
197
- ],
198
- "role": "reviewer",
199
- "executor": "pi",
200
- "complexity": "HIGH",
201
- "writePolicy": "read-only",
202
- "allowedPaths": [
203
- "testcase/**",
204
- "docs/test-reports/**"
205
- ],
206
- "forbiddenPaths": [
207
- ".harness/**",
208
- ".harness/dag-runs/**",
209
- "artifacts/**"
210
- ],
211
- "outputContract": "advisory case review evidence whose first non-empty line is VERDICT: pass or VERDICT: request-revision; followed by Findings and Coverage Assessment. No file writes; this review neither authorizes nor blocks pytest generation.",
212
- "subtask_prompt": "Review the generated backend functional test cases under testcase/md/ and the validated Case Manifest v1.\n\n## Mandatory First Line:\n\nFirst non-empty line must be exactly: VERDICT: pass or VERDICT: request-revision\n\n## Review Checklist:\n\n- ID format: every case uses BE-<MODULE>-<NNN> (full ids only in bodies and matrices)\n\n- Positive coverage: each in-scope acceptance criterion (AC-xxx) has happy-path case\n\n- Negative coverage: error scenarios (invalid input, not found, state violations)\n\n- Traceability: each explicit AC maps to a case ID or an evidenceGap in contracts/backend-test-case-manifest.json\n\n- Case structure: ID, Title, Precondition, Steps, Expected Result\n\n- No duplicate IDs across files\n\n- Manifest consistency (Critical): every AC claimed in MD case bodies/matrices must match manifest caseId→acIds; never accept 'all cases cover AC-xxx' unless every case maps that AC\n\n## Conditional Coverage (check ONLY if mentioned in upstream analysis):\n\n- Boundary coverage: check ONLY if analyze-inputs-pi mentions value ranges, length limits, numeric bounds, or format constraints\n\n- State transition coverage: check ONLY if analyze-inputs-pi mentions state machine\n\n- Authentication coverage: check ONLY if analyze-inputs-pi mentions auth mechanism\n\n- Timeout coverage: check ONLY if analyze-inputs-pi mentions timeout handling\n\n- Concurrency coverage: check ONLY if analyze-inputs-pi mentions concurrency/idempotency rules\n\n- If not mentioned, do NOT flag as missing\n\n## Do NOT treat as Critical alone:\n\n- Missing test_*.py / automation still planned (expected before generate-backend-pytest-pi)\n\n- Out-of-scope ACs already listed in manifest evidenceGaps (Flyway, frontend e2e, mvn test)\n\n## Verdict Rules:\n\n- All Critical checks pass + Important findings ≤ 2 → VERDICT: pass\n\n- Any Critical fails OR Important > 2 → VERDICT: request-revision\n\n- Any request-revision verdict is advisory evidence for canonical context, retrospective, and L-5; it does not authorize or block the pytest writer.\n\n## Output After Verdict:\n\n1. Coverage Assessment table (AC → full BE-* case IDs) using manifest + MD\n\n2. Findings list (Critical/Important/Informational)\n\n3. Statistics (total cases, positive/negative/boundary breakdown)\n\n4. Required follow-up actions (only when request-revision; no in-run writer)\n\n## Constraints:\n\n- Read-only: do not modify files\n\n- Read validated analysis + case manifest artifacts; do not recompute coverage percentages\n\n- Use testcase/md/ files for case review",
213
- "retryPolicy": {
214
- "maxAttempts": 3,
215
- "backoff": "exponential",
216
- "initialDelayMs": 2000,
217
- "maxDelayMs": 30000,
218
- "retryCategories": [
219
- "timeout",
220
- "network",
221
- "rate-limit",
222
- "unavailable"
223
- ]
224
- }
225
- },
226
181
  {
227
182
  "id": "generate-backend-pytest-pi",
228
183
  "depends_on": [
229
- "backend-test-case-manifest-shell",
230
- "validate-backend-test-contracts-shell"
184
+ "validate-backend-md-cases-shell"
231
185
  ],
232
186
  "role": "implementer",
233
187
  "executor": "pi",
@@ -248,15 +202,14 @@
248
202
  ".harness/dag-runs/**",
249
203
  "artifacts/**"
250
204
  ],
251
- "subtask_prompt": "Convert the validated test cases under testcase/md/ into pytest automation code.\n\n\n\n## Inputs (MUST use validated contracts):\n\n- Validated cases under testcase/md/ and contracts/backend-test-case-manifest.json (case review runs independently as advisory evidence).\n\n- Validated Backend Test Analysis v2 under contracts/backend-test-analysis.json.\n\n\n\n- Validated Backend Test Execution Contract v1 under contracts/backend-test-execution.json (execution gate).\n\nUse only fixture names, env NAMES, testRoot, targetMode, and field/API facts already present in those contracts or reviewed cases. Do not invent production credentials or secret values.\n\nWhen targetMode is in-process (including demoted local npm/node managed servers): bootstrap the service inside function-scoped pytest fixtures under testcase/** — e.g. subprocess node server.js / startWelcomeServer with PORT=0 — and never require host-injected base URL env vars (clean-env shell will not provide WELCOME_BASE_URL / API_BASE_URL).\n\nDo not depend on requiredEnvNames being present at process start for in-process mode; if the contract still lists an env name, the fixture must set it or start the server without that env.\n\n\n\n## Output Steps (do in order):\n\n1. First, output a brief summary: how many files, how many test functions planned\n\n2. Then write each test file under testcase/\n\n\n\n## Format Rules:\n\n- File prefix: test_<module>.py\n\n- Function name: test_BE_<MODULE>_<NNN>_<description>\n\n- Docstring first line: BE-<MODULE>-<NNN>: <Case Title>\n\n- 1:1 mapping: each functional case → one pytest function\n\n\n\n## Implementation Rules:\n\n- Use assert statements, not unittest assertions\n\n- Use @pytest.mark.parametrize for boundary cases when the case defines edge values\n\n- Use markers: @pytest.mark.positive, @pytest.mark.negative, @pytest.mark.boundary\n\n\n\n## Test Data Preparation Rules (MUST follow):\n\n\n\n### When Setup is Needed\n\nSetup phase is REQUIRED only when test cases need pre-existing data:\n\n- Query/Read APIs: need data to exist before querying\n\n- Update/Delete APIs: need data to exist before modifying\n\n- State transition tests: need data in specific state\n\n\n\nSetup phase is NOT needed for:\n\n- Create APIs: testing the creation itself\n\n- Validation tests: testing input validation with invalid data\n\n\n\n### Data Setup Strategy\n\nWhen setup is needed:\n\n1. Prefer function-scoped fixtures for isolation; use module/session scope only when cases explicitly share immutable fixtures\n\n2. Prefer API-based setup from the upstream analyze-inputs-pi API list and reviewed cases\n\n3. If a required helper/factory is missing, create NEW files only under testcase/**/helpers/** or testcase/**/factories/**\n\n\n\n### Data Construction Priority\n\n1. API-first: construct data via documented APIs from analyze-inputs-pi / reviewed cases\n\n2. Reuse existing conftest fixtures when present (read-only)\n\n3. Direct DB writes are LAST RESORT and only if conftest already exposes a safe test DB fixture with rollback/isolation\n\n4. If neither API nor safe DB fixture exists, skip the case with an explicit gap note — do NOT invent production DB credentials or write live data\n\n\n\n### API Data Construction\n\n- Prefer the analyze-inputs-pi API Endpoints section and reviewed cases for method/path/fields\n\n- Chain API calls only when cases document multi-step preconditions\n\n- Store created resource IDs in fixtures for reuse\n\n- Do NOT broadly search host route/controller trees for secrets, .env, private keys, or production configs\n\n- Read host API definitions only when needed to resolve a field name already referenced by reviewed cases; stay out of credential/config paths\n\n\n\n### Database Data Construction (restricted)\n\n- Allowed only via existing conftest test-DB fixtures with transaction rollback or equivalent isolation\n\n- Never hardcode connection strings, passwords, tokens, or cloud credentials\n\n- Never target production/shared non-test databases\n\n- If isolation is unclear, report the gap instead of writing DB rows\n\n\n\n## Assertion Rules (MUST follow):\n\n\n\n### Positive Path\n\nMUST assert ALL of the following:\n\n1. HTTP status code: as defined in API spec (e.g. 200, 201)\n\n2. Response structure: key fields exist in response body\n\n3. Specific values: each field equals expected value from test case\n\n4. Data type: each field is correct type\n\n\n\n### Negative Path\n\nMUST assert ALL of the following:\n\n1. HTTP status code: as defined in API spec (e.g. 400, 404, 500)\n\n2. Error code field: field name from API spec (e.g. code, error_code, errcode, ret)\n\n3. Error message field: field name from API spec (e.g. message, msg, errmsg, error)\n\n\n\n### Field Name Resolution\n\nField names MUST come from the upstream analyze-inputs-pi output (API Endpoints section) or reviewed cases, NOT guessed. For example:\n\n- If API spec defines {\"ret\": 0, \"msg\": \"success\"}, assert response.json()['ret'] and response.json()['msg']\n\n- If API spec defines {\"code\": 4001, \"message\": \"error\"}, assert response.json()['code'] and response.json()['message']\n\n\n\n## Conditional Implementation (include ONLY if test cases exist):\n\n- Authentication tests: implement ONLY if testcase/md/ contains auth-related cases\n\n- Timeout tests: implement ONLY if testcase/md/ contains timeout-related cases\n\n- Boundary tests: implement ONLY when cases define value ranges, length limits, or format constraints\n\n- Use @pytest.mark.auth for auth tests, @pytest.mark.timeout for timeout tests\n\n- If no such cases exist, do NOT add these tests\n\n\n\n## Constraints:\n\n- Only create NEW files under writeSet: testcase/**/test_*.py, testcase/**/helpers/**, testcase/**/factories/**\n\n- Do NOT modify existing framework files (conftest.py, pytest.ini, pyproject.toml, setup.cfg, __init__.py)\n\n- If a test filename exists, add suffix: test_order.py → test_order_01.py\n\n- Do NOT re-read source documents — use reviewed cases under testcase/md/ and upstream analyze-inputs-pi output only\n\n- Read existing conftest.py/pytest.ini to understand conventions, but do NOT modify them\n\n- Do NOT execute pytest/python -m pytest or npm test in this node; the single execution is owned by the dedicated shell node. Local smoke runs create __pycache__/.pytest_cache and are unnecessary here."
205
+ "outputContract": "Convert every final automatable Markdown case one-to-one into pytest assets under the narrow writeSet; 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\nEach case maps to one `test_BE_<MODULE>_<NNN>_<description>` function whose first docstring line contains the exact Case ID. Assertions come only from Expected Results; setup comes only from Preconditions/Test Data/Automation Notes.\n\nDo not read source/**, add cases, reassign ACs, modify conftest/config/production code, use skip/xfail, swallow assertions, execute pytest, or emit JSON."
252
207
  },
253
208
  {
254
209
  "id": "backend-test-traceability-gate-shell",
255
210
  "depends_on": [
256
- "generate-backend-pytest-pi",
257
- "backend-test-case-manifest-shell"
211
+ "generate-backend-pytest-pi"
258
212
  ],
259
- "dependsPolicy": "all-or-condition-skip",
260
213
  "role": "verifier",
261
214
  "executor": "shell",
262
215
  "complexity": "LOW",
@@ -270,21 +223,19 @@
270
223
  ".harness/dag-runs/**",
271
224
  "artifacts/**"
272
225
  ],
273
- "outputContract": "Deterministic traceability: generated cases have real file/symbol; skipped/unsupported have gapReason; convention symbols scanned under testcase/**/test_*.py.",
274
- "subtask_prompt": "Fail closed when generated automation claims do not resolve to workspace pytest symbols, or skip/unsupported lacks gapReason.",
226
+ "outputContract": "Run-owned reports/backend-test-traceability.md proving Markdown-to-pytest one-to-one mapping.",
227
+ "subtask_prompt": "Fail closed on missing, duplicate or extra Case ID mappings, mismatched docstrings, skip/xfail or swallowed exceptions.",
275
228
  "shell": {
276
- "commands": [
277
- "backend-test-traceability-gate"
278
- ],
229
+ "commands": [],
230
+ "backendTestPipeline": "markdown-traceability",
279
231
  "cwd": ".",
280
232
  "timeoutMs": 60000
281
233
  }
282
234
  },
283
235
  {
284
- "id": "execute-and-parse-backend-pytest-shell",
236
+ "id": "execute-backend-pytest-and-html-report-shell",
285
237
  "depends_on": [
286
- "backend-test-traceability-gate-shell",
287
- "validate-backend-test-contracts-shell"
238
+ "backend-test-traceability-gate-shell"
288
239
  ],
289
240
  "role": "verifier",
290
241
  "executor": "shell",
@@ -299,95 +250,22 @@
299
250
  ".harness/dag-runs/**",
300
251
  "artifacts/**"
301
252
  ],
302
- "outputContract": "Archived pytest stdout/stderr; raw pytestExitCode side-channel + JUnit at $HARNESS_DAG_RUN_DIR/reports/**. Exit 0/1 with non-empty JUnit finishes the node so parse/classify/retrospect can run; assertion failures remain recorded in exit file.",
303
- "subtask_prompt": "Run pytest for the backend test suite; write JUnit + pytestExitCode evidence only under the current HARNESS_DAG_RUN_DIR/reports/.",
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 self-contained HTML from that JUnit without rerun, and preserve failures as facts.",
304
255
  "shell": {
305
256
  "commands": [
306
- "test -n \"${HARNESS_DAG_RUN_DIR:-}\" || { echo \"missing HARNESS_DAG_RUN_DIR for backend pytest preflight\" >&2; exit 2; } && CONTRACT=\"${HARNESS_DAG_RUN_DIR}/contracts/backend-test-execution.json\" && test -f \"${CONTRACT}\" || { echo \"missing backend-test execution contract: ${CONTRACT}\" >&2; exit 2; } && node -e 'const fs=require(\"fs\");const path=require(\"path\");const contractPath=process.argv[1];const contract=JSON.parse(fs.readFileSync(contractPath,\"utf8\"));const expected=\"testcase\";const errors=[];if(contract.framework!==\"pytest\") errors.push(\"framework must be pytest\");const testRoot=String(contract.testRoot||\"\");if(!testRoot||testRoot.includes(\"..\")||path.isAbsolute(testRoot)) errors.push(\"unsafe testRoot\");if(testRoot.replace(/\\/+$/,\"\")!==expected.replace(/\\/+$/,\"\")) errors.push(\"testRoot mismatch vs frozen command: \"+testRoot+\" !== \"+expected);const rootAbs=path.resolve(process.cwd(),testRoot);if(!fs.existsSync(rootAbs)) errors.push(\"testRoot does not exist: \"+testRoot);if(contract.targetMode===\"in-process\"&&!(Array.isArray(contract.existingFixtures)&&contract.existingFixtures.length)) errors.push(\"in-process requires existingFixtures\");for (const name of (contract.requiredEnvNames||[])) { if(!process.env[name]) errors.push(\"required env missing: \"+name); }if(contract.targetMode===\"external-running-service\"){ const n=contract.baseUrlEnvName; if(!n||!process.env[n]) errors.push(\"external base URL env missing: \"+String(n||\"<empty>\")); }if(contract.targetMode===\"managed-command\" && !(contract.managedCommand&&contract.managedCommand.sourceRef)) errors.push(\"managed-command requires sourceRef evidence\");if(errors.length){ console.error(errors.join(\"; \")); process.exit(2);} console.log(\"backend-test preflight ok: framework=pytest testRoot=\"+testRoot+\" targetMode=\"+contract.targetMode);' \"${CONTRACT}\" && { REPORT=\"${HARNESS_DAG_RUN_DIR}/reports/backend-test-initial-junit.xml\"; EXIT_FILE=\"${HARNESS_DAG_RUN_DIR}/reports/backend-test-initial-pytest-exit.txt\"; mkdir -p \"$(dirname \"${REPORT}\")\"; PYTHONUTF8=1 PYTHONIOENCODING=utf-8 PYTHONDONTWRITEBYTECODE=1 python -m pytest testcase/ -v -p no:cacheprovider --junitxml=\"${REPORT}\"; STATUS=$?; printf \"%s\" \"${STATUS}\" > \"${EXIT_FILE}\"; printf \"JUnit report: %s\\n\" \"${REPORT}\"; printf \"pytestExitCode=%s\\n\" \"${STATUS}\"; if { [ \"${STATUS}\" -eq 0 ] || [ \"${STATUS}\" -eq 1 ]; } && [ -s \"${REPORT}\" ]; then exit 0; fi; exit \"${STATUS}\"; }"
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}\""
307
258
  ],
308
- "envAllowlist": [],
309
- "verifyEvidence": {
310
- "phase": "final",
311
- "quota": "full",
312
- "commandSource": "inline",
313
- "commandCount": 1,
314
- "commandLabels": [
315
- "test -n \"${HARNESS_DAG_RUN_DIR:-}\" || { echo \"missing HARNESS_DAG_RUN_DIR for backend pytest preflight\" >&2; exit 2; } && CONTRACT=\"${HARNESS_DAG_RUN_DIR}/contracts/backend-test-execution.json\" && test -f \"${CONTRACT}\" || { echo \"missing backend-test execution contract: ${CONTRACT}\" >&2; exit 2; } && node -e 'const fs=require(\"fs\");const path=require(\"path\");const contractPath=process.argv[1];const contract=JSON.parse(fs.readFileSync(contractPath,\"utf8\"));const expected=\"testcase\";const errors=[];if(contract.framework!==\"pytest\") errors.push(\"framework must be pytest\");const testRoot=String(contract.testRoot||\"\");if(!testRoot||testRoot.includes(\"..\")||path.isAbsolute(testRoot)) errors.push(\"unsafe testRoot\");if(testRoot.replace(/\\/+$/,\"\")!==expected.replace(/\\/+$/,\"\")) errors.push(\"testRoot mismatch vs frozen command: \"+testRoot+\" !== \"+expected);const rootAbs=path.resolve(process.cwd(),testRoot);if(!fs.existsSync(rootAbs)) errors.push(\"testRoot does not exist: \"+testRoot);if(contract.targetMode===\"in-process\"&&!(Array.isArray(contract.existingFixtures)&&contract.existingFixtures.length)) errors.push(\"in-process requires existingFixtures\");for (const name of (contract.requiredEnvNames||[])) { if(!process.env[name]) errors.push(\"required env missing: \"+name); }if(contract.targetMode===\"external-running-service\"){ const n=contract.baseUrlEnvName; if(!n||!process.env[n]) errors.push(\"external base URL env missing: \"+String(n||\"<empty>\")); }if(contract.targetMode===\"managed-command\" && !(contract.managedCommand&&contract.managedCommand.sourceRef)) errors.push(\"managed-command requires sourceRef evidence\");if(errors.length){ console.error(errors.join(\"; \")); process.exit(2);} console.log(\"backend-test preflight ok: framework=pytest testRoot=\"+testRoot+\" targetMode=\"+contract.targetMode);' \"${CONTRACT}\" && { REPORT=\"${HARNESS_DAG_RUN_DIR}/reports/backend-test-initial-junit.xml\"; EXIT_FILE=\"${HARNESS_DAG_RUN_DIR}/reports/backend-test-initial-pytest-exit.txt\"; mkdir -p \"$(dirname \"${REPORT}\")\"; PYTHONUTF8=1 PYTHONIOENCODING=utf-8 PYTHONDONTWRITEBYTECODE=1 python -m pytest testcase/ -v -p no:cacheprovider --junitxml=\"${REPORT}\"; STATUS=$?; printf \"%s\" \"${STATUS}\" > \"${EXIT_FILE}\"; printf \"JUnit report: %s\\n\" \"${REPORT}\"; printf \"pytestExitCode=%s\\n\" \"${STATUS}\"; if { [ \"${STATUS}\" -eq 0 ] || [ \"${STATUS}\" -eq 1 ]; } && [ -s \"${REPORT}\" ]; then exit 0; fi; exit \"${STATUS}\"; }"
316
- ],
317
- "finalFullRequired": true
318
- },
259
+ "backendTestPipeline": "markdown-execute-html",
319
260
  "cwd": ".",
320
261
  "timeoutMs": 300000,
321
- "backendTestPipeline": "execute-parse-initial"
262
+ "envAllowlist": []
322
263
  }
323
264
  },
324
265
  {
325
- "id": "classify-backend-test-result-pi",
266
+ "id": "backend-test-report-and-l5-pi",
326
267
  "depends_on": [
327
- "execute-and-parse-backend-pytest-shell"
328
- ],
329
- "role": "reviewer",
330
- "executor": "pi",
331
- "complexity": "MED",
332
- "writePolicy": "read-only",
333
- "allowedPaths": [
334
- "testcase/**",
335
- "docs/test-reports/**"
336
- ],
337
- "forbiddenPaths": [
338
- ".harness/**",
339
- ".harness/dag-runs/**",
340
- "artifacts/**"
341
- ],
342
- "outputContract": "Pure JSON classification: category in {ProductBug,TestBug,EnvFailure,ContractMismatch,FlakyTest,Unknown}, evidence[], confidence (capped), notes. No file writes.",
343
- "subtask_prompt": "Read-only classifier for Backend Test Result v1.\n\nReturn exactly one JSON object (prefer pure JSON; single fenced json block tolerated; no trailing prose).\n\nThe object must contain exactly category, evidence, confidence, notes. evidence must be a non-empty array of strings, confidence must be a number from 0 through 1, and notes must be a non-empty string. Do not emit schemaVersion or custom fields.\n\nMinimal shape: {\"category\":\"Unknown\",\"evidence\":[\"outcome=completed-with-failures\"],\"confidence\":0.5,\"notes\":\"Single-run evidence is insufficient for a stronger classification.\"}\n\nRead contracts/backend-test-result-initial.json (run-owned initial Result v1). Do NOT invent pass rates from raw logs.\n\ncategory must be one of: ProductBug, TestBug, EnvFailure, ContractMismatch, FlakyTest, Unknown.\n\nHard constraints:\n\n- Single-run failure MUST NOT use FlakyTest (use Unknown, TestBug, or ProductBug).\n\n- executionStatus/outcome collection-error, command-error, or report-error MUST NOT use ProductBug.\n\n- Prefer EnvFailure/Unknown/TestBug for env, import, collection, and missing-report cases.\n\n- confidence must respect deterministic caps (≤0.75 for assertion failures; ≤0.6 for env/collection).\n\nInclude evidence[] referencing result fields (outcome, failed, failures[].name, executionStatus).\n\nRead-only: do not modify code, docs, artifacts, or repository files.",
344
- "retryPolicy": {
345
- "maxAttempts": 3,
346
- "backoff": "exponential",
347
- "initialDelayMs": 2000,
348
- "maxDelayMs": 30000,
349
- "retryCategories": [
350
- "timeout",
351
- "network",
352
- "rate-limit",
353
- "unavailable"
354
- ]
355
- }
356
- },
357
- {
358
- "id": "materialize-classification-and-result-context-shell",
359
- "depends_on": [
360
- "classify-backend-test-result-pi",
361
- "backend-test-case-manifest-shell",
362
- "review-backend-cases-pi",
363
- "backend-test-traceability-gate-shell"
364
- ],
365
- "role": "verifier",
366
- "executor": "shell",
367
- "complexity": "LOW",
368
- "writePolicy": "read-only",
369
- "allowedPaths": [
370
- "testcase/**",
371
- "docs/test-reports/**"
372
- ],
373
- "forbiddenPaths": [
374
- ".harness/**",
375
- ".harness/dag-runs/**",
376
- "artifacts/**"
377
- ],
378
- "outputContract": "Materialize Classification v1, copy the unique initial Result to canonical contracts/backend-test-result.json, and emit Result + Manifest + Classification + advisory case review + traceability context.",
379
- "subtask_prompt": "Validate classification and materialize canonical single-run result context with auditable case review and traceability evidence, without repair eligibility or rerun.",
380
- "shell": {
381
- "commands": [],
382
- "backendTestPipeline": "classification-result-context",
383
- "cwd": ".",
384
- "timeoutMs": 60000
385
- }
386
- },
387
- {
388
- "id": "test-retrospect-pi",
389
- "depends_on": [
390
- "materialize-classification-and-result-context-shell"
268
+ "execute-backend-pytest-and-html-report-shell"
391
269
  ],
392
270
  "role": "closeout",
393
271
  "executor": "pi",
@@ -405,41 +283,8 @@
405
283
  ".harness/dag-runs/**",
406
284
  "artifacts/**"
407
285
  ],
408
- "outputContract": "Maturity rating in assistant output plus a report written under docs/test-reports/**.",
409
- "subtask_prompt": "Read the complete JSON from direct upstream materialize-classification-and-result-context-shell and generate a test retrospective report.\n\nThat JSON contains result, manifest (including coverageSummary), and classification. Treat those fields as authoritative; do not rely on pointer/hash summaries.\n\n\n\n## Output Steps (do in order):\n\n1. First, output the maturity rating on the first line: Rating: A/B/C/D\n\n2. Then write the full report under docs/test-reports/\n\n\n\n## Stats authority (deterministic only):\n\n- Pass rate, failed/error/skipped counts, and failure list MUST come from contracts/backend-test-result.json only.\n\n- AC coverage ratio / case counts MUST come from contracts/backend-test-case-manifest.json coverageSummary (or gate-derived fields). Do NOT invent coverage %.\n\n- Automation coverage MUST use coverageSummary.generatedCount / coverageSummary.caseCount. If either field is missing, write unavailable; do not estimate.\n\n- Code coverage MUST come only from the validated contracts/code-coverage-v1.json artifact generated by coverage.py/pytest-cov or JaCoCo. Show line, branch, function/method, covered, total, ratio, threshold, status, source scope, requirement IDs, tool, commit, and artifact hash.\n\n- Stability MUST come from independent Stability Evidence: use successfulRuns / recordedRuns, same suite/version, and require n≥5; a single run is unavailable.\n\n- Use classify-backend-test-result-pi JSON as interpretive evidence only.\n\n- NEVER rewrite a failed result as passed. Result v1 is authoritative for testOutcome; pipeline completion and L-5 readiness are separate conclusions.\n\n\n\n\n\n## Report Structure:\n\n1. Maturity Rating with rationale\n\n2. Test Coverage Summary (Result v1 pass rate, AC coverage, automation coverage, code coverage, and stability evidence)\n\n3. Failed Test Analysis (failure/error details, category, confidence, evidence, and owner direction)\n\n4. Defects (local Bug ledger in the same report directory; unavailable when absent)\n\n5. Risks (Critical/High/Medium/Low, impact, controls, residual risk, treatment; Critical risks block L-5, High risks do not automatically block)\n\n6. Regression Recommendations (immediate, related, periodic, deferred; every item links to failure/risk/AC/case IDs)\n\n7. L-5 conclusion with blocking items\n\n\n\n## Rating Criteria:\n\n- L-5 ready requires pass rate=100%, AC coverage=100%, automation coverage≥90%, stability95% with n5, line coverage≥80%, branch coverage≥70%, skipped=0, and no blocking Critical risk.\n\n- Any required metric fail or unavailable means L-5 not-ready. Function/method coverage is displayed but not a gate. Preserve the existing A/B/C/D single-run rating separately.\n\n\n\n## Constraints:\n\n- Stay within writeSet: docs/test-reports/**\n\n- Do NOT re-read source documents — use upstream outputs only\n\n- Do not write root artifacts/**"
410
- },
411
- {
412
- "id": "l5-metrics-pi",
413
- "depends_on": [
414
- "test-retrospect-pi"
415
- ],
416
- "role": "reviewer",
417
- "executor": "pi",
418
- "complexity": "MED",
419
- "writePolicy": "read-only",
420
- "allowedPaths": [
421
- "testcase/**",
422
- "docs/test-reports/**"
423
- ],
424
- "forbiddenPaths": [
425
- ".harness/**",
426
- ".harness/dag-runs/**",
427
- "artifacts/**"
428
- ],
429
- "outputContract": "Exactly one JSON object with status=ready|not-ready, metrics, and blockingItems; no file writes.",
430
- "subtask_prompt": "You are the independent L-5 metrics node at the end of the existing backend-test DAG.\n\nThe direct upstream test-retrospect-pi output is the primary report to assess. Read it together with the run-owned Result v1, Case Manifest v1, Code Coverage v1, and Stability Evidence artifacts when present.\n\nDo not create a new DAG, rewrite the retrospective report, change test outcome, or modify any repository file.\n\nReturn exactly one JSON object and no surrounding prose.\n\nRequired shape: {\"status\":\"ready\"|\"not-ready\",\"metrics\":{\"passRate\":metric,\"acCoverage\":metric,\"automationCoverage\":metric,\"stability\":metric,\"lineCoverage\":metric,\"branchCoverage\":metric,\"skipped\":metric,\"criticalRisks\":metric},\"blockingItems\":[string]}.\n\nEach metric must contain numerator, denominator, ratio, threshold, status=pass|fail|unavailable, and reason (null only when passed).\n\nUse only explicit evidence. Missing or invalid required evidence is unavailable, never zero or an estimate.\n\nL-5 ready requires pass rate=100%, AC coverage=100%, automation coverage>=90%, stability>=95% with n>=5, line coverage>=80%, branch coverage>=70%, skipped=0, and zero blocking Critical risks.\n\nFunction/method coverage is display-only and does not gate L-5. Preserve the distinction between L-5 maturity and the Result v1 outcome gate.",
431
- "retryPolicy": {
432
- "maxAttempts": 3,
433
- "backoff": "exponential",
434
- "initialDelayMs": 2000,
435
- "maxDelayMs": 30000,
436
- "retryCategories": [
437
- "timeout",
438
- "network",
439
- "rate-limit",
440
- "unavailable"
441
- ]
442
- }
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/**."
443
288
  }
444
289
  ],
445
290
  "sourceBinding": {
@@ -455,5 +300,15 @@
455
300
  "requirementIds": [
456
301
  "AC-001"
457
302
  ]
303
+ },
304
+ "taskContractBinding": {
305
+ "schemaVersion": 1,
306
+ "taskId": "backend-test-template",
307
+ "revision": 1,
308
+ "projectionVersion": 1,
309
+ "canonicalizerVersion": 1,
310
+ "taskConfigSchemaVersion": 1,
311
+ "canonicalHash": "752c95f16925ee7711b41e465b8eb3530b99eaa40d17a88d753b3b4fcc7aeb6e",
312
+ "taskConfigSha256": "926c8986ce0b291d26af9ba1be8cf1630e647a06c362dac1d6bbac72e6df7bb0"
458
313
  }
459
314
  }
@@ -11,7 +11,7 @@ Mode rationale: `<why this mode is sufficient>`
11
11
 
12
12
  ## Naming Convention
13
13
 
14
- Use `YYYY-MM-DD-origin-<source>-into-<target>-<source-short-sha>.md` under `docs/reports/`. Replace `/` and other path separators in branch names with `-`. The source short SHA distinguishes repeated merges on the same day.
14
+ Use `YYYY-MM-DD-origin-<source>-into-<target>-<source-short-sha>.md` under `docs/reports/merge/`. Replace `/` and other path separators in branch names with `-`. The source short SHA distinguishes repeated merges on the same day.
15
15
 
16
16
  ## Pre-merge Inspection
17
17
 
@@ -1,5 +1,7 @@
1
1
  # 执行计划模板
2
2
 
3
+ > 进行中:`docs/exec-plans/active/YYYY-MM-DD-<topic>.md`。完成后原名移入 `docs/exec-plans/completed/`,并更新两边 README;handoff 写 `docs/progress/`,验证证据写 `docs/reports/`。
4
+
3
5
  ## 标题
4
6
 
5
7
  ## 状态
@@ -1,5 +1,8 @@
1
1
  # 进度日志模板
2
2
 
3
+ > 复制到 `docs/progress/YYYY-MM-DD-<topic>.md`。保持简短交接;完整验证证据写到 `docs/reports/`。
4
+ > 写完后更新 `docs/progress/README.md` 的近期要点与全量列表。
5
+
3
6
  ## 日期 / 会话
4
7
 
5
8
  ## 变更内容
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tea-agent/loop-agent",
3
- "version": "0.17.2",
3
+ "version": "0.18.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "loop-agent": "bin/loop-agent.js",
@@ -44,7 +44,7 @@ description: 用于 loop-agent 本仓库的初始化能力演化审查,判断
44
44
  轻量审查可以只在 handoff 中说明。高影响审查应写入:
45
45
 
46
46
  ```text
47
- ai_workspace/loop-agent/reports/YYYY-MM-DD-init-evolution-review.md
47
+ ai_workspace/loop-agent/reports/init-evolution/YYYY-MM-DD-init-evolution-review.md
48
48
  ```
49
49
 
50
50
  报告保持短小,包含:
@@ -446,7 +446,7 @@ loop-agent pi-reuse-benchmark \
446
446
 
447
447
  ```bash
448
448
  loop-agent loop-benchmark --markdown
449
- loop-agent loop-benchmark --markdown --output ai_workspace/loop-agent/reports/2026-06-30-loop-agent-loop-benchmark.md
449
+ loop-agent loop-benchmark --markdown --output ai_workspace/loop-agent/reports/dogfood/2026-06-30-loop-agent-loop-benchmark.md
450
450
  ```
451
451
 
452
452
  生成 M0 deterministic baseline,对照 `single-repair`、`3-pass-convergence`、`3-pass-convergence+quota`。**不**跑 live Pi/Cursor call、不创建 task、不改 `convergence.enabled` 默认值。live dogfood 证据缺失时输出 `blocked` 并建议保持 opt-in。
@@ -19,9 +19,9 @@
19
19
  前端专用链在 `frontend-scout-pi` 后加入只读 `frontend-mock-assess-pi` 和确定性 contract gate,根据接口契约、后端就绪度、生成期能力 seed 与固化验证入口选择 `native|browser-intercept|request-adapter|not-needed|blocked`。策略直接传给 plan、条件 design review、唯一 writer、实现 review 和 closeout;真实请求保持默认,缺少契约、生产隔离、注释真实请求或显式 required 合同不完整时 gate 阻塞。standard/full 拓扑的 initial design pass 直接使用 original plan,只有 request-revision 才运行 plan revision 和 final review;small-risk 拓扑保留 final review 作为对 original plan 的单一审查。已删除 `frontend-first-design-gate-shell`,保留的 final gate 只接受生效 initial/final verdict 的 pass。可选 `frontendMock` 配置声明 `auto|required|disabled`、既有服务目录与专项命令;默认 `auto` 下没有已确认 Mock 能力时跳过 Mock 继续实现并保留真实联调缺口,不安全或不完整的显式 required 合同只生成无 writer 的评估链,有可信命令时才增加 `frontend-mock-verify-shell`。Mock-backed 证据只证明前端状态;跳过 Mock 且未调用后端时 closeout 报告 `Frontend status: locally-validated` 与 `Real integration: pending`。初始验证后的 assessment 输出 JSON,只有 `eligible=true` 才运行 repair/reverify/retrace;绿色路径跳过该分支后仍继续 diff/review/只读 `frontend-closeout-pi`,non-repairable 或 `ERROR` 仍硬阻断。
20
20
 
21
21
 
22
- > Backend-test report-first:Analysis v2 明确 responseBody shapeorderingfield comparison/precision sourceRefs,并兼容归一化 v1 及窄范围 evidence gap alias;Manifest 后直接生成 pytest,case review 作为 advisory evidence 进入 canonical context。pytest 生成后由确定性 traceability 校验真实 file/symbol/case 映射,再执行唯一一次 pytest。exit 0/1 JUnit 有效都继续 Result、classification、retrospective 与最终 L-5;Observe 对新 run 投影 initial/canonical、classification 与 coverage,历史 repair/final evidence 仍兼容读取。
22
+ > Backend-test Markdown-first:先由确定性环境 Shell 检查 clean env 中 Python/pytest、常见配置、conftest/fixturetest rootserver entry HTML renderer,失败时不消耗模型调用。随后 Pi 生成并独立 Review `testcase/md/**`,Shell 校验 Case ID、AC/source traceability、章节、步骤、可断言预期与 secret 安全;pytest writer 仅转换最终 Markdown,不重读 `source/**`。traceability 是执行前唯一资产硬门;pytest 只运行一次,生成 JUnit,并从同一 JUnit 生成 self-contained HTML Markdown facts。最终 Pi 只解释事实并生成 Markdown 报告和 L-5 结论。active 流程不要求模型生成 backend-test 业务 JSON。
23
23
 
24
- 显式专用 `taskKind` 保持兼容并优先于任务源分类。`backend-test` 选择固定 **12 个真实顶层节点**的报告优先 DAG:intake 双合同、cases+manifest、advisory case review、pytest 生成、确定性 traceability gate、单次 execute+parse、classification、包含 review/traceability canonical context、retrospective 与最终 L-5。case review 不授权或阻断 writer;pytest assertion failure Result testOutcome,不再由最终 outcome shell gate 将报告流水线判失败。`knowledge-sync` 与 `knowledge-graph-bootstrap` 继续通过各自显式 taskKind 选择知识回写/图谱开荒 DAG。治理等级仍由 `minimal|standard|reviewed|supervised` 推断。
24
+ 显式专用 `taskKind` 保持兼容并优先于任务源分类。`backend-test` 选择固定 **8 个真实顶层节点**的 Markdown-first DAG:环境硬门、Markdown cases、独立 Review/修订、Markdown gate、pytest 转换、确定性 traceability、单次 pytest + JUnit/HTML/facts、最终 Markdown 报告与 L-5。历史 JSON contract/materializer 可继续读取旧 DAG,但新 runtime/template 不再生成模型业务 JSON。`knowledge-sync` 与 `knowledge-graph-bootstrap` 继续通过各自显式 taskKind 选择知识回写/图谱开荒 DAG。治理等级仍由 `minimal|standard|reviewed|supervised` 推断。
25
25
 
26
26
  ### DAG workflow 层级
27
27