@dommaker/harness 0.19.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/bin/harness.js +136 -557
  3. package/dist/cli/commands/check.d.ts.map +1 -1
  4. package/dist/cli/commands/check.js +2 -13
  5. package/dist/cli/commands/check.js.map +1 -1
  6. package/dist/cli/commands/definitions.d.ts +90 -0
  7. package/dist/cli/commands/definitions.d.ts.map +1 -0
  8. package/dist/cli/commands/definitions.js +519 -0
  9. package/dist/cli/commands/definitions.js.map +1 -0
  10. package/dist/cli/commands/knowledge.js.map +1 -1
  11. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts +3 -25
  12. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts.map +1 -1
  13. package/dist/cli/commands/sync-docs/capabilities-syncer.js +3 -93
  14. package/dist/cli/commands/sync-docs/capabilities-syncer.js.map +1 -1
  15. package/dist/cli/commands/sync-docs/index.d.ts +1 -1
  16. package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
  17. package/dist/cli/commands/sync-docs/index.js +4 -4
  18. package/dist/cli/commands/sync-docs/index.js.map +1 -1
  19. package/dist/context/index.d.ts +1 -5
  20. package/dist/context/index.d.ts.map +1 -1
  21. package/dist/context/index.js +1 -5
  22. package/dist/context/index.js.map +1 -1
  23. package/dist/context/knowledge-injector.d.ts +3 -3
  24. package/dist/context/knowledge-injector.d.ts.map +1 -1
  25. package/dist/context/knowledge-injector.js +1 -1
  26. package/dist/context/session-manager.d.ts +1 -12
  27. package/dist/context/session-manager.d.ts.map +1 -1
  28. package/dist/context/session-manager.js +0 -63
  29. package/dist/context/session-manager.js.map +1 -1
  30. package/dist/context/types.d.ts +1 -39
  31. package/dist/context/types.d.ts.map +1 -1
  32. package/dist/context/types.js +2 -15
  33. package/dist/context/types.js.map +1 -1
  34. package/dist/core/constraints/agent-prompt-renderer.d.ts +1 -1
  35. package/dist/core/constraints/agent-prompt-renderer.js +1 -1
  36. package/dist/core/constraints/capabilities-parser.d.ts +17 -2
  37. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  38. package/dist/core/constraints/capabilities-parser.js +84 -2
  39. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  40. package/dist/core/constraints/checker.d.ts +3 -17
  41. package/dist/core/constraints/checker.d.ts.map +1 -1
  42. package/dist/core/constraints/checker.js +7 -47
  43. package/dist/core/constraints/checker.js.map +1 -1
  44. package/dist/core/constraints/definitions.d.ts +0 -7
  45. package/dist/core/constraints/definitions.d.ts.map +1 -1
  46. package/dist/core/constraints/definitions.js +1 -8
  47. package/dist/core/constraints/definitions.js.map +1 -1
  48. package/dist/core/constraints/doc-freshness/runner.d.ts +0 -2
  49. package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
  50. package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
  51. package/dist/core/constraints/index.d.ts +1 -1
  52. package/dist/core/constraints/index.d.ts.map +1 -1
  53. package/dist/core/constraints/index.js +2 -3
  54. package/dist/core/constraints/index.js.map +1 -1
  55. package/dist/core/constraints/interceptor.d.ts.map +1 -1
  56. package/dist/core/constraints/interceptor.js +1 -5
  57. package/dist/core/constraints/interceptor.js.map +1 -1
  58. package/dist/core/effective-constraints.d.ts.map +1 -1
  59. package/dist/core/effective-constraints.js +0 -1
  60. package/dist/core/effective-constraints.js.map +1 -1
  61. package/dist/core/project-config-loader.d.ts.map +1 -1
  62. package/dist/core/project-config-loader.js +1 -8
  63. package/dist/core/project-config-loader.js.map +1 -1
  64. package/dist/dashboard/stats.d.ts.map +1 -1
  65. package/dist/dashboard/stats.js.map +1 -1
  66. package/dist/dashboard/types.d.ts +2 -2
  67. package/dist/dashboard/types.d.ts.map +1 -1
  68. package/dist/failure/constraint-handler.d.ts.map +1 -1
  69. package/dist/failure/constraint-handler.js +0 -2
  70. package/dist/failure/constraint-handler.js.map +1 -1
  71. package/dist/gates/acceptance.d.ts +9 -1
  72. package/dist/gates/acceptance.d.ts.map +1 -1
  73. package/dist/gates/acceptance.js +21 -0
  74. package/dist/gates/acceptance.js.map +1 -1
  75. package/dist/gates/checker-gate.d.ts +23 -0
  76. package/dist/gates/checker-gate.d.ts.map +1 -0
  77. package/dist/gates/checker-gate.js +53 -0
  78. package/dist/gates/checker-gate.js.map +1 -0
  79. package/dist/gates/command.d.ts +9 -2
  80. package/dist/gates/command.d.ts.map +1 -1
  81. package/dist/gates/command.js +10 -0
  82. package/dist/gates/command.js.map +1 -1
  83. package/dist/gates/contract.d.ts +8 -2
  84. package/dist/gates/contract.d.ts.map +1 -1
  85. package/dist/gates/contract.js +9 -0
  86. package/dist/gates/contract.js.map +1 -1
  87. package/dist/gates/decision.d.ts +17 -0
  88. package/dist/gates/decision.d.ts.map +1 -0
  89. package/dist/gates/decision.js +25 -0
  90. package/dist/gates/decision.js.map +1 -0
  91. package/dist/gates/definitions.d.ts +63 -0
  92. package/dist/gates/definitions.d.ts.map +1 -0
  93. package/dist/gates/definitions.js +160 -0
  94. package/dist/gates/definitions.js.map +1 -0
  95. package/dist/gates/effective-gates.d.ts +30 -0
  96. package/dist/gates/effective-gates.d.ts.map +1 -0
  97. package/dist/gates/effective-gates.js +85 -0
  98. package/dist/gates/effective-gates.js.map +1 -0
  99. package/dist/gates/index.d.ts +25 -1
  100. package/dist/gates/index.d.ts.map +1 -1
  101. package/dist/gates/index.js +37 -1
  102. package/dist/gates/index.js.map +1 -1
  103. package/dist/gates/performance.d.ts +8 -2
  104. package/dist/gates/performance.d.ts.map +1 -1
  105. package/dist/gates/performance.js +9 -0
  106. package/dist/gates/performance.js.map +1 -1
  107. package/dist/gates/registry.d.ts +32 -0
  108. package/dist/gates/registry.d.ts.map +1 -0
  109. package/dist/gates/registry.js +90 -0
  110. package/dist/gates/registry.js.map +1 -0
  111. package/dist/gates/review.d.ts +8 -2
  112. package/dist/gates/review.d.ts.map +1 -1
  113. package/dist/gates/review.js +9 -0
  114. package/dist/gates/review.js.map +1 -1
  115. package/dist/gates/runner.d.ts +30 -0
  116. package/dist/gates/runner.d.ts.map +1 -0
  117. package/dist/gates/runner.js +38 -0
  118. package/dist/gates/runner.js.map +1 -0
  119. package/dist/gates/security.d.ts +8 -2
  120. package/dist/gates/security.d.ts.map +1 -1
  121. package/dist/gates/security.js +9 -0
  122. package/dist/gates/security.js.map +1 -1
  123. package/dist/gates/types.d.ts +41 -1
  124. package/dist/gates/types.d.ts.map +1 -1
  125. package/dist/hooks/bootstrap.d.ts.map +1 -1
  126. package/dist/hooks/bootstrap.js +0 -2
  127. package/dist/hooks/bootstrap.js.map +1 -1
  128. package/dist/hooks/config.d.ts +26 -0
  129. package/dist/hooks/config.d.ts.map +1 -0
  130. package/dist/hooks/config.js +30 -0
  131. package/dist/hooks/config.js.map +1 -0
  132. package/dist/hooks/index.d.ts +2 -1
  133. package/dist/hooks/index.d.ts.map +1 -1
  134. package/dist/hooks/index.js +4 -1
  135. package/dist/hooks/index.js.map +1 -1
  136. package/dist/hooks/registry.d.ts +18 -1
  137. package/dist/hooks/registry.d.ts.map +1 -1
  138. package/dist/hooks/registry.js +45 -0
  139. package/dist/hooks/registry.js.map +1 -1
  140. package/dist/hooks/types.d.ts +20 -0
  141. package/dist/hooks/types.d.ts.map +1 -1
  142. package/dist/index.d.ts +4 -8
  143. package/dist/index.d.ts.map +1 -1
  144. package/dist/index.js +5 -20
  145. package/dist/index.js.map +1 -1
  146. package/dist/knowledge/import.d.ts +2 -2
  147. package/dist/knowledge/import.d.ts.map +1 -1
  148. package/dist/knowledge/ingest.js.map +1 -1
  149. package/dist/knowledge/lifecycle-hooks.d.ts +2 -2
  150. package/dist/knowledge/lifecycle-hooks.d.ts.map +1 -1
  151. package/dist/knowledge/types.d.ts +5 -7
  152. package/dist/knowledge/types.d.ts.map +1 -1
  153. package/dist/knowledge/types.js +1 -1
  154. package/dist/knowledge/types.js.map +1 -1
  155. package/dist/monitoring/constraint-doctor.d.ts +4 -22
  156. package/dist/monitoring/constraint-doctor.d.ts.map +1 -1
  157. package/dist/monitoring/constraint-doctor.js +7 -94
  158. package/dist/monitoring/constraint-doctor.js.map +1 -1
  159. package/dist/presets/standard.d.ts +1 -1
  160. package/dist/presets/standard.d.ts.map +1 -1
  161. package/dist/presets/standard.js +1 -2
  162. package/dist/presets/standard.js.map +1 -1
  163. package/dist/spec/annotation-checker.d.ts.map +1 -1
  164. package/dist/spec/annotation-checker.js +6 -26
  165. package/dist/spec/annotation-checker.js.map +1 -1
  166. package/dist/tools/index.d.ts +0 -4
  167. package/dist/tools/index.d.ts.map +1 -1
  168. package/dist/tools/index.js +0 -4
  169. package/dist/tools/index.js.map +1 -1
  170. package/dist/types/constraint.d.ts +1 -12
  171. package/dist/types/constraint.d.ts.map +1 -1
  172. package/dist/types/constraint.js +0 -3
  173. package/dist/types/constraint.js.map +1 -1
  174. package/dist/types/project-config.d.ts +0 -2
  175. package/dist/types/project-config.d.ts.map +1 -1
  176. package/dist/utils/file-walk.d.ts +2 -2
  177. package/dist/utils/file-walk.js +2 -2
  178. package/package.json +6 -1
  179. package/src/CONTEXT.md +14 -0
  180. package/src/__tests__/checker-extra.test.ts +2 -59
  181. package/src/__tests__/constraint-doctor.test.ts +1 -140
  182. package/src/__tests__/constraint-handler.test.ts +0 -4
  183. package/src/__tests__/project-config-loader-extra.test.ts +0 -20
  184. package/src/__tests__/project-config-loader.test.ts +0 -1
  185. package/src/cli/commands/CONTEXT.md +15 -7
  186. package/src/cli/commands/__tests__/check-drift.test.ts +0 -3
  187. package/src/cli/commands/__tests__/check-skip-output.test.ts +0 -5
  188. package/src/cli/commands/__tests__/check.test.ts +7 -75
  189. package/src/cli/commands/__tests__/registry.test.ts +201 -0
  190. package/src/cli/commands/check.ts +2 -14
  191. package/src/cli/commands/definitions.ts +593 -0
  192. package/src/cli/commands/knowledge.ts +3 -3
  193. package/src/cli/commands/sync-docs/capabilities-syncer.ts +4 -110
  194. package/src/cli/commands/sync-docs/index.ts +8 -5
  195. package/src/context/CONTEXT.md +2 -7
  196. package/src/context/__tests__/session-manager.test.ts +0 -91
  197. package/src/context/index.ts +1 -5
  198. package/src/context/knowledge-injector.ts +3 -3
  199. package/src/context/session-manager.ts +0 -74
  200. package/src/context/types.ts +2 -63
  201. package/src/core/constraints/__tests__/interceptor.test.ts +0 -2
  202. package/src/core/constraints/agent-prompt-renderer.ts +1 -1
  203. package/src/core/constraints/capabilities-parser.ts +95 -2
  204. package/src/core/constraints/checker.ts +8 -53
  205. package/src/core/constraints/definitions.ts +0 -8
  206. package/src/core/constraints/doc-freshness/runner.ts +1 -2
  207. package/src/core/constraints/index.ts +1 -2
  208. package/src/core/constraints/interceptor.ts +1 -6
  209. package/src/core/effective-constraints.ts +0 -1
  210. package/src/core/project-config-loader.ts +1 -7
  211. package/src/dashboard/stats.ts +2 -2
  212. package/src/dashboard/types.ts +2 -2
  213. package/src/failure/constraint-handler.ts +0 -2
  214. package/src/gates/CONTEXT.md +16 -13
  215. package/src/gates/__tests__/checker-gate.test.ts +45 -0
  216. package/src/gates/__tests__/contract.test.ts +73 -0
  217. package/src/gates/__tests__/effective-gates.test.ts +82 -0
  218. package/src/gates/__tests__/gate-interface.test.ts +202 -0
  219. package/src/gates/__tests__/registry.test.ts +87 -0
  220. package/src/gates/__tests__/runner.test.ts +81 -0
  221. package/src/gates/acceptance.ts +24 -1
  222. package/src/gates/checker-gate.ts +54 -0
  223. package/src/gates/command.ts +13 -2
  224. package/src/gates/contract.ts +12 -2
  225. package/src/gates/decision.ts +27 -0
  226. package/src/gates/definitions.ts +207 -0
  227. package/src/gates/effective-gates.ts +106 -0
  228. package/src/gates/index.ts +38 -0
  229. package/src/gates/performance.ts +12 -2
  230. package/src/gates/registry.ts +107 -0
  231. package/src/gates/review.ts +12 -2
  232. package/src/gates/runner.ts +57 -0
  233. package/src/gates/security.ts +12 -2
  234. package/src/gates/types.ts +48 -1
  235. package/src/hooks/CONTEXT.md +12 -2
  236. package/src/hooks/__tests__/bootstrap.test.ts +0 -1
  237. package/src/hooks/__tests__/config.test.ts +19 -0
  238. package/src/hooks/__tests__/pipeline.test.ts +79 -0
  239. package/src/hooks/__tests__/registry.test.ts +67 -0
  240. package/src/hooks/bootstrap.ts +0 -2
  241. package/src/hooks/config.ts +29 -0
  242. package/src/hooks/index.ts +2 -1
  243. package/src/hooks/registry.ts +60 -1
  244. package/src/hooks/types.ts +21 -0
  245. package/src/index.ts +5 -22
  246. package/src/knowledge/import.ts +3 -3
  247. package/src/knowledge/ingest.ts +4 -4
  248. package/src/knowledge/lifecycle-hooks.ts +3 -3
  249. package/src/knowledge/types.ts +5 -8
  250. package/src/monitoring/constraint-doctor.ts +7 -106
  251. package/src/presets/__tests__/standard.test.ts +0 -2
  252. package/src/presets/standard.ts +1 -2
  253. package/src/spec/__tests__/annotation-checker.test.ts +9 -3
  254. package/src/spec/annotation-checker.ts +7 -29
  255. package/src/tools/CONTEXT.md +7 -14
  256. package/src/tools/index.ts +0 -4
  257. package/src/types/constraint.ts +1 -14
  258. package/src/types/project-config.ts +0 -3
  259. package/src/utils/file-walk.ts +2 -2
  260. package/dist/architecture/constraint-engine.d.ts +0 -67
  261. package/dist/architecture/constraint-engine.d.ts.map +0 -1
  262. package/dist/architecture/constraint-engine.js +0 -295
  263. package/dist/architecture/constraint-engine.js.map +0 -1
  264. package/dist/architecture/cross-project-checker.d.ts +0 -54
  265. package/dist/architecture/cross-project-checker.d.ts.map +0 -1
  266. package/dist/architecture/cross-project-checker.js +0 -467
  267. package/dist/architecture/cross-project-checker.js.map +0 -1
  268. package/dist/cli/commands/index.d.ts +0 -30
  269. package/dist/cli/commands/index.d.ts.map +0 -1
  270. package/dist/cli/commands/index.js +0 -91
  271. package/dist/cli/commands/index.js.map +0 -1
  272. package/dist/context/file-budget.d.ts +0 -40
  273. package/dist/context/file-budget.d.ts.map +0 -1
  274. package/dist/context/file-budget.js +0 -147
  275. package/dist/context/file-budget.js.map +0 -1
  276. package/dist/context/progressive-loader.d.ts +0 -109
  277. package/dist/context/progressive-loader.d.ts.map +0 -1
  278. package/dist/context/progressive-loader.js +0 -166
  279. package/dist/context/progressive-loader.js.map +0 -1
  280. package/dist/context/token-pipeline.d.ts +0 -55
  281. package/dist/context/token-pipeline.d.ts.map +0 -1
  282. package/dist/context/token-pipeline.js +0 -220
  283. package/dist/context/token-pipeline.js.map +0 -1
  284. package/dist/context/tool-output-budget.d.ts +0 -59
  285. package/dist/context/tool-output-budget.d.ts.map +0 -1
  286. package/dist/context/tool-output-budget.js +0 -177
  287. package/dist/context/tool-output-budget.js.map +0 -1
  288. package/dist/core/constraints/default-executors.d.ts +0 -10
  289. package/dist/core/constraints/default-executors.d.ts.map +0 -1
  290. package/dist/core/constraints/default-executors.js +0 -120
  291. package/dist/core/constraints/default-executors.js.map +0 -1
  292. package/dist/llm/adapter.d.ts +0 -36
  293. package/dist/llm/adapter.d.ts.map +0 -1
  294. package/dist/llm/adapter.js +0 -118
  295. package/dist/llm/adapter.js.map +0 -1
  296. package/dist/llm/index.d.ts +0 -3
  297. package/dist/llm/index.d.ts.map +0 -1
  298. package/dist/llm/index.js +0 -19
  299. package/dist/llm/index.js.map +0 -1
  300. package/dist/llm/types.d.ts +0 -62
  301. package/dist/llm/types.d.ts.map +0 -1
  302. package/dist/llm/types.js +0 -8
  303. package/dist/llm/types.js.map +0 -1
  304. package/dist/tools/core/index.d.ts +0 -13
  305. package/dist/tools/core/index.d.ts.map +0 -1
  306. package/dist/tools/core/index.js +0 -198
  307. package/dist/tools/core/index.js.map +0 -1
  308. package/dist/tools/loader.d.ts +0 -21
  309. package/dist/tools/loader.d.ts.map +0 -1
  310. package/dist/tools/loader.js +0 -199
  311. package/dist/tools/loader.js.map +0 -1
  312. package/dist/tools/registry.d.ts +0 -59
  313. package/dist/tools/registry.d.ts.map +0 -1
  314. package/dist/tools/registry.js +0 -115
  315. package/dist/tools/registry.js.map +0 -1
  316. package/dist/tools/types.d.ts +0 -38
  317. package/dist/tools/types.d.ts.map +0 -1
  318. package/dist/tools/types.js +0 -6
  319. package/dist/tools/types.js.map +0 -1
  320. package/src/__tests__/architecture-engine.test.ts +0 -619
  321. package/src/__tests__/context/progressive-loader.test.ts +0 -131
  322. package/src/__tests__/cross-project-checker.test.ts +0 -318
  323. package/src/architecture/CONTEXT.md +0 -22
  324. package/src/architecture/constraint-engine.ts +0 -351
  325. package/src/architecture/cross-project-checker.ts +0 -545
  326. package/src/cli/commands/index.ts +0 -30
  327. package/src/context/__tests__/file-budget.test.ts +0 -142
  328. package/src/context/__tests__/progressive-loader.test.ts +0 -264
  329. package/src/context/__tests__/token-pipeline.test.ts +0 -178
  330. package/src/context/__tests__/tool-output-budget.test.ts +0 -95
  331. package/src/context/file-budget.ts +0 -142
  332. package/src/context/progressive-loader.ts +0 -260
  333. package/src/context/token-pipeline.ts +0 -265
  334. package/src/context/tool-output-budget.ts +0 -178
  335. package/src/core/constraints/__tests__/default-executors.test.ts +0 -57
  336. package/src/core/constraints/default-executors.ts +0 -92
  337. package/src/llm/CONTEXT.md +0 -21
  338. package/src/llm/__tests__/adapter.test.ts +0 -172
  339. package/src/llm/adapter.ts +0 -149
  340. package/src/llm/index.ts +0 -2
  341. package/src/llm/types.ts +0 -81
  342. package/src/tools/__tests__/loader.test.ts +0 -252
  343. package/src/tools/__tests__/registry.test.ts +0 -157
  344. package/src/tools/core/__tests__/core.test.ts +0 -122
  345. package/src/tools/core/index.ts +0 -201
  346. package/src/tools/loader.ts +0 -216
  347. package/src/tools/registry.ts +0 -128
  348. package/src/tools/types.ts +0 -46
package/bin/harness.js CHANGED
@@ -2,595 +2,174 @@
2
2
 
3
3
  /**
4
4
  * @dommaker/harness CLI 入口
5
- *
5
+ *
6
6
  * 通用工程约束框架
7
+ *
8
+ * H5(#44):命令注册表驱动生成(R6 消灭手工 commander 块 + commands/index.ts
9
+ * 两处同步)+ per-command 懒加载(O2,拆单一 commands barrel)。
10
+ * 本文件是纯通用引擎:命令形状(名称/别名/选项/子命令/实现引用)全部来自
11
+ * COMMAND_DEFINITIONS(非门禁命令)与 GATE_DEFINITIONS.cli(6 门禁命令),
12
+ * 不含任何单命令知识;新增命令 = 命令文件 + 定义表一条 + 测试,不再改本文件。
7
13
  */
8
14
 
9
15
  const { Command } = require('commander');
10
16
  const { version } = require('../package.json');
11
17
 
12
18
  /**
13
- * 懒加载命令实现(工单 17):只在 .action 执行时 require 命令桶,
14
- * --version/--help 等不触发命令体的调用不再加载全部实现。
19
+ * 命令定义表(纯数据模块,无实现 import),--help/--version 懒加载不受影响;
20
+ * 门禁注册表双向闭环校验在实现加载期执行(src/gates/registry.ts),
21
+ * 命令实现引用可解析性断言在测试期执行(src/cli/commands/__tests__/registry.test.ts)。
15
22
  */
16
- function cmd(name) {
17
- return require('../dist/cli/commands/index')[name];
23
+ const { COMMAND_DEFINITIONS } = require('../dist/cli/commands/definitions');
24
+ const { GATE_DEFINITIONS } = require('../dist/gates/definitions');
25
+
26
+ /**
27
+ * per-command 懒加载(O2):按定义表中的 module+export 引用,只在 action
28
+ * 执行时 require 对应命令模块——任一命令执行不再经单一 barrel 加载全部命令实现。
29
+ */
30
+ function loadImpl(ref) {
31
+ const mod = require('../dist/cli/commands/' + ref.module);
32
+ const fn = mod[ref.export];
33
+ if (typeof fn !== 'function') {
34
+ throw new Error(
35
+ `[harness] 命令实现 "${ref.export}" 在 dist/cli/commands/${ref.module} 中不存在或不是函数。`
36
+ );
37
+ }
38
+ return fn;
18
39
  }
19
40
 
20
- const program = new Command();
41
+ function callImpl(ref, args = []) {
42
+ return loadImpl(ref)(...args);
43
+ }
21
44
 
22
- program
23
- .name('harness')
24
- .description('通用工程约束框架 - 铁律系统、检查点验证、测试门控、执行追踪')
25
- .version(version);
45
+ /** 位置参数个数('[a] [b]' → 2;无声明 → 0) */
46
+ function positionalCount(argument) {
47
+ if (!argument) return 0;
48
+ const matches = argument.match(/\[[^\]]+\]|<[^>]+>/g);
49
+ return matches ? matches.length : 0;
50
+ }
26
51
 
27
- // ========================================
28
- // harness check
29
- // ========================================
30
- program
31
- .command('check')
32
- .description('检查铁律是否满足')
33
- .option('-p, --preset <preset>', '预设名称', 'standard')
34
- .option('-s, --staged', '只检查暂存文件', false)
35
- .option('-t, --trigger <trigger>', '触发条件')
36
- .option('--project-path <path>', '项目路径')
37
- .option('--list', '列出所有铁律')
38
- .action(async (options) => {
39
- if (options.list) {
40
- cmd('listLaws')();
52
+ /**
53
+ * 定义表 → commander 命令树(递归处理 children,如 constraints report/retire)
54
+ */
55
+ function buildCommand(parent, def) {
56
+ const command = parent.command(def.command + (def.argument ? ' ' + def.argument : ''));
57
+ command.description(def.description);
58
+ if (def.alias) command.alias(def.alias);
59
+ for (const opt of def.options) {
60
+ if (opt.defaultValue !== undefined) {
61
+ command.option(opt.flags, opt.description, opt.defaultValue);
41
62
  } else {
42
- await cmd('check')(options);
63
+ command.option(opt.flags, opt.description);
43
64
  }
44
- });
45
-
46
- // ========================================
47
- // harness validate
48
- // ========================================
49
- program
50
- .command('validate')
51
- .description('验证检查点是否满足')
52
- .option('-f, --file <path>', '检查点文件路径')
53
- .option('-p, --project-path <path>', '项目路径')
54
- .option('--strict', '严格模式(任何失败都退出)', false)
55
- .action(async (options) => {
56
- await cmd('validate')(options);
57
- });
65
+ }
66
+
67
+ const argCount = positionalCount(def.argument);
68
+ command.action(async (...args) => {
69
+ // commander:有位置参数时 [p1..pN(缺失为 null), options, command];
70
+ // 无位置参数时 [options, command]
71
+ const positionals = argCount > 0
72
+ ? args.slice(0, argCount).map(p => (p === null ? undefined : p))
73
+ : [];
74
+ const options = argCount > 0 ? args[argCount] : args[0];
75
+ await runDefinition(command, def, positionals, options);
76
+ });
77
+
78
+ for (const child of def.children || []) {
79
+ buildCommand(command, child);
80
+ }
81
+ }
58
82
 
59
- // ========================================
60
- // harness passes-gate
61
- // ========================================
62
- program
63
- .command('passes-gate')
64
- .description('运行测试门控,确保测试通过')
65
- .alias('pg')
66
- .option('-t, --test-command <command>', '测试命令')
67
- .option('-p, --project-path <path>', '项目路径')
68
- .option('--allow-partial', '允许部分测试通过', false)
69
- .option('--max-retries <n>', '最大重试次数', '2')
70
- .option('--coverage', '检查测试覆盖率')
71
- .option('--coverage-threshold <n>', '覆盖率阈值', '80')
72
- .action(async (options) => {
73
- if (options.coverage) {
74
- const threshold = parseInt(options.coverageThreshold, 10);
75
- await cmd('runPassesGate')(options);
76
- const projectPath = options.projectPath || process.cwd();
77
- await cmd('checkCoverage')(projectPath, threshold);
78
- } else {
79
- await cmd('runPassesGate')(options);
83
+ /**
84
+ * 执行一条命令定义:
85
+ * 1. optionRoutes(选项条件路由,全部匹配项按序执行,替代默认 action)
86
+ * 2. subcommands(位置参数首值路由;strict 下未知值报错退出)
87
+ * 3. 默认 action
88
+ * afterRun 统一接收返回值(如 sync-docs --check 失败 exit(1)
89
+ */
90
+ async function runDefinition(command, def, positionals, options) {
91
+ if (def.optionRoutes) {
92
+ const matched = def.optionRoutes.filter(r => options[r.flag] === r.when);
93
+ if (matched.length > 0) {
94
+ for (const route of matched) {
95
+ await callImpl(route.impl, route.args ? route.args(positionals, options) : [options]);
96
+ }
97
+ return;
80
98
  }
81
- });
82
-
83
- // ========================================
84
- // harness init
85
- // ========================================
86
- program
87
- .command('init')
88
- .description('初始化项目的 harness 配置')
89
- .option('-p, --preset <preset>', '预设名称 (strict/standard/relaxed)', 'standard')
90
- .option('-g, --governance <level>', '治理级别 (minimal/standard/strict)')
91
- .option('-t, --type <type>', '项目类型 (node-api/nextjs-app/python-api/custom)')
92
- .option('--project-path <path>', '项目路径')
93
- .option('--no-git-hooks', '不创建 Git hooks')
94
- .option('--no-github-actions', '不创建 GitHub Actions')
95
- .option('--print-snippets', '只输出代码片段,不创建文件')
96
- .action(async (options) => {
97
- await cmd('init')(options);
98
- });
99
-
100
- // ========================================
101
- // harness report
102
- // ========================================
103
- program
104
- .command('report')
105
- .description('生成检查报告')
106
- .option('-o, --output <path>', '输出文件路径')
107
- .option('-f, --format <format>', '输出格式 (json/markdown/html)', 'markdown')
108
- .option('-p, --project-path <path>', '项目路径')
109
- .action(async (options) => {
110
- await cmd('report')(options);
111
- });
112
-
113
- // ========================================
114
- // harness status
115
- // ========================================
116
- program
117
- .command('status')
118
- .description('显示 Harness 状态、统计、异常检测')
119
- .option('-p, --project-path <path>', '项目路径')
120
- .option('-d, --detail', '显示详细信息', false)
121
- .option('-a, --anomalies', '只显示异常', false)
122
- .option('--hours <n>', '分析最近 N 小时', '24')
123
- .action(async (options) => {
124
- await cmd('status')({
125
- projectPath: options.projectPath,
126
- detail: options.detail,
127
- anomalies: options.anomalies,
128
- hours: parseInt(options.hours, 10),
129
- });
130
- });
131
-
132
- // ========================================
133
- // harness spec
134
- // ========================================
135
- program
136
- .command('spec [subcommand]')
137
- .description('Spec 验证命令')
138
- .option('-s, --schema <path>', 'Schema 路径(项目定义)')
139
- .option('--staged', '只验证暂存文件', false)
140
- .option('-f, --file <path>', '验证指定文件')
141
- .option('-p, --project-path <path>', '项目路径')
142
- .option('-v, --verbose', '详细输出', false)
143
- .action(async (subcommand, options, command) => {
144
- if (subcommand === 'list') {
145
- cmd('listSpecTypes')();
99
+ }
100
+
101
+ if (def.subcommands) {
102
+ const sub = positionals[0];
103
+ if (sub != null) {
104
+ const entry = def.subcommands[sub];
105
+ if (entry) {
106
+ const result = await callImpl(entry.impl, entry.args ? entry.args(positionals.slice(1), options) : [options]);
107
+ if (def.afterRun) def.afterRun(result, options);
108
+ return;
109
+ }
110
+ if (def.subcommandStrict !== false) {
111
+ console.error(`未知子命令: ${sub}`);
112
+ process.exit(1);
113
+ }
114
+ // strict(如 spec):未知位置参数落回默认 action
146
115
  } else {
147
- // 默认执行 validate
148
- await cmd('specValidate')({
149
- schema: options.schema,
150
- staged: options.staged,
151
- file: options.file || (subcommand && !subcommand.startsWith('-') ? subcommand : undefined),
152
- projectPath: options.projectPath,
153
- verbose: options.verbose,
154
- });
116
+ // 无子命令时显示帮助
117
+ command.help();
118
+ return;
155
119
  }
156
- });
120
+ }
121
+
122
+ if (!def.action) {
123
+ command.help();
124
+ return;
125
+ }
126
+ const result = await callImpl(def.action, def.mapActionArgs ? def.mapActionArgs(positionals, options) : [options]);
127
+ if (def.afterRun) def.afterRun(result, options);
128
+ }
157
129
 
158
- // ========================================
159
- // harness acceptance
160
- // ========================================
161
- program
162
- .command('acceptance [subcommand]')
163
- .description('验收标准门控,检查任务是否满足验收标准')
164
- .alias('acc')
165
- .option('-t, --task-id <id>', '任务 ID')
166
- .option('--tasks-path <path>', 'tasks.yml 路径')
167
- .option('-p, --project-path <path>', '项目路径')
168
- .option('--check-all', '检查所有任务', false)
169
- .option('--run-e2e', '运行 E2E 测试', false)
170
- .action(async (subcommand, options, command) => {
171
- if (subcommand === 'list') {
172
- await cmd('listAcceptanceCriteria')(options);
173
- } else {
174
- await cmd('acceptance')(options);
175
- }
176
- });
130
+ const program = new Command();
177
131
 
178
- // ========================================
179
- // harness performance
180
- // ========================================
181
132
  program
182
- .command('performance')
183
- .description('性能门控,检查性能指标')
184
- .alias('perf')
185
- .option('-p, --project-path <path>', '项目路径')
186
- .option('--coverage', '检查测试覆盖率', false)
187
- .option('--coverage-threshold <n>', '覆盖率阈值', '80')
188
- .option('--bundle', '检查打包大小', false)
189
- .option('--bundle-threshold <n>', '打包大小阈值 (KB)', '500')
190
- .option('--benchmark', '运行基准测试', false)
191
- .option('--benchmark-timeout <n>', '基准测试超时(秒)', '60')
192
- .action(async (options) => {
193
- await cmd('performance')({
194
- projectPath: options.projectPath,
195
- coverage: options.coverage,
196
- coverageThreshold: parseInt(options.coverageThreshold, 10),
197
- bundle: options.bundle,
198
- bundleThreshold: parseInt(options.bundleThreshold, 10),
199
- benchmark: options.benchmark,
200
- benchmarkTimeout: parseInt(options.benchmarkTimeout, 10),
201
- });
202
- });
133
+ .name('harness')
134
+ .description('通用工程约束框架 - 铁律系统、检查点验证、测试门控、执行追踪')
135
+ .version(version);
203
136
 
204
137
  // ========================================
205
- // harness security
138
+ // 非门禁命令:COMMAND_DEFINITIONS 注册表驱动生成
206
139
  // ========================================
207
- program
208
- .command('security [subcommand]')
209
- .description('安全门控,检查安全漏洞')
210
- .alias('sec')
211
- .option('-p, --project-path <path>', '项目路径')
212
- .option('--severity <level>', '严重性阈值 (low/moderate/high/critical)', 'high')
213
- .option('--ignore-warnings', '忽略警告', false)
214
- .option('--ignore-dev-deps', '忽略开发依赖', false)
215
- .option('--scan-command <cmd>', '自定义扫描命令')
216
- .action(async (subcommand, options, command) => {
217
- if (subcommand === 'audit') {
218
- await cmd('auditDetails')(options);
219
- } else {
220
- await cmd('security')(options);
221
- }
222
- });
140
+ for (const def of COMMAND_DEFINITIONS) {
141
+ buildCommand(program, def);
142
+ }
223
143
 
224
144
  // ========================================
225
- // harness contract
145
+ // 门禁命令(6 个):GATE_DEFINITIONS.cli 注册表驱动生成(G1)
226
146
  // ========================================
227
- program
228
- .command('contract [subcommand]')
229
- .description('API 契约门控,检查 OpenAPI Schema')
230
- .option('-p, --project-path <path>', '项目路径')
231
- .option('--contract-path <path>', '契约文件路径', 'openapi.yaml')
232
- .option('--no-strict', '关闭严格模式')
233
- .option('--allow-breaking', '允许破坏性变更', false)
234
- .action(async (subcommand, options, command) => {
235
- if (subcommand === 'validate') {
236
- await cmd('validateSchema')(options);
147
+ for (const def of GATE_DEFINITIONS) {
148
+ const cli = def.cli;
149
+ const command = program.command(cli.command + (cli.argument ? ' ' + cli.argument : ''));
150
+ command.description(cli.description);
151
+ if (cli.alias) {
152
+ command.alias(cli.alias);
153
+ }
154
+ for (const opt of cli.options) {
155
+ if (opt.defaultValue !== undefined) {
156
+ command.option(opt.flags, opt.description, opt.defaultValue);
237
157
  } else {
238
- await cmd('contract')(options);
158
+ command.option(opt.flags, opt.description);
239
159
  }
240
- });
241
-
242
- // ========================================
243
- // harness review
244
- // ========================================
245
- program
246
- .command('review [subcommand]')
247
- .description('代码审查门控,检查审查状态')
248
- .option('-p, --project-path <path>', '项目路径')
249
- .option('--min-reviewers <n>', '最少审查人数', '1')
250
- .option('--no-require-approval', '不要求审批')
251
- .option('--no-block-on-changes', '不阻止变更请求')
252
- .option('--allowed-reviewers <list>', '允许的审查者(逗号分隔)')
253
- .action(async (subcommand, options, command) => {
254
- if (subcommand === 'status') {
255
- await cmd('reviewStatus')(options);
160
+ }
161
+ command.action(async (arg, options) => {
162
+ // commander:无位置参数的命令把 options 传入第一个形参
163
+ const realArg = cli.argument ? arg : undefined;
164
+ const realOptions = cli.argument ? options : arg;
165
+ const sub = cli.subcommands && realArg != null ? cli.subcommands[realArg] : undefined;
166
+ if (sub) {
167
+ await callImpl(sub, [realOptions]);
256
168
  } else {
257
- await cmd('review')({
258
- projectPath: options.projectPath,
259
- minReviewers: parseInt(options.minReviewers, 10),
260
- requireApproval: options.requireApproval,
261
- blockOnChangesRequested: options.blockOnChanges,
262
- allowedReviewers: options.allowedReviewers,
263
- });
264
- }
265
- });
266
-
267
- // ========================================
268
- // harness command
269
- // ========================================
270
- program
271
- .command('command [cmd]')
272
- .description('检查命令是否在黑名单中')
273
- .alias('cmd')
274
- .option('-l, --level', '显示风险等级')
275
- .option('--list', '列出所有黑名单规则')
276
- .option('--json', 'JSON 格式输出')
277
- .option('--strict', '严格模式(warn 也阻止)')
278
- .action(async (cmdArg, options) => {
279
- await cmd('executeCommand')(cmdArg, options);
280
- });
281
-
282
- // ========================================
283
- // harness sync-docs
284
- // ========================================
285
- program
286
- .command('sync-docs')
287
- .description('同步项目文档(CAPABILITIES.md、CONTEXT.md、AGENTS.md)')
288
- .option('-p, --project-path <path>', '项目路径')
289
- .option('-c, --check', '只检查不修改(CI 模式)', false)
290
- .option('--json', '输出 JSON 格式(供 LLM 消费)', false)
291
- .option('--agents', '同步 AGENTS.md(agent 导读;PRESERVE 标记段重新生成时保留)', false)
292
- .option('--compact', '一次性迁移:将 CAPABILITIES.md 文件表格折叠为目录条目', false)
293
- .action(async (options) => {
294
- const ok = await cmd('syncDocs')(options);
295
- if (!ok && options.check) {
296
- process.exit(1);
297
- }
298
- });
299
-
300
- // ========================================
301
- // harness knowledge
302
- // ========================================
303
- program
304
- .command('knowledge [subcommand] [arg]')
305
- .description('知识库管理(list/search/import/decay/stats/audit)')
306
- .alias('kb')
307
- .option('-p, --project-path <path>', '项目路径')
308
- .option('--type <types>', '按类型过滤(逗号分隔)')
309
- .option('--maturity <levels>', '按成熟度过滤(逗号分隔)')
310
- .option('--tag <tags>', '按标签过滤(逗号分隔)')
311
- .option('--sources <sources>', '导入源(逗号分隔: code,git,docs)')
312
- .option('--limit <n>', '结果数量限制', '20')
313
- .option('--reset', '重置导入状态', false)
314
- .option('--scope <scope>', '知识范围(用于 upsert 去重)')
315
- .option('--title <title>', '知识标题(用于 upsert)')
316
- .option('--content <content>', '知识内容 Markdown(用于 upsert)')
317
- .option('--file <path>', '从文件读取内容(用于 upsert)')
318
- .option('--source <source>', '知识来源 (analyst/cli/design)', 'cli')
319
- .option('--fix', '自动修复(用于 audit)', false)
320
- .option('--dry-run', '只输出报告不修改(用于 audit)', false)
321
- .option('--threshold <n>', '短内容阈值(字符数,用于 audit)', '50')
322
- .option('--dir <path>', '知识库目录(覆盖默认路径)')
323
- .option('--json', 'JSON 格式输出', false)
324
- .action(async (subcommand, arg, options) => {
325
- const opts = { projectPath: options.projectPath, json: options.json };
326
- switch (subcommand) {
327
- case 'list':
328
- case 'ls':
329
- await cmd('knowledgeList')({ ...opts, type: options.type, maturity: options.maturity, tag: options.tag });
330
- break;
331
- case 'search':
332
- case 's':
333
- if (!arg) { console.error('请提供搜索关键词'); process.exit(1); }
334
- await cmd('knowledgeSearch')(arg, { ...opts, limit: parseInt(options.limit, 10) });
335
- break;
336
- case 'import':
337
- case 'i':
338
- await cmd('knowledgeImport')({ ...opts, sources: options.sources, reset: options.reset });
339
- break;
340
- case 'decay':
341
- case 'd':
342
- await cmd('knowledgeDecay')(opts);
343
- break;
344
- case 'stats':
345
- case 'st':
346
- await cmd('knowledgeStats')(opts);
347
- break;
348
- case 'sync-rag':
349
- await cmd('knowledgeSyncRag')(opts);
350
- break;
351
- case 'sync-status':
352
- case 'sync':
353
- await cmd('knowledgeSyncStatus')(opts);
354
- break;
355
- case 'upsert':
356
- case 'up':
357
- await cmd('knowledgeUpsert')({
358
- scope: options.scope || '',
359
- title: options.title || '',
360
- content: options.content || '',
361
- file: options.file || '',
362
- type: options.type || 'architecture',
363
- source: options.source || 'cli',
364
- });
365
- break;
366
- case 'audit':
367
- case 'a':
368
- await cmd('knowledgeAudit')({
369
- ...opts,
370
- fix: options.fix,
371
- dryRun: options.dryRun,
372
- threshold: options.threshold,
373
- dir: options.dir,
374
- });
375
- break;
376
- case 'snapshot':
377
- cmd('knowledgeSnapshot')({ ...opts, dir: options.dir });
378
- break;
379
- case 'migrate':
380
- cmd('knowledgeMigrate')({ ...opts, dir: options.dir });
381
- break;
382
- case 'index':
383
- case 'idx':
384
- cmd('knowledgeIndex')({ ...opts, dir: options.dir });
385
- break;
386
- case 'health':
387
- case 'h':
388
- await cmd('knowledgeHealth')({ ...opts, dir: options.dir });
389
- break;
390
- default:
391
- // 无子命令时显示帮助
392
- if (!subcommand) {
393
- program.commands.find(c => c.name() === 'knowledge').help();
394
- } else {
395
- console.error(`未知子命令: ${subcommand}`);
396
- process.exit(1);
397
- }
398
- }
399
- });
400
-
401
- // ========================================
402
- // harness sdd
403
- // ========================================
404
- program
405
- .command('sdd [subcommand]')
406
- .description('SDD 管理(index)')
407
- .option('-p, --project-path <path>', '项目路径')
408
- .option('--dir <dir>', '指定基础目录')
409
- .option('--json', 'JSON 输出')
410
- .action(async (subcommand, options) => {
411
- const opts = { projectPath: options.projectPath, json: options.json };
412
- switch (subcommand) {
413
- case 'index':
414
- case 'idx':
415
- cmd('sddIndex')({ ...opts, dir: options.dir });
416
- break;
417
- default:
418
- if (!subcommand) {
419
- program.commands.find(c => c.name() === 'sdd').help();
420
- } else {
421
- console.error(`未知子命令: ${subcommand}`);
422
- process.exit(1);
423
- }
424
- }
425
- });
426
-
427
- // ========================================
428
- // harness failure
429
- // ========================================
430
- program
431
- .command('failure [subcommand]')
432
- .description('失败记录管理(list/stats/clear)')
433
- .option('-p, --project-path <path>', '项目路径')
434
- .option('--type <type>', '按错误类型过滤')
435
- .option('--level <level>', '按失败等级过滤 (L1/L2/L3/L4)')
436
- .option('--limit <n>', '结果数量限制', '20')
437
- .option('--json', 'JSON 格式输出', false)
438
- .action(async (subcommand, options) => {
439
- const opts = { projectPath: options.projectPath, json: options.json };
440
- switch (subcommand) {
441
- case 'list':
442
- case 'ls':
443
- await cmd('failureList')({ ...opts, limit: parseInt(options.limit, 10), type: options.type, level: options.level });
444
- break;
445
- case 'stats':
446
- case 'st':
447
- await cmd('failureStats')(opts);
448
- break;
449
- case 'clear':
450
- await cmd('failureClear')(opts);
451
- break;
452
- default:
453
- if (!subcommand) {
454
- program.commands.find(c => c.name() === 'failure').help();
455
- } else {
456
- console.error(`未知子命令: ${subcommand}`);
457
- process.exit(1);
458
- }
169
+ await callImpl(cli.action, cli.mapActionArgs(realArg, realOptions));
459
170
  }
460
171
  });
461
-
462
- // ========================================
463
- // harness posteval-plan
464
- // ========================================
465
- program
466
- .command('posteval-plan <planPath>')
467
- .description('验证 plan 文件的 checklist items 是否都有对应的 staged diff')
468
- .action(async (planPath) => {
469
- await cmd('postevalPlan')({ planPath });
470
- });
471
-
472
- // ========================================
473
- // harness update-user-model
474
- // ========================================
475
- program
476
- .command('update-user-model')
477
- .description('从新对话中提取信号,更新用户思维模型(增量演化)')
478
- .alias('uum')
479
- .option('--json', 'JSON 格式输出', false)
480
- .option('--dry-run', '只显示变化,不更新状态', false)
481
- .option('--days <n>', '只处理最近 N 天的会话(自然日,含今天)')
482
- .action(async (options) => {
483
- await cmd('updateUserModel')({
484
- days: options.days !== undefined ? parseInt(options.days, 10) : undefined,
485
- json: options.json,
486
- dryRun: options.dryRun,
487
- });
488
- });
489
-
490
- // ========================================
491
- // harness release
492
- // ========================================
493
- program
494
- .command('release')
495
- .description('npm 发布流水线:tsc → dist 验证 → npm version → git push → npm publish → gh release。不依赖 Studio API。')
496
- .option('--bump <type>', '版本递增类型', 'patch')
497
- .option('--dry-run <bool>', '仅模拟执行', 'false')
498
- .action(async (options) => {
499
- await cmd('release')({ bumpType: options.bump, dryRun: options.dryRun });
500
- });
501
-
502
- // ========================================
503
- // harness analyze-sessions
504
- // ========================================
505
- program
506
- .command('analyze-sessions')
507
- .description('分析 Claude Code 对话,挖掘纠正模式和高频概念,生成规则候选')
508
- .alias('analyze')
509
- .option('-d, --days <n>', '分析最近 N 天的会话', '7')
510
- .option('--json', 'JSON 格式输出', false)
511
- .action(async (options) => {
512
- await cmd('analyzeSessions')({
513
- days: parseInt(options.days, 10),
514
- json: options.json,
515
- });
516
- });
517
-
518
- // ========================================
519
- // harness constraints
520
- // ========================================
521
- const constraintsCmd = program
522
- .command('constraints')
523
- .description('输出约束集合元数据(版本、hash、计数、文本大小)')
524
- .option('--json', '输出 JSON 格式', false)
525
- .action(async (options) => {
526
- await cmd('constraints')(options);
527
- });
528
-
529
- constraintsCmd
530
- .command('report')
531
- .description('约束使用报告:check 层统计表、退役候选诊断、prompt 注入清单、配置健康(只读)')
532
- .option('-p, --project-path <path>', '项目路径')
533
- .option('--export [file]', '导出脱敏 markdown 摘要(缺省 .harness/reports/constraints-<YYYYMMDD>.md)')
534
- .option('--json', '输出 JSON 格式', false)
535
- .option('--zero-intercept-min <n>', '零拦截候选的最小评估样本数', '50')
536
- .option('--noise-fail-rate <rate>', '高噪候选 fail 率阈值', '0.8')
537
- .option('--noise-min-total <n>', '高噪候选最小评估样本数', '20')
538
- .action(async (options) => {
539
- await cmd('constraintsReport')({
540
- projectPath: options.projectPath,
541
- export: options.export,
542
- json: options.json,
543
- zeroInterceptMin: parseInt(options.zeroInterceptMin, 10),
544
- noiseFailRate: parseFloat(options.noiseFailRate),
545
- noiseMinTotal: parseInt(options.noiseMinTotal, 10),
546
- });
547
- });
548
-
549
- constraintsCmd
550
- .command('retire [id]')
551
- .description('退役约束:无 id 进入交互式候选选择(人确认);带 id 直达退役需显式 --yes(写 config.yml + KnowledgeStore + 同步 CLAUDE.md 注入段)')
552
- .option('-p, --project-path <path>', '项目路径')
553
- .option('--reason <text>', '退役原因')
554
- .option('-y, --yes', '显式确认直达退役(人确认闸门;无此 flag 直达报错并提示改走交互模式)', false)
555
- .action(async (id, options) => {
556
- await cmd('constraintsRetire')(id, {
557
- projectPath: options.projectPath,
558
- reason: options.reason,
559
- yes: options.yes,
560
- });
561
- });
562
-
563
- // ========================================
564
- // harness doc-freshness-check
565
- // ========================================
566
- program
567
- .command('doc-freshness-check <docPath>')
568
- .description('检查文档声明的新鲜度:提取可验证声明,与代码对照')
569
- .option('--changed-files <list>', '变更文件列表(逗号分隔)')
570
- .option('--format <format>', '输出格式 (table/json)', 'table')
571
- .option('-p, --project-path <path>', '项目路径')
572
- .action(async (docPath, options) => {
573
- await cmd('docFreshnessCheck')(docPath, {
574
- changedFiles: options.changedFiles,
575
- format: options.format,
576
- projectPath: options.projectPath,
577
- });
578
- });
579
-
580
- // ========================================
581
- // harness spec-baseline-check
582
- // ========================================
583
- program
584
- .command('spec-baseline-check <specPath>')
585
- .description('验证 spec 文件的前置条件是否满足')
586
- .option('-p, --project-path <path>', '项目路径')
587
- .option('--json', '输出 JSON 格式', false)
588
- .action(async (specPath, options) => {
589
- await cmd('specBaselineCheck')(specPath, {
590
- projectPath: options.projectPath,
591
- json: options.json,
592
- });
593
- });
172
+ }
594
173
 
595
174
  // 解析命令行参数
596
175
  program.parse();