@tea-agent/loop-agent 0.13.0-beta.0 → 0.14.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.
- package/AGENTS.md +2 -0
- package/CHANGELOG.md +56 -305
- package/README.md +13 -19
- package/dist/commands/init.js +92 -23
- package/dist/executors/pi-event-serializer.js +33 -11
- package/dist/executors/shell-executor.js +200 -21
- package/dist/infrastructure/evaluation/candidate-store.js +5 -1
- package/dist/worker/observe/spec-evidence.js +19 -10
- package/dist/worker/observe/static/app.js +4 -3
- package/dist/worker/observe/static/constants.js +10 -2
- package/dist/worker/observe/static/dag-helpers.js +37 -8
- package/dist/worker/observe/static/dom.js +159 -0
- package/dist/worker/observe/static/format-pool.d.ts +71 -0
- package/dist/worker/observe/static/format-pool.js +67 -0
- package/dist/worker/observe/static/format.js +27 -2
- package/dist/worker/observe/static/index.html +76 -34
- package/dist/worker/observe/static/kpi.js +12 -6
- package/dist/worker/observe/static/markdown-render.js +124 -0
- package/dist/worker/observe/static/shell-chrome.js +8 -2
- package/dist/worker/observe/static/state.js +20 -0
- package/dist/worker/observe/static/styles.css +662 -60
- package/dist/worker/observe/static/views/dag-inspector.js +65 -142
- package/dist/worker/observe/static/views/dag.js +9 -0
- package/dist/worker/observe/static/views/dashboard.js +512 -269
- package/dist/worker/observe/static/views/pool.js +595 -237
- package/dist/worker/observe/static/views/session-timeline.js +577 -11
- package/dist/workflows/dag/backend-test-case-manifest.js +503 -0
- package/dist/workflows/dag/backend-test-execution-contract.js +353 -0
- package/dist/workflows/dag/backend-test-result-contract.js +568 -0
- package/dist/workflows/dag/decision-envelope.js +57 -2
- package/dist/workflows/dag/frontend-implementation-contract.js +240 -0
- package/dist/workflows/dag/frontend-project-capability.js +309 -0
- package/dist/workflows/dag/frontend-repair.js +341 -0
- package/dist/workflows/dag/frontend-risk.js +161 -0
- package/dist/workflows/dag/frontend-verification-trace.js +190 -0
- package/dist/workflows/dag/init-hybrid.js +1020 -125
- package/dist/workflows/dag/repair-artifact.js +43 -3
- package/dist/workflows/dag/skill-instructions.js +4 -2
- package/dist/workflows/dag/types.js +29 -8
- package/docs/README.md +2 -0
- package/docs/agent-dag-recovery-playbook.md +3 -3
- package/docs/agent-dag-runner.md +3 -3
- package/docs/architecture/README.md +3 -3
- package/docs/architecture/dag-execution.md +1 -1
- package/docs/architecture/evolution.md +13 -13
- package/docs/architecture/facts-and-state.md +1 -1
- package/docs/architecture/runtime-boundaries.md +7 -7
- package/docs/architecture/system-overview.md +3 -3
- package/docs/architecture/worker-and-feature.md +3 -3
- package/docs/design/README.md +7 -7
- package/docs/development-principles.md +4 -4
- package/docs/exec-plans/active/README.md +2 -4
- package/docs/exec-plans/completed/README.md +29 -6
- package/docs/feature-workflow.md +57 -32
- package/docs/init-surface.manifest.json +21 -3
- package/docs/loop-agent-harness.md +8 -8
- package/docs/production-readiness.md +1 -1
- package/docs/progress/README.md +20 -3
- package/docs/reports/README.md +53 -7
- package/docs/templates/agent-dag.supervised-implementation.json +127 -8
- package/docs/templates/backend-test-case-manifest.schema.json +190 -0
- package/docs/templates/backend-test-dag.classify.prompt.md +75 -0
- package/docs/templates/backend-test-dag.generate-pytest.prompt.md +6 -4
- package/docs/templates/backend-test-dag.json +269 -21
- package/docs/templates/backend-test-dag.retrospect.prompt.md +44 -30
- package/docs/templates/backend-test-dag.review-cases.prompt.md +6 -4
- package/docs/templates/backend-test-execution.schema.json +133 -0
- package/docs/templates/backend-test-result.schema.json +99 -0
- package/docs/templates/branch-merge-report.md +93 -0
- package/docs/templates/frontend-eval/fixtures/failures/01-type-build-error.md +17 -0
- package/docs/templates/frontend-eval/fixtures/failures/02-unit-component-test-fail.md +16 -0
- package/docs/templates/frontend-eval/fixtures/failures/03-fixture-schema-drift.md +16 -0
- package/docs/templates/frontend-eval/fixtures/failures/04-missing-loading-empty-error-state.md +16 -0
- package/docs/templates/frontend-eval/fixtures/failures/05-forbidden-write-writeset-expansion.md +16 -0
- package/docs/templates/frontend-eval/fixtures/failures/06-unapproved-dependency-add.md +16 -0
- package/docs/templates/frontend-eval/fixtures/failures/07-mock-production-on.md +21 -0
- package/docs/templates/frontend-eval/fixtures/functional/01-simple-component-style.md +29 -0
- package/docs/templates/frontend-eval/fixtures/functional/02-form-validation.md +28 -0
- package/docs/templates/frontend-eval/fixtures/functional/03-list-detail-page.md +28 -0
- package/docs/templates/frontend-eval/fixtures/functional/04-api-mock.md +29 -0
- package/docs/templates/frontend-eval/fixtures/functional/05-permission-auth-gated-ui.md +27 -0
- package/docs/templates/frontend-eval/fixtures/functional/06-ssr-server-client-boundary.md +28 -0
- package/docs/templates/frontend-eval/fixtures/functional/07-shared-public-component-api.md +28 -0
- package/docs/templates/frontend-eval/fixtures/functional/08-pure-local-no-remote.md +27 -0
- package/docs/templates/frontend-eval/metrics.md +138 -0
- package/docs/templates/frontend-eval/smoke-targets.md +53 -0
- package/docs/templates/frontend-implementation-contract.schema.json +27 -0
- package/docs/verification-matrix.md +1 -1
- package/examples/decision-gate-agent-dag.json +4 -4
- package/examples/hybrid-loop-agent-dag.json +1 -1
- package/package.json +2 -2
- package/skills/ai-engineering-context/SKILL.md +2 -2
- package/skills/browser-tools/SKILL.md +196 -0
- package/skills/browser-tools/browser-content.js +103 -0
- package/skills/browser-tools/browser-cookies.js +35 -0
- package/skills/browser-tools/browser-eval.js +53 -0
- package/skills/browser-tools/browser-hn-scraper.js +108 -0
- package/skills/browser-tools/browser-nav.js +44 -0
- package/skills/browser-tools/browser-pick.js +162 -0
- package/skills/browser-tools/browser-screenshot.js +34 -0
- package/skills/browser-tools/browser-start.js +86 -0
- package/skills/browser-tools/package-lock.json +2556 -0
- package/skills/browser-tools/package.json +19 -0
- package/skills/frontend-implementation/SKILL.md +3 -1
- package/skills/frontend-implementation/references/node-contracts.md +17 -66
- package/skills/frontend-verification/SKILL.md +1 -1
- package/skills/grill-with-docs/SKILL.md +5 -5
- package/skills/grill-with-docs/adr-format.md +3 -3
- package/skills/init-capability-evolution/SKILL.md +5 -5
- package/skills/loop-agent/SKILL.md +5 -5
- package/skills/loop-agent/references/README.md +3 -3
- package/skills/loop-agent/references/command-reference.md +39 -17
- package/skills/loop-agent/references/docs-converge.md +15 -15
- package/skills/loop-agent/references/harness-policy.md +2 -2
- package/skills/loop-agent/references/hybrid-dag.md +20 -15
- package/skills/loop-agent/references/multi-worktree.md +1 -1
- package/skills/loop-agent/references/orchestrator-and-interventions.md +8 -8
- package/skills/loop-agent/references/task-workflow.md +1 -1
- package/skills/loop-agent/references/verification-and-failure-handling.md +6 -4
- package/skills/requesting-code-review/SKILL.md +1 -1
- package/skills/systematic-debugging/CREATION-LOG.md +3 -3
- package/skills/systematic-debugging/SKILL.md +1 -1
- package/skills/systematic-debugging/test-academic.md +1 -1
- package/skills/systematic-debugging/test-pressure-1.md +1 -1
- package/skills/systematic-debugging/test-pressure-2.md +1 -1
- package/skills/systematic-debugging/test-pressure-3.md +1 -1
- package/skills/verification-before-completion/SKILL.md +1 -1
|
@@ -7,15 +7,26 @@
|
|
|
7
7
|
"agentRuntime": "pi-only",
|
|
8
8
|
"repairWriterProtocol": "explicit-node-v1"
|
|
9
9
|
},
|
|
10
|
-
"objective": "End-to-end backend functional testing pipeline: analyze requirements as Backend Test Analysis v1 JSON → validate analysis contract → generate functional test cases → review cases → generate pytest automation → execute pytest → retrospective
|
|
10
|
+
"objective": "End-to-end backend functional testing pipeline: analyze requirements as Backend Test Analysis v1 JSON → validate analysis contract → environment scout + execution contract → generate functional test cases → emit+validate Case Manifest v1 → review cases → generate pytest automation → traceability gate → preflight + execute pytest → parse Result v1 → classify failures → retrospective → outcome gate. Covers the full chain from requirement analysis to test maturity assessment with always-run retrospect on assertion failures and deterministic AC→case→symbol traceability.",
|
|
11
11
|
"successCriteria": [
|
|
12
12
|
"analyze-inputs-pi returns pure Backend Test Analysis v1 JSON (schema docs/templates/backend-test-analysis.schema.json) with no Markdown prose",
|
|
13
13
|
"backend-test-analysis-contract-shell validates schemaId backend-test-analysis-v1 and materializes run-owned contracts/backend-test-analysis.json",
|
|
14
|
-
"
|
|
14
|
+
"backend-test-environment-scout-pi returns pure Backend Test Execution Contract v1 JSON (schema docs/templates/backend-test-execution.schema.json)",
|
|
15
|
+
"backend-test-execution-contract-shell validates schemaId backend-test-execution-v1 and materializes run-owned contracts/backend-test-execution.json",
|
|
16
|
+
"generate-backend-functional-cases-pi consumes validated contracts and produces structured test cases with BE-<MODULE>-<NNN> IDs under testcase/md/",
|
|
17
|
+
"emit-backend-case-manifest-pi returns pure Backend Test Case Manifest v1 JSON (schema docs/templates/backend-test-case-manifest.schema.json) with no Markdown prose",
|
|
18
|
+
"backend-test-case-manifest-shell validates schemaId backend-test-case-manifest-v1 and materializes run-owned contracts/backend-test-case-manifest.json with deterministic AC coverage",
|
|
19
|
+
"backend-test-traceability-gate-shell verifies generated file/symbol existence after pytest generation and before execute",
|
|
20
|
+
"test-retrospect-pi uses Case Manifest coverageSummary + Result v1 only for coverage/pass rate inputs (model must not invent percentages)",
|
|
15
21
|
"review-backend-cases-pi returns VERDICT: pass or request-revision with coverage assessment",
|
|
16
22
|
"review-backend-cases-gate-shell blocks pytest generation unless the review verdict is VERDICT: pass",
|
|
17
|
-
"generate-backend-pytest-pi converts reviewed cases into pytest code
|
|
18
|
-
"execute-backend-pytest-shell runs pytest with
|
|
23
|
+
"generate-backend-pytest-pi converts reviewed cases into pytest code using verified analysis + execution contracts under testcase/",
|
|
24
|
+
"execute-backend-pytest-shell runs deterministic preflight against the execution contract, then pytest with frozen Adapter testRoot (default testcase/), writing JUnit XML under the current $HARNESS_DAG_RUN_DIR/reports/** only",
|
|
25
|
+
"execute-backend-pytest-shell maps pytest exit 0/1 to node success only when non-empty JUnit exists; raw pytestExitCode is side-channeled under reports/",
|
|
26
|
+
"parse-backend-test-result-shell materializes run-owned contracts/backend-test-result.json (Backend Test Result v1) from JUnit + pytestExitCode",
|
|
27
|
+
"classify-backend-test-result-pi returns structured failure classification JSON (ProductBug|TestBug|EnvFailure|ContractMismatch|FlakyTest|Unknown) without writing files",
|
|
28
|
+
"test-retrospect-pi runs after parse+classify on both pass and assertion-fail paths; stats come from Result v1 only",
|
|
29
|
+
"backend-test-outcome-gate-shell exits non-zero unless result.outcome=passed (shell facts only; retrospective cannot override)",
|
|
19
30
|
"test-retrospect-pi generates retrospective report with A/B/C/D maturity rating under docs/test-reports/",
|
|
20
31
|
"Full traceability from acceptance criteria → functional test case ID → pytest function name"
|
|
21
32
|
],
|
|
@@ -36,7 +47,10 @@
|
|
|
36
47
|
"execute-backend-pytest-shell must not modify test assertions or production code to make tests pass; test failures indicate potential implementation issues and must be reported honestly.",
|
|
37
48
|
"Prompt templates must not ask main session to write artifacts; node output is the artifact and runner archives it under .harness/dag-runs/.",
|
|
38
49
|
"Actual file operation paths must be macOS/Windows compatible; use / only for stable repo refs, JSON/Markdown evidence refs, and glob conventions.",
|
|
39
|
-
"Same-rank exclusive writeSet entries must be disjoint."
|
|
50
|
+
"Same-rank exclusive writeSet entries must be disjoint.",
|
|
51
|
+
"parse-backend-test-result-shell materializes Backend Test Result v1 from JUnit + pytestExitCode; classify/retrospect run on pass and assertion-fail; backend-test-outcome-gate-shell uses result.outcome only.",
|
|
52
|
+
"backend-test-case-manifest-shell validates schemaId backend-test-case-manifest-v1 and materializes contracts/backend-test-case-manifest.json; AC coverage is fail-closed and deterministic.",
|
|
53
|
+
"backend-test-traceability-gate-shell verifies generated file/symbol existence after pytest generation and before execute; models must not invent coverage percentages."
|
|
40
54
|
],
|
|
41
55
|
"defaults": {
|
|
42
56
|
"executor": "pi",
|
|
@@ -136,15 +150,76 @@
|
|
|
136
150
|
}
|
|
137
151
|
},
|
|
138
152
|
{
|
|
139
|
-
"id": "
|
|
153
|
+
"id": "backend-test-environment-scout-pi",
|
|
140
154
|
"depends_on": [
|
|
141
155
|
"backend-test-analysis-contract-shell"
|
|
142
156
|
],
|
|
143
157
|
"complexity": "MED",
|
|
144
158
|
"executor": "pi",
|
|
159
|
+
"role": "scout",
|
|
160
|
+
"writePolicy": "read-only",
|
|
161
|
+
"allowedPaths": [
|
|
162
|
+
"REPLACE/WITH/SOURCE/PATH/**"
|
|
163
|
+
],
|
|
164
|
+
"forbiddenPaths": [
|
|
165
|
+
".harness/**",
|
|
166
|
+
"artifacts/**"
|
|
167
|
+
],
|
|
168
|
+
"outputContract": "Pure Backend Test Execution Contract v1 JSON object matching docs/templates/backend-test-execution.schema.json. No Markdown prose and no file writes.",
|
|
169
|
+
"retryPolicy": {
|
|
170
|
+
"maxAttempts": 3,
|
|
171
|
+
"backoff": "exponential",
|
|
172
|
+
"initialDelayMs": 2000,
|
|
173
|
+
"maxDelayMs": 30000,
|
|
174
|
+
"retryCategories": [
|
|
175
|
+
"timeout",
|
|
176
|
+
"network",
|
|
177
|
+
"rate-limit",
|
|
178
|
+
"unavailable"
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
"subtask_prompt": "Read-only environment scout for backend-test pytest MVP.\n\nReturn exactly one JSON object matching Backend Test Execution Contract v1 (schema docs/templates/backend-test-execution.schema.json).\n\nPrefer pure JSON; a single fenced json block is tolerated; no trailing prose.\n\nDiscover only non-secret evidence: pytest config files (pytest.ini / pyproject.toml / setup.cfg test paths), candidate test roots, existing fixtures/clients, documented run commands, and env *names* (not values).\n\nDo NOT search the whole repo for secrets, .env values, tokens, private keys, or production credentials.\n\nframework must be \"pytest\". Default targetMode to \"in-process\" unless evidence clearly shows an external service base URL env name or documented managed start/stop with sourceRef.\n\nDo NOT select targetMode \"managed-command\" unless task source documents a safe start/stop command with an explicit sourceRef; otherwise leave managedCommand absent and record the gap in evidenceGaps.\n\ntestRoot and workingDirectory must be repo-relative posix paths without .. or absolute form. Adapter default testRoot is testcase when evidence is incomplete.\n\nrunner must not include secret values. report.format must be junit with a relativeHint under the run (e.g. reports/backend-test-junit.xml).\n\nrequiredEnvNames lists env NAMES only. baseUrlEnvName is required only for external-running-service and must match ^[A-Z_][A-Z0-9_]*$.\n\nRecord incomplete discovery in evidenceGaps. Populate evidenceRefs with repo-relative paths actually read.\n\nRequired top-level keys: schemaVersion, framework, runner, testRoot, workingDirectory, report, targetMode, existingFixtures, authenticationMode, requiredEnvNames, dataIsolation, evidenceGaps, evidenceRefs.\n\nRead-only: do not modify code, docs, artifacts, or repository files."
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"id": "backend-test-execution-contract-shell",
|
|
185
|
+
"depends_on": [
|
|
186
|
+
"backend-test-environment-scout-pi"
|
|
187
|
+
],
|
|
188
|
+
"complexity": "LOW",
|
|
189
|
+
"executor": "shell",
|
|
190
|
+
"role": "verifier",
|
|
191
|
+
"writePolicy": "read-only",
|
|
192
|
+
"allowedPaths": [
|
|
193
|
+
"REPLACE/WITH/SOURCE/PATH/**"
|
|
194
|
+
],
|
|
195
|
+
"forbiddenPaths": [
|
|
196
|
+
".harness/**",
|
|
197
|
+
"artifacts/**"
|
|
198
|
+
],
|
|
199
|
+
"outputContract": "Validated run-owned Backend Test Execution Contract v1 artifact pointer, schema ID, and SHA-256.",
|
|
200
|
+
"subtask_prompt": "Materialize and validate the backend-test execution contract under the current DAG run.",
|
|
201
|
+
"shell": {
|
|
202
|
+
"commands": [],
|
|
203
|
+
"jsonArtifactGate": {
|
|
204
|
+
"fromNodeId": "backend-test-environment-scout-pi",
|
|
205
|
+
"schemaId": "backend-test-execution-v1",
|
|
206
|
+
"artifactName": "backend-test-execution.json",
|
|
207
|
+
"outputDir": "contracts"
|
|
208
|
+
},
|
|
209
|
+
"cwd": ".",
|
|
210
|
+
"timeoutMs": 60000
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"id": "generate-backend-functional-cases-pi",
|
|
215
|
+
"depends_on": [
|
|
216
|
+
"backend-test-execution-contract-shell"
|
|
217
|
+
],
|
|
218
|
+
"complexity": "MED",
|
|
219
|
+
"executor": "pi",
|
|
145
220
|
"role": "implementer",
|
|
146
|
-
"toolProfile": "write",
|
|
147
221
|
"writePolicy": "exclusive",
|
|
222
|
+
"toolProfile": "write",
|
|
148
223
|
"writeSet": [
|
|
149
224
|
"testcase/md/**"
|
|
150
225
|
],
|
|
@@ -155,15 +230,76 @@
|
|
|
155
230
|
".harness/**",
|
|
156
231
|
"artifacts/**"
|
|
157
232
|
],
|
|
158
|
-
"
|
|
159
|
-
"subtask_prompt": "Read the validated structured artifact pointer from backend-test-analysis-contract-shell and generate cases only from that JSON contract.\n\n## Output Steps (do in order):\n1. First, output a brief summary: how many modules, how many cases planned per module\n2. Then write each test case file under testcase/md/\n\n## Format Rules:\n- Each test case ID: BE-<MODULE>-<NNN> (e.g. BE-ORDER-001)\n- Each file covers one module\n- Case structure: ID, Title, Precondition, Steps, Expected Result\n- Map each case to acceptance criteria (AC-xxx)\n\n## Coverage Requirements:\n- Positive paths: happy path for each acceptance criterion\n- Negative paths: error scenarios (invalid input, not found, state violations)\n\n## Conditional Coverage (include ONLY if mentioned in upstream analysis):\n- Boundary conditions: include ONLY if upstream analyze-inputs-pi mentions value ranges, length limits, numeric bounds, or format constraints\n- State transitions: include ONLY if upstream analyze-inputs-pi mentions state machine\n- Authentication scenarios: include ONLY if upstream analyze-inputs-pi mentions auth mechanism\n- Timeout scenarios: include ONLY if upstream analyze-inputs-pi mentions timeout handling\n- Concurrency scenarios: include ONLY if upstream analyze-inputs-pi mentions concurrency/idempotency rules\n- If not mentioned, do NOT generate these test cases\n\n## Constraints:\n- Stay within writeSet: testcase/md/**\n- Do NOT re-read source documents or fall back to free-form analysis — use the validated structured artifact only\n- Do not write root artifacts/**"
|
|
233
|
+
"subtask_prompt": "Read the validated structured artifact pointer from backend-test-analysis-contract-shell and generate cases only from that JSON contract.\n\n\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)\n\n- Each file covers one module\n\n- Case structure: ID, Title, Precondition, Steps, Expected Result\n\n- Map each case to acceptance criteria (AC-xxx)\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 validated structured artifact only\n\n\n\n- Do not write root artifacts/**"
|
|
160
234
|
},
|
|
161
235
|
{
|
|
162
|
-
"id": "
|
|
236
|
+
"id": "emit-backend-case-manifest-pi",
|
|
163
237
|
"depends_on": [
|
|
164
238
|
"generate-backend-functional-cases-pi",
|
|
165
239
|
"backend-test-analysis-contract-shell"
|
|
166
240
|
],
|
|
241
|
+
"complexity": "MED",
|
|
242
|
+
"executor": "pi",
|
|
243
|
+
"role": "scout",
|
|
244
|
+
"writePolicy": "read-only",
|
|
245
|
+
"allowedPaths": [
|
|
246
|
+
"**"
|
|
247
|
+
],
|
|
248
|
+
"forbiddenPaths": [
|
|
249
|
+
".harness/**",
|
|
250
|
+
"artifacts/**"
|
|
251
|
+
],
|
|
252
|
+
"outputContract": "Pure Backend Test Case Manifest v1 JSON (schema docs/templates/backend-test-case-manifest.schema.json). No file writes; model must not write .harness/**.",
|
|
253
|
+
"retryPolicy": {
|
|
254
|
+
"maxAttempts": 3,
|
|
255
|
+
"backoff": "exponential",
|
|
256
|
+
"initialDelayMs": 2000,
|
|
257
|
+
"maxDelayMs": 30000,
|
|
258
|
+
"retryCategories": [
|
|
259
|
+
"timeout",
|
|
260
|
+
"network",
|
|
261
|
+
"rate-limit",
|
|
262
|
+
"unavailable"
|
|
263
|
+
]
|
|
264
|
+
},
|
|
265
|
+
"subtask_prompt": "Emit Backend Test Case Manifest v1 as pure JSON (or one fenced json block with no trailing text).\n\nRead-only: use validated contracts/backend-test-analysis.json pointer + testcase/md/** only. Do not write repository files or .harness/**.\n\nsourceBinding must match the analysis contract / DAG source binding exactly (taskId, requirementPath, requirementSha256, referencePaths, requirementIds).\n\nFor each functional case under testcase/md/: caseId BE-<MODULE>-<NNN>, acIds[], title, category, automationStatus.\n\nAfter case generation (pre-pytest), default automationStatus=planned. Use skipped/unsupported only with gapReason. Use generated only when file+symbol already exist.\n\nevidenceGaps: structured gaps for explicit AC-* that cannot be mapped to a case.\n\nDo NOT invent coverage percentages. Optional coverageSummary must match deterministic counts (gate recomputes/validates).\n\nNo secrets or credential-shaped fields."
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"id": "backend-test-case-manifest-shell",
|
|
269
|
+
"depends_on": [
|
|
270
|
+
"emit-backend-case-manifest-pi"
|
|
271
|
+
],
|
|
272
|
+
"complexity": "LOW",
|
|
273
|
+
"executor": "shell",
|
|
274
|
+
"role": "verifier",
|
|
275
|
+
"writePolicy": "read-only",
|
|
276
|
+
"allowedPaths": [
|
|
277
|
+
"**"
|
|
278
|
+
],
|
|
279
|
+
"forbiddenPaths": [
|
|
280
|
+
".harness/**",
|
|
281
|
+
"artifacts/**"
|
|
282
|
+
],
|
|
283
|
+
"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.",
|
|
284
|
+
"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.",
|
|
285
|
+
"shell": {
|
|
286
|
+
"commands": [],
|
|
287
|
+
"jsonArtifactGate": {
|
|
288
|
+
"fromNodeId": "emit-backend-case-manifest-pi",
|
|
289
|
+
"schemaId": "backend-test-case-manifest-v1",
|
|
290
|
+
"artifactName": "backend-test-case-manifest.json",
|
|
291
|
+
"outputDir": "contracts"
|
|
292
|
+
},
|
|
293
|
+
"cwd": ".",
|
|
294
|
+
"timeoutMs": 60000
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"id": "review-backend-cases-pi",
|
|
299
|
+
"depends_on": [
|
|
300
|
+
"backend-test-case-manifest-shell",
|
|
301
|
+
"backend-test-analysis-contract-shell"
|
|
302
|
+
],
|
|
167
303
|
"complexity": "HIGH",
|
|
168
304
|
"executor": "pi",
|
|
169
305
|
"role": "reviewer",
|
|
@@ -225,13 +361,14 @@
|
|
|
225
361
|
{
|
|
226
362
|
"id": "generate-backend-pytest-pi",
|
|
227
363
|
"depends_on": [
|
|
228
|
-
"review-backend-cases-gate-shell"
|
|
364
|
+
"review-backend-cases-gate-shell",
|
|
365
|
+
"backend-test-execution-contract-shell"
|
|
229
366
|
],
|
|
230
367
|
"complexity": "HIGH",
|
|
231
368
|
"executor": "pi",
|
|
232
369
|
"role": "implementer",
|
|
233
|
-
"toolProfile": "write",
|
|
234
370
|
"writePolicy": "exclusive",
|
|
371
|
+
"toolProfile": "write",
|
|
235
372
|
"writeSet": [
|
|
236
373
|
"testcase/**/test_*.py",
|
|
237
374
|
"testcase/**/helpers/**",
|
|
@@ -245,13 +382,40 @@
|
|
|
245
382
|
".harness/**",
|
|
246
383
|
"artifacts/**"
|
|
247
384
|
],
|
|
248
|
-
"outputContract": "Pytest test files under testcase/ with 1:1 mapping to functional test case IDs; optional helpers/factories under testcase/**/helpers|factories. Summary lists generated files, test function count, and any skipped cases with reasons.",
|
|
249
385
|
"subtask_prompt_markdown": "./backend-test-dag.generate-pytest.prompt.md"
|
|
250
386
|
},
|
|
387
|
+
{
|
|
388
|
+
"id": "backend-test-traceability-gate-shell",
|
|
389
|
+
"depends_on": [
|
|
390
|
+
"generate-backend-pytest-pi",
|
|
391
|
+
"backend-test-case-manifest-shell"
|
|
392
|
+
],
|
|
393
|
+
"complexity": "LOW",
|
|
394
|
+
"executor": "shell",
|
|
395
|
+
"role": "verifier",
|
|
396
|
+
"writePolicy": "read-only",
|
|
397
|
+
"allowedPaths": [
|
|
398
|
+
"**"
|
|
399
|
+
],
|
|
400
|
+
"forbiddenPaths": [
|
|
401
|
+
".harness/**",
|
|
402
|
+
"artifacts/**"
|
|
403
|
+
],
|
|
404
|
+
"outputContract": "Deterministic traceability: generated cases have real file/symbol; skipped/unsupported have gapReason; convention symbols scanned under testcase/**/test_*.py.",
|
|
405
|
+
"subtask_prompt": "Fail closed when generated automation claims do not resolve to workspace pytest symbols, or skip/unsupported lacks gapReason.",
|
|
406
|
+
"shell": {
|
|
407
|
+
"commands": [
|
|
408
|
+
"backend-test-traceability-gate"
|
|
409
|
+
],
|
|
410
|
+
"cwd": ".",
|
|
411
|
+
"timeoutMs": 60000
|
|
412
|
+
}
|
|
413
|
+
},
|
|
251
414
|
{
|
|
252
415
|
"id": "execute-backend-pytest-shell",
|
|
253
416
|
"depends_on": [
|
|
254
|
-
"
|
|
417
|
+
"backend-test-traceability-gate-shell",
|
|
418
|
+
"backend-test-execution-contract-shell"
|
|
255
419
|
],
|
|
256
420
|
"complexity": "LOW",
|
|
257
421
|
"executor": "shell",
|
|
@@ -264,11 +428,11 @@
|
|
|
264
428
|
".harness/**",
|
|
265
429
|
"artifacts/**"
|
|
266
430
|
],
|
|
267
|
-
"outputContract": "Archived pytest stdout/stderr
|
|
268
|
-
"subtask_prompt": "Run pytest for the backend test suite; write JUnit evidence only under the current HARNESS_DAG_RUN_DIR/reports/.",
|
|
431
|
+
"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.",
|
|
432
|
+
"subtask_prompt": "Run pytest for the backend test suite; write JUnit + pytestExitCode evidence only under the current HARNESS_DAG_RUN_DIR/reports/.",
|
|
269
433
|
"shell": {
|
|
270
434
|
"commands": [
|
|
271
|
-
"test -n \"${HARNESS_DAG_RUN_DIR:-}\" || { echo \"missing HARNESS_DAG_RUN_DIR for backend pytest
|
|
435
|
+
"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(Array.isArray(contract.evidenceGaps)&&contract.evidenceGaps.length) errors.push(\"evidenceGaps present: \"+contract.evidenceGaps.length);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-junit.xml\"; EXIT_FILE=\"${HARNESS_DAG_RUN_DIR}/reports/backend-test-pytest-exit.txt\"; mkdir -p \"$(dirname \"${REPORT}\")\"; 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}\""
|
|
272
436
|
],
|
|
273
437
|
"verifyEvidence": {
|
|
274
438
|
"phase": "final",
|
|
@@ -276,7 +440,7 @@
|
|
|
276
440
|
"commandSource": "inline",
|
|
277
441
|
"commandCount": 1,
|
|
278
442
|
"commandLabels": [
|
|
279
|
-
"backend pytest execution"
|
|
443
|
+
"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(Array.isArray(contract.evidenceGaps)&&contract.evidenceGaps.length) errors.push(\"evidenceGaps present: \"+contract.evidenceGaps.length);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-junit.xml\"; EXIT_FILE=\"${HARNESS_DAG_RUN_DIR}/reports/backend-test-pytest-exit.txt\"; mkdir -p \"$(dirname \"${REPORT}\")\"; 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}\""
|
|
280
444
|
],
|
|
281
445
|
"finalFullRequired": true
|
|
282
446
|
},
|
|
@@ -285,15 +449,64 @@
|
|
|
285
449
|
}
|
|
286
450
|
},
|
|
287
451
|
{
|
|
288
|
-
"id": "test-
|
|
452
|
+
"id": "parse-backend-test-result-shell",
|
|
289
453
|
"depends_on": [
|
|
290
454
|
"execute-backend-pytest-shell"
|
|
291
455
|
],
|
|
456
|
+
"complexity": "LOW",
|
|
457
|
+
"executor": "shell",
|
|
458
|
+
"role": "verifier",
|
|
459
|
+
"writePolicy": "read-only",
|
|
460
|
+
"allowedPaths": [
|
|
461
|
+
"**"
|
|
462
|
+
],
|
|
463
|
+
"forbiddenPaths": [
|
|
464
|
+
".harness/**",
|
|
465
|
+
"artifacts/**"
|
|
466
|
+
],
|
|
467
|
+
"outputContract": "Validated run-owned Backend Test Result v1 at contracts/backend-test-result.json (schemaId backend-test-result-v1) with outcome/counts/failures from deterministic JUnit parse.",
|
|
468
|
+
"subtask_prompt": "Materialize Backend Test Result v1 from JUnit + pytestExitCode under the current DAG run (fail-closed on missing/corrupt report).",
|
|
469
|
+
"shell": {
|
|
470
|
+
"commands": [],
|
|
471
|
+
"jsonArtifactGate": {
|
|
472
|
+
"fromNodeId": "execute-backend-pytest-shell",
|
|
473
|
+
"schemaId": "backend-test-result-v1",
|
|
474
|
+
"artifactName": "backend-test-result.json",
|
|
475
|
+
"outputDir": "contracts"
|
|
476
|
+
},
|
|
477
|
+
"cwd": ".",
|
|
478
|
+
"timeoutMs": 60000
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
"id": "classify-backend-test-result-pi",
|
|
483
|
+
"depends_on": [
|
|
484
|
+
"parse-backend-test-result-shell"
|
|
485
|
+
],
|
|
486
|
+
"complexity": "MED",
|
|
487
|
+
"executor": "pi",
|
|
488
|
+
"role": "reviewer",
|
|
489
|
+
"writePolicy": "read-only",
|
|
490
|
+
"allowedPaths": [
|
|
491
|
+
"**"
|
|
492
|
+
],
|
|
493
|
+
"forbiddenPaths": [
|
|
494
|
+
".harness/**",
|
|
495
|
+
"artifacts/**"
|
|
496
|
+
],
|
|
497
|
+
"outputContract": "Pure JSON classification: category in {ProductBug,TestBug,EnvFailure,ContractMismatch,FlakyTest,Unknown}, evidence[], confidence (capped), notes. No file writes.",
|
|
498
|
+
"subtask_prompt_markdown": "./backend-test-dag.classify.prompt.md"
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
"id": "test-retrospect-pi",
|
|
502
|
+
"depends_on": [
|
|
503
|
+
"classify-backend-test-result-pi"
|
|
504
|
+
],
|
|
292
505
|
"complexity": "MED",
|
|
293
506
|
"executor": "pi",
|
|
294
507
|
"role": "closeout",
|
|
295
|
-
"toolProfile": "write",
|
|
296
508
|
"writePolicy": "exclusive",
|
|
509
|
+
"toolProfile": "write",
|
|
297
510
|
"writeSet": [
|
|
298
511
|
"docs/test-reports/**"
|
|
299
512
|
],
|
|
@@ -304,8 +517,43 @@
|
|
|
304
517
|
".harness/**",
|
|
305
518
|
"artifacts/**"
|
|
306
519
|
],
|
|
307
|
-
"outputContract": "Markdown retrospective report under docs/test-reports/ with coverage summary, review findings, pytest results, and maturity rating (A/B/C/D).",
|
|
308
520
|
"subtask_prompt_markdown": "./backend-test-dag.retrospect.prompt.md"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
"id": "backend-test-outcome-gate-shell",
|
|
524
|
+
"depends_on": [
|
|
525
|
+
"test-retrospect-pi"
|
|
526
|
+
],
|
|
527
|
+
"complexity": "LOW",
|
|
528
|
+
"executor": "shell",
|
|
529
|
+
"role": "verifier",
|
|
530
|
+
"writePolicy": "read-only",
|
|
531
|
+
"allowedPaths": [
|
|
532
|
+
"**"
|
|
533
|
+
],
|
|
534
|
+
"forbiddenPaths": [
|
|
535
|
+
".harness/**",
|
|
536
|
+
"artifacts/**"
|
|
537
|
+
],
|
|
538
|
+
"outputContract": "Shell exit 0 only when Result v1 outcome=passed with failed=0 and error=0; non-zero otherwise. Ignores retrospective Markdown.",
|
|
539
|
+
"subtask_prompt": "Gate the backend-test DAG on run-owned Result v1 shell facts only (not retrospective prose).",
|
|
540
|
+
"shell": {
|
|
541
|
+
"commands": [
|
|
542
|
+
"test -n \"${HARNESS_DAG_RUN_DIR:-}\" || { echo \"missing HARNESS_DAG_RUN_DIR for backend-test outcome gate\" >&2; exit 2; }; RESULT=\"${HARNESS_DAG_RUN_DIR}/contracts/backend-test-result.json\"; test -f \"${RESULT}\" || { echo \"missing backend-test result: ${RESULT}\" >&2; exit 2; }; node -e 'const fs=require(\"fs\");const r=JSON.parse(fs.readFileSync(process.argv[1],\"utf8\"));const outcome=String(r.outcome||\"\");const ok=outcome===\"passed\"&&Number(r.failed||0)===0&&Number(r.error||0)===0;console.log(\"backend-test outcome=\"+outcome+\" passed=\"+r.passed+\" failed=\"+r.failed+\" error=\"+r.error+\" executionStatus=\"+r.executionStatus);if(!ok){process.exit(1);}' \"${RESULT}\""
|
|
543
|
+
],
|
|
544
|
+
"verifyEvidence": {
|
|
545
|
+
"phase": "final",
|
|
546
|
+
"quota": "full",
|
|
547
|
+
"commandSource": "inline",
|
|
548
|
+
"commandCount": 1,
|
|
549
|
+
"commandLabels": [
|
|
550
|
+
"test -n \"${HARNESS_DAG_RUN_DIR:-}\" || { echo \"missing HARNESS_DAG_RUN_DIR for backend-test outcome gate\" >&2; exit 2; }; RESULT=\"${HARNESS_DAG_RUN_DIR}/contracts/backend-test-result.json\"; test -f \"${RESULT}\" || { echo \"missing backend-test result: ${RESULT}\" >&2; exit 2; }; node -e 'const fs=require(\"fs\");const r=JSON.parse(fs.readFileSync(process.argv[1],\"utf8\"));const outcome=String(r.outcome||\"\");const ok=outcome===\"passed\"&&Number(r.failed||0)===0&&Number(r.error||0)===0;console.log(\"backend-test outcome=\"+outcome+\" passed=\"+r.passed+\" failed=\"+r.failed+\" error=\"+r.error+\" executionStatus=\"+r.executionStatus);if(!ok){process.exit(1);}' \"${RESULT}\""
|
|
551
|
+
],
|
|
552
|
+
"finalFullRequired": true
|
|
553
|
+
},
|
|
554
|
+
"cwd": ".",
|
|
555
|
+
"timeoutMs": 60000
|
|
556
|
+
}
|
|
309
557
|
}
|
|
310
558
|
]
|
|
311
559
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
|
-
Use this prompt for a **test retrospective** node: `executor: "pi"`, `role: "closeout"`, `toolProfile: "write"`, `writePolicy: "exclusive"`. The closeout agent reads
|
|
5
|
+
Use this prompt for a **test retrospective** node: `executor: "pi"`, `role: "closeout"`, `toolProfile: "write"`, `writePolicy: "exclusive"`. The closeout agent reads **Backend Test Result v1** (and classification), then generates a retrospective report with an objective maturity rating.
|
|
6
6
|
|
|
7
7
|
Do **not** create a new executor type. This is a standard `executor: pi` writer node.
|
|
8
8
|
|
|
@@ -11,7 +11,7 @@ Do **not** create a new executor type. This is a standard `executor: pi` writer
|
|
|
11
11
|
```json
|
|
12
12
|
{
|
|
13
13
|
"id": "test-retrospect-pi",
|
|
14
|
-
"depends_on": ["
|
|
14
|
+
"depends_on": ["classify-backend-test-result-pi"],
|
|
15
15
|
"complexity": "MED",
|
|
16
16
|
"executor": "pi",
|
|
17
17
|
"role": "closeout",
|
|
@@ -20,7 +20,7 @@ Do **not** create a new executor type. This is a standard `executor: pi` writer
|
|
|
20
20
|
"writeSet": ["docs/test-reports/**"],
|
|
21
21
|
"allowedPaths": ["docs/test-reports/**"],
|
|
22
22
|
"forbiddenPaths": [".harness/**", "artifacts/**"],
|
|
23
|
-
"outputContract": "Markdown retrospective report under docs/test-reports/ with coverage summary, review findings,
|
|
23
|
+
"outputContract": "Markdown retrospective report under docs/test-reports/ with coverage summary, review findings, Result v1 stats, classification, and maturity rating (A/B/C/D).",
|
|
24
24
|
"subtask_prompt_markdown": "./backend-test-dag.retrospect.prompt.md"
|
|
25
25
|
}
|
|
26
26
|
```
|
|
@@ -29,7 +29,9 @@ Do **not** create a new executor type. This is a standard `executor: pi` writer
|
|
|
29
29
|
|
|
30
30
|
You are the Backend Test DAG **test retrospective** agent.
|
|
31
31
|
|
|
32
|
-
Your job is to read upstream
|
|
32
|
+
Your job is to read upstream Result v1 + classification (+ review report) and generate a retrospective report with a maturity rating. Write the report under `docs/test-reports/` only. Stay within `writeSet`. Do not write root `artifacts/**`.
|
|
33
|
+
|
|
34
|
+
This node runs on **both pass and assertion-fail** paths (after parse + classify). Final task success is decided later by `backend-test-outcome-gate-shell` using Result v1 shell facts only — **never** rewrite a failed result as passed in this report.
|
|
33
35
|
|
|
34
36
|
### Output Steps (do in order)
|
|
35
37
|
|
|
@@ -38,28 +40,40 @@ Your job is to read upstream outputs (review report + pytest results) and genera
|
|
|
38
40
|
|
|
39
41
|
### Inputs
|
|
40
42
|
|
|
41
|
-
1. **
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
1. **Result v1 (authoritative stats)** — `$HARNESS_DAG_RUN_DIR/contracts/backend-test-result.json`
|
|
44
|
+
Use `passed` / `failed` / `error` / `skipped` / `outcome` / `failures[]` / `pytestExitCode` only from this artifact.
|
|
45
|
+
2. **Case Manifest v1 (authoritative AC coverage)** — `$HARNESS_DAG_RUN_DIR/contracts/backend-test-case-manifest.json`
|
|
46
|
+
Use `coverageSummary.acCoverageRatio`, `coveredAcCount`, `explicitAcCount`, case counts only from this artifact.
|
|
47
|
+
3. **Classification** — `classify-backend-test-result-pi` JSON (`category`, `confidence`, `evidence`). Interpretive only; does not override outcome.
|
|
48
|
+
4. **Review report** — `review-backend-cases-pi` output (VERDICT, findings, coverage assessment).
|
|
49
|
+
5. Optional secondary: execute stdout markers / JUnit path (do not re-parse logs for counts when Result v1 exists).
|
|
44
50
|
|
|
45
51
|
Do NOT re-read source documents. Use upstream outputs only.
|
|
46
52
|
|
|
53
|
+
### Stats authority
|
|
54
|
+
|
|
55
|
+
- Pass rate = `passed / (passed + failed + error)` when denominator > 0 (skipped excluded from denominator unless Result documents otherwise) — **Result v1 only**.
|
|
56
|
+
- AC coverage = `coverageSummary.acCoverageRatio` from Case Manifest v1 only (do **not** recompute or invent percentages).
|
|
57
|
+
- Failed case table rows must match `failures[]` from Result v1.
|
|
58
|
+
- If Result v1 `outcome` is not `passed`, the retrospective **must not** claim overall success.
|
|
59
|
+
|
|
47
60
|
### Maturity Rating Criteria
|
|
48
61
|
|
|
49
|
-
| Rating | Coverage | Pass Rate | Review Findings |
|
|
50
|
-
|
|
51
|
-
| **A** |
|
|
52
|
-
| **B** | ≥
|
|
53
|
-
| **C** | ≥
|
|
62
|
+
| Rating | Coverage (manifest) | Pass Rate (Result v1) | Review Findings |
|
|
63
|
+
|--------|---------------------|------------------------|-----------------|
|
|
64
|
+
| **A** | `acCoverageRatio` = 1 | 100% pytest pass | No Critical or Important findings |
|
|
65
|
+
| **B** | `acCoverageRatio` ≥ 0.8 | ≥90% pytest pass | Only Informational findings |
|
|
66
|
+
| **C** | `acCoverageRatio` ≥ 0.6 | ≥70% pytest pass | No Critical findings (Important allowed) |
|
|
54
67
|
| **D** | Below C thresholds | Below C thresholds | Or any Critical finding unresolved |
|
|
55
68
|
|
|
56
69
|
#### Rating Rules
|
|
57
70
|
|
|
58
|
-
- **Coverage**
|
|
59
|
-
- **Pass rate**
|
|
71
|
+
- **Coverage** from Case Manifest `coverageSummary` only (deterministic gate product).
|
|
72
|
+
- **Pass rate** from Result v1 only (not guessed from logs).
|
|
60
73
|
- If `review-backend-cases-pi` returned `VERDICT: request-revision` and revision was not completed, cap at **D**.
|
|
61
|
-
- If
|
|
62
|
-
- Skipped tests
|
|
74
|
+
- If Result v1 shows >30% failed+error among executed tests, cap at **D** regardless of coverage.
|
|
75
|
+
- Skipped tests count as "not covered" for pass rate but not as failures.
|
|
76
|
+
- Collection/command/report errors → cap at **D** and record classification (not ProductBug by default).
|
|
63
77
|
|
|
64
78
|
### Report Structure
|
|
65
79
|
|
|
@@ -71,6 +85,8 @@ Write the report as a Markdown file named `backend-test-retrospect-<date>.md` un
|
|
|
71
85
|
**Date:** <YYYY-MM-DD>
|
|
72
86
|
**Task:** <task-id>
|
|
73
87
|
**Maturity Rating:** <A|B|C|D>
|
|
88
|
+
**Result outcome:** <from Result v1>
|
|
89
|
+
**Classification:** <from classify JSON>
|
|
74
90
|
|
|
75
91
|
## 1. Test Coverage Summary
|
|
76
92
|
|
|
@@ -79,43 +95,41 @@ Write the report as a Markdown file named `backend-test-retrospect-<date>.md` un
|
|
|
79
95
|
| Total acceptance criteria | N |
|
|
80
96
|
| Covered by test cases | N (X%) |
|
|
81
97
|
| Total functional test cases | N |
|
|
82
|
-
| Positive path cases | N |
|
|
83
|
-
| Negative path cases | N |
|
|
84
|
-
| Boundary cases | N |
|
|
85
98
|
|
|
86
|
-
## 2. Automation Results
|
|
99
|
+
## 2. Automation Results (from Result v1)
|
|
87
100
|
|
|
88
101
|
| Metric | Value |
|
|
89
102
|
|--------|-------|
|
|
90
|
-
| Total
|
|
103
|
+
| Total tests | N |
|
|
91
104
|
| Passed | N |
|
|
92
105
|
| Failed | N |
|
|
106
|
+
| Error | N |
|
|
93
107
|
| Skipped | N |
|
|
94
108
|
| Pass rate | X% |
|
|
95
109
|
| Pytest exit code | N |
|
|
110
|
+
| Outcome | … |
|
|
111
|
+
| Execution status | … |
|
|
96
112
|
|
|
97
113
|
### Failed Test Analysis
|
|
98
114
|
|
|
99
|
-
| Test Case
|
|
100
|
-
|
|
101
|
-
| ... | ... | ... |
|
|
115
|
+
| Test Case / Function | Message (truncated) | Classification |
|
|
116
|
+
|----------------------|-------------------|----------------|
|
|
117
|
+
| ... | ... | ... |
|
|
102
118
|
|
|
103
119
|
## 3. Review Findings
|
|
104
120
|
|
|
105
121
|
| Severity | Finding | Status |
|
|
106
122
|
|----------|---------|--------|
|
|
107
|
-
|
|
|
108
|
-
| Important | ... | Resolved / Unresolved |
|
|
109
|
-
| Informational | ... | Resolved / Unresolved |
|
|
123
|
+
| … | … | … |
|
|
110
124
|
|
|
111
125
|
## 4. Maturity Rating Rationale
|
|
112
126
|
|
|
113
|
-
Explain which threshold was met or missed
|
|
127
|
+
Explain which threshold was met or missed.
|
|
114
128
|
|
|
115
129
|
## 5. Recommendations
|
|
116
130
|
|
|
117
|
-
- Actionable items for
|
|
118
|
-
-
|
|
131
|
+
- Actionable items for the next iteration.
|
|
132
|
+
- Do not propose changing production code solely to greenwash tests.
|
|
119
133
|
```
|
|
120
134
|
|
|
121
135
|
### Output Shape (after rating line)
|
|
@@ -11,7 +11,7 @@ Do **not** create `executor: reviewer`. Reviewer is a **role** on `executor: pi`
|
|
|
11
11
|
```json
|
|
12
12
|
{
|
|
13
13
|
"id": "review-backend-cases-pi",
|
|
14
|
-
"depends_on": ["
|
|
14
|
+
"depends_on": ["backend-test-case-manifest-shell", "backend-test-analysis-contract-shell"],
|
|
15
15
|
"complexity": "HIGH",
|
|
16
16
|
"executor": "pi",
|
|
17
17
|
"role": "reviewer",
|
|
@@ -41,9 +41,10 @@ No preamble, heading, or blank lines before the verdict line.
|
|
|
41
41
|
### Inputs to Review
|
|
42
42
|
|
|
43
43
|
1. **Acceptance criteria / analysis** — from the validated Backend Test Analysis v1 artifact materialized by `backend-test-analysis-contract-shell` (`contracts/backend-test-analysis.json` under the current DAG run). Do not treat free-form Markdown from `analyze-inputs-pi` as the contract.
|
|
44
|
-
2. **
|
|
44
|
+
2. **Case Manifest v1** — `contracts/backend-test-case-manifest.json` (schemaId `backend-test-case-manifest-v1`). Prefer `coverageSummary` and caseId↔acIds from this artifact; do not invent coverage percentages.
|
|
45
|
+
3. **Generated test cases** — files under `testcase/md/`.
|
|
45
46
|
|
|
46
|
-
Do NOT re-read source documents. Use the validated analysis artifact and generated cases only.
|
|
47
|
+
Do NOT re-read source documents. Use the validated analysis artifact, case manifest, and generated cases only.
|
|
47
48
|
|
|
48
49
|
### Review Checklist
|
|
49
50
|
|
|
@@ -54,7 +55,8 @@ Do NOT re-read source documents. Use the validated analysis artifact and generat
|
|
|
54
55
|
| **Negative path coverage** | Error/exception scenarios (invalid input, not found, state violations) | Important |
|
|
55
56
|
| **Boundary conditions** | Edge cases (empty input, max length, edge values) | Important |
|
|
56
57
|
| **State transitions** | Illegal state changes covered | Important |
|
|
57
|
-
| **Requirement traceability** | Each acceptance criterion (AC-xxx) maps to at least one test case ID | Critical |
|
|
58
|
+
| **Requirement traceability** | Each acceptance criterion (AC-xxx) maps to at least one test case ID (manifest coverageSummary or evidenceGaps) | Critical |
|
|
59
|
+
| **Manifest consistency** | Markdown cases align with Case Manifest v1 caseId/acIds | Critical |
|
|
58
60
|
| **Case structure** | Each case has: ID, Title, Precondition, Steps, Expected Result | Important |
|
|
59
61
|
| **No duplicate IDs** | All test case IDs are unique across files | Critical |
|
|
60
62
|
|