@tea-agent/loop-agent 0.16.19 → 0.16.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -5
- package/README.md +8 -0
- package/dist/cli/command-definitions.js +4 -2
- package/dist/cli/program.js +2 -1
- package/dist/cli/update/init-surface-notifier.js +167 -0
- package/dist/cli/update/policy.js +36 -1
- package/dist/cli/update/runtime-activity.js +29 -0
- package/dist/cli.js +14 -2
- package/dist/commands/init.js +85 -2
- package/dist/executors/shell-executor.js +92 -66
- package/dist/executors/shell-write-guard.js +5 -0
- package/dist/shared/runtime-activity.js +6 -0
- package/dist/worker/observability/read-model.js +10 -7
- package/dist/worker/observe/static/views/session-timeline.js +1 -1
- package/dist/workflows/dag/backend-test-case-manifest.js +13 -3
- package/dist/workflows/dag/backend-test-classification-contract.js +38 -0
- package/dist/workflows/dag/backend-test-contract-envelope.js +167 -0
- package/dist/workflows/dag/backend-test-semantic-review-contract.js +2 -2
- package/dist/workflows/dag/init-hybrid.js +64 -409
- package/dist/workflows/dag/node-execution.js +4 -3
- package/dist/workflows/dag/types.js +1 -5
- package/docs/README.md +1 -0
- package/docs/templates/agent-dag.schema.json +1 -1
- package/docs/templates/backend-test-case-manifest.schema.json +35 -2
- package/docs/templates/backend-test-dag.json +39 -340
- package/docs/templates/backend-test-dag.review-cases.prompt.md +4 -4
- package/package.json +1 -1
- package/skills/loop-agent/references/command-reference.md +4 -0
- package/skills/loop-agent/references/hybrid-dag.md +2 -2
- package/dist/workflows/dag/backend-test-repair-contract.js +0 -94
|
@@ -28,10 +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
|
|
32
|
-
"
|
|
31
|
+
"backend-test-dag uses exactly 15 real top-level tasks and executes pytest exactly once.",
|
|
32
|
+
"Case and semantic request-revision verdicts fail at deterministic gates; no in-run revision or repair writer is authorized.",
|
|
33
|
+
"Analysis, execution, manifest, semantic review, single-run result, classification, canonical result, retrospective and outcome evidence remain run-owned and fail-closed.",
|
|
33
34
|
"Functional test case IDs must use BE-<MODULE>-<NNN> format.",
|
|
34
|
-
"pytest writers may only
|
|
35
|
+
"pytest writers may only create the initially declared testcase assets; production code, config, skip/xfail, swallowed failures and mock substitution are forbidden."
|
|
35
36
|
],
|
|
36
37
|
"defaults": {
|
|
37
38
|
"executor": "pi",
|
|
@@ -67,8 +68,8 @@
|
|
|
67
68
|
"executorModels": {
|
|
68
69
|
"pi": {
|
|
69
70
|
"LOW": "gpt-5.3-codex-spark",
|
|
70
|
-
"MED": "
|
|
71
|
-
"HIGH": "gpt-5.
|
|
71
|
+
"MED": "grok-4.5",
|
|
72
|
+
"HIGH": "gpt-5.6-sol"
|
|
72
73
|
}
|
|
73
74
|
},
|
|
74
75
|
"tasks": [
|
|
@@ -89,7 +90,7 @@
|
|
|
89
90
|
"artifacts/**"
|
|
90
91
|
],
|
|
91
92
|
"outputContract": "Pure JSON envelope {analysis: Backend Test Analysis v2, execution: Backend Test Execution Contract v1}; no prose or writes.",
|
|
92
|
-
"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\": \"
|
|
93
|
+
"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\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.",
|
|
93
94
|
"retryPolicy": {
|
|
94
95
|
"maxAttempts": 3,
|
|
95
96
|
"backoff": "exponential",
|
|
@@ -151,7 +152,7 @@
|
|
|
151
152
|
".harness/dag-runs/**",
|
|
152
153
|
"artifacts/**"
|
|
153
154
|
],
|
|
154
|
-
"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
|
|
155
|
+
"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\":[]}",
|
|
155
156
|
"outputContract": "Write testcase/md/** and end with one fenced json Backend Test Case Manifest v1 block matching the strict field contract."
|
|
156
157
|
},
|
|
157
158
|
{
|
|
@@ -205,101 +206,8 @@
|
|
|
205
206
|
".harness/dag-runs/**",
|
|
206
207
|
"artifacts/**"
|
|
207
208
|
],
|
|
208
|
-
"outputContract": "Plain Markdown whose first non-empty line is VERDICT: pass or VERDICT: request-revision; followed by Findings
|
|
209
|
-
"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-
|
|
210
|
-
"retryPolicy": {
|
|
211
|
-
"maxAttempts": 3,
|
|
212
|
-
"backoff": "exponential",
|
|
213
|
-
"initialDelayMs": 2000,
|
|
214
|
-
"maxDelayMs": 30000,
|
|
215
|
-
"retryCategories": [
|
|
216
|
-
"timeout",
|
|
217
|
-
"network",
|
|
218
|
-
"rate-limit",
|
|
219
|
-
"unavailable"
|
|
220
|
-
]
|
|
221
|
-
}
|
|
222
|
-
},
|
|
223
|
-
{
|
|
224
|
-
"id": "revise-backend-cases-pi",
|
|
225
|
-
"depends_on": [
|
|
226
|
-
"review-backend-cases-pi"
|
|
227
|
-
],
|
|
228
|
-
"role": "implementer",
|
|
229
|
-
"executor": "pi",
|
|
230
|
-
"toolProfile": "write",
|
|
231
|
-
"complexity": "MED",
|
|
232
|
-
"writePolicy": "exclusive",
|
|
233
|
-
"writeSet": [
|
|
234
|
-
"testcase/md/**"
|
|
235
|
-
],
|
|
236
|
-
"allowedPaths": [
|
|
237
|
-
"testcase/md/**"
|
|
238
|
-
],
|
|
239
|
-
"forbiddenPaths": [
|
|
240
|
-
".harness/**",
|
|
241
|
-
".harness/dag-runs/**",
|
|
242
|
-
"artifacts/**"
|
|
243
|
-
],
|
|
244
|
-
"outputContract": "Apply one case revision and end with one fenced json final Case Manifest v1 block matching the strict field contract.",
|
|
245
|
-
"subtask_prompt": "You are the single backend case revision pass (max one per DAG run).\n\nThis node is only scheduled when review-backend-cases-pi emitted VERDICT: request-revision.\n\n\n\n## Inputs\n\n- First review: review-backend-cases-pi Markdown (VERDICT + Findings + Required revisions)\n\n- Current cases: testcase/md/**\n\n- Validated analysis + case manifest under the current run contracts/\n\n\n\n## Required work\n\n1. Edit only testcase/md/** to address every Critical finding and Required revision item\n\n2. Fix AC matrices to list FULL BE-* ids matching case bodies; remove false 'all cases' AC claims\n\n3. Keep BE-<MODULE>-<NNN> ids stable when possible; do not invent out-of-scope AC coverage\n\n4. Stay within writeSet; do not write pytest or production code\n\n5. End with a short summary of files touched\n\n\n\nDownstream will re-emit and re-validate Case Manifest v1, then run a FINAL review (pass-only gate).\n\nAfter edits, end assistant output with exactly one fenced json block containing the complete final Backend Test Case Manifest v1.\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, and optional coverageSummary. 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; omit coverageSummary unless all deterministic counts are exact.\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\":[]}",
|
|
246
|
-
"runIf": "$.nodes['review-backend-cases-pi'].firstVerdictLine == 'VERDICT: request-revision'"
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
"id": "backend-test-case-manifest-final-shell",
|
|
250
|
-
"depends_on": [
|
|
251
|
-
"revise-backend-cases-pi"
|
|
252
|
-
],
|
|
253
|
-
"role": "verifier",
|
|
254
|
-
"executor": "shell",
|
|
255
|
-
"complexity": "LOW",
|
|
256
|
-
"writePolicy": "read-only",
|
|
257
|
-
"allowedPaths": [
|
|
258
|
-
"testcase/**",
|
|
259
|
-
"docs/test-reports/**"
|
|
260
|
-
],
|
|
261
|
-
"forbiddenPaths": [
|
|
262
|
-
".harness/**",
|
|
263
|
-
".harness/dag-runs/**",
|
|
264
|
-
"artifacts/**"
|
|
265
|
-
],
|
|
266
|
-
"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.",
|
|
267
|
-
"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.",
|
|
268
|
-
"shell": {
|
|
269
|
-
"commands": [],
|
|
270
|
-
"jsonArtifactGate": {
|
|
271
|
-
"fromNodeId": "revise-backend-cases-pi",
|
|
272
|
-
"schemaId": "backend-test-case-manifest-v1",
|
|
273
|
-
"artifactName": "backend-test-case-manifest.json",
|
|
274
|
-
"outputDir": "contracts"
|
|
275
|
-
},
|
|
276
|
-
"cwd": ".",
|
|
277
|
-
"timeoutMs": 60000
|
|
278
|
-
},
|
|
279
|
-
"runIf": "$.nodes['review-backend-cases-pi'].firstVerdictLine == 'VERDICT: request-revision'"
|
|
280
|
-
},
|
|
281
|
-
{
|
|
282
|
-
"id": "review-backend-cases-final-pi",
|
|
283
|
-
"depends_on": [
|
|
284
|
-
"backend-test-case-manifest-final-shell",
|
|
285
|
-
"validate-backend-test-contracts-shell"
|
|
286
|
-
],
|
|
287
|
-
"role": "reviewer",
|
|
288
|
-
"executor": "pi",
|
|
289
|
-
"complexity": "HIGH",
|
|
290
|
-
"writePolicy": "read-only",
|
|
291
|
-
"allowedPaths": [
|
|
292
|
-
"testcase/**",
|
|
293
|
-
"docs/test-reports/**"
|
|
294
|
-
],
|
|
295
|
-
"forbiddenPaths": [
|
|
296
|
-
".harness/**",
|
|
297
|
-
".harness/dag-runs/**",
|
|
298
|
-
"artifacts/**"
|
|
299
|
-
],
|
|
300
|
-
"outputContract": "Plain Markdown whose first non-empty line is VERDICT: pass or VERDICT: request-revision after at most one revision; followed by Findings and Coverage Assessment. No file writes. Final gate accepts pass only.",
|
|
301
|
-
"subtask_prompt": "Final review of backend functional cases under testcase/md/ and the re-validated Case Manifest v1 after at most one revision pass.\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- This is the FINAL review after one revision opportunity; remaining Critical issues must still request-revision (final gate will stop the DAG).\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\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",
|
|
302
|
-
"runIf": "$.nodes['review-backend-cases-pi'].firstVerdictLine == 'VERDICT: request-revision'",
|
|
209
|
+
"outputContract": "Plain Markdown whose first non-empty line is VERDICT: pass or VERDICT: request-revision; followed by Findings and Coverage Assessment. No file writes. The deterministic gate accepts pass only; request-revision ends this run.",
|
|
210
|
+
"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 ends the current run at the deterministic gate; describe findings clearly for an independent follow-up task.\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",
|
|
303
211
|
"retryPolicy": {
|
|
304
212
|
"maxAttempts": 3,
|
|
305
213
|
"backoff": "exponential",
|
|
@@ -316,10 +224,8 @@
|
|
|
316
224
|
{
|
|
317
225
|
"id": "review-backend-cases-gate-shell",
|
|
318
226
|
"depends_on": [
|
|
319
|
-
"review-backend-cases-pi"
|
|
320
|
-
"review-backend-cases-final-pi"
|
|
227
|
+
"review-backend-cases-pi"
|
|
321
228
|
],
|
|
322
|
-
"dependsPolicy": "all-or-condition-skip",
|
|
323
229
|
"role": "verifier",
|
|
324
230
|
"executor": "shell",
|
|
325
231
|
"complexity": "LOW",
|
|
@@ -333,19 +239,16 @@
|
|
|
333
239
|
".harness/dag-runs/**",
|
|
334
240
|
"artifacts/**"
|
|
335
241
|
],
|
|
336
|
-
"outputContract": "Deterministic backend case review gate: exit 0 only when the
|
|
337
|
-
"subtask_prompt": "
|
|
242
|
+
"outputContract": "Deterministic backend case review gate: exit 0 only when the first and only review emits VERDICT: pass.",
|
|
243
|
+
"subtask_prompt": "Block pytest generation when backend case review requests revision; do not authorize an in-run writer.",
|
|
338
244
|
"shell": {
|
|
339
245
|
"commands": [],
|
|
340
246
|
"verdictGate": {
|
|
341
|
-
"fromNodeId": "review-backend-cases-
|
|
342
|
-
"fallbackFromNodeIds": [
|
|
343
|
-
"review-backend-cases-pi"
|
|
344
|
-
],
|
|
247
|
+
"fromNodeId": "review-backend-cases-pi",
|
|
345
248
|
"accept": [
|
|
346
249
|
"VERDICT: pass"
|
|
347
250
|
],
|
|
348
|
-
"label": "backend case
|
|
251
|
+
"label": "backend case review",
|
|
349
252
|
"lineMode": "first-verdict-line"
|
|
350
253
|
},
|
|
351
254
|
"cwd": ".",
|
|
@@ -377,17 +280,15 @@
|
|
|
377
280
|
".harness/dag-runs/**",
|
|
378
281
|
"artifacts/**"
|
|
379
282
|
],
|
|
380
|
-
"subtask_prompt": "Convert the reviewed test cases under testcase/md/ into pytest automation code.\n\n\n\n## Inputs (MUST use validated contracts):\n\n- Reviewed cases under testcase/md/ (after review-backend-cases-gate-shell).\n\n- Validated Backend Test Analysis v1 under the current run contracts/ (analysis gate).\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\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"
|
|
283
|
+
"subtask_prompt": "Convert the reviewed test cases under testcase/md/ into pytest automation code.\n\n\n\n## Inputs (MUST use validated contracts):\n\n- Reviewed cases under testcase/md/ (after review-backend-cases-gate-shell).\n\n- Validated Backend Test Analysis v1 under the current run contracts/ (analysis gate).\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\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."
|
|
381
284
|
},
|
|
382
285
|
{
|
|
383
286
|
"id": "review-generated-backend-pytest-pi",
|
|
384
287
|
"depends_on": [
|
|
385
288
|
"generate-backend-pytest-pi",
|
|
386
289
|
"validate-backend-test-contracts-shell",
|
|
387
|
-
"backend-test-case-manifest-shell"
|
|
388
|
-
"backend-test-case-manifest-final-shell"
|
|
290
|
+
"backend-test-case-manifest-shell"
|
|
389
291
|
],
|
|
390
|
-
"dependsPolicy": "all-or-condition-skip",
|
|
391
292
|
"role": "reviewer",
|
|
392
293
|
"executor": "pi",
|
|
393
294
|
"complexity": "MED",
|
|
@@ -401,7 +302,7 @@
|
|
|
401
302
|
"artifacts/**"
|
|
402
303
|
],
|
|
403
304
|
"outputContract": "Pure Backend Test Semantic Review v1 JSON: verdict, findings[], summary. No file writes.",
|
|
404
|
-
"subtask_prompt": "Review generated pytest semantics before the
|
|
305
|
+
"subtask_prompt": "Review generated pytest semantics before the single execution.\n\nUse only compact authoritative inputs: contracts/backend-test-analysis.json, contracts/backend-test-case-manifest.json, testcase/md/**, and generated testcase/**/test_*.py/helpers/factories.\n\nReturn exactly one pure JSON object with only verdict, findings, summary; no Markdown fence or surrounding prose.\n\nverdict must be pass or request-revision. Each findings[] item must contain exactly severity, caseId, testFile, testSymbol, contractRefs, issue, requiredChange.\n\nseverity must be exactly Critical, Important, or Informational; contractRefs must be a non-empty string array. A request-revision verdict requires at least one finding; pass must not contain Critical findings.\n\nMinimal shape: {\"verdict\":\"pass\",\"findings\":[],\"summary\":\"No contract-backed semantic contradiction found.\"}\n\nCheck responseBody.kind (array vs object/items), ordering, field comparison (especially parseable-only date-time precision), documented status/error fields, and each caseId→symbol assertion meaning.\n\nDo not use aliases such as file, symbol, refs, finding, or requiredFix; the strict contract requires testFile, testSymbol, contractRefs, issue, requiredChange.\n\nrequest-revision only for concrete semantic contradiction with reviewed cases/formal analysis evidence. No style findings.\n\nRead-only; do not edit tests or production code.",
|
|
405
306
|
"retryPolicy": {
|
|
406
307
|
"maxAttempts": 3,
|
|
407
308
|
"backoff": "exponential",
|
|
@@ -419,10 +320,8 @@
|
|
|
419
320
|
"id": "validate-semantic-review-and-traceability-shell",
|
|
420
321
|
"depends_on": [
|
|
421
322
|
"review-generated-backend-pytest-pi",
|
|
422
|
-
"backend-test-case-manifest-shell"
|
|
423
|
-
"backend-test-case-manifest-final-shell"
|
|
323
|
+
"backend-test-case-manifest-shell"
|
|
424
324
|
],
|
|
425
|
-
"dependsPolicy": "all-or-condition-skip",
|
|
426
325
|
"role": "verifier",
|
|
427
326
|
"executor": "shell",
|
|
428
327
|
"complexity": "LOW",
|
|
@@ -436,8 +335,8 @@
|
|
|
436
335
|
".harness/dag-runs/**",
|
|
437
336
|
"artifacts/**"
|
|
438
337
|
],
|
|
439
|
-
"outputContract": "Materialize
|
|
440
|
-
"subtask_prompt": "
|
|
338
|
+
"outputContract": "Materialize the only semantic review and validate pytest traceability.",
|
|
339
|
+
"subtask_prompt": "Materialize semantic facts and traceability; verdict authorization is handled by the next deterministic gate.",
|
|
441
340
|
"shell": {
|
|
442
341
|
"commands": [],
|
|
443
342
|
"backendTestPipeline": "semantic-initial",
|
|
@@ -446,108 +345,11 @@
|
|
|
446
345
|
}
|
|
447
346
|
},
|
|
448
347
|
{
|
|
449
|
-
"id": "
|
|
450
|
-
"depends_on": [
|
|
451
|
-
"validate-semantic-review-and-traceability-shell"
|
|
452
|
-
],
|
|
453
|
-
"role": "implementer",
|
|
454
|
-
"executor": "pi",
|
|
455
|
-
"toolProfile": "write",
|
|
456
|
-
"complexity": "MED",
|
|
457
|
-
"writePolicy": "exclusive",
|
|
458
|
-
"writeSet": [
|
|
459
|
-
"testcase/**/test_*.py",
|
|
460
|
-
"testcase/**/helpers/**",
|
|
461
|
-
"testcase/**/factories/**"
|
|
462
|
-
],
|
|
463
|
-
"allowedPaths": [
|
|
464
|
-
"testcase/**/test_*.py",
|
|
465
|
-
"testcase/**/helpers/**",
|
|
466
|
-
"testcase/**/factories/**"
|
|
467
|
-
],
|
|
468
|
-
"forbiddenPaths": [
|
|
469
|
-
".harness/**",
|
|
470
|
-
".harness/dag-runs/**",
|
|
471
|
-
"artifacts/**",
|
|
472
|
-
"apps/**",
|
|
473
|
-
"src/**",
|
|
474
|
-
"testcase/md/**",
|
|
475
|
-
"**/conftest.py",
|
|
476
|
-
"**/pytest.ini"
|
|
477
|
-
],
|
|
478
|
-
"outputContract": "Apply one bounded semantic correction to generated pytest from validated findings only.",
|
|
479
|
-
"subtask_prompt": "This is the only pre-execution generated-pytest semantic revision (1/1).\n\nRead contracts/backend-test-semantic-review.json and edit only the cited generated test files/helpers/factories.\n\nPreserve case IDs, symbols, test count, target mode, base URL and real-service path.\n\nDo not delete tests, add skip/xfail, swallow failures, substitute mocks, or weaken assertions beyond the formal comparison/shape contract.\n\nDo not modify product code, testcase/md/**, conftest.py, pytest.ini, or .harness/**.",
|
|
480
|
-
"runIf": "$.nodes['validate-semantic-review-and-traceability-shell'].json.verdict == 'request-revision'"
|
|
481
|
-
},
|
|
482
|
-
{
|
|
483
|
-
"id": "review-generated-backend-pytest-final-pi",
|
|
484
|
-
"depends_on": [
|
|
485
|
-
"revise-generated-backend-pytest-pi"
|
|
486
|
-
],
|
|
487
|
-
"dependsPolicy": "all-or-condition-skip",
|
|
488
|
-
"role": "reviewer",
|
|
489
|
-
"executor": "pi",
|
|
490
|
-
"complexity": "MED",
|
|
491
|
-
"writePolicy": "read-only",
|
|
492
|
-
"allowedPaths": [
|
|
493
|
-
"testcase/**"
|
|
494
|
-
],
|
|
495
|
-
"forbiddenPaths": [
|
|
496
|
-
".harness/**",
|
|
497
|
-
".harness/dag-runs/**",
|
|
498
|
-
"artifacts/**"
|
|
499
|
-
],
|
|
500
|
-
"outputContract": "Pure Backend Test Semantic Review v1 JSON: verdict, findings[], summary. No file writes.",
|
|
501
|
-
"subtask_prompt": "Final semantic review after the single generated-pytest revision.\n\nUse only compact authoritative inputs: contracts/backend-test-analysis.json, contracts/backend-test-case-manifest.json, testcase/md/**, and generated testcase/**/test_*.py/helpers/factories.\n\nReturn exactly one pure JSON object with only verdict, findings, summary; no Markdown fence or surrounding prose.\n\nverdict must be pass or request-revision. Each findings[] item must contain exactly severity, caseId, testFile, testSymbol, contractRefs, issue, requiredChange.\n\nseverity must be exactly Critical, Important, or Informational; contractRefs must be a non-empty string array. A request-revision verdict requires at least one finding; pass must not contain Critical findings.\n\nMinimal shape: {\"verdict\":\"pass\",\"findings\":[],\"summary\":\"No contract-backed semantic contradiction found.\"}\n\nCheck responseBody.kind (array vs object/items), ordering, field comparison (especially parseable-only date-time precision), documented status/error fields, and each caseId→symbol assertion meaning.\n\nDo not use aliases such as file, symbol, refs, finding, or requiredFix; the strict contract requires testFile, testSymbol, contractRefs, issue, requiredChange.\n\nrequest-revision only for concrete semantic contradiction with reviewed cases/formal analysis evidence. No style findings.\n\nRead-only; do not edit tests or production code.",
|
|
502
|
-
"runIf": "$.nodes['validate-semantic-review-and-traceability-shell'].json.verdict == 'request-revision'",
|
|
503
|
-
"retryPolicy": {
|
|
504
|
-
"maxAttempts": 3,
|
|
505
|
-
"backoff": "exponential",
|
|
506
|
-
"initialDelayMs": 2000,
|
|
507
|
-
"maxDelayMs": 30000,
|
|
508
|
-
"retryCategories": [
|
|
509
|
-
"timeout",
|
|
510
|
-
"network",
|
|
511
|
-
"rate-limit",
|
|
512
|
-
"unavailable"
|
|
513
|
-
]
|
|
514
|
-
}
|
|
515
|
-
},
|
|
516
|
-
{
|
|
517
|
-
"id": "materialize-final-semantic-review-shell",
|
|
518
|
-
"depends_on": [
|
|
519
|
-
"review-generated-backend-pytest-final-pi"
|
|
520
|
-
],
|
|
521
|
-
"role": "verifier",
|
|
522
|
-
"executor": "shell",
|
|
523
|
-
"complexity": "LOW",
|
|
524
|
-
"writePolicy": "read-only",
|
|
525
|
-
"allowedPaths": [
|
|
526
|
-
"testcase/**",
|
|
527
|
-
"docs/test-reports/**"
|
|
528
|
-
],
|
|
529
|
-
"forbiddenPaths": [
|
|
530
|
-
".harness/**",
|
|
531
|
-
".harness/dag-runs/**",
|
|
532
|
-
"artifacts/**"
|
|
533
|
-
],
|
|
534
|
-
"runIf": "$.nodes['validate-semantic-review-and-traceability-shell'].json.verdict == 'request-revision'",
|
|
535
|
-
"outputContract": "Materialize final semantic review and re-check traceability.",
|
|
536
|
-
"subtask_prompt": "Validate final semantic review and traceability.",
|
|
537
|
-
"shell": {
|
|
538
|
-
"commands": [],
|
|
539
|
-
"backendTestPipeline": "semantic-final",
|
|
540
|
-
"cwd": ".",
|
|
541
|
-
"timeoutMs": 60000
|
|
542
|
-
}
|
|
543
|
-
},
|
|
544
|
-
{
|
|
545
|
-
"id": "backend-test-semantic-final-gate-shell",
|
|
348
|
+
"id": "backend-test-semantic-gate-shell",
|
|
546
349
|
"depends_on": [
|
|
547
350
|
"validate-semantic-review-and-traceability-shell",
|
|
548
|
-
"
|
|
351
|
+
"review-generated-backend-pytest-pi"
|
|
549
352
|
],
|
|
550
|
-
"dependsPolicy": "all-or-condition-skip",
|
|
551
353
|
"role": "verifier",
|
|
552
354
|
"executor": "shell",
|
|
553
355
|
"complexity": "LOW",
|
|
@@ -561,20 +363,19 @@
|
|
|
561
363
|
".harness/dag-runs/**",
|
|
562
364
|
"artifacts/**"
|
|
563
365
|
],
|
|
564
|
-
"outputContract": "Pass-only
|
|
565
|
-
"subtask_prompt": "
|
|
366
|
+
"outputContract": "Pass-only authorization by reading contracts/backend-test-semantic-review.json; only verdict=pass proceeds to the single pytest execution.",
|
|
367
|
+
"subtask_prompt": "Read the canonical semantic review artifact written by validate-semantic-review-and-traceability-shell. Authorize only when verdict is pass. Do not materialize, do not parse raw Pi Markdown or VERDICT lines, and do not authorize an in-run pytest writer.",
|
|
566
368
|
"shell": {
|
|
567
|
-
"commands": [
|
|
568
|
-
|
|
569
|
-
],
|
|
369
|
+
"commands": [],
|
|
370
|
+
"backendTestPipeline": "semantic-initial",
|
|
570
371
|
"cwd": ".",
|
|
571
372
|
"timeoutMs": 60000
|
|
572
373
|
}
|
|
573
374
|
},
|
|
574
375
|
{
|
|
575
|
-
"id": "execute-and-parse-backend-pytest-
|
|
376
|
+
"id": "execute-and-parse-backend-pytest-shell",
|
|
576
377
|
"depends_on": [
|
|
577
|
-
"backend-test-semantic-
|
|
378
|
+
"backend-test-semantic-gate-shell",
|
|
578
379
|
"validate-backend-test-contracts-shell"
|
|
579
380
|
],
|
|
580
381
|
"role": "verifier",
|
|
@@ -615,7 +416,7 @@
|
|
|
615
416
|
{
|
|
616
417
|
"id": "classify-backend-test-result-pi",
|
|
617
418
|
"depends_on": [
|
|
618
|
-
"execute-and-parse-backend-pytest-
|
|
419
|
+
"execute-and-parse-backend-pytest-shell"
|
|
619
420
|
],
|
|
620
421
|
"role": "reviewer",
|
|
621
422
|
"executor": "pi",
|
|
@@ -646,9 +447,10 @@
|
|
|
646
447
|
}
|
|
647
448
|
},
|
|
648
449
|
{
|
|
649
|
-
"id": "materialize-classification-and-
|
|
450
|
+
"id": "materialize-classification-and-result-context-shell",
|
|
650
451
|
"depends_on": [
|
|
651
|
-
"classify-backend-test-result-pi"
|
|
452
|
+
"classify-backend-test-result-pi",
|
|
453
|
+
"backend-test-case-manifest-shell"
|
|
652
454
|
],
|
|
653
455
|
"role": "verifier",
|
|
654
456
|
"executor": "shell",
|
|
@@ -663,122 +465,19 @@
|
|
|
663
465
|
".harness/dag-runs/**",
|
|
664
466
|
"artifacts/**"
|
|
665
467
|
],
|
|
666
|
-
"outputContract": "Materialize Classification v1 and
|
|
667
|
-
"subtask_prompt": "Validate classification and
|
|
668
|
-
"shell": {
|
|
669
|
-
"commands": [],
|
|
670
|
-
"backendTestPipeline": "classification-eligibility",
|
|
671
|
-
"cwd": ".",
|
|
672
|
-
"timeoutMs": 60000
|
|
673
|
-
}
|
|
674
|
-
},
|
|
675
|
-
{
|
|
676
|
-
"id": "repair-backend-pytest-pi",
|
|
677
|
-
"depends_on": [
|
|
678
|
-
"materialize-classification-and-eligibility-shell"
|
|
679
|
-
],
|
|
680
|
-
"role": "implementer",
|
|
681
|
-
"executor": "pi",
|
|
682
|
-
"toolProfile": "write",
|
|
683
|
-
"complexity": "HIGH",
|
|
684
|
-
"writePolicy": "exclusive",
|
|
685
|
-
"writeSet": [
|
|
686
|
-
"testcase/**/test_*.py",
|
|
687
|
-
"testcase/**/helpers/**",
|
|
688
|
-
"testcase/**/factories/**"
|
|
689
|
-
],
|
|
690
|
-
"allowedPaths": [
|
|
691
|
-
"testcase/**/test_*.py",
|
|
692
|
-
"testcase/**/helpers/**",
|
|
693
|
-
"testcase/**/factories/**"
|
|
694
|
-
],
|
|
695
|
-
"forbiddenPaths": [
|
|
696
|
-
".harness/**",
|
|
697
|
-
".harness/dag-runs/**",
|
|
698
|
-
"artifacts/**",
|
|
699
|
-
"apps/**",
|
|
700
|
-
"src/**",
|
|
701
|
-
".env*",
|
|
702
|
-
"**/migrations/**"
|
|
703
|
-
],
|
|
704
|
-
"outputContract": "Repair only existing generated pytest tests/helpers/factories for classified TestBug findings. No production/config/runtime evidence writes.",
|
|
705
|
-
"subtask_prompt": "This is the only automatic TestBug repair attempt (1/1).\n\nRead contracts/backend-test-result-initial.json, contracts/backend-test-classification.json, contracts/backend-test-analysis.json, contracts/backend-test-case-manifest.json, and only the generated pytest files named in failures[].name or manifest mappings.\n\nDo not re-read the full task source tree: the run-owned analysis/manifest are the compact authoritative context.\n\nRepair only test implementation defects directly supported by reviewed Expected Results or formal API contract evidence.\n\nNever modify product code, migrations, service configuration, conftest.py, pytest.ini, pyproject.toml, setup.cfg, source requirements, testcase/md/**, or .harness/**.\n\nNever delete a test, remove a case mapping, add skip/skipif/xfail, swallow AssertionError/network exceptions, switch to a mock server, or weaken documented status/value assertions.\n\nKeep the full suite runnable and preserve each BE-* case ID and pytest symbol mapping.\n\nStay within writeSet: testcase/**/test_*.py, helpers/**, factories/**.",
|
|
706
|
-
"runIf": "$.nodes['materialize-classification-and-eligibility-shell'].json.eligible == true"
|
|
707
|
-
},
|
|
708
|
-
{
|
|
709
|
-
"id": "validate-repair-safety-and-traceability-shell",
|
|
710
|
-
"depends_on": [
|
|
711
|
-
"repair-backend-pytest-pi"
|
|
712
|
-
],
|
|
713
|
-
"role": "verifier",
|
|
714
|
-
"executor": "shell",
|
|
715
|
-
"complexity": "LOW",
|
|
716
|
-
"writePolicy": "read-only",
|
|
717
|
-
"allowedPaths": [
|
|
718
|
-
"testcase/**"
|
|
719
|
-
],
|
|
720
|
-
"forbiddenPaths": [
|
|
721
|
-
".harness/**",
|
|
722
|
-
".harness/dag-runs/**",
|
|
723
|
-
"artifacts/**"
|
|
724
|
-
],
|
|
725
|
-
"runIf": "$.nodes['materialize-classification-and-eligibility-shell'].json.eligible == true",
|
|
726
|
-
"outputContract": "Validate repair safety and final traceability.",
|
|
727
|
-
"subtask_prompt": "Reject manufactured success and revalidate mapping.",
|
|
468
|
+
"outputContract": "Materialize Classification v1, copy the unique initial Result to canonical contracts/backend-test-result.json, and emit Result + Manifest + Classification context.",
|
|
469
|
+
"subtask_prompt": "Validate classification and materialize canonical single-run result context without repair eligibility or rerun.",
|
|
728
470
|
"shell": {
|
|
729
471
|
"commands": [],
|
|
730
|
-
"backendTestPipeline": "
|
|
472
|
+
"backendTestPipeline": "classification-result-context",
|
|
731
473
|
"cwd": ".",
|
|
732
474
|
"timeoutMs": 60000
|
|
733
475
|
}
|
|
734
476
|
},
|
|
735
|
-
{
|
|
736
|
-
"id": "finalize-effective-backend-test-result-shell",
|
|
737
|
-
"depends_on": [
|
|
738
|
-
"materialize-classification-and-eligibility-shell",
|
|
739
|
-
"validate-repair-safety-and-traceability-shell",
|
|
740
|
-
"validate-backend-test-contracts-shell"
|
|
741
|
-
],
|
|
742
|
-
"role": "verifier",
|
|
743
|
-
"executor": "shell",
|
|
744
|
-
"complexity": "LOW",
|
|
745
|
-
"writePolicy": "read-only",
|
|
746
|
-
"allowedPaths": [
|
|
747
|
-
"testcase/**",
|
|
748
|
-
"docs/test-reports/**"
|
|
749
|
-
],
|
|
750
|
-
"forbiddenPaths": [
|
|
751
|
-
".harness/**",
|
|
752
|
-
".harness/dag-runs/**",
|
|
753
|
-
"artifacts/**"
|
|
754
|
-
],
|
|
755
|
-
"outputContract": "If repaired, execute/parse final pytest; always materialize contracts/backend-test-result.json from final or initial result.",
|
|
756
|
-
"subtask_prompt": "Run pytest for the backend test suite; write JUnit + pytestExitCode evidence only under the current HARNESS_DAG_RUN_DIR/reports/.",
|
|
757
|
-
"shell": {
|
|
758
|
-
"commands": [
|
|
759
|
-
"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-final-junit.xml\"; EXIT_FILE=\"${HARNESS_DAG_RUN_DIR}/reports/backend-test-final-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}\""
|
|
760
|
-
],
|
|
761
|
-
"envAllowlist": [],
|
|
762
|
-
"verifyEvidence": {
|
|
763
|
-
"phase": "final",
|
|
764
|
-
"quota": "full",
|
|
765
|
-
"commandSource": "inline",
|
|
766
|
-
"commandCount": 1,
|
|
767
|
-
"commandLabels": [
|
|
768
|
-
"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-final-junit.xml\"; EXIT_FILE=\"${HARNESS_DAG_RUN_DIR}/reports/backend-test-final-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}\""
|
|
769
|
-
],
|
|
770
|
-
"finalFullRequired": true
|
|
771
|
-
},
|
|
772
|
-
"cwd": ".",
|
|
773
|
-
"timeoutMs": 300000,
|
|
774
|
-
"backendTestPipeline": "finalize-effective-result"
|
|
775
|
-
},
|
|
776
|
-
"dependsPolicy": "all-or-condition-skip"
|
|
777
|
-
},
|
|
778
477
|
{
|
|
779
478
|
"id": "test-retrospect-pi",
|
|
780
479
|
"depends_on": [
|
|
781
|
-
"
|
|
480
|
+
"materialize-classification-and-result-context-shell"
|
|
782
481
|
],
|
|
783
482
|
"role": "closeout",
|
|
784
483
|
"executor": "pi",
|
|
@@ -797,7 +496,7 @@
|
|
|
797
496
|
"artifacts/**"
|
|
798
497
|
],
|
|
799
498
|
"outputContract": "Maturity rating in assistant output plus a report written under docs/test-reports/**.",
|
|
800
|
-
"subtask_prompt": "Read the complete JSON from direct upstream
|
|
499
|
+
"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- Use classify-backend-test-result-pi JSON as interpretive evidence only.\n\n- NEVER rewrite a failed result as passed. Outcome gate (not this report) is authoritative for task success.\n\n\n\n## Report Structure:\n\n1. Maturity Rating with rationale\n\n2. Test Coverage Summary (manifest coverageSummary + Result v1 pass rate)\n\n3. Review Findings and resolution status\n\n4. Failed Test Analysis (if any) + classification category\n\n5. Recommendations for improvement\n\n\n\n## Rating Criteria:\n\n- A: coverageSummary.acCoverageRatio=1 + 100% pytest pass + no Critical findings\n\n- B: acCoverageRatio≥0.8 + ≥90% pass + Low findings only\n\n- C: acCoverageRatio≥0.6 + ≥70% pass + no Critical findings\n\n- D: below C thresholds\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/**"
|
|
801
500
|
},
|
|
802
501
|
{
|
|
803
502
|
"id": "backend-test-outcome-gate-shell",
|
|
@@ -845,7 +544,7 @@
|
|
|
845
544
|
{
|
|
846
545
|
"kind": "requirement",
|
|
847
546
|
"path": "source/需求.md",
|
|
848
|
-
"sha256": "
|
|
547
|
+
"sha256": "e33ab9d1d3d6a785b8f429d8581d015a299adc093b0c9a7c0f9057f968a71837"
|
|
849
548
|
}
|
|
850
549
|
],
|
|
851
550
|
"requirementIds": [
|