@tea-agent/loop-agent 0.12.0 → 0.13.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +155 -153
- package/CHANGELOG.md +338 -265
- package/README.md +345 -298
- package/bin/agent-worker.js +22 -22
- package/bin/loop-agent.js +21 -21
- package/dist/application/dag/generate-task-dag.js +28 -28
- package/dist/application/evaluation/candidate-hash.js +75 -0
- package/dist/application/evaluation/candidate.js +52 -0
- package/dist/application/evaluation/replay.js +289 -0
- package/dist/application/evaluation/types.js +130 -0
- package/dist/cli/command-definitions.js +27 -7
- package/dist/cli/program.js +8 -4
- package/dist/commands/cursor-prompt.js +6 -6
- package/dist/commands/eval.js +235 -0
- package/dist/commands/init.js +544 -506
- package/dist/commands/knowledge.js +129 -31
- package/dist/commands/loop-benchmark.js +11 -11
- package/dist/commands/pi-reuse-benchmark.js +16 -16
- package/dist/executors/pi-sdk-executor.js +38 -24
- package/dist/executors/shell-executor.js +34 -2
- package/dist/executors/shell-presets.js +20 -0
- package/dist/executors/shell-verification.js +7 -0
- package/dist/governance/manifest-types.js +4 -0
- package/dist/infrastructure/evaluation/candidate-store.js +435 -0
- package/dist/infrastructure/evaluation/store.js +40 -0
- package/dist/sidecars/cursor-prompt/executor.js +1 -1
- package/dist/task/config-types.js +28 -1
- package/dist/task/runtime.js +27 -27
- package/dist/worker/cli.js +96 -1
- package/dist/worker/delivery/package.js +3 -3
- package/dist/worker/feature/decision-loader.js +37 -6
- package/dist/worker/feature/next-action.js +10 -2
- package/dist/worker/feature/ready-plan-projection.js +81 -0
- package/dist/worker/feature/reducer.js +2 -1
- package/dist/worker/feature/review.js +19 -2
- package/dist/worker/feature/run.js +27 -2
- package/dist/worker/follow-up/approve.js +5 -2
- package/dist/worker/follow-up/factory.js +1 -1
- package/dist/worker/observability/read-model.js +246 -41
- package/dist/worker/observe/routes.js +173 -15
- package/dist/worker/observe/spec-evidence.js +281 -0
- package/dist/worker/observe/static/api.js +46 -27
- package/dist/worker/observe/static/app.js +150 -150
- package/dist/worker/observe/static/constants.js +148 -148
- package/dist/worker/observe/static/copy.js +67 -67
- package/dist/worker/observe/static/dag-helpers.js +172 -172
- package/dist/worker/observe/static/dag-layout.d.ts +31 -31
- package/dist/worker/observe/static/dag-layout.js +83 -83
- package/dist/worker/observe/static/dag-model.js +72 -72
- package/dist/worker/observe/static/dom.js +61 -61
- package/dist/worker/observe/static/format-pool.js +67 -67
- package/dist/worker/observe/static/format.js +292 -292
- package/dist/worker/observe/static/index.html +308 -308
- package/dist/worker/observe/static/kpi.js +94 -94
- package/dist/worker/observe/static/relations.js +133 -128
- package/dist/worker/observe/static/router.js +93 -85
- package/dist/worker/observe/static/run-processing.js +148 -148
- package/dist/worker/observe/static/shell-chrome.js +68 -68
- package/dist/worker/observe/static/state.js +253 -253
- package/dist/worker/observe/static/styles.css +1902 -1890
- package/dist/worker/observe/static/views/batch.js +227 -226
- package/dist/worker/observe/static/views/dag-graph.js +172 -172
- package/dist/worker/observe/static/views/dag-inspector.js +607 -477
- package/dist/worker/observe/static/views/dag.js +362 -362
- package/dist/worker/observe/static/views/dashboard.js +445 -442
- package/dist/worker/observe/static/views/failures.js +143 -143
- package/dist/worker/observe/static/views/feature.js +492 -453
- package/dist/worker/observe/static/views/pool.js +350 -347
- package/dist/worker/observe/static/views/run.js +453 -453
- package/dist/worker/observe/static/views/session-timeline.js +205 -205
- package/dist/worker/observe/static/views/shell.js +7 -7
- package/dist/worker/observe/static/views/task.js +314 -260
- package/dist/worker/observe/static/views/timeline.js +163 -163
- package/dist/worker/pool/doctor.js +165 -0
- package/dist/worker/pool/migrate-state.js +303 -0
- package/dist/worker/pool/run-store.js +205 -17
- package/dist/worker/pool/types.js +17 -1
- package/dist/worker/pool/validation.js +100 -15
- package/dist/worker/report/morning-report.js +12 -2
- package/dist/worker/runner/run-ready.js +41 -26
- package/dist/worker/task-graph/ready-planner.js +136 -0
- package/dist/workflows/dag/backend-test-analysis-contract.js +120 -0
- package/dist/workflows/dag/canvas-observer.js +275 -275
- package/dist/workflows/dag/convergence/controller.js +16 -8
- package/dist/workflows/dag/dynamic-runtime/map.js +90 -2
- package/dist/workflows/dag/failure-routing.js +12 -1
- package/dist/workflows/dag/init-hybrid.js +2404 -360
- package/dist/workflows/dag/node-execution.js +9 -0
- package/dist/workflows/dag/prompt.js +9 -0
- package/dist/workflows/dag/report.js +35 -1
- package/dist/workflows/dag/runner.js +28 -2
- package/dist/workflows/dag/task-demand-routing.js +383 -0
- package/dist/workflows/dag/types.js +51 -13
- package/dist/workflows/dag/upstream-artifacts.js +1 -0
- package/dist/workflows/dag/validate.js +59 -1
- package/docs/README.md +106 -104
- package/docs/agent-dag-recovery-playbook.md +195 -184
- package/docs/agent-dag-runner.md +67 -67
- package/docs/architecture/README.md +26 -26
- package/docs/architecture/dag-execution.md +140 -140
- package/docs/architecture/evolution.md +54 -53
- package/docs/architecture/facts-and-state.md +71 -58
- package/docs/architecture/runtime-boundaries.md +191 -191
- package/docs/architecture/system-overview.md +93 -93
- package/docs/architecture/worker-and-feature.md +85 -81
- package/docs/cursor-prompt-sidecar.md +36 -36
- package/docs/decisions/README.md +18 -15
- package/docs/design/README.md +167 -77
- package/docs/development-principles.md +73 -73
- package/docs/exec-plans/README.md +6 -6
- package/docs/exec-plans/active/README.md +15 -9
- package/docs/exec-plans/completed/README.md +85 -73
- package/docs/feature-workflow.md +389 -261
- package/docs/harness-methodology-debugging.md +153 -153
- package/docs/harness-methodology-tdd.md +130 -130
- package/docs/harness-methodology-verification.md +27 -27
- package/docs/init-surface.manifest.json +289 -280
- package/docs/loop-agent-harness.md +142 -130
- package/docs/production-readiness.md +96 -96
- package/docs/progress/README.md +64 -54
- package/docs/reports/README.md +117 -94
- package/docs/skills/README.md +7 -7
- package/docs/skills/vetted-skill-registry.md +29 -27
- package/docs/templates/adr.md +60 -60
- package/docs/templates/agent-dag-authority-surface-audit.prompt.md +94 -94
- package/docs/templates/agent-dag-decision-envelope.schema.json +213 -213
- package/docs/templates/agent-dag-decision-gate-dogfood-report.md +117 -117
- package/docs/templates/agent-dag-decision-gate.prompt.md +246 -246
- package/docs/templates/agent-dag-process-supervisor.prompt.md +98 -98
- package/docs/templates/agent-dag-report.schema.json +473 -473
- package/docs/templates/agent-dag-review-verdict.prompt.md +68 -68
- package/docs/templates/agent-dag.base.json +190 -190
- package/docs/templates/agent-dag.final-verification.json +185 -185
- package/docs/templates/agent-dag.schema.json +411 -383
- package/docs/templates/agent-dag.supervised-implementation.json +501 -501
- package/docs/templates/backend-test-analysis.schema.json +44 -0
- package/docs/templates/backend-test-dag.generate-pytest.prompt.md +202 -139
- package/docs/templates/backend-test-dag.json +311 -276
- package/docs/templates/backend-test-dag.retrospect.prompt.md +125 -125
- package/docs/templates/backend-test-dag.review-cases.prompt.md +81 -81
- package/docs/templates/exec-plan.md +64 -64
- package/docs/templates/feature-spec.md +53 -53
- package/docs/templates/frontend-design-contract.md +42 -33
- package/docs/templates/frontend-task-constraints.md +35 -25
- package/docs/templates/frontend-task-requirement.md +70 -61
- package/docs/templates/frontend-test-dag.generate-cases.prompt.md +5 -0
- package/docs/templates/frontend-test-dag.json +23 -0
- package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +3 -0
- package/docs/templates/frontend-test-dag.retrospect.prompt.md +3 -0
- package/docs/templates/frontend-test-dag.review-cases.prompt.md +3 -0
- package/docs/templates/frontend-test-dag.review-execution.prompt.md +3 -0
- package/docs/templates/harness.schema.json +221 -221
- package/docs/templates/hybrid-dag.json +188 -188
- package/docs/templates/init-evolution-review.md +35 -35
- package/docs/templates/interactive-ui-round2-experiment.md +66 -66
- package/docs/templates/knowledge-graph-bootstrap-dag.json +118 -0
- package/docs/templates/knowledge-sync-dag.json +178 -0
- package/docs/templates/knowledge-sync-draft.schema.json +71 -0
- package/docs/templates/product-line/AGENTS.md +8 -8
- package/docs/templates/product-line/README.md +9 -9
- package/docs/templates/product-line/acceptance.yaml +14 -14
- package/docs/templates/product-line/closeout.yaml +9 -9
- package/docs/templates/product-line/design.md +13 -13
- package/docs/templates/product-line/links.md +10 -10
- package/docs/templates/product-line/requirement.md +17 -17
- package/docs/templates/product-line/task-graph.yaml +15 -15
- package/docs/templates/product-line/task.yaml +64 -64
- package/docs/templates/product-line/test-plan.md +7 -7
- package/docs/templates/production-readiness-checklist.md +57 -57
- package/docs/templates/progress-log.md +17 -17
- package/docs/templates/project-start-checklist.md +9 -9
- package/docs/templates/qa-report.md +48 -48
- package/docs/templates/sprint-contract.md +29 -29
- package/docs/templates/worker-dogfood-evidence.md +80 -80
- package/docs/templates/worker-dogfood-setup.md +68 -68
- package/docs/verification-matrix.md +70 -66
- package/examples/decision-gate-agent-dag.json +177 -177
- package/examples/example-dag.json +46 -46
- package/examples/hybrid-loop-agent-dag.json +189 -189
- package/harness.json +66 -66
- package/package.json +88 -46
- package/scripts/check-product-line-docs.sh +29 -29
- package/scripts/check-task-pool-root.sh +32 -32
- package/scripts/kb-bootstrap-init-skeleton.sh +240 -0
- package/scripts/kb-graph-incremental-prepare.mjs +386 -0
- package/scripts/kb-graph-incremental-prepare.sh +5 -0
- package/scripts/kb-graph-materialize.mjs +105 -0
- package/scripts/kb-graph-materialize.sh +4 -0
- package/scripts/kb-graph-promote.mjs +164 -0
- package/scripts/kb-graph-promote.sh +4 -0
- package/scripts/kb-query.mjs +554 -0
- package/scripts/kb-query.sh +5 -0
- package/skills/agent-worker/SKILL.md +39 -37
- package/skills/agent-worker/references/agent-worker-operator.md +60 -43
- package/skills/ai-engineering-context/SKILL.md +48 -48
- package/skills/analyze-product-dependencies/SKILL.md +67 -0
- package/skills/analyze-product-dependencies/agents/openai.yaml +4 -0
- package/skills/analyze-product-dependencies/references/api-documentation-schema.md +30 -0
- package/skills/analyze-product-dependencies/references/dependency-analysis-schema.md +28 -0
- package/skills/analyze-product-dependencies/references/example.md +76 -0
- package/skills/analyze-product-dependencies/references/forward-test-cases.md +35 -0
- package/skills/analyze-product-dependencies/references/input-contract.md +11 -0
- package/skills/analyze-product-dependencies/references/scouting-rules.md +61 -0
- package/skills/analyze-product-dependencies/scripts/test-validators.mjs +267 -0
- package/skills/analyze-product-dependencies/scripts/validate-api-documentation.mjs +101 -0
- package/skills/analyze-product-dependencies/scripts/validate-dependency-analysis.mjs +142 -0
- package/skills/analyze-product-dependencies/scripts/validate-product-requirement-input.mjs +76 -0
- package/skills/analyze-product-dependencies/scripts/validation-helpers.mjs +146 -0
- package/skills/analyze-product-requirements/SKILL.md +90 -0
- package/skills/analyze-product-requirements/agents/openai.yaml +4 -0
- package/skills/analyze-product-requirements/references/acceptance-criteria.md +91 -0
- package/skills/analyze-product-requirements/references/clarification-and-knowledge.md +56 -0
- package/skills/analyze-product-requirements/references/example.md +86 -0
- package/skills/analyze-product-requirements/references/forward-test-cases.md +66 -0
- package/skills/analyze-product-requirements/references/product-analysis-schema.md +32 -0
- package/skills/analyze-product-requirements/references/product-requirement-schema.md +33 -0
- package/skills/analyze-product-requirements/references/requirement-clarification-schema.md +35 -0
- package/skills/analyze-product-requirements/scripts/test-validators.mjs +193 -0
- package/skills/analyze-product-requirements/scripts/validate-product-analysis.mjs +69 -0
- package/skills/analyze-product-requirements/scripts/validate-product-requirement.mjs +97 -0
- package/skills/analyze-product-requirements/scripts/validate-requirement-clarification.mjs +98 -0
- package/skills/analyze-product-requirements/scripts/validation-helpers.mjs +156 -0
- package/skills/code-review-core/SKILL.md +20 -20
- package/skills/codebase-scout/SKILL.md +19 -19
- package/skills/frontend-design-review/SKILL.md +66 -59
- package/skills/frontend-design-review/references/review-checklist.md +58 -37
- package/skills/frontend-implementation/SKILL.md +47 -51
- package/skills/frontend-implementation/references/code-standards.md +32 -34
- package/skills/frontend-implementation/references/design-spec.md +46 -46
- package/skills/frontend-implementation/references/node-contracts.md +76 -32
- package/skills/frontend-review/SKILL.md +59 -53
- package/skills/frontend-review/references/review-findings.md +47 -42
- package/skills/frontend-verification/SKILL.md +53 -40
- package/skills/frontend-verification/references/verification-checklist.md +68 -56
- package/skills/grill-me/SKILL.md +10 -10
- package/skills/grill-with-docs/SKILL.md +88 -88
- package/skills/grill-with-docs/adr-format.md +47 -47
- package/skills/grill-with-docs/context-format.md +60 -60
- package/skills/init-capability-evolution/SKILL.md +70 -70
- package/skills/loop-agent/SKILL.md +151 -151
- package/skills/loop-agent/references/README.md +67 -67
- package/skills/loop-agent/references/command-reference.md +505 -452
- package/skills/loop-agent/references/docs-converge.md +126 -126
- package/skills/loop-agent/references/harness-policy.md +263 -263
- package/skills/loop-agent/references/hybrid-dag.md +238 -233
- package/skills/loop-agent/references/learned/README.md +21 -21
- package/skills/loop-agent/references/long-running-loop.md +57 -57
- package/skills/loop-agent/references/model-routing.md +36 -36
- package/skills/loop-agent/references/multi-worktree.md +54 -54
- package/skills/loop-agent/references/one-shot-runs.md +85 -85
- package/skills/loop-agent/references/orchestrator-and-interventions.md +169 -169
- package/skills/loop-agent/references/pi-prompt.md +23 -23
- package/skills/loop-agent/references/pi-subagent-assisted-mode.md +84 -84
- package/skills/loop-agent/references/post-implementation-and-patterns.md +44 -44
- package/skills/loop-agent/references/task-workflow.md +89 -89
- package/skills/loop-agent/references/verification-and-failure-handling.md +139 -139
- package/skills/playwright-cli/SKILL.md +420 -0
- package/skills/playwright-cli/references/element-attributes.md +23 -0
- package/skills/playwright-cli/references/playwright-tests.md +39 -0
- package/skills/playwright-cli/references/request-mocking.md +87 -0
- package/skills/playwright-cli/references/running-code.md +241 -0
- package/skills/playwright-cli/references/session-management.md +225 -0
- package/skills/playwright-cli/references/storage-state.md +275 -0
- package/skills/playwright-cli/references/test-generation.md +433 -0
- package/skills/playwright-cli/references/tracing.md +139 -0
- package/skills/playwright-cli/references/video-recording.md +143 -0
- package/skills/playwright-cli-case-generator/SKILL.md +74 -0
- package/skills/requesting-code-review/SKILL.md +101 -101
- package/skills/requesting-code-review/code-reviewer.md +168 -168
- package/skills/systematic-debugging/CREATION-LOG.md +119 -119
- package/skills/systematic-debugging/SKILL.md +296 -296
- package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -158
- package/skills/systematic-debugging/condition-based-waiting.md +115 -115
- package/skills/systematic-debugging/defense-in-depth.md +122 -122
- package/skills/systematic-debugging/find-polluter.sh +63 -63
- package/skills/systematic-debugging/root-cause-tracing.md +169 -169
- package/skills/systematic-debugging/test-academic.md +14 -14
- package/skills/systematic-debugging/test-pressure-1.md +58 -58
- package/skills/systematic-debugging/test-pressure-2.md +68 -68
- package/skills/systematic-debugging/test-pressure-3.md +69 -69
- package/skills/test-driven-development/SKILL.md +20 -20
- package/skills/using-git-worktrees/SKILL.md +215 -215
- package/skills/verification-before-completion/SKILL.md +154 -154
- package/skills/webapp-testing/SKILL.md +19 -19
package/dist/commands/init.js
CHANGED
|
@@ -94,523 +94,523 @@ const COMPAT_PROMPTS = {
|
|
|
94
94
|
].join("\n"),
|
|
95
95
|
};
|
|
96
96
|
const GOVERNANCE_ROOT_TOKEN = "__LOOP_AGENT_GOVERNANCE_ROOT__";
|
|
97
|
-
const INIT_CHECK_ENGINEERING_STRUCTURE_SH = `#!/usr/bin/env bash
|
|
98
|
-
set -euo pipefail
|
|
99
|
-
|
|
100
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
101
|
-
cd "\${ROOT_DIR}"
|
|
102
|
-
|
|
103
|
-
required_paths=(
|
|
104
|
-
"README.md"
|
|
105
|
-
"harness.json"
|
|
106
|
-
"AGENTS.md"
|
|
107
|
-
"${GOVERNANCE_ROOT_TOKEN}/README.md"
|
|
108
|
-
"${GOVERNANCE_ROOT_TOKEN}/development-principles.md"
|
|
109
|
-
"${GOVERNANCE_ROOT_TOKEN}/feature-workflow.md"
|
|
110
|
-
"${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md"
|
|
111
|
-
"${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
|
|
112
|
-
"${GOVERNANCE_ROOT_TOKEN}/templates"
|
|
113
|
-
".agents/skills/loop-agent/SKILL.md"
|
|
114
|
-
".harness/prompts/analyze.md"
|
|
115
|
-
".harness/prompts/plan.md"
|
|
116
|
-
".harness/tasks"
|
|
117
|
-
".harness/dag-runs/active"
|
|
118
|
-
".harness/dag-runs/completed"
|
|
119
|
-
".harness/dag-runs/paused"
|
|
120
|
-
".harness/runs/active"
|
|
121
|
-
".harness/runs/completed"
|
|
122
|
-
".harness/runs/failed"
|
|
123
|
-
"scripts/check-engineering-structure.sh"
|
|
124
|
-
"scripts/check-doc-index.sh"
|
|
125
|
-
"scripts/check-doc-links.sh"
|
|
126
|
-
"scripts/check-active-plan-status.sh"
|
|
127
|
-
"scripts/check-exec-plan-index-sync.sh"
|
|
128
|
-
"scripts/check-harness-runtime-clean.sh"
|
|
129
|
-
"scripts/check-architecture-boundaries.sh"
|
|
130
|
-
"scripts/check-skill-entry.sh"
|
|
131
|
-
"scripts/check-repo.sh"
|
|
132
|
-
"scripts/ci-governance.sh"
|
|
133
|
-
"scripts/ci-tests.sh"
|
|
134
|
-
"scripts/ci.sh"
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
missing=()
|
|
138
|
-
for item in "\${required_paths[@]}"; do
|
|
139
|
-
if [[ ! -e "\${item}" ]]; then
|
|
140
|
-
missing+=("\${item}")
|
|
141
|
-
fi
|
|
142
|
-
done
|
|
143
|
-
|
|
144
|
-
if (( \${#missing[@]} > 0 )); then
|
|
145
|
-
echo "loop-agent 初始化检查失败,缺少必要路径:"
|
|
146
|
-
for item in "\${missing[@]}"; do
|
|
147
|
-
echo " - \${item}"
|
|
148
|
-
done
|
|
149
|
-
exit 1
|
|
150
|
-
fi
|
|
151
|
-
|
|
152
|
-
echo "loop-agent 工程结构检查通过"
|
|
97
|
+
const INIT_CHECK_ENGINEERING_STRUCTURE_SH = `#!/usr/bin/env bash
|
|
98
|
+
set -euo pipefail
|
|
99
|
+
|
|
100
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
101
|
+
cd "\${ROOT_DIR}"
|
|
102
|
+
|
|
103
|
+
required_paths=(
|
|
104
|
+
"README.md"
|
|
105
|
+
"harness.json"
|
|
106
|
+
"AGENTS.md"
|
|
107
|
+
"${GOVERNANCE_ROOT_TOKEN}/README.md"
|
|
108
|
+
"${GOVERNANCE_ROOT_TOKEN}/development-principles.md"
|
|
109
|
+
"${GOVERNANCE_ROOT_TOKEN}/feature-workflow.md"
|
|
110
|
+
"${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md"
|
|
111
|
+
"${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
|
|
112
|
+
"${GOVERNANCE_ROOT_TOKEN}/templates"
|
|
113
|
+
".agents/skills/loop-agent/SKILL.md"
|
|
114
|
+
".harness/prompts/analyze.md"
|
|
115
|
+
".harness/prompts/plan.md"
|
|
116
|
+
".harness/tasks"
|
|
117
|
+
".harness/dag-runs/active"
|
|
118
|
+
".harness/dag-runs/completed"
|
|
119
|
+
".harness/dag-runs/paused"
|
|
120
|
+
".harness/runs/active"
|
|
121
|
+
".harness/runs/completed"
|
|
122
|
+
".harness/runs/failed"
|
|
123
|
+
"scripts/check-engineering-structure.sh"
|
|
124
|
+
"scripts/check-doc-index.sh"
|
|
125
|
+
"scripts/check-doc-links.sh"
|
|
126
|
+
"scripts/check-active-plan-status.sh"
|
|
127
|
+
"scripts/check-exec-plan-index-sync.sh"
|
|
128
|
+
"scripts/check-harness-runtime-clean.sh"
|
|
129
|
+
"scripts/check-architecture-boundaries.sh"
|
|
130
|
+
"scripts/check-skill-entry.sh"
|
|
131
|
+
"scripts/check-repo.sh"
|
|
132
|
+
"scripts/ci-governance.sh"
|
|
133
|
+
"scripts/ci-tests.sh"
|
|
134
|
+
"scripts/ci.sh"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
missing=()
|
|
138
|
+
for item in "\${required_paths[@]}"; do
|
|
139
|
+
if [[ ! -e "\${item}" ]]; then
|
|
140
|
+
missing+=("\${item}")
|
|
141
|
+
fi
|
|
142
|
+
done
|
|
143
|
+
|
|
144
|
+
if (( \${#missing[@]} > 0 )); then
|
|
145
|
+
echo "loop-agent 初始化检查失败,缺少必要路径:"
|
|
146
|
+
for item in "\${missing[@]}"; do
|
|
147
|
+
echo " - \${item}"
|
|
148
|
+
done
|
|
149
|
+
exit 1
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
echo "loop-agent 工程结构检查通过"
|
|
153
153
|
`;
|
|
154
|
-
const INIT_CHECK_DOC_INDEX_SH = `#!/usr/bin/env bash
|
|
155
|
-
set -euo pipefail
|
|
156
|
-
|
|
157
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
158
|
-
cd "\${ROOT_DIR}"
|
|
159
|
-
|
|
160
|
-
required_docs=(
|
|
161
|
-
"${GOVERNANCE_ROOT_TOKEN}/README.md"
|
|
162
|
-
"${GOVERNANCE_ROOT_TOKEN}/development-principles.md"
|
|
163
|
-
"${GOVERNANCE_ROOT_TOKEN}/feature-workflow.md"
|
|
164
|
-
"${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md"
|
|
165
|
-
"${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
|
|
166
|
-
"${GOVERNANCE_ROOT_TOKEN}/loop-agent-harness.md"
|
|
167
|
-
"${GOVERNANCE_ROOT_TOKEN}/harness-methodology-tdd.md"
|
|
168
|
-
"${GOVERNANCE_ROOT_TOKEN}/harness-methodology-verification.md"
|
|
169
|
-
"${GOVERNANCE_ROOT_TOKEN}/harness-methodology-debugging.md"
|
|
170
|
-
"${GOVERNANCE_ROOT_TOKEN}/templates"
|
|
171
|
-
"${GOVERNANCE_ROOT_TOKEN}/exec-plans/active/README.md"
|
|
172
|
-
"${GOVERNANCE_ROOT_TOKEN}/exec-plans/completed/README.md"
|
|
173
|
-
"${GOVERNANCE_ROOT_TOKEN}/progress/README.md"
|
|
174
|
-
"${GOVERNANCE_ROOT_TOKEN}/reports/README.md"
|
|
175
|
-
"${GOVERNANCE_ROOT_TOKEN}/decisions/README.md"
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
missing=()
|
|
179
|
-
for item in "\${required_docs[@]}"; do
|
|
180
|
-
if [[ ! -e "\${item}" ]]; then
|
|
181
|
-
missing+=("\${item}")
|
|
182
|
-
fi
|
|
183
|
-
done
|
|
184
|
-
|
|
185
|
-
if (( \${#missing[@]} > 0 )); then
|
|
186
|
-
echo "docs 索引检查失败,缺少必要文档或目录:" >&2
|
|
187
|
-
for item in "\${missing[@]}"; do
|
|
188
|
-
echo " - \${item}" >&2
|
|
189
|
-
done
|
|
190
|
-
exit 1
|
|
191
|
-
fi
|
|
192
|
-
|
|
193
|
-
echo "docs 索引检查通过"
|
|
154
|
+
const INIT_CHECK_DOC_INDEX_SH = `#!/usr/bin/env bash
|
|
155
|
+
set -euo pipefail
|
|
156
|
+
|
|
157
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
158
|
+
cd "\${ROOT_DIR}"
|
|
159
|
+
|
|
160
|
+
required_docs=(
|
|
161
|
+
"${GOVERNANCE_ROOT_TOKEN}/README.md"
|
|
162
|
+
"${GOVERNANCE_ROOT_TOKEN}/development-principles.md"
|
|
163
|
+
"${GOVERNANCE_ROOT_TOKEN}/feature-workflow.md"
|
|
164
|
+
"${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md"
|
|
165
|
+
"${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
|
|
166
|
+
"${GOVERNANCE_ROOT_TOKEN}/loop-agent-harness.md"
|
|
167
|
+
"${GOVERNANCE_ROOT_TOKEN}/harness-methodology-tdd.md"
|
|
168
|
+
"${GOVERNANCE_ROOT_TOKEN}/harness-methodology-verification.md"
|
|
169
|
+
"${GOVERNANCE_ROOT_TOKEN}/harness-methodology-debugging.md"
|
|
170
|
+
"${GOVERNANCE_ROOT_TOKEN}/templates"
|
|
171
|
+
"${GOVERNANCE_ROOT_TOKEN}/exec-plans/active/README.md"
|
|
172
|
+
"${GOVERNANCE_ROOT_TOKEN}/exec-plans/completed/README.md"
|
|
173
|
+
"${GOVERNANCE_ROOT_TOKEN}/progress/README.md"
|
|
174
|
+
"${GOVERNANCE_ROOT_TOKEN}/reports/README.md"
|
|
175
|
+
"${GOVERNANCE_ROOT_TOKEN}/decisions/README.md"
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
missing=()
|
|
179
|
+
for item in "\${required_docs[@]}"; do
|
|
180
|
+
if [[ ! -e "\${item}" ]]; then
|
|
181
|
+
missing+=("\${item}")
|
|
182
|
+
fi
|
|
183
|
+
done
|
|
184
|
+
|
|
185
|
+
if (( \${#missing[@]} > 0 )); then
|
|
186
|
+
echo "docs 索引检查失败,缺少必要文档或目录:" >&2
|
|
187
|
+
for item in "\${missing[@]}"; do
|
|
188
|
+
echo " - \${item}" >&2
|
|
189
|
+
done
|
|
190
|
+
exit 1
|
|
191
|
+
fi
|
|
192
|
+
|
|
193
|
+
echo "docs 索引检查通过"
|
|
194
194
|
`;
|
|
195
|
-
const INIT_CHECK_DOC_LINKS_SH = `#!/usr/bin/env bash
|
|
196
|
-
set -euo pipefail
|
|
197
|
-
|
|
198
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
199
|
-
cd "\${ROOT_DIR}"
|
|
200
|
-
|
|
201
|
-
if [[ ! -d "${GOVERNANCE_ROOT_TOKEN}" ]]; then
|
|
202
|
-
echo "docs 链接检查失败:缺少 ${GOVERNANCE_ROOT_TOKEN}/" >&2
|
|
203
|
-
exit 1
|
|
204
|
-
fi
|
|
205
|
-
|
|
206
|
-
missing=()
|
|
207
|
-
while IFS= read -r -d '' file; do
|
|
208
|
-
while IFS= read -r link; do
|
|
209
|
-
[[ -z "\${link}" ]] && continue
|
|
210
|
-
[[ "\${link}" == http://* || "\${link}" == https://* || "\${link}" == mailto:* || "\${link}" == "#"* ]] && continue
|
|
211
|
-
[[ "\${link}" == *"://"* ]] && continue
|
|
212
|
-
target="\${link%%#*}"
|
|
213
|
-
[[ -z "\${target}" ]] && continue
|
|
214
|
-
[[ "\${target}" == /* ]] && continue
|
|
215
|
-
base="$(dirname "\${file}")"
|
|
216
|
-
if [[ ! -e "\${base}/\${target}" ]]; then
|
|
217
|
-
missing+=("\${file}: \${link}")
|
|
218
|
-
fi
|
|
219
|
-
done < <(grep -Eo '\\[[^]]+\\]\\([^)]+\\)' "\${file}" | sed -E 's/^.*\\(([^)]+)\\)$/\\1/' || true)
|
|
220
|
-
done < <(find "${GOVERNANCE_ROOT_TOKEN}" -type f -name '*.md' -print0)
|
|
221
|
-
|
|
222
|
-
if (( \${#missing[@]} > 0 )); then
|
|
223
|
-
echo "docs 链接检查失败:" >&2
|
|
224
|
-
for item in "\${missing[@]}"; do
|
|
225
|
-
echo " - \${item}" >&2
|
|
226
|
-
done
|
|
227
|
-
exit 1
|
|
228
|
-
fi
|
|
229
|
-
|
|
230
|
-
echo "docs 链接检查通过"
|
|
195
|
+
const INIT_CHECK_DOC_LINKS_SH = `#!/usr/bin/env bash
|
|
196
|
+
set -euo pipefail
|
|
197
|
+
|
|
198
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
199
|
+
cd "\${ROOT_DIR}"
|
|
200
|
+
|
|
201
|
+
if [[ ! -d "${GOVERNANCE_ROOT_TOKEN}" ]]; then
|
|
202
|
+
echo "docs 链接检查失败:缺少 ${GOVERNANCE_ROOT_TOKEN}/" >&2
|
|
203
|
+
exit 1
|
|
204
|
+
fi
|
|
205
|
+
|
|
206
|
+
missing=()
|
|
207
|
+
while IFS= read -r -d '' file; do
|
|
208
|
+
while IFS= read -r link; do
|
|
209
|
+
[[ -z "\${link}" ]] && continue
|
|
210
|
+
[[ "\${link}" == http://* || "\${link}" == https://* || "\${link}" == mailto:* || "\${link}" == "#"* ]] && continue
|
|
211
|
+
[[ "\${link}" == *"://"* ]] && continue
|
|
212
|
+
target="\${link%%#*}"
|
|
213
|
+
[[ -z "\${target}" ]] && continue
|
|
214
|
+
[[ "\${target}" == /* ]] && continue
|
|
215
|
+
base="$(dirname "\${file}")"
|
|
216
|
+
if [[ ! -e "\${base}/\${target}" ]]; then
|
|
217
|
+
missing+=("\${file}: \${link}")
|
|
218
|
+
fi
|
|
219
|
+
done < <(grep -Eo '\\[[^]]+\\]\\([^)]+\\)' "\${file}" | sed -E 's/^.*\\(([^)]+)\\)$/\\1/' || true)
|
|
220
|
+
done < <(find "${GOVERNANCE_ROOT_TOKEN}" -type f -name '*.md' -print0)
|
|
221
|
+
|
|
222
|
+
if (( \${#missing[@]} > 0 )); then
|
|
223
|
+
echo "docs 链接检查失败:" >&2
|
|
224
|
+
for item in "\${missing[@]}"; do
|
|
225
|
+
echo " - \${item}" >&2
|
|
226
|
+
done
|
|
227
|
+
exit 1
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
echo "docs 链接检查通过"
|
|
231
231
|
`;
|
|
232
|
-
const INIT_CHECK_ACTIVE_PLAN_STATUS_SH = `#!/usr/bin/env bash
|
|
233
|
-
set -euo pipefail
|
|
234
|
-
|
|
235
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
236
|
-
cd "\${ROOT_DIR}"
|
|
237
|
-
|
|
238
|
-
active_dir="${GOVERNANCE_ROOT_TOKEN}/exec-plans/active"
|
|
239
|
-
[[ -d "\${active_dir}" ]] || { echo "active plan 检查失败:缺少 \${active_dir}" >&2; exit 1; }
|
|
240
|
-
|
|
241
|
-
bad=()
|
|
242
|
-
while IFS= read -r -d '' file; do
|
|
243
|
-
name="$(basename "\${file}")"
|
|
244
|
-
[[ "\${name}" == "README.md" ]] && continue
|
|
245
|
-
if grep -Eiq 'status:[[:space:]]*(completed|done|closed)|状态[::][[:space:]]*(已完成|完成|关闭)' "\${file}"; then
|
|
246
|
-
bad+=("\${file}")
|
|
247
|
-
fi
|
|
248
|
-
done < <(find "\${active_dir}" -maxdepth 1 -type f -name '*.md' -print0)
|
|
249
|
-
|
|
250
|
-
if (( \${#bad[@]} > 0 )); then
|
|
251
|
-
echo "active plan 状态检查失败:已完成计划不应留在 active 目录:" >&2
|
|
252
|
-
for item in "\${bad[@]}"; do
|
|
253
|
-
echo " - \${item}" >&2
|
|
254
|
-
done
|
|
255
|
-
exit 1
|
|
256
|
-
fi
|
|
257
|
-
|
|
258
|
-
echo "active plan 状态检查通过"
|
|
232
|
+
const INIT_CHECK_ACTIVE_PLAN_STATUS_SH = `#!/usr/bin/env bash
|
|
233
|
+
set -euo pipefail
|
|
234
|
+
|
|
235
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
236
|
+
cd "\${ROOT_DIR}"
|
|
237
|
+
|
|
238
|
+
active_dir="${GOVERNANCE_ROOT_TOKEN}/exec-plans/active"
|
|
239
|
+
[[ -d "\${active_dir}" ]] || { echo "active plan 检查失败:缺少 \${active_dir}" >&2; exit 1; }
|
|
240
|
+
|
|
241
|
+
bad=()
|
|
242
|
+
while IFS= read -r -d '' file; do
|
|
243
|
+
name="$(basename "\${file}")"
|
|
244
|
+
[[ "\${name}" == "README.md" ]] && continue
|
|
245
|
+
if grep -Eiq 'status:[[:space:]]*(completed|done|closed)|状态[::][[:space:]]*(已完成|完成|关闭)' "\${file}"; then
|
|
246
|
+
bad+=("\${file}")
|
|
247
|
+
fi
|
|
248
|
+
done < <(find "\${active_dir}" -maxdepth 1 -type f -name '*.md' -print0)
|
|
249
|
+
|
|
250
|
+
if (( \${#bad[@]} > 0 )); then
|
|
251
|
+
echo "active plan 状态检查失败:已完成计划不应留在 active 目录:" >&2
|
|
252
|
+
for item in "\${bad[@]}"; do
|
|
253
|
+
echo " - \${item}" >&2
|
|
254
|
+
done
|
|
255
|
+
exit 1
|
|
256
|
+
fi
|
|
257
|
+
|
|
258
|
+
echo "active plan 状态检查通过"
|
|
259
259
|
`;
|
|
260
|
-
const INIT_CHECK_EXEC_PLAN_INDEX_SYNC_SH = `#!/usr/bin/env bash
|
|
261
|
-
set -euo pipefail
|
|
262
|
-
|
|
263
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
264
|
-
cd "\${ROOT_DIR}"
|
|
265
|
-
|
|
266
|
-
required=(
|
|
267
|
-
"${GOVERNANCE_ROOT_TOKEN}/exec-plans/README.md"
|
|
268
|
-
"${GOVERNANCE_ROOT_TOKEN}/exec-plans/active/README.md"
|
|
269
|
-
"${GOVERNANCE_ROOT_TOKEN}/exec-plans/completed/README.md"
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
for item in "\${required[@]}"; do
|
|
273
|
-
if [[ ! -f "\${item}" ]]; then
|
|
274
|
-
echo "exec-plan 索引同步检查失败:缺少 \${item}" >&2
|
|
275
|
-
exit 1
|
|
276
|
-
fi
|
|
277
|
-
done
|
|
278
|
-
|
|
279
|
-
echo "exec-plan 索引同步检查通过"
|
|
260
|
+
const INIT_CHECK_EXEC_PLAN_INDEX_SYNC_SH = `#!/usr/bin/env bash
|
|
261
|
+
set -euo pipefail
|
|
262
|
+
|
|
263
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
264
|
+
cd "\${ROOT_DIR}"
|
|
265
|
+
|
|
266
|
+
required=(
|
|
267
|
+
"${GOVERNANCE_ROOT_TOKEN}/exec-plans/README.md"
|
|
268
|
+
"${GOVERNANCE_ROOT_TOKEN}/exec-plans/active/README.md"
|
|
269
|
+
"${GOVERNANCE_ROOT_TOKEN}/exec-plans/completed/README.md"
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
for item in "\${required[@]}"; do
|
|
273
|
+
if [[ ! -f "\${item}" ]]; then
|
|
274
|
+
echo "exec-plan 索引同步检查失败:缺少 \${item}" >&2
|
|
275
|
+
exit 1
|
|
276
|
+
fi
|
|
277
|
+
done
|
|
278
|
+
|
|
279
|
+
echo "exec-plan 索引同步检查通过"
|
|
280
280
|
`;
|
|
281
|
-
const INIT_CHECK_HARNESS_RUNTIME_CLEAN_SH = `#!/usr/bin/env bash
|
|
282
|
-
set -euo pipefail
|
|
283
|
-
|
|
284
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
285
|
-
cd "\${ROOT_DIR}"
|
|
286
|
-
|
|
287
|
-
failures=()
|
|
288
|
-
|
|
289
|
-
count_entries() {
|
|
290
|
-
local dir="$1"
|
|
291
|
-
if [[ ! -d "\${dir}" ]]; then
|
|
292
|
-
echo 0
|
|
293
|
-
return
|
|
294
|
-
fi
|
|
295
|
-
find "\${dir}" -mindepth 1 -maxdepth 1 ! -name .gitkeep | wc -l | tr -d ' '
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if [[ "\${HARNESS_ALLOW_ACTIVE_DAG_RUNS:-}" != "1" ]]; then
|
|
299
|
-
active_dag_count="$(count_entries ".harness/dag-runs/active")"
|
|
300
|
-
[[ "\${active_dag_count}" == "0" ]] || failures+=(".harness/dag-runs/active contains \${active_dag_count} entries")
|
|
301
|
-
fi
|
|
302
|
-
|
|
303
|
-
if [[ "\${HARNESS_ALLOW_ACTIVE_TOOL_RUNS:-\${HARNESS_ALLOW_ACTIVE_ONE_SHOT_RUNS:-}}" != "1" ]]; then
|
|
304
|
-
active_run_count="$(count_entries ".harness/runs/active")"
|
|
305
|
-
[[ "\${active_run_count}" == "0" ]] || failures+=(".harness/runs/active contains \${active_run_count} entries")
|
|
306
|
-
fi
|
|
307
|
-
|
|
308
|
-
if [[ -d artifacts ]]; then
|
|
309
|
-
artifact_count="$(find artifacts -mindepth 1 -maxdepth 1 ! -name .gitkeep | wc -l | tr -d ' ')"
|
|
310
|
-
[[ "\${artifact_count}" == "0" ]] || failures+=("root artifacts/ contains \${artifact_count} entries; use ${GOVERNANCE_ROOT_TOKEN}/reports or .harness run artifacts")
|
|
311
|
-
fi
|
|
312
|
-
|
|
313
|
-
if (( \${#failures[@]} > 0 )); then
|
|
314
|
-
echo "[HARNESS RUNTIME DIRTY]" >&2
|
|
315
|
-
for item in "\${failures[@]}"; do
|
|
316
|
-
echo " - \${item}" >&2
|
|
317
|
-
done
|
|
318
|
-
exit 1
|
|
319
|
-
fi
|
|
320
|
-
|
|
321
|
-
echo "harness runtime clean check passed"
|
|
281
|
+
const INIT_CHECK_HARNESS_RUNTIME_CLEAN_SH = `#!/usr/bin/env bash
|
|
282
|
+
set -euo pipefail
|
|
283
|
+
|
|
284
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
285
|
+
cd "\${ROOT_DIR}"
|
|
286
|
+
|
|
287
|
+
failures=()
|
|
288
|
+
|
|
289
|
+
count_entries() {
|
|
290
|
+
local dir="$1"
|
|
291
|
+
if [[ ! -d "\${dir}" ]]; then
|
|
292
|
+
echo 0
|
|
293
|
+
return
|
|
294
|
+
fi
|
|
295
|
+
find "\${dir}" -mindepth 1 -maxdepth 1 ! -name .gitkeep | wc -l | tr -d ' '
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if [[ "\${HARNESS_ALLOW_ACTIVE_DAG_RUNS:-}" != "1" ]]; then
|
|
299
|
+
active_dag_count="$(count_entries ".harness/dag-runs/active")"
|
|
300
|
+
[[ "\${active_dag_count}" == "0" ]] || failures+=(".harness/dag-runs/active contains \${active_dag_count} entries")
|
|
301
|
+
fi
|
|
302
|
+
|
|
303
|
+
if [[ "\${HARNESS_ALLOW_ACTIVE_TOOL_RUNS:-\${HARNESS_ALLOW_ACTIVE_ONE_SHOT_RUNS:-}}" != "1" ]]; then
|
|
304
|
+
active_run_count="$(count_entries ".harness/runs/active")"
|
|
305
|
+
[[ "\${active_run_count}" == "0" ]] || failures+=(".harness/runs/active contains \${active_run_count} entries")
|
|
306
|
+
fi
|
|
307
|
+
|
|
308
|
+
if [[ -d artifacts ]]; then
|
|
309
|
+
artifact_count="$(find artifacts -mindepth 1 -maxdepth 1 ! -name .gitkeep | wc -l | tr -d ' ')"
|
|
310
|
+
[[ "\${artifact_count}" == "0" ]] || failures+=("root artifacts/ contains \${artifact_count} entries; use ${GOVERNANCE_ROOT_TOKEN}/reports or .harness run artifacts")
|
|
311
|
+
fi
|
|
312
|
+
|
|
313
|
+
if (( \${#failures[@]} > 0 )); then
|
|
314
|
+
echo "[HARNESS RUNTIME DIRTY]" >&2
|
|
315
|
+
for item in "\${failures[@]}"; do
|
|
316
|
+
echo " - \${item}" >&2
|
|
317
|
+
done
|
|
318
|
+
exit 1
|
|
319
|
+
fi
|
|
320
|
+
|
|
321
|
+
echo "harness runtime clean check passed"
|
|
322
322
|
`;
|
|
323
|
-
const INIT_CHECK_ARCHITECTURE_BOUNDARIES_SH = `#!/usr/bin/env bash
|
|
324
|
-
set -euo pipefail
|
|
325
|
-
|
|
326
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
327
|
-
cd "\${ROOT_DIR}"
|
|
328
|
-
|
|
329
|
-
boundary_doc="${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
|
|
330
|
-
if [[ ! -f "\${boundary_doc}" ]]; then
|
|
331
|
-
echo "architecture boundary 检查失败:缺少 \${boundary_doc}" >&2
|
|
332
|
-
exit 1
|
|
333
|
-
fi
|
|
334
|
-
|
|
335
|
-
violations=()
|
|
336
|
-
|
|
337
|
-
check_ts_import_boundary() {
|
|
338
|
-
local from_dir="$1"
|
|
339
|
-
local forbidden_dir="$2"
|
|
340
|
-
local label="$3"
|
|
341
|
-
[[ -d "\${from_dir}" && -d "\${forbidden_dir}" ]] || return 0
|
|
342
|
-
while IFS= read -r -d '' file; do
|
|
343
|
-
if grep -Eq "from ['\\\"][^'\\\"]*\${forbidden_dir}/|import\\(['\\\"][^'\\\"]*\${forbidden_dir}/|require\\(['\\\"][^'\\\"]*\${forbidden_dir}/" "\${file}"; then
|
|
344
|
-
violations+=("\${label}: \${file} imports \${forbidden_dir}")
|
|
345
|
-
fi
|
|
346
|
-
done < <(find "\${from_dir}" -type f \\( -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' -o -name '*.mjs' -o -name '*.cjs' \\) -print0)
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
# These checks are intentionally optional and stack-agnostic. They activate only
|
|
350
|
-
# when a target repository has recognizable source directories.
|
|
351
|
-
check_ts_import_boundary "src/workflows" "src/commands" "workflow-runtime"
|
|
352
|
-
check_ts_import_boundary "src/executors" "src/commands" "executors"
|
|
353
|
-
check_ts_import_boundary "src/domain" "src/infrastructure" "domain"
|
|
354
|
-
|
|
355
|
-
if (( \${#violations[@]} > 0 )); then
|
|
356
|
-
echo "architecture boundary 检查失败:" >&2
|
|
357
|
-
for item in "\${violations[@]}"; do
|
|
358
|
-
echo " - \${item}" >&2
|
|
359
|
-
done
|
|
360
|
-
echo "请更新 \${boundary_doc} 中的层边界,或修正反向依赖。" >&2
|
|
361
|
-
exit 1
|
|
362
|
-
fi
|
|
363
|
-
|
|
364
|
-
echo "architecture boundary 检查通过"
|
|
323
|
+
const INIT_CHECK_ARCHITECTURE_BOUNDARIES_SH = `#!/usr/bin/env bash
|
|
324
|
+
set -euo pipefail
|
|
325
|
+
|
|
326
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
327
|
+
cd "\${ROOT_DIR}"
|
|
328
|
+
|
|
329
|
+
boundary_doc="${GOVERNANCE_ROOT_TOKEN}/architecture/runtime-boundaries.md"
|
|
330
|
+
if [[ ! -f "\${boundary_doc}" ]]; then
|
|
331
|
+
echo "architecture boundary 检查失败:缺少 \${boundary_doc}" >&2
|
|
332
|
+
exit 1
|
|
333
|
+
fi
|
|
334
|
+
|
|
335
|
+
violations=()
|
|
336
|
+
|
|
337
|
+
check_ts_import_boundary() {
|
|
338
|
+
local from_dir="$1"
|
|
339
|
+
local forbidden_dir="$2"
|
|
340
|
+
local label="$3"
|
|
341
|
+
[[ -d "\${from_dir}" && -d "\${forbidden_dir}" ]] || return 0
|
|
342
|
+
while IFS= read -r -d '' file; do
|
|
343
|
+
if grep -Eq "from ['\\\"][^'\\\"]*\${forbidden_dir}/|import\\(['\\\"][^'\\\"]*\${forbidden_dir}/|require\\(['\\\"][^'\\\"]*\${forbidden_dir}/" "\${file}"; then
|
|
344
|
+
violations+=("\${label}: \${file} imports \${forbidden_dir}")
|
|
345
|
+
fi
|
|
346
|
+
done < <(find "\${from_dir}" -type f \\( -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' -o -name '*.mjs' -o -name '*.cjs' \\) -print0)
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
# These checks are intentionally optional and stack-agnostic. They activate only
|
|
350
|
+
# when a target repository has recognizable source directories.
|
|
351
|
+
check_ts_import_boundary "src/workflows" "src/commands" "workflow-runtime"
|
|
352
|
+
check_ts_import_boundary "src/executors" "src/commands" "executors"
|
|
353
|
+
check_ts_import_boundary "src/domain" "src/infrastructure" "domain"
|
|
354
|
+
|
|
355
|
+
if (( \${#violations[@]} > 0 )); then
|
|
356
|
+
echo "architecture boundary 检查失败:" >&2
|
|
357
|
+
for item in "\${violations[@]}"; do
|
|
358
|
+
echo " - \${item}" >&2
|
|
359
|
+
done
|
|
360
|
+
echo "请更新 \${boundary_doc} 中的层边界,或修正反向依赖。" >&2
|
|
361
|
+
exit 1
|
|
362
|
+
fi
|
|
363
|
+
|
|
364
|
+
echo "architecture boundary 检查通过"
|
|
365
365
|
`;
|
|
366
|
-
const INIT_CHECK_SKILL_ENTRY_SH = `#!/usr/bin/env bash
|
|
367
|
-
set -euo pipefail
|
|
368
|
-
|
|
369
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
370
|
-
cd "\${ROOT_DIR}"
|
|
371
|
-
|
|
372
|
-
check_skill() {
|
|
373
|
-
local skill_name="$1"
|
|
374
|
-
shift
|
|
375
|
-
local skill_dir=".agents/skills/\${skill_name}"
|
|
376
|
-
local skill_md="\${skill_dir}/SKILL.md"
|
|
377
|
-
local missing=()
|
|
378
|
-
|
|
379
|
-
if [[ ! -f "\${skill_md}" ]]; then
|
|
380
|
-
echo "skill entry 检查失败:缺少 \${skill_md}" >&2
|
|
381
|
-
exit 1
|
|
382
|
-
fi
|
|
383
|
-
grep -Eq "^name:[[:space:]]*\${skill_name}[[:space:]]*$" "\${skill_md}" || missing+=("frontmatter name")
|
|
384
|
-
grep -Eq '^description:[[:space:]]*[^[:space:]]' "\${skill_md}" || missing+=("frontmatter description")
|
|
385
|
-
|
|
386
|
-
local ref
|
|
387
|
-
for ref in "$@"; do
|
|
388
|
-
[[ -f "\${skill_dir}/\${ref}" ]] || missing+=("\${ref}")
|
|
389
|
-
grep -Fq "\${ref}" "\${skill_md}" || missing+=("SKILL.md -> \${ref}")
|
|
390
|
-
done
|
|
391
|
-
if (( \${#missing[@]} > 0 )); then
|
|
392
|
-
echo "skill entry 检查失败(\${skill_name}):" >&2
|
|
393
|
-
printf ' - %s\\n' "\${missing[@]}" >&2
|
|
394
|
-
exit 1
|
|
395
|
-
fi
|
|
396
|
-
|
|
397
|
-
local line_count
|
|
398
|
-
line_count="$(wc -l < "\${skill_md}" | tr -d ' ')"
|
|
399
|
-
if [[ "\${line_count}" =~ ^[0-9]+$ && "\${line_count}" -gt 180 ]]; then
|
|
400
|
-
echo "skill entry 检查失败:\${skill_md} 行数为 \${line_count},入口应保持精简" >&2
|
|
401
|
-
exit 1
|
|
402
|
-
fi
|
|
403
|
-
echo "skill entry 检查通过:\${skill_name} references ok, lines=\${line_count}"
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
check_skill "loop-agent" \\
|
|
407
|
-
"references/harness-policy.md" \\
|
|
408
|
-
"references/hybrid-dag.md" \\
|
|
409
|
-
"references/verification-and-failure-handling.md" \\
|
|
410
|
-
"references/command-reference.md"
|
|
411
|
-
check_skill "agent-worker" "references/agent-worker-operator.md"
|
|
412
|
-
|
|
413
|
-
description_line="$(grep -E '^description:' .agents/skills/agent-worker/SKILL.md | head -n 1 | tr '[:upper:]' '[:lower:]')"
|
|
414
|
-
for term in "agent-worker" "feature packet" "taskspec" "task pool" "self-host" "candidate" "loop-agent"; do
|
|
415
|
-
if [[ "\${description_line}" != *"\${term}"* ]]; then
|
|
416
|
-
echo "skill entry 检查失败(agent-worker):description 缺少触发/路由词 \${term}" >&2
|
|
417
|
-
exit 1
|
|
418
|
-
fi
|
|
419
|
-
done
|
|
366
|
+
const INIT_CHECK_SKILL_ENTRY_SH = `#!/usr/bin/env bash
|
|
367
|
+
set -euo pipefail
|
|
368
|
+
|
|
369
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
370
|
+
cd "\${ROOT_DIR}"
|
|
371
|
+
|
|
372
|
+
check_skill() {
|
|
373
|
+
local skill_name="$1"
|
|
374
|
+
shift
|
|
375
|
+
local skill_dir=".agents/skills/\${skill_name}"
|
|
376
|
+
local skill_md="\${skill_dir}/SKILL.md"
|
|
377
|
+
local missing=()
|
|
378
|
+
|
|
379
|
+
if [[ ! -f "\${skill_md}" ]]; then
|
|
380
|
+
echo "skill entry 检查失败:缺少 \${skill_md}" >&2
|
|
381
|
+
exit 1
|
|
382
|
+
fi
|
|
383
|
+
grep -Eq "^name:[[:space:]]*\${skill_name}[[:space:]]*$" "\${skill_md}" || missing+=("frontmatter name")
|
|
384
|
+
grep -Eq '^description:[[:space:]]*[^[:space:]]' "\${skill_md}" || missing+=("frontmatter description")
|
|
385
|
+
|
|
386
|
+
local ref
|
|
387
|
+
for ref in "$@"; do
|
|
388
|
+
[[ -f "\${skill_dir}/\${ref}" ]] || missing+=("\${ref}")
|
|
389
|
+
grep -Fq "\${ref}" "\${skill_md}" || missing+=("SKILL.md -> \${ref}")
|
|
390
|
+
done
|
|
391
|
+
if (( \${#missing[@]} > 0 )); then
|
|
392
|
+
echo "skill entry 检查失败(\${skill_name}):" >&2
|
|
393
|
+
printf ' - %s\\n' "\${missing[@]}" >&2
|
|
394
|
+
exit 1
|
|
395
|
+
fi
|
|
396
|
+
|
|
397
|
+
local line_count
|
|
398
|
+
line_count="$(wc -l < "\${skill_md}" | tr -d ' ')"
|
|
399
|
+
if [[ "\${line_count}" =~ ^[0-9]+$ && "\${line_count}" -gt 180 ]]; then
|
|
400
|
+
echo "skill entry 检查失败:\${skill_md} 行数为 \${line_count},入口应保持精简" >&2
|
|
401
|
+
exit 1
|
|
402
|
+
fi
|
|
403
|
+
echo "skill entry 检查通过:\${skill_name} references ok, lines=\${line_count}"
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
check_skill "loop-agent" \\
|
|
407
|
+
"references/harness-policy.md" \\
|
|
408
|
+
"references/hybrid-dag.md" \\
|
|
409
|
+
"references/verification-and-failure-handling.md" \\
|
|
410
|
+
"references/command-reference.md"
|
|
411
|
+
check_skill "agent-worker" "references/agent-worker-operator.md"
|
|
412
|
+
|
|
413
|
+
description_line="$(grep -E '^description:' .agents/skills/agent-worker/SKILL.md | head -n 1 | tr '[:upper:]' '[:lower:]')"
|
|
414
|
+
for term in "agent-worker" "feature packet" "taskspec" "task pool" "self-host" "candidate" "loop-agent"; do
|
|
415
|
+
if [[ "\${description_line}" != *"\${term}"* ]]; then
|
|
416
|
+
echo "skill entry 检查失败(agent-worker):description 缺少触发/路由词 \${term}" >&2
|
|
417
|
+
exit 1
|
|
418
|
+
fi
|
|
419
|
+
done
|
|
420
420
|
`;
|
|
421
|
-
const INIT_CHECK_REPO_SH = `#!/usr/bin/env bash
|
|
422
|
-
set -euo pipefail
|
|
423
|
-
|
|
424
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
425
|
-
cd "\${ROOT_DIR}"
|
|
426
|
-
|
|
427
|
-
checks=(
|
|
428
|
-
"scripts/check-engineering-structure.sh"
|
|
429
|
-
"scripts/check-doc-index.sh"
|
|
430
|
-
"scripts/check-doc-links.sh"
|
|
431
|
-
"scripts/check-active-plan-status.sh"
|
|
432
|
-
"scripts/check-exec-plan-index-sync.sh"
|
|
433
|
-
"scripts/check-harness-runtime-clean.sh"
|
|
434
|
-
"scripts/check-architecture-boundaries.sh"
|
|
435
|
-
"scripts/check-skill-entry.sh"
|
|
436
|
-
"scripts/check-product-line-docs.sh"
|
|
437
|
-
)
|
|
438
|
-
|
|
439
|
-
for check in "\${checks[@]}"; do
|
|
440
|
-
echo "==> bash \${check}"
|
|
441
|
-
bash "\${check}"
|
|
442
|
-
echo
|
|
443
|
-
done
|
|
444
|
-
|
|
445
|
-
echo "仓库治理检查全部通过"
|
|
421
|
+
const INIT_CHECK_REPO_SH = `#!/usr/bin/env bash
|
|
422
|
+
set -euo pipefail
|
|
423
|
+
|
|
424
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
425
|
+
cd "\${ROOT_DIR}"
|
|
426
|
+
|
|
427
|
+
checks=(
|
|
428
|
+
"scripts/check-engineering-structure.sh"
|
|
429
|
+
"scripts/check-doc-index.sh"
|
|
430
|
+
"scripts/check-doc-links.sh"
|
|
431
|
+
"scripts/check-active-plan-status.sh"
|
|
432
|
+
"scripts/check-exec-plan-index-sync.sh"
|
|
433
|
+
"scripts/check-harness-runtime-clean.sh"
|
|
434
|
+
"scripts/check-architecture-boundaries.sh"
|
|
435
|
+
"scripts/check-skill-entry.sh"
|
|
436
|
+
"scripts/check-product-line-docs.sh"
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
for check in "\${checks[@]}"; do
|
|
440
|
+
echo "==> bash \${check}"
|
|
441
|
+
bash "\${check}"
|
|
442
|
+
echo
|
|
443
|
+
done
|
|
444
|
+
|
|
445
|
+
echo "仓库治理检查全部通过"
|
|
446
446
|
`;
|
|
447
|
-
const INIT_CHECK_PRODUCT_LINE_DOCS_SH = `#!/usr/bin/env bash
|
|
448
|
-
set -euo pipefail
|
|
449
|
-
|
|
450
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
451
|
-
cd "\${ROOT_DIR}"
|
|
452
|
-
|
|
453
|
-
if ! command -v agent-worker >/dev/null 2>&1; then
|
|
454
|
-
echo "product-line docs check skipped: agent-worker is not installed"
|
|
455
|
-
exit 0
|
|
456
|
-
fi
|
|
457
|
-
|
|
458
|
-
feature_dirs=()
|
|
459
|
-
for root in features product/features dogfood/features; do
|
|
460
|
-
[[ -d "\${root}" ]] || continue
|
|
461
|
-
while IFS= read -r feature_dir; do
|
|
462
|
-
if [[ ! -f "\${feature_dir}/acceptance.yaml" ]]; then
|
|
463
|
-
echo "product-line docs check failed: incomplete feature packet missing acceptance.yaml: \${feature_dir}" >&2
|
|
464
|
-
exit 1
|
|
465
|
-
fi
|
|
466
|
-
feature_dirs+=("\${feature_dir}")
|
|
467
|
-
done < <(find "\${root}" -mindepth 1 -maxdepth 1 -type d | sort)
|
|
468
|
-
done
|
|
469
|
-
|
|
470
|
-
if [[ \${#feature_dirs[@]} -eq 0 ]]; then
|
|
471
|
-
echo "product-line docs check skipped: no feature packets found"
|
|
472
|
-
exit 0
|
|
473
|
-
fi
|
|
474
|
-
|
|
475
|
-
for feature_dir in "\${feature_dirs[@]}"; do
|
|
476
|
-
echo "==> validate product-line feature: \${feature_dir}"
|
|
477
|
-
agent-worker task validate-feature "\${feature_dir}"
|
|
478
|
-
done
|
|
479
|
-
|
|
480
|
-
echo "product-line docs checks passed: \${#feature_dirs[@]} feature packet(s)"
|
|
447
|
+
const INIT_CHECK_PRODUCT_LINE_DOCS_SH = `#!/usr/bin/env bash
|
|
448
|
+
set -euo pipefail
|
|
449
|
+
|
|
450
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
451
|
+
cd "\${ROOT_DIR}"
|
|
452
|
+
|
|
453
|
+
if ! command -v agent-worker >/dev/null 2>&1; then
|
|
454
|
+
echo "product-line docs check skipped: agent-worker is not installed"
|
|
455
|
+
exit 0
|
|
456
|
+
fi
|
|
457
|
+
|
|
458
|
+
feature_dirs=()
|
|
459
|
+
for root in features product/features dogfood/features; do
|
|
460
|
+
[[ -d "\${root}" ]] || continue
|
|
461
|
+
while IFS= read -r feature_dir; do
|
|
462
|
+
if [[ ! -f "\${feature_dir}/acceptance.yaml" ]]; then
|
|
463
|
+
echo "product-line docs check failed: incomplete feature packet missing acceptance.yaml: \${feature_dir}" >&2
|
|
464
|
+
exit 1
|
|
465
|
+
fi
|
|
466
|
+
feature_dirs+=("\${feature_dir}")
|
|
467
|
+
done < <(find "\${root}" -mindepth 1 -maxdepth 1 -type d | sort)
|
|
468
|
+
done
|
|
469
|
+
|
|
470
|
+
if [[ \${#feature_dirs[@]} -eq 0 ]]; then
|
|
471
|
+
echo "product-line docs check skipped: no feature packets found"
|
|
472
|
+
exit 0
|
|
473
|
+
fi
|
|
474
|
+
|
|
475
|
+
for feature_dir in "\${feature_dirs[@]}"; do
|
|
476
|
+
echo "==> validate product-line feature: \${feature_dir}"
|
|
477
|
+
agent-worker task validate-feature "\${feature_dir}"
|
|
478
|
+
done
|
|
479
|
+
|
|
480
|
+
echo "product-line docs checks passed: \${#feature_dirs[@]} feature packet(s)"
|
|
481
481
|
`;
|
|
482
|
-
const INIT_CI_GOVERNANCE_SH = `#!/usr/bin/env bash
|
|
483
|
-
set -euo pipefail
|
|
484
|
-
|
|
485
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
486
|
-
cd "\${ROOT_DIR}"
|
|
487
|
-
|
|
488
|
-
bash scripts/check-repo.sh
|
|
482
|
+
const INIT_CI_GOVERNANCE_SH = `#!/usr/bin/env bash
|
|
483
|
+
set -euo pipefail
|
|
484
|
+
|
|
485
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
486
|
+
cd "\${ROOT_DIR}"
|
|
487
|
+
|
|
488
|
+
bash scripts/check-repo.sh
|
|
489
489
|
`;
|
|
490
|
-
const INIT_CI_TESTS_SH = `#!/usr/bin/env bash
|
|
491
|
-
set -euo pipefail
|
|
492
|
-
|
|
493
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
494
|
-
cd "\${ROOT_DIR}"
|
|
495
|
-
|
|
496
|
-
ran=0
|
|
497
|
-
notes=()
|
|
498
|
-
|
|
499
|
-
run_cmd() {
|
|
500
|
-
echo "==> $*"
|
|
501
|
-
"$@"
|
|
502
|
-
ran=1
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
run_bash() {
|
|
506
|
-
echo "==> $*"
|
|
507
|
-
bash -lc "$*"
|
|
508
|
-
ran=1
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
has_make_target() {
|
|
512
|
-
local target="$1"
|
|
513
|
-
[[ -f Makefile || -f makefile ]] || return 1
|
|
514
|
-
grep -Eq "^[[:alnum:]_.-]*\${target}[[:alnum:]_.-]*:" Makefile makefile 2>/dev/null
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
has_npm_script() {
|
|
518
|
-
local script="$1"
|
|
519
|
-
[[ -f package.json ]] || return 1
|
|
520
|
-
command -v node >/dev/null 2>&1 || return 1
|
|
521
|
-
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
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
if [[ -f package.json ]]; then
|
|
525
|
-
if command -v npm >/dev/null 2>&1; then
|
|
526
|
-
for script in lint typecheck test build; do
|
|
527
|
-
if has_npm_script "\${script}"; then
|
|
528
|
-
run_cmd npm run "\${script}"
|
|
529
|
-
fi
|
|
530
|
-
done
|
|
531
|
-
else
|
|
532
|
-
notes+=("package.json exists but npm is not available")
|
|
533
|
-
fi
|
|
534
|
-
fi
|
|
535
|
-
|
|
536
|
-
if has_make_target verify; then
|
|
537
|
-
run_cmd make verify
|
|
538
|
-
elif has_make_target test; then
|
|
539
|
-
run_cmd make test
|
|
540
|
-
fi
|
|
541
|
-
|
|
542
|
-
if [[ -f go.mod ]]; then
|
|
543
|
-
if command -v go >/dev/null 2>&1; then
|
|
544
|
-
run_cmd go test ./...
|
|
545
|
-
else
|
|
546
|
-
notes+=("go.mod exists but go is not available")
|
|
547
|
-
fi
|
|
548
|
-
fi
|
|
549
|
-
|
|
550
|
-
if [[ -f Cargo.toml ]]; then
|
|
551
|
-
if command -v cargo >/dev/null 2>&1; then
|
|
552
|
-
run_cmd cargo test
|
|
553
|
-
else
|
|
554
|
-
notes+=("Cargo.toml exists but cargo is not available")
|
|
555
|
-
fi
|
|
556
|
-
fi
|
|
557
|
-
|
|
558
|
-
if [[ -f pyproject.toml || -f pytest.ini || -f tox.ini ]]; then
|
|
559
|
-
if command -v pytest >/dev/null 2>&1; then
|
|
560
|
-
run_cmd pytest
|
|
561
|
-
elif command -v tox >/dev/null 2>&1 && [[ -f tox.ini ]]; then
|
|
562
|
-
run_cmd tox
|
|
563
|
-
else
|
|
564
|
-
notes+=("Python project metadata found but pytest/tox is not available")
|
|
565
|
-
fi
|
|
566
|
-
fi
|
|
567
|
-
|
|
568
|
-
if [[ -f pom.xml ]]; then
|
|
569
|
-
if command -v mvn >/dev/null 2>&1; then
|
|
570
|
-
run_cmd mvn test
|
|
571
|
-
else
|
|
572
|
-
notes+=("pom.xml exists but mvn is not available")
|
|
573
|
-
fi
|
|
574
|
-
fi
|
|
575
|
-
|
|
576
|
-
if [[ -f build.gradle || -f build.gradle.kts || -f settings.gradle || -f settings.gradle.kts ]]; then
|
|
577
|
-
if [[ -x ./gradlew ]]; then
|
|
578
|
-
run_cmd ./gradlew test
|
|
579
|
-
elif command -v gradle >/dev/null 2>&1; then
|
|
580
|
-
run_cmd gradle test
|
|
581
|
-
else
|
|
582
|
-
notes+=("Gradle project metadata found but gradle/gradlew is not available")
|
|
583
|
-
fi
|
|
584
|
-
fi
|
|
585
|
-
|
|
586
|
-
if compgen -G "*.sln" >/dev/null || compgen -G "*.csproj" >/dev/null; then
|
|
587
|
-
if command -v dotnet >/dev/null 2>&1; then
|
|
588
|
-
run_cmd dotnet test
|
|
589
|
-
else
|
|
590
|
-
notes+=(".NET project metadata found but dotnet is not available")
|
|
591
|
-
fi
|
|
592
|
-
fi
|
|
593
|
-
|
|
594
|
-
if (( ran == 0 )); then
|
|
595
|
-
echo "未检测到可安全自动运行的项目测试入口。"
|
|
596
|
-
echo "loop-agent 治理检查仍可运行;请让初始化模型根据目标项目技术栈补充 scripts/ci-tests.sh 与 ${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md。"
|
|
597
|
-
fi
|
|
598
|
-
|
|
599
|
-
if (( \${#notes[@]} > 0 )); then
|
|
600
|
-
echo "项目验证探测备注:"
|
|
601
|
-
for note in "\${notes[@]}"; do
|
|
602
|
-
echo " - \${note}"
|
|
603
|
-
done
|
|
604
|
-
fi
|
|
490
|
+
const INIT_CI_TESTS_SH = `#!/usr/bin/env bash
|
|
491
|
+
set -euo pipefail
|
|
492
|
+
|
|
493
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
494
|
+
cd "\${ROOT_DIR}"
|
|
495
|
+
|
|
496
|
+
ran=0
|
|
497
|
+
notes=()
|
|
498
|
+
|
|
499
|
+
run_cmd() {
|
|
500
|
+
echo "==> $*"
|
|
501
|
+
"$@"
|
|
502
|
+
ran=1
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
run_bash() {
|
|
506
|
+
echo "==> $*"
|
|
507
|
+
bash -lc "$*"
|
|
508
|
+
ran=1
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
has_make_target() {
|
|
512
|
+
local target="$1"
|
|
513
|
+
[[ -f Makefile || -f makefile ]] || return 1
|
|
514
|
+
grep -Eq "^[[:alnum:]_.-]*\${target}[[:alnum:]_.-]*:" Makefile makefile 2>/dev/null
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
has_npm_script() {
|
|
518
|
+
local script="$1"
|
|
519
|
+
[[ -f package.json ]] || return 1
|
|
520
|
+
command -v node >/dev/null 2>&1 || return 1
|
|
521
|
+
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
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
if [[ -f package.json ]]; then
|
|
525
|
+
if command -v npm >/dev/null 2>&1; then
|
|
526
|
+
for script in lint typecheck test build; do
|
|
527
|
+
if has_npm_script "\${script}"; then
|
|
528
|
+
run_cmd npm run "\${script}"
|
|
529
|
+
fi
|
|
530
|
+
done
|
|
531
|
+
else
|
|
532
|
+
notes+=("package.json exists but npm is not available")
|
|
533
|
+
fi
|
|
534
|
+
fi
|
|
535
|
+
|
|
536
|
+
if has_make_target verify; then
|
|
537
|
+
run_cmd make verify
|
|
538
|
+
elif has_make_target test; then
|
|
539
|
+
run_cmd make test
|
|
540
|
+
fi
|
|
541
|
+
|
|
542
|
+
if [[ -f go.mod ]]; then
|
|
543
|
+
if command -v go >/dev/null 2>&1; then
|
|
544
|
+
run_cmd go test ./...
|
|
545
|
+
else
|
|
546
|
+
notes+=("go.mod exists but go is not available")
|
|
547
|
+
fi
|
|
548
|
+
fi
|
|
549
|
+
|
|
550
|
+
if [[ -f Cargo.toml ]]; then
|
|
551
|
+
if command -v cargo >/dev/null 2>&1; then
|
|
552
|
+
run_cmd cargo test
|
|
553
|
+
else
|
|
554
|
+
notes+=("Cargo.toml exists but cargo is not available")
|
|
555
|
+
fi
|
|
556
|
+
fi
|
|
557
|
+
|
|
558
|
+
if [[ -f pyproject.toml || -f pytest.ini || -f tox.ini ]]; then
|
|
559
|
+
if command -v pytest >/dev/null 2>&1; then
|
|
560
|
+
run_cmd pytest
|
|
561
|
+
elif command -v tox >/dev/null 2>&1 && [[ -f tox.ini ]]; then
|
|
562
|
+
run_cmd tox
|
|
563
|
+
else
|
|
564
|
+
notes+=("Python project metadata found but pytest/tox is not available")
|
|
565
|
+
fi
|
|
566
|
+
fi
|
|
567
|
+
|
|
568
|
+
if [[ -f pom.xml ]]; then
|
|
569
|
+
if command -v mvn >/dev/null 2>&1; then
|
|
570
|
+
run_cmd mvn test
|
|
571
|
+
else
|
|
572
|
+
notes+=("pom.xml exists but mvn is not available")
|
|
573
|
+
fi
|
|
574
|
+
fi
|
|
575
|
+
|
|
576
|
+
if [[ -f build.gradle || -f build.gradle.kts || -f settings.gradle || -f settings.gradle.kts ]]; then
|
|
577
|
+
if [[ -x ./gradlew ]]; then
|
|
578
|
+
run_cmd ./gradlew test
|
|
579
|
+
elif command -v gradle >/dev/null 2>&1; then
|
|
580
|
+
run_cmd gradle test
|
|
581
|
+
else
|
|
582
|
+
notes+=("Gradle project metadata found but gradle/gradlew is not available")
|
|
583
|
+
fi
|
|
584
|
+
fi
|
|
585
|
+
|
|
586
|
+
if compgen -G "*.sln" >/dev/null || compgen -G "*.csproj" >/dev/null; then
|
|
587
|
+
if command -v dotnet >/dev/null 2>&1; then
|
|
588
|
+
run_cmd dotnet test
|
|
589
|
+
else
|
|
590
|
+
notes+=(".NET project metadata found but dotnet is not available")
|
|
591
|
+
fi
|
|
592
|
+
fi
|
|
593
|
+
|
|
594
|
+
if (( ran == 0 )); then
|
|
595
|
+
echo "未检测到可安全自动运行的项目测试入口。"
|
|
596
|
+
echo "loop-agent 治理检查仍可运行;请让初始化模型根据目标项目技术栈补充 scripts/ci-tests.sh 与 ${GOVERNANCE_ROOT_TOKEN}/verification-matrix.md。"
|
|
597
|
+
fi
|
|
598
|
+
|
|
599
|
+
if (( \${#notes[@]} > 0 )); then
|
|
600
|
+
echo "项目验证探测备注:"
|
|
601
|
+
for note in "\${notes[@]}"; do
|
|
602
|
+
echo " - \${note}"
|
|
603
|
+
done
|
|
604
|
+
fi
|
|
605
605
|
`;
|
|
606
|
-
const INIT_CI_SH = `#!/usr/bin/env bash
|
|
607
|
-
set -euo pipefail
|
|
608
|
-
|
|
609
|
-
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
610
|
-
cd "\${ROOT_DIR}"
|
|
611
|
-
|
|
612
|
-
bash scripts/ci-governance.sh
|
|
613
|
-
bash scripts/ci-tests.sh
|
|
606
|
+
const INIT_CI_SH = `#!/usr/bin/env bash
|
|
607
|
+
set -euo pipefail
|
|
608
|
+
|
|
609
|
+
ROOT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
|
|
610
|
+
cd "\${ROOT_DIR}"
|
|
611
|
+
|
|
612
|
+
bash scripts/ci-governance.sh
|
|
613
|
+
bash scripts/ci-tests.sh
|
|
614
614
|
`;
|
|
615
615
|
const INIT_SCRIPT_FILES = {
|
|
616
616
|
"scripts/check-engineering-structure.sh": INIT_CHECK_ENGINEERING_STRUCTURE_SH,
|
|
@@ -805,6 +805,12 @@ export function buildManagedGitignoreBlock() {
|
|
|
805
805
|
"# one-shot executor runs",
|
|
806
806
|
".harness/runs/*",
|
|
807
807
|
"!.harness/runs/.gitkeep",
|
|
808
|
+
"!.harness/runs/active/",
|
|
809
|
+
"!.harness/runs/active/.gitkeep",
|
|
810
|
+
"!.harness/runs/completed/",
|
|
811
|
+
"!.harness/runs/completed/.gitkeep",
|
|
812
|
+
"!.harness/runs/failed/",
|
|
813
|
+
"!.harness/runs/failed/.gitkeep",
|
|
808
814
|
"",
|
|
809
815
|
"# session / cache / logs / recomputable surface state",
|
|
810
816
|
".harness/live/",
|
|
@@ -980,6 +986,26 @@ async function ensureHarnessDirs(repoRoot, written) {
|
|
|
980
986
|
await mkdir(path.join(repoRoot, dir), { recursive: true });
|
|
981
987
|
written.push(dir);
|
|
982
988
|
}
|
|
989
|
+
const placeholders = [
|
|
990
|
+
".harness/tasks/.gitkeep",
|
|
991
|
+
".harness/dag-runs/active/.gitkeep",
|
|
992
|
+
".harness/dag-runs/completed/.gitkeep",
|
|
993
|
+
".harness/dag-runs/paused/.gitkeep",
|
|
994
|
+
".harness/runs/.gitkeep",
|
|
995
|
+
".harness/runs/active/.gitkeep",
|
|
996
|
+
".harness/runs/completed/.gitkeep",
|
|
997
|
+
".harness/runs/failed/.gitkeep",
|
|
998
|
+
];
|
|
999
|
+
for (const relativePath of placeholders) {
|
|
1000
|
+
const target = path.join(repoRoot, relativePath);
|
|
1001
|
+
try {
|
|
1002
|
+
await access(target);
|
|
1003
|
+
}
|
|
1004
|
+
catch {
|
|
1005
|
+
await writeFile(target, "", "utf8");
|
|
1006
|
+
written.push(relativePath);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
983
1009
|
}
|
|
984
1010
|
async function writeCompatPrompts(input) {
|
|
985
1011
|
for (const [name, content] of Object.entries(COMPAT_PROMPTS)) {
|
|
@@ -1824,12 +1850,24 @@ function buildTargetFeatureWorkflow(input) {
|
|
|
1824
1850
|
DAG_HARD_GATE_TRIGGER,
|
|
1825
1851
|
"",
|
|
1826
1852
|
"Before executing a DAG, review profile routing, governance profile, writer writeSet, allowed paths, forbidden paths, shell verification, and decision gate mode.",
|
|
1853
|
+
"Generated DAGs bind authoritative task-source paths, SHA-256 hashes, and explicit REQ/BR/AC identifiers. Frontend plans with explicit identifiers pass a deterministic coverage gate before final design review and implementation.",
|
|
1854
|
+
"After an interrupted run, repair the task source and regenerate the complete DAG. Do not construct an impl-only recovery DAG from an upstream summary; strict governance rejects a v3 orphan writer without sourceBinding or a read-only planner ancestor.",
|
|
1827
1855
|
"",
|
|
1828
1856
|
"## Specialized Task Kinds",
|
|
1829
1857
|
"",
|
|
1830
|
-
"
|
|
1858
|
+
"- standard tasks are classified conservatively from the task title, `source/需求.md`, and structured `allowedPaths`.",
|
|
1859
|
+
"- Only high-confidence frontend implementation demands select the frontend DAG automatically; backend, mixed, negated, and unknown demands keep the template selected by the normal governance profile.",
|
|
1860
|
+
"- `frontend-mock-assess-pi` reads Mock/API/schema evidence and selects `native|browser-intercept|request-adapter|not-needed|blocked` before frontend planning; its deterministic gate rejects blocked or malformed output, while the existing frontend implementer remains the only writer.",
|
|
1861
|
+
"- Mock-backed verification never proves real API integration. When the backend was not exercised, closeout must retain the gap and name `<task-id>-real-api-integration-verify`; that follow-up is explicitly created/run after backend readiness, never automatic.",
|
|
1862
|
+
"- Automatic frontend classification never replaces a supervised template selected by an explicit profile, workflowPolicy, or the supervised quality gate.",
|
|
1863
|
+
"- A backend implementation does not select the backend test DAG. `backend-test` remains an explicit test-engineering workflow.",
|
|
1864
|
+
"- Explicit specialized `taskKind` values remain compatible and take precedence over task-source classification.",
|
|
1865
|
+
"",
|
|
1866
|
+
"Set an explicit specialized `taskKind` in `.harness/tasks/<task-id>/task.json` only when the dedicated workflow itself is part of the task contract:",
|
|
1831
1867
|
"",
|
|
1868
|
+
"- `taskKind: \"frontend-implementation\"` explicitly selects the frontend DAG for compatibility or intentional override. Optional `frontendMock` config sets `policy: auto|required|disabled`, an existing `serviceRoot`, and generation-time-frozen `verifyCommands`; an unsafe or incomplete explicit required contract produces an assessment-only DAG with no writer, while a complete required contract adds Mock-specific verification only when trusted commands exist. Auto API tasks without a native service may use an existing browser interception harness or reversible request adapter, then continue through static and behavior verification.",
|
|
1832
1869
|
"- `taskKind: \"backend-test\"` selects the dedicated backend test DAG. Its Pi nodes analyze requirements, generate and review backend cases, generate pytest, and retrospect on results; shell gate/execution nodes enforce the review verdict and run the target project's pytest. The backend test templates (`backend-test-dag.json` and the `backend-test-dag.*.prompt.md` files) ship inside the loop-agent package as static references and are projected to target projects under the governance `templates/` directory.",
|
|
1870
|
+
"- `taskKind: \"frontend-test\"` selects the FE-test RAG DAG. It writes a traceable frontend RAG package and Markdown case manifest, then executes manifest cases serially with `playwright-cli` in isolated test environments and retains per-case evidence. It never generates pytest or Playwright source code. `frontendTest.maxCasesPerBatch` defaults to 20 (maximum 50); optional `maxTokensPerCase` and `maxTotalTokens` stop only later cases after a completed case's token usage is recorded, marking them `blocked: token-budget-exhausted`. Generated browser startup uses `playwright-cli open --browser=chrome --headed <base-url>`; the generic playwright-cli skill is unchanged.",
|
|
1833
1871
|
"- Only eligible read-only Pi nodes (planner, scout, reviewer, verifier, closeout with no write-capable tool profile) receive the conservative automatic retry policy. Supervisor, implementer, writer, docs-only, dynamic, shell, static, and decision-gate nodes are not retried automatically. Eligible nodes cannot write repository files; the controller only records immutable attempt evidence under `.harness/dag-runs/<state>/<run-id>/<node-id>/attempt-<n>.json`.",
|
|
1834
1872
|
"",
|
|
1835
1873
|
"## Verification",
|