@tea-agent/loop-agent 0.2.0 → 0.2.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 (58) hide show
  1. package/AGENTS.md +62 -45
  2. package/CHANGELOG.md +59 -43
  3. package/README.md +180 -179
  4. package/bin/loop-agent.js +21 -21
  5. package/dist/application/dag/generate-task-dag.js +3 -3
  6. package/dist/application/dag/run-dag.js +14 -1
  7. package/dist/application/dag/validate-dag.js +1 -0
  8. package/dist/commands/init.js +482 -459
  9. package/dist/workflows/dag/failure-routing.js +82 -0
  10. package/dist/workflows/dag/lifecycle.js +95 -3
  11. package/dist/workflows/dag/report.js +73 -1
  12. package/docs/README.md +47 -45
  13. package/docs/agent-dag-recovery-playbook.md +32 -6
  14. package/docs/agent-dag-runner.md +17 -17
  15. package/docs/architecture/runtime-boundaries.md +1 -1
  16. package/docs/cursor-executor-usage.md +5 -5
  17. package/docs/decisions/README.md +2 -2
  18. package/docs/design/README.md +24 -24
  19. package/docs/development-principles.md +50 -50
  20. package/docs/dynamic-workflow-dag-engine-roadmap.md +6 -6
  21. package/docs/exec-plans/README.md +4 -4
  22. package/docs/exec-plans/active/README.md +10 -9
  23. package/docs/exec-plans/completed/README.md +8 -8
  24. package/docs/feature-workflow.md +111 -109
  25. package/docs/harness-methodology-verification.md +18 -18
  26. package/docs/loop-agent-harness.md +36 -36
  27. package/docs/production-readiness.md +96 -0
  28. package/docs/progress/README.md +2 -2
  29. package/docs/reports/README.md +4 -2
  30. package/docs/templates/agent-dag-decision-gate-dogfood-report.md +1 -1
  31. package/docs/templates/agent-dag-process-supervisor.prompt.md +2 -2
  32. package/docs/templates/agent-dag-report.schema.json +33 -2
  33. package/docs/templates/agent-dag-review-verdict.prompt.md +1 -1
  34. package/docs/templates/agent-dag.base.json +195 -195
  35. package/docs/templates/agent-dag.final-verification.json +190 -190
  36. package/docs/templates/agent-dag.schema.json +17 -17
  37. package/docs/templates/agent-dag.supervised-implementation.json +500 -500
  38. package/docs/templates/hybrid-dag.json +193 -193
  39. package/docs/templates/production-readiness-checklist.md +57 -0
  40. package/docs/templates/progress-log.md +7 -7
  41. package/docs/templates/project-start-checklist.md +8 -8
  42. package/docs/templates/qa-report.md +17 -11
  43. package/docs/templates/sprint-contract.md +19 -19
  44. package/docs/verification-matrix.md +37 -26
  45. package/examples/example-dag.json +51 -51
  46. package/examples/hybrid-loop-agent-dag.json +194 -194
  47. package/harness.json +5 -5
  48. package/package.json +62 -62
  49. package/skills/loop-agent/SKILL.md +35 -35
  50. package/skills/loop-agent/references/command-reference.md +107 -65
  51. package/skills/loop-agent/references/harness-policy.md +30 -30
  52. package/skills/loop-agent/references/hybrid-dag.md +30 -30
  53. package/skills/loop-agent/references/model-routing.md +1 -1
  54. package/skills/loop-agent/references/orchestrator-and-interventions.md +1 -1
  55. package/skills/loop-agent/references/pi-prompt.md +9 -9
  56. package/skills/loop-agent/references/post-implementation-and-patterns.md +7 -7
  57. package/skills/loop-agent/references/task-workflow.md +19 -19
  58. package/skills/loop-agent/references/verification-and-failure-handling.md +36 -0
@@ -88,474 +88,474 @@ const COMPAT_PROMPTS = {
88
88
  ].join("\n"),
89
89
  };
90
90
  const GOVERNANCE_ROOT_TOKEN = "__LOOP_AGENT_GOVERNANCE_ROOT__";
91
- const INIT_CHECK_ENGINEERING_STRUCTURE_SH = `#!/usr/bin/env bash
92
- set -euo pipefail
93
-
94
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
95
- cd "\${ROOT_DIR}"
96
-
97
- required_paths=(
98
- "README.md"
99
- "harness.json"
100
- "AGENTS.md"
101
- "${GOVERNANCE_ROOT_TOKEN}/README.md"
102
- "${GOVERNANCE_ROOT_TOKEN}/development-principles.md"
103
- "${GOVERNANCE_ROOT_TOKEN}/feature-workflow.md"
104
- "${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md"
105
- "${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
106
- "${GOVERNANCE_ROOT_TOKEN}/templates"
107
- "skills/loop-agent/SKILL.md"
108
- ".harness/prompts/analyze.md"
109
- ".harness/prompts/plan.md"
110
- ".harness/tasks"
111
- ".harness/dag-runs/active"
112
- ".harness/dag-runs/completed"
113
- ".harness/dag-runs/paused"
114
- ".harness/runs/active"
115
- ".harness/runs/completed"
116
- ".harness/runs/failed"
117
- "scripts/check-engineering-structure.sh"
118
- "scripts/check-doc-index.sh"
119
- "scripts/check-doc-links.sh"
120
- "scripts/check-active-plan-status.sh"
121
- "scripts/check-exec-plan-index-sync.sh"
122
- "scripts/check-harness-runtime-clean.sh"
123
- "scripts/check-architecture-boundaries.sh"
124
- "scripts/check-skill-entry.sh"
125
- "scripts/check-repo.sh"
126
- "scripts/ci-governance.sh"
127
- "scripts/ci-tests.sh"
128
- "scripts/ci.sh"
129
- )
130
-
131
- missing=()
132
- for item in "\${required_paths[@]}"; do
133
- if [[ ! -e "\${item}" ]]; then
134
- missing+=("\${item}")
135
- fi
136
- done
137
-
138
- if (( \${#missing[@]} > 0 )); then
139
- echo "loop-agent 初始化检查失败,缺少必要路径:"
140
- for item in "\${missing[@]}"; do
141
- echo " - \${item}"
142
- done
143
- exit 1
144
- fi
145
-
146
- echo "loop-agent 工程结构检查通过"
91
+ const INIT_CHECK_ENGINEERING_STRUCTURE_SH = `#!/usr/bin/env bash
92
+ set -euo pipefail
93
+
94
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
95
+ cd "\${ROOT_DIR}"
96
+
97
+ required_paths=(
98
+ "README.md"
99
+ "harness.json"
100
+ "AGENTS.md"
101
+ "${GOVERNANCE_ROOT_TOKEN}/README.md"
102
+ "${GOVERNANCE_ROOT_TOKEN}/development-principles.md"
103
+ "${GOVERNANCE_ROOT_TOKEN}/feature-workflow.md"
104
+ "${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md"
105
+ "${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
106
+ "${GOVERNANCE_ROOT_TOKEN}/templates"
107
+ "skills/loop-agent/SKILL.md"
108
+ ".harness/prompts/analyze.md"
109
+ ".harness/prompts/plan.md"
110
+ ".harness/tasks"
111
+ ".harness/dag-runs/active"
112
+ ".harness/dag-runs/completed"
113
+ ".harness/dag-runs/paused"
114
+ ".harness/runs/active"
115
+ ".harness/runs/completed"
116
+ ".harness/runs/failed"
117
+ "scripts/check-engineering-structure.sh"
118
+ "scripts/check-doc-index.sh"
119
+ "scripts/check-doc-links.sh"
120
+ "scripts/check-active-plan-status.sh"
121
+ "scripts/check-exec-plan-index-sync.sh"
122
+ "scripts/check-harness-runtime-clean.sh"
123
+ "scripts/check-architecture-boundaries.sh"
124
+ "scripts/check-skill-entry.sh"
125
+ "scripts/check-repo.sh"
126
+ "scripts/ci-governance.sh"
127
+ "scripts/ci-tests.sh"
128
+ "scripts/ci.sh"
129
+ )
130
+
131
+ missing=()
132
+ for item in "\${required_paths[@]}"; do
133
+ if [[ ! -e "\${item}" ]]; then
134
+ missing+=("\${item}")
135
+ fi
136
+ done
137
+
138
+ if (( \${#missing[@]} > 0 )); then
139
+ echo "loop-agent 初始化检查失败,缺少必要路径:"
140
+ for item in "\${missing[@]}"; do
141
+ echo " - \${item}"
142
+ done
143
+ exit 1
144
+ fi
145
+
146
+ echo "loop-agent 工程结构检查通过"
147
147
  `;
148
- const INIT_CHECK_DOC_INDEX_SH = `#!/usr/bin/env bash
149
- set -euo pipefail
150
-
151
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
152
- cd "\${ROOT_DIR}"
153
-
154
- required_docs=(
155
- "${GOVERNANCE_ROOT_TOKEN}/README.md"
156
- "${GOVERNANCE_ROOT_TOKEN}/development-principles.md"
157
- "${GOVERNANCE_ROOT_TOKEN}/feature-workflow.md"
158
- "${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md"
159
- "${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
160
- "${GOVERNANCE_ROOT_TOKEN}/loop-agent-harness.md"
161
- "${GOVERNANCE_ROOT_TOKEN}/harness-methodology-tdd.md"
162
- "${GOVERNANCE_ROOT_TOKEN}/harness-methodology-verification.md"
163
- "${GOVERNANCE_ROOT_TOKEN}/harness-methodology-debugging.md"
164
- "${GOVERNANCE_ROOT_TOKEN}/templates"
165
- "${GOVERNANCE_ROOT_TOKEN}/exec-plans/active/README.md"
166
- "${GOVERNANCE_ROOT_TOKEN}/exec-plans/completed/README.md"
167
- "${GOVERNANCE_ROOT_TOKEN}/progress/README.md"
168
- "${GOVERNANCE_ROOT_TOKEN}/reports/README.md"
169
- "${GOVERNANCE_ROOT_TOKEN}/decisions/README.md"
170
- )
171
-
172
- missing=()
173
- for item in "\${required_docs[@]}"; do
174
- if [[ ! -e "\${item}" ]]; then
175
- missing+=("\${item}")
176
- fi
177
- done
178
-
179
- if (( \${#missing[@]} > 0 )); then
180
- echo "docs 索引检查失败,缺少必要文档或目录:" >&2
181
- for item in "\${missing[@]}"; do
182
- echo " - \${item}" >&2
183
- done
184
- exit 1
185
- fi
186
-
187
- echo "docs 索引检查通过"
148
+ const INIT_CHECK_DOC_INDEX_SH = `#!/usr/bin/env bash
149
+ set -euo pipefail
150
+
151
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
152
+ cd "\${ROOT_DIR}"
153
+
154
+ required_docs=(
155
+ "${GOVERNANCE_ROOT_TOKEN}/README.md"
156
+ "${GOVERNANCE_ROOT_TOKEN}/development-principles.md"
157
+ "${GOVERNANCE_ROOT_TOKEN}/feature-workflow.md"
158
+ "${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md"
159
+ "${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
160
+ "${GOVERNANCE_ROOT_TOKEN}/loop-agent-harness.md"
161
+ "${GOVERNANCE_ROOT_TOKEN}/harness-methodology-tdd.md"
162
+ "${GOVERNANCE_ROOT_TOKEN}/harness-methodology-verification.md"
163
+ "${GOVERNANCE_ROOT_TOKEN}/harness-methodology-debugging.md"
164
+ "${GOVERNANCE_ROOT_TOKEN}/templates"
165
+ "${GOVERNANCE_ROOT_TOKEN}/exec-plans/active/README.md"
166
+ "${GOVERNANCE_ROOT_TOKEN}/exec-plans/completed/README.md"
167
+ "${GOVERNANCE_ROOT_TOKEN}/progress/README.md"
168
+ "${GOVERNANCE_ROOT_TOKEN}/reports/README.md"
169
+ "${GOVERNANCE_ROOT_TOKEN}/decisions/README.md"
170
+ )
171
+
172
+ missing=()
173
+ for item in "\${required_docs[@]}"; do
174
+ if [[ ! -e "\${item}" ]]; then
175
+ missing+=("\${item}")
176
+ fi
177
+ done
178
+
179
+ if (( \${#missing[@]} > 0 )); then
180
+ echo "docs 索引检查失败,缺少必要文档或目录:" >&2
181
+ for item in "\${missing[@]}"; do
182
+ echo " - \${item}" >&2
183
+ done
184
+ exit 1
185
+ fi
186
+
187
+ echo "docs 索引检查通过"
188
188
  `;
189
- const INIT_CHECK_DOC_LINKS_SH = `#!/usr/bin/env bash
190
- set -euo pipefail
191
-
192
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
193
- cd "\${ROOT_DIR}"
194
-
195
- if [[ ! -d "${GOVERNANCE_ROOT_TOKEN}" ]]; then
196
- echo "docs 链接检查失败:缺少 ${GOVERNANCE_ROOT_TOKEN}/" >&2
197
- exit 1
198
- fi
199
-
200
- missing=()
201
- while IFS= read -r -d '' file; do
202
- while IFS= read -r link; do
203
- [[ -z "\${link}" ]] && continue
204
- [[ "\${link}" == http://* || "\${link}" == https://* || "\${link}" == mailto:* || "\${link}" == "#"* ]] && continue
205
- [[ "\${link}" == *"://"* ]] && continue
206
- target="\${link%%#*}"
207
- [[ -z "\${target}" ]] && continue
208
- [[ "\${target}" == /* ]] && continue
209
- base="$(dirname "\${file}")"
210
- if [[ ! -e "\${base}/\${target}" ]]; then
211
- missing+=("\${file}: \${link}")
212
- fi
213
- done < <(grep -Eo '\\[[^]]+\\]\\([^)]+\\)' "\${file}" | sed -E 's/^.*\\(([^)]+)\\)$/\\1/' || true)
214
- done < <(find "${GOVERNANCE_ROOT_TOKEN}" -type f -name '*.md' -print0)
215
-
216
- if (( \${#missing[@]} > 0 )); then
217
- echo "docs 链接检查失败:" >&2
218
- for item in "\${missing[@]}"; do
219
- echo " - \${item}" >&2
220
- done
221
- exit 1
222
- fi
223
-
224
- echo "docs 链接检查通过"
189
+ const INIT_CHECK_DOC_LINKS_SH = `#!/usr/bin/env bash
190
+ set -euo pipefail
191
+
192
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
193
+ cd "\${ROOT_DIR}"
194
+
195
+ if [[ ! -d "${GOVERNANCE_ROOT_TOKEN}" ]]; then
196
+ echo "docs 链接检查失败:缺少 ${GOVERNANCE_ROOT_TOKEN}/" >&2
197
+ exit 1
198
+ fi
199
+
200
+ missing=()
201
+ while IFS= read -r -d '' file; do
202
+ while IFS= read -r link; do
203
+ [[ -z "\${link}" ]] && continue
204
+ [[ "\${link}" == http://* || "\${link}" == https://* || "\${link}" == mailto:* || "\${link}" == "#"* ]] && continue
205
+ [[ "\${link}" == *"://"* ]] && continue
206
+ target="\${link%%#*}"
207
+ [[ -z "\${target}" ]] && continue
208
+ [[ "\${target}" == /* ]] && continue
209
+ base="$(dirname "\${file}")"
210
+ if [[ ! -e "\${base}/\${target}" ]]; then
211
+ missing+=("\${file}: \${link}")
212
+ fi
213
+ done < <(grep -Eo '\\[[^]]+\\]\\([^)]+\\)' "\${file}" | sed -E 's/^.*\\(([^)]+)\\)$/\\1/' || true)
214
+ done < <(find "${GOVERNANCE_ROOT_TOKEN}" -type f -name '*.md' -print0)
215
+
216
+ if (( \${#missing[@]} > 0 )); then
217
+ echo "docs 链接检查失败:" >&2
218
+ for item in "\${missing[@]}"; do
219
+ echo " - \${item}" >&2
220
+ done
221
+ exit 1
222
+ fi
223
+
224
+ echo "docs 链接检查通过"
225
225
  `;
226
- const INIT_CHECK_ACTIVE_PLAN_STATUS_SH = `#!/usr/bin/env bash
227
- set -euo pipefail
228
-
229
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
230
- cd "\${ROOT_DIR}"
231
-
232
- active_dir="${GOVERNANCE_ROOT_TOKEN}/exec-plans/active"
233
- [[ -d "\${active_dir}" ]] || { echo "active plan 检查失败:缺少 \${active_dir}" >&2; exit 1; }
234
-
235
- bad=()
236
- while IFS= read -r -d '' file; do
237
- name="$(basename "\${file}")"
238
- [[ "\${name}" == "README.md" ]] && continue
239
- if grep -Eiq 'status:[[:space:]]*(completed|done|closed)|状态[::][[:space:]]*(已完成|完成|关闭)' "\${file}"; then
240
- bad+=("\${file}")
241
- fi
242
- done < <(find "\${active_dir}" -maxdepth 1 -type f -name '*.md' -print0)
243
-
244
- if (( \${#bad[@]} > 0 )); then
245
- echo "active plan 状态检查失败:已完成计划不应留在 active 目录:" >&2
246
- for item in "\${bad[@]}"; do
247
- echo " - \${item}" >&2
248
- done
249
- exit 1
250
- fi
251
-
252
- echo "active plan 状态检查通过"
226
+ const INIT_CHECK_ACTIVE_PLAN_STATUS_SH = `#!/usr/bin/env bash
227
+ set -euo pipefail
228
+
229
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
230
+ cd "\${ROOT_DIR}"
231
+
232
+ active_dir="${GOVERNANCE_ROOT_TOKEN}/exec-plans/active"
233
+ [[ -d "\${active_dir}" ]] || { echo "active plan 检查失败:缺少 \${active_dir}" >&2; exit 1; }
234
+
235
+ bad=()
236
+ while IFS= read -r -d '' file; do
237
+ name="$(basename "\${file}")"
238
+ [[ "\${name}" == "README.md" ]] && continue
239
+ if grep -Eiq 'status:[[:space:]]*(completed|done|closed)|状态[::][[:space:]]*(已完成|完成|关闭)' "\${file}"; then
240
+ bad+=("\${file}")
241
+ fi
242
+ done < <(find "\${active_dir}" -maxdepth 1 -type f -name '*.md' -print0)
243
+
244
+ if (( \${#bad[@]} > 0 )); then
245
+ echo "active plan 状态检查失败:已完成计划不应留在 active 目录:" >&2
246
+ for item in "\${bad[@]}"; do
247
+ echo " - \${item}" >&2
248
+ done
249
+ exit 1
250
+ fi
251
+
252
+ echo "active plan 状态检查通过"
253
253
  `;
254
- const INIT_CHECK_EXEC_PLAN_INDEX_SYNC_SH = `#!/usr/bin/env bash
255
- set -euo pipefail
256
-
257
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
258
- cd "\${ROOT_DIR}"
259
-
260
- required=(
261
- "${GOVERNANCE_ROOT_TOKEN}/exec-plans/README.md"
262
- "${GOVERNANCE_ROOT_TOKEN}/exec-plans/active/README.md"
263
- "${GOVERNANCE_ROOT_TOKEN}/exec-plans/completed/README.md"
264
- )
265
-
266
- for item in "\${required[@]}"; do
267
- if [[ ! -f "\${item}" ]]; then
268
- echo "exec-plan 索引同步检查失败:缺少 \${item}" >&2
269
- exit 1
270
- fi
271
- done
272
-
273
- echo "exec-plan 索引同步检查通过"
254
+ const INIT_CHECK_EXEC_PLAN_INDEX_SYNC_SH = `#!/usr/bin/env bash
255
+ set -euo pipefail
256
+
257
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
258
+ cd "\${ROOT_DIR}"
259
+
260
+ required=(
261
+ "${GOVERNANCE_ROOT_TOKEN}/exec-plans/README.md"
262
+ "${GOVERNANCE_ROOT_TOKEN}/exec-plans/active/README.md"
263
+ "${GOVERNANCE_ROOT_TOKEN}/exec-plans/completed/README.md"
264
+ )
265
+
266
+ for item in "\${required[@]}"; do
267
+ if [[ ! -f "\${item}" ]]; then
268
+ echo "exec-plan 索引同步检查失败:缺少 \${item}" >&2
269
+ exit 1
270
+ fi
271
+ done
272
+
273
+ echo "exec-plan 索引同步检查通过"
274
274
  `;
275
- const INIT_CHECK_HARNESS_RUNTIME_CLEAN_SH = `#!/usr/bin/env bash
276
- set -euo pipefail
277
-
278
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
279
- cd "\${ROOT_DIR}"
280
-
281
- failures=()
282
-
283
- count_entries() {
284
- local dir="$1"
285
- if [[ ! -d "\${dir}" ]]; then
286
- echo 0
287
- return
288
- fi
289
- find "\${dir}" -mindepth 1 -maxdepth 1 ! -name .gitkeep | wc -l | tr -d ' '
290
- }
291
-
292
- if [[ "\${HARNESS_ALLOW_ACTIVE_DAG_RUNS:-}" != "1" ]]; then
293
- active_dag_count="$(count_entries ".harness/dag-runs/active")"
294
- [[ "\${active_dag_count}" == "0" ]] || failures+=(".harness/dag-runs/active contains \${active_dag_count} entries")
295
- fi
296
-
297
- if [[ "\${HARNESS_ALLOW_ACTIVE_TOOL_RUNS:-\${HARNESS_ALLOW_ACTIVE_ONE_SHOT_RUNS:-}}" != "1" ]]; then
298
- active_run_count="$(count_entries ".harness/runs/active")"
299
- [[ "\${active_run_count}" == "0" ]] || failures+=(".harness/runs/active contains \${active_run_count} entries")
300
- fi
301
-
302
- if [[ -d artifacts ]]; then
303
- artifact_count="$(find artifacts -mindepth 1 -maxdepth 1 ! -name .gitkeep | wc -l | tr -d ' ')"
304
- [[ "\${artifact_count}" == "0" ]] || failures+=("root artifacts/ contains \${artifact_count} entries; use docs/reports or .harness run artifacts")
305
- fi
306
-
307
- if (( \${#failures[@]} > 0 )); then
308
- echo "[HARNESS RUNTIME DIRTY]" >&2
309
- for item in "\${failures[@]}"; do
310
- echo " - \${item}" >&2
311
- done
312
- exit 1
313
- fi
314
-
315
- echo "harness runtime clean check passed"
275
+ const INIT_CHECK_HARNESS_RUNTIME_CLEAN_SH = `#!/usr/bin/env bash
276
+ set -euo pipefail
277
+
278
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
279
+ cd "\${ROOT_DIR}"
280
+
281
+ failures=()
282
+
283
+ count_entries() {
284
+ local dir="$1"
285
+ if [[ ! -d "\${dir}" ]]; then
286
+ echo 0
287
+ return
288
+ fi
289
+ find "\${dir}" -mindepth 1 -maxdepth 1 ! -name .gitkeep | wc -l | tr -d ' '
290
+ }
291
+
292
+ if [[ "\${HARNESS_ALLOW_ACTIVE_DAG_RUNS:-}" != "1" ]]; then
293
+ active_dag_count="$(count_entries ".harness/dag-runs/active")"
294
+ [[ "\${active_dag_count}" == "0" ]] || failures+=(".harness/dag-runs/active contains \${active_dag_count} entries")
295
+ fi
296
+
297
+ if [[ "\${HARNESS_ALLOW_ACTIVE_TOOL_RUNS:-\${HARNESS_ALLOW_ACTIVE_ONE_SHOT_RUNS:-}}" != "1" ]]; then
298
+ active_run_count="$(count_entries ".harness/runs/active")"
299
+ [[ "\${active_run_count}" == "0" ]] || failures+=(".harness/runs/active contains \${active_run_count} entries")
300
+ fi
301
+
302
+ if [[ -d artifacts ]]; then
303
+ artifact_count="$(find artifacts -mindepth 1 -maxdepth 1 ! -name .gitkeep | wc -l | tr -d ' ')"
304
+ [[ "\${artifact_count}" == "0" ]] || failures+=("root artifacts/ contains \${artifact_count} entries; use docs/reports or .harness run artifacts")
305
+ fi
306
+
307
+ if (( \${#failures[@]} > 0 )); then
308
+ echo "[HARNESS RUNTIME DIRTY]" >&2
309
+ for item in "\${failures[@]}"; do
310
+ echo " - \${item}" >&2
311
+ done
312
+ exit 1
313
+ fi
314
+
315
+ echo "harness runtime clean check passed"
316
316
  `;
317
- const INIT_CHECK_ARCHITECTURE_BOUNDARIES_SH = `#!/usr/bin/env bash
318
- set -euo pipefail
319
-
320
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
321
- cd "\${ROOT_DIR}"
322
-
323
- boundary_doc="${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
324
- if [[ ! -f "\${boundary_doc}" ]]; then
325
- echo "architecture boundary 检查失败:缺少 \${boundary_doc}" >&2
326
- exit 1
327
- fi
328
-
329
- violations=()
330
-
331
- check_ts_import_boundary() {
332
- local from_dir="$1"
333
- local forbidden_dir="$2"
334
- local label="$3"
335
- [[ -d "\${from_dir}" && -d "\${forbidden_dir}" ]] || return 0
336
- while IFS= read -r -d '' file; do
337
- if grep -Eq "from ['\\\"][^'\\\"]*\${forbidden_dir}/|import\\(['\\\"][^'\\\"]*\${forbidden_dir}/|require\\(['\\\"][^'\\\"]*\${forbidden_dir}/" "\${file}"; then
338
- violations+=("\${label}: \${file} imports \${forbidden_dir}")
339
- fi
340
- done < <(find "\${from_dir}" -type f \\( -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' -o -name '*.mjs' -o -name '*.cjs' \\) -print0)
341
- }
342
-
343
- # These checks are intentionally optional and stack-agnostic. They activate only
344
- # when a target repository has recognizable source directories.
345
- check_ts_import_boundary "src/workflows" "src/commands" "workflow-runtime"
346
- check_ts_import_boundary "src/executors" "src/commands" "executors"
347
- check_ts_import_boundary "src/domain" "src/infrastructure" "domain"
348
-
349
- if (( \${#violations[@]} > 0 )); then
350
- echo "architecture boundary 检查失败:" >&2
351
- for item in "\${violations[@]}"; do
352
- echo " - \${item}" >&2
353
- done
354
- echo "请更新 \${boundary_doc} 中的层边界,或修正反向依赖。" >&2
355
- exit 1
356
- fi
357
-
358
- echo "architecture boundary 检查通过"
317
+ const INIT_CHECK_ARCHITECTURE_BOUNDARIES_SH = `#!/usr/bin/env bash
318
+ set -euo pipefail
319
+
320
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
321
+ cd "\${ROOT_DIR}"
322
+
323
+ boundary_doc="${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
324
+ if [[ ! -f "\${boundary_doc}" ]]; then
325
+ echo "architecture boundary 检查失败:缺少 \${boundary_doc}" >&2
326
+ exit 1
327
+ fi
328
+
329
+ violations=()
330
+
331
+ check_ts_import_boundary() {
332
+ local from_dir="$1"
333
+ local forbidden_dir="$2"
334
+ local label="$3"
335
+ [[ -d "\${from_dir}" && -d "\${forbidden_dir}" ]] || return 0
336
+ while IFS= read -r -d '' file; do
337
+ if grep -Eq "from ['\\\"][^'\\\"]*\${forbidden_dir}/|import\\(['\\\"][^'\\\"]*\${forbidden_dir}/|require\\(['\\\"][^'\\\"]*\${forbidden_dir}/" "\${file}"; then
338
+ violations+=("\${label}: \${file} imports \${forbidden_dir}")
339
+ fi
340
+ done < <(find "\${from_dir}" -type f \\( -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' -o -name '*.mjs' -o -name '*.cjs' \\) -print0)
341
+ }
342
+
343
+ # These checks are intentionally optional and stack-agnostic. They activate only
344
+ # when a target repository has recognizable source directories.
345
+ check_ts_import_boundary "src/workflows" "src/commands" "workflow-runtime"
346
+ check_ts_import_boundary "src/executors" "src/commands" "executors"
347
+ check_ts_import_boundary "src/domain" "src/infrastructure" "domain"
348
+
349
+ if (( \${#violations[@]} > 0 )); then
350
+ echo "architecture boundary 检查失败:" >&2
351
+ for item in "\${violations[@]}"; do
352
+ echo " - \${item}" >&2
353
+ done
354
+ echo "请更新 \${boundary_doc} 中的层边界,或修正反向依赖。" >&2
355
+ exit 1
356
+ fi
357
+
358
+ echo "architecture boundary 检查通过"
359
359
  `;
360
- const INIT_CHECK_SKILL_ENTRY_SH = `#!/usr/bin/env bash
361
- set -euo pipefail
362
-
363
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
364
- cd "\${ROOT_DIR}"
365
-
366
- skill_md="skills/loop-agent/SKILL.md"
367
- if [[ ! -f "\${skill_md}" ]]; then
368
- echo "skill entry 检查失败:缺少 \${skill_md}" >&2
369
- exit 1
370
- fi
371
-
372
- required_refs=(
373
- "references/harness-policy.md"
374
- "references/hybrid-dag.md"
375
- "references/verification-and-failure-handling.md"
376
- "references/command-reference.md"
377
- )
378
-
379
- missing=()
380
- for ref in "\${required_refs[@]}"; do
381
- [[ -f "skills/loop-agent/\${ref}" ]] || missing+=("\${ref}")
382
- done
383
-
384
- while IFS= read -r ref; do
385
- [[ -z "\${ref}" ]] && continue
386
- [[ -f "skills/loop-agent/\${ref}" ]] || missing+=("\${ref}")
387
- done < <(grep -Eo 'references/[A-Za-z0-9._/-]+\\.md' "\${skill_md}" | sort -u || true)
388
-
389
- if (( \${#missing[@]} > 0 )); then
390
- echo "skill entry 检查失败:引用的 reference 文件不存在:" >&2
391
- printf ' - %s\\n' "\${missing[@]}" >&2
392
- exit 1
393
- fi
394
-
395
- line_count="$(wc -l < "\${skill_md}" | tr -d ' ')"
396
- if [[ "\${line_count}" =~ ^[0-9]+$ && "\${line_count}" -gt 220 ]]; then
397
- echo "skill entry 检查警告:\${skill_md} 行数为 \${line_count},建议保持入口精简并把细节放入 references/" >&2
398
- fi
399
-
400
- echo "skill entry 检查通过:references ok, lines=\${line_count}"
360
+ const INIT_CHECK_SKILL_ENTRY_SH = `#!/usr/bin/env bash
361
+ set -euo pipefail
362
+
363
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
364
+ cd "\${ROOT_DIR}"
365
+
366
+ skill_md="skills/loop-agent/SKILL.md"
367
+ if [[ ! -f "\${skill_md}" ]]; then
368
+ echo "skill entry 检查失败:缺少 \${skill_md}" >&2
369
+ exit 1
370
+ fi
371
+
372
+ required_refs=(
373
+ "references/harness-policy.md"
374
+ "references/hybrid-dag.md"
375
+ "references/verification-and-failure-handling.md"
376
+ "references/command-reference.md"
377
+ )
378
+
379
+ missing=()
380
+ for ref in "\${required_refs[@]}"; do
381
+ [[ -f "skills/loop-agent/\${ref}" ]] || missing+=("\${ref}")
382
+ done
383
+
384
+ while IFS= read -r ref; do
385
+ [[ -z "\${ref}" ]] && continue
386
+ [[ -f "skills/loop-agent/\${ref}" ]] || missing+=("\${ref}")
387
+ done < <(grep -Eo 'references/[A-Za-z0-9._/-]+\\.md' "\${skill_md}" | sort -u || true)
388
+
389
+ if (( \${#missing[@]} > 0 )); then
390
+ echo "skill entry 检查失败:引用的 reference 文件不存在:" >&2
391
+ printf ' - %s\\n' "\${missing[@]}" >&2
392
+ exit 1
393
+ fi
394
+
395
+ line_count="$(wc -l < "\${skill_md}" | tr -d ' ')"
396
+ if [[ "\${line_count}" =~ ^[0-9]+$ && "\${line_count}" -gt 220 ]]; then
397
+ echo "skill entry 检查警告:\${skill_md} 行数为 \${line_count},建议保持入口精简并把细节放入 references/" >&2
398
+ fi
399
+
400
+ echo "skill entry 检查通过:references ok, lines=\${line_count}"
401
401
  `;
402
- const INIT_CHECK_REPO_SH = `#!/usr/bin/env bash
403
- set -euo pipefail
404
-
405
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
406
- cd "\${ROOT_DIR}"
407
-
408
- checks=(
409
- "scripts/check-engineering-structure.sh"
410
- "scripts/check-doc-index.sh"
411
- "scripts/check-doc-links.sh"
412
- "scripts/check-active-plan-status.sh"
413
- "scripts/check-exec-plan-index-sync.sh"
414
- "scripts/check-harness-runtime-clean.sh"
415
- "scripts/check-architecture-boundaries.sh"
416
- "scripts/check-skill-entry.sh"
417
- )
418
-
419
- for check in "\${checks[@]}"; do
420
- echo "==> bash \${check}"
421
- bash "\${check}"
422
- echo
423
- done
424
-
425
- echo "仓库治理检查全部通过"
402
+ const INIT_CHECK_REPO_SH = `#!/usr/bin/env bash
403
+ set -euo pipefail
404
+
405
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
406
+ cd "\${ROOT_DIR}"
407
+
408
+ checks=(
409
+ "scripts/check-engineering-structure.sh"
410
+ "scripts/check-doc-index.sh"
411
+ "scripts/check-doc-links.sh"
412
+ "scripts/check-active-plan-status.sh"
413
+ "scripts/check-exec-plan-index-sync.sh"
414
+ "scripts/check-harness-runtime-clean.sh"
415
+ "scripts/check-architecture-boundaries.sh"
416
+ "scripts/check-skill-entry.sh"
417
+ )
418
+
419
+ for check in "\${checks[@]}"; do
420
+ echo "==> bash \${check}"
421
+ bash "\${check}"
422
+ echo
423
+ done
424
+
425
+ echo "仓库治理检查全部通过"
426
426
  `;
427
- const INIT_CI_GOVERNANCE_SH = `#!/usr/bin/env bash
428
- set -euo pipefail
429
-
430
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
431
- cd "\${ROOT_DIR}"
432
-
433
- bash scripts/check-repo.sh
427
+ const INIT_CI_GOVERNANCE_SH = `#!/usr/bin/env bash
428
+ set -euo pipefail
429
+
430
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
431
+ cd "\${ROOT_DIR}"
432
+
433
+ bash scripts/check-repo.sh
434
434
  `;
435
- const INIT_CI_TESTS_SH = `#!/usr/bin/env bash
436
- set -euo pipefail
437
-
438
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
439
- cd "\${ROOT_DIR}"
440
-
441
- ran=0
442
- notes=()
443
-
444
- run_cmd() {
445
- echo "==> $*"
446
- "$@"
447
- ran=1
448
- }
449
-
450
- run_bash() {
451
- echo "==> $*"
452
- bash -lc "$*"
453
- ran=1
454
- }
455
-
456
- has_make_target() {
457
- local target="$1"
458
- [[ -f Makefile || -f makefile ]] || return 1
459
- grep -Eq "^[[:alnum:]_.-]*\${target}[[:alnum:]_.-]*:" Makefile makefile 2>/dev/null
460
- }
461
-
462
- has_npm_script() {
463
- local script="$1"
464
- [[ -f package.json ]] || return 1
465
- command -v node >/dev/null 2>&1 || return 1
466
- node -e "const fs=require('fs'); const p=JSON.parse(fs.readFileSync('package.json','utf8')); process.exit(p.scripts && p.scripts[process.argv[1]] ? 0 : 1)" "\${script}" >/dev/null 2>&1
467
- }
468
-
469
- if [[ -f package.json ]]; then
470
- if command -v npm >/dev/null 2>&1; then
471
- for script in lint typecheck test build; do
472
- if has_npm_script "\${script}"; then
473
- run_cmd npm run "\${script}"
474
- fi
475
- done
476
- else
477
- notes+=("package.json exists but npm is not available")
478
- fi
479
- fi
480
-
481
- if has_make_target verify; then
482
- run_cmd make verify
483
- elif has_make_target test; then
484
- run_cmd make test
485
- fi
486
-
487
- if [[ -f go.mod ]]; then
488
- if command -v go >/dev/null 2>&1; then
489
- run_cmd go test ./...
490
- else
491
- notes+=("go.mod exists but go is not available")
492
- fi
493
- fi
494
-
495
- if [[ -f Cargo.toml ]]; then
496
- if command -v cargo >/dev/null 2>&1; then
497
- run_cmd cargo test
498
- else
499
- notes+=("Cargo.toml exists but cargo is not available")
500
- fi
501
- fi
502
-
503
- if [[ -f pyproject.toml || -f pytest.ini || -f tox.ini ]]; then
504
- if command -v pytest >/dev/null 2>&1; then
505
- run_cmd pytest
506
- elif command -v tox >/dev/null 2>&1 && [[ -f tox.ini ]]; then
507
- run_cmd tox
508
- else
509
- notes+=("Python project metadata found but pytest/tox is not available")
510
- fi
511
- fi
512
-
513
- if [[ -f pom.xml ]]; then
514
- if command -v mvn >/dev/null 2>&1; then
515
- run_cmd mvn test
516
- else
517
- notes+=("pom.xml exists but mvn is not available")
518
- fi
519
- fi
520
-
521
- if [[ -f build.gradle || -f build.gradle.kts || -f settings.gradle || -f settings.gradle.kts ]]; then
522
- if [[ -x ./gradlew ]]; then
523
- run_cmd ./gradlew test
524
- elif command -v gradle >/dev/null 2>&1; then
525
- run_cmd gradle test
526
- else
527
- notes+=("Gradle project metadata found but gradle/gradlew is not available")
528
- fi
529
- fi
530
-
531
- if compgen -G "*.sln" >/dev/null || compgen -G "*.csproj" >/dev/null; then
532
- if command -v dotnet >/dev/null 2>&1; then
533
- run_cmd dotnet test
534
- else
535
- notes+=(".NET project metadata found but dotnet is not available")
536
- fi
537
- fi
538
-
539
- if (( ran == 0 )); then
540
- echo "未检测到可安全自动运行的项目测试入口。"
541
- echo "loop-agent 治理检查仍可运行;请让初始化模型根据目标项目技术栈补充 scripts/ci-tests.sh 与 docs/verification-matrix.md。"
542
- fi
543
-
544
- if (( \${#notes[@]} > 0 )); then
545
- echo "项目验证探测备注:"
546
- for note in "\${notes[@]}"; do
547
- echo " - \${note}"
548
- done
549
- fi
435
+ const INIT_CI_TESTS_SH = `#!/usr/bin/env bash
436
+ set -euo pipefail
437
+
438
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
439
+ cd "\${ROOT_DIR}"
440
+
441
+ ran=0
442
+ notes=()
443
+
444
+ run_cmd() {
445
+ echo "==> $*"
446
+ "$@"
447
+ ran=1
448
+ }
449
+
450
+ run_bash() {
451
+ echo "==> $*"
452
+ bash -lc "$*"
453
+ ran=1
454
+ }
455
+
456
+ has_make_target() {
457
+ local target="$1"
458
+ [[ -f Makefile || -f makefile ]] || return 1
459
+ grep -Eq "^[[:alnum:]_.-]*\${target}[[:alnum:]_.-]*:" Makefile makefile 2>/dev/null
460
+ }
461
+
462
+ has_npm_script() {
463
+ local script="$1"
464
+ [[ -f package.json ]] || return 1
465
+ command -v node >/dev/null 2>&1 || return 1
466
+ node -e "const fs=require('fs'); const p=JSON.parse(fs.readFileSync('package.json','utf8')); process.exit(p.scripts && p.scripts[process.argv[1]] ? 0 : 1)" "\${script}" >/dev/null 2>&1
467
+ }
468
+
469
+ if [[ -f package.json ]]; then
470
+ if command -v npm >/dev/null 2>&1; then
471
+ for script in lint typecheck test build; do
472
+ if has_npm_script "\${script}"; then
473
+ run_cmd npm run "\${script}"
474
+ fi
475
+ done
476
+ else
477
+ notes+=("package.json exists but npm is not available")
478
+ fi
479
+ fi
480
+
481
+ if has_make_target verify; then
482
+ run_cmd make verify
483
+ elif has_make_target test; then
484
+ run_cmd make test
485
+ fi
486
+
487
+ if [[ -f go.mod ]]; then
488
+ if command -v go >/dev/null 2>&1; then
489
+ run_cmd go test ./...
490
+ else
491
+ notes+=("go.mod exists but go is not available")
492
+ fi
493
+ fi
494
+
495
+ if [[ -f Cargo.toml ]]; then
496
+ if command -v cargo >/dev/null 2>&1; then
497
+ run_cmd cargo test
498
+ else
499
+ notes+=("Cargo.toml exists but cargo is not available")
500
+ fi
501
+ fi
502
+
503
+ if [[ -f pyproject.toml || -f pytest.ini || -f tox.ini ]]; then
504
+ if command -v pytest >/dev/null 2>&1; then
505
+ run_cmd pytest
506
+ elif command -v tox >/dev/null 2>&1 && [[ -f tox.ini ]]; then
507
+ run_cmd tox
508
+ else
509
+ notes+=("Python project metadata found but pytest/tox is not available")
510
+ fi
511
+ fi
512
+
513
+ if [[ -f pom.xml ]]; then
514
+ if command -v mvn >/dev/null 2>&1; then
515
+ run_cmd mvn test
516
+ else
517
+ notes+=("pom.xml exists but mvn is not available")
518
+ fi
519
+ fi
520
+
521
+ if [[ -f build.gradle || -f build.gradle.kts || -f settings.gradle || -f settings.gradle.kts ]]; then
522
+ if [[ -x ./gradlew ]]; then
523
+ run_cmd ./gradlew test
524
+ elif command -v gradle >/dev/null 2>&1; then
525
+ run_cmd gradle test
526
+ else
527
+ notes+=("Gradle project metadata found but gradle/gradlew is not available")
528
+ fi
529
+ fi
530
+
531
+ if compgen -G "*.sln" >/dev/null || compgen -G "*.csproj" >/dev/null; then
532
+ if command -v dotnet >/dev/null 2>&1; then
533
+ run_cmd dotnet test
534
+ else
535
+ notes+=(".NET project metadata found but dotnet is not available")
536
+ fi
537
+ fi
538
+
539
+ if (( ran == 0 )); then
540
+ echo "未检测到可安全自动运行的项目测试入口。"
541
+ echo "loop-agent 治理检查仍可运行;请让初始化模型根据目标项目技术栈补充 scripts/ci-tests.sh 与 docs/verification-matrix.md。"
542
+ fi
543
+
544
+ if (( \${#notes[@]} > 0 )); then
545
+ echo "项目验证探测备注:"
546
+ for note in "\${notes[@]}"; do
547
+ echo " - \${note}"
548
+ done
549
+ fi
550
550
  `;
551
- const INIT_CI_SH = `#!/usr/bin/env bash
552
- set -euo pipefail
553
-
554
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
555
- cd "\${ROOT_DIR}"
556
-
557
- bash scripts/ci-governance.sh
558
- bash scripts/ci-tests.sh
551
+ const INIT_CI_SH = `#!/usr/bin/env bash
552
+ set -euo pipefail
553
+
554
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
555
+ cd "\${ROOT_DIR}"
556
+
557
+ bash scripts/ci-governance.sh
558
+ bash scripts/ci-tests.sh
559
559
  `;
560
560
  const INIT_SCRIPT_FILES = {
561
561
  "scripts/check-engineering-structure.sh": INIT_CHECK_ENGINEERING_STRUCTURE_SH,
@@ -621,6 +621,7 @@ function buildManagedAgentsBlock(input) {
621
621
  "- 实现前先搜索现有代码、文档、脚本和测试,避免重复造轮子。",
622
622
  "- Shell 验证是完成依据;模型建议不能替代命令证据。",
623
623
  "- 保留无关的用户改动,不要回退自己没有做的修改。",
624
+ "- 委托模型写入前,必须把写入边界写成结构化 `task.json.allowedPaths` / `task.json.forbiddenPaths`,再审查生成 DAG 的 writer `writeSet`;不要只依赖 `source/执行约束.md` 的自然语言约束。",
624
625
  "",
625
626
  "### 初始化闭环",
626
627
  "",
@@ -636,6 +637,10 @@ function buildManagedAgentsBlock(input) {
636
637
  "",
637
638
  "如果仓库信息不足,写明“尚未从仓库文件中识别到 ...”以及下一步需要的事实;不要留下泛化占位符,也不要只提示用户稍后手填。",
638
639
  "",
640
+ "### 文档收敛",
641
+ "",
642
+ "完成实现和验证后,必须检查 `README.md`、`AGENTS.md`、`CHANGELOG.md`(如果目标项目维护)、治理文档、skills references、初始化模板和脚本说明是否仍与实际行为一致。只更新与本次变更相关的内容;如果决定不更新,应在交接里写明理由。",
643
+ "",
639
644
  "### 开始顺序",
640
645
  "",
641
646
  "改文件前先完成:",
@@ -664,10 +669,16 @@ function buildManagedAgentsBlock(input) {
664
669
  "",
665
670
  "任务 source 是必需项。`source/需求.md` 写目标、范围、非目标、验收标准和相关链接;`source/执行约束.md` 写允许路径、禁止路径、受保护变更、不变量、预期验证和失败条件。",
666
671
  "",
672
+ "委托写入前,还要把允许/禁止路径同步到 `.harness/tasks/<task-id>/task.json` 的 `allowedPaths` / `forbiddenPaths` 字段,并在执行前审查生成 DAG 的 writer `writeSet` 是否窄且准确。",
673
+ "",
667
674
  "凡是影响项目公共契约、执行入口、交付流水线、自动化/治理、数据模型、安全或权限模型、跨模块行为、用户可见工作流的改动,都必须在编辑实现文件前先创建任务、写好两个 source 文件、生成 DAG,并审查 DAG/writeSet。",
668
675
  "",
669
676
  "执行 DAG 前必须审查 profile routing、governance profile、writer 的 `writeSet`、`allowedPaths`、`forbiddenPaths`、shell verification 和 decision gate mode。不要执行占位或过宽的写入范围。",
670
677
  "",
678
+ "### DAG 诊断与收口",
679
+ "",
680
+ "执行后优先使用 `loop-agent dag report --run-id <run-id> --markdown` 读取 run facts;失败或 paused run 使用 `loop-agent dag doctor --run-id <run-id> --markdown` 诊断。失败 DAG run 不应写成成功 closeout,应使用 `loop-agent dag closeout-draft --run-id <run-id>` 生成 failure handoff,保留 what failed、evidence、classification、recommended follow-up、safe retry conditions 和 human decision needed。",
681
+ "",
671
682
  "### 运行态与 Skills",
672
683
  "",
673
684
  "- `.harness/tasks/` 保存任务状态和 source 材料。",
@@ -880,6 +891,8 @@ function buildManagedReadmeBlock(input) {
880
891
  "",
881
892
  `详细工作流见 \`${input.governanceRoot}/feature-workflow.md\`;验证矩阵见 \`${input.governanceRoot}/verification-matrix.md\`。任务 source 是必需项:\`source/需求.md\` 写目标、范围、非目标、验收标准和相关链接,\`source/执行约束.md\` 写允许路径、禁止路径、受保护变更、不变量、预期验证和失败条件。`,
882
893
  "",
894
+ "执行后使用 `loop-agent dag report --run-id <run-id> --markdown` 和 `loop-agent dag doctor --run-id <run-id> --markdown` 读取事实与诊断失败。失败 run 不做成功式 closeout;使用 `loop-agent dag closeout-draft --run-id <run-id>` 生成 failure handoff。",
895
+ "",
883
896
  "### 文档导航",
884
897
  "",
885
898
  `- \`${input.governanceRoot}/README.md\` - 治理文档索引(含原则、工作流、验证矩阵与方法论)`,
@@ -948,6 +961,7 @@ function buildTargetDocsReadme(input) {
948
961
  "- `reports/README.md` - 验证与审计报告 / verification and audit reports",
949
962
  "- `decisions/README.md` - 架构决策 / architecture decisions",
950
963
  "- `templates/` - 可复用的计划、报告与 DAG 模板 / reusable planning, reporting, and DAG templates",
964
+ "- `templates/production-readiness-checklist.md` - 低/中风险单仓库 DAG 任务的 production readiness 检查清单 / production readiness checklist for low/medium-risk single-repo DAG work",
951
965
  "",
952
966
  "## 验证 / Verification",
953
967
  "",
@@ -1143,6 +1157,12 @@ function buildTargetLoopAgentHarness(input) {
1143
1157
  "",
1144
1158
  "Use `loop-agent new-task`, `loop-agent dag run-task`, `loop-agent dag validate`, and `loop-agent run-dag` for non-trivial implementation work.",
1145
1159
  "",
1160
+ "## Operator Recovery",
1161
+ "",
1162
+ "After a run, use `loop-agent dag report --run-id <run-id> --markdown` to read canonical run facts and `loop-agent dag doctor --run-id <run-id> --markdown` to diagnose failed or paused runs. Failed DAG runs should produce a failure handoff via `loop-agent dag closeout-draft --run-id <run-id>` instead of a successful closeout.",
1163
+ "",
1164
+ "Use `docs/templates/production-readiness-checklist.md` when claiming Production Readiness v0.1 for low/medium-risk single-repo DAG work.",
1165
+ "",
1146
1166
  "## Script Matrix",
1147
1167
  "",
1148
1168
  "`scripts/check-repo.sh` verifies loop-agent governance. `scripts/ci-tests.sh` handles target project verification through conservative language/toolchain detection and should be adapted after reading the project.",
@@ -1213,6 +1233,8 @@ export function buildInitInstructions(input) {
1213
1233
  "- Copy repo-local skills by default so the target repo has auditable skill instructions.",
1214
1234
  "- Do not copy examples by default; examples stay bundled in the tool and are available through `loop-agent examples`.",
1215
1235
  "- Add or update a loop-agent managed block in AGENTS.md.",
1236
+ "- The generated AGENTS.md must include documentation convergence and structured DAG write-boundary rules so target projects keep the same working discipline as this repository.",
1237
+ "- The generated target docs must surface the production readiness checklist and the operator recovery path: `dag report`, `dag doctor --run-id --markdown`, and failed-run `dag closeout-draft` failure handoff.",
1216
1238
  "- Create `.harness/` runtime directories but do not create historical run facts.",
1217
1239
  "",
1218
1240
  "## Automatic Workflow For Model-Executed Init",
@@ -1235,8 +1257,9 @@ export function buildInitInstructions(input) {
1235
1257
  "1. Read the target project's existing README, manifest/build/config files, and top-level source/module directories.",
1236
1258
  "2. Replace the root README's `初始化模型补充` comments when the information can be inferred from files. At minimum, fill project overview, technology stack/directory structure, and development/verification commands.",
1237
1259
  "3. Update `docs/verification-matrix.md` with the target project's actual quick, standard, and full verification commands.",
1238
- "4. Update `scripts/ci-tests.sh` only when the conservative generated detector is insufficient for the target project.",
1239
- "5. Run `loop-agent init doctor`, `loop-agent inspect`, `loop-agent docs audit`, and the quick verification command.",
1260
+ "4. Confirm the generated docs expose `docs/templates/production-readiness-checklist.md` plus the operator recovery path: `dag report`, `dag doctor --run-id --markdown`, and failed-run `dag closeout-draft` failure handoff.",
1261
+ "5. Update `scripts/ci-tests.sh` only when the conservative generated detector is insufficient for the target project.",
1262
+ "6. Run `loop-agent init doctor`, `loop-agent inspect`, `loop-agent docs audit`, and the quick verification command.",
1240
1263
  "",
1241
1264
  "Completion rule: if target files provide enough evidence, the final README should not leave generic `初始化模型补充` comments in the sections that can be filled. If a section truly cannot be inferred, write a short explicit note such as `尚未从仓库文件中识别到 ...` instead of asking the user to fill it later.",
1242
1265
  "",