@tea-agent/loop-agent 0.16.1-beta.2 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/AGENTS.md +4 -8
  2. package/CHANGELOG.md +55 -18
  3. package/README.md +76 -299
  4. package/dist/application/evaluation/alias.js +184 -0
  5. package/dist/application/evaluation/budget.js +192 -0
  6. package/dist/application/evaluation/campaign-hash.js +47 -0
  7. package/dist/application/evaluation/campaign-matrix.js +372 -0
  8. package/dist/application/evaluation/campaign-scorecard.js +135 -0
  9. package/dist/application/evaluation/campaign.js +370 -0
  10. package/dist/application/evaluation/candidate.js +23 -6
  11. package/dist/application/evaluation/corpus-hash.js +38 -0
  12. package/dist/application/evaluation/corpus.js +56 -0
  13. package/dist/application/evaluation/experiment.js +294 -0
  14. package/dist/application/evaluation/ignition.js +198 -0
  15. package/dist/application/evaluation/integrity-audit.js +162 -0
  16. package/dist/application/evaluation/outer-loop.js +132 -0
  17. package/dist/application/evaluation/pi-cell-executor.js +39 -0
  18. package/dist/application/evaluation/private-verifier.js +46 -0
  19. package/dist/application/evaluation/promotion-policy.js +151 -0
  20. package/dist/application/evaluation/proposer.js +98 -0
  21. package/dist/application/evaluation/types.js +522 -0
  22. package/dist/cli/command-definitions.js +19 -3
  23. package/dist/commands/dag-reconcile-run.js +3 -116
  24. package/dist/commands/eval.js +1176 -13
  25. package/dist/commands/init.js +7 -1
  26. package/dist/executors/dag-pi-executor.js +4 -44
  27. package/dist/executors/pi-sdk-executor.js +3 -3
  28. package/dist/executors/shell-executor.js +1 -1
  29. package/dist/infrastructure/evaluation/alias-store.js +199 -0
  30. package/dist/infrastructure/evaluation/campaign-store.js +154 -0
  31. package/dist/infrastructure/evaluation/corpus-store.js +181 -0
  32. package/dist/infrastructure/evaluation/experiment-store.js +124 -0
  33. package/dist/infrastructure/evaluation/ignition-store.js +82 -0
  34. package/dist/infrastructure/evaluation/private-verifier-store.js +145 -0
  35. package/dist/infrastructure/evaluation/proposer-store.js +78 -0
  36. package/dist/records/promotion.js +3 -1
  37. package/dist/worker/cli.js +83 -0
  38. package/dist/worker/delivery/git-transaction.js +75 -0
  39. package/dist/worker/delivery/verification-bundle.js +13 -2
  40. package/dist/worker/feature/review.js +3 -2
  41. package/dist/worker/observe/static/dag-helpers.js +0 -62
  42. package/dist/worker/observe/static/styles.css +18 -55
  43. package/dist/worker/observe/static/views/dag.js +13 -5
  44. package/dist/worker/outcomes/adapters.js +4 -1
  45. package/dist/worker/outcomes/declared-artifacts.js +103 -0
  46. package/dist/worker/outcomes/evidence-tokens.js +29 -0
  47. package/dist/worker/outcomes/gate.js +10 -11
  48. package/dist/worker/outcomes/projector.js +30 -4
  49. package/dist/worker/outcomes/types.js +3 -0
  50. package/dist/worker/pool/reconcile.js +285 -0
  51. package/dist/worker/run-task/run-task.js +81 -4
  52. package/dist/worker/runner/run-ready.js +25 -2
  53. package/dist/worker/task-graph/ready-planner.js +14 -8
  54. package/dist/worker/task-graph/task-graph-schema.js +5 -3
  55. package/dist/workflows/dag/budget-enforcement.js +67 -0
  56. package/dist/workflows/dag/context-policy.js +137 -0
  57. package/dist/workflows/dag/failure-routing.js +7 -0
  58. package/dist/workflows/dag/frontend-implementation-contract.js +0 -77
  59. package/dist/workflows/dag/init-hybrid.js +33 -53
  60. package/dist/workflows/dag/knowledge-curator.js +3 -0
  61. package/dist/workflows/dag/node-execution.js +11 -4
  62. package/dist/workflows/dag/prompt.js +1 -1
  63. package/dist/workflows/dag/reconcile-run.js +121 -0
  64. package/dist/workflows/dag/report.js +12 -0
  65. package/dist/workflows/dag/runner.js +43 -16
  66. package/dist/workflows/dag/skill-snapshot.js +11 -7
  67. package/dist/workflows/dag/types.js +18 -1
  68. package/dist/workflows/dag/validate.js +15 -1
  69. package/docs/README.md +3 -1
  70. package/docs/architecture/runtime-boundaries.md +3 -2
  71. package/docs/init-surface.manifest.json +4 -0
  72. package/docs/local-development-environment.md +52 -0
  73. package/docs/templates/agent-dag.schema.json +0 -5
  74. package/docs/templates/agent-dag.supervised-implementation.json +23 -4
  75. package/docs/templates/branch-merge-report.md +14 -0
  76. package/docs/templates/evaluation/campaign-budget-v1.json +12 -0
  77. package/docs/templates/evaluation/campaign-dogfood-v0.json +24 -0
  78. package/docs/templates/evaluation/campaign-evidence-v1.json +44 -0
  79. package/docs/templates/evaluation/context-policy-baseline-v1.json +17 -0
  80. package/docs/templates/evaluation/context-policy-role-specialized-v1.json +28 -0
  81. package/docs/templates/evaluation/corpus-dogfood-v0.manifest.json +118 -0
  82. package/docs/templates/evaluation/matrix-dag-dry-run-v1.json +21 -0
  83. package/docs/templates/evaluation/matrix-fixture-v1.json +10 -0
  84. package/docs/templates/evaluation/private-verifier-dogfood-v0.json +16 -0
  85. package/docs/templates/product-line/AGENTS.md +1 -0
  86. package/docs/templates/product-line/README.md +17 -0
  87. package/docs/templates/product-line/acceptance.yaml +9 -0
  88. package/docs/templates/product-line/feature.yaml +11 -0
  89. package/docs/templates/product-line/task-graph.yaml +8 -0
  90. package/docs/templates/product-line/task.yaml +4 -0
  91. package/package.json +2 -1
  92. package/skills/frontend-implementation/references/node-contracts.md +3 -3
  93. package/skills/loop-agent/references/command-reference.md +5 -0
  94. package/skills/loop-agent/references/hybrid-dag.md +3 -3
@@ -0,0 +1,118 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "corpusId": "corpus-dogfood-v0",
4
+ "createdAt": "2026-07-19T00:00:00.000Z",
5
+ "description": "W1.5 initial dogfood corpus contract: 15 heterogeneous tasks with public/private/held_out splits. Contract-only; not live campaign evidence.",
6
+ "tasks": [
7
+ {
8
+ "taskRef": "features/F-2026-001/login-flow",
9
+ "class": "fullstack",
10
+ "split": "public",
11
+ "seeds": [1, 2, 3],
12
+ "featureId": "F-2026-001",
13
+ "description": "Dogfood login Feature packet (public feedback allowed)."
14
+ },
15
+ {
16
+ "taskRef": "features/F-2026-002/profile-filter",
17
+ "class": "implement",
18
+ "split": "public",
19
+ "seeds": [1, 2],
20
+ "featureId": "F-2026-002",
21
+ "description": "Profile filter implementation path."
22
+ },
23
+ {
24
+ "taskRef": "features/F-2026-005/welcome-banner",
25
+ "class": "fullstack",
26
+ "split": "public",
27
+ "seeds": [1, 2, 3],
28
+ "featureId": "F-2026-005",
29
+ "description": "fullstack-v1 welcome sample (public)."
30
+ },
31
+ {
32
+ "taskRef": "synthetic/docs-agents-converge",
33
+ "class": "docs",
34
+ "split": "public",
35
+ "seeds": [1, 2],
36
+ "description": "Docs/AGENTS converge style task (synthetic contract slot)."
37
+ },
38
+ {
39
+ "taskRef": "synthetic/docs-changelog-summary",
40
+ "class": "docs",
41
+ "split": "public",
42
+ "seeds": [1, 2, 3],
43
+ "description": "Changelog-style documentation task."
44
+ },
45
+ {
46
+ "taskRef": "synthetic/frontend-welcome-render",
47
+ "class": "frontend",
48
+ "split": "public",
49
+ "seeds": [1, 2],
50
+ "description": "Frontend render/accessibility contract slot."
51
+ },
52
+ {
53
+ "taskRef": "features/F-2026-003/empty-profile-regression",
54
+ "class": "bugfix",
55
+ "split": "private",
56
+ "seeds": [1, 2, 3],
57
+ "featureId": "F-2026-003",
58
+ "description": "Empty profile id/displayName regression (private selection)."
59
+ },
60
+ {
61
+ "taskRef": "features/F-2026-004/versioned-bootstrap",
62
+ "class": "bootstrap",
63
+ "split": "private",
64
+ "seeds": [1, 2],
65
+ "featureId": "F-2026-004",
66
+ "description": "Versioned self-host bootstrap canary (private)."
67
+ },
68
+ {
69
+ "taskRef": "synthetic/backend-test-welcome-api",
70
+ "class": "backend-test",
71
+ "split": "private",
72
+ "seeds": [1, 2, 3],
73
+ "description": "Backend API test workflow contract slot."
74
+ },
75
+ {
76
+ "taskRef": "synthetic/refactor-outcome-tokens",
77
+ "class": "refactor",
78
+ "split": "private",
79
+ "seeds": [1, 2],
80
+ "description": "Bounded refactor around evidence token naming."
81
+ },
82
+ {
83
+ "taskRef": "synthetic/implement-ready-planner-gate",
84
+ "class": "implement",
85
+ "split": "private",
86
+ "seeds": [1, 2, 3],
87
+ "description": "Ready Planner artifact-gate implementation slot."
88
+ },
89
+ {
90
+ "taskRef": "synthetic/heldout-docs-handoff",
91
+ "class": "docs",
92
+ "split": "held_out",
93
+ "seeds": [1, 2],
94
+ "description": "Held-out docs/handoff generalization slot; never used for candidate generation."
95
+ },
96
+ {
97
+ "taskRef": "synthetic/heldout-bugfix-gate",
98
+ "class": "bugfix",
99
+ "split": "held_out",
100
+ "seeds": [1, 2, 3],
101
+ "description": "Held-out bugfix gate; promotion-only signal."
102
+ },
103
+ {
104
+ "taskRef": "synthetic/heldout-fullstack-smoke",
105
+ "class": "fullstack",
106
+ "split": "held_out",
107
+ "seeds": [1, 2],
108
+ "description": "Held-out fullstack smoke; not for public feedback."
109
+ },
110
+ {
111
+ "taskRef": "synthetic/heldout-bootstrap-slot",
112
+ "class": "bootstrap",
113
+ "split": "held_out",
114
+ "seeds": [1, 2, 3],
115
+ "description": "Held-out bootstrap identity/slot discipline."
116
+ }
117
+ ]
118
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "version": 3,
3
+ "title": "eval-matrix-cell-dry-run",
4
+ "runtimeContract": {
5
+ "schemaVersion": 1,
6
+ "agentRuntime": "pi-only",
7
+ "repairWriterProtocol": "explicit-node-v1"
8
+ },
9
+ "tasks": [
10
+ {
11
+ "id": "matrix-cell-static",
12
+ "depends_on": [],
13
+ "complexity": "LOW",
14
+ "executor": "static",
15
+ "subtask_prompt": "Matrix cell placeholder; evaluation binding is injected by campaign matrix.",
16
+ "static": {
17
+ "resultMarkdown": "matrix cell dry-run placeholder"
18
+ }
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "defaultVerifyPassed": false,
4
+ "results": [
5
+ {
6
+ "split": "public",
7
+ "verifyPassed": true
8
+ }
9
+ ]
10
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "privateVerifierId": "pv-dogfood-v0",
4
+ "createdAt": "2026-07-19T00:00:00.000Z",
5
+ "description": "M4 dogfood private verifier. Controller-only; never enter candidate contentRefs/prompts/skill snapshots.",
6
+ "checks": [
7
+ {
8
+ "checkId": "node-version-ok",
9
+ "kind": "shell",
10
+ "command": ["node", "-e", "process.exit(process.versions.node ? 0 : 1)"],
11
+ "cwd": ".",
12
+ "timeoutMs": 15000,
13
+ "expectedExitCode": 0
14
+ }
15
+ ]
16
+ }
@@ -4,5 +4,6 @@
4
4
  - Treat `constraints.allowed_paths` and `constraints.forbidden_paths` as machine-enforced write boundaries; review DAG writer `writeSet` before execution.
5
5
  - Advance only tasks whose dependencies are complete. Preserve failed run records; retries receive new worker run IDs.
6
6
  - A Ready task must have acceptance references, non-empty allowed/forbidden paths, and deterministic verification commands.
7
+ - For `fullstack-v1` packets (`feature.yaml`), every TaskSpec should declare `execution.workflow`; required ACs need implementation/verification refs, `required_evidence`, and integration policy. Parallel writers must not share overlapping `allowed_paths`.
7
8
  - QA records an independent verdict and evidence. Do not write `status: success` closeout until `qa_verdict: pass` and non-empty `qa_evidence` exist.
8
9
  - Human gates remain human decisions. Record owner, time, reason, evidence, and follow-up without rewriting failed history.
@@ -7,3 +7,20 @@ agent-worker task validate-feature <feature-dir>
7
7
  ```
8
8
 
9
9
  The validator checks acceptance ID uniqueness, task references and dependencies, cycles, TaskSpec/path/verification completeness, and QA evidence before a successful closeout.
10
+
11
+ ## Profiles
12
+
13
+ | Profile | How to declare | Behavior |
14
+ |---|---|---|
15
+ | `generic`(默认) | 省略 `feature.yaml`,或 `profile: generic` | 保持 legacy 校验;不强制 `execution.workflow` / 双覆盖 AC |
16
+ | `fullstack-v1` | `feature.yaml` 中 `profile: fullstack-v1` 并声明 `scope` | 强制显式 workflow、required AC 双覆盖、frontend-test 依赖、writer writeSet 串行等结构门禁 |
17
+
18
+ 端到端全栈 dogfood 样板见仓库 `features/F-2026-005/`(欢迎语链路:契约 → BE/FE 实现 → backend-test / frontend-test → Final Verification)。
19
+
20
+ ## Minimal files
21
+
22
+ - `feature.yaml`(可选;fullstack 必填)
23
+ - `requirement.md` / `design.md` / `test-plan.md`
24
+ - `acceptance.yaml`
25
+ - `tasks/task-graph.yaml` + `tasks/*.yaml`
26
+ - `links.md` / `closeout.yaml`(按交付阶段)
@@ -12,3 +12,12 @@ acceptance:
12
12
  expected_task_refs:
13
13
  - BE-001
14
14
  - QA-001
15
+ # fullstack-v1 required AC fields (optional for generic packets):
16
+ # implementation_task_refs:
17
+ # - BE-001
18
+ # verification_task_refs:
19
+ # - BE-TEST-001
20
+ # required_evidence:
21
+ # - backend-test-result-v1
22
+ # - shell_verification
23
+ # integration: real-required
@@ -0,0 +1,11 @@
1
+ schema_version: 1
2
+ feature_id: F-YYYY-NNN
3
+ # generic = legacy/simple packet (default when this file is absent)
4
+ # fullstack-v1 = enable structural gates for explicit workflows + dual-coverage ACs
5
+ profile: generic
6
+ # Uncomment and set true flags when profile is fullstack-v1:
7
+ # scope:
8
+ # backend: true
9
+ # frontend: true
10
+ # backendVerification: true
11
+ # frontendVerification: true
@@ -5,11 +5,19 @@ nodes:
5
5
  task: BE-001.yaml
6
6
  type: backend-feature
7
7
  depends_on: []
8
+ # Optional artifact-aware edges (Ready Planner envelope-level gate):
9
+ # produces:
10
+ # - kind: backend-impl
11
+ # schemaId: backend-impl-v1
8
12
  - id: QA-001
9
13
  task: QA-001.yaml
10
14
  type: qa-execute
11
15
  depends_on:
12
16
  - BE-001
17
+ # consumes:
18
+ # - kind: backend-impl
19
+ # schemaId: backend-impl-v1
20
+ # producerTaskId: BE-001
13
21
  parallel_policy:
14
22
  max_parallel_tasks: 2
15
23
  disallow_same_file_parallel_writes: true
@@ -30,6 +30,10 @@ constraints:
30
30
  - <protected/path/**>
31
31
  hard_constraints:
32
32
  - Do not access production secrets
33
+ # Explicit runtime workflow → taskKind. For fullstack-v1 packets this should be set
34
+ # on every TaskSpec. Allowed: agent-dag | frontend-implementation | backend-test | frontend-test
35
+ execution:
36
+ workflow: agent-dag
33
37
  verify:
34
38
  preset: standard
35
39
  mode: serial
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tea-agent/loop-agent",
3
- "version": "0.16.1-beta.2",
3
+ "version": "0.16.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "loop-agent": "bin/loop-agent.js",
@@ -14,6 +14,7 @@
14
14
  "docs/harness-methodology-tdd.md",
15
15
  "docs/harness-methodology-verification.md",
16
16
  "docs/harness-methodology-debugging.md",
17
+ "docs/local-development-environment.md",
17
18
  "docs/architecture/runtime-boundaries.md",
18
19
  "docs/architecture/README.md",
19
20
  "docs/architecture/system-overview.md",
@@ -6,10 +6,10 @@ Pre-write nodes are read-only. Preserve IDs, labels, commands, language, require
6
6
 
7
7
  - **`frontend-contract-pi`**: `Scope`, `Non-goals`, `Acceptance Criteria`, `UI States`, `Target Runtime Environment`, `Risks`, `Verification Expectations`. No guessed requirements.
8
8
  - **`frontend-scout-pi`**: routes, components, tokens, data/API/Mock, scripts, tests, assets. Fact vs inference vs gap. Knowledge base first; else search+read `<repoRoot>/openSpec/**` before repo fallback. Output stack, routes, components, styling, conventions, state/data, test entry points, reuse, risks.
9
- - **`frontend-mock-assess-pi` + gate**: declares `firstProtocolLine: "MOCK_STRATEGY:"`; canonical output first line
9
+ - **`frontend-mock-assess-pi` + gate**: first non-empty line
10
10
  `MOCK_STRATEGY: native|browser-intercept|request-adapter|not-needed|blocked`
11
- Pi output mapping promotes the first matching protocol line ahead of any preamble without inventing or replacing its value; missing, malformed, or blocked strategies still fail closed. Prefer native Mock; browser intercept only with existing e2e; request-adapter only for reversible local preview. Default `auto` may select `not-needed` when contract/scout evidence confirms no project Mock capability, without adding Mock files/deps, while keeping real requests default and recording the Real Integration Gap. Other `not-needed` cases need positive no-remote/stable-backend evidence; invalid when `frontendMock.policy=required`. `blocked` for missing/conflicting contracts, unsafe paths/deps, unread specs, production-default-on, unverifiable entrypoints. Output Mock Decision, API/spec/service evidence, backend readiness, selection evidence, endpoint/fixture matrix, activation, targets, production safety, verification plan, real-integration gap, blocking issues. Never invent fields, store secrets, comment real requests, import test mocks into production, or treat Mock as real integration. Gate uses `first-non-empty` only; never authorizes writes. Unsafe required contracts → no writer.
12
- - **`frontend-plan-pi` + design loop**: AC → steps, in-bound files, UI states, reuse, deps, activation/rollback, frozen verify entrypoints, real-integration gap. First gate: `VERDICT: pass|request-revision`. Pass may emit `PASS_NO_REVISION_NEEDED`; else full corrected plan without invented evidence. Final review rechecks plan/findings/revision/assessment/Mock safety. Only final `VERDICT: pass` authorizes writes; failure → replan/rerun (not dev-fix). The plan-pi prompt now includes the complete `frontend-implementation-contract-v1` JSON Schema loaded from the loop-agent package `docs/templates/` path, plus deterministic source binding, risk level, and allowed implementation targets. The model does not need to search or guess contract fields; `schemaId`, `targetFiles`, `requirementCoverage` are explicitly forbidden.
11
+ Prefer native Mock; browser intercept only with existing e2e; request-adapter only for reversible local preview. Default `auto` may select `not-needed` when contract/scout evidence confirms no project Mock capability, without adding Mock files/deps, while keeping real requests default and recording the Real Integration Gap. Other `not-needed` cases need positive no-remote/stable-backend evidence; invalid when `frontendMock.policy=required`. `blocked` for missing/conflicting contracts, unsafe paths/deps, unread specs, production-default-on, unverifiable entrypoints. Output Mock Decision, API/spec/service evidence, backend readiness, selection evidence, endpoint/fixture matrix, activation, targets, production safety, verification plan, real-integration gap, blocking issues. Never invent fields, store secrets, comment real requests, import test mocks into production, or treat Mock as real integration. Gate uses `first-non-empty` only; never authorizes writes. Unsafe required contracts → no writer.
12
+ - **`frontend-plan-pi` + design loop**: AC → steps, in-bound files, UI states, reuse, deps, activation/rollback, frozen verify entrypoints, real-integration gap. First gate: `VERDICT: pass|request-revision`. Pass may emit `PASS_NO_REVISION_NEEDED`; else full corrected plan without invented evidence. Final review rechecks plan/findings/revision/assessment/Mock safety. Only final `VERDICT: pass` authorizes writes; failure → replan/rerun (not dev-fix).
13
13
  - **`frontend-implement-pi`**: sole exclusive writer. Stay in `writeSet`; real requests default-on; Mock reversible, dev/test-only, production-off. Atomic handler/intercept/adapter with consumer+tests. Stop on forbidden paths or guesses. Output changed files, behavior, UI states, styling notes, verification attempted, residual risks. Optional mock-verify when frozen; static+behavior always; behavior must prove page consumption. Skipped-Mock `not-needed` keeps real integration pending unless the real backend path has fresh evidence.
14
14
 
15
15
  ## Contract / trace / stages (M1–M2)
@@ -466,6 +466,11 @@ agent-worker report metrics --repo <repo-root> --month <YYYY-MM> [--json]
466
466
  agent-worker task draft-followup <task-id> --worker-run-id <id> --feature-dir <feature-dir> --repo <repo-root> [--json]
467
467
  agent-worker feature approve-followup --feature-dir <feature-dir> --followup-id <id> --repo <repo-root> --owner <owner> [--dry-run] [--json]
468
468
  agent-worker task retry <task-id> --repo <repo-root> [--reason "<已修复的原因>"]
469
+ agent-worker task reconcile <task-id> --feature-id <feature-id> --worker-run-id <id> --dag-run-id <id> --action abandon --reason "<text>" --repo <repo-root> [--force-abandon-recoverable]
470
+ agent-worker pool mark-failed --feature-id <feature-id> --task-id <task-id> --worker-run-id <id> --reason "<text>" --repo <repo-root>
471
+ agent-worker pool doctor --repo <repo-root> [--json] [--mapping <file>]
472
+ agent-worker pool migrate-state --repo <repo-root> [--apply --owner <owner> --reason <reason>] [--mapping <file>] [--json]
473
+ agent-worker feature git advance-checkpoint --feature-id <feature-id> --reason "<text>" --repo <repo-root>
469
474
  agent-worker batch plan-ready --feature-dir <feature-dir> --repo <repo-root> [--limit <count>] [--json]
470
475
  agent-worker batch run-ready \
471
476
  --feature-dir <feature-dir> \ # 含 tasks/task-graph.yaml
@@ -99,7 +99,7 @@ contract-pi → scout-src ∥ scout-tests → plan-pi → write-set-audit-pi
99
99
  → write-set-gate-shell → implement-pi → soft-verify-shell → process-supervisor-pi → process-gate-shell
100
100
  → repair-pi → hard-verify-shell
101
101
  → [authority-surface-audit-pi → authority-surface-gate-shell] # 可选
102
- → review-pi → review-gate-shell → decision-pi → closeout-pi
102
+ → review-pi → review-verdict-recovery-pi → review-gate-shell → decision-pi → closeout-pi
103
103
  ```
104
104
 
105
105
  | Stage | 减少 main-session 工作的方式 |
@@ -115,9 +115,9 @@ contract-pi → scout-src ∥ scout-tests → plan-pi → write-set-audit-pi
115
115
  | `repair-pi` | supervisor 请求 revision 时在 repair `writeSet` 内 bounded exclusive fix |
116
116
  | `hard-verify-shell` | lint/typecheck + `HARNESS_ALLOW_ACTIVE_DAG_RUNS=1 check-repo.sh` fact |
117
117
  | `authority-surface-audit-pi` + `authority-surface-gate-shell` | 可选 permission/state/tool-exposure audit;仅 authority signal 或显式 `authority-surface-audit` marker 时插入;gate 仅接受 `VERDICT: pass` |
118
- | `review-pi` + `review-gate-shell` | Critical/Important → `request-revision`;node JSON `shell.verdictGate` block,除非 extracted verdict 行为 `VERDICT: pass` |
118
+ | `review-pi` + `review-verdict-recovery-pi` + `review-gate-shell` | Critical/Important → `request-revision`;recovery 只规范化 VERDICT 协议(不得从自然语言猜 pass);gate 只认 `review-verdict-recovery-pi` `VERDICT: pass` |
119
119
 
120
- **Verdict gate contract(`shell.verdictGate`)**:声明 `fromNodeId`、`accept[]`、可选 `label`、可选 `lineMode`。runner 展开为一条 shell command,从 injected current run directory 读 `$HARNESS_DAG_RUN_DIR/<fromNodeId>.json`,对 extracted `assistantText ?? stdout` verdict line 与 `accept[]` exact-match。默认 `lineMode` 为 `first-non-empty` 以兼容;需要固定非 `VERDICT:` 协议首行的 Pi 节点可显式声明 `firstProtocolLine`,executor 会把第一条匹配前缀的行提升为 canonical 首行,不匹配时不伪造。`frontend-mock-assess-pi` 用它固定 `MOCK_STRATEGY:`,gate 仍保持 `first-non-empty` exact-match。supervised gate 用 `first-verdict-line` 选 Pi 在 preamble 或常见整行 Markdown emphasis(如 `**VERDICT: pass**`)后第一条 normalized `VERDICT:` line。勿用 `result.summary.md`、grep VERDICT、latest-active-run discovery 或 multi-command stateful gate。`--strict-governance` 对 anti-pattern fail。supervisor 仍为 `executor: pi` 上的 `role: supervisor`。
120
+ **Verdict gate contract(`shell.verdictGate`)**:声明 `fromNodeId`、`accept[]`、可选 `label`、可选 `lineMode`。runner 展开为一条 shell command,从 injected current run directory 读 `$HARNESS_DAG_RUN_DIR/<fromNodeId>.json`,对 extracted `assistantText ?? stdout` verdict line 与 `accept[]` exact-match。默认 `lineMode` 为 `first-non-empty` 以兼容;supervised gate 用 `first-verdict-line` 选 Pi 在 preamble 或常见整行 Markdown emphasis(如 `**VERDICT: pass**`)后第一条 normalized `VERDICT:` line。勿用 `result.summary.md`、grep VERDICT、latest-active-run discovery 或 multi-command stateful gate。`--strict-governance` 对 anti-pattern fail。supervisor 仍为 `executor: pi` 上的 `role: supervisor`。
121
121
 
122
122
  **Repair artifact gate contract(`shell.repairArtifactGate`)**:声明 `fromNodeId`(supervisor artifact 节点)与 `repairNodeId`(承接修订的 Pi 修复节点)。runner **不再**按节点名(历史 `repair-cursor` / `repair-pi`)猜测 repair 节点:显式 `repairNodeId` 必须存在、直接 `depends_on` gate、且是受治理 Pi writer(`executor: pi`、`toolProfile: write`、`writePolicy: exclusive`、`allowedPaths`+`writeSet` 非空且 `writeSet` 不与 `forbiddenPaths` 冲突)。新生成的 supervised DAG 总是写入 `repairNodeId`;旧 DAG 缺失时只在能唯一、安全地推导出下游 Pi writer 时兼容,零个或多个候选、或候选不满足契约都在执行前 fail closed。validation 覆盖存在性、直接下游、writer 属性与路径边界。
123
123