@tea-agent/loop-agent 0.5.0 → 0.6.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.
Files changed (133) hide show
  1. package/AGENTS.md +142 -142
  2. package/CHANGELOG.md +116 -98
  3. package/README.md +195 -195
  4. package/bin/agent-worker.js +22 -22
  5. package/bin/loop-agent.js +21 -21
  6. package/dist/application/dag/args.js +9 -1
  7. package/dist/application/dag/run-dag.js +16 -2
  8. package/dist/cli/command-definitions.js +22 -4
  9. package/dist/cli/help.js +3 -2
  10. package/dist/cli/program.js +7 -5
  11. package/dist/commands/import-prd.js +76 -0
  12. package/dist/commands/init.js +467 -457
  13. package/dist/commands/instructions.js +90 -58
  14. package/dist/commands/loop-benchmark.js +11 -11
  15. package/dist/commands/pi-reuse-benchmark.js +16 -16
  16. package/dist/executors/cursor-executor.js +1 -1
  17. package/dist/executors/dag-pi-executor.js +1 -0
  18. package/dist/executors/pi-sdk-executor.js +63 -1
  19. package/dist/shared/preview.js +39 -0
  20. package/dist/task/runtime.js +27 -27
  21. package/dist/task/source-references.js +221 -0
  22. package/dist/worker/cli.js +62 -1
  23. package/dist/worker/loop-agent/loop-agent-client.js +97 -5
  24. package/dist/worker/materialize/harness-task-materializer.js +162 -5
  25. package/dist/worker/observability/event-store.js +82 -0
  26. package/dist/worker/observability/events.js +79 -0
  27. package/dist/worker/observability/progress-composite.js +33 -0
  28. package/dist/worker/observability/read-model.js +1013 -0
  29. package/dist/worker/observability/snapshot-store.js +43 -0
  30. package/dist/worker/observability/types.js +1 -0
  31. package/dist/worker/observe/paths.js +64 -0
  32. package/dist/worker/observe/routes.js +423 -0
  33. package/dist/worker/observe/server.js +61 -0
  34. package/dist/worker/observe/static/app.js +1419 -0
  35. package/dist/worker/observe/static/index.html +63 -0
  36. package/dist/worker/observe/static/styles.css +613 -0
  37. package/dist/worker/pool/failure-routing.js +41 -6
  38. package/dist/worker/pool/run-store.js +50 -0
  39. package/dist/worker/progress-reporter.js +0 -18
  40. package/dist/worker/run-task/run-task.js +327 -92
  41. package/dist/worker/runner/run-ready.js +112 -4
  42. package/dist/workflows/dag/canvas-observer.js +275 -275
  43. package/dist/workflows/dag/event-observer.js +132 -0
  44. package/dist/workflows/dag/init-hybrid.js +146 -13
  45. package/dist/workflows/dag/observer-compose.js +52 -0
  46. package/docs/README.md +74 -72
  47. package/docs/agent-dag-recovery-playbook.md +184 -184
  48. package/docs/agent-dag-runner.md +42 -42
  49. package/docs/architecture/runtime-boundaries.md +162 -147
  50. package/docs/cursor-executor-usage.md +25 -25
  51. package/docs/decisions/README.md +3 -3
  52. package/docs/design/README.md +49 -36
  53. package/docs/development-principles.md +73 -73
  54. package/docs/dynamic-workflow-dag-engine-roadmap.md +1749 -1749
  55. package/docs/exec-plans/README.md +6 -6
  56. package/docs/exec-plans/active/README.md +12 -7
  57. package/docs/exec-plans/completed/README.md +31 -19
  58. package/docs/feature-workflow.md +186 -186
  59. package/docs/harness-methodology-debugging.md +153 -153
  60. package/docs/harness-methodology-tdd.md +130 -130
  61. package/docs/harness-methodology-verification.md +27 -27
  62. package/docs/init-surface.manifest.json +205 -199
  63. package/docs/loop-agent-harness.md +55 -42
  64. package/docs/production-readiness.md +96 -96
  65. package/docs/progress/README.md +3 -3
  66. package/docs/reports/README.md +9 -5
  67. package/docs/skills/README.md +6 -6
  68. package/docs/skills/vetted-skill-registry.md +26 -26
  69. package/docs/templates/adr.md +60 -60
  70. package/docs/templates/agent-dag-authority-surface-audit.prompt.md +94 -94
  71. package/docs/templates/agent-dag-decision-envelope.schema.json +213 -213
  72. package/docs/templates/agent-dag-decision-gate-dogfood-report.md +117 -117
  73. package/docs/templates/agent-dag-decision-gate.prompt.md +246 -246
  74. package/docs/templates/agent-dag-process-supervisor.prompt.md +98 -98
  75. package/docs/templates/agent-dag-report.schema.json +454 -454
  76. package/docs/templates/agent-dag-review-verdict.prompt.md +68 -68
  77. package/docs/templates/agent-dag.base.json +195 -195
  78. package/docs/templates/agent-dag.final-verification.json +190 -190
  79. package/docs/templates/agent-dag.schema.json +316 -316
  80. package/docs/templates/agent-dag.supervised-implementation.json +500 -500
  81. package/docs/templates/exec-plan.md +64 -64
  82. package/docs/templates/feature-spec.md +53 -53
  83. package/docs/templates/hybrid-dag.json +193 -193
  84. package/docs/templates/init-evolution-review.md +33 -33
  85. package/docs/templates/production-readiness-checklist.md +57 -57
  86. package/docs/templates/progress-log.md +17 -17
  87. package/docs/templates/project-start-checklist.md +9 -9
  88. package/docs/templates/qa-report.md +48 -48
  89. package/docs/templates/sprint-contract.md +29 -29
  90. package/docs/templates/worker-dogfood-evidence.md +52 -0
  91. package/docs/templates/worker-dogfood-setup.md +48 -0
  92. package/docs/verification-matrix.md +41 -41
  93. package/examples/decision-gate-agent-dag.json +123 -123
  94. package/examples/example-dag.json +51 -51
  95. package/examples/hybrid-loop-agent-dag.json +194 -194
  96. package/harness.json +70 -69
  97. package/package.json +66 -66
  98. package/skills/ai-engineering-context/SKILL.md +48 -48
  99. package/skills/code-review-core/SKILL.md +20 -20
  100. package/skills/codebase-scout/SKILL.md +19 -19
  101. package/skills/init-capability-evolution/SKILL.md +69 -69
  102. package/skills/loop-agent/SKILL.md +149 -147
  103. package/skills/loop-agent/references/README.md +67 -67
  104. package/skills/loop-agent/references/command-reference.md +412 -403
  105. package/skills/loop-agent/references/harness-policy.md +263 -259
  106. package/skills/loop-agent/references/hybrid-dag.md +216 -216
  107. package/skills/loop-agent/references/learned/README.md +21 -21
  108. package/skills/loop-agent/references/long-running-loop.md +59 -59
  109. package/skills/loop-agent/references/model-routing.md +36 -36
  110. package/skills/loop-agent/references/multi-worktree.md +54 -54
  111. package/skills/loop-agent/references/one-shot-runs.md +85 -85
  112. package/skills/loop-agent/references/orchestrator-and-interventions.md +169 -169
  113. package/skills/loop-agent/references/pi-prompt.md +23 -23
  114. package/skills/loop-agent/references/pi-subagent-assisted-mode.md +81 -81
  115. package/skills/loop-agent/references/post-implementation-and-patterns.md +44 -44
  116. package/skills/loop-agent/references/task-workflow.md +89 -84
  117. package/skills/loop-agent/references/verification-and-failure-handling.md +128 -128
  118. package/skills/requesting-code-review/SKILL.md +101 -101
  119. package/skills/requesting-code-review/code-reviewer.md +168 -168
  120. package/skills/systematic-debugging/CREATION-LOG.md +119 -119
  121. package/skills/systematic-debugging/SKILL.md +296 -296
  122. package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -158
  123. package/skills/systematic-debugging/condition-based-waiting.md +115 -115
  124. package/skills/systematic-debugging/defense-in-depth.md +122 -122
  125. package/skills/systematic-debugging/find-polluter.sh +63 -63
  126. package/skills/systematic-debugging/root-cause-tracing.md +169 -169
  127. package/skills/systematic-debugging/test-academic.md +14 -14
  128. package/skills/systematic-debugging/test-pressure-1.md +58 -58
  129. package/skills/systematic-debugging/test-pressure-2.md +68 -68
  130. package/skills/systematic-debugging/test-pressure-3.md +69 -69
  131. package/skills/test-driven-development/SKILL.md +20 -20
  132. package/skills/verification-before-completion/SKILL.md +154 -154
  133. package/skills/webapp-testing/SKILL.md +19 -19
@@ -92,474 +92,474 @@ const COMPAT_PROMPTS = {
92
92
  ].join("\n"),
93
93
  };
94
94
  const GOVERNANCE_ROOT_TOKEN = "__LOOP_AGENT_GOVERNANCE_ROOT__";
95
- const INIT_CHECK_ENGINEERING_STRUCTURE_SH = `#!/usr/bin/env bash
96
- set -euo pipefail
97
-
98
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
99
- cd "\${ROOT_DIR}"
100
-
101
- required_paths=(
102
- "README.md"
103
- "harness.json"
104
- "AGENTS.md"
105
- "${GOVERNANCE_ROOT_TOKEN}/README.md"
106
- "${GOVERNANCE_ROOT_TOKEN}/development-principles.md"
107
- "${GOVERNANCE_ROOT_TOKEN}/feature-workflow.md"
108
- "${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md"
109
- "${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
110
- "${GOVERNANCE_ROOT_TOKEN}/templates"
111
- "skills/loop-agent/SKILL.md"
112
- ".harness/prompts/analyze.md"
113
- ".harness/prompts/plan.md"
114
- ".harness/tasks"
115
- ".harness/dag-runs/active"
116
- ".harness/dag-runs/completed"
117
- ".harness/dag-runs/paused"
118
- ".harness/runs/active"
119
- ".harness/runs/completed"
120
- ".harness/runs/failed"
121
- "scripts/check-engineering-structure.sh"
122
- "scripts/check-doc-index.sh"
123
- "scripts/check-doc-links.sh"
124
- "scripts/check-active-plan-status.sh"
125
- "scripts/check-exec-plan-index-sync.sh"
126
- "scripts/check-harness-runtime-clean.sh"
127
- "scripts/check-architecture-boundaries.sh"
128
- "scripts/check-skill-entry.sh"
129
- "scripts/check-repo.sh"
130
- "scripts/ci-governance.sh"
131
- "scripts/ci-tests.sh"
132
- "scripts/ci.sh"
133
- )
134
-
135
- missing=()
136
- for item in "\${required_paths[@]}"; do
137
- if [[ ! -e "\${item}" ]]; then
138
- missing+=("\${item}")
139
- fi
140
- done
141
-
142
- if (( \${#missing[@]} > 0 )); then
143
- echo "loop-agent 初始化检查失败,缺少必要路径:"
144
- for item in "\${missing[@]}"; do
145
- echo " - \${item}"
146
- done
147
- exit 1
148
- fi
149
-
150
- echo "loop-agent 工程结构检查通过"
95
+ const INIT_CHECK_ENGINEERING_STRUCTURE_SH = `#!/usr/bin/env bash
96
+ set -euo pipefail
97
+
98
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
99
+ cd "\${ROOT_DIR}"
100
+
101
+ required_paths=(
102
+ "README.md"
103
+ "harness.json"
104
+ "AGENTS.md"
105
+ "${GOVERNANCE_ROOT_TOKEN}/README.md"
106
+ "${GOVERNANCE_ROOT_TOKEN}/development-principles.md"
107
+ "${GOVERNANCE_ROOT_TOKEN}/feature-workflow.md"
108
+ "${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md"
109
+ "${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
110
+ "${GOVERNANCE_ROOT_TOKEN}/templates"
111
+ "skills/loop-agent/SKILL.md"
112
+ ".harness/prompts/analyze.md"
113
+ ".harness/prompts/plan.md"
114
+ ".harness/tasks"
115
+ ".harness/dag-runs/active"
116
+ ".harness/dag-runs/completed"
117
+ ".harness/dag-runs/paused"
118
+ ".harness/runs/active"
119
+ ".harness/runs/completed"
120
+ ".harness/runs/failed"
121
+ "scripts/check-engineering-structure.sh"
122
+ "scripts/check-doc-index.sh"
123
+ "scripts/check-doc-links.sh"
124
+ "scripts/check-active-plan-status.sh"
125
+ "scripts/check-exec-plan-index-sync.sh"
126
+ "scripts/check-harness-runtime-clean.sh"
127
+ "scripts/check-architecture-boundaries.sh"
128
+ "scripts/check-skill-entry.sh"
129
+ "scripts/check-repo.sh"
130
+ "scripts/ci-governance.sh"
131
+ "scripts/ci-tests.sh"
132
+ "scripts/ci.sh"
133
+ )
134
+
135
+ missing=()
136
+ for item in "\${required_paths[@]}"; do
137
+ if [[ ! -e "\${item}" ]]; then
138
+ missing+=("\${item}")
139
+ fi
140
+ done
141
+
142
+ if (( \${#missing[@]} > 0 )); then
143
+ echo "loop-agent 初始化检查失败,缺少必要路径:"
144
+ for item in "\${missing[@]}"; do
145
+ echo " - \${item}"
146
+ done
147
+ exit 1
148
+ fi
149
+
150
+ echo "loop-agent 工程结构检查通过"
151
151
  `;
152
- const INIT_CHECK_DOC_INDEX_SH = `#!/usr/bin/env bash
153
- set -euo pipefail
154
-
155
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
156
- cd "\${ROOT_DIR}"
157
-
158
- required_docs=(
159
- "${GOVERNANCE_ROOT_TOKEN}/README.md"
160
- "${GOVERNANCE_ROOT_TOKEN}/development-principles.md"
161
- "${GOVERNANCE_ROOT_TOKEN}/feature-workflow.md"
162
- "${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md"
163
- "${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
164
- "${GOVERNANCE_ROOT_TOKEN}/loop-agent-harness.md"
165
- "${GOVERNANCE_ROOT_TOKEN}/harness-methodology-tdd.md"
166
- "${GOVERNANCE_ROOT_TOKEN}/harness-methodology-verification.md"
167
- "${GOVERNANCE_ROOT_TOKEN}/harness-methodology-debugging.md"
168
- "${GOVERNANCE_ROOT_TOKEN}/templates"
169
- "${GOVERNANCE_ROOT_TOKEN}/exec-plans/active/README.md"
170
- "${GOVERNANCE_ROOT_TOKEN}/exec-plans/completed/README.md"
171
- "${GOVERNANCE_ROOT_TOKEN}/progress/README.md"
172
- "${GOVERNANCE_ROOT_TOKEN}/reports/README.md"
173
- "${GOVERNANCE_ROOT_TOKEN}/decisions/README.md"
174
- )
175
-
176
- missing=()
177
- for item in "\${required_docs[@]}"; do
178
- if [[ ! -e "\${item}" ]]; then
179
- missing+=("\${item}")
180
- fi
181
- done
182
-
183
- if (( \${#missing[@]} > 0 )); then
184
- echo "docs 索引检查失败,缺少必要文档或目录:" >&2
185
- for item in "\${missing[@]}"; do
186
- echo " - \${item}" >&2
187
- done
188
- exit 1
189
- fi
190
-
191
- echo "docs 索引检查通过"
152
+ const INIT_CHECK_DOC_INDEX_SH = `#!/usr/bin/env bash
153
+ set -euo pipefail
154
+
155
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
156
+ cd "\${ROOT_DIR}"
157
+
158
+ required_docs=(
159
+ "${GOVERNANCE_ROOT_TOKEN}/README.md"
160
+ "${GOVERNANCE_ROOT_TOKEN}/development-principles.md"
161
+ "${GOVERNANCE_ROOT_TOKEN}/feature-workflow.md"
162
+ "${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md"
163
+ "${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
164
+ "${GOVERNANCE_ROOT_TOKEN}/loop-agent-harness.md"
165
+ "${GOVERNANCE_ROOT_TOKEN}/harness-methodology-tdd.md"
166
+ "${GOVERNANCE_ROOT_TOKEN}/harness-methodology-verification.md"
167
+ "${GOVERNANCE_ROOT_TOKEN}/harness-methodology-debugging.md"
168
+ "${GOVERNANCE_ROOT_TOKEN}/templates"
169
+ "${GOVERNANCE_ROOT_TOKEN}/exec-plans/active/README.md"
170
+ "${GOVERNANCE_ROOT_TOKEN}/exec-plans/completed/README.md"
171
+ "${GOVERNANCE_ROOT_TOKEN}/progress/README.md"
172
+ "${GOVERNANCE_ROOT_TOKEN}/reports/README.md"
173
+ "${GOVERNANCE_ROOT_TOKEN}/decisions/README.md"
174
+ )
175
+
176
+ missing=()
177
+ for item in "\${required_docs[@]}"; do
178
+ if [[ ! -e "\${item}" ]]; then
179
+ missing+=("\${item}")
180
+ fi
181
+ done
182
+
183
+ if (( \${#missing[@]} > 0 )); then
184
+ echo "docs 索引检查失败,缺少必要文档或目录:" >&2
185
+ for item in "\${missing[@]}"; do
186
+ echo " - \${item}" >&2
187
+ done
188
+ exit 1
189
+ fi
190
+
191
+ echo "docs 索引检查通过"
192
192
  `;
193
- const INIT_CHECK_DOC_LINKS_SH = `#!/usr/bin/env bash
194
- set -euo pipefail
195
-
196
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
197
- cd "\${ROOT_DIR}"
198
-
199
- if [[ ! -d "${GOVERNANCE_ROOT_TOKEN}" ]]; then
200
- echo "docs 链接检查失败:缺少 ${GOVERNANCE_ROOT_TOKEN}/" >&2
201
- exit 1
202
- fi
203
-
204
- missing=()
205
- while IFS= read -r -d '' file; do
206
- while IFS= read -r link; do
207
- [[ -z "\${link}" ]] && continue
208
- [[ "\${link}" == http://* || "\${link}" == https://* || "\${link}" == mailto:* || "\${link}" == "#"* ]] && continue
209
- [[ "\${link}" == *"://"* ]] && continue
210
- target="\${link%%#*}"
211
- [[ -z "\${target}" ]] && continue
212
- [[ "\${target}" == /* ]] && continue
213
- base="$(dirname "\${file}")"
214
- if [[ ! -e "\${base}/\${target}" ]]; then
215
- missing+=("\${file}: \${link}")
216
- fi
217
- done < <(grep -Eo '\\[[^]]+\\]\\([^)]+\\)' "\${file}" | sed -E 's/^.*\\(([^)]+)\\)$/\\1/' || true)
218
- done < <(find "${GOVERNANCE_ROOT_TOKEN}" -type f -name '*.md' -print0)
219
-
220
- if (( \${#missing[@]} > 0 )); then
221
- echo "docs 链接检查失败:" >&2
222
- for item in "\${missing[@]}"; do
223
- echo " - \${item}" >&2
224
- done
225
- exit 1
226
- fi
227
-
228
- echo "docs 链接检查通过"
193
+ const INIT_CHECK_DOC_LINKS_SH = `#!/usr/bin/env bash
194
+ set -euo pipefail
195
+
196
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
197
+ cd "\${ROOT_DIR}"
198
+
199
+ if [[ ! -d "${GOVERNANCE_ROOT_TOKEN}" ]]; then
200
+ echo "docs 链接检查失败:缺少 ${GOVERNANCE_ROOT_TOKEN}/" >&2
201
+ exit 1
202
+ fi
203
+
204
+ missing=()
205
+ while IFS= read -r -d '' file; do
206
+ while IFS= read -r link; do
207
+ [[ -z "\${link}" ]] && continue
208
+ [[ "\${link}" == http://* || "\${link}" == https://* || "\${link}" == mailto:* || "\${link}" == "#"* ]] && continue
209
+ [[ "\${link}" == *"://"* ]] && continue
210
+ target="\${link%%#*}"
211
+ [[ -z "\${target}" ]] && continue
212
+ [[ "\${target}" == /* ]] && continue
213
+ base="$(dirname "\${file}")"
214
+ if [[ ! -e "\${base}/\${target}" ]]; then
215
+ missing+=("\${file}: \${link}")
216
+ fi
217
+ done < <(grep -Eo '\\[[^]]+\\]\\([^)]+\\)' "\${file}" | sed -E 's/^.*\\(([^)]+)\\)$/\\1/' || true)
218
+ done < <(find "${GOVERNANCE_ROOT_TOKEN}" -type f -name '*.md' -print0)
219
+
220
+ if (( \${#missing[@]} > 0 )); then
221
+ echo "docs 链接检查失败:" >&2
222
+ for item in "\${missing[@]}"; do
223
+ echo " - \${item}" >&2
224
+ done
225
+ exit 1
226
+ fi
227
+
228
+ echo "docs 链接检查通过"
229
229
  `;
230
- const INIT_CHECK_ACTIVE_PLAN_STATUS_SH = `#!/usr/bin/env bash
231
- set -euo pipefail
232
-
233
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
234
- cd "\${ROOT_DIR}"
235
-
236
- active_dir="${GOVERNANCE_ROOT_TOKEN}/exec-plans/active"
237
- [[ -d "\${active_dir}" ]] || { echo "active plan 检查失败:缺少 \${active_dir}" >&2; exit 1; }
238
-
239
- bad=()
240
- while IFS= read -r -d '' file; do
241
- name="$(basename "\${file}")"
242
- [[ "\${name}" == "README.md" ]] && continue
243
- if grep -Eiq 'status:[[:space:]]*(completed|done|closed)|状态[::][[:space:]]*(已完成|完成|关闭)' "\${file}"; then
244
- bad+=("\${file}")
245
- fi
246
- done < <(find "\${active_dir}" -maxdepth 1 -type f -name '*.md' -print0)
247
-
248
- if (( \${#bad[@]} > 0 )); then
249
- echo "active plan 状态检查失败:已完成计划不应留在 active 目录:" >&2
250
- for item in "\${bad[@]}"; do
251
- echo " - \${item}" >&2
252
- done
253
- exit 1
254
- fi
255
-
256
- echo "active plan 状态检查通过"
230
+ const INIT_CHECK_ACTIVE_PLAN_STATUS_SH = `#!/usr/bin/env bash
231
+ set -euo pipefail
232
+
233
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
234
+ cd "\${ROOT_DIR}"
235
+
236
+ active_dir="${GOVERNANCE_ROOT_TOKEN}/exec-plans/active"
237
+ [[ -d "\${active_dir}" ]] || { echo "active plan 检查失败:缺少 \${active_dir}" >&2; exit 1; }
238
+
239
+ bad=()
240
+ while IFS= read -r -d '' file; do
241
+ name="$(basename "\${file}")"
242
+ [[ "\${name}" == "README.md" ]] && continue
243
+ if grep -Eiq 'status:[[:space:]]*(completed|done|closed)|状态[::][[:space:]]*(已完成|完成|关闭)' "\${file}"; then
244
+ bad+=("\${file}")
245
+ fi
246
+ done < <(find "\${active_dir}" -maxdepth 1 -type f -name '*.md' -print0)
247
+
248
+ if (( \${#bad[@]} > 0 )); then
249
+ echo "active plan 状态检查失败:已完成计划不应留在 active 目录:" >&2
250
+ for item in "\${bad[@]}"; do
251
+ echo " - \${item}" >&2
252
+ done
253
+ exit 1
254
+ fi
255
+
256
+ echo "active plan 状态检查通过"
257
257
  `;
258
- const INIT_CHECK_EXEC_PLAN_INDEX_SYNC_SH = `#!/usr/bin/env bash
259
- set -euo pipefail
260
-
261
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
262
- cd "\${ROOT_DIR}"
263
-
264
- required=(
265
- "${GOVERNANCE_ROOT_TOKEN}/exec-plans/README.md"
266
- "${GOVERNANCE_ROOT_TOKEN}/exec-plans/active/README.md"
267
- "${GOVERNANCE_ROOT_TOKEN}/exec-plans/completed/README.md"
268
- )
269
-
270
- for item in "\${required[@]}"; do
271
- if [[ ! -f "\${item}" ]]; then
272
- echo "exec-plan 索引同步检查失败:缺少 \${item}" >&2
273
- exit 1
274
- fi
275
- done
276
-
277
- echo "exec-plan 索引同步检查通过"
258
+ const INIT_CHECK_EXEC_PLAN_INDEX_SYNC_SH = `#!/usr/bin/env bash
259
+ set -euo pipefail
260
+
261
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
262
+ cd "\${ROOT_DIR}"
263
+
264
+ required=(
265
+ "${GOVERNANCE_ROOT_TOKEN}/exec-plans/README.md"
266
+ "${GOVERNANCE_ROOT_TOKEN}/exec-plans/active/README.md"
267
+ "${GOVERNANCE_ROOT_TOKEN}/exec-plans/completed/README.md"
268
+ )
269
+
270
+ for item in "\${required[@]}"; do
271
+ if [[ ! -f "\${item}" ]]; then
272
+ echo "exec-plan 索引同步检查失败:缺少 \${item}" >&2
273
+ exit 1
274
+ fi
275
+ done
276
+
277
+ echo "exec-plan 索引同步检查通过"
278
278
  `;
279
- const INIT_CHECK_HARNESS_RUNTIME_CLEAN_SH = `#!/usr/bin/env bash
280
- set -euo pipefail
281
-
282
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
283
- cd "\${ROOT_DIR}"
284
-
285
- failures=()
286
-
287
- count_entries() {
288
- local dir="$1"
289
- if [[ ! -d "\${dir}" ]]; then
290
- echo 0
291
- return
292
- fi
293
- find "\${dir}" -mindepth 1 -maxdepth 1 ! -name .gitkeep | wc -l | tr -d ' '
294
- }
295
-
296
- if [[ "\${HARNESS_ALLOW_ACTIVE_DAG_RUNS:-}" != "1" ]]; then
297
- active_dag_count="$(count_entries ".harness/dag-runs/active")"
298
- [[ "\${active_dag_count}" == "0" ]] || failures+=(".harness/dag-runs/active contains \${active_dag_count} entries")
299
- fi
300
-
301
- if [[ "\${HARNESS_ALLOW_ACTIVE_TOOL_RUNS:-\${HARNESS_ALLOW_ACTIVE_ONE_SHOT_RUNS:-}}" != "1" ]]; then
302
- active_run_count="$(count_entries ".harness/runs/active")"
303
- [[ "\${active_run_count}" == "0" ]] || failures+=(".harness/runs/active contains \${active_run_count} entries")
304
- fi
305
-
306
- if [[ -d artifacts ]]; then
307
- artifact_count="$(find artifacts -mindepth 1 -maxdepth 1 ! -name .gitkeep | wc -l | tr -d ' ')"
308
- [[ "\${artifact_count}" == "0" ]] || failures+=("root artifacts/ contains \${artifact_count} entries; use docs/reports or .harness run artifacts")
309
- fi
310
-
311
- if (( \${#failures[@]} > 0 )); then
312
- echo "[HARNESS RUNTIME DIRTY]" >&2
313
- for item in "\${failures[@]}"; do
314
- echo " - \${item}" >&2
315
- done
316
- exit 1
317
- fi
318
-
319
- echo "harness runtime clean check passed"
279
+ const INIT_CHECK_HARNESS_RUNTIME_CLEAN_SH = `#!/usr/bin/env bash
280
+ set -euo pipefail
281
+
282
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
283
+ cd "\${ROOT_DIR}"
284
+
285
+ failures=()
286
+
287
+ count_entries() {
288
+ local dir="$1"
289
+ if [[ ! -d "\${dir}" ]]; then
290
+ echo 0
291
+ return
292
+ fi
293
+ find "\${dir}" -mindepth 1 -maxdepth 1 ! -name .gitkeep | wc -l | tr -d ' '
294
+ }
295
+
296
+ if [[ "\${HARNESS_ALLOW_ACTIVE_DAG_RUNS:-}" != "1" ]]; then
297
+ active_dag_count="$(count_entries ".harness/dag-runs/active")"
298
+ [[ "\${active_dag_count}" == "0" ]] || failures+=(".harness/dag-runs/active contains \${active_dag_count} entries")
299
+ fi
300
+
301
+ if [[ "\${HARNESS_ALLOW_ACTIVE_TOOL_RUNS:-\${HARNESS_ALLOW_ACTIVE_ONE_SHOT_RUNS:-}}" != "1" ]]; then
302
+ active_run_count="$(count_entries ".harness/runs/active")"
303
+ [[ "\${active_run_count}" == "0" ]] || failures+=(".harness/runs/active contains \${active_run_count} entries")
304
+ fi
305
+
306
+ if [[ -d artifacts ]]; then
307
+ artifact_count="$(find artifacts -mindepth 1 -maxdepth 1 ! -name .gitkeep | wc -l | tr -d ' ')"
308
+ [[ "\${artifact_count}" == "0" ]] || failures+=("root artifacts/ contains \${artifact_count} entries; use docs/reports or .harness run artifacts")
309
+ fi
310
+
311
+ if (( \${#failures[@]} > 0 )); then
312
+ echo "[HARNESS RUNTIME DIRTY]" >&2
313
+ for item in "\${failures[@]}"; do
314
+ echo " - \${item}" >&2
315
+ done
316
+ exit 1
317
+ fi
318
+
319
+ echo "harness runtime clean check passed"
320
320
  `;
321
- const INIT_CHECK_ARCHITECTURE_BOUNDARIES_SH = `#!/usr/bin/env bash
322
- set -euo pipefail
323
-
324
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
325
- cd "\${ROOT_DIR}"
326
-
327
- boundary_doc="${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
328
- if [[ ! -f "\${boundary_doc}" ]]; then
329
- echo "architecture boundary 检查失败:缺少 \${boundary_doc}" >&2
330
- exit 1
331
- fi
332
-
333
- violations=()
334
-
335
- check_ts_import_boundary() {
336
- local from_dir="$1"
337
- local forbidden_dir="$2"
338
- local label="$3"
339
- [[ -d "\${from_dir}" && -d "\${forbidden_dir}" ]] || return 0
340
- while IFS= read -r -d '' file; do
341
- if grep -Eq "from ['\\\"][^'\\\"]*\${forbidden_dir}/|import\\(['\\\"][^'\\\"]*\${forbidden_dir}/|require\\(['\\\"][^'\\\"]*\${forbidden_dir}/" "\${file}"; then
342
- violations+=("\${label}: \${file} imports \${forbidden_dir}")
343
- fi
344
- done < <(find "\${from_dir}" -type f \\( -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' -o -name '*.mjs' -o -name '*.cjs' \\) -print0)
345
- }
346
-
347
- # These checks are intentionally optional and stack-agnostic. They activate only
348
- # when a target repository has recognizable source directories.
349
- check_ts_import_boundary "src/workflows" "src/commands" "workflow-runtime"
350
- check_ts_import_boundary "src/executors" "src/commands" "executors"
351
- check_ts_import_boundary "src/domain" "src/infrastructure" "domain"
352
-
353
- if (( \${#violations[@]} > 0 )); then
354
- echo "architecture boundary 检查失败:" >&2
355
- for item in "\${violations[@]}"; do
356
- echo " - \${item}" >&2
357
- done
358
- echo "请更新 \${boundary_doc} 中的层边界,或修正反向依赖。" >&2
359
- exit 1
360
- fi
361
-
362
- echo "architecture boundary 检查通过"
321
+ const INIT_CHECK_ARCHITECTURE_BOUNDARIES_SH = `#!/usr/bin/env bash
322
+ set -euo pipefail
323
+
324
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
325
+ cd "\${ROOT_DIR}"
326
+
327
+ boundary_doc="${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
328
+ if [[ ! -f "\${boundary_doc}" ]]; then
329
+ echo "architecture boundary 检查失败:缺少 \${boundary_doc}" >&2
330
+ exit 1
331
+ fi
332
+
333
+ violations=()
334
+
335
+ check_ts_import_boundary() {
336
+ local from_dir="$1"
337
+ local forbidden_dir="$2"
338
+ local label="$3"
339
+ [[ -d "\${from_dir}" && -d "\${forbidden_dir}" ]] || return 0
340
+ while IFS= read -r -d '' file; do
341
+ if grep -Eq "from ['\\\"][^'\\\"]*\${forbidden_dir}/|import\\(['\\\"][^'\\\"]*\${forbidden_dir}/|require\\(['\\\"][^'\\\"]*\${forbidden_dir}/" "\${file}"; then
342
+ violations+=("\${label}: \${file} imports \${forbidden_dir}")
343
+ fi
344
+ done < <(find "\${from_dir}" -type f \\( -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' -o -name '*.mjs' -o -name '*.cjs' \\) -print0)
345
+ }
346
+
347
+ # These checks are intentionally optional and stack-agnostic. They activate only
348
+ # when a target repository has recognizable source directories.
349
+ check_ts_import_boundary "src/workflows" "src/commands" "workflow-runtime"
350
+ check_ts_import_boundary "src/executors" "src/commands" "executors"
351
+ check_ts_import_boundary "src/domain" "src/infrastructure" "domain"
352
+
353
+ if (( \${#violations[@]} > 0 )); then
354
+ echo "architecture boundary 检查失败:" >&2
355
+ for item in "\${violations[@]}"; do
356
+ echo " - \${item}" >&2
357
+ done
358
+ echo "请更新 \${boundary_doc} 中的层边界,或修正反向依赖。" >&2
359
+ exit 1
360
+ fi
361
+
362
+ echo "architecture boundary 检查通过"
363
363
  `;
364
- const INIT_CHECK_SKILL_ENTRY_SH = `#!/usr/bin/env bash
365
- set -euo pipefail
366
-
367
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
368
- cd "\${ROOT_DIR}"
369
-
370
- skill_md="skills/loop-agent/SKILL.md"
371
- if [[ ! -f "\${skill_md}" ]]; then
372
- echo "skill entry 检查失败:缺少 \${skill_md}" >&2
373
- exit 1
374
- fi
375
-
376
- required_refs=(
377
- "references/harness-policy.md"
378
- "references/hybrid-dag.md"
379
- "references/verification-and-failure-handling.md"
380
- "references/command-reference.md"
381
- )
382
-
383
- missing=()
384
- for ref in "\${required_refs[@]}"; do
385
- [[ -f "skills/loop-agent/\${ref}" ]] || missing+=("\${ref}")
386
- done
387
-
388
- while IFS= read -r ref; do
389
- [[ -z "\${ref}" ]] && continue
390
- [[ -f "skills/loop-agent/\${ref}" ]] || missing+=("\${ref}")
391
- done < <(grep -Eo 'references/[A-Za-z0-9._/-]+\\.md' "\${skill_md}" | sort -u || true)
392
-
393
- if (( \${#missing[@]} > 0 )); then
394
- echo "skill entry 检查失败:引用的 reference 文件不存在:" >&2
395
- printf ' - %s\\n' "\${missing[@]}" >&2
396
- exit 1
397
- fi
398
-
399
- line_count="$(wc -l < "\${skill_md}" | tr -d ' ')"
400
- if [[ "\${line_count}" =~ ^[0-9]+$ && "\${line_count}" -gt 220 ]]; then
401
- echo "skill entry 检查警告:\${skill_md} 行数为 \${line_count},建议保持入口精简并把细节放入 references/" >&2
402
- fi
403
-
404
- echo "skill entry 检查通过:references ok, lines=\${line_count}"
364
+ const INIT_CHECK_SKILL_ENTRY_SH = `#!/usr/bin/env bash
365
+ set -euo pipefail
366
+
367
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
368
+ cd "\${ROOT_DIR}"
369
+
370
+ skill_md="skills/loop-agent/SKILL.md"
371
+ if [[ ! -f "\${skill_md}" ]]; then
372
+ echo "skill entry 检查失败:缺少 \${skill_md}" >&2
373
+ exit 1
374
+ fi
375
+
376
+ required_refs=(
377
+ "references/harness-policy.md"
378
+ "references/hybrid-dag.md"
379
+ "references/verification-and-failure-handling.md"
380
+ "references/command-reference.md"
381
+ )
382
+
383
+ missing=()
384
+ for ref in "\${required_refs[@]}"; do
385
+ [[ -f "skills/loop-agent/\${ref}" ]] || missing+=("\${ref}")
386
+ done
387
+
388
+ while IFS= read -r ref; do
389
+ [[ -z "\${ref}" ]] && continue
390
+ [[ -f "skills/loop-agent/\${ref}" ]] || missing+=("\${ref}")
391
+ done < <(grep -Eo 'references/[A-Za-z0-9._/-]+\\.md' "\${skill_md}" | sort -u || true)
392
+
393
+ if (( \${#missing[@]} > 0 )); then
394
+ echo "skill entry 检查失败:引用的 reference 文件不存在:" >&2
395
+ printf ' - %s\\n' "\${missing[@]}" >&2
396
+ exit 1
397
+ fi
398
+
399
+ line_count="$(wc -l < "\${skill_md}" | tr -d ' ')"
400
+ if [[ "\${line_count}" =~ ^[0-9]+$ && "\${line_count}" -gt 220 ]]; then
401
+ echo "skill entry 检查警告:\${skill_md} 行数为 \${line_count},建议保持入口精简并把细节放入 references/" >&2
402
+ fi
403
+
404
+ echo "skill entry 检查通过:references ok, lines=\${line_count}"
405
405
  `;
406
- const INIT_CHECK_REPO_SH = `#!/usr/bin/env bash
407
- set -euo pipefail
408
-
409
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
410
- cd "\${ROOT_DIR}"
411
-
412
- checks=(
413
- "scripts/check-engineering-structure.sh"
414
- "scripts/check-doc-index.sh"
415
- "scripts/check-doc-links.sh"
416
- "scripts/check-active-plan-status.sh"
417
- "scripts/check-exec-plan-index-sync.sh"
418
- "scripts/check-harness-runtime-clean.sh"
419
- "scripts/check-architecture-boundaries.sh"
420
- "scripts/check-skill-entry.sh"
421
- )
422
-
423
- for check in "\${checks[@]}"; do
424
- echo "==> bash \${check}"
425
- bash "\${check}"
426
- echo
427
- done
428
-
429
- echo "仓库治理检查全部通过"
406
+ const INIT_CHECK_REPO_SH = `#!/usr/bin/env bash
407
+ set -euo pipefail
408
+
409
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
410
+ cd "\${ROOT_DIR}"
411
+
412
+ checks=(
413
+ "scripts/check-engineering-structure.sh"
414
+ "scripts/check-doc-index.sh"
415
+ "scripts/check-doc-links.sh"
416
+ "scripts/check-active-plan-status.sh"
417
+ "scripts/check-exec-plan-index-sync.sh"
418
+ "scripts/check-harness-runtime-clean.sh"
419
+ "scripts/check-architecture-boundaries.sh"
420
+ "scripts/check-skill-entry.sh"
421
+ )
422
+
423
+ for check in "\${checks[@]}"; do
424
+ echo "==> bash \${check}"
425
+ bash "\${check}"
426
+ echo
427
+ done
428
+
429
+ echo "仓库治理检查全部通过"
430
430
  `;
431
- const INIT_CI_GOVERNANCE_SH = `#!/usr/bin/env bash
432
- set -euo pipefail
433
-
434
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
435
- cd "\${ROOT_DIR}"
436
-
437
- bash scripts/check-repo.sh
431
+ const INIT_CI_GOVERNANCE_SH = `#!/usr/bin/env bash
432
+ set -euo pipefail
433
+
434
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
435
+ cd "\${ROOT_DIR}"
436
+
437
+ bash scripts/check-repo.sh
438
438
  `;
439
- const INIT_CI_TESTS_SH = `#!/usr/bin/env bash
440
- set -euo pipefail
441
-
442
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
443
- cd "\${ROOT_DIR}"
444
-
445
- ran=0
446
- notes=()
447
-
448
- run_cmd() {
449
- echo "==> $*"
450
- "$@"
451
- ran=1
452
- }
453
-
454
- run_bash() {
455
- echo "==> $*"
456
- bash -lc "$*"
457
- ran=1
458
- }
459
-
460
- has_make_target() {
461
- local target="$1"
462
- [[ -f Makefile || -f makefile ]] || return 1
463
- grep -Eq "^[[:alnum:]_.-]*\${target}[[:alnum:]_.-]*:" Makefile makefile 2>/dev/null
464
- }
465
-
466
- has_npm_script() {
467
- local script="$1"
468
- [[ -f package.json ]] || return 1
469
- command -v node >/dev/null 2>&1 || return 1
470
- 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
471
- }
472
-
473
- if [[ -f package.json ]]; then
474
- if command -v npm >/dev/null 2>&1; then
475
- for script in lint typecheck test build; do
476
- if has_npm_script "\${script}"; then
477
- run_cmd npm run "\${script}"
478
- fi
479
- done
480
- else
481
- notes+=("package.json exists but npm is not available")
482
- fi
483
- fi
484
-
485
- if has_make_target verify; then
486
- run_cmd make verify
487
- elif has_make_target test; then
488
- run_cmd make test
489
- fi
490
-
491
- if [[ -f go.mod ]]; then
492
- if command -v go >/dev/null 2>&1; then
493
- run_cmd go test ./...
494
- else
495
- notes+=("go.mod exists but go is not available")
496
- fi
497
- fi
498
-
499
- if [[ -f Cargo.toml ]]; then
500
- if command -v cargo >/dev/null 2>&1; then
501
- run_cmd cargo test
502
- else
503
- notes+=("Cargo.toml exists but cargo is not available")
504
- fi
505
- fi
506
-
507
- if [[ -f pyproject.toml || -f pytest.ini || -f tox.ini ]]; then
508
- if command -v pytest >/dev/null 2>&1; then
509
- run_cmd pytest
510
- elif command -v tox >/dev/null 2>&1 && [[ -f tox.ini ]]; then
511
- run_cmd tox
512
- else
513
- notes+=("Python project metadata found but pytest/tox is not available")
514
- fi
515
- fi
516
-
517
- if [[ -f pom.xml ]]; then
518
- if command -v mvn >/dev/null 2>&1; then
519
- run_cmd mvn test
520
- else
521
- notes+=("pom.xml exists but mvn is not available")
522
- fi
523
- fi
524
-
525
- if [[ -f build.gradle || -f build.gradle.kts || -f settings.gradle || -f settings.gradle.kts ]]; then
526
- if [[ -x ./gradlew ]]; then
527
- run_cmd ./gradlew test
528
- elif command -v gradle >/dev/null 2>&1; then
529
- run_cmd gradle test
530
- else
531
- notes+=("Gradle project metadata found but gradle/gradlew is not available")
532
- fi
533
- fi
534
-
535
- if compgen -G "*.sln" >/dev/null || compgen -G "*.csproj" >/dev/null; then
536
- if command -v dotnet >/dev/null 2>&1; then
537
- run_cmd dotnet test
538
- else
539
- notes+=(".NET project metadata found but dotnet is not available")
540
- fi
541
- fi
542
-
543
- if (( ran == 0 )); then
544
- echo "未检测到可安全自动运行的项目测试入口。"
545
- echo "loop-agent 治理检查仍可运行;请让初始化模型根据目标项目技术栈补充 scripts/ci-tests.sh 与 docs/verification-matrix.md。"
546
- fi
547
-
548
- if (( \${#notes[@]} > 0 )); then
549
- echo "项目验证探测备注:"
550
- for note in "\${notes[@]}"; do
551
- echo " - \${note}"
552
- done
553
- fi
439
+ const INIT_CI_TESTS_SH = `#!/usr/bin/env bash
440
+ set -euo pipefail
441
+
442
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
443
+ cd "\${ROOT_DIR}"
444
+
445
+ ran=0
446
+ notes=()
447
+
448
+ run_cmd() {
449
+ echo "==> $*"
450
+ "$@"
451
+ ran=1
452
+ }
453
+
454
+ run_bash() {
455
+ echo "==> $*"
456
+ bash -lc "$*"
457
+ ran=1
458
+ }
459
+
460
+ has_make_target() {
461
+ local target="$1"
462
+ [[ -f Makefile || -f makefile ]] || return 1
463
+ grep -Eq "^[[:alnum:]_.-]*\${target}[[:alnum:]_.-]*:" Makefile makefile 2>/dev/null
464
+ }
465
+
466
+ has_npm_script() {
467
+ local script="$1"
468
+ [[ -f package.json ]] || return 1
469
+ command -v node >/dev/null 2>&1 || return 1
470
+ 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
471
+ }
472
+
473
+ if [[ -f package.json ]]; then
474
+ if command -v npm >/dev/null 2>&1; then
475
+ for script in lint typecheck test build; do
476
+ if has_npm_script "\${script}"; then
477
+ run_cmd npm run "\${script}"
478
+ fi
479
+ done
480
+ else
481
+ notes+=("package.json exists but npm is not available")
482
+ fi
483
+ fi
484
+
485
+ if has_make_target verify; then
486
+ run_cmd make verify
487
+ elif has_make_target test; then
488
+ run_cmd make test
489
+ fi
490
+
491
+ if [[ -f go.mod ]]; then
492
+ if command -v go >/dev/null 2>&1; then
493
+ run_cmd go test ./...
494
+ else
495
+ notes+=("go.mod exists but go is not available")
496
+ fi
497
+ fi
498
+
499
+ if [[ -f Cargo.toml ]]; then
500
+ if command -v cargo >/dev/null 2>&1; then
501
+ run_cmd cargo test
502
+ else
503
+ notes+=("Cargo.toml exists but cargo is not available")
504
+ fi
505
+ fi
506
+
507
+ if [[ -f pyproject.toml || -f pytest.ini || -f tox.ini ]]; then
508
+ if command -v pytest >/dev/null 2>&1; then
509
+ run_cmd pytest
510
+ elif command -v tox >/dev/null 2>&1 && [[ -f tox.ini ]]; then
511
+ run_cmd tox
512
+ else
513
+ notes+=("Python project metadata found but pytest/tox is not available")
514
+ fi
515
+ fi
516
+
517
+ if [[ -f pom.xml ]]; then
518
+ if command -v mvn >/dev/null 2>&1; then
519
+ run_cmd mvn test
520
+ else
521
+ notes+=("pom.xml exists but mvn is not available")
522
+ fi
523
+ fi
524
+
525
+ if [[ -f build.gradle || -f build.gradle.kts || -f settings.gradle || -f settings.gradle.kts ]]; then
526
+ if [[ -x ./gradlew ]]; then
527
+ run_cmd ./gradlew test
528
+ elif command -v gradle >/dev/null 2>&1; then
529
+ run_cmd gradle test
530
+ else
531
+ notes+=("Gradle project metadata found but gradle/gradlew is not available")
532
+ fi
533
+ fi
534
+
535
+ if compgen -G "*.sln" >/dev/null || compgen -G "*.csproj" >/dev/null; then
536
+ if command -v dotnet >/dev/null 2>&1; then
537
+ run_cmd dotnet test
538
+ else
539
+ notes+=(".NET project metadata found but dotnet is not available")
540
+ fi
541
+ fi
542
+
543
+ if (( ran == 0 )); then
544
+ echo "未检测到可安全自动运行的项目测试入口。"
545
+ echo "loop-agent 治理检查仍可运行;请让初始化模型根据目标项目技术栈补充 scripts/ci-tests.sh 与 docs/verification-matrix.md。"
546
+ fi
547
+
548
+ if (( \${#notes[@]} > 0 )); then
549
+ echo "项目验证探测备注:"
550
+ for note in "\${notes[@]}"; do
551
+ echo " - \${note}"
552
+ done
553
+ fi
554
554
  `;
555
- const INIT_CI_SH = `#!/usr/bin/env bash
556
- set -euo pipefail
557
-
558
- ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
559
- cd "\${ROOT_DIR}"
560
-
561
- bash scripts/ci-governance.sh
562
- bash scripts/ci-tests.sh
555
+ const INIT_CI_SH = `#!/usr/bin/env bash
556
+ set -euo pipefail
557
+
558
+ ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
559
+ cd "\${ROOT_DIR}"
560
+
561
+ bash scripts/ci-governance.sh
562
+ bash scripts/ci-tests.sh
563
563
  `;
564
564
  const INIT_SCRIPT_FILES = {
565
565
  "scripts/check-engineering-structure.sh": INIT_CHECK_ENGINEERING_STRUCTURE_SH,
@@ -826,6 +826,7 @@ function buildHarness(input) {
826
826
  progressDir: `${input.governanceRoot}/progress`,
827
827
  reportsDir: `${input.governanceRoot}/reports`,
828
828
  decisionsDir: `${input.governanceRoot}/decisions`,
829
+ taskPoolDir: ".task-pool",
829
830
  }),
830
831
  scripts: mergeRecord(input.existing.scripts, {
831
832
  checkEngineeringStructure: "scripts/check-engineering-structure.sh",
@@ -1305,6 +1306,8 @@ function buildTargetDocsReadme(input) {
1305
1306
  "- `decisions/README.md` - 架构决策 / architecture decisions",
1306
1307
  "- `templates/` - 可复用的计划、报告与 DAG 模板 / reusable planning, reporting, and DAG templates",
1307
1308
  "- `templates/production-readiness-checklist.md` - 低/中风险单仓库 DAG 任务的 production readiness 检查清单 / production readiness checklist for low/medium-risk single-repo DAG work",
1309
+ "- `templates/worker-dogfood-setup.md` - 发布控制器下的真实 Worker sample setup / real Worker sample setup with a published controller",
1310
+ "- `templates/worker-dogfood-evidence.md` - Worker sample、Observe、morning report 与 QA coverage evidence / Worker evidence template",
1308
1311
  "",
1309
1312
  "## 验证 / Verification",
1310
1313
  "",
@@ -1339,6 +1342,9 @@ function buildTargetRuntimeBoundaries(input) {
1339
1342
  "Executors / Integrations layer",
1340
1343
  " └─ 外部工具、SDK、数据库、消息队列、浏览器、模型或 shell 适配",
1341
1344
  "",
1345
+ "Worker adapter layer (optional)",
1346
+ " └─ 产品线 TaskSpec / Task Pool / local Observe 适配;通过已发布 loop-agent CLI 执行,不在进程内耦合 target command 或 application 层",
1347
+ "",
1342
1348
  "Infrastructure / Store layer",
1343
1349
  " └─ 文件系统、数据库、缓存、运行事实、原子写入和生命周期副作用",
1344
1350
  "",
@@ -1352,6 +1358,7 @@ function buildTargetRuntimeBoundaries(input) {
1352
1358
  "- Application / Use-case layer 可以依赖 Domain / Workflow、Infrastructure 和 Integrations。",
1353
1359
  "- Domain / Workflow layer 不应依赖 Entry layer 的格式化、argv、HTTP/UI 细节。",
1354
1360
  "- Executors / Integrations 不应依赖 Entry layer 的输出格式。",
1361
+ "- Worker adapter 应把 `.task-pool/` 作为独立运行事实区;它通过 CLI/subprocess contract 调用 loop-agent,不能复制或直接耦合 target command/application 实现。",
1355
1362
  "- Infrastructure / Store 应集中副作用,不把 raw path mutation 或持久化细节扩散给上层。",
1356
1363
  "",
1357
1364
  "## 目标项目适配",
@@ -1493,6 +1500,7 @@ function buildTargetLoopAgentHarness(input) {
1493
1500
  "- `.harness/tasks/` stores task state and source materials.",
1494
1501
  "- `.harness/dag-runs/` stores DAG run facts.",
1495
1502
  "- `.harness/runs/` stores one-shot executor facts.",
1503
+ "- `.task-pool/` stores optional agent-worker Task Pool state, batch artifacts, failure handoffs, and local Observe events; it is runtime state and normally ignored by Git.",
1496
1504
  "- `docs/` stores durable governance, plans, reports, progress, and decisions.",
1497
1505
  "- `skills/` stores repo-local skill instructions; the CLI can fall back to bundled skills when needed.",
1498
1506
  "",
@@ -1506,6 +1514,8 @@ function buildTargetLoopAgentHarness(input) {
1506
1514
  "",
1507
1515
  "Use `docs/templates/production-readiness-checklist.md` when claiming Production Readiness v0.1 for low/medium-risk single-repo DAG work.",
1508
1516
  "",
1517
+ "For real product-line Worker samples, use `docs/templates/worker-dogfood-setup.md` and `docs/templates/worker-dogfood-evidence.md`. Explicit failed-task retries must preserve prior evidence and use a new worker run id.",
1518
+ "",
1509
1519
  "## Script Matrix",
1510
1520
  "",
1511
1521
  "`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.",