coding-agent-harness 1.0.4 → 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.
Files changed (279) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/CONTRIBUTING.md +2 -2
  3. package/LICENSE +661 -21
  4. package/LICENSE-EXCEPTION.md +37 -0
  5. package/README.md +96 -4
  6. package/README.zh-CN.md +75 -4
  7. package/SKILL.md +52 -51
  8. package/dist/build-dist.mjs +189 -0
  9. package/dist/check-dist-observation.mjs +428 -0
  10. package/dist/check-harness.mjs +489 -0
  11. package/dist/check-import-graph.mjs +511 -0
  12. package/dist/check-runtime-emit.mjs +304 -0
  13. package/dist/check-type-boundaries.mjs +139 -0
  14. package/dist/commands/dashboard-command.mjs +80 -0
  15. package/dist/commands/migration-command.mjs +152 -0
  16. package/dist/commands/preset-command.mjs +91 -0
  17. package/dist/commands/task-command.mjs +324 -0
  18. package/dist/harness.mjs +304 -0
  19. package/dist/lib/capability-registry.mjs +643 -0
  20. package/dist/lib/check-module-parallel.mjs +227 -0
  21. package/dist/lib/check-profiles.mjs +414 -0
  22. package/dist/lib/check-task-contracts.mjs +54 -0
  23. package/dist/lib/core-shared.mjs +254 -0
  24. package/dist/lib/dashboard-data.mjs +608 -0
  25. package/dist/lib/dashboard-workbench.mjs +334 -0
  26. package/dist/lib/dashboard-writer.mjs +200 -0
  27. package/dist/lib/git-status-summary.mjs +45 -0
  28. package/dist/lib/governance-index-generator.mjs +236 -0
  29. package/dist/lib/governance-sync.mjs +617 -0
  30. package/dist/lib/governance-table-boundary.mjs +161 -0
  31. package/{scripts → dist}/lib/harness-core.mjs +3 -0
  32. package/dist/lib/harness-paths.mjs +338 -0
  33. package/dist/lib/lesson-maintenance.mjs +139 -0
  34. package/dist/lib/markdown-utils.mjs +193 -0
  35. package/dist/lib/migration-planner.mjs +439 -0
  36. package/dist/lib/migration-support.mjs +317 -0
  37. package/dist/lib/phase-kind.mjs +46 -0
  38. package/dist/lib/preset-audit-contracts.mjs +40 -0
  39. package/dist/lib/preset-engine.mjs +516 -0
  40. package/dist/lib/preset-registry.mjs +831 -0
  41. package/dist/lib/preset-resource-contracts.mjs +83 -0
  42. package/dist/lib/review-confirm-git-gate.mjs +244 -0
  43. package/dist/lib/status-builder.mjs +87 -0
  44. package/{scripts → dist}/lib/status-dashboard-renderer.mjs +48 -47
  45. package/dist/lib/structure-migration.mjs +404 -0
  46. package/dist/lib/subagent-authorization-audit.mjs +198 -0
  47. package/dist/lib/task-audit-metadata.mjs +376 -0
  48. package/dist/lib/task-audit-migration.mjs +355 -0
  49. package/dist/lib/task-completion-consistency.mjs +29 -0
  50. package/dist/lib/task-index.mjs +133 -0
  51. package/dist/lib/task-lesson-candidates.mjs +239 -0
  52. package/dist/lib/task-lesson-sedimentation.mjs +300 -0
  53. package/dist/lib/task-lifecycle/create-task-helpers.mjs +84 -0
  54. package/dist/lib/task-lifecycle/phase-sync.mjs +82 -0
  55. package/dist/lib/task-lifecycle/review-confirm.mjs +93 -0
  56. package/dist/lib/task-lifecycle/review-gates.mjs +62 -0
  57. package/dist/lib/task-lifecycle/review-submission.mjs +52 -0
  58. package/dist/lib/task-lifecycle/scaffold-provenance.mjs +54 -0
  59. package/dist/lib/task-lifecycle/template-files.mjs +52 -0
  60. package/dist/lib/task-lifecycle/text-utils.mjs +26 -0
  61. package/dist/lib/task-lifecycle.mjs +611 -0
  62. package/dist/lib/task-metadata.mjs +116 -0
  63. package/dist/lib/task-review-model.mjs +474 -0
  64. package/dist/lib/task-scanner.mjs +439 -0
  65. package/dist/lib/task-tombstone-commands.mjs +125 -0
  66. package/dist/postinstall.mjs +14 -0
  67. package/dist/run-built-tests.mjs +84 -0
  68. package/docs-release/README.md +1 -0
  69. package/docs-release/architecture/overview.md +13 -13
  70. package/docs-release/architecture/overview.zh-CN.md +13 -13
  71. package/docs-release/architecture/system-explainer/01-system-overview.md +218 -0
  72. package/docs-release/architecture/system-explainer/02-module-dependency.md +257 -0
  73. package/docs-release/architecture/system-explainer/03-task-lifecycle.md +304 -0
  74. package/docs-release/architecture/system-explainer/04-check-and-governance.md +241 -0
  75. package/docs-release/architecture/system-explainer/05-data-flow.md +276 -0
  76. package/docs-release/architecture/system-explainer/06-preset-and-migration.md +300 -0
  77. package/docs-release/architecture/system-explainer/README.md +67 -0
  78. package/docs-release/architecture/system-explainer/en-US/01-system-overview.md +227 -0
  79. package/docs-release/architecture/system-explainer/en-US/02-module-dependency.md +263 -0
  80. package/docs-release/architecture/system-explainer/en-US/03-task-lifecycle.md +319 -0
  81. package/docs-release/architecture/system-explainer/en-US/04-check-and-governance.md +252 -0
  82. package/docs-release/architecture/system-explainer/en-US/05-data-flow.md +290 -0
  83. package/docs-release/architecture/system-explainer/en-US/06-preset-and-migration.md +320 -0
  84. package/docs-release/architecture/system-explainer/en-US/README.md +70 -0
  85. package/docs-release/guides/agent-installation.en-US.md +22 -15
  86. package/docs-release/guides/agent-installation.md +23 -15
  87. package/docs-release/guides/contributing.md +3 -3
  88. package/docs-release/guides/contributing.zh-CN.md +3 -3
  89. package/docs-release/guides/document-audience-and-surfaces.en-US.md +10 -10
  90. package/docs-release/guides/document-audience-and-surfaces.md +10 -10
  91. package/docs-release/guides/legacy-migration-agent-prompt.md +25 -2
  92. package/docs-release/guides/legacy-migration-agent-prompt.zh-CN.md +25 -2
  93. package/docs-release/guides/migration-playbook.en-US.md +63 -1
  94. package/docs-release/guides/migration-playbook.md +59 -1
  95. package/docs-release/guides/parent-control-repository-pattern.en-US.md +25 -25
  96. package/docs-release/guides/parent-control-repository-pattern.md +25 -25
  97. package/docs-release/guides/preset-development.md +28 -4
  98. package/docs-release/guides/repository-operating-models.en-US.md +21 -21
  99. package/docs-release/guides/repository-operating-models.md +21 -21
  100. package/docs-release/guides/task-state-machine.en-US.md +35 -18
  101. package/docs-release/guides/task-state-machine.md +35 -18
  102. package/docs-release/guides/typescript-runtime-migration-closeout.md +96 -0
  103. package/examples/minimal-project/AGENTS.md +2 -2
  104. package/examples/minimal-project/coding-agent-harness/harness.yaml +14 -0
  105. package/examples/minimal-project/coding-agent-harness/planning/tasks/demo-task/INDEX.md +60 -0
  106. package/examples/minimal-project/coding-agent-harness/planning/tasks/demo-task/progress.md +11 -0
  107. package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/review.md +1 -1
  108. package/package.json +22 -13
  109. package/presets/legacy-migration/preset.yaml +5 -5
  110. package/presets/legacy-migration/templates/execution_strategy.append.md +1 -1
  111. package/presets/lesson-sedimentation/preset.yaml +3 -3
  112. package/presets/module/preset.yaml +2 -2
  113. package/presets/module/templates/execution_strategy.append.md +1 -1
  114. package/presets/module/templates/task_plan.append.md +3 -3
  115. package/presets/standard-task/preset.yaml +2 -2
  116. package/references/adversarial-review-standard.md +2 -2
  117. package/references/agents-md-pattern.md +14 -14
  118. package/references/cadence-ledger.md +1 -1
  119. package/references/ci-cd-standard.md +1 -1
  120. package/references/delivery-operating-model-standard.md +4 -4
  121. package/references/docs-directory-standard.md +65 -159
  122. package/references/external-source-intake-standard.md +10 -10
  123. package/references/harness-ledger.md +6 -6
  124. package/references/legacy-12-phase-bootstrap.md +2 -2
  125. package/references/lessons-governance.md +15 -15
  126. package/references/long-running-task-standard.md +6 -6
  127. package/references/module-parallel-standard.md +34 -34
  128. package/references/planning-loop.md +6 -6
  129. package/references/project-onboarding-audit.md +4 -4
  130. package/references/regression-system.md +2 -2
  131. package/references/repo-governance-standard.md +4 -4
  132. package/references/review-routing-standard.md +1 -1
  133. package/references/ssot-governance.md +19 -19
  134. package/references/taskr-gap-analysis.md +5 -5
  135. package/references/walkthrough-closeout.md +14 -14
  136. package/references/worktree-parallel.md +3 -3
  137. package/skills/preset-creator/references/complex-task-skeleton/brief.md +11 -0
  138. package/skills/preset-creator/references/complex-task-skeleton/task_plan.md +1 -1
  139. package/skills/preset-creator/references/preset-package-skeleton.md +5 -5
  140. package/templates/AGENTS.md.template +31 -29
  141. package/templates/architecture/README.md +4 -4
  142. package/templates/architecture/service-catalog.md +2 -2
  143. package/templates/architecture/services/service-template.md +1 -1
  144. package/templates/dashboard/assets/app-src/00-state.js +12 -0
  145. package/templates/dashboard/assets/app-src/10-router.js +3 -0
  146. package/templates/dashboard/assets/app-src/20-overview.js +13 -3
  147. package/templates/dashboard/assets/app-src/35-task-detail.js +46 -6
  148. package/templates/dashboard/assets/app-src/40-modules.js +1 -1
  149. package/templates/dashboard/assets/app-src/55-presets.js +375 -0
  150. package/templates/dashboard/assets/app-src/60-shared.js +3 -1
  151. package/templates/dashboard/assets/app-src/90-bindings.js +131 -0
  152. package/templates/dashboard/assets/app.css +583 -0
  153. package/templates/dashboard/assets/app.css.manifest.json +1 -0
  154. package/templates/dashboard/assets/app.js +585 -11
  155. package/templates/dashboard/assets/app.manifest.json +1 -0
  156. package/templates/dashboard/assets/css-src/00-foundation.css +4 -0
  157. package/templates/dashboard/assets/css-src/40-detail-modules-migration.css +62 -0
  158. package/templates/dashboard/assets/css-src/45-presets.css +516 -0
  159. package/templates/dashboard/assets/i18n.js +144 -4
  160. package/templates/development/README.md +10 -10
  161. package/templates/development/cross-repo-debugging.md +3 -3
  162. package/templates/development/external-context/service-template.md +2 -2
  163. package/templates/development/external-source-packs/README.md +4 -4
  164. package/templates/integrations/README.md +4 -4
  165. package/templates/integrations/api-contract.md +2 -2
  166. package/templates/integrations/event-contract.md +2 -2
  167. package/templates/integrations/third-party/vendor-template.md +2 -2
  168. package/templates/integrations/webhook-contract.md +2 -2
  169. package/templates/ledger/Harness-Ledger.md +1 -1
  170. package/templates/planning/INDEX.md +88 -0
  171. package/templates/planning/brief.md +1 -1
  172. package/templates/planning/module_session_prompt.md +2 -1
  173. package/templates/planning/review.md +0 -18
  174. package/templates/planning/task_plan.md +5 -44
  175. package/templates/planning/visual_map.md +13 -9
  176. package/templates/planning/visual_map.simple.md +52 -0
  177. package/templates/planning/walkthrough.md +47 -0
  178. package/templates/reference/docs-library-standard.md +8 -8
  179. package/templates/reference/execution-workflow-standard.md +29 -2
  180. package/templates/reference/external-source-intake-standard.md +15 -15
  181. package/templates/reference/repo-governance-standard.md +1 -1
  182. package/templates/ssot/Module-Registry.md +1 -1
  183. package/templates/walkthrough/walkthrough-template.md +2 -2
  184. package/templates-zh-CN/AGENTS.md.template +31 -29
  185. package/templates-zh-CN/CLAUDE.md.template +1 -1
  186. package/templates-zh-CN/architecture/README.md +4 -4
  187. package/templates-zh-CN/architecture/service-catalog.md +2 -2
  188. package/templates-zh-CN/architecture/services/service-template.md +1 -1
  189. package/templates-zh-CN/development/README.md +10 -10
  190. package/templates-zh-CN/development/cross-repo-debugging.md +3 -3
  191. package/templates-zh-CN/development/external-context/service-template.md +2 -2
  192. package/templates-zh-CN/development/external-source-packs/README.md +4 -4
  193. package/templates-zh-CN/integrations/README.md +4 -4
  194. package/templates-zh-CN/integrations/api-contract.md +2 -2
  195. package/templates-zh-CN/integrations/event-contract.md +2 -2
  196. package/templates-zh-CN/integrations/third-party/vendor-template.md +2 -2
  197. package/templates-zh-CN/integrations/webhook-contract.md +2 -2
  198. package/templates-zh-CN/ledger/Harness-Ledger.md +1 -1
  199. package/templates-zh-CN/lessons/lesson-arch-process-change.md +1 -1
  200. package/templates-zh-CN/lessons/lesson-new-doc.md +3 -3
  201. package/templates-zh-CN/lessons/lesson-ref-change.md +4 -4
  202. package/templates-zh-CN/planning/INDEX.md +87 -0
  203. package/templates-zh-CN/planning/brief.md +1 -1
  204. package/templates-zh-CN/planning/module_session_prompt.md +12 -11
  205. package/templates-zh-CN/planning/review.md +0 -18
  206. package/templates-zh-CN/planning/task_plan.md +3 -63
  207. package/templates-zh-CN/planning/visual_map.md +14 -7
  208. package/templates-zh-CN/planning/visual_map.simple.md +48 -0
  209. package/templates-zh-CN/planning/walkthrough.md +47 -0
  210. package/templates-zh-CN/reference/adversarial-review-standard.md +2 -2
  211. package/templates-zh-CN/reference/delivery-operating-model-standard.md +3 -3
  212. package/templates-zh-CN/reference/docs-library-standard.md +28 -28
  213. package/templates-zh-CN/reference/execution-workflow-standard.md +32 -7
  214. package/templates-zh-CN/reference/external-source-intake-standard.md +16 -16
  215. package/templates-zh-CN/reference/harness-ledger-standard.md +6 -6
  216. package/templates-zh-CN/reference/regression-ssot-governance.md +2 -2
  217. package/templates-zh-CN/reference/repo-governance-standard.md +1 -1
  218. package/templates-zh-CN/reference/review-routing-standard.md +1 -1
  219. package/templates-zh-CN/reference/walkthrough-standard.md +7 -7
  220. package/templates-zh-CN/reference/worktree-standard.md +1 -1
  221. package/templates-zh-CN/regression/Cadence-Ledger.md +2 -2
  222. package/templates-zh-CN/ssot/Delivery-SSoT.md +3 -3
  223. package/templates-zh-CN/ssot/Module-Registry.md +3 -3
  224. package/templates-zh-CN/ssot/Regression-SSoT.md +2 -2
  225. package/templates-zh-CN/walkthrough/walkthrough-template.md +5 -5
  226. package/tsconfig.dist.json +16 -0
  227. package/tsconfig.json +25 -0
  228. package/tsconfig.runtime.json +24 -0
  229. package/examples/minimal-project/.harness-capabilities.json +0 -8
  230. package/examples/minimal-project/docs/09-PLANNING/TASKS/demo-task/progress.md +0 -11
  231. package/scripts/check-harness.mjs +0 -508
  232. package/scripts/commands/dashboard-command.mjs +0 -67
  233. package/scripts/commands/migration-command.mjs +0 -96
  234. package/scripts/commands/preset-command.mjs +0 -73
  235. package/scripts/commands/task-command.mjs +0 -327
  236. package/scripts/harness.mjs +0 -287
  237. package/scripts/lib/capability-registry.mjs +0 -591
  238. package/scripts/lib/check-module-parallel.mjs +0 -237
  239. package/scripts/lib/check-profiles.mjs +0 -418
  240. package/scripts/lib/check-task-contracts.mjs +0 -47
  241. package/scripts/lib/core-shared.mjs +0 -196
  242. package/scripts/lib/dashboard-data.mjs +0 -412
  243. package/scripts/lib/dashboard-workbench.mjs +0 -257
  244. package/scripts/lib/dashboard-writer.mjs +0 -198
  245. package/scripts/lib/git-status-summary.mjs +0 -46
  246. package/scripts/lib/governance-index-generator.mjs +0 -174
  247. package/scripts/lib/governance-sync.mjs +0 -514
  248. package/scripts/lib/governance-table-boundary.mjs +0 -175
  249. package/scripts/lib/lesson-maintenance.mjs +0 -152
  250. package/scripts/lib/markdown-utils.mjs +0 -158
  251. package/scripts/lib/migration-planner.mjs +0 -478
  252. package/scripts/lib/migration-support.mjs +0 -312
  253. package/scripts/lib/preset-audit-contracts.mjs +0 -37
  254. package/scripts/lib/preset-engine.mjs +0 -497
  255. package/scripts/lib/preset-registry.mjs +0 -627
  256. package/scripts/lib/preset-resource-contracts.mjs +0 -83
  257. package/scripts/lib/review-confirm-git-gate.mjs +0 -248
  258. package/scripts/lib/subagent-authorization-audit.mjs +0 -196
  259. package/scripts/lib/task-completion-consistency.mjs +0 -16
  260. package/scripts/lib/task-index.mjs +0 -93
  261. package/scripts/lib/task-lesson-candidates.mjs +0 -242
  262. package/scripts/lib/task-lesson-sedimentation.mjs +0 -326
  263. package/scripts/lib/task-lifecycle/review-confirm.mjs +0 -101
  264. package/scripts/lib/task-lifecycle/review-gates.mjs +0 -70
  265. package/scripts/lib/task-lifecycle/text-utils.mjs +0 -24
  266. package/scripts/lib/task-lifecycle.mjs +0 -649
  267. package/scripts/lib/task-review-model.mjs +0 -469
  268. package/scripts/lib/task-scanner.mjs +0 -576
  269. package/scripts/lib/task-tombstone-commands.mjs +0 -140
  270. package/scripts/postinstall.mjs +0 -14
  271. package/templates/walkthrough/Closeout-SSoT.md +0 -43
  272. package/templates-zh-CN/walkthrough/Closeout-SSoT.md +0 -42
  273. /package/examples/minimal-project/{docs → coding-agent-harness/governance/generated}/Harness-Ledger.md +0 -0
  274. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/brief.md +0 -0
  275. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/execution_strategy.md +0 -0
  276. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/findings.md +0 -0
  277. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/lesson_candidates.md +0 -0
  278. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/task_plan.md +0 -0
  279. /package/examples/minimal-project/{docs/09-PLANNING/TASKS → coding-agent-harness/planning/tasks}/demo-task/visual_map.md +0 -0
@@ -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();
@@ -1,67 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import {
4
- serveDashboardWorkbench,
5
- writeDashboardFolder,
6
- writeDashboardSingleFile,
7
- } from "../lib/harness-core.mjs";
8
-
9
- export async function runDashboardCommand({ takeFlag, takeOption, targetArg }) {
10
- const watch = takeFlag("--watch");
11
- const workbench = takeFlag("--workbench");
12
- const out = takeOption("--out", path.join("tmp", "harness-dashboard.html"));
13
- const outDir = takeOption("--out-dir", "");
14
- const host = takeOption("--host", "127.0.0.1");
15
- const port = takeOption("--port", "0");
16
- const localeOverride = takeOption("--locale", "");
17
- const opts = localeOverride ? { localeOverride } : {};
18
- if (workbench) {
19
- if (!outDir) {
20
- console.error("dashboard --workbench requires --out-dir so regenerated data has a stable folder");
21
- process.exit(2);
22
- }
23
- try {
24
- await serveDashboardWorkbench(outDir, targetArg(), { ...opts, host, port });
25
- } catch (error) {
26
- console.error(error.message);
27
- process.exit(1);
28
- }
29
- }
30
- if (watch) {
31
- if (!outDir) {
32
- console.error("dashboard --watch requires --out-dir so updates are written to a stable folder");
33
- process.exit(2);
34
- }
35
- const target = targetArg();
36
- const docsRoot = path.basename(path.resolve(target)) === "docs" ? path.resolve(target) : path.join(path.resolve(target), "docs");
37
- const regenerate = () => {
38
- try {
39
- console.log(writeDashboardFolder(outDir, target, opts));
40
- console.log(`dashboard regenerated: ${new Date().toISOString()}`);
41
- } catch (error) {
42
- console.error(`dashboard regeneration failed: ${error.message}`);
43
- }
44
- };
45
- regenerate();
46
- let timer = null;
47
- const watcher = fs.watch(docsRoot, { recursive: true }, () => {
48
- clearTimeout(timer);
49
- timer = setTimeout(regenerate, 300);
50
- });
51
- const close = () => {
52
- watcher.close();
53
- clearTimeout(timer);
54
- process.exit(0);
55
- };
56
- process.on("SIGINT", close);
57
- process.on("SIGTERM", close);
58
- console.log(`watching ${docsRoot}`);
59
- await new Promise(() => {});
60
- }
61
- if (outDir) {
62
- console.log(writeDashboardFolder(outDir, targetArg(), opts));
63
- } else {
64
- console.log(writeDashboardSingleFile(out, targetArg(), opts));
65
- }
66
- process.exit(0);
67
- }
@@ -1,96 +0,0 @@
1
- import {
2
- buildMigrationPlan,
3
- runMigration,
4
- verifyMigrationSession,
5
- } from "../lib/harness-core.mjs";
6
-
7
- export function runMigrationCommand(command, { args, takeFlag, takeOption, targetArg }) {
8
- if (command === "migrate-plan") {
9
- const json = takeFlag("--json");
10
- const limit = Number.parseInt(takeOption("--limit", "20"), 10) || 20;
11
- try {
12
- const plan = buildMigrationPlan(targetArg(), { limit });
13
- if (json) {
14
- console.log(JSON.stringify(plan, null, 2));
15
- } else {
16
- console.log(`Migration Plan: ${plan.target}`);
17
- console.log(`mode: ${plan.mode}`);
18
- console.log(`warnings: ${plan.summary.warnings}`);
19
- console.log(`task actions: ${plan.summary.taskActions}`);
20
- console.log(`visual map actions: ${plan.summary.visualMapActions}`);
21
- console.log(`legacy visual-only tasks: ${plan.summary.legacyVisualOnly}`);
22
- console.log(`weak briefs: ${plan.summary.weakBrief}`);
23
- console.log(`unknown classifications: ${plan.summary.unknownClassification}`);
24
- console.log(`full cutover eligible: ${plan.summary.fullCutoverEligible ? "yes" : "no"}`);
25
- console.log(`review actions: ${plan.summary.reviewSchemaGaps}`);
26
- console.log(`legacy actions: ${plan.summary.legacyReferenceGaps}`);
27
- console.log(`legacy residuals: ${plan.summary.legacyResiduals}`);
28
- console.log(`recommended capabilities: ${plan.summary.recommendedCapabilities.join(", ") || "none"}`);
29
- console.log("\nPhases:");
30
- for (const phase of plan.phases) console.log(`- ${phase.id}: ${phase.title}`);
31
- console.log("\nTop task actions:");
32
- for (const action of plan.taskActions) console.log(`- ${action.taskId}: add ${action.files.join(", ")}`);
33
- console.log("\nTop review actions:");
34
- for (const action of plan.reviewActions) console.log(`- ${action.path}: add ${action.missing.join(", ")}`);
35
- console.log("\nTop legacy residuals:");
36
- for (const action of plan.legacyResiduals) console.log(`- ${action.taskId}: ${action.missing} (${action.reason})`);
37
- console.log("\nNext commands:");
38
- for (const next of plan.nextCommands) console.log(`- ${next}`);
39
- }
40
- } catch (error) {
41
- console.error(error.message);
42
- process.exit(1);
43
- }
44
- return;
45
- }
46
-
47
- if (command === "migrate-run") {
48
- const locale = takeOption("--locale", "");
49
- const assumeLocale = takeFlag("--assume-locale");
50
- const allowDirty = takeFlag("--allow-dirty");
51
- const planOnly = takeFlag("--plan-only");
52
- const outDir = takeOption("--out-dir", "");
53
- const sessionDir = takeOption("--session-dir", "");
54
- try {
55
- console.log(
56
- JSON.stringify(
57
- runMigration(targetArg(), {
58
- locale,
59
- assumeLocale,
60
- allowDirty,
61
- planOnly,
62
- outDir,
63
- sessionDir,
64
- }),
65
- null,
66
- 2,
67
- ),
68
- );
69
- } catch (error) {
70
- console.error(error.message);
71
- process.exit(1);
72
- }
73
- return;
74
- }
75
-
76
- if (command === "migrate-verify") {
77
- const json = takeFlag("--json");
78
- const fullCutover = takeFlag("--full-cutover");
79
- const sessionPath = args.shift();
80
- if (!sessionPath) {
81
- console.error("Missing session.json path");
82
- process.exit(2);
83
- }
84
- const result = verifyMigrationSession(sessionPath, { fullCutover });
85
- if (json) {
86
- console.log(JSON.stringify(result, null, 2));
87
- } else {
88
- for (const failure of result.failures) console.error(`Failure: ${failure}`);
89
- for (const warning of result.warnings) console.log(`Warning: ${warning}`);
90
- console.log(`Migration verify ${result.status}: ${result.sessionPath}`);
91
- }
92
- process.exit(result.status === "pass" ? 0 : 1);
93
- }
94
-
95
- throw new Error(`Unsupported migration command: ${command}`);
96
- }