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,73 +0,0 @@
1
- import {
2
- checkPresetPackage,
3
- inspectPresetPackage,
4
- installPresetPackage,
5
- listPresetPackages,
6
- seedBundledPresets,
7
- uninstallPresetPackage,
8
- } from "../lib/harness-core.mjs";
9
-
10
- export function runPresetCommand({ args, takeFlag, targetArg }) {
11
- const subcommand = args.shift() || "list";
12
- const json = takeFlag("--json");
13
- const project = takeFlag("--project");
14
- try {
15
- if (subcommand === "list") {
16
- const target = targetArg();
17
- const presets = listPresetPackages({ targetInput: target }).map((preset) => ({
18
- id: preset.id,
19
- version: preset.version,
20
- purpose: preset.purpose,
21
- compatibleBudgets: preset.compatibleBudgets,
22
- source: preset.source,
23
- manifestPath: preset.manifestRelativePath,
24
- }));
25
- if (json) console.log(JSON.stringify({ presets }, null, 2));
26
- else for (const preset of presets) console.log(`${preset.id}@${preset.version} [${preset.source}] ${preset.compatibleBudgets.join(",")} - ${preset.purpose}`);
27
- } else if (subcommand === "inspect") {
28
- const id = args.shift();
29
- if (!id) throw new Error("Missing preset id");
30
- const preset = inspectPresetPackage(id, { targetInput: targetArg() });
31
- if (json) console.log(JSON.stringify(preset, null, 2));
32
- else console.log(`${preset.id}@${preset.version}\n${preset.purpose}`);
33
- } else if (subcommand === "check") {
34
- const id = args.shift();
35
- if (!id) throw new Error("Missing preset id");
36
- const report = checkPresetPackage(id, { targetInput: targetArg() });
37
- if (json) console.log(JSON.stringify(report, null, 2));
38
- else {
39
- for (const failure of report.failures) console.error(`Failure: ${failure}`);
40
- for (const warning of report.warnings) console.log(`Warning: ${warning}`);
41
- console.log(`Preset check ${report.status}: ${report.id}@${report.version}`);
42
- }
43
- process.exit(report.status === "pass" ? 0 : 1);
44
- } else if (subcommand === "install") {
45
- const force = takeFlag("--force");
46
- const source = args.shift();
47
- if (!source) throw new Error("Missing preset source");
48
- const result = installPresetPackage(source, { force, scope: project ? "project" : "user", targetInput: targetArg() });
49
- if (json) console.log(JSON.stringify(result, null, 2));
50
- else console.log(`Installed preset ${result.id}@${result.version} to ${result.destination}`);
51
- } else if (subcommand === "seed") {
52
- const force = takeFlag("--force");
53
- const dryRun = takeFlag("--dry-run");
54
- const result = seedBundledPresets({ force, dryRun, scope: project ? "project" : "user", targetInput: targetArg() });
55
- if (json) console.log(JSON.stringify(result, null, 2));
56
- else {
57
- console.log(`Seeded bundled presets to ${result.target}`);
58
- for (const preset of result.presets) console.log(`${preset.action}: ${preset.id}@${preset.version}`);
59
- }
60
- } else if (subcommand === "uninstall") {
61
- const id = args.shift();
62
- if (!id) throw new Error("Missing preset id");
63
- const result = uninstallPresetPackage(id, { scope: project ? "project" : "user", targetInput: targetArg() });
64
- if (json) console.log(JSON.stringify(result, null, 2));
65
- else console.log(`${result.removed ? "Removed" : "Preset not installed"}: ${result.id}`);
66
- } else {
67
- throw new Error(`Unknown preset subcommand: ${subcommand}`);
68
- }
69
- } catch (error) {
70
- console.error(error.message);
71
- process.exit(1);
72
- }
73
- }
@@ -1,327 +0,0 @@
1
- import fs from "node:fs";
2
- import {
3
- confirmTaskReview,
4
- createTask,
5
- readPresetPackage,
6
- buildTaskIndex,
7
- createLessonSedimentationTask,
8
- archiveTask,
9
- listLifecycleTasks,
10
- promoteLessonCandidate,
11
- reopenTask,
12
- softDeleteTask,
13
- supersedeTask,
14
- updateModuleStep,
15
- updateTaskPhase,
16
- updateTaskLifecycle,
17
- } from "../lib/harness-core.mjs";
18
-
19
- export function runTaskCommand(command, { args, takeFlag, takeOption, targetArg }) {
20
- if (command === "new-task") {
21
- const dryRun = takeFlag("--dry-run");
22
- const locale = takeOption("--locale", "");
23
- const title = takeOption("--title", "");
24
- const moduleKey = takeOption("--module", "");
25
- const budget = takeOption("--budget", "standard");
26
- const preset = takeOption("--preset", "");
27
- const fromSession = takeOption("--from-session", "");
28
- const longRunning = takeFlag("--long-running");
29
- try {
30
- const parsed = parseNewTaskArgs(args, { preset, fromSession });
31
- const taskId = parsed.taskId;
32
- if (!taskId) {
33
- console.error("Missing task id");
34
- process.exit(2);
35
- }
36
- console.log(JSON.stringify(createTask(parsed.target, taskId, { title, locale, dryRun, moduleKey, budget, longRunning, preset, fromSession, presetArgs: parsed.presetArgs }), null, 2));
37
- } catch (error) {
38
- console.error(error.message);
39
- process.exit(1);
40
- }
41
- return;
42
- }
43
-
44
- if (command === "task-phase") {
45
- const state = takeOption("--state", "");
46
- const completion = takeOption("--completion", "");
47
- const evidenceStatus = takeOption("--evidence", "");
48
- const taskId = args.shift();
49
- const phaseId = args.shift();
50
- if (!taskId || !phaseId) {
51
- console.error("Missing task id or phase id");
52
- process.exit(2);
53
- }
54
- try {
55
- console.log(JSON.stringify(updateTaskPhase(targetArg(), taskId, phaseId, { state, completion, evidenceStatus }), null, 2));
56
- } catch (error) {
57
- console.error(error.message);
58
- process.exit(1);
59
- }
60
- return;
61
- }
62
-
63
- if (["task-start", "task-log", "task-block", "task-review", "task-complete"].includes(command)) {
64
- const message = takeOption("--message", "");
65
- const evidence = takeOption("--evidence", "");
66
- const taskId = args.shift();
67
- if (!taskId) {
68
- console.error("Missing task id");
69
- process.exit(2);
70
- }
71
- const lifecycle = {
72
- "task-start": { event: "task-start", state: "in_progress" },
73
- "task-log": { event: "task-log", state: "" },
74
- "task-block": { event: "task-block", state: "blocked" },
75
- "task-review": { event: "task-review", state: "review" },
76
- "task-complete": { event: "task-complete", state: "done" },
77
- }[command];
78
- try {
79
- console.log(JSON.stringify(updateTaskLifecycle(targetArg(), taskId, { ...lifecycle, message, evidence }), null, 2));
80
- } catch (error) {
81
- console.error(error.message);
82
- process.exit(1);
83
- }
84
- return;
85
- }
86
-
87
- if (command === "review-confirm") {
88
- const reviewer = takeOption("--reviewer", "Human Reviewer");
89
- const message = takeOption("--message", "");
90
- const evidence = takeOption("--evidence", "");
91
- const confirmText = takeOption("--confirm", "");
92
- const taskId = args.shift();
93
- if (!taskId) {
94
- console.error("Missing task id");
95
- process.exit(2);
96
- }
97
- try {
98
- console.log(JSON.stringify(confirmTaskReview(targetArg(), taskId, { reviewer, message, evidence, confirmText }), null, 2));
99
- } catch (error) {
100
- console.error(formatTaskCommandError(error));
101
- process.exit(1);
102
- }
103
- return;
104
- }
105
-
106
- if (command === "lesson-promote") {
107
- const dryRun = takeFlag("--dry-run");
108
- const apply = takeFlag("--apply");
109
- const taskId = args.shift();
110
- const candidateId = args.shift();
111
- if (!taskId || !candidateId) {
112
- console.error("Missing task id or candidate id");
113
- process.exit(2);
114
- }
115
- try {
116
- console.log(JSON.stringify(promoteLessonCandidate(targetArg(), taskId, candidateId, { dryRun, apply }), null, 2));
117
- } catch (error) {
118
- console.error(error.message);
119
- process.exit(1);
120
- }
121
- return;
122
- }
123
-
124
- if (command === "lesson-sediment") {
125
- const dryRun = takeFlag("--dry-run");
126
- const title = takeOption("--title", "");
127
- const taskId = args.shift();
128
- const candidateId = args.shift();
129
- if (!taskId || !candidateId) {
130
- console.error("Missing task id or candidate id");
131
- process.exit(2);
132
- }
133
- try {
134
- console.log(JSON.stringify(createLessonSedimentationTask(targetArg(), taskId, candidateId, { dryRun, title }), null, 2));
135
- } catch (error) {
136
- console.error(error.message);
137
- process.exit(1);
138
- }
139
- return;
140
- }
141
-
142
- if (command === "task-list") {
143
- const json = takeFlag("--json");
144
- const state = takeOption("--state", "");
145
- const moduleKey = takeOption("--module", "");
146
- const queue = takeOption("--queue", "");
147
- const preset = takeOption("--preset", "");
148
- const review = takeOption("--review", "");
149
- const lesson = takeOption("--lesson", "");
150
- const search = takeOption("--search", "");
151
- const missingMaterials = takeFlag("--missing-materials");
152
- const result = listLifecycleTasks(targetArg(), { state, moduleKey, queue, preset, review, lesson, search, missingMaterials });
153
- if (json) {
154
- console.log(JSON.stringify(result, null, 2));
155
- } else {
156
- for (const task of result.tasks) {
157
- console.log(`${task.id}\t${task.state}\t${task.completion}%\t${task.title}`);
158
- }
159
- }
160
- return;
161
- }
162
-
163
- if (command === "task-index") {
164
- const json = takeFlag("--json");
165
- const result = buildTaskIndex(targetArg());
166
- if (json) console.log(JSON.stringify(result, null, 2));
167
- else console.log(`${result.tasks.length} tasks indexed (${result.schemaVersion})`);
168
- return;
169
- }
170
-
171
- if (command === "task-supersede") {
172
- const by = takeOption("--by", "");
173
- const reason = takeOption("--reason", "");
174
- const taskId = args.shift();
175
- if (!taskId) {
176
- console.error("Missing task id");
177
- process.exit(2);
178
- }
179
- try {
180
- console.log(JSON.stringify(supersedeTask(targetArg(), taskId, { by, reason }), null, 2));
181
- } catch (error) {
182
- console.error(error.message);
183
- process.exit(1);
184
- }
185
- return;
186
- }
187
-
188
- if (["task-delete", "task-archive", "task-reopen"].includes(command)) {
189
- const soft = takeFlag("--soft");
190
- const reason = takeOption("--reason", "");
191
- const taskId = args.shift();
192
- if (!taskId) {
193
- console.error("Missing task id");
194
- process.exit(2);
195
- }
196
- try {
197
- if (command === "task-delete" && !soft) throw new Error("task-delete only supports --soft; hard delete is intentionally disabled.");
198
- const result =
199
- command === "task-delete"
200
- ? softDeleteTask(targetArg(), taskId, { reason })
201
- : command === "task-archive"
202
- ? archiveTask(targetArg(), taskId, { reason })
203
- : reopenTask(targetArg(), taskId, { reason });
204
- console.log(JSON.stringify(result, null, 2));
205
- } catch (error) {
206
- console.error(error.message);
207
- process.exit(1);
208
- }
209
- return;
210
- }
211
-
212
- if (command === "module-step") {
213
- const state = takeOption("--state", "done");
214
- const moduleKey = args.shift();
215
- const stepId = args.shift();
216
- if (!moduleKey || !stepId) {
217
- console.error("Missing module key or step id");
218
- process.exit(2);
219
- }
220
- try {
221
- console.log(JSON.stringify(updateModuleStep(targetArg(), moduleKey, stepId, { state }), null, 2));
222
- } catch (error) {
223
- console.error(error.message);
224
- process.exit(1);
225
- }
226
- return;
227
- }
228
-
229
- throw new Error(`Unsupported task command: ${command}`);
230
- }
231
-
232
- function parseNewTaskArgs(args, { preset = "", fromSession = "" } = {}) {
233
- const values = [...args];
234
- let taskId = "";
235
- if (!fromSession) {
236
- taskId = values.shift() || "";
237
- } else if (values.length > 0 && !values[0].startsWith("-") && !(values.length === 1 && fs.existsSync(values[0]))) {
238
- taskId = values.shift();
239
- }
240
- const presetPackage = preset ? readPresetPackageForNewTask(preset, values) : null;
241
- if (!taskId && fromSession) taskId = presetPackage?.task?.defaultTaskId || "harness-v1-migration";
242
- const parsed = splitPresetArgsAndTarget(values, presetPackage);
243
- return {
244
- taskId,
245
- target: parsed.target || ".",
246
- presetArgs: parsed.presetArgs,
247
- };
248
- }
249
-
250
- function readPresetPackageForNewTask(preset, values) {
251
- const candidates = presetDiscoveryTargetCandidates(values);
252
- let fallbackPackage = null;
253
- let lastError = null;
254
- for (const targetInput of candidates) {
255
- try {
256
- const presetPackage = readPresetPackage(preset, { targetInput });
257
- if (presetPackage.source === "project") return presetPackage;
258
- if (!fallbackPackage) fallbackPackage = presetPackage;
259
- } catch (error) {
260
- lastError = error;
261
- }
262
- }
263
- if (fallbackPackage) return fallbackPackage;
264
- throw lastError;
265
- }
266
-
267
- function presetDiscoveryTargetCandidates(values) {
268
- const candidates = [];
269
- for (let index = values.length - 1; index >= 0; index -= 1) {
270
- const value = values[index];
271
- if (!value || value.startsWith("-")) continue;
272
- if (!candidates.includes(value)) candidates.push(value);
273
- }
274
- if (!candidates.includes(".")) candidates.push(".");
275
- return candidates;
276
- }
277
-
278
- function splitPresetArgsAndTarget(values, presetPackage) {
279
- const presetArgs = [];
280
- const targetCandidates = [];
281
- const declaredFlags = new Map(Object.values(presetPackage?.inputs || {}).filter((input) => input.flag).map((input) => [input.flag, input]));
282
- for (let index = 0; index < values.length; index += 1) {
283
- const value = values[index];
284
- const declared = declaredFlags.get(value);
285
- if (declared) {
286
- presetArgs.push(value);
287
- if (declared.type !== "flag" && index + 1 < values.length) {
288
- presetArgs.push(values[index + 1]);
289
- index += 1;
290
- }
291
- } else if (value.startsWith("-")) {
292
- presetArgs.push(value);
293
- if (index + 1 < values.length && !values[index + 1].startsWith("-")) {
294
- presetArgs.push(values[index + 1]);
295
- index += 1;
296
- }
297
- } else {
298
- targetCandidates.push(value);
299
- }
300
- }
301
- if (targetCandidates.length > 1) {
302
- throw new Error(`Too many positional arguments for new-task: ${targetCandidates.join(", ")}`);
303
- }
304
- return {
305
- target: targetCandidates[0] || "",
306
- presetArgs,
307
- };
308
- }
309
-
310
- function formatTaskCommandError(error) {
311
- const lines = [error.message];
312
- if (Array.isArray(error.recovery) && error.recovery.length > 0) {
313
- lines.push("", "Recovery:");
314
- for (const item of error.recovery) lines.push(`- ${item}`);
315
- }
316
- if (error.details?.entries?.length) {
317
- lines.push("", "Blocking Git status:");
318
- for (const entry of error.details.entries) lines.push(`- ${entry.raw || entry.path}`);
319
- }
320
- if (error.details?.disallowed?.length) {
321
- lines.push("", "Disallowed paths:");
322
- for (const item of error.details.disallowed) lines.push(`- ${item}`);
323
- }
324
- if (error.details?.stderr) lines.push("", error.details.stderr);
325
- if (error.details?.stdout) lines.push("", error.details.stdout);
326
- return lines.join("\n");
327
- }
@@ -1,287 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import fs from "node:fs";
4
- import os from "node:os";
5
- import path from "node:path";
6
- import { createInterface } from "node:readline/promises";
7
- import {
8
- addCapability,
9
- buildStatus,
10
- doctorUserSkill,
11
- installUserSkill,
12
- normalizeLocale,
13
- rebuildGovernanceIndexes,
14
- serveDashboardWorkbench,
15
- validateSourcePackageBoundary,
16
- writeInitFiles,
17
- } from "./lib/harness-core.mjs";
18
- import { runDashboardCommand } from "./commands/dashboard-command.mjs";
19
- import { runMigrationCommand } from "./commands/migration-command.mjs";
20
- import { runPresetCommand } from "./commands/preset-command.mjs";
21
- import { runTaskCommand } from "./commands/task-command.mjs";
22
-
23
- const args = process.argv.slice(2);
24
- const command = args.shift() || "help";
25
-
26
- function takeFlag(name, fallback = false) {
27
- const index = args.indexOf(name);
28
- if (index < 0) return fallback;
29
- args.splice(index, 1);
30
- return true;
31
- }
32
-
33
- function takeOption(name, fallback = "") {
34
- const index = args.indexOf(name);
35
- if (index < 0) return fallback;
36
- const value = args[index + 1] || fallback;
37
- args.splice(index, 2);
38
- return value;
39
- }
40
-
41
- async function resolveInitLocale(requestedLocale) {
42
- if (requestedLocale) return normalizeLocale(requestedLocale);
43
- if (!process.stdin.isTTY || !process.stdout.isTTY) return "en-US";
44
-
45
- const prompt = [
46
- "Select harness language / 选择初始化语言:",
47
- " 1. 中文 (zh-CN)",
48
- " 2. English (en-US)",
49
- "Language [1/2, default 2]: ",
50
- ].join("\n");
51
- const reader = createInterface({ input: process.stdin, output: process.stdout });
52
- try {
53
- const answer = (await reader.question(prompt)).trim().toLowerCase();
54
- if (["1", "zh", "zh-cn", "cn", "中文"].includes(answer)) return "zh-CN";
55
- if (["2", "en", "en-us", "english", "英文", ""].includes(answer)) return "en-US";
56
- console.error(`Unknown language selection: ${answer}. Falling back to en-US.`);
57
- return "en-US";
58
- } finally {
59
- reader.close();
60
- }
61
- }
62
-
63
- async function confirmUserInstall({ yes = false, dryRun = false, agent = "codex" } = {}) {
64
- if (yes || dryRun) return true;
65
- if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
66
- const reader = createInterface({ input: process.stdin, output: process.stdout });
67
- try {
68
- const answer = (await reader.question(`Install Coding Agent Harness into user skill directory for ${agent}? [y/N] `)).trim().toLowerCase();
69
- return ["y", "yes"].includes(answer);
70
- } finally {
71
- reader.close();
72
- }
73
- }
74
-
75
- function targetArg() {
76
- return args[args.length - 1] && !args[args.length - 1].startsWith("-") ? args[args.length - 1] : ".";
77
- }
78
-
79
- function printHelp() {
80
- console.log(`Coding Agent Harness
81
-
82
- Usage:
83
- harness check [--profile source-package|private-harness|target-project] [target]
84
- harness status [--json] [--strict] [target]
85
- harness dev [--no-open] [--out-dir folder] [--host 127.0.0.1] [--port n] [target]
86
- harness dashboard [--out file.html] [--out-dir folder] [--workbench] [--host 127.0.0.1] [--port n] [target]
87
- harness init [--dry-run] [--locale zh-CN|en-US] [--capabilities core,dashboard] [--add-npm-scripts] [target]
88
- harness add-capability <name> [--dry-run] [--locale zh-CN|en-US] [target]
89
- harness migrate-plan [--json] [--limit n] [target]
90
- harness migrate-run [--locale zh-CN|en-US] [--assume-locale] [--allow-dirty] [--plan-only] [--out-dir folder] [--session-dir folder] [target]
91
- harness migrate-verify [--json] [--full-cutover] <session.json>
92
- harness governance rebuild [--dry-run] [--archive] [--apply] [target]
93
- harness preset list [--json] [target]
94
- harness preset inspect <id> [--json] [target]
95
- harness preset check <id> [--json] [target]
96
- harness preset install <path-or-builtin-id> [--project] [--force] [--json] [target]
97
- harness preset seed [--project] [--force] [--dry-run] [--json] [target]
98
- harness preset uninstall <id> [--project] [--json] [target]
99
- harness new-task <task-id> [--module key] [--budget simple|standard|complex] [--preset id] [--from-session session.json] [--long-running] [--title title] [--locale zh-CN|en-US] [--dry-run] [target]
100
- harness task-start <task-id> [--message text] [target]
101
- harness task-phase <task-id> <phase-id> [--state done] [--completion 100] [--evidence present] [target]
102
- harness task-log <task-id> --message text [--evidence type:PATH:summary] [target]
103
- harness task-block <task-id> [--message text] [target]
104
- harness task-review <task-id> [--message text] [target]
105
- harness review-confirm <task-id> --confirm task-id [--reviewer name] [--message text] [target]
106
- harness lesson-promote <task-id> <candidate-id> [--dry-run|--apply] [target]
107
- harness lesson-sediment <task-id> <candidate-id> [--dry-run] [--title title] [target]
108
- harness task-complete <task-id> [--message text] [target]
109
- harness task-list [--json] [--state state] [--module key] [--queue queue] [--preset id] [--review status] [--lesson status] [--missing-materials] [--search text] [target]
110
- harness task-index [--json] [target]
111
- harness task-supersede <old-task-id> --by <new-task-id> [--reason text] [target]
112
- harness task-delete <task-id> --soft [--reason text] [target]
113
- harness task-archive <task-id> [--reason text] [target]
114
- harness task-reopen <task-id> [--reason text] [target]
115
- harness module-step <module-key> <step-id> [--state done|in-progress|blocked] [target]
116
- harness install-user [--agent codex|claude|gemini|openclaw|agents|all] [--home dir] [--dry-run] [--force] [--skip-presets] [--yes]
117
- harness doctor-user [--agent codex|claude|gemini|openclaw|agents|all] [--home dir]
118
-
119
- If init runs in an interactive terminal and --locale is omitted, it asks for a
120
- language. Non-interactive init defaults to en-US.
121
-
122
- Preset discovery:
123
- Project presets live in <target>/.coding-agent-harness/presets/<preset-id>/.
124
- User presets live in ~/.coding-agent-harness/presets/<preset-id>/.
125
- Harness discovers project presets first when a target is supplied, then user
126
- presets, then bundled package presets under presets/<preset-id>/.
127
- "harness init" seeds bundled presets into the target project. "harness
128
- install-user" and npm postinstall seed bundled presets into the user root.
129
- Use "harness preset seed" to repair or re-run preset seeding.
130
- Use "harness preset list --json" to see available presets, their source,
131
- purpose, compatible budgets, and manifest path. Use "harness preset inspect
132
- <id> --json" for the full preset manifest summary.
133
- `);
134
- }
135
-
136
- function exitWithReport(report) {
137
- for (const warning of report.warnings || []) console.log(`Warning: ${warning}`);
138
- for (const failure of report.failures || []) console.error(`Failure: ${failure}`);
139
- process.exit((report.failures || []).length > 0 ? 1 : 0);
140
- }
141
-
142
- if (command === "help" || command === "--help" || command === "-h") {
143
- printHelp();
144
- } else if (args[0] === "help" || args.includes("--help") || args.includes("-h")) {
145
- printHelp();
146
- } else if (command === "check") {
147
- const profile = takeOption("--profile", "target-project");
148
- const strict = takeFlag("--strict");
149
- const target = targetArg();
150
- const failures = [];
151
- const warnings = [];
152
-
153
- if (profile === "source-package") {
154
- for (const required of ["package.json", "scripts/harness.mjs", "scripts/check-harness.mjs", "templates/planning/task_plan.md"]) {
155
- if (!fs.existsSync(path.resolve(target, required))) failures.push(`missing source package file: ${required}`);
156
- }
157
- const boundary = validateSourcePackageBoundary(target);
158
- failures.push(...boundary.failures);
159
- warnings.push(...boundary.warnings);
160
- }
161
-
162
- const status = buildStatus(target, { skipLegacyCheck: profile === "source-package", strictLegacy: strict, strict });
163
- failures.push(...status.checkState.details.failures);
164
- warnings.push(...status.checkState.details.warnings);
165
-
166
- if (!["source-package", "private-harness", "target-project"].includes(profile)) failures.push(`unknown profile: ${profile}`);
167
- if (failures.length === 0) console.log(`Harness check passed (${profile}): ${path.resolve(target)}`);
168
- exitWithReport({ failures: [...new Set(failures)], warnings: [...new Set(warnings)] });
169
- } else if (command === "status") {
170
- const json = takeFlag("--json");
171
- const strict = takeFlag("--strict");
172
- const status = buildStatus(targetArg(), { strictLegacy: strict, strict });
173
- if (json) {
174
- console.log(JSON.stringify(status, null, 2));
175
- } else {
176
- console.log(`${status.project.name}: ${status.checkState.status} (${status.checkState.failures} failures, ${status.checkState.warnings} warnings)`);
177
- console.log(`mode: ${status.mode}`);
178
- console.log(`capabilities: ${status.capabilities.map((capability) => `${capability.name}:${capability.state}`).join(", ")}`);
179
- console.log(`tasks: ${status.tasks.length}`);
180
- }
181
- process.exitCode = status.checkState.status === "fail" ? 1 : 0;
182
- } else if (command === "dev") {
183
- const open = !takeFlag("--no-open");
184
- const outDir = takeOption("--out-dir", "");
185
- const host = takeOption("--host", "127.0.0.1");
186
- const port = takeOption("--port", "0");
187
- const localeOverride = takeOption("--locale", "");
188
- const target = targetArg();
189
- const usesDefaultOutDir = !outDir;
190
- const dashboardOutDir = outDir || defaultDevOutDir(target);
191
- const opts = { ...(localeOverride ? { localeOverride } : {}), recoverGeneratedDashboard: usesDefaultOutDir };
192
- try {
193
- await serveDashboardWorkbench(dashboardOutDir, target, { ...opts, host, port, autoRefresh: true, open, label: "harness dev" });
194
- } catch (error) {
195
- console.error(error.message);
196
- process.exit(1);
197
- }
198
- } else if (command === "dashboard") {
199
- await runDashboardCommand({ takeFlag, takeOption, targetArg });
200
- } else if (command === "init") {
201
- const dryRun = takeFlag("--dry-run");
202
- const addNpmScripts = takeFlag("--add-npm-scripts");
203
- const locale = await resolveInitLocale(takeOption("--locale", ""));
204
- const capabilities = takeOption("--capabilities", "core").split(",").map((item) => item.trim()).filter(Boolean);
205
- try {
206
- const result = writeInitFiles(targetArg(), capabilities, { dryRun, locale, addNpmScripts });
207
- console.log(JSON.stringify({ dryRun, locale: result.locale, capabilities: result.capabilities, changes: result.changes, presetSeed: result.presetSeed, nextCommands: result.nextCommands, report: result.report }, null, 2));
208
- } catch (error) {
209
- console.error(error.message);
210
- process.exit(1);
211
- }
212
- } else if (command === "add-capability") {
213
- const dryRun = takeFlag("--dry-run");
214
- const locale = normalizeLocale(takeOption("--locale", ""));
215
- const capability = args.shift();
216
- if (!capability) {
217
- console.error("Missing capability name");
218
- process.exit(2);
219
- }
220
- try {
221
- const result = addCapability(targetArg(), capability, { dryRun, locale });
222
- console.log(JSON.stringify({ dryRun, registry: result.registry, changes: result.changes, report: result.report }, null, 2));
223
- } catch (error) {
224
- console.error(error.message);
225
- process.exit(1);
226
- }
227
- } else if (["migrate-plan", "migrate-run", "migrate-verify"].includes(command)) {
228
- runMigrationCommand(command, { args, takeFlag, takeOption, targetArg });
229
- } else if (command === "governance") {
230
- const subcommand = args.shift() || "";
231
- if (subcommand !== "rebuild") {
232
- console.error(`Unknown governance subcommand: ${subcommand || "(missing)"}`);
233
- process.exit(2);
234
- }
235
- const dryRun = takeFlag("--dry-run");
236
- const archive = takeFlag("--archive");
237
- const apply = takeFlag("--apply");
238
- try {
239
- console.log(JSON.stringify(rebuildGovernanceIndexes(targetArg(), { dryRun, archive, apply }), null, 2));
240
- } catch (error) {
241
- console.error(error.message);
242
- process.exit(1);
243
- }
244
- } else if (command === "preset") {
245
- runPresetCommand({ args, takeFlag, targetArg });
246
- } else if (["new-task", "task-phase", "task-start", "task-log", "task-block", "task-review", "task-complete", "review-confirm", "lesson-promote", "lesson-sediment", "task-list", "task-index", "task-supersede", "task-delete", "task-archive", "task-reopen", "module-step"].includes(command)) {
247
- runTaskCommand(command, { args, takeFlag, takeOption, targetArg });
248
- } else if (command === "install-user") {
249
- const dryRun = takeFlag("--dry-run");
250
- const force = takeFlag("--force");
251
- const yes = takeFlag("--yes") || takeFlag("-y");
252
- const skipPresets = takeFlag("--skip-presets");
253
- takeFlag("--global");
254
- const agent = takeOption("--agent", "codex");
255
- const home = takeOption("--home", "");
256
- if (!(await confirmUserInstall({ yes, dryRun, agent }))) {
257
- console.error("Refusing to write user skill files without confirmation. Re-run with --yes or --dry-run.");
258
- process.exit(2);
259
- }
260
- try {
261
- console.log(JSON.stringify(installUserSkill({ agent, home, dryRun, force, seedPresets: !skipPresets }), null, 2));
262
- } catch (error) {
263
- console.error(error.message);
264
- process.exit(1);
265
- }
266
- } else if (command === "doctor-user") {
267
- const agent = takeOption("--agent", "codex");
268
- const home = takeOption("--home", "");
269
- try {
270
- const report = doctorUserSkill({ agent, home });
271
- console.log(JSON.stringify(report, null, 2));
272
- process.exit(report.status === "pass" ? 0 : 1);
273
- } catch (error) {
274
- console.error(error.message);
275
- process.exit(1);
276
- }
277
- } else {
278
- printHelp();
279
- process.exit(2);
280
- }
281
-
282
- function defaultDevOutDir(targetInput) {
283
- const target = path.resolve(targetInput || ".");
284
- const name = path.basename(target) || "project";
285
- const hash = Buffer.from(target).toString("hex").slice(0, 16);
286
- return path.join(os.tmpdir(), "coding-agent-harness-dev", `${name}-${hash}`);
287
- }