@tea-agent/loop-agent 0.28.12 → 0.29.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 +1 -1
- package/CHANGELOG.md +61 -15
- package/dist/commands/client-recovery.js +56 -1
- package/dist/commands/init-upgrade.js +186 -21
- package/dist/executors/dag-pi-executor.js +49 -2
- package/dist/executors/shell-executor.js +135 -0
- package/dist/worker/console/app-data.js +132 -11
- package/dist/worker/console/chat/pi-runtime.js +24 -42
- package/dist/worker/console/chat/resource-loader.js +11 -20
- package/dist/worker/console/chat/routes.js +7 -8
- package/dist/worker/console/chat/runtime-context.js +1 -1
- package/dist/worker/console/chat/tools.js +67 -54
- package/dist/worker/console/operation-runner.js +15 -1
- package/dist/worker/console/operation-store.js +70 -49
- package/dist/worker/console/operator-actions.js +57 -1
- package/dist/worker/console/static/assets/index-Cwx-ZVEQ.js +29 -0
- package/dist/worker/console/static/favicon.svg +37 -0
- package/dist/worker/console/static/index.html +2 -1
- package/dist/workflows/dag/backend-test-scenario-param.js +846 -0
- package/dist/workflows/dag/backend-test-writer-completeness.js +418 -0
- package/dist/workflows/dag/init-hybrid.js +20 -6
- package/dist/workflows/dag/node-execution.js +31 -2
- package/dist/workflows/dag/retry-policy.js +55 -18
- package/dist/workflows/dag/types.js +1 -0
- package/dist/workflows/dag/validate.js +38 -3
- package/docs/operations/README.md +1 -1
- package/docs/templates/README.md +1 -1
- package/docs/templates/agent-dag.schema.json +3 -3
- package/docs/templates/backend-test-dag.json +36 -11
- package/docs/templates/init-managed-agents.md +1 -1
- package/harness.json +2 -2
- package/package.json +2 -1
- package/dist/worker/console/static/assets/index-BfRgtLF4.js +0 -29
|
@@ -2,9 +2,9 @@ import { z } from "zod";
|
|
|
2
2
|
/**
|
|
3
3
|
* Failure categories that are safe to auto-retry for read-only Pi nodes.
|
|
4
4
|
*
|
|
5
|
-
* These are
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* These are failures with no repository write side-effects: model connection
|
|
6
|
+
* interruption, provider rate-limiting, temporary provider unavailability,
|
|
7
|
+
* request timeout, or a settled read-only turn with no assistant text.
|
|
8
8
|
*
|
|
9
9
|
* `quota` is intentionally NOT included: a quota exhaustion is an account
|
|
10
10
|
* billing/plan state, not a transient rate limit, and retrying immediately
|
|
@@ -15,9 +15,14 @@ export const DEFAULT_DAG_RETRY_CATEGORIES = [
|
|
|
15
15
|
"network",
|
|
16
16
|
"rate-limit",
|
|
17
17
|
"unavailable",
|
|
18
|
+
"empty-output",
|
|
18
19
|
];
|
|
19
20
|
export const STRUCTURED_OUTPUT_RETRY_CATEGORY = "output-too-large";
|
|
20
21
|
export const PROTOCOL_INVALID_RETRY_CATEGORY = "protocol-invalid";
|
|
22
|
+
/** Retry only a proven no-op from an explicitly opt-in bounded Pi writer. */
|
|
23
|
+
export const WRITER_EMPTY_DIFF_RETRY_CATEGORY = "writer-empty-diff";
|
|
24
|
+
/** Retry when a backend-test writer finished but Completeness Gate found missing/broken targets. */
|
|
25
|
+
export const INCOMPLETE_WRITE_SET_RETRY_CATEGORY = "incomplete-write-set";
|
|
21
26
|
export const STRUCTURED_REQUIRED_DAG_RETRY_CATEGORIES = [
|
|
22
27
|
...DEFAULT_DAG_RETRY_CATEGORIES,
|
|
23
28
|
STRUCTURED_OUTPUT_RETRY_CATEGORY,
|
|
@@ -31,6 +36,8 @@ export const ALL_DAG_RETRY_CATEGORIES = [
|
|
|
31
36
|
...DEFAULT_DAG_RETRY_CATEGORIES,
|
|
32
37
|
STRUCTURED_OUTPUT_RETRY_CATEGORY,
|
|
33
38
|
PROTOCOL_INVALID_RETRY_CATEGORY,
|
|
39
|
+
WRITER_EMPTY_DIFF_RETRY_CATEGORY,
|
|
40
|
+
INCOMPLETE_WRITE_SET_RETRY_CATEGORY,
|
|
34
41
|
];
|
|
35
42
|
const RETRY_SAFE_PI_ROLES = new Set([
|
|
36
43
|
"planner",
|
|
@@ -43,9 +50,9 @@ const RETRY_SAFE_PI_ROLES = new Set([
|
|
|
43
50
|
export const dagRetryCategorySchema = z.enum(ALL_DAG_RETRY_CATEGORIES);
|
|
44
51
|
export const dagRetryBackoffSchema = z.enum(["exponential"]);
|
|
45
52
|
/**
|
|
46
|
-
* Opt-in retry policy for a DagTask. Generated
|
|
47
|
-
*
|
|
48
|
-
* shell, static, and decision-gate nodes.
|
|
53
|
+
* Opt-in retry policy for a DagTask. Generated for safe read-only Pi nodes,
|
|
54
|
+
* except the single validation-gated writer-empty-diff policy. Validation
|
|
55
|
+
* rejects all other writers, dynamic, shell, static, and decision-gate nodes.
|
|
49
56
|
*/
|
|
50
57
|
export const dagRetryPolicySchema = z
|
|
51
58
|
.object({
|
|
@@ -106,6 +113,32 @@ export const PROTOCOL_AWARE_PI_RETRY_POLICY = {
|
|
|
106
113
|
...DEFAULT_READ_ONLY_PI_RETRY_POLICY,
|
|
107
114
|
retryCategories: [...PROTOCOL_AWARE_DAG_RETRY_CATEGORIES],
|
|
108
115
|
};
|
|
116
|
+
/**
|
|
117
|
+
* The sole writer retry policy. It is intentionally not included in any
|
|
118
|
+
* read-only default: a writer may retry only after its executor proves an
|
|
119
|
+
* otherwise successful attempt changed no files.
|
|
120
|
+
*/
|
|
121
|
+
export const WRITER_EMPTY_DIFF_RETRY_POLICY = {
|
|
122
|
+
maxAttempts: 2,
|
|
123
|
+
backoff: "exponential",
|
|
124
|
+
initialDelayMs: 2000,
|
|
125
|
+
maxDelayMs: 30000,
|
|
126
|
+
retryCategories: [WRITER_EMPTY_DIFF_RETRY_CATEGORY],
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Backend-test generation writers: empty-diff once, plus bounded incomplete-write-set
|
|
130
|
+
* recovery attempts driven by Completeness Gate (missing/broken target files).
|
|
131
|
+
*/
|
|
132
|
+
export const BACKEND_TEST_WRITER_COMPLETENESS_RETRY_POLICY = {
|
|
133
|
+
maxAttempts: 3,
|
|
134
|
+
backoff: "exponential",
|
|
135
|
+
initialDelayMs: 2000,
|
|
136
|
+
maxDelayMs: 30000,
|
|
137
|
+
retryCategories: [
|
|
138
|
+
WRITER_EMPTY_DIFF_RETRY_CATEGORY,
|
|
139
|
+
INCOMPLETE_WRITE_SET_RETRY_CATEGORY,
|
|
140
|
+
],
|
|
141
|
+
};
|
|
109
142
|
/**
|
|
110
143
|
* Deterministic helper: is this raw failure category eligible for retry under
|
|
111
144
|
* the given policy? Pure function; executor never decides retry eligibility.
|
|
@@ -117,19 +150,23 @@ export function isRetryablePiFailureCategory(rawFailureCategory, options = {}) {
|
|
|
117
150
|
return categories.includes(rawFailureCategory);
|
|
118
151
|
}
|
|
119
152
|
/**
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* - executor === "pi"
|
|
124
|
-
* - role is planner/scout/reviewer/verifier/supervisor/closeout (never implementer)
|
|
125
|
-
* - writePolicy is read-only/none/default and toolProfile is not write
|
|
126
|
-
* - NOT dynamic (no dynamicExpansion/Reduction/Condition/LoopUntil)
|
|
127
|
-
* - NOT a decision gate
|
|
128
|
-
*
|
|
129
|
-
* Writers can have non-idempotent side effects and must not auto-retry.
|
|
130
|
-
* Read-only, non-dynamic supervisors are safe because they only classify
|
|
131
|
-
* settled evidence; dynamic nodes still do not retry at the controller level.
|
|
153
|
+
* Static eligibility for the sole retryable writer class. This deliberately
|
|
154
|
+
* does not infer a no-op: the Pi executor assigns writer-empty-diff only after
|
|
155
|
+
* post-write-guard attribution proves an empty changedFiles list.
|
|
132
156
|
*/
|
|
157
|
+
export function isWriterEmptyDiffRetryCandidate(task) {
|
|
158
|
+
return (task.executor === "pi" &&
|
|
159
|
+
task.role === "implementer" &&
|
|
160
|
+
task.toolProfile === "write" &&
|
|
161
|
+
task.writePolicy === "exclusive" &&
|
|
162
|
+
(task.writeSet?.length ?? 0) > 0 &&
|
|
163
|
+
task.writerOutcomePolicy?.requireChangedFiles === true &&
|
|
164
|
+
!task.decisionGate?.enabled &&
|
|
165
|
+
!task.dynamicExpansion &&
|
|
166
|
+
!task.dynamicReduction &&
|
|
167
|
+
!task.dynamicCondition &&
|
|
168
|
+
!task.dynamicLoopUntil);
|
|
169
|
+
}
|
|
133
170
|
export function isSafeReadOnlyPiRetryCandidate(task) {
|
|
134
171
|
if (task.executor !== "pi")
|
|
135
172
|
return false;
|
|
@@ -3,7 +3,8 @@ import { resolveShellCommands } from "../../executors/shell-executor.js";
|
|
|
3
3
|
import { pathMatchesPattern } from "../../shared/git-progress.js";
|
|
4
4
|
import { resolveRepairTaskForGate } from "./repair-artifact.js";
|
|
5
5
|
import { topoSortToRanks } from "./topo.js";
|
|
6
|
-
import { isSafeReadOnlyPiRetryCandidate } from "./retry-policy.js";
|
|
6
|
+
import { isSafeReadOnlyPiRetryCandidate, isWriterEmptyDiffRetryCandidate, INCOMPLETE_WRITE_SET_RETRY_CATEGORY, WRITER_EMPTY_DIFF_RETRY_CATEGORY, } from "./retry-policy.js";
|
|
7
|
+
import { isBackendTestCompletenessRetryCandidate } from "./backend-test-writer-completeness.js";
|
|
7
8
|
const GOVERNANCE_WARNING_TYPES = new Set([
|
|
8
9
|
"read-only-missing-artifacts-forbidden",
|
|
9
10
|
"read-only-prompt-mentions-artifact-writes",
|
|
@@ -592,10 +593,44 @@ function validateStaticTaskConfig(task, issues) {
|
|
|
592
593
|
function validateRetryPolicyTaskConfig(task, issues) {
|
|
593
594
|
if (task.retryPolicy === undefined)
|
|
594
595
|
return;
|
|
595
|
-
|
|
596
|
+
const isReadOnlyCandidate = isSafeReadOnlyPiRetryCandidate(task);
|
|
597
|
+
const isWriterEmptyDiffCandidate = isWriterEmptyDiffRetryCandidate(task);
|
|
598
|
+
const isBackendCompletenessCandidate = isBackendTestCompletenessRetryCandidate(task);
|
|
599
|
+
if (!isReadOnlyCandidate &&
|
|
600
|
+
!isWriterEmptyDiffCandidate &&
|
|
601
|
+
!isBackendCompletenessCandidate) {
|
|
602
|
+
issues.push({
|
|
603
|
+
type: "invalid-retry-policy",
|
|
604
|
+
message: `task ${task.id} declares retryPolicy but is neither a safe read-only non-dynamic Pi node nor an exclusive bounded Pi implementer with writerOutcomePolicy.requireChangedFiles=true`,
|
|
605
|
+
});
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
if (isBackendCompletenessCandidate) {
|
|
609
|
+
const categories = new Set(task.retryPolicy.retryCategories);
|
|
610
|
+
const allowed = new Set([
|
|
611
|
+
WRITER_EMPTY_DIFF_RETRY_CATEGORY,
|
|
612
|
+
INCOMPLETE_WRITE_SET_RETRY_CATEGORY,
|
|
613
|
+
]);
|
|
614
|
+
const unsupported = task.retryPolicy.retryCategories.filter((category) => !allowed.has(category));
|
|
615
|
+
if (task.retryPolicy.maxAttempts < 2 ||
|
|
616
|
+
task.retryPolicy.maxAttempts > 3 ||
|
|
617
|
+
unsupported.length > 0 ||
|
|
618
|
+
!categories.has(WRITER_EMPTY_DIFF_RETRY_CATEGORY)) {
|
|
619
|
+
issues.push({
|
|
620
|
+
type: "invalid-retry-policy",
|
|
621
|
+
message: `task ${task.id} backend-test writer retryPolicy must use 2..3 total attempts and only ${WRITER_EMPTY_DIFF_RETRY_CATEGORY} and/or ${INCOMPLETE_WRITE_SET_RETRY_CATEGORY}`,
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
if (isWriterEmptyDiffCandidate &&
|
|
627
|
+
(task.retryPolicy.maxAttempts !== 2 ||
|
|
628
|
+
task.retryPolicy.retryCategories.length !== 1 ||
|
|
629
|
+
task.retryPolicy.retryCategories[0] !==
|
|
630
|
+
WRITER_EMPTY_DIFF_RETRY_CATEGORY)) {
|
|
596
631
|
issues.push({
|
|
597
632
|
type: "invalid-retry-policy",
|
|
598
|
-
message: `task ${task.id}
|
|
633
|
+
message: `task ${task.id} writer retryPolicy must use exactly two total attempts and only ${WRITER_EMPTY_DIFF_RETRY_CATEGORY}`,
|
|
599
634
|
});
|
|
600
635
|
}
|
|
601
636
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
- [`local-development-environment.md`](local-development-environment.md):本地环境、Windows 差异和常见排障。
|
|
8
8
|
- [`branch-merge-guideline.md`](branch-merge-guideline.md):按风险选择合并模式并留下 source-SHA 证据。
|
|
9
|
-
- [`github-collaboration.md`](github-collaboration.md):仓库内 GitHub
|
|
9
|
+
- [`github-collaboration.md`](github-collaboration.md):仓库内 GitHub 协作约定及自动/人工发布通道。
|
|
10
10
|
- [`production-readiness.md`](production-readiness.md):交付前的生产就绪判断。
|
|
11
11
|
|
|
12
12
|
验证命令仍以 [`../governance/verification-matrix.md`](../governance/verification-matrix.md) 为准。
|
package/docs/templates/README.md
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
## Backend-test
|
|
31
31
|
|
|
32
|
-
- `backend-test-dag.json` — backend-test DAG
|
|
32
|
+
- `backend-test-dag.json` — backend-test DAG 模板;其中 `generate-backend-md-cases-pi` 是唯一允许 `writer-empty-diff` 重试的 writer(总共两次,仅限 post-write-guard attribution 确认的空 diff)。
|
|
33
33
|
- `backend-test-dag.classify.prompt.md`、`backend-test-dag.generate-pytest.prompt.md`、`backend-test-dag.review-cases.prompt.md`、`backend-test-dag.retrospect.prompt.md` — 分类、生成、审查和复盘提示。
|
|
34
34
|
- `backend-test-analysis.schema.json`、`backend-test-execution.schema.json`、`backend-test-result.schema.json`、`backend-test-case-manifest.schema.json` — 分析、执行、结果与用例清单 schema。
|
|
35
35
|
|
|
@@ -396,7 +396,7 @@
|
|
|
396
396
|
"type": "object",
|
|
397
397
|
"additionalProperties": false,
|
|
398
398
|
"required": ["maxAttempts"],
|
|
399
|
-
"description": "Retry policy for safe read-only
|
|
399
|
+
"description": "Retry policy for safe read-only Pi nodes, plus the sole explicit writer exception: an exclusive bounded Pi implementer with writerOutcomePolicy.requireChangedFiles=true may use exactly two attempts with only writer-empty-diff. Total attempts include the first try and are capped at five. Only the categories listed in retryCategories are retried; quota/auth/invalid-output/write-guard are never retried.",
|
|
400
400
|
"properties": {
|
|
401
401
|
"maxAttempts": {
|
|
402
402
|
"type": "integer",
|
|
@@ -418,10 +418,10 @@
|
|
|
418
418
|
"retryCategories": {
|
|
419
419
|
"type": "array",
|
|
420
420
|
"items": {
|
|
421
|
-
"enum": ["timeout", "network", "rate-limit", "unavailable", "output-too-large", "protocol-invalid"]
|
|
421
|
+
"enum": ["timeout", "network", "rate-limit", "unavailable", "empty-output", "output-too-large", "protocol-invalid", "writer-empty-diff"]
|
|
422
422
|
},
|
|
423
423
|
"default": ["timeout", "network", "rate-limit", "unavailable"],
|
|
424
|
-
"description": "Failure categories eligible for retry. quota is never eligible. output-too-large is reserved for explicit structured-required nodes. protocol-invalid is for nodes that declare outputProtocol with retryOnInvalid."
|
|
424
|
+
"description": "Failure categories eligible for retry. quota is never eligible. empty-output is safe only because retryPolicy is restricted to read-only Pi nodes (apart from the exact writer-empty-diff exception). output-too-large is reserved for explicit structured-required nodes. protocol-invalid is for nodes that declare outputProtocol with retryOnInvalid. writer-empty-diff is reserved for the exact bounded writer policy (two total attempts, requireChangedFiles=true) after executor-attributed empty diff evidence."
|
|
425
425
|
}
|
|
426
426
|
}
|
|
427
427
|
},
|
|
@@ -30,9 +30,10 @@
|
|
|
30
30
|
"Replace REPLACE/WITH/NARROW/IMPLEMENT/PATHS/** with concrete paths before executing the implementation writer",
|
|
31
31
|
"backend-test-dag uses exactly 12 real top-level tasks. Pytest collection runs once on the green path and at most twice only when one bounded pre-execution repair is eligible; business pytest test bodies execute exactly once over safe scripts explicitly mapped by final Markdown cases.",
|
|
32
32
|
"Model nodes produce Markdown and pytest assets, never backend-test business JSON envelopes.",
|
|
33
|
-
"Environment, advisory Markdown validation/coverage, collection initial/effective facts, advisory traceability/correspondence, canonical manifest, pytest-html, HTML and execution facts are deterministic evidence. Node 4 quality findings stay advisory; nodes 6/8 form the fail-closed collection authorization; node 9 traceability findings stay advisory; node 10 partial/unavailable manifest does not block node 11 when effective collection remains fresh.",
|
|
33
|
+
"Environment, advisory Markdown validation/coverage, collection initial/effective facts, advisory traceability/correspondence, pre-execution scenario-param consistency (with at most one deterministic param repair), canonical manifest, pytest-html, HTML, failure-analysis and execution facts are deterministic evidence. Node 4 quality findings stay advisory; nodes 6/8 form the fail-closed collection authorization; node 9 traceability/scenario-param findings stay advisory by default; node 10 partial/unavailable manifest does not block node 11 when effective collection remains fresh.",
|
|
34
34
|
"Only Markdown case generation/review may read source facts; pytest generation must not read source/**.",
|
|
35
|
-
"Functional case IDs use canonical BE-<MODULE>-<NNN> with exactly three digits and no alphabetic suffix. Every Test Point has exactly one variant/assertion/cross-cutting binding; only variant bindings create pytest parameter items. Production code/config, skip/xfail, execution-result repair and business pytest rerun are forbidden;
|
|
35
|
+
"Functional case IDs use canonical BE-<MODULE>-<NNN> with exactly three digits and no alphabetic suffix. Every Test Point has exactly one variant/assertion/cross-cutting binding; only variant bindings create pytest parameter items. Production code/config, skip/xfail, execution-result repair and business pytest rerun are forbidden; pre-execution repairs are limited to one collection-proven generated-test asset repair and one scenario-param payload repair (deterministic preferred).",
|
|
36
|
+
"Writer nodes must obey multi-file output-budget protocol under 16K max tokens: one file per write/edit, no chat dumps; Completeness Gate may trigger bounded incomplete-write-set recovery without lowering coverage quality."
|
|
36
37
|
],
|
|
37
38
|
"defaults": {
|
|
38
39
|
"executor": "pi",
|
|
@@ -124,12 +125,22 @@
|
|
|
124
125
|
".harness/dag-runs/**",
|
|
125
126
|
"artifacts/**"
|
|
126
127
|
],
|
|
127
|
-
"outputContract": "Write a Chinese, human-readable testcase/md/README.md plus module Markdown case cards using BE-<MODULE>-<NNN>; keep machine IDs/literals exact and do not execute pytest or modify production code/config.",
|
|
128
|
-
"subtask_prompt": "This is a required file-generation node. After reading the bounded inputs, immediately use write/edit tools to create testcase/md/README.md and the module Markdown files. Do not end after analysis or planning, and do not return before a non-empty bounded diff exists.\n\nThe first non-empty response line must be exactly IMPLEMENTATION_OUTCOME: changed after the required files have been written, or IMPLEMENTATION_OUTCOME: blocked when precise missing evidence prevents safe generation. already-satisfied is not valid for this node.\n\nRead the upstream environment report. Generate a Markdown-first backend test strategy and cases under testcase/md/**.\n\nWrite human-readable content in Simplified Chinese by default. Keep English only for machine-readable IDs and technical literals such as Case/AC/REQ/BR IDs, HTTP methods, paths, field names, enum values, commands, filenames, code symbols and exact source citations.\n\nCreate testcase/md/README.md as the concise entry page: test objective, target/environment, isolation/cleanup, module summary and a linked case index table with Case ID, Chinese case name, scenario type, endpoint and expected status/result. Avoid repeating every case body in README.\n\nBefore the Coverage Matrix, write a mandatory machine-readable `## Coverage Scope` section in README using exactly `| Field | Value |`, immediately followed by the separator row `|---|---|`, and these six unique rows: `Change Classification`, `Coverage Policy`, `Affected Operations`, `Affected Rule Keys`, `Regression Floor`, `Scope Evidence`. Classify from authoritative task/reference evidence, not merely whether a route already exists. Use only these pairs: `new-operation` → `full-contract`; `contract-change` → `affected-contract-full`; `behavior-change` → `affected-behavior-full`; `bugfix` → `reproduction-plus-neighbors`; `implementation-optimization` → `change-focused-plus-regression-floor`. List affected operations exactly as `METHOD /path`, stable rule keys separated by semicolons, and precise source pointers as Scope Evidence.\n\nCoverage depth follows the declared change scope. For `new-operation`, fully cover every documented status, request/response field rule, requiredness, enum, boundary, format, auth and business state of each affected new operation, but do not re-test unrelated existing operations. For contract/behavior changes, fully cover the changed contract or behavior and its directly affected operations. For bugfix, cover exact reproduction, adjacent boundary/equivalence cases and a normal path. For `implementation-optimization`, cover explicit ACs, deterministic affected operations and a minimum regression floor; do not exhaustively regenerate unrelated POST/PUT/GET/DELETE rules. Every non-new classification must include `main-success-path` and `unchanged-response-shape`; contract changes also include `changed-contract-boundaries`, behavior changes `affected-state-transition`, and bugfixes `defect-reproduction` plus `adjacent-boundary`. Inspect shared validator/helper/DTO/query builder evidence and expand Affected Operations when the same changed path can affect them; unresolved impact stays visible as GAP/CONFLICT.\n\nBefore writing cases, build the mandatory machine-readable Coverage Matrix inside `testcase/md/README.md` itself. Its section heading line must be exactly `## Coverage Matrix` with no numeric prefix/suffix; never place the canonical Matrix only in a module file. Use this exact header: `| Rule Key | Priority | Source | Endpoint/Field | Dimension | Rule | Required Test Points | Case IDs | Status |`. Every data row must contain exactly 9 pipe-delimited cells and must never omit `Dimension`; use concise dimensions such as requirement, operation, response-status, requiredness, enum, boundary, format, business-state or error. Use only P0/P1/P2 and COVERED/PARTIAL/GAP/CONFLICT. Use stable `TP-<UPPERCASE-HYPHENATED-ID>` test points separated by semicolons.\n\nEach Rule Key must appear in exactly one Matrix row. Preserve each AC/REQ/BR Rule Key as one row; if one product rule spans multiple dimensions, use a concise composite Dimension in that single row instead of duplicating the key. Derive OpenAPI Rule Keys exactly as the deterministic analyzer does: operation token is `<HTTP-METHOD>-<PATH>` with braces removed and every non-alphanumeric run replaced by a hyphen, uppercase (for example POST `/api/resource-notes` → `POST-API-RESOURCE-NOTES`); response statuses use `API-<OPERATION>-RESPONSE-STATUS`; body/parameter fields use `API-<OPERATION>-<FIELD>-REQUIRED|ENUM|MIN-LENGTH|MAX-LENGTH|MINIMUM|MAXIMUM|PATTERN|FORMAT`. Do not invent aliases such as API-CREATE-FIELDS when a deterministic key applies.\n\nCoverage priority is strict inside the declared scope: P0 product requirements/task hard constraints always remain in scope; P1 exhaustively supplements documented operations, fields, business rules, statuses and errors only for Affected Operations; P2 adds bounded protocol robustness only when it is relevant to the change and does not invent product behavior. Coverage percentages describe the declared affected scope, never whole-API completeness unless every operation is explicitly listed. Conflicts or undefined expectations must stay visible as GAP/CONFLICT with precise source pointers, never guessed.\n\nFor uniqueness/lifecycle rules cover absent, active-existing, deleted-existing, create-delete-recreate, restore-then-recreate and documented scope/case-normalization states. For every enum cover every valid value plus bounded invalid equivalence classes (unknown, case variant, whitespace, empty, null/missing and wrong types as applicable). For every length/number rule cover min-1, min, nominal, max and max+1. For format rules cover each allowed class separately plus a valid mixed value, and representative forbidden classes including uppercase, internal/leading/trailing whitespace, tab/newline, unsupported punctuation, slash, emoji or control characters when the source contract supports that expectation.\n\nWrite each module as readable case cards. Every case starts with `## BE-<MODULE>-<NNN>|<中文用例名称>`. `<NNN>` is exactly three zero-padded digits (`001`, `002`, ...), never two digits (`01`), a bare number, or an alphabetic suffix such as `011A`. Every case must include `### 覆盖规则`, `### 测试点`, `### 场景类型`, `### 前置条件`, `### 操作步骤`, `### 预期结果`, and `### 自动化映射`; `覆盖规则` and `测试点` must reference exact Matrix Rule Keys/Test Points. Add `测试目的`, `验收标准`, `需求依据`, and `测试数据` for readable evidence. The `验收标准` section must list the exact applicable `AC-...` IDs, and every explicit task AC must appear in at least one Case. Every automatable case explicitly names its target pytest script and exactly one primary symbol so traceability scans only that script/symbol.\n\nName each module file with a stable lowercase business stem such as `testcase/md/health.md` or `testcase/md/resource_notes.md`. Do not use Case-ID-like module filenames such as `BE-HEALTH.md` or `BE-NOTES.md`. For every automatable case, `自动化映射` must name exactly `testcase/test_<module>.py`, where <module> is that Markdown filename without `.md`, lowercased, with non-alphanumeric characters replaced by underscores. Example: `testcase/md/health.md` → `testcase/test_health.py`; `testcase/md/resource_notes.md` → `testcase/test_resource_notes.py`. Never invent a different pytest path in Markdown than the module stem implies.\n\nEvery Case must keep at least one numbered executable line under `### 操作步骤`; a compact variant/result table may follow but must not replace the numbered action anchor. Keep numbered/bulleted independently assertable results under `### 预期结果`. The exact `### 操作步骤` and `### 预期结果` headings must remain present for every Case, including compact/table-based Cases; never compress later Cases by dropping required headings. Every result must name the observable HTTP status, response field/value, state transition or membership condition, never vague wording such as ‘符合预期’.\n\nIn every `自动化映射`, use exactly these machine-readable list labels: `脚本`, `primary symbol`, `变体测试点`, `场景断言测试点`, `横切证据测试点`. Each Test Point from `### 测试点` must appear in exactly one binding list, and every Test Point named in any binding list must also be declared in that Case's `### 测试点`; write `无` for an empty list. A variant Test Point is atomic: one exact endpoint/input/precondition/outcome row equals one exact pytest item and one exact TP ID. If a parameter table has five rows, declare five distinct variant TP IDs in Markdown; never declare one family TP and append row suffixes only in pytest. Classify as `variant` only when endpoint, request input, precondition business state, or expected outcome genuinely changes and therefore needs an independent pytest parameter item. Classify CRUD checkpoints, status/body/header/schema assertions and multiple checks over the same response/journey as `assertion`; classify shared HTTP logging/redaction/truncation evidence as `cross-cutting`. Never create a Test Point merely to parameterize a checkpoint. Every non-cross-cutting TP ID is owned by exactly one Case; when the same response/schema/error assertion is needed in different Cases, use distinct Case-specific TP IDs instead of reusing one assertion TP across Cases. Keep the script path identical to the module one-to-one path and declare exactly one primary symbol named with the canonical Case prefix, for example `BE-RN-003` → `test_BE_RN_003_<description>`; non-Case-prefixed primary symbols are forbidden because parameterized item association must remain deterministic. For redaction scenarios, list sensitive header/field key names only. Never write any header-name-and-value pair, credential placeholder, fake token, anti-example, or other secret-shaped literal in Markdown; state only that a test-only value is supplied at runtime and omitted. Put implementation-only restrictions in a concise `<details>` block rather than dominating the main case flow. Before finalizing Markdown, calculate the predicted collected-item count as `sum(max(1, number of variant Test Points in each Case))`. If the task declares an item budget, the prediction must not exceed it. Reduce excess only by removing duplicate execution and converting same-request checkpoints to assertions; never drop required rules, boundaries, enums, operation-specific inputs, or business states. Record the prediction in README. Use only environment-supported fixtures/targets/isolation, record evidence gaps in Chinese, and do not emit JSON, pytest, or execute commands.\n\n## Derived task contract: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Authoritative reference index\n\n[]\n\nFor each index entry, use `readPath` for Pi read-tool calls and copy `path` exactly into Markdown Source References. Bound files under .harness/tasks/<taskId>/source/** are read-only inputs: reading them is allowed even though writing .harness/** is forbidden. Never resolve `path` relative to the repository root, search for substitutes, or fall back to docs/** when a bound read fails.\n\nRead only precise indexed references needed for AC/API/field/rule evidence; references remain authoritative over derived text.",
|
|
129
128
|
"writerOutcomePolicy": {
|
|
130
129
|
"type": "implementation-outcome-v1",
|
|
131
130
|
"requireChangedFiles": true
|
|
132
|
-
}
|
|
131
|
+
},
|
|
132
|
+
"retryPolicy": {
|
|
133
|
+
"maxAttempts": 3,
|
|
134
|
+
"backoff": "exponential",
|
|
135
|
+
"initialDelayMs": 2000,
|
|
136
|
+
"maxDelayMs": 30000,
|
|
137
|
+
"retryCategories": [
|
|
138
|
+
"writer-empty-diff",
|
|
139
|
+
"incomplete-write-set"
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
"outputContract": "Write a Chinese, human-readable testcase/md/README.md plus module Markdown case cards using BE-<MODULE>-<NNN>; keep machine IDs/literals exact and do not execute pytest or modify production code/config.",
|
|
143
|
+
"subtask_prompt": "This is a required file-generation node. After reading the bounded inputs, immediately use write/edit tools to create testcase/md/README.md and the module Markdown files. Do not end after analysis or planning, and do not return before a non-empty bounded diff exists.\n\nOutput budget protocol (hard, max output <=16K per turn): Never paste full Matrix, case bodies, or source text into assistant chat. Each write/edit tool call touches at most one file. Order: README.md (Scope+Matrix+module index only) → one module file per turn → short IMPLEMENTATION_OUTCOME. Splitting modules preserves every in-scope rule/TP; it must not drop coverage. Compact tables/lists are required; omitting required sections or in-scope variants is forbidden. If a Completeness Gate / OUTPUT_LIMIT_RECOVERY retry is injected, continue only listed target paths.\n\nThe first non-empty response line must be exactly IMPLEMENTATION_OUTCOME: changed after the required files have been written, or IMPLEMENTATION_OUTCOME: blocked when precise missing evidence prevents safe generation. already-satisfied is not valid for this node.\n\nRead the upstream environment report. Generate a Markdown-first backend test strategy and cases under testcase/md/**.\n\nWrite human-readable content in Simplified Chinese by default. Keep English only for machine-readable IDs and technical literals such as Case/AC/REQ/BR IDs, HTTP methods, paths, field names, enum values, commands, filenames, code symbols and exact source citations.\n\nCreate testcase/md/README.md as the concise entry page: test objective, target/environment, isolation/cleanup, module summary and a linked case index table with Case ID, Chinese case name, scenario type, endpoint and expected status/result. Avoid repeating every case body in README.\n\nBefore the Coverage Matrix, write a mandatory machine-readable `## Coverage Scope` section in README using exactly `| Field | Value |`, immediately followed by the separator row `|---|---|`, and these six unique rows: `Change Classification`, `Coverage Policy`, `Affected Operations`, `Affected Rule Keys`, `Regression Floor`, `Scope Evidence`. Classify from authoritative task/reference evidence, not merely whether a route already exists. Use only these pairs: `new-operation` → `full-contract`; `contract-change` → `affected-contract-full`; `behavior-change` → `affected-behavior-full`; `bugfix` → `reproduction-plus-neighbors`; `implementation-optimization` → `change-focused-plus-regression-floor`. List affected operations exactly as `METHOD /path`, stable rule keys separated by semicolons, and precise source pointers as Scope Evidence.\n\nCoverage depth follows the declared change scope. For `new-operation`, fully cover every documented status, request/response field rule, requiredness, enum, boundary, format, auth and business state of each affected new operation, but do not re-test unrelated existing operations. For contract/behavior changes, fully cover the changed contract or behavior and its directly affected operations. For bugfix, cover exact reproduction, adjacent boundary/equivalence cases and a normal path. For `implementation-optimization`, cover explicit ACs, deterministic affected operations and a minimum regression floor; do not exhaustively regenerate unrelated POST/PUT/GET/DELETE rules. Every non-new classification must include `main-success-path` and `unchanged-response-shape`; contract changes also include `changed-contract-boundaries`, behavior changes `affected-state-transition`, and bugfixes `defect-reproduction` plus `adjacent-boundary`. Inspect shared validator/helper/DTO/query builder evidence and expand Affected Operations when the same changed path can affect them; unresolved impact stays visible as GAP/CONFLICT.\n\nBefore writing cases, build the mandatory machine-readable Coverage Matrix inside `testcase/md/README.md` itself. Its section heading line must be exactly `## Coverage Matrix` with no numeric prefix/suffix; never place the canonical Matrix only in a module file. Use this exact header: `| Rule Key | Priority | Source | Endpoint/Field | Dimension | Rule | Required Test Points | Case IDs | Status |`. Every data row must contain exactly 9 pipe-delimited cells and must never omit `Dimension`; use concise dimensions such as requirement, operation, response-status, requiredness, enum, boundary, format, business-state or error. Use only P0/P1/P2 and COVERED/PARTIAL/GAP/CONFLICT. Use stable `TP-<UPPERCASE-HYPHENATED-ID>` test points separated by semicolons.\n\nEach Rule Key must appear in exactly one Matrix row. Preserve each AC/REQ/BR Rule Key as one row; if one product rule spans multiple dimensions, use a concise composite Dimension in that single row instead of duplicating the key. Derive OpenAPI Rule Keys exactly as the deterministic analyzer does: operation token is `<HTTP-METHOD>-<PATH>` with braces removed and every non-alphanumeric run replaced by a hyphen, uppercase (for example POST `/api/resource-notes` → `POST-API-RESOURCE-NOTES`); response statuses use `API-<OPERATION>-RESPONSE-STATUS`; body/parameter fields use `API-<OPERATION>-<FIELD>-REQUIRED|ENUM|MIN-LENGTH|MAX-LENGTH|MINIMUM|MAXIMUM|PATTERN|FORMAT`. Do not invent aliases such as API-CREATE-FIELDS when a deterministic key applies.\n\nCoverage priority is strict inside the declared scope: P0 product requirements/task hard constraints always remain in scope; P1 exhaustively supplements documented operations, fields, business rules, statuses and errors only for Affected Operations; P2 adds bounded protocol robustness only when it is relevant to the change and does not invent product behavior. Coverage percentages describe the declared affected scope, never whole-API completeness unless every operation is explicitly listed. Conflicts or undefined expectations must stay visible as GAP/CONFLICT with precise source pointers, never guessed.\n\nFor uniqueness/lifecycle rules cover absent, active-existing, deleted-existing, create-delete-recreate, restore-then-recreate and documented scope/case-normalization states. For every enum cover every valid value plus bounded invalid equivalence classes (unknown, case variant, whitespace, empty, null/missing and wrong types as applicable). For every length/number rule cover min-1, min, nominal, max and max+1. For format rules cover each allowed class separately plus a valid mixed value, and representative forbidden classes including uppercase, internal/leading/trailing whitespace, tab/newline, unsupported punctuation, slash, emoji or control characters when the source contract supports that expectation.\n\nWrite each module as readable case cards. Every case starts with `## BE-<MODULE>-<NNN>|<中文用例名称>`. `<NNN>` is exactly three zero-padded digits (`001`, `002`, ...), never two digits (`01`), a bare number, or an alphabetic suffix such as `011A`. Every case must include `### 覆盖规则`, `### 测试点`, `### 场景类型`, `### 前置条件`, `### 操作步骤`, `### 预期结果`, and `### 自动化映射`; `覆盖规则` and `测试点` must reference exact Matrix Rule Keys/Test Points. Add `测试目的`, `验收标准`, `需求依据`, and `测试数据` for readable evidence. The `验收标准` section must list the exact applicable `AC-...` IDs, and every explicit task AC must appear in at least one Case. Every automatable case explicitly names its target pytest script and exactly one primary symbol so traceability scans only that script/symbol.\n\nName each module file with a stable lowercase business stem such as `testcase/md/health.md` or `testcase/md/resource_notes.md`. Do not use Case-ID-like module filenames such as `BE-HEALTH.md` or `BE-NOTES.md`. For every automatable case, `自动化映射` must name exactly `testcase/test_<module>.py`, where <module> is that Markdown filename without `.md`, lowercased, with non-alphanumeric characters replaced by underscores. Example: `testcase/md/health.md` → `testcase/test_health.py`; `testcase/md/resource_notes.md` → `testcase/test_resource_notes.py`. Never invent a different pytest path in Markdown than the module stem implies.\n\nEvery Case must keep at least one numbered executable line under `### 操作步骤`; a compact variant/result table may follow but must not replace the numbered action anchor. Keep numbered/bulleted independently assertable results under `### 预期结果`. The exact `### 操作步骤` and `### 预期结果` headings must remain present for every Case, including compact/table-based Cases; never compress later Cases by dropping required headings. Every result must name the observable HTTP status, response field/value, state transition or membership condition, never vague wording such as ‘符合预期’.\n\nIn every `自动化映射`, use exactly these machine-readable list labels: `脚本`, `primary symbol`, `变体测试点`, `场景断言测试点`, `横切证据测试点`. Each Test Point from `### 测试点` must appear in exactly one binding list, and every Test Point named in any binding list must also be declared in that Case's `### 测试点`; write `无` for an empty list. A variant Test Point is atomic: one exact endpoint/input/precondition/outcome row equals one exact pytest item and one exact TP ID. If a parameter table has five rows, declare five distinct variant TP IDs in Markdown; never declare one family TP and append row suffixes only in pytest. Classify as `variant` only when endpoint, request input, precondition business state, or expected outcome genuinely changes and therefore needs an independent pytest parameter item. Classify CRUD checkpoints, status/body/header/schema assertions and multiple checks over the same response/journey as `assertion`; classify shared HTTP logging/redaction/truncation evidence as `cross-cutting`. Never create a Test Point merely to parameterize a checkpoint. Every non-cross-cutting TP ID is owned by exactly one Case; when the same response/schema/error assertion is needed in different Cases, use distinct Case-specific TP IDs instead of reusing one assertion TP across Cases. Keep the script path identical to the module one-to-one path and declare exactly one primary symbol named with the canonical Case prefix, for example `BE-RN-003` → `test_BE_RN_003_<description>`; non-Case-prefixed primary symbols are forbidden because parameterized item association must remain deterministic. For redaction scenarios, list sensitive header/field key names only. Never write any header-name-and-value pair, credential placeholder, fake token, anti-example, or other secret-shaped literal in Markdown; state only that a test-only value is supplied at runtime and omitted. Put implementation-only restrictions in a concise `<details>` block rather than dominating the main case flow. Before finalizing Markdown, calculate the predicted collected-item count as `sum(max(1, number of variant Test Points in each Case))`. If the task declares an item budget, the prediction must not exceed it. Reduce excess only by removing duplicate execution and converting same-request checkpoints to assertions; never drop required rules, boundaries, enums, operation-specific inputs, or business states. Record the prediction in README. Use only environment-supported fixtures/targets/isolation, record evidence gaps in Chinese, and do not emit JSON, pytest, or execute commands.\n\n## Derived task contract: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Authoritative reference index\n\n[]\n\nFor each index entry, use `readPath` for Pi read-tool calls and copy `path` exactly into Markdown Source References. Bound files under .harness/tasks/<taskId>/source/** are read-only inputs: reading them is allowed even though writing .harness/** is forbidden. Never resolve `path` relative to the repository root, search for substitutes, or fall back to docs/** when a bound read fails.\n\nRead only precise indexed references needed for AC/API/field/rule evidence; references remain authoritative over derived text."
|
|
133
144
|
},
|
|
134
145
|
{
|
|
135
146
|
"id": "review-and-revise-backend-md-cases-pi",
|
|
@@ -153,7 +164,7 @@
|
|
|
153
164
|
"artifacts/**"
|
|
154
165
|
],
|
|
155
166
|
"outputContract": "Review source fidelity and directly revise only testcase/md/**; return concise Markdown, never JSON.",
|
|
156
|
-
"subtask_prompt": "Independently review generated Markdown cases against the task requirements and environment evidence. Treat the files as human-facing test documentation: require clear preconditions, executable steps and assertable expected results; improve names, purpose, metadata and automation mapping where useful while preserving exact machine IDs and technical literals.\n\nIndependently reconstruct the change classification, affected operations/rules, P0 product scenarios and applicable P1 documented API rules from authoritative sources before trusting the generated Coverage Scope or Coverage Matrix. Perform an explicit coverage-scope review: reject `new-operation` when the task only optimizes an existing implementation without contract change; reject narrow optimization scope when shared validator/helper/DTO/query builder evidence directly affects more operations; reject full-contract expansion across unrelated operations. For every in-scope operation, check applicable lifecycle/uniqueness states (including deleted-existing when in scope), valid enum values, bounded invalid classes, min-1/min/nominal/max/max+1, allowed/forbidden format classes, required/null/missing/wrong-type semantics, status/error codes, auth and state transitions. Directly add in-scope omissions; undefined impact remains GAP/CONFLICT rather than invented behavior.\n\nCheck AC completeness/meaning, endpoint, fields/shape, status/error codes, rules, states, documented boundaries/auth, positive/negative coverage, executable steps and assertable results. Require the exact `## Coverage Scope` Field/Value table with the `|---|---|` separator row, a valid classification-policy pair, non-empty Affected Operations/Rule Keys/Scope Evidence, and the classification-specific Regression Floor. Require the exact unnumbered `## Coverage Matrix` heading in `testcase/md/README.md`, exact headers, exactly 9 cells in every data row (including a non-empty Dimension), deterministic OpenAPI Rule Keys for every in-scope affected operation, exactly one Matrix row per Rule Key (merge multi-dimension product rows), and bidirectional Matrix Rule/Test Point ↔ Case bindings. Never describe affected-scope coverage as whole-API completeness. Every explicit AC ID must appear in at least one Case `验收标准`; every explicit in-scope AC/REQ/BR Rule Key cited by a Case must have exactly one Coverage Matrix row, and no Case may cite a source Rule Key omitted from the Matrix. Every Matrix Case ID must share at least one of that row's Required Test Points and the Case must cite that Rule Key. Perform an explicit execution-redundancy review: merge checkpoint-only parameter rows, repeated default/read-back assertions, DELETE status/body/follow-up-read checks, response schema/Content-Type checks, PUT full-update/timestamp checks, repeated list setup and identical null/empty inputs when endpoint, input partition, precondition state and expected outcome are the same. Preserve separate POST/PUT, boundary, enum, wrong-type, role/tenant and distinct business-state variants. Directly repair malformed headings/rows/keys and binding modes rather than merely commenting on them. Reject avoidable English prose, duplicated bilingual wording, repeated boilerplate, oversized unstructured sections, a `### 操作步骤` section that contains only a table without any numbered executable line, vague results such as ‘符合预期’, Case-ID-like module filenames (for example `BE-HEALTH.md`), dropped exact `### 操作步骤`/`### 预期结果` headings, and missing or drifted script/function mapping where it can be derived.\n\nCorrect testcase/md/** directly: add documented omissions, remove unsupported cases, rename module files to stable lowercase stems when needed, normalize every Case ID to hyphen-separated module segments plus exactly three zero-padded digits (`BE-RESOURCE_NOTES-01` → `BE-RESOURCE-NOTES-001`; `BE-RN-011A` must be renumbered or merged) consistently across headings/index/mappings, fix automation mappings so each case points at `testcase/test_<module>.py` derived from that module filename and declares exactly one primary symbol, assign every Test Point exactly one of `变体测试点`/`场景断言测试点`/`横切证据测试点`, ensure every binding-list Test Point is also present in that Case's `### 测试点`, expand every variant parameter row into its own atomic TP ID, make every non-cross-cutting TP Case-specific and owned by exactly one Case, require every primary symbol to start with the canonical Case prefix, ensure every explicit AC ID appears in an applicable Case `验收标准`, merge execution duplicates, improve navigation/tables/Chinese wording, or record gaps in Chinese. Remove every credential/header value, placeholder, fake token and anti-example from Markdown. Sensitive key names may remain only as a plain list; values must be described as runtime-only and omitted, with no colon/value pair or literal example anywhere, including details blocks and explanatory text. Keep Case IDs, AC/REQ/BR IDs, HTTP methods, paths, fields, enum values, filenames, code symbols and source citations as exact machine-readable identifiers; only normalize Case ID separator/sequence formatting as specified above. Recalculate predicted collected items as `sum(max(1, variant count per Case))`; when the task declares a budget, directly merge redundant journeys/reclassify same-request checkpoints until the prediction is within budget, while preserving all required coverage. The validator accepts Chinese and legacy English section aliases; retain or converge to the Chinese human-readable headings without losing structure.\n\nRead only precise referenced source paths plus requirement sections needed for uncovered ACs. Do not scan the repository, modify source/**, generate pytest, execute tests, or emit JSON.\n\n## Derived task contract: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Authoritative reference index\n\n[]\n\nFor each index entry, use `readPath` for Pi read-tool calls and keep `path` as the exact Markdown Source References citation. Bound files under .harness/tasks/<taskId>/source/** are read-only inputs: reading them is allowed even though writing .harness/** is forbidden. Never resolve `path` relative to the repository root, search for substitutes, or fall back to docs/** when a bound read fails."
|
|
167
|
+
"subtask_prompt": "Independently review generated Markdown cases against the task requirements and environment evidence. Treat the files as human-facing test documentation: require clear preconditions, executable steps and assertable expected results; improve names, purpose, metadata and automation mapping where useful while preserving exact machine IDs and technical literals.\n\nOutput budget protocol: default to local edit per file; never dump full Matrix/case bodies into assistant chat. Review order is README (Scope/Matrix) then one module file per turn. When adding omitted in-scope cases, write one file per tool call and keep every required section. Do not bulk-delete in-scope cases to save tokens.\n\nFor every variant Test Point, ensure the Markdown scenario intent is machine-checkable: prefer an explicit line `场景意图: <empty|missing|null|min-1|min|max|max+1|pattern-invalid|enum-invalid|wrong-type|nominal|custom-literal:V>; field=<name>; bound=<n optional>; example=<optional>` near 测试数据/操作步骤, and keep pytest params later aligned to that intent.\n\nIndependently reconstruct the change classification, affected operations/rules, P0 product scenarios and applicable P1 documented API rules from authoritative sources before trusting the generated Coverage Scope or Coverage Matrix. Perform an explicit coverage-scope review: reject `new-operation` when the task only optimizes an existing implementation without contract change; reject narrow optimization scope when shared validator/helper/DTO/query builder evidence directly affects more operations; reject full-contract expansion across unrelated operations. For every in-scope operation, check applicable lifecycle/uniqueness states (including deleted-existing when in scope), valid enum values, bounded invalid classes, min-1/min/nominal/max/max+1, allowed/forbidden format classes, required/null/missing/wrong-type semantics, status/error codes, auth and state transitions. Directly add in-scope omissions; undefined impact remains GAP/CONFLICT rather than invented behavior.\n\nCheck AC completeness/meaning, endpoint, fields/shape, status/error codes, rules, states, documented boundaries/auth, positive/negative coverage, executable steps and assertable results. Require the exact `## Coverage Scope` Field/Value table with the `|---|---|` separator row, a valid classification-policy pair, non-empty Affected Operations/Rule Keys/Scope Evidence, and the classification-specific Regression Floor. Require the exact unnumbered `## Coverage Matrix` heading in `testcase/md/README.md`, exact headers, exactly 9 cells in every data row (including a non-empty Dimension), deterministic OpenAPI Rule Keys for every in-scope affected operation, exactly one Matrix row per Rule Key (merge multi-dimension product rows), and bidirectional Matrix Rule/Test Point ↔ Case bindings. Never describe affected-scope coverage as whole-API completeness. Every explicit AC ID must appear in at least one Case `验收标准`; every explicit in-scope AC/REQ/BR Rule Key cited by a Case must have exactly one Coverage Matrix row, and no Case may cite a source Rule Key omitted from the Matrix. Every Matrix Case ID must share at least one of that row's Required Test Points and the Case must cite that Rule Key. Perform an explicit execution-redundancy review: merge checkpoint-only parameter rows, repeated default/read-back assertions, DELETE status/body/follow-up-read checks, response schema/Content-Type checks, PUT full-update/timestamp checks, repeated list setup and identical null/empty inputs when endpoint, input partition, precondition state and expected outcome are the same. Preserve separate POST/PUT, boundary, enum, wrong-type, role/tenant and distinct business-state variants. Directly repair malformed headings/rows/keys and binding modes rather than merely commenting on them. Reject avoidable English prose, duplicated bilingual wording, repeated boilerplate, oversized unstructured sections, a `### 操作步骤` section that contains only a table without any numbered executable line, vague results such as ‘符合预期’, Case-ID-like module filenames (for example `BE-HEALTH.md`), dropped exact `### 操作步骤`/`### 预期结果` headings, and missing or drifted script/function mapping where it can be derived.\n\nCorrect testcase/md/** directly: add documented omissions, remove unsupported cases, rename module files to stable lowercase stems when needed, normalize every Case ID to hyphen-separated module segments plus exactly three zero-padded digits (`BE-RESOURCE_NOTES-01` → `BE-RESOURCE-NOTES-001`; `BE-RN-011A` must be renumbered or merged) consistently across headings/index/mappings, fix automation mappings so each case points at `testcase/test_<module>.py` derived from that module filename and declares exactly one primary symbol, assign every Test Point exactly one of `变体测试点`/`场景断言测试点`/`横切证据测试点`, ensure every binding-list Test Point is also present in that Case's `### 测试点`, expand every variant parameter row into its own atomic TP ID, make every non-cross-cutting TP Case-specific and owned by exactly one Case, require every primary symbol to start with the canonical Case prefix, ensure every explicit AC ID appears in an applicable Case `验收标准`, merge execution duplicates, improve navigation/tables/Chinese wording, or record gaps in Chinese. Remove every credential/header value, placeholder, fake token and anti-example from Markdown. Sensitive key names may remain only as a plain list; values must be described as runtime-only and omitted, with no colon/value pair or literal example anywhere, including details blocks and explanatory text. Keep Case IDs, AC/REQ/BR IDs, HTTP methods, paths, fields, enum values, filenames, code symbols and source citations as exact machine-readable identifiers; only normalize Case ID separator/sequence formatting as specified above. Recalculate predicted collected items as `sum(max(1, variant count per Case))`; when the task declares a budget, directly merge redundant journeys/reclassify same-request checkpoints until the prediction is within budget, while preserving all required coverage. The validator accepts Chinese and legacy English section aliases; retain or converge to the Chinese human-readable headings without losing structure.\n\nRead only precise referenced source paths plus requirement sections needed for uncovered ACs. Do not scan the repository, modify source/**, generate pytest, execute tests, or emit JSON.\n\n## Derived task contract: 需求.md\n\n# Backend test\n- AC-001 proof\n\n## Authoritative reference index\n\n[]\n\nFor each index entry, use `readPath` for Pi read-tool calls and keep `path` as the exact Markdown Source References citation. Bound files under .harness/tasks/<taskId>/source/** are read-only inputs: reading them is allowed even though writing .harness/** is forbidden. Never resolve `path` relative to the repository root, search for substitutes, or fall back to docs/** when a bound read fails."
|
|
157
168
|
},
|
|
158
169
|
{
|
|
159
170
|
"id": "validate-backend-md-cases-shell",
|
|
@@ -206,8 +217,22 @@
|
|
|
206
217
|
".harness/dag-runs/**",
|
|
207
218
|
"artifacts/**"
|
|
208
219
|
],
|
|
220
|
+
"retryPolicy": {
|
|
221
|
+
"maxAttempts": 3,
|
|
222
|
+
"backoff": "exponential",
|
|
223
|
+
"initialDelayMs": 2000,
|
|
224
|
+
"maxDelayMs": 30000,
|
|
225
|
+
"retryCategories": [
|
|
226
|
+
"writer-empty-diff",
|
|
227
|
+
"incomplete-write-set"
|
|
228
|
+
]
|
|
229
|
+
},
|
|
230
|
+
"writerOutcomePolicy": {
|
|
231
|
+
"type": "implementation-outcome-v1",
|
|
232
|
+
"requireChangedFiles": true
|
|
233
|
+
},
|
|
209
234
|
"outputContract": "Convert every final automatable Markdown case into pytest assets whose actual test function region contains the exact Case ID, preferably in the function name or docstring. Each testcase/md/<module>.md (excluding README.md) maps one-to-one to testcase/test_<module>.py; never merge or split modules. No JSON and no pytest execution.",
|
|
210
|
-
"subtask_prompt": "Convert testcase/md/** to pytest using upstream environment and advisory validation evidence plus only bounded pytest config/conftest. A FAIL advisory report does not authorize inventing missing behavior; use the final Markdown facts that are present.\n\nEnsure every final Markdown Case ID appears in exactly one primary pytest test function or pytest test class method region, using the exact `primary symbol` declared by Markdown. The symbol must start with `test_BE_<MODULE>_<NNN>_` so every parameterized collected item remains associated with its Case. Module-level functions and class-based pytest methods are both supported. Only `变体测试点` may use stable `pytest.param(..., id=\"TP-...\")` IDs, and every atomic variant ID must appear exactly once with a genuine input/state/outcome change. Use `pytest.param(..., id=...)` for every row; do not use decorator-level `ids=[...]`, generated suffixes, or IDs that extend/shorten the exact Markdown TP. Do not parameterize `场景断言测试点` or `横切证据测试点`; execute all assertion checkpoints within the same business journey/item and use shared helpers for cross-cutting evidence. The primary symbol docstring must contain exact metadata lines `Case-ID: BE-...`, `Assertion-Test-Points: TP-...;TP-...` and `Cross-Cutting-Test-Points: TP-...;TP-...` (use `none` when empty). No Test Point may be invented, renamed, omitted or bound in two modes. The generated pytest collection shape must equal the Markdown prediction `sum(max(1, variant count per Case))`; keep it at or below the task's explicit budget by removing duplicate execution, never by collapsing multiple parameter rows under a coarse family TP. Assertions come only from 预期结果 and setup comes only from 前置条件/测试数据/自动化映射.\n\nName each generated pytest file so it corresponds one-to-one with its source Markdown module file: for each `testcase/md/<module>.md` (excluding README.md), emit exactly one `testcase/test_<module>.py`. The <module> stem is the Markdown filename without the `.md` extension, lowercased and with non-alphanumeric characters replaced by underscores. For example, `testcase/md/resource_notes.md` maps to `testcase/test_resource_notes.py`, `testcase/md/health.md` maps to `testcase/test_health.py`, `testcase/md/BE-HEALTH.md` maps to `testcase/test_be_health.py`, and `testcase/md/order-api.md` maps to `testcase/test_order_api.py`. If Markdown automation mapping names a different path than this module stem path, still write the module stem path and do not invent prefixes such as `test_be_*` unless the module filename itself normalizes to that stem. Never merge multiple Markdown modules into one pytest file, never split one module across several files, and never invent pytest filenames unrelated to the Markdown modules.\n\nGenerate a reusable HTTP logging helper (or equivalent client wrapper) and call it for every interface request. The request log must include method, URL/path, and request parameters (query plus JSON/body/payload summary). The response log must include status code and response result (JSON/text/body summary), and both records must be visible in pytest stdout/stderr without changing assertions.\n\nHTTP response header names are case-insensitive. If the helper stores a lower-case normalized header map, every Content-Type or other header assertion must query the lower-case key (for example `content-type`) or use an explicitly case-insensitive accessor; never call a case-sensitive plain dict with `Content-Type` when the stored key is lower-case. Preserve the actual media-type assertion rather than dropping it.\n\nCompare timestamps and other semantically equivalent protocol values by parsed meaning, not byte-for-byte serialization. In particular, normalize valid ISO-8601 instants before equality/order assertions so differences such as omitted trailing fractional seconds do not create TestBug failures; preserve exact-string assertions only when the Markdown explicitly requires representation equality.\n\nBefore logging, recursively redact sensitive keys and header values including authorization, proxy-authorization, cookie, set-cookie, token, password, secret, api key and credentials. Never print full Authorization/Cookie values. Apply bounded truncation to serialized request and response bodies (with an explicit truncation marker) so large payloads cannot flood pytest or report artifacts.\n\nDo not read source/**, add cases, reassign ACs, modify conftest/config/production code, use skip/xfail, swallow assertions, execute pytest, or emit JSON. For best-effort cleanup, catch only the narrow transport exception actually raised by the selected HTTP client (for example `requests.RequestException` or `urllib.error.URLError`); never use bare `except`, `Exception`, or `BaseException` with `pass`."
|
|
235
|
+
"subtask_prompt": "Convert testcase/md/** to pytest using upstream environment and advisory validation evidence plus only bounded pytest config/conftest. A FAIL advisory report does not authorize inventing missing behavior; use the final Markdown facts that are present.\n\nOutput budget protocol (hard, max output <=16K per turn): Write helpers/factories first, then exactly one test_<module>.py per write/edit tool call following MD stems. Never paste full Python modules into assistant chat. Do not merge modules. Do not reduce params/assertions/skips to fit. If OUTPUT_LIMIT_RECOVERY is injected, continue only listed missing/broken scripts.\n\nAlign every variant pytest.param payload with the Markdown scenario intent (empty/missing/null/length/pattern/enum/wrong-type/nominal). Prefer literal payloads over Faker for intent-critical fields so pre-execution scenario-param checks can verify them.\n\nEnsure every final Markdown Case ID appears in exactly one primary pytest test function or pytest test class method region, using the exact `primary symbol` declared by Markdown. The symbol must start with `test_BE_<MODULE>_<NNN>_` so every parameterized collected item remains associated with its Case. Module-level functions and class-based pytest methods are both supported. Only `变体测试点` may use stable `pytest.param(..., id=\"TP-...\")` IDs, and every atomic variant ID must appear exactly once with a genuine input/state/outcome change. Use `pytest.param(..., id=...)` for every row; do not use decorator-level `ids=[...]`, generated suffixes, or IDs that extend/shorten the exact Markdown TP. Do not parameterize `场景断言测试点` or `横切证据测试点`; execute all assertion checkpoints within the same business journey/item and use shared helpers for cross-cutting evidence. The primary symbol docstring must contain exact metadata lines `Case-ID: BE-...`, `Assertion-Test-Points: TP-...;TP-...` and `Cross-Cutting-Test-Points: TP-...;TP-...` (use `none` when empty). No Test Point may be invented, renamed, omitted or bound in two modes. The generated pytest collection shape must equal the Markdown prediction `sum(max(1, variant count per Case))`; keep it at or below the task's explicit budget by removing duplicate execution, never by collapsing multiple parameter rows under a coarse family TP. Assertions come only from 预期结果 and setup comes only from 前置条件/测试数据/自动化映射.\n\nName each generated pytest file so it corresponds one-to-one with its source Markdown module file: for each `testcase/md/<module>.md` (excluding README.md), emit exactly one `testcase/test_<module>.py`. The <module> stem is the Markdown filename without the `.md` extension, lowercased and with non-alphanumeric characters replaced by underscores. For example, `testcase/md/resource_notes.md` maps to `testcase/test_resource_notes.py`, `testcase/md/health.md` maps to `testcase/test_health.py`, `testcase/md/BE-HEALTH.md` maps to `testcase/test_be_health.py`, and `testcase/md/order-api.md` maps to `testcase/test_order_api.py`. If Markdown automation mapping names a different path than this module stem path, still write the module stem path and do not invent prefixes such as `test_be_*` unless the module filename itself normalizes to that stem. Never merge multiple Markdown modules into one pytest file, never split one module across several files, and never invent pytest filenames unrelated to the Markdown modules.\n\nGenerate a reusable HTTP logging helper (or equivalent client wrapper) and call it for every interface request. The request log must include method, URL/path, and request parameters (query plus JSON/body/payload summary). The response log must include status code and response result (JSON/text/body summary), and both records must be visible in pytest stdout/stderr without changing assertions.\n\nHTTP response header names are case-insensitive. If the helper stores a lower-case normalized header map, every Content-Type or other header assertion must query the lower-case key (for example `content-type`) or use an explicitly case-insensitive accessor; never call a case-sensitive plain dict with `Content-Type` when the stored key is lower-case. Preserve the actual media-type assertion rather than dropping it.\n\nCompare timestamps and other semantically equivalent protocol values by parsed meaning, not byte-for-byte serialization. In particular, normalize valid ISO-8601 instants before equality/order assertions so differences such as omitted trailing fractional seconds do not create TestBug failures; preserve exact-string assertions only when the Markdown explicitly requires representation equality.\n\nBefore logging, recursively redact sensitive keys and header values including authorization, proxy-authorization, cookie, set-cookie, token, password, secret, api key and credentials. Never print full Authorization/Cookie values. Apply bounded truncation to serialized request and response bodies (with an explicit truncation marker) so large payloads cannot flood pytest or report artifacts.\n\nDo not read source/**, add cases, reassign ACs, modify conftest/config/production code, use skip/xfail, swallow assertions, execute pytest, or emit JSON. For best-effort cleanup, catch only the narrow transport exception actually raised by the selected HTTP client (for example `requests.RequestException` or `urllib.error.URLError`); never use bare `except`, `Exception`, or `BaseException` with `pass`."
|
|
211
236
|
},
|
|
212
237
|
{
|
|
213
238
|
"id": "assess-backend-pytest-collection-shell",
|
|
@@ -270,7 +295,7 @@
|
|
|
270
295
|
"type": "implementation-outcome-v1"
|
|
271
296
|
},
|
|
272
297
|
"outputContract": "First non-empty line is IMPLEMENTATION_OUTCOME: changed|already-satisfied|blocked, followed by a concise repair summary. Modify only generated pytest scripts/helpers/factories and preserve every Markdown Case, Test Point, primary symbol and assertion meaning.",
|
|
273
|
-
"subtask_prompt": "Repair the generated backend pytest asset as one bounded program using the direct upstream collection assessment. This is the only repair attempt and happens before any business test body execution.\n\nFix only collection-proven generated testcase-local defects: create the exact safe missing mapped test_*.py paths listed by the initial facts, or repair syntax, module path, missing symbol, circular import, fixture-name, decorator or parameterization inconsistencies. Inspect all affected importers and providers so the repair is cross-file consistent; do not create unrelated pytest scripts.\n\nPreserve final testcase/md/** semantics, every Case ID, Rule/Test Point binding, primary symbol, parameter ID, expected status/body/schema assertion, HTTP logging, redaction and truncation behavior.\n\nDo not read task source/** or reinterpret requirements. Do not modify Markdown, conftest, pytest config, production code or dependencies.\n\nDo not add skip/skipif/xfail, remove tests, reduce collected items, loosen assertions, swallow exceptions, use try/except ImportError fallback, mutate sys.path/PYTHONPATH, or replace the real API with mocks.\n\nDo not execute pytest; the deterministic effective collection gate owns the final collection attempt."
|
|
298
|
+
"subtask_prompt": "Repair the generated backend pytest asset as one bounded program using the direct upstream collection assessment. This is the only repair attempt and happens before any business test body execution.\n\nFix only collection-proven generated testcase-local defects: create the exact safe missing mapped test_*.py paths listed by the initial facts, or repair syntax, module path, missing symbol, circular import, fixture-name, decorator or parameterization inconsistencies. Inspect all affected importers and providers so the repair is cross-file consistent; do not create unrelated pytest scripts.\n\nPreserve final testcase/md/** semantics, every Case ID, Rule/Test Point binding, primary symbol, parameter ID, expected status/body/schema assertion, HTTP logging, redaction and truncation behavior.\n\nUse local edit only on assessment-listed paths; keep summaries short; never rewrite unrelated modules.\n\nDo not read task source/** or reinterpret requirements. Do not modify Markdown, conftest, pytest config, production code or dependencies.\n\nDo not add skip/skipif/xfail, remove tests, reduce collected items, loosen assertions, swallow exceptions, use try/except ImportError fallback, mutate sys.path/PYTHONPATH, or replace the real API with mocks.\n\nDo not execute pytest; the deterministic effective collection gate owns the final collection attempt."
|
|
274
299
|
},
|
|
275
300
|
{
|
|
276
301
|
"id": "effective-backend-pytest-collection-gate-shell",
|
|
@@ -319,8 +344,8 @@
|
|
|
319
344
|
".harness/dag-runs/**",
|
|
320
345
|
"artifacts/**"
|
|
321
346
|
],
|
|
322
|
-
"outputContract": "Run-owned reports/backend-test-traceability.md, reports/backend-test-markdown-pytest-correspondence.md
|
|
323
|
-
"subtask_prompt": "Deterministically scan only Markdown-mapped pytest scripts after the effective hash-bound collection gate. Keep the existing traceability/logging checks and produce a bidirectional Markdown module/Case/Test Point ↔ pytest file/primary symbol correspondence analysis. Map variant Test Points from stable parameter IDs, assertion Test Points from the primary symbol docstring, and cross-cutting Test Points from the primary symbol evidence binding. Report 1:1, 1:0, 1:N, 0:1, script/primary-symbol mismatch, missing Case ID, missing variant parameter IDs, missing assertion/cross-cutting bindings, duplicate modes and extra bindings.
|
|
347
|
+
"outputContract": "Run-owned reports/backend-test-traceability.md, reports/backend-test-markdown-pytest-correspondence.md, contracts/backend-test-markdown-pytest-correspondence-facts.json, reports/backend-test-scenario-param-consistency.md and contracts/backend-test-scenario-param-consistency-facts.json (initial+final) with optional repair audit; PASS/FAIL/UNAVAILABLE correspondence facts bound after effective collection.",
|
|
348
|
+
"subtask_prompt": "Deterministically scan only Markdown-mapped pytest scripts after the effective hash-bound collection gate. Keep the existing traceability/logging checks and produce a bidirectional Markdown module/Case/Test Point ↔ pytest file/primary symbol correspondence analysis. Map variant Test Points from stable parameter IDs, assertion Test Points from the primary symbol docstring, and cross-cutting Test Points from the primary symbol evidence binding. Report 1:1, 1:0, 1:N, 0:1, script/primary-symbol mismatch, missing Case ID, missing variant parameter IDs, missing assertion/cross-cutting bindings, duplicate modes and extra bindings. In the same shell, assess scenario-intent vs pytest.param literal features, apply at most one deterministic pre-execution scenario-param repair for repairable MISMATCH entries, reassess final consistency, and bind asset hashes for execute. Findings for correspondence remain advisory; residual scenario-param MISMATCH is advisory unless strictScenarioParamGate is enabled. Never block pytest solely on correspondence FAIL.",
|
|
324
349
|
"shell": {
|
|
325
350
|
"commands": [],
|
|
326
351
|
"backendTestPipeline": "markdown-traceability",
|
|
@@ -407,7 +432,7 @@
|
|
|
407
432
|
"artifacts/**"
|
|
408
433
|
],
|
|
409
434
|
"outputContract": "Final Markdown report and L-5 conclusion under docs/test-reports/**; the deterministic L-5 dashboard at reports/backend-test-l5-dashboard.html is the authoritative visualization and must be linked, not re-rendered; no JSON.",
|
|
410
|
-
"subtask_prompt": "Generate the final Markdown report only from authoritative run-owned artifacts. Read node 1 reports/backend-test-environment.md; node 4 backend-md-case-validation.md and backend-test-case-coverage-analysis.md; nodes 6/8 backend-test-pytest-collection initial/effective reports and facts; node 9 backend-test-traceability.md
|
|
435
|
+
"subtask_prompt": "Generate the final Markdown report only from authoritative run-owned artifacts. Read node 1 reports/backend-test-environment.md; node 4 backend-md-case-validation.md and backend-test-case-coverage-analysis.md; nodes 6/8 backend-test-pytest-collection initial/effective reports and facts; node 9 backend-test-traceability.md, backend-test-markdown-pytest-correspondence.md and backend-test-scenario-param-consistency.md; node 10 contracts/backend-test-case-manifest.json; and node 11 backend-test-result.json, backend-test-facts.md, backend-test-failure-analysis.md, pytest-html/HTML and L-5 dashboard. Do not use node 2/3/5 assistant prose as facts. Do not emit JSON.\n\nUse this exact human-facing section order: 测试结论 → 执行概览 → 质量校验 → 失败分析 → 风险与建议 → 证据与 L-5. Put the decision and key numbers first, use compact tables/bullets, and keep headings concise. Do not paste entire upstream reports, duplicate per-case tables already present in facts, or repeat the same evidence in multiple sections; link to paths/hashes and quote only the findings needed for the conclusion. Prefer linking reports/backend-test-failure-analysis.md for structured failure analysis rather than inventing classifications.\n\nOutput budget: list evidence paths first, then write a short fixed six-section report; never paste upstream full text into chat.\n\nThe L-5 metrics and visualization are produced deterministically by node 11 at reports/backend-test-l5-dashboard.html. Link to that dashboard as the authoritative L-5 view. Pytest execution facts come from node 11; coverage/correspondence numbers and materializationStatus come from node 10; collection authorization comes from nodes 6/8; detailed coverage findings come from node 4; detailed mapping findings come from node 9. Never recompute these values. If machine manifest and human reports disagree, report evidence inconsistency rather than silently choosing.\n\nAlways state the exact Coverage Scope classification, policy, affected operations, regression floor, completeness claim, PASS/FAIL/UNAVAILABLE status and findings from node 4 case validation + coverage, plus node 9 traceability + correspondence. Affected-scope or affected-operations-full coverage must never be described as whole-API completeness unless every operation is explicitly listed. Their FAIL status does not block pytest, but it must remain visible and must never be rewritten as PASS.\n\nInclude environment, case quality/review, automation mapping, exact pytest facts, failure classification/analysis, risks, regression recommendations, evidence paths/hashes, coverage availability, and L-5 READY/NOT READY. Distinguish Markdown Case count, primary pytest symbol count, collected pytest item count, variant/assertion/cross-cutting Test Point counts and execution amplification; never describe pytest item count as the number of business scenarios.\n\nNever override Shell/pytest-html facts. L-5 requires pass=100%, AC=100%, automation>=90%, line>=80%, branch>=70%, skipped=0 and no blocking Critical risk.\n\nWrite only under docs/test-reports/**."
|
|
411
436
|
}
|
|
412
437
|
],
|
|
413
438
|
"sourceBinding": {
|
|
@@ -136,7 +136,7 @@ agent-worker console serve --repo . --port 8790 # 兼容入口,等价于上
|
|
|
136
136
|
|
|
137
137
|
live run 先用 `loop-agent dag status --run-id <run-id>` 看 lifecycle 与 liveness;用 `loop-agent dag report --run-id <run-id> --markdown` 读 facts;失败/paused 用 `loop-agent dag doctor --run-id <run-id> --markdown`。生命周期对齐先只读运行 `loop-agent dag reconcile-run --run-id <run-id>`;只有 runner 已停止且 operator 明确提供 `--action supersede|abandon --reason "..."` 时才允许变更。失败 run 用 `loop-agent dag closeout-draft --run-id <run-id>` 生成 failure handoff,不要写成成功 closeout。
|
|
138
138
|
|
|
139
|
-
Operator 须持续监控 live run,直到 controller 报告 run 已结束(节点/流程终态如 `FINISHED`、`FAILED` 或 `partial_failed`),或 Decision Gate **需要 approve
|
|
139
|
+
Operator 须持续监控 live run,直到 controller 报告 run 已结束(节点/流程终态如 `FINISHED`、`FAILED` 或 `partial_failed`),或 Decision Gate **需要 approve**;不要在节点仍运行时假定完成。持续监视过程中,主会话可在合适节点(例如节点/rank 状态变化、进入 verify/closeout、出现 stall 嫌疑或需要 approve 时)向用户做简短进度汇报(当前节点、状态、是否有风险),避免长时间静默;汇报是告知,不是请求确认,不得因此停下流程。判活须组合 runner heartbeat、session events 与 `dag doctor` liveness/provider meaningful progress;Runner heartbeat 只证明 lease,alone ≠ progress,不得仅凭运行时长结束节点。exclusive writer(如 `implement-pi` / `repair-pi`)运行期间:主会话与其他 writer **不得并发修改工作区**,以免 write-guard 错误归因;只读 status/doctor/report/observe 与 approve/reject/resume CLI 仍允许。恢复:status/doctor/report → classify → reconcile/replan → CLI 重跑 → shell verify。**禁止**把主会话直接 Edit 业务代码当作恢复手段。
|
|
140
140
|
|
|
141
141
|
### 运行态与验证
|
|
142
142
|
|
package/harness.json
CHANGED
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
"pi": {
|
|
82
82
|
"description": "Pi planning, review, diagnosis, and bounded writing when DAG toolProfile=write",
|
|
83
83
|
"LOW": "minimax-m3",
|
|
84
|
-
"MED": "
|
|
85
|
-
"HIGH": "
|
|
84
|
+
"MED": { "model": "deepseek/deepseek-v4-flash", "thinking": "max" },
|
|
85
|
+
"HIGH": "grok-4.5"
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tea-agent/loop-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"loop-agent": "bin/loop-agent.js",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"lint": "tsc --noEmit",
|
|
52
52
|
"typecheck": "tsc --noEmit",
|
|
53
53
|
"test": "node scripts/run-tests.mjs",
|
|
54
|
+
"test:host": "vitest run test/init-upgrade.test.ts --maxWorkers=1 -t \"records and reuses|controller-authorized semantic merge|authority-sensitive\"",
|
|
54
55
|
"test:fast": "vitest run --config vitest.fast.config.ts",
|
|
55
56
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
56
57
|
"docs:dev": "npm --prefix website start",
|