coding-agent-harness 1.0.5 → 1.0.6
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/CONTRIBUTING.md +2 -2
- package/README.md +63 -3
- package/README.zh-CN.md +52 -3
- package/SKILL.md +43 -43
- package/dist/build-dist.mjs +189 -0
- package/dist/check-dist-observation.mjs +428 -0
- package/dist/check-harness.mjs +489 -0
- package/dist/check-import-graph.mjs +511 -0
- package/dist/check-runtime-emit.mjs +304 -0
- package/dist/check-type-boundaries.mjs +139 -0
- package/dist/commands/dashboard-command.mjs +80 -0
- package/dist/commands/migration-command.mjs +152 -0
- package/dist/commands/preset-command.mjs +91 -0
- package/dist/commands/task-command.mjs +324 -0
- package/dist/harness.mjs +304 -0
- package/dist/lib/capability-registry.mjs +643 -0
- package/dist/lib/check-module-parallel.mjs +227 -0
- package/dist/lib/check-profiles.mjs +414 -0
- package/dist/lib/check-task-contracts.mjs +54 -0
- package/dist/lib/core-shared.mjs +254 -0
- package/dist/lib/dashboard-data.mjs +608 -0
- package/dist/lib/dashboard-workbench.mjs +334 -0
- package/dist/lib/dashboard-writer.mjs +200 -0
- package/dist/lib/git-status-summary.mjs +45 -0
- package/dist/lib/governance-index-generator.mjs +236 -0
- package/dist/lib/governance-sync.mjs +617 -0
- package/dist/lib/governance-table-boundary.mjs +161 -0
- package/{scripts → dist}/lib/harness-core.mjs +2 -0
- package/dist/lib/harness-paths.mjs +338 -0
- package/dist/lib/lesson-maintenance.mjs +139 -0
- package/dist/lib/markdown-utils.mjs +193 -0
- package/dist/lib/migration-planner.mjs +439 -0
- package/dist/lib/migration-support.mjs +317 -0
- package/dist/lib/phase-kind.mjs +46 -0
- package/dist/lib/preset-audit-contracts.mjs +40 -0
- package/dist/lib/preset-engine.mjs +516 -0
- package/dist/lib/preset-registry.mjs +831 -0
- package/dist/lib/preset-resource-contracts.mjs +83 -0
- package/dist/lib/review-confirm-git-gate.mjs +244 -0
- package/dist/lib/status-builder.mjs +87 -0
- package/{scripts → dist}/lib/status-dashboard-renderer.mjs +44 -46
- package/dist/lib/structure-migration.mjs +404 -0
- package/dist/lib/subagent-authorization-audit.mjs +198 -0
- package/dist/lib/task-audit-metadata.mjs +376 -0
- package/dist/lib/task-audit-migration.mjs +355 -0
- package/dist/lib/task-completion-consistency.mjs +29 -0
- package/dist/lib/task-index.mjs +133 -0
- package/dist/lib/task-lesson-candidates.mjs +239 -0
- package/dist/lib/task-lesson-sedimentation.mjs +300 -0
- package/dist/lib/task-lifecycle/create-task-helpers.mjs +84 -0
- package/dist/lib/task-lifecycle/phase-sync.mjs +82 -0
- package/dist/lib/task-lifecycle/review-confirm.mjs +93 -0
- package/dist/lib/task-lifecycle/review-gates.mjs +62 -0
- package/dist/lib/task-lifecycle/review-submission.mjs +52 -0
- package/dist/lib/task-lifecycle/scaffold-provenance.mjs +54 -0
- package/dist/lib/task-lifecycle/template-files.mjs +52 -0
- package/dist/lib/task-lifecycle/text-utils.mjs +26 -0
- package/dist/lib/task-lifecycle.mjs +611 -0
- package/dist/lib/task-metadata.mjs +116 -0
- package/dist/lib/task-review-model.mjs +474 -0
- package/dist/lib/task-scanner.mjs +439 -0
- package/dist/lib/task-tombstone-commands.mjs +125 -0
- package/dist/postinstall.mjs +14 -0
- package/dist/run-built-tests.mjs +84 -0
- package/docs-release/README.md +1 -0
- package/docs-release/architecture/overview.md +12 -12
- package/docs-release/architecture/overview.zh-CN.md +12 -12
- package/docs-release/architecture/system-explainer/01-system-overview.md +15 -14
- package/docs-release/architecture/system-explainer/02-module-dependency.md +8 -8
- package/docs-release/architecture/system-explainer/03-task-lifecycle.md +3 -3
- package/docs-release/architecture/system-explainer/04-check-and-governance.md +9 -7
- package/docs-release/architecture/system-explainer/05-data-flow.md +5 -5
- package/docs-release/architecture/system-explainer/06-preset-and-migration.md +1 -4
- package/docs-release/architecture/system-explainer/en-US/01-system-overview.md +15 -14
- package/docs-release/architecture/system-explainer/en-US/02-module-dependency.md +8 -8
- package/docs-release/architecture/system-explainer/en-US/03-task-lifecycle.md +3 -3
- package/docs-release/architecture/system-explainer/en-US/04-check-and-governance.md +10 -8
- package/docs-release/architecture/system-explainer/en-US/05-data-flow.md +5 -5
- package/docs-release/architecture/system-explainer/en-US/06-preset-and-migration.md +1 -4
- package/docs-release/guides/agent-installation.en-US.md +14 -8
- package/docs-release/guides/agent-installation.md +14 -8
- package/docs-release/guides/contributing.md +3 -3
- package/docs-release/guides/contributing.zh-CN.md +3 -3
- package/docs-release/guides/document-audience-and-surfaces.en-US.md +10 -10
- package/docs-release/guides/document-audience-and-surfaces.md +10 -10
- package/docs-release/guides/legacy-migration-agent-prompt.md +25 -2
- package/docs-release/guides/legacy-migration-agent-prompt.zh-CN.md +25 -2
- package/docs-release/guides/migration-playbook.en-US.md +63 -1
- package/docs-release/guides/migration-playbook.md +59 -1
- package/docs-release/guides/parent-control-repository-pattern.en-US.md +25 -25
- package/docs-release/guides/parent-control-repository-pattern.md +25 -25
- package/docs-release/guides/preset-development.md +2 -2
- package/docs-release/guides/repository-operating-models.en-US.md +21 -21
- package/docs-release/guides/repository-operating-models.md +21 -21
- package/docs-release/guides/task-state-machine.en-US.md +5 -5
- package/docs-release/guides/task-state-machine.md +5 -5
- package/docs-release/guides/typescript-runtime-migration-closeout.md +96 -0
- package/examples/minimal-project/AGENTS.md +2 -2
- package/examples/minimal-project/coding-agent-harness/harness.yaml +14 -0
- package/examples/minimal-project/coding-agent-harness/planning/tasks/demo-task/progress.md +11 -0
- package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/review.md +1 -1
- package/package.json +20 -12
- package/presets/legacy-migration/preset.yaml +5 -5
- package/presets/legacy-migration/templates/execution_strategy.append.md +1 -1
- package/presets/lesson-sedimentation/preset.yaml +3 -3
- package/presets/module/preset.yaml +2 -2
- package/presets/module/templates/execution_strategy.append.md +1 -1
- package/presets/module/templates/task_plan.append.md +3 -3
- package/presets/standard-task/preset.yaml +2 -2
- package/references/adversarial-review-standard.md +2 -2
- package/references/agents-md-pattern.md +14 -14
- package/references/cadence-ledger.md +1 -1
- package/references/ci-cd-standard.md +1 -1
- package/references/delivery-operating-model-standard.md +4 -4
- package/references/docs-directory-standard.md +65 -159
- package/references/external-source-intake-standard.md +10 -10
- package/references/harness-ledger.md +5 -5
- package/references/legacy-12-phase-bootstrap.md +2 -2
- package/references/lessons-governance.md +15 -15
- package/references/long-running-task-standard.md +6 -6
- package/references/module-parallel-standard.md +34 -34
- package/references/planning-loop.md +6 -6
- package/references/project-onboarding-audit.md +4 -4
- package/references/regression-system.md +2 -2
- package/references/repo-governance-standard.md +4 -4
- package/references/review-routing-standard.md +1 -1
- package/references/ssot-governance.md +19 -19
- package/references/taskr-gap-analysis.md +5 -5
- package/references/walkthrough-closeout.md +14 -14
- package/references/worktree-parallel.md +3 -3
- package/skills/preset-creator/references/complex-task-skeleton/task_plan.md +1 -1
- package/skills/preset-creator/references/preset-package-skeleton.md +5 -5
- package/templates/AGENTS.md.template +26 -26
- package/templates/architecture/README.md +4 -4
- package/templates/architecture/service-catalog.md +2 -2
- package/templates/architecture/services/service-template.md +1 -1
- package/templates/dashboard/assets/app-src/20-overview.js +11 -5
- package/templates/dashboard/assets/app-src/40-modules.js +1 -1
- package/templates/dashboard/assets/app.js +12 -6
- package/templates/dashboard/assets/i18n.js +4 -2
- package/templates/development/README.md +10 -10
- package/templates/development/cross-repo-debugging.md +3 -3
- package/templates/development/external-context/service-template.md +2 -2
- package/templates/development/external-source-packs/README.md +4 -4
- package/templates/integrations/README.md +4 -4
- package/templates/integrations/api-contract.md +2 -2
- package/templates/integrations/event-contract.md +2 -2
- package/templates/integrations/third-party/vendor-template.md +2 -2
- package/templates/integrations/webhook-contract.md +2 -2
- package/templates/ledger/Harness-Ledger.md +1 -1
- package/templates/planning/INDEX.md +1 -0
- package/templates/planning/module_session_prompt.md +1 -1
- package/templates/planning/task_plan.md +1 -1
- package/templates/planning/walkthrough.md +47 -0
- package/templates/reference/docs-library-standard.md +8 -8
- package/templates/reference/external-source-intake-standard.md +15 -15
- package/templates/reference/repo-governance-standard.md +1 -1
- package/templates/ssot/Module-Registry.md +1 -1
- package/templates/walkthrough/walkthrough-template.md +2 -2
- package/templates-zh-CN/AGENTS.md.template +26 -26
- package/templates-zh-CN/CLAUDE.md.template +1 -1
- package/templates-zh-CN/architecture/README.md +4 -4
- package/templates-zh-CN/architecture/service-catalog.md +2 -2
- package/templates-zh-CN/architecture/services/service-template.md +1 -1
- package/templates-zh-CN/development/README.md +10 -10
- package/templates-zh-CN/development/cross-repo-debugging.md +3 -3
- package/templates-zh-CN/development/external-context/service-template.md +2 -2
- package/templates-zh-CN/development/external-source-packs/README.md +4 -4
- package/templates-zh-CN/integrations/README.md +4 -4
- package/templates-zh-CN/integrations/api-contract.md +2 -2
- package/templates-zh-CN/integrations/event-contract.md +2 -2
- package/templates-zh-CN/integrations/third-party/vendor-template.md +2 -2
- package/templates-zh-CN/integrations/webhook-contract.md +2 -2
- package/templates-zh-CN/ledger/Harness-Ledger.md +1 -1
- package/templates-zh-CN/lessons/lesson-arch-process-change.md +1 -1
- package/templates-zh-CN/lessons/lesson-new-doc.md +3 -3
- package/templates-zh-CN/lessons/lesson-ref-change.md +4 -4
- package/templates-zh-CN/planning/module_session_prompt.md +11 -11
- package/templates-zh-CN/planning/walkthrough.md +47 -0
- package/templates-zh-CN/reference/adversarial-review-standard.md +2 -2
- package/templates-zh-CN/reference/delivery-operating-model-standard.md +3 -3
- package/templates-zh-CN/reference/docs-library-standard.md +28 -28
- package/templates-zh-CN/reference/execution-workflow-standard.md +1 -1
- package/templates-zh-CN/reference/external-source-intake-standard.md +16 -16
- package/templates-zh-CN/reference/harness-ledger-standard.md +6 -6
- package/templates-zh-CN/reference/regression-ssot-governance.md +2 -2
- package/templates-zh-CN/reference/repo-governance-standard.md +1 -1
- package/templates-zh-CN/reference/review-routing-standard.md +1 -1
- package/templates-zh-CN/reference/walkthrough-standard.md +7 -7
- package/templates-zh-CN/reference/worktree-standard.md +1 -1
- package/templates-zh-CN/regression/Cadence-Ledger.md +2 -2
- package/templates-zh-CN/ssot/Delivery-SSoT.md +3 -3
- package/templates-zh-CN/ssot/Module-Registry.md +3 -3
- package/templates-zh-CN/ssot/Regression-SSoT.md +2 -2
- package/templates-zh-CN/walkthrough/walkthrough-template.md +5 -5
- package/tsconfig.dist.json +16 -0
- package/tsconfig.json +25 -0
- package/tsconfig.runtime.json +24 -0
- package/examples/minimal-project/.harness-capabilities.json +0 -8
- package/examples/minimal-project/docs/09-PLANNING/TASKS/demo-task/progress.md +0 -11
- package/scripts/check-harness.mjs +0 -508
- package/scripts/commands/dashboard-command.mjs +0 -67
- package/scripts/commands/migration-command.mjs +0 -126
- package/scripts/commands/preset-command.mjs +0 -73
- package/scripts/commands/task-command.mjs +0 -328
- package/scripts/harness.mjs +0 -291
- package/scripts/lib/capability-registry.mjs +0 -587
- package/scripts/lib/check-module-parallel.mjs +0 -230
- package/scripts/lib/check-profiles.mjs +0 -372
- package/scripts/lib/check-task-contracts.mjs +0 -55
- package/scripts/lib/core-shared.mjs +0 -249
- package/scripts/lib/dashboard-data.mjs +0 -520
- package/scripts/lib/dashboard-workbench.mjs +0 -336
- package/scripts/lib/dashboard-writer.mjs +0 -202
- package/scripts/lib/git-status-summary.mjs +0 -46
- package/scripts/lib/governance-index-generator.mjs +0 -174
- package/scripts/lib/governance-sync.mjs +0 -611
- package/scripts/lib/governance-table-boundary.mjs +0 -175
- package/scripts/lib/lesson-maintenance.mjs +0 -152
- package/scripts/lib/markdown-utils.mjs +0 -191
- package/scripts/lib/migration-planner.mjs +0 -476
- package/scripts/lib/migration-support.mjs +0 -312
- package/scripts/lib/phase-kind.mjs +0 -50
- package/scripts/lib/preset-audit-contracts.mjs +0 -37
- package/scripts/lib/preset-engine.mjs +0 -494
- package/scripts/lib/preset-registry.mjs +0 -776
- package/scripts/lib/preset-resource-contracts.mjs +0 -83
- package/scripts/lib/review-confirm-git-gate.mjs +0 -248
- package/scripts/lib/status-builder.mjs +0 -88
- package/scripts/lib/subagent-authorization-audit.mjs +0 -196
- package/scripts/lib/task-audit-metadata.mjs +0 -385
- package/scripts/lib/task-audit-migration.mjs +0 -350
- package/scripts/lib/task-completion-consistency.mjs +0 -26
- package/scripts/lib/task-index.mjs +0 -93
- package/scripts/lib/task-lesson-candidates.mjs +0 -242
- package/scripts/lib/task-lesson-sedimentation.mjs +0 -326
- package/scripts/lib/task-lifecycle/create-task-helpers.mjs +0 -67
- package/scripts/lib/task-lifecycle/phase-sync.mjs +0 -88
- package/scripts/lib/task-lifecycle/review-confirm.mjs +0 -112
- package/scripts/lib/task-lifecycle/review-gates.mjs +0 -73
- package/scripts/lib/task-lifecycle/review-submission.mjs +0 -63
- package/scripts/lib/task-lifecycle/scaffold-provenance.mjs +0 -49
- package/scripts/lib/task-lifecycle/template-files.mjs +0 -53
- package/scripts/lib/task-lifecycle/text-utils.mjs +0 -24
- package/scripts/lib/task-lifecycle.mjs +0 -616
- package/scripts/lib/task-metadata.mjs +0 -118
- package/scripts/lib/task-review-model.mjs +0 -455
- package/scripts/lib/task-scanner.mjs +0 -503
- package/scripts/lib/task-tombstone-commands.mjs +0 -140
- package/scripts/postinstall.mjs +0 -14
- package/templates/walkthrough/Closeout-SSoT.md +0 -43
- package/templates-zh-CN/walkthrough/Closeout-SSoT.md +0 -42
- /package/examples/minimal-project/{docs → coding-agent-harness/governance/generated}/Harness-Ledger.md +0 -0
- /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/INDEX.md +0 -0
- /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/brief.md +0 -0
- /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/execution_strategy.md +0 -0
- /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/findings.md +0 -0
- /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/lesson_candidates.md +0 -0
- /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/task_plan.md +0 -0
- /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/visual_map.md +0 -0
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
|
|
23
23
|
## 归档索引
|
|
24
24
|
|
|
25
|
-
> 完成、取消或合并进其他模块的条目移入 `
|
|
25
|
+
> 完成、取消或合并进其他模块的条目移入 `coding-agent-harness/planning/modules/_archive/Module-Registry-archive-YYYY-QN.md`。
|
|
26
26
|
|
|
27
27
|
| 归档文件 | 覆盖模块 | 移入日期 | 说明 |
|
|
28
28
|
| --- | --- | --- | --- |
|
|
29
|
-
| `
|
|
29
|
+
| `coding-agent-harness/planning/modules/_archive/Module-Registry-archive-YYYY-QN.md` | [模块 Key 范围] | YYYY-MM-DD | [说明] |
|
|
30
30
|
|
|
31
31
|
## 状态说明
|
|
32
32
|
|
|
@@ -45,4 +45,4 @@
|
|
|
45
45
|
2. 模块状态变化要有对应的 module plan、progress、review 或 evidence 证据。
|
|
46
46
|
3. `ready-for-sync` 不能直接等同完成;协调者同步后才能标记 `completed`。
|
|
47
47
|
4. 写入范围变化必须先更新本表,再让 worker 修改文件。
|
|
48
|
-
5. 模块完成后,收口证据回写 Harness Ledger、Closeout
|
|
48
|
+
5. 模块完成后,收口证据回写 Harness Ledger、Closeout Index 和必要的 Feature / Regression SSoT。
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
|
|
28
28
|
## 归档索引
|
|
29
29
|
|
|
30
|
-
> 废弃 gate、已关闭残余和历史批次移入 `
|
|
30
|
+
> 废弃 gate、已关闭残余和历史批次移入 `coding-agent-harness/governance/regression/_archive/Regression-SSoT-archive-YYYY-QN.md`。活跃表只保留仍会影响当前开发和发布判断的内容。
|
|
31
31
|
|
|
32
32
|
| 归档文件 | 覆盖范围 | 移入日期 | 说明 |
|
|
33
33
|
| --- | --- | --- | --- |
|
|
34
|
-
| `
|
|
34
|
+
| `coding-agent-harness/governance/regression/_archive/Regression-SSoT-archive-YYYY-QN.md` | RG-... / R-... | YYYY-MM-DD | [说明] |
|
|
35
35
|
|
|
36
36
|
## 结果状态
|
|
37
37
|
|
|
@@ -47,16 +47,16 @@
|
|
|
47
47
|
| 是否出现跨模块、跨阶段、跨 agent 的重复问题? | [有 / 无,写一句理由] |
|
|
48
48
|
| 下次 agent 是否可能在同类任务中重复踩坑? | [有 / 无,写一句理由] |
|
|
49
49
|
| Lessons 结果 | `checked-candidate: LC-...` / `queued-promotion: LC-...` / `checked-created: L-YYYY-MM-DD-NNN` / 旧任务 `checked-none: [一句话原因]` |
|
|
50
|
-
| Lessons 详情文档 | `lesson_candidates.md` / `
|
|
50
|
+
| Lessons 详情文档 | `lesson_candidates.md` / `coding-agent-harness/governance/lessons/[file].md` / `none` |
|
|
51
51
|
|
|
52
52
|
## 关联索引
|
|
53
53
|
|
|
54
|
-
- 任务计划:`
|
|
55
|
-
- 进度记录:`
|
|
56
|
-
- 审查报告:`
|
|
54
|
+
- 任务计划:`coding-agent-harness/planning/tasks/[task]/task_plan.md`
|
|
55
|
+
- 进度记录:`coding-agent-harness/planning/tasks/[task]/progress.md`
|
|
56
|
+
- 审查报告:`coding-agent-harness/planning/tasks/[task]/review.md` / `n/a`
|
|
57
57
|
- 功能 SSoT:[F-...]
|
|
58
58
|
- Delivery SSoT:[DB-...] / `n/a`
|
|
59
59
|
- 回归 Gate:[RG-...] / `n/a`
|
|
60
60
|
- Harness Ledger:[HL-...]
|
|
61
|
-
-
|
|
61
|
+
- 任务本地收口:`walkthrough.md`
|
|
62
62
|
- Commit / PR:[hash、branch 或 PR 链接]
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2024",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"verbatimModuleSyntax": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
"checkJs": false,
|
|
11
|
+
"skipLibCheck": true
|
|
12
|
+
},
|
|
13
|
+
"include": [
|
|
14
|
+
"scripts/**/*.mts",
|
|
15
|
+
"scripts/**/*.ts",
|
|
16
|
+
"tests/**/*.mts",
|
|
17
|
+
"tests/**/*.ts"
|
|
18
|
+
],
|
|
19
|
+
"exclude": [
|
|
20
|
+
"node_modules",
|
|
21
|
+
".worktrees",
|
|
22
|
+
"tmp",
|
|
23
|
+
"dist"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2024",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"verbatimModuleSyntax": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"rootDir": ".",
|
|
9
|
+
"outDir": "tmp/runtime-emit",
|
|
10
|
+
"declaration": false,
|
|
11
|
+
"sourceMap": false,
|
|
12
|
+
"removeComments": false,
|
|
13
|
+
"skipLibCheck": true
|
|
14
|
+
},
|
|
15
|
+
"include": [
|
|
16
|
+
"scripts/**/*.mts"
|
|
17
|
+
],
|
|
18
|
+
"exclude": [
|
|
19
|
+
"node_modules",
|
|
20
|
+
".worktrees",
|
|
21
|
+
"tmp",
|
|
22
|
+
"dist"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -1,508 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { checkModuleParallelStructure } from "./lib/check-module-parallel.mjs";
|
|
6
|
-
|
|
7
|
-
const targetRoot = path.resolve(process.argv[2] || process.cwd());
|
|
8
|
-
const requireGlobalModuleSync = process.env.HARNESS_REQUIRE_GLOBAL_MODULE_SYNC === "1";
|
|
9
|
-
|
|
10
|
-
const requiredFiles = [
|
|
11
|
-
"AGENTS.md",
|
|
12
|
-
"CLAUDE.md",
|
|
13
|
-
"docs/Harness-Ledger.md",
|
|
14
|
-
"docs/11-REFERENCE/testing-standard.md",
|
|
15
|
-
"docs/11-REFERENCE/execution-workflow-standard.md",
|
|
16
|
-
"docs/11-REFERENCE/repo-governance-standard.md",
|
|
17
|
-
"docs/11-REFERENCE/ci-cd-standard.md",
|
|
18
|
-
"docs/11-REFERENCE/long-running-task-standard.md",
|
|
19
|
-
"docs/11-REFERENCE/adversarial-review-standard.md",
|
|
20
|
-
"docs/11-REFERENCE/review-routing-standard.md",
|
|
21
|
-
"docs/11-REFERENCE/docs-library-standard.md",
|
|
22
|
-
"docs/11-REFERENCE/harness-ledger-standard.md",
|
|
23
|
-
"docs/10-WALKTHROUGH/_walkthrough-template.md",
|
|
24
|
-
"docs/10-WALKTHROUGH/Closeout-SSoT.md",
|
|
25
|
-
"docs/05-TEST-QA/Regression-SSoT.md",
|
|
26
|
-
"docs/05-TEST-QA/Cadence-Ledger.md",
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
const legacyPlanningFiles = [
|
|
30
|
-
"docs/09-PLANNING/TASKS/_task-template/task_plan.md",
|
|
31
|
-
"docs/09-PLANNING/TASKS/_task-template/findings.md",
|
|
32
|
-
"docs/09-PLANNING/TASKS/_task-template/progress.md",
|
|
33
|
-
"docs/09-PLANNING/TASKS/_task-template/review.md",
|
|
34
|
-
"docs/09-PLANNING/TASKS/_task-template/long-running-task-contract.md",
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
const agAgentsRefs = [
|
|
38
|
-
"repo-governance-standard.md",
|
|
39
|
-
"ci-cd-standard.md",
|
|
40
|
-
"execution-workflow-standard.md",
|
|
41
|
-
"adversarial-review-standard.md",
|
|
42
|
-
"review-routing-standard.md",
|
|
43
|
-
"walkthrough-standard.md",
|
|
44
|
-
"harness-ledger-standard.md",
|
|
45
|
-
"Closeout-SSoT.md",
|
|
46
|
-
];
|
|
47
|
-
|
|
48
|
-
const forbiddenTemplatePatterns = [
|
|
49
|
-
/\[如有[^\]]*\]/,
|
|
50
|
-
/\[[^\]]*(根据项目|框架名|目标覆盖率|列出关键|示例)[^\]]*\]/,
|
|
51
|
-
/\[TODO\]/i,
|
|
52
|
-
/\bTODO\b/,
|
|
53
|
-
/\bTBD\b/i,
|
|
54
|
-
/\[command\]/,
|
|
55
|
-
/\[workflow path\]/,
|
|
56
|
-
/\[owner\/repo or URL\]/,
|
|
57
|
-
];
|
|
58
|
-
|
|
59
|
-
const statusWords = ["designed", "implemented", "verified", "blocked-with-owner"];
|
|
60
|
-
const closedLedgerStatuses = new Set(["closed", "closed-with-residual", "closed-local-only"]);
|
|
61
|
-
const allowedWalkthroughSkip =
|
|
62
|
-
/walkthrough skipped-with-reason:\s*(docs-only|no-runtime|superseded|historical-backfill|owner-deferred)/i;
|
|
63
|
-
const lessonsCreatedPattern = /checked-created:\s*(L-\d{4}-\d{2}-\d{2}-\d{3}|L-\d+)/i;
|
|
64
|
-
const lessonsNonePattern = /checked-none:\s*\S+/i;
|
|
65
|
-
const lessonsCandidatePattern = /checked-candidate:\s*(LC-[A-Za-z0-9-]+)/i;
|
|
66
|
-
const lessonsQueuedPromotionPattern = /queued-promotion:\s*(LC-[A-Za-z0-9-]+)/i;
|
|
67
|
-
|
|
68
|
-
const failures = [];
|
|
69
|
-
const warnings = [];
|
|
70
|
-
|
|
71
|
-
function rel(file) {
|
|
72
|
-
return file.split(path.sep).join("/");
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function filePath(relativePath) {
|
|
76
|
-
return path.join(targetRoot, relativePath);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function exists(relativePath) {
|
|
80
|
-
return fs.existsSync(filePath(relativePath));
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function read(relativePath) {
|
|
84
|
-
return fs.readFileSync(filePath(relativePath), "utf8");
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function fail(message) {
|
|
88
|
-
failures.push(message);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function warn(message) {
|
|
92
|
-
warnings.push(message);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function requireFile(relativePath) {
|
|
96
|
-
if (!exists(relativePath)) {
|
|
97
|
-
fail(`missing required file: ${relativePath}`);
|
|
98
|
-
return false;
|
|
99
|
-
}
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function checkRequiredFiles() {
|
|
104
|
-
for (const requiredFile of requiredFiles) {
|
|
105
|
-
requireFile(requiredFile);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function checkPlanningStructure() {
|
|
110
|
-
if (exists("docs/09-PLANNING/Module-Registry.md")) {
|
|
111
|
-
checkModuleParallelStructure({
|
|
112
|
-
exists,
|
|
113
|
-
fail,
|
|
114
|
-
filePath,
|
|
115
|
-
markdownTable,
|
|
116
|
-
read,
|
|
117
|
-
rel,
|
|
118
|
-
requireFile,
|
|
119
|
-
requireGlobalModuleSync,
|
|
120
|
-
targetRoot,
|
|
121
|
-
warn,
|
|
122
|
-
});
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
for (const legacyFile of legacyPlanningFiles) {
|
|
126
|
-
requireFile(legacyFile);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function checkAgentsIndex() {
|
|
131
|
-
if (!exists("AGENTS.md")) return;
|
|
132
|
-
const content = read("AGENTS.md");
|
|
133
|
-
for (const ref of agAgentsRefs) {
|
|
134
|
-
if (!content.includes(ref)) {
|
|
135
|
-
fail(`AGENTS.md does not route to ${ref}`);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
if (exists("docs/11-REFERENCE/delivery-operating-model-standard.md") && !content.includes("delivery-operating-model-standard.md")) {
|
|
139
|
-
fail("AGENTS.md does not route to delivery-operating-model-standard.md");
|
|
140
|
-
}
|
|
141
|
-
if (exists("docs/09-PLANNING/Module-Registry.md")) {
|
|
142
|
-
for (const ref of ["Module-Registry.md", "Session-Prompt-Pack.md"]) {
|
|
143
|
-
if (!content.includes(ref)) {
|
|
144
|
-
fail(`AGENTS.md does not route to ${ref}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
if (!/Subagent|worker/i.test(content) || !/worktree/i.test(content) || !/commit SHA|commit/i.test(content)) {
|
|
148
|
-
fail("AGENTS.md does not define subagent worker worktree/commit handoff rule");
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function checkNoGenericPlaceholders(relativePath, { allowTemplates = false } = {}) {
|
|
154
|
-
if (!exists(relativePath)) return;
|
|
155
|
-
const content = read(relativePath);
|
|
156
|
-
if (allowTemplates) return;
|
|
157
|
-
for (const pattern of forbiddenTemplatePatterns) {
|
|
158
|
-
if (pattern.test(content)) {
|
|
159
|
-
fail(`${relativePath} still contains generic placeholder matching ${pattern}`);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function checkGovernanceContent() {
|
|
165
|
-
const governancePath = "docs/11-REFERENCE/repo-governance-standard.md";
|
|
166
|
-
if (!exists(governancePath)) return;
|
|
167
|
-
const content = read(governancePath);
|
|
168
|
-
const requiredTerms = [
|
|
169
|
-
["Repo Platform Profile", "仓库平台画像"],
|
|
170
|
-
["Branch Model", "分支模型"],
|
|
171
|
-
["PR Policy", "PR 规则"],
|
|
172
|
-
["Required Checks", "必要检查"],
|
|
173
|
-
["Branch Protection", "分支保护"],
|
|
174
|
-
["Worktree Concurrency", "Worktree 并发"],
|
|
175
|
-
];
|
|
176
|
-
for (const terms of requiredTerms) {
|
|
177
|
-
if (!contentIncludesAny(content, terms)) fail(`${governancePath} missing section: ${terms[0]}`);
|
|
178
|
-
}
|
|
179
|
-
if (!statusWords.some((status) => content.includes(status))) {
|
|
180
|
-
fail(`${governancePath} does not use evidence status model`);
|
|
181
|
-
}
|
|
182
|
-
checkNoGenericPlaceholders(governancePath);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function checkCiCdContent() {
|
|
186
|
-
const ciPath = "docs/11-REFERENCE/ci-cd-standard.md";
|
|
187
|
-
if (!exists(ciPath)) return;
|
|
188
|
-
const content = read(ciPath);
|
|
189
|
-
const requiredTerms = [
|
|
190
|
-
["CI Profile", "CI 画像"],
|
|
191
|
-
["Workflow", "工作流"],
|
|
192
|
-
["Required Checks", "必要检查"],
|
|
193
|
-
["Evidence Status", "证据状态"],
|
|
194
|
-
];
|
|
195
|
-
for (const terms of requiredTerms) {
|
|
196
|
-
if (!contentIncludesAny(content, terms)) fail(`${ciPath} missing section: ${terms[0]}`);
|
|
197
|
-
}
|
|
198
|
-
if (!statusWords.some((status) => content.includes(status))) {
|
|
199
|
-
fail(`${ciPath} does not use evidence status model`);
|
|
200
|
-
}
|
|
201
|
-
checkNoGenericPlaceholders(ciPath);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function checkDeliveryOperatingModelContent() {
|
|
205
|
-
const deliveryPath = "docs/11-REFERENCE/delivery-operating-model-standard.md";
|
|
206
|
-
if (!exists(deliveryPath)) return;
|
|
207
|
-
const content = read(deliveryPath);
|
|
208
|
-
const normalized = content.toLowerCase();
|
|
209
|
-
const requiredTerms = [
|
|
210
|
-
["operating model profile", "运行模型"],
|
|
211
|
-
["work decomposition rule", "工作拆分规则"],
|
|
212
|
-
["agent visibility", "agent 可见性"],
|
|
213
|
-
["integration owner", "集成 owner"],
|
|
214
|
-
["delivery ssot", "交付 ssot"],
|
|
215
|
-
];
|
|
216
|
-
for (const terms of requiredTerms) {
|
|
217
|
-
if (!contentIncludesAny(normalized, terms.map((term) => term.toLowerCase()))) fail(`${deliveryPath} missing section: ${terms[0]}`);
|
|
218
|
-
}
|
|
219
|
-
if (!/solo-orchestrator|team-feature-lead|split-repo-contract|program-multi-repo|waterfall-stage-gate|kanban-continuous/.test(content)) {
|
|
220
|
-
fail(`${deliveryPath} does not define a recognized operating model`);
|
|
221
|
-
}
|
|
222
|
-
checkNoGenericPlaceholders(deliveryPath);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function checkPrTemplateOrResidual() {
|
|
226
|
-
const templateCandidates = [
|
|
227
|
-
".github/pull_request_template.md",
|
|
228
|
-
".github/PULL_REQUEST_TEMPLATE.md",
|
|
229
|
-
".gitlab/merge_request_templates/default.md",
|
|
230
|
-
];
|
|
231
|
-
if (templateCandidates.some((candidate) => exists(candidate))) return;
|
|
232
|
-
if (exists("docs/11-REFERENCE/repo-governance-standard.md")) {
|
|
233
|
-
const content = read("docs/11-REFERENCE/repo-governance-standard.md");
|
|
234
|
-
if (/PR template/i.test(content) && /blocked-with-owner|manual setup residual|manual-setup-residual/i.test(content)) {
|
|
235
|
-
warn("PR template missing, but repo governance records residual");
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
fail("missing PR template or explicit blocked-with-owner residual");
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function checkWorkflowOrResidual() {
|
|
243
|
-
const workflowDir = filePath(".github/workflows");
|
|
244
|
-
const hasGitHubWorkflow =
|
|
245
|
-
fs.existsSync(workflowDir) &&
|
|
246
|
-
fs.readdirSync(workflowDir).some((name) => /\.(ya?ml)$/i.test(name));
|
|
247
|
-
if (hasGitHubWorkflow) return;
|
|
248
|
-
if (exists("docs/11-REFERENCE/ci-cd-standard.md")) {
|
|
249
|
-
const content = read("docs/11-REFERENCE/ci-cd-standard.md");
|
|
250
|
-
if (/blocked-with-owner|unsupported checks|residual/i.test(content)) {
|
|
251
|
-
warn("CI workflow missing, but CI/CD standard records residual");
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
fail("missing CI workflow or explicit blocked-with-owner residual");
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function checkReviewTemplate() {
|
|
259
|
-
const reviewPath = "docs/09-PLANNING/TASKS/_task-template/review.md";
|
|
260
|
-
if (!exists(reviewPath)) return;
|
|
261
|
-
const content = read(reviewPath);
|
|
262
|
-
if (!contentIncludesAny(content, ["Confidence Challenge", "信心挑战"])) {
|
|
263
|
-
fail(`${reviewPath} missing Confidence Challenge`);
|
|
264
|
-
}
|
|
265
|
-
if (/\|\s*R-001\s*\|\s*P[01]\s*\|.*\|\s*open\s*\|/i.test(content)) {
|
|
266
|
-
fail(`${reviewPath} ships with an open P0/P1 example finding`);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function checkHarnessLedger() {
|
|
271
|
-
if (!exists("docs/Harness-Ledger.md")) return;
|
|
272
|
-
const content = read("docs/Harness-Ledger.md");
|
|
273
|
-
if (!/Repo Governance|CI\/CD|ci-cd|repo-governance/i.test(content)) {
|
|
274
|
-
fail("docs/Harness-Ledger.md does not mention repo governance / CI-CD update status");
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
function markdownTableRows(content, idPattern) {
|
|
279
|
-
return content
|
|
280
|
-
.split(/\r?\n/)
|
|
281
|
-
.filter((line) => line.trim().startsWith("|"))
|
|
282
|
-
.map((line) => line.split("|").slice(1, -1).map((cell) => cell.trim()))
|
|
283
|
-
.filter((cells) => cells.length > 0 && idPattern.test(cells[0] || ""));
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
function markdownTable(content) {
|
|
287
|
-
return content
|
|
288
|
-
.split(/\r?\n/)
|
|
289
|
-
.filter((line) => line.trim().startsWith("|"))
|
|
290
|
-
.map((line) => line.split("|").slice(1, -1).map((cell) => cell.trim()));
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
function findHeaderIndex(rows, pattern) {
|
|
294
|
-
return rows.findIndex((cells) => cells.some((cell) => pattern.test(cell)));
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function contentIncludesAny(content, terms) {
|
|
298
|
-
return terms.some((term) => (term instanceof RegExp ? term.test(content) : content.includes(term)));
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
function columnIndexAny(header, patterns) {
|
|
302
|
-
return header.findIndex((cell) => patterns.some((pattern) => pattern.test(cell)));
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
function checkDuplicateIds(rows, sourcePath) {
|
|
306
|
-
const seen = new Set();
|
|
307
|
-
for (const cells of rows) {
|
|
308
|
-
const id = cells[0];
|
|
309
|
-
if (seen.has(id)) {
|
|
310
|
-
fail(`${sourcePath} contains duplicate closeout id: ${id}`);
|
|
311
|
-
}
|
|
312
|
-
seen.add(id);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
function checkCloseoutSsot() {
|
|
317
|
-
const closeoutPath = "docs/10-WALKTHROUGH/Closeout-SSoT.md";
|
|
318
|
-
if (!exists(closeoutPath)) return;
|
|
319
|
-
|
|
320
|
-
const closeoutContent = read(closeoutPath);
|
|
321
|
-
for (const terms of [["Walkthrough"], ["Lessons Check", "Lessons 检查"], ["Closeout Status", "收口状态"]]) {
|
|
322
|
-
if (!contentIncludesAny(closeoutContent, terms)) {
|
|
323
|
-
fail(`${closeoutPath} missing required closeout column or section: ${terms[0]}`);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
checkNoGenericPlaceholders(closeoutPath);
|
|
327
|
-
|
|
328
|
-
const closeoutTable = markdownTable(closeoutContent);
|
|
329
|
-
const closeoutHeaderIndex = findHeaderIndex(closeoutTable, /^Harness ID$/i);
|
|
330
|
-
const closeoutHeader = closeoutHeaderIndex >= 0 ? closeoutTable[closeoutHeaderIndex] : [];
|
|
331
|
-
const lessonsColumn = columnIndexAny(closeoutHeader, [/^Lessons Check$/i, /^Lessons 检查$/i, /^Lessons 检查\s*\/\s*Lessons Check$/i]);
|
|
332
|
-
if (lessonsColumn < 0) {
|
|
333
|
-
fail(`${closeoutPath} missing Lessons Check column`);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
if (!exists("docs/Harness-Ledger.md")) return;
|
|
337
|
-
const ledgerContent = read("docs/Harness-Ledger.md");
|
|
338
|
-
const lessonIds = collectLessonIds();
|
|
339
|
-
const lessonCandidateIds = collectLessonCandidateIds();
|
|
340
|
-
const ledgerTable = markdownTable(ledgerContent);
|
|
341
|
-
const ledgerHeaderIndex = findHeaderIndex(ledgerTable, /^ID$/i);
|
|
342
|
-
const ledgerHeader = ledgerHeaderIndex >= 0 ? ledgerTable[ledgerHeaderIndex] : [];
|
|
343
|
-
const ledgerLessonsColumn = columnIndexAny(ledgerHeader, [/^Lessons Check$/i, /^Lessons 检查$/i, /^Lessons 检查\s*\/\s*Lessons Check$/i]);
|
|
344
|
-
if (ledgerLessonsColumn < 0) {
|
|
345
|
-
fail("docs/Harness-Ledger.md missing Lessons Check column");
|
|
346
|
-
}
|
|
347
|
-
const ledgerRows = markdownTableRows(ledgerContent, /^H-\d+/i);
|
|
348
|
-
const closeoutTableRows = markdownTableRows(closeoutContent, /^H-\d+/i);
|
|
349
|
-
checkDuplicateIds(ledgerRows, "docs/Harness-Ledger.md");
|
|
350
|
-
checkDuplicateIds(closeoutTableRows, closeoutPath);
|
|
351
|
-
const closeoutRows = new Map(closeoutTableRows.map((cells) => [cells[0], cells]));
|
|
352
|
-
|
|
353
|
-
for (const cells of ledgerRows) {
|
|
354
|
-
const id = cells[0];
|
|
355
|
-
const status = (cells[cells.length - 1] || "").toLowerCase();
|
|
356
|
-
if (!closedLedgerStatuses.has(status)) continue;
|
|
357
|
-
|
|
358
|
-
const closeout = closeoutRows.get(id);
|
|
359
|
-
if (!closeout) {
|
|
360
|
-
fail(`${closeoutPath} missing row for closed Harness Ledger item ${id}`);
|
|
361
|
-
continue;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const joined = closeout.join(" ");
|
|
365
|
-
const hasWalkthrough = /docs\/10-WALKTHROUGH\/[^|\s]+\.md/.test(joined);
|
|
366
|
-
const hasAllowedSkip = allowedWalkthroughSkip.test(joined);
|
|
367
|
-
if (!hasWalkthrough && !hasAllowedSkip) {
|
|
368
|
-
fail(`${closeoutPath} row ${id} needs walkthrough path or allowed skipped-with-reason`);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
if (lessonsColumn >= 0) {
|
|
372
|
-
const lessonsCheck = closeout[lessonsColumn] || "";
|
|
373
|
-
const createdMatch = lessonsCheck.match(lessonsCreatedPattern);
|
|
374
|
-
const candidateMatch = lessonsCheck.match(lessonsCandidatePattern) || lessonsCheck.match(lessonsQueuedPromotionPattern);
|
|
375
|
-
if (!createdMatch && !candidateMatch && !lessonsNonePattern.test(lessonsCheck)) {
|
|
376
|
-
fail(`${closeoutPath} row ${id} needs Lessons Check value: checked-created:<lesson-id>, checked-candidate:<candidate-id>, queued-promotion:<candidate-id>, or checked-none:<reason>`);
|
|
377
|
-
} else if (createdMatch && !lessonIds.has(createdMatch[1])) {
|
|
378
|
-
fail(`${closeoutPath} row ${id} references missing lesson detail doc id: ${createdMatch[1]}`);
|
|
379
|
-
} else if (candidateMatch && !lessonCandidateIds.has(candidateMatch[1])) {
|
|
380
|
-
fail(`${closeoutPath} row ${id} references missing lesson candidate id: ${candidateMatch[1]}`);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
if (ledgerLessonsColumn >= 0) {
|
|
385
|
-
const ledgerLessonsCheck = cells[ledgerLessonsColumn] || "";
|
|
386
|
-
const ledgerCreatedMatch = ledgerLessonsCheck.match(lessonsCreatedPattern);
|
|
387
|
-
const ledgerCandidateMatch = ledgerLessonsCheck.match(lessonsCandidatePattern) || ledgerLessonsCheck.match(lessonsQueuedPromotionPattern);
|
|
388
|
-
if (!ledgerCreatedMatch && !ledgerCandidateMatch && !lessonsNonePattern.test(ledgerLessonsCheck)) {
|
|
389
|
-
fail(`docs/Harness-Ledger.md row ${id} needs Lessons Check value: checked-created:<lesson-id>, checked-candidate:<candidate-id>, queued-promotion:<candidate-id>, or checked-none:<reason>`);
|
|
390
|
-
} else if (ledgerCreatedMatch && !lessonIds.has(ledgerCreatedMatch[1])) {
|
|
391
|
-
fail(`docs/Harness-Ledger.md row ${id} references missing lesson detail doc id: ${ledgerCreatedMatch[1]}`);
|
|
392
|
-
} else if (ledgerCandidateMatch && !lessonCandidateIds.has(ledgerCandidateMatch[1])) {
|
|
393
|
-
fail(`docs/Harness-Ledger.md row ${id} references missing lesson candidate id: ${ledgerCandidateMatch[1]}`);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
function collectLessonIds() {
|
|
400
|
-
const root = filePath("docs/01-GOVERNANCE/lessons");
|
|
401
|
-
const ids = new Set();
|
|
402
|
-
if (!fs.existsSync(root)) return ids;
|
|
403
|
-
for (const entry of fs.readdirSync(root)) {
|
|
404
|
-
if (!entry.endsWith(".md")) continue;
|
|
405
|
-
const full = path.join(root, entry);
|
|
406
|
-
if (!fs.statSync(full).isFile()) continue;
|
|
407
|
-
const content = fs.readFileSync(full, "utf8");
|
|
408
|
-
const pathMatch = entry.match(/(L-\d{4}(?:-\d{2}-\d{2})?-\d+)/i);
|
|
409
|
-
const titleMatch = content.match(/#\s*(L-\d{4}(?:-\d{2}-\d{2})?-\d+)/i);
|
|
410
|
-
const id = titleMatch?.[1] || pathMatch?.[1];
|
|
411
|
-
if (id) ids.add(id);
|
|
412
|
-
}
|
|
413
|
-
return ids;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
function collectLessonCandidateIds() {
|
|
417
|
-
const root = filePath("docs/09-PLANNING");
|
|
418
|
-
const ids = new Set();
|
|
419
|
-
if (!fs.existsSync(root)) return ids;
|
|
420
|
-
function visit(dir) {
|
|
421
|
-
for (const entry of fs.readdirSync(dir)) {
|
|
422
|
-
const full = path.join(dir, entry);
|
|
423
|
-
const stat = fs.statSync(full);
|
|
424
|
-
if (stat.isDirectory()) {
|
|
425
|
-
if (entry === "_archive") continue;
|
|
426
|
-
visit(full);
|
|
427
|
-
continue;
|
|
428
|
-
}
|
|
429
|
-
if (entry !== "lesson_candidates.md") continue;
|
|
430
|
-
const content = fs.readFileSync(full, "utf8");
|
|
431
|
-
for (const match of content.matchAll(/\|\s*(LC-[A-Za-z0-9-]+)\s*\|/g)) {
|
|
432
|
-
ids.add(match[1]);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
visit(root);
|
|
437
|
-
return ids;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
function checkLessonDetailDocs() {
|
|
441
|
-
const root = filePath("docs/01-GOVERNANCE/lessons");
|
|
442
|
-
if (!fs.existsSync(root)) return;
|
|
443
|
-
for (const entry of fs.readdirSync(root)) {
|
|
444
|
-
if (!entry.endsWith(".md")) continue;
|
|
445
|
-
const relativePath = `docs/01-GOVERNANCE/lessons/${entry}`;
|
|
446
|
-
const content = read(relativePath);
|
|
447
|
-
const id = entry.match(/(L-\d{4}(?:-\d{2}-\d{2})?-\d+)/i)?.[1];
|
|
448
|
-
if (id && !content.includes(id)) {
|
|
449
|
-
fail(`${relativePath} does not include lesson id ${id}`);
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
function checkWalkthroughTemplate() {
|
|
455
|
-
const walkthroughTemplate = "docs/10-WALKTHROUGH/_walkthrough-template.md";
|
|
456
|
-
if (!exists(walkthroughTemplate)) return;
|
|
457
|
-
const content = read(walkthroughTemplate);
|
|
458
|
-
if (!contentIncludesAny(content, ["Lessons Reflection", "Lessons 回看"])) {
|
|
459
|
-
fail(`${walkthroughTemplate} missing Lessons Reflection section`);
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
function checkReferencePlaceholders() {
|
|
464
|
-
const refDir = filePath("docs/11-REFERENCE");
|
|
465
|
-
if (!fs.existsSync(refDir)) return;
|
|
466
|
-
for (const entry of fs.readdirSync(refDir)) {
|
|
467
|
-
const full = path.join(refDir, entry);
|
|
468
|
-
if (!fs.statSync(full).isFile() || !entry.endsWith(".md")) continue;
|
|
469
|
-
checkNoGenericPlaceholders(rel(path.relative(targetRoot, full)));
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
function main() {
|
|
474
|
-
if (!fs.existsSync(targetRoot)) {
|
|
475
|
-
console.error(`Target path does not exist: ${targetRoot}`);
|
|
476
|
-
process.exit(2);
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
checkRequiredFiles();
|
|
480
|
-
checkPlanningStructure();
|
|
481
|
-
checkAgentsIndex();
|
|
482
|
-
checkGovernanceContent();
|
|
483
|
-
checkCiCdContent();
|
|
484
|
-
checkDeliveryOperatingModelContent();
|
|
485
|
-
checkPrTemplateOrResidual();
|
|
486
|
-
checkWorkflowOrResidual();
|
|
487
|
-
checkReviewTemplate();
|
|
488
|
-
checkHarnessLedger();
|
|
489
|
-
checkCloseoutSsot();
|
|
490
|
-
checkLessonDetailDocs();
|
|
491
|
-
checkWalkthroughTemplate();
|
|
492
|
-
checkReferencePlaceholders();
|
|
493
|
-
|
|
494
|
-
if (warnings.length > 0) {
|
|
495
|
-
console.log("Warnings:");
|
|
496
|
-
for (const warning of warnings) console.log(`- ${warning}`);
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
if (failures.length > 0) {
|
|
500
|
-
console.error("Harness check failed:");
|
|
501
|
-
for (const failure of failures) console.error(`- ${failure}`);
|
|
502
|
-
process.exit(1);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
console.log(`Harness check passed: ${targetRoot}`);
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
main();
|