@dommaker/harness 0.13.0 → 0.13.2

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 (420) hide show
  1. package/CHANGELOG.md +169 -0
  2. package/bin/harness-knowledge-capture.js +99 -0
  3. package/bin/harness-knowledge-check.js +149 -0
  4. package/bin/harness-knowledge-track.js +92 -0
  5. package/bin/harness-knowledge-track.sh +47 -0
  6. package/bin/harness-sensitive-check.sh +67 -0
  7. package/dist/cli/commands/init.js +34 -2
  8. package/dist/cli/commands/init.js.map +1 -1
  9. package/package.json +6 -3
  10. package/src/CONTEXT.md +34 -0
  11. package/src/__tests__/acceptance-gate.test.ts +364 -0
  12. package/src/__tests__/annotation-checker.test.ts +183 -0
  13. package/src/__tests__/architecture-engine.test.ts +619 -0
  14. package/src/__tests__/checker-extra.test.ts +1627 -0
  15. package/src/__tests__/checker.test.ts +1268 -0
  16. package/src/__tests__/checkpoint.test.ts +697 -0
  17. package/src/__tests__/clean-state-extra.test.ts +301 -0
  18. package/src/__tests__/clean-state.test.ts +169 -0
  19. package/src/__tests__/constraint-doctor.test.ts +410 -0
  20. package/src/__tests__/constraint-evolver.test.ts +404 -0
  21. package/src/__tests__/constraint-handler.test.ts +136 -0
  22. package/src/__tests__/context/progressive-loader.test.ts +131 -0
  23. package/src/__tests__/contract-gate.test.ts +321 -0
  24. package/src/__tests__/cross-project-checker.test.ts +318 -0
  25. package/src/__tests__/cso-validator.test.ts +205 -0
  26. package/src/__tests__/detect-source-roots.test.ts +98 -0
  27. package/src/__tests__/doctor-evolver.test.ts +381 -0
  28. package/src/__tests__/error-classifier.test.ts +304 -0
  29. package/src/__tests__/exec.test.ts +83 -0
  30. package/src/__tests__/extend-exceptions.test.ts +149 -0
  31. package/src/__tests__/failure-recorder.test.ts +335 -0
  32. package/src/__tests__/hooks-pipeline.test.ts +214 -0
  33. package/src/__tests__/interceptor.test.ts +89 -0
  34. package/src/__tests__/iron-laws.test.ts +246 -0
  35. package/src/__tests__/long-running.test.ts +17 -0
  36. package/src/__tests__/passes-gate-check.test.ts +138 -0
  37. package/src/__tests__/passes-gate-extension.test.ts +151 -0
  38. package/src/__tests__/passes-gate-extra.test.ts +238 -0
  39. package/src/__tests__/passes-gate.test.ts +231 -0
  40. package/src/__tests__/performance-analyzer.test.ts +501 -0
  41. package/src/__tests__/performance-collector.test.ts +276 -0
  42. package/src/__tests__/performance-gate.test.ts +74 -0
  43. package/src/__tests__/presets.test.ts +104 -0
  44. package/src/__tests__/project-config-loader-extra.test.ts +269 -0
  45. package/src/__tests__/project-config-loader.test.ts +127 -0
  46. package/src/__tests__/review-gate.test.ts +92 -0
  47. package/src/__tests__/security-gate.test.ts +100 -0
  48. package/src/__tests__/session-startup.test.ts +334 -0
  49. package/src/__tests__/spec-validator.test.ts +57 -0
  50. package/src/__tests__/token-budget.test.ts +252 -0
  51. package/src/__tests__/trace-analyzer-extra.test.ts +307 -0
  52. package/src/__tests__/trace-analyzer.test.ts +131 -0
  53. package/src/__tests__/trace-collector.test.ts +258 -0
  54. package/src/__tests__/traces.test.ts +347 -0
  55. package/src/agents/CONTEXT.md +21 -0
  56. package/src/agents/__tests__/lifecycle.test.ts +248 -0
  57. package/src/agents/index.ts +2 -0
  58. package/src/agents/lifecycle.ts +201 -0
  59. package/src/agents/types.ts +46 -0
  60. package/src/architecture/CONTEXT.md +22 -0
  61. package/src/architecture/constraint-engine.ts +356 -0
  62. package/src/architecture/cross-project-checker.ts +563 -0
  63. package/src/cli/commands/CONTEXT.md +24 -0
  64. package/src/cli/commands/__tests__/acceptance.test.ts +180 -0
  65. package/src/cli/commands/__tests__/check.test.ts +598 -0
  66. package/src/cli/commands/__tests__/command.test.ts +149 -0
  67. package/src/cli/commands/__tests__/contract.test.ts +151 -0
  68. package/src/cli/commands/__tests__/failure.test.ts +199 -0
  69. package/src/cli/commands/__tests__/flow.test.ts +343 -0
  70. package/src/cli/commands/__tests__/init.test.ts +306 -0
  71. package/src/cli/commands/__tests__/passes-gate.test.ts +256 -0
  72. package/src/cli/commands/__tests__/performance.test.ts +116 -0
  73. package/src/cli/commands/__tests__/posteval-plan.test.ts +201 -0
  74. package/src/cli/commands/__tests__/report-extra.test.ts +98 -0
  75. package/src/cli/commands/__tests__/report.test.ts +109 -0
  76. package/src/cli/commands/__tests__/review.test.ts +153 -0
  77. package/src/cli/commands/__tests__/security.test.ts +147 -0
  78. package/src/cli/commands/__tests__/spec.test.ts +193 -0
  79. package/src/cli/commands/__tests__/status-extra.test.ts +223 -0
  80. package/src/cli/commands/__tests__/status.test.ts +306 -0
  81. package/src/cli/commands/__tests__/sync-docs.test.ts +335 -0
  82. package/src/cli/commands/__tests__/validate.test.ts +139 -0
  83. package/src/cli/commands/acceptance.ts +111 -0
  84. package/src/cli/commands/analyze-sessions.ts +488 -0
  85. package/src/cli/commands/check.ts +441 -0
  86. package/src/cli/commands/command.ts +90 -0
  87. package/src/cli/commands/constraints.ts +86 -0
  88. package/src/cli/commands/contract.ts +168 -0
  89. package/src/cli/commands/failure.ts +117 -0
  90. package/src/cli/commands/flow.ts +275 -0
  91. package/src/cli/commands/index.ts +26 -0
  92. package/src/cli/commands/init.ts +832 -0
  93. package/src/cli/commands/knowledge.ts +391 -0
  94. package/src/cli/commands/passes-gate.ts +158 -0
  95. package/src/cli/commands/performance.ts +108 -0
  96. package/src/cli/commands/posteval-plan.ts +85 -0
  97. package/src/cli/commands/release.ts +159 -0
  98. package/src/cli/commands/report.ts +198 -0
  99. package/src/cli/commands/review.ts +118 -0
  100. package/src/cli/commands/security.ts +122 -0
  101. package/src/cli/commands/spec.ts +158 -0
  102. package/src/cli/commands/status.ts +169 -0
  103. package/src/cli/commands/sync-docs.ts +743 -0
  104. package/src/cli/commands/update-user-model.ts +527 -0
  105. package/src/cli/commands/validate.ts +222 -0
  106. package/src/constraints/__tests__/lifecycle-runner.test.ts +246 -0
  107. package/src/constraints/__tests__/registry.test.ts +196 -0
  108. package/src/constraints/index.ts +3 -0
  109. package/src/constraints/lifecycle-runner.ts +184 -0
  110. package/src/constraints/registry.ts +134 -0
  111. package/src/constraints/types.ts +59 -0
  112. package/src/context/CONTEXT.md +28 -0
  113. package/src/context/__tests__/compaction.test.ts +169 -0
  114. package/src/context/__tests__/file-budget.test.ts +142 -0
  115. package/src/context/__tests__/knowledge-injector.test.ts +148 -0
  116. package/src/context/__tests__/progressive-loader.test.ts +264 -0
  117. package/src/context/__tests__/session-manager.test.ts +300 -0
  118. package/src/context/__tests__/token-budget.test.ts +338 -0
  119. package/src/context/__tests__/token-pipeline.test.ts +178 -0
  120. package/src/context/__tests__/tool-output-budget.test.ts +95 -0
  121. package/src/context/compaction.ts +202 -0
  122. package/src/context/file-budget.ts +142 -0
  123. package/src/context/index.ts +15 -0
  124. package/src/context/knowledge-injector.ts +168 -0
  125. package/src/context/progressive-loader.ts +260 -0
  126. package/src/context/session-manager.ts +343 -0
  127. package/src/context/token-budget.ts +295 -0
  128. package/src/context/token-pipeline.ts +265 -0
  129. package/src/context/tool-output-budget.ts +178 -0
  130. package/src/context/types.ts +160 -0
  131. package/src/core/CONTEXT.md +26 -0
  132. package/src/core/constraints/__tests__/default-executors.test.ts +57 -0
  133. package/src/core/constraints/__tests__/interceptor.test.ts +251 -0
  134. package/src/core/constraints/__tests__/prompt-injection.test.ts +89 -0
  135. package/src/core/constraints/check-cache.ts +96 -0
  136. package/src/core/constraints/checker.ts +1169 -0
  137. package/src/core/constraints/default-executors.ts +92 -0
  138. package/src/core/constraints/definitions.ts +1119 -0
  139. package/src/core/constraints/doc-freshness/__tests__/runner.test.ts +551 -0
  140. package/src/core/constraints/doc-freshness/auto-fix.ts +69 -0
  141. package/src/core/constraints/doc-freshness/runner.ts +486 -0
  142. package/src/core/constraints/index.ts +78 -0
  143. package/src/core/constraints/interceptor.ts +220 -0
  144. package/src/core/constraints/prompt-injection.ts +73 -0
  145. package/src/core/index.ts +23 -0
  146. package/src/core/project-config-loader.ts +252 -0
  147. package/src/core/session/__tests__/startup.test.ts +281 -0
  148. package/src/core/session/clean-state.ts +178 -0
  149. package/src/core/session/index.ts +15 -0
  150. package/src/core/session/startup.ts +253 -0
  151. package/src/core/spec/__tests__/validator.test.ts +379 -0
  152. package/src/core/spec/index.ts +7 -0
  153. package/src/core/spec/validator.ts +383 -0
  154. package/src/core/validators/__tests__/passes-gate.test.ts +131 -0
  155. package/src/core/validators/checkpoint.ts +547 -0
  156. package/src/core/validators/cso.ts +124 -0
  157. package/src/core/validators/index.ts +25 -0
  158. package/src/core/validators/passes-gate.ts +613 -0
  159. package/src/dashboard/CONTEXT.md +21 -0
  160. package/src/dashboard/__tests__/data.test.ts +115 -0
  161. package/src/dashboard/__tests__/stats.test.ts +156 -0
  162. package/src/dashboard/data.ts +113 -0
  163. package/src/dashboard/index.ts +3 -0
  164. package/src/dashboard/stats.ts +127 -0
  165. package/src/dashboard/types.ts +113 -0
  166. package/src/evolution/CONTEXT.md +22 -0
  167. package/src/evolution/__tests__/auto-evolve.test.ts +320 -0
  168. package/src/evolution/auto-evolve.ts +98 -0
  169. package/src/evolution/index.ts +1 -0
  170. package/src/failure/CONTEXT.md +24 -0
  171. package/src/failure/classifier.ts +156 -0
  172. package/src/failure/constraint-handler.ts +173 -0
  173. package/src/failure/index.ts +35 -0
  174. package/src/failure/recorder.ts +201 -0
  175. package/src/failure/types.ts +165 -0
  176. package/src/gates/CONTEXT.md +27 -0
  177. package/src/gates/__tests__/acceptance.test.ts +608 -0
  178. package/src/gates/__tests__/command.test.ts +206 -0
  179. package/src/gates/__tests__/performance.test.ts +381 -0
  180. package/src/gates/__tests__/review.test.ts +302 -0
  181. package/src/gates/__tests__/security.test.ts +332 -0
  182. package/src/gates/acceptance.ts +493 -0
  183. package/src/gates/command.ts +444 -0
  184. package/src/gates/contract.ts +260 -0
  185. package/src/gates/index.ts +67 -0
  186. package/src/gates/performance.ts +359 -0
  187. package/src/gates/review.ts +169 -0
  188. package/src/gates/security.ts +244 -0
  189. package/src/gates/types.ts +159 -0
  190. package/src/governance/CONTEXT.md +22 -0
  191. package/src/governance/__tests__/executor.test.ts +249 -0
  192. package/src/governance/executor.ts +229 -0
  193. package/src/governance/index.ts +13 -0
  194. package/src/governance/types.ts +53 -0
  195. package/src/hooks/CONTEXT.md +23 -0
  196. package/src/hooks/__tests__/bootstrap.test.ts +184 -0
  197. package/src/hooks/bootstrap.ts +144 -0
  198. package/src/hooks/index.ts +15 -0
  199. package/src/hooks/pipeline.ts +157 -0
  200. package/src/hooks/registry.ts +88 -0
  201. package/src/hooks/types.ts +80 -0
  202. package/src/index.ts +198 -0
  203. package/src/knowledge/CONTEXT.md +29 -0
  204. package/src/knowledge/__tests__/doctor.test.ts +272 -0
  205. package/src/knowledge/__tests__/import.test.ts +376 -0
  206. package/src/knowledge/__tests__/ingest.test.ts +125 -0
  207. package/src/knowledge/__tests__/lifecycle-hooks.test.ts +137 -0
  208. package/src/knowledge/__tests__/lifecycle.test.ts +248 -0
  209. package/src/knowledge/__tests__/lint.test.ts +401 -0
  210. package/src/knowledge/__tests__/query.test.ts +185 -0
  211. package/src/knowledge/__tests__/reference-tracker.test.ts +129 -0
  212. package/src/knowledge/__tests__/store.test.ts +238 -0
  213. package/src/knowledge/doctor.ts +104 -0
  214. package/src/knowledge/import.ts +505 -0
  215. package/src/knowledge/index.ts +16 -0
  216. package/src/knowledge/ingest.ts +126 -0
  217. package/src/knowledge/lifecycle-hooks.ts +199 -0
  218. package/src/knowledge/lifecycle.ts +175 -0
  219. package/src/knowledge/lint.ts +360 -0
  220. package/src/knowledge/query.ts +150 -0
  221. package/src/knowledge/reference-tracker.ts +99 -0
  222. package/src/knowledge/store.ts +264 -0
  223. package/src/knowledge/types.ts +139 -0
  224. package/src/llm/CONTEXT.md +21 -0
  225. package/src/llm/__tests__/adapter.test.ts +172 -0
  226. package/src/llm/adapter.ts +149 -0
  227. package/src/llm/index.ts +2 -0
  228. package/src/llm/types.ts +81 -0
  229. package/src/monitoring/CONTEXT.md +29 -0
  230. package/src/monitoring/__tests__/context-tracker.test.ts +172 -0
  231. package/src/monitoring/__tests__/knowledge-doctor.test.ts +276 -0
  232. package/src/monitoring/__tests__/knowledge-evolver.test.ts +365 -0
  233. package/src/monitoring/__tests__/performance-analyzer.test.ts +137 -0
  234. package/src/monitoring/__tests__/performance-collector.test.ts +332 -0
  235. package/src/monitoring/__tests__/traces.test.ts +190 -0
  236. package/src/monitoring/constraint-doctor.ts +499 -0
  237. package/src/monitoring/constraint-evolver.ts +573 -0
  238. package/src/monitoring/context-tracker.ts +148 -0
  239. package/src/monitoring/index.ts +23 -0
  240. package/src/monitoring/knowledge-doctor.ts +323 -0
  241. package/src/monitoring/knowledge-evolver.ts +289 -0
  242. package/src/monitoring/performance-analyzer.ts +450 -0
  243. package/src/monitoring/performance-collector.ts +348 -0
  244. package/src/monitoring/trace-analyzer.ts +470 -0
  245. package/src/monitoring/traces.ts +339 -0
  246. package/src/presets/__tests__/standard.test.ts +104 -0
  247. package/src/presets/index.ts +16 -0
  248. package/src/presets/standard.ts +163 -0
  249. package/src/safety/CONTEXT.md +23 -0
  250. package/src/safety/__tests__/input-guardrail.test.ts +105 -0
  251. package/src/safety/__tests__/output-guardrail.test.ts +108 -0
  252. package/src/safety/__tests__/sandbox.test.ts +158 -0
  253. package/src/safety/__tests__/tool-guardrail.test.ts +127 -0
  254. package/src/safety/index.ts +5 -0
  255. package/src/safety/input-guardrail.ts +133 -0
  256. package/src/safety/output-guardrail.ts +174 -0
  257. package/src/safety/sandbox.ts +148 -0
  258. package/src/safety/tool-guardrail.ts +176 -0
  259. package/src/safety/types.ts +124 -0
  260. package/src/spec/CONTEXT.md +19 -0
  261. package/src/spec/__tests__/annotation-checker.test.ts +289 -0
  262. package/src/spec/annotation-checker.ts +342 -0
  263. package/src/tools/CONTEXT.md +25 -0
  264. package/src/tools/__tests__/loader.test.ts +252 -0
  265. package/src/tools/__tests__/registry.test.ts +157 -0
  266. package/src/tools/core/__tests__/core.test.ts +122 -0
  267. package/src/tools/core/index.ts +201 -0
  268. package/src/tools/core/package.json +7 -0
  269. package/src/tools/core/pnpm-lock.yaml +232 -0
  270. package/src/tools/definitions/core/code/fingerprint.sh +273 -0
  271. package/src/tools/definitions/core/code/fingerprint.yml +72 -0
  272. package/src/tools/definitions/core/code/parse.yml +68 -0
  273. package/src/tools/definitions/core/code/register-language.sh +475 -0
  274. package/src/tools/definitions/core/code/register-language.yml +74 -0
  275. package/src/tools/definitions/core/docker/build.yml +73 -0
  276. package/src/tools/definitions/core/docker/run.yml +81 -0
  277. package/src/tools/definitions/core/file/copy.yml +88 -0
  278. package/src/tools/definitions/core/file/read.yml +69 -0
  279. package/src/tools/definitions/core/file/write.yml +75 -0
  280. package/src/tools/definitions/core/git/branch.yml +61 -0
  281. package/src/tools/definitions/core/git/cleanup-worktree.yml +50 -0
  282. package/src/tools/definitions/core/git/clone.yml +69 -0
  283. package/src/tools/definitions/core/git/commit.yml +65 -0
  284. package/src/tools/definitions/core/git/push.yml +79 -0
  285. package/src/tools/definitions/core/git/worktree.yml +96 -0
  286. package/src/tools/definitions/core/notification/notify.sh +152 -0
  287. package/src/tools/definitions/core/notification/notify.yml +60 -0
  288. package/src/tools/definitions/core/npm/build.yml +75 -0
  289. package/src/tools/definitions/core/npm/install.yml +58 -0
  290. package/src/tools/definitions/core/npm/test.yml +75 -0
  291. package/src/tools/definitions/core/validation/check-reuse.yml +170 -0
  292. package/src/tools/definitions/core/validation/validate-handlers.yml +118 -0
  293. package/src/tools/definitions/core/validation/validate-readme-stats.yml +155 -0
  294. package/src/tools/definitions/core/validation/validate-yaml-syntax.yml +134 -0
  295. package/src/tools/definitions/ext/browser/browser-automate.sh +255 -0
  296. package/src/tools/definitions/ext/browser/browser-automate.yml +166 -0
  297. package/src/tools/definitions/ext/browser/browser-close.sh +104 -0
  298. package/src/tools/definitions/ext/browser/browser-close.yml +55 -0
  299. package/src/tools/definitions/ext/browser/browser-mcp-debug.sh +682 -0
  300. package/src/tools/definitions/ext/browser/browser-mcp-debug.yml +167 -0
  301. package/src/tools/definitions/ext/browser/browser-start.sh +101 -0
  302. package/src/tools/definitions/ext/browser/browser-start.yml +62 -0
  303. package/src/tools/definitions/registry.json +795 -0
  304. package/src/tools/definitions/std/README.md +350 -0
  305. package/src/tools/definitions/std/analysis/analyze-codebase.yml +72 -0
  306. package/src/tools/definitions/std/analysis/analyze-diff.yml +182 -0
  307. package/src/tools/definitions/std/analysis/analyze-git-diff.yml +70 -0
  308. package/src/tools/definitions/std/analysis/analyze-impact.yml +78 -0
  309. package/src/tools/definitions/std/analysis/analyze-requirements.yml +105 -0
  310. package/src/tools/definitions/std/analysis/brainstorm-options.yml +106 -0
  311. package/src/tools/definitions/std/analysis/build-graph.yml +154 -0
  312. package/src/tools/definitions/std/analysis/clarify-requirements.yml +90 -0
  313. package/src/tools/definitions/std/analysis/detect-context.yml +109 -0
  314. package/src/tools/definitions/std/analysis/detect-layers.yml +125 -0
  315. package/src/tools/definitions/std/analysis/generate-tour.yml +102 -0
  316. package/src/tools/definitions/std/analysis/search-enhance.yml +105 -0
  317. package/src/tools/definitions/std/backlog/add.yml +51 -0
  318. package/src/tools/definitions/std/backlog/decide.yml +39 -0
  319. package/src/tools/definitions/std/backlog/github-sync.yml +161 -0
  320. package/src/tools/definitions/std/backlog/list.yml +53 -0
  321. package/src/tools/definitions/std/backlog/load.yml +46 -0
  322. package/src/tools/definitions/std/backlog/resolve.yml +37 -0
  323. package/src/tools/definitions/std/backlog/update.yml +42 -0
  324. package/src/tools/definitions/std/bugfix/diagnose.yml +68 -0
  325. package/src/tools/definitions/std/bugfix/fix.yml +66 -0
  326. package/src/tools/definitions/std/bugfix/verify.yml +69 -0
  327. package/src/tools/definitions/std/constraint/check-decomposition.yml +103 -0
  328. package/src/tools/definitions/std/constraint/check-feature-list.yml +77 -0
  329. package/src/tools/definitions/std/constraint/check-progress.yml +97 -0
  330. package/src/tools/definitions/std/constraint/generate-report.yml +147 -0
  331. package/src/tools/definitions/std/deploy/commit-push.yml +33 -0
  332. package/src/tools/definitions/std/deploy/deploy-backend.yml +37 -0
  333. package/src/tools/definitions/std/deploy/deploy-frontend.yml +37 -0
  334. package/src/tools/definitions/std/deploy/rollback.yml +148 -0
  335. package/src/tools/definitions/std/design/analyze-architecture-impact.yml +113 -0
  336. package/src/tools/definitions/std/design/design-api.yml +55 -0
  337. package/src/tools/definitions/std/design/design-architecture.yml +97 -0
  338. package/src/tools/definitions/std/design/design-db.yml +81 -0
  339. package/src/tools/definitions/std/design/generate-spec.yml +182 -0
  340. package/src/tools/definitions/std/development/develop-api.yml +85 -0
  341. package/src/tools/definitions/std/development/develop-backend.yml +88 -0
  342. package/src/tools/definitions/std/development/develop-frontend.yml +87 -0
  343. package/src/tools/definitions/std/development/develop-shared-types.yml +74 -0
  344. package/src/tools/definitions/std/development/develop-task.yml +122 -0
  345. package/src/tools/definitions/std/development/develop-tests.yml +76 -0
  346. package/src/tools/definitions/std/development/execute-batch.yml +152 -0
  347. package/src/tools/definitions/std/development/fix-issues.yml +100 -0
  348. package/src/tools/definitions/std/development/implement-task.yml +124 -0
  349. package/src/tools/definitions/std/development/review-fix-cycle.yml +232 -0
  350. package/src/tools/definitions/std/evolution/implement.yml +125 -0
  351. package/src/tools/definitions/std/evolution/prioritize.yml +112 -0
  352. package/src/tools/definitions/std/evolution/report-gap.yml +166 -0
  353. package/src/tools/definitions/std/file/read.yml +21 -0
  354. package/src/tools/definitions/std/governance/aggregate-opinions.sh +201 -0
  355. package/src/tools/definitions/std/governance/aggregate-opinions.yml +79 -0
  356. package/src/tools/definitions/std/governance/audit-task.yml +178 -0
  357. package/src/tools/definitions/std/governance/cast-vote.yml +129 -0
  358. package/src/tools/definitions/std/governance/collect-issues.yml +16 -0
  359. package/src/tools/definitions/std/governance/create-signed-document.yml +23 -0
  360. package/src/tools/definitions/std/governance/create-voting-session.yml +101 -0
  361. package/src/tools/definitions/std/governance/define-stance.sh +243 -0
  362. package/src/tools/definitions/std/governance/define-stance.yml +82 -0
  363. package/src/tools/definitions/std/governance/generate-review-report.yml +23 -0
  364. package/src/tools/definitions/std/governance/impeach.yml +179 -0
  365. package/src/tools/definitions/std/governance/multi-stance-review.yml +154 -0
  366. package/src/tools/definitions/std/governance/prepare-artifact.yml +20 -0
  367. package/src/tools/definitions/std/governance/review-spec-approval.yml +262 -0
  368. package/src/tools/definitions/std/governance/rollback.yml +186 -0
  369. package/src/tools/definitions/std/governance/stance-review.yml +149 -0
  370. package/src/tools/definitions/std/governance/track-effect.yml +199 -0
  371. package/src/tools/definitions/std/governance/vote-tally.yml +144 -0
  372. package/src/tools/definitions/std/patch/execute.yml +51 -0
  373. package/src/tools/definitions/std/planning/generate-tasks.yml +36 -0
  374. package/src/tools/definitions/std/planning/load-tasks.yml +44 -0
  375. package/src/tools/definitions/std/planning/split-batch.yml +481 -0
  376. package/src/tools/definitions/std/planning/split-tasks.yml +359 -0
  377. package/src/tools/definitions/std/planning/update-tasks.yml +51 -0
  378. package/src/tools/definitions/std/planning/validate-tasks.yml +46 -0
  379. package/src/tools/definitions/std/project/decide-next-workflow.yml +38 -0
  380. package/src/tools/definitions/std/project/load-state.yml +31 -0
  381. package/src/tools/definitions/std/project/save-state.yml +32 -0
  382. package/src/tools/definitions/std/quality/check-quality.yml +241 -0
  383. package/src/tools/definitions/std/quality/debug-systematic.yml +163 -0
  384. package/src/tools/definitions/std/quality/handle-feedback.yml +108 -0
  385. package/src/tools/definitions/std/quality/review-code.yml +128 -0
  386. package/src/tools/definitions/std/quality/review-spec.yml +140 -0
  387. package/src/tools/definitions/std/quality/review-task.yml +190 -0
  388. package/src/tools/definitions/std/quality/run-tests.yml +80 -0
  389. package/src/tools/definitions/std/quick/analyze.yml +56 -0
  390. package/src/tools/definitions/std/quick/implement.yml +67 -0
  391. package/src/tools/definitions/std/quick/verify.yml +71 -0
  392. package/src/tools/definitions/std/verification/verify_completion.yml +113 -0
  393. package/src/tools/definitions/std/verification/wait-condition.yml +107 -0
  394. package/src/tools/index.ts +5 -0
  395. package/src/tools/loader.ts +216 -0
  396. package/src/tools/paths.ts +15 -0
  397. package/src/tools/registry.ts +128 -0
  398. package/src/tools/types.ts +46 -0
  399. package/src/types/__tests__/types.test.ts +86 -0
  400. package/src/types/checkpoint.ts +174 -0
  401. package/src/types/constraint.ts +335 -0
  402. package/src/types/cso.ts +37 -0
  403. package/src/types/enforcement.ts +48 -0
  404. package/src/types/index.ts +59 -0
  405. package/src/types/iron-law.ts +50 -0
  406. package/src/types/passes-gate.ts +185 -0
  407. package/src/types/performance.ts +295 -0
  408. package/src/types/project-config.ts +251 -0
  409. package/src/types/session.ts +132 -0
  410. package/src/types/spec.ts +91 -0
  411. package/src/types/trace.ts +228 -0
  412. package/src/utils/detect-source-roots.ts +114 -0
  413. package/src/utils/exec.ts +61 -0
  414. package/src/verification/CONTEXT.md +23 -0
  415. package/src/verification/__tests__/loop.test.ts +303 -0
  416. package/src/verification/__tests__/rules-based.test.ts +240 -0
  417. package/src/verification/index.ts +3 -0
  418. package/src/verification/loop.ts +137 -0
  419. package/src/verification/rules-based.ts +153 -0
  420. package/src/verification/types.ts +81 -0
@@ -0,0 +1,85 @@
1
+ /**
2
+ * harness posteval-plan 命令
3
+ *
4
+ * 调用 Studio PostEval API,验证 plan 文件的 checklist items 是否都有对应的 staged diff。
5
+ * pre-commit hook 使用此命令防止"假装完成"。
6
+ */
7
+
8
+ import chalk from 'chalk';
9
+
10
+ export interface PostEvalPlanOptions {
11
+ planPath: string;
12
+ }
13
+
14
+ const MAX_RETRIES = 3;
15
+ const RETRY_DELAY_MS = 2000;
16
+ const GRACE_PERIOD_MS = parseInt(process.env.POSTEVAL_GRACE_MS || '30000', 10); // 30s total before fallback
17
+
18
+ async function fetchWithRetry(url: string, body: string, retries: number): Promise<Response> {
19
+ let lastError: any;
20
+ for (let i = 0; i < retries; i++) {
21
+ try {
22
+ const controller = new AbortController();
23
+ const timeout = setTimeout(() => controller.abort(), 5000);
24
+ const res = await fetch(url, {
25
+ method: 'POST',
26
+ headers: { 'Content-Type': 'application/json' },
27
+ body,
28
+ signal: controller.signal,
29
+ });
30
+ clearTimeout(timeout);
31
+ return res;
32
+ } catch (error: any) {
33
+ lastError = error;
34
+ if (i < retries - 1) {
35
+ await new Promise(resolve => setTimeout(resolve, RETRY_DELAY_MS * (i + 1))); // exponential backoff
36
+ }
37
+ }
38
+ }
39
+ throw lastError;
40
+ }
41
+
42
+ export async function postevalPlan(options: PostEvalPlanOptions): Promise<void> {
43
+ const apiPort = process.env.API_PORT || '3001';
44
+ const url = `http://localhost:${apiPort}/api/v1/agents/post-eval/plan-coverage`;
45
+
46
+ try {
47
+ const res = await fetchWithRetry(url, JSON.stringify({ planPath: options.planPath }), MAX_RETRIES);
48
+
49
+ if (!res.ok) {
50
+ if (res.status >= 500) {
51
+ // Server error — allow commit with warning (don't block on infrastructure failure)
52
+ console.error(chalk.yellow(`⚠️ PostEval API unavailable (${res.status}), allowing commit with warning`));
53
+ console.error(chalk.yellow(` Plan: ${options.planPath}`));
54
+ process.exit(0);
55
+ }
56
+ console.error(chalk.red(`❌ PostEval API error: ${res.status} ${res.statusText}`));
57
+ process.exit(1);
58
+ }
59
+
60
+ const report = await res.json() as {
61
+ completeness: number;
62
+ matchedAcs: string[];
63
+ missedAcs: string[];
64
+ };
65
+
66
+ const pct = Math.round(report.completeness * 100);
67
+
68
+ if (report.completeness < 1) {
69
+ console.error(chalk.red(`❌ Plan coverage: ${pct}% (${report.matchedAcs.length}/${report.matchedAcs.length + report.missedAcs.length})`));
70
+ if (report.missedAcs.length > 0) {
71
+ console.error(chalk.red('Missed items:'));
72
+ report.missedAcs.forEach((item: string) => console.error(chalk.red(` - ${item}`)));
73
+ }
74
+ process.exit(1);
75
+ }
76
+
77
+ console.log(chalk.green(`✅ Plan coverage: ${pct}%`));
78
+ } catch (error: any) {
79
+ // API unreachable after all retries — allow with warning (don't block commits on infra)
80
+ console.error(chalk.yellow(`⚠️ Studio API unreachable after ${MAX_RETRIES} retries, allowing commit with warning`));
81
+ console.error(chalk.yellow(` Plan: ${options.planPath}`));
82
+ console.error(chalk.yellow(` Error: ${error?.code || error?.message || String(error)}`));
83
+ process.exit(0);
84
+ }
85
+ }
@@ -0,0 +1,159 @@
1
+ /**
2
+ * harness release 命令
3
+ *
4
+ * 完整 npm 发布流水线:tsc → dist 验证 → npm version → git push → npm publish → gh release。
5
+ * 与 studio MCP tool `publishPackage` 共享同一逻辑,但此 CLI 命令不依赖 Studio API 运行。
6
+ * 当 studio API 因 harness 包损坏而无法启动时,此 CLI 命令仍可用。
7
+ */
8
+
9
+ import { execSync } from 'child_process';
10
+ import * as fs from 'fs';
11
+ import * as path from 'path';
12
+ import chalk from 'chalk';
13
+
14
+ export interface ReleaseOptions {
15
+ bumpType?: 'patch' | 'minor' | 'major';
16
+ dryRun?: string;
17
+ }
18
+
19
+ async function run(cmd: string, cwd: string, timeout = 60_000): Promise<{ stdout: string; stderr: string }> {
20
+ try {
21
+ const stdout = execSync(cmd, { cwd, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], timeout });
22
+ return { stdout: stdout.trim(), stderr: '' };
23
+ } catch (e: any) {
24
+ const stderr = typeof e.stderr === 'string' ? e.stderr : e.stderr?.toString() || '';
25
+ const stdout = typeof e.stdout === 'string' ? e.stdout : e.stdout?.toString() || '';
26
+ return { stdout: stdout.trim(), stderr: stderr.trim() || e.message || String(e) };
27
+ }
28
+ }
29
+
30
+ export async function release(options: ReleaseOptions): Promise<void> {
31
+ const pkgPath = process.cwd();
32
+ const bumpType = options.bumpType || 'patch';
33
+ const dryRun = options.dryRun === 'true';
34
+
35
+ // ── 1. Verify package ──
36
+ const pkgJsonPath = path.join(pkgPath, 'package.json');
37
+ if (!fs.existsSync(pkgJsonPath)) {
38
+ console.error(chalk.red(`❌ Not a package: ${pkgPath}`));
39
+ process.exit(1);
40
+ }
41
+ const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
42
+ const pkgName = pkgJson.name;
43
+ const oldVersion = pkgJson.version;
44
+ console.log(chalk.cyan(`📦 ${pkgName}@${oldVersion}`));
45
+ console.log(chalk.cyan(` bump: ${bumpType}${dryRun ? ' (dry-run)' : ''}`));
46
+
47
+ // ── 2. Check clean working tree ──
48
+ const stat = await run('git status --porcelain -uno', pkgPath);
49
+ if (stat.stdout.length > 0) {
50
+ console.error(chalk.red('❌ Uncommitted changes. Commit or stash before releasing.'));
51
+ console.error(chalk.gray(stat.stdout.slice(0, 500)));
52
+ process.exit(1);
53
+ }
54
+ console.log(chalk.green('✅ git: clean'));
55
+
56
+ // ── 3. tsc build ──
57
+ console.log(chalk.cyan('🔨 Building...'));
58
+ const build = await run('npx tsc', pkgPath, 60_000);
59
+ if (build.stderr && !build.stdout) {
60
+ console.error(chalk.red('❌ tsc failed:'), build.stderr.slice(0, 800));
61
+ process.exit(1);
62
+ }
63
+ console.log(chalk.green('✅ tsc: built'));
64
+
65
+ // ── 4. Verify dist ──
66
+ const criticalFiles = [
67
+ 'dist/index.js',
68
+ 'dist/knowledge/index.js',
69
+ 'dist/knowledge/store.js',
70
+ 'dist/knowledge/ingest.js',
71
+ 'dist/knowledge/query.js',
72
+ 'dist/knowledge/lifecycle.js',
73
+ 'dist/knowledge/lint.js',
74
+ 'dist/knowledge/types.js',
75
+ 'dist/knowledge/import.js',
76
+ 'dist/knowledge/reference-tracker.js',
77
+ 'dist/knowledge/lifecycle-hooks.js',
78
+ 'dist/knowledge/doctor.js',
79
+ 'dist/core/constraints/prompt-injection.js',
80
+ ];
81
+ const missing = criticalFiles.filter(f => !fs.existsSync(path.join(pkgPath, f)));
82
+ if (missing.length > 0) {
83
+ console.error(chalk.red(`❌ dist missing critical files: ${missing.join(', ')}`));
84
+ process.exit(1);
85
+ }
86
+ console.log(chalk.green('✅ dist: verified'));
87
+
88
+ if (dryRun) {
89
+ const [major, minor, patch] = oldVersion.split('.').map(Number);
90
+ let newVer: string;
91
+ if (bumpType === 'major') newVer = `${major + 1}.0.0`;
92
+ else if (bumpType === 'minor') newVer = `${major}.${minor + 1}.0`;
93
+ else newVer = `${major}.${minor}.${patch + 1}`;
94
+ console.log(chalk.yellow(`🏁 Dry-run complete. Would publish: ${pkgName}@${newVer}`));
95
+ process.exit(0);
96
+ }
97
+
98
+ // ── 5. Bump version (npm version creates git commit + tag atomically,
99
+ // including package-lock.json — no desync possible) ──
100
+ console.log(chalk.cyan('🔢 Bumping version...'));
101
+ const bump = await run(`npm version ${bumpType} -m "release: %s"`, pkgPath);
102
+ if (bump.stderr && !bump.stdout) {
103
+ console.error(chalk.red('❌ npm version failed:'), bump.stderr);
104
+ process.exit(1);
105
+ }
106
+ const newVersion = bump.stdout.trim().replace(/^v/, '');
107
+ const tag = `v${newVersion}`;
108
+ console.log(chalk.green(`✅ version: ${oldVersion} → ${newVersion} (committed + tagged)`));
109
+
110
+ // ── 7. Push ──
111
+ console.log(chalk.cyan('⬆️ Pushing...'));
112
+ const branch = await run('git rev-parse --abbrev-ref HEAD', pkgPath);
113
+ const push = await run(`git push origin ${branch.stdout}`, pkgPath, 30_000);
114
+ if (push.stderr && push.stderr.includes('error')) {
115
+ console.error(chalk.red('❌ git push failed:'), push.stderr.slice(0, 500));
116
+ process.exit(1);
117
+ }
118
+ await run(`git push origin ${tag}`, pkgPath, 30_000);
119
+ console.log(chalk.green('✅ git: pushed'));
120
+
121
+ // ── 8. npm publish ──
122
+ // Switch to npmjs.org for publishing (npmmirror is read-only mirror)
123
+ const origRegistry = await run('npm config get registry', pkgPath);
124
+ await run('npm config set registry https://registry.npmjs.org/', pkgPath);
125
+ console.log(chalk.cyan('📤 Publishing to npm...'));
126
+ // npm publish to npmjs.org (the write registry — npmmirror is read-only)
127
+ const pub = await run('npm publish --registry https://registry.npmjs.org/', pkgPath, 180_000);
128
+ // Restore original registry
129
+ await run(`npm config set registry ${origRegistry.stdout}`, pkgPath);
130
+ // Don't string-match npm output — verify by querying the registry
131
+ const verify = await run(`npm view ${pkgName} version --registry https://registry.npmjs.org/`, pkgPath);
132
+ if (verify.stdout.trim() === newVersion) {
133
+ console.log(chalk.green(`✅ npm: published ${pkgName}@${newVersion}`));
134
+ } else {
135
+ console.log(chalk.red(`❌ npm publish verification failed. Expected ${newVersion}, registry has ${verify.stdout.trim() || '???'}`));
136
+ process.exit(1);
137
+ }
138
+
139
+ // ── 9. GitHub Release ──
140
+ console.log(chalk.cyan('🐙 Creating GitHub Release...'));
141
+ const gh = await run(`gh release create ${tag} --generate-notes`, pkgPath, 30_000);
142
+ if (gh.stderr && gh.stderr.includes('already exists')) {
143
+ console.log(chalk.yellow(`⚠️ gh: release ${tag} already exists`));
144
+ } else if (gh.stderr) {
145
+ console.log(chalk.yellow(`⚠️ gh: release may have failed (non-fatal): ${gh.stderr.slice(0, 200)}`));
146
+ } else {
147
+ // Derive repo URL from git remote
148
+ let repoUrl = '';
149
+ try {
150
+ const remoteUrl = execSync('git remote get-url origin', { cwd: pkgPath, encoding: 'utf-8', stdio: 'pipe', timeout: 5_000 }).trim();
151
+ const m = remoteUrl.match(/github\.com[:/]([^/]+)\/([^/\s.]+?)(?:\.git)?$/);
152
+ if (m) repoUrl = `https://github.com/${m[1]}/${m[2]}/releases/tag/${tag}`;
153
+ } catch { /* no remote */ }
154
+ console.log(chalk.green(`✅ GitHub Release: ${repoUrl || tag}`));
155
+ }
156
+
157
+ console.log(chalk.green(`\n🎉 Released ${pkgName}@${newVersion}`));
158
+ console.log(chalk.gray(` npm: https://www.npmjs.com/package/${pkgName}/v/${newVersion}`));
159
+ }
@@ -0,0 +1,198 @@
1
+ /**
2
+ * harness report 命令
3
+ *
4
+ * 生成检查报告(接入真实约束检查数据)
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+ import * as fs from 'fs/promises';
9
+ import { ConstraintChecker } from '../../core/constraints/checker';
10
+ import { IRON_LAWS, GUIDELINES, TIPS } from '../../core/constraints/definitions';
11
+ import { executeWithCollect } from '../../failure/constraint-handler';
12
+ import type { ConstraintContext } from '../../types/constraint';
13
+
14
+ export interface ReportOptions {
15
+ /** 输出文件路径 */
16
+ output?: string;
17
+ /** 输出格式 */
18
+ format: 'json' | 'markdown' | 'html';
19
+ /** 项目路径 */
20
+ projectPath?: string;
21
+ }
22
+
23
+ interface ReportData {
24
+ timestamp: string;
25
+ projectPath: string;
26
+ constraints: {
27
+ total: number;
28
+ ironLaws: number;
29
+ guidelines: number;
30
+ tips: number;
31
+ passed: number;
32
+ failed: number;
33
+ warnings: number;
34
+ violations: Array<{
35
+ id: string;
36
+ level: string;
37
+ message: string;
38
+ }>;
39
+ };
40
+ }
41
+
42
+ /**
43
+ * 生成检查报告
44
+ */
45
+ export async function report(options: ReportOptions): Promise<void> {
46
+ console.log(chalk.blue('📊 生成检查报告...'));
47
+
48
+ const projectPath = options.projectPath || process.cwd();
49
+ const checker = ConstraintChecker.getInstance();
50
+
51
+ const allConstraints = { ...IRON_LAWS, ...GUIDELINES, ...TIPS };
52
+ const totalConstraints = Object.keys(allConstraints).length;
53
+
54
+ const context: ConstraintContext = {
55
+ operation: 'file_modification',
56
+ projectPath,
57
+ };
58
+
59
+ // S4: 使用 COLLECT 策略 — Iron Law 违规不抛异常,收集到结果中
60
+ const { checkResult } = await executeWithCollect(() =>
61
+ checker.checkConstraints(context)
62
+ );
63
+ // COLLECT 策略始终返回 checkResult
64
+ const result = checkResult!;
65
+
66
+ const failedIronLaws = result.ironLaws.filter(r => !r.satisfied);
67
+ const failedGuidelines = result.guidelines.filter(r => !r.satisfied);
68
+
69
+ const violations = [...failedIronLaws, ...failedGuidelines].map(r => ({
70
+ id: r.id,
71
+ level: r.level,
72
+ message: r.message || '',
73
+ }));
74
+
75
+ const reportData: ReportData = {
76
+ timestamp: new Date().toISOString(),
77
+ projectPath,
78
+ constraints: {
79
+ total: totalConstraints,
80
+ ironLaws: Object.keys(IRON_LAWS).length,
81
+ guidelines: Object.keys(GUIDELINES).length,
82
+ tips: Object.keys(TIPS).length,
83
+ passed: result.passed ? totalConstraints : totalConstraints - violations.length,
84
+ failed: failedIronLaws.length,
85
+ warnings: failedGuidelines.length,
86
+ violations,
87
+ },
88
+ };
89
+
90
+ let content: string;
91
+
92
+ switch (options.format) {
93
+ case 'json':
94
+ content = JSON.stringify(reportData, null, 2);
95
+ break;
96
+ case 'markdown':
97
+ content = generateMarkdownReport(reportData);
98
+ break;
99
+ case 'html':
100
+ content = generateHtmlReport(reportData);
101
+ break;
102
+ default:
103
+ content = JSON.stringify(reportData, null, 2);
104
+ }
105
+
106
+ if (options.output) {
107
+ await fs.writeFile(options.output, content, 'utf-8');
108
+ console.log(chalk.green(`✅ 报告已保存到: ${options.output}`));
109
+ } else {
110
+ console.log(content);
111
+ }
112
+ }
113
+
114
+ function generateMarkdownReport(data: ReportData): string {
115
+ const lines: string[] = [
116
+ `# Harness 检查报告`,
117
+ ``,
118
+ `> 生成时间: ${data.timestamp}`,
119
+ `> 项目路径: ${data.projectPath}`,
120
+ ``,
121
+ `---`,
122
+ ``,
123
+ `## 约束检查`,
124
+ ``,
125
+ `| 指标 | 数值 |`,
126
+ `|------|------|`,
127
+ `| 总约束 | ${data.constraints.total} |`,
128
+ `| Iron Laws | ${data.constraints.ironLaws} |`,
129
+ `| Guidelines | ${data.constraints.guidelines} |`,
130
+ `| Tips | ${data.constraints.tips} |`,
131
+ `| 通过 | ${data.constraints.passed} |`,
132
+ `| 失败 (error) | ${data.constraints.failed} |`,
133
+ `| 警告 (warning) | ${data.constraints.warnings} |`,
134
+ ``,
135
+ ];
136
+
137
+ if (data.constraints.violations.length > 0) {
138
+ lines.push(`### 违规项`, ``);
139
+ data.constraints.violations.forEach(v => {
140
+ lines.push(`- **${v.id}** (${v.level}): ${v.message}`);
141
+ });
142
+ lines.push(``);
143
+ }
144
+
145
+ lines.push(`---`, `*报告由 @dommaker/harness 生成*`, ``);
146
+ return lines.join('\n');
147
+ }
148
+
149
+ function generateHtmlReport(data: ReportData): string {
150
+ const violationsHtml = data.constraints.violations.length > 0
151
+ ? `<h3>违规项</h3><ul>${data.constraints.violations.map(v =>
152
+ `<li><strong>${v.id}</strong> (${v.level}): ${v.message}</li>`
153
+ ).join('')}</ul>`
154
+ : '';
155
+
156
+ return `<!DOCTYPE html>
157
+ <html lang="zh-CN">
158
+ <head>
159
+ <meta charset="UTF-8">
160
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
161
+ <title>Harness 检查报告</title>
162
+ <style>
163
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
164
+ h1 { color: #333; border-bottom: 2px solid #4CAF50; padding-bottom: 10px; }
165
+ h2 { color: #555; margin-top: 30px; }
166
+ table { width: 100%; border-collapse: collapse; margin: 15px 0; }
167
+ th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
168
+ th { background-color: #4CAF50; color: white; }
169
+ tr:nth-child(even) { background-color: #f2f2f2; }
170
+ .passed { color: #4CAF50; }
171
+ .failed { color: #f44336; }
172
+ .meta { color: #666; font-size: 0.9em; margin-bottom: 20px; }
173
+ </style>
174
+ </head>
175
+ <body>
176
+ <h1>Harness 检查报告</h1>
177
+ <p class="meta">生成时间: ${data.timestamp}<br>项目路径: ${data.projectPath}</p>
178
+
179
+ <h2>约束检查</h2>
180
+ <table>
181
+ <tr><th>指标</th><th>数值</th></tr>
182
+ <tr><td>总约束</td><td>${data.constraints.total}</td></tr>
183
+ <tr><td>Iron Laws</td><td>${data.constraints.ironLaws}</td></tr>
184
+ <tr><td>Guidelines</td><td>${data.constraints.guidelines}</td></tr>
185
+ <tr><td>Tips</td><td>${data.constraints.tips}</td></tr>
186
+ <tr><td>通过</td><td class="passed">${data.constraints.passed}</td></tr>
187
+ <tr><td>失败</td><td class="failed">${data.constraints.failed}</td></tr>
188
+ <tr><td>警告</td><td>${data.constraints.warnings}</td></tr>
189
+ </table>
190
+
191
+ ${violationsHtml}
192
+
193
+ <footer style="margin-top: 40px; color: #999; text-align: center;">
194
+ 报告由 @dommaker/harness 生成
195
+ </footer>
196
+ </body>
197
+ </html>`;
198
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * harness review 命令
3
+ *
4
+ * 代码审查门控,检查审查状态
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+ import { execAsync } from '../../utils/exec';
9
+ import { ReviewGate } from '../../gates/review';
10
+
11
+ export interface ReviewOptions {
12
+ /** 项目路径 */
13
+ projectPath?: string;
14
+ /** 最少审查人数 */
15
+ minReviewers?: number;
16
+ /** 是否要求审批 */
17
+ requireApproval?: boolean;
18
+ /** 是否阻止变更请求 */
19
+ blockOnChangesRequested?: boolean;
20
+ /** 允许的审查者(逗号分隔) */
21
+ allowedReviewers?: string;
22
+ }
23
+
24
+ /**
25
+ * 执行审查门控
26
+ */
27
+ export async function review(options: ReviewOptions): Promise<void> {
28
+ console.log(chalk.blue('👀 代码审查门控检查...'));
29
+
30
+ const projectPath = options.projectPath || process.cwd();
31
+
32
+ const gate = new ReviewGate({
33
+ minReviewers: options.minReviewers ?? 1,
34
+ requireApproval: options.requireApproval ?? true,
35
+ blockOnChangesRequested: options.blockOnChangesRequested ?? true,
36
+ allowedReviewers: options.allowedReviewers
37
+ ? options.allowedReviewers.split(',').map(s => s.trim()).filter(Boolean)
38
+ : [],
39
+ });
40
+
41
+ try {
42
+ const { stdout: branch } = await execAsync('git rev-parse --abbrev-ref HEAD', { cwd: projectPath });
43
+ console.log(chalk.gray(`当前分支: ${branch.trim()}`));
44
+
45
+ const result = await gate.check({ projectPath, projectId: 'default' });
46
+
47
+ console.log();
48
+ if (result.passed) {
49
+ console.log(chalk.green('✅ 代码审查门控检查通过'));
50
+ if (result.details) {
51
+ console.log(chalk.gray(` 审批: ${result.details.approvals ?? 0}, 变更请求: ${result.details.changesRequested ?? 0}`));
52
+ }
53
+ } else {
54
+ console.log(chalk.red('❌ 代码审查门控检查失败'));
55
+ console.log(chalk.red(` ${result.message}`));
56
+ if (result.details?.suggestion) {
57
+ console.log(chalk.gray(` ${result.details.suggestion}`));
58
+ }
59
+ process.exit(1);
60
+ }
61
+ } catch (error: any) {
62
+ console.log();
63
+ console.log(chalk.red('❌ 代码审查门控检查出错'));
64
+ console.log(chalk.red(` ${error.message}`));
65
+
66
+ if (error.message.includes('not a git repository')) {
67
+ console.log();
68
+ console.log(chalk.gray('提示: 此命令需要在 Git 仓库中运行'));
69
+ }
70
+
71
+ process.exit(1);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * 显示审查状态详情
77
+ */
78
+ export async function reviewStatus(options: ReviewOptions): Promise<void> {
79
+ console.log(chalk.blue('👀 代码审查状态...\n'));
80
+
81
+ const projectPath = options.projectPath || process.cwd();
82
+
83
+ try {
84
+ const { stdout: branch } = await execAsync('git rev-parse --abbrev-ref HEAD', { cwd: projectPath });
85
+ console.log(chalk.gray(`当前分支: ${branch.trim()}`));
86
+
87
+ try {
88
+ const { stdout: prInfo } = await execAsync('gh pr view --json number,title,state,reviewDecision,reviews', {
89
+ cwd: projectPath,
90
+ });
91
+ const pr = JSON.parse(prInfo);
92
+
93
+ console.log();
94
+ console.log(chalk.cyan(`PR #${pr.number}: ${pr.title}`));
95
+ console.log(chalk.gray(`状态: ${pr.state}`));
96
+
97
+ if (pr.reviewDecision) {
98
+ const decisionColor = pr.reviewDecision === 'APPROVED' ? chalk.green : chalk.yellow;
99
+ console.log(decisionColor(`审查决策: ${pr.reviewDecision}`));
100
+ }
101
+
102
+ if (pr.reviews && pr.reviews.length > 0) {
103
+ console.log();
104
+ console.log(chalk.gray('审查历史:'));
105
+ pr.reviews.forEach((r: any) => {
106
+ const statusColor = r.state === 'APPROVED' ? chalk.green :
107
+ r.state === 'CHANGES_REQUESTED' ? chalk.red : chalk.gray;
108
+ console.log(statusColor(` - ${r.author?.login || 'unknown'}: ${r.state}`));
109
+ });
110
+ }
111
+ } catch {
112
+ console.log(chalk.yellow('\n⚠️ 未找到关联的 PR'));
113
+ console.log(chalk.gray(' 使用 gh pr create 创建 PR'));
114
+ }
115
+ } catch (error: any) {
116
+ console.log(chalk.red(`❌ 获取审查状态失败: ${error.message}`));
117
+ }
118
+ }
@@ -0,0 +1,122 @@
1
+ /**
2
+ * harness security 命令
3
+ *
4
+ * 安全门控,检查安全漏洞
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+ import { SecurityGate } from '../../gates/security';
9
+
10
+ export interface SecurityOptions {
11
+ /** 项目路径 */
12
+ projectPath?: string;
13
+ /** 严重性阈值 (low/moderate/high/critical) */
14
+ severity?: 'low' | 'moderate' | 'high' | 'critical';
15
+ /** 是否忽略警告 */
16
+ ignoreWarnings?: boolean;
17
+ /** 是否忽略开发依赖 */
18
+ ignoreDevDeps?: boolean;
19
+ /** 自定义扫描命令 */
20
+ scanCommand?: string;
21
+ }
22
+
23
+ /**
24
+ * 执行安全门控
25
+ */
26
+ export async function security(options: SecurityOptions): Promise<void> {
27
+ console.log(chalk.blue('🔒 安全门控检查...'));
28
+
29
+ try {
30
+ const projectPath = options.projectPath || process.cwd();
31
+
32
+ const gate = new SecurityGate({
33
+ severityThreshold: options.severity || 'high',
34
+ scanCommand: options.scanCommand,
35
+ ignoreWarnings: options.ignoreWarnings,
36
+ ignoreDevDependencies: options.ignoreDevDeps,
37
+ });
38
+
39
+ const result = await gate.scan({ projectPath, projectId: 'default' });
40
+
41
+ console.log();
42
+ if (result.passed) {
43
+ console.log(chalk.green('✅ 安全门控检查通过'));
44
+ if (result.details) {
45
+ console.log(chalk.gray(` critical: ${result.details.critical}, high: ${result.details.high}, moderate: ${result.details.moderate}, low: ${result.details.low}`));
46
+ }
47
+ } else {
48
+ console.log(chalk.red('❌ 安全门控检查失败'));
49
+ console.log(chalk.red(` ${result.message}`));
50
+ if (result.details?.vulnerabilities) {
51
+ console.log();
52
+ (result.details.vulnerabilities as Array<{ name: string; severity: string; via: string }>).forEach((v, i) => {
53
+ const severityColor = getSeverityColor(v.severity);
54
+ console.log(severityColor(` ${i + 1}. [${v.severity.toUpperCase()}] ${v.name}`));
55
+ console.log(chalk.gray(` via: ${v.via}`));
56
+ });
57
+ }
58
+ console.log(chalk.gray('\n 运行 harness security audit 查看详情'));
59
+ process.exit(1);
60
+ }
61
+ } catch (error) {
62
+ console.log();
63
+ console.log(chalk.red(`❌ 安全检查异常: ${error instanceof Error ? error.message : String(error)}`));
64
+ process.exit(1);
65
+ }
66
+ }
67
+
68
+ /**
69
+ * 获取严重性颜色
70
+ */
71
+ function getSeverityColor(severity: string): (text: string) => string {
72
+ switch (severity.toLowerCase()) {
73
+ case 'critical':
74
+ return chalk.red.bold;
75
+ case 'high':
76
+ return chalk.red;
77
+ case 'moderate':
78
+ return chalk.yellow;
79
+ case 'low':
80
+ return chalk.blue;
81
+ default:
82
+ return chalk.gray;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * 运行安全审计详情
88
+ */
89
+ export async function auditDetails(options: SecurityOptions): Promise<void> {
90
+ console.log(chalk.blue('🔒 安全审计详情...\n'));
91
+
92
+ try {
93
+ const projectPath = options.projectPath || process.cwd();
94
+
95
+ const gate = new SecurityGate({
96
+ severityThreshold: options.severity || 'low',
97
+ scanCommand: options.scanCommand,
98
+ });
99
+
100
+ const result = await gate.scan({ projectPath, projectId: 'default' });
101
+
102
+ if (result.passed && !result.details?.total) {
103
+ console.log(chalk.green('✅ 未发现安全漏洞'));
104
+ return;
105
+ }
106
+
107
+ const details = result.details as any;
108
+ if (details?.vulnerabilities?.length > 0) {
109
+ console.log(chalk.yellow(`发现 ${details.total} 个漏洞:\n`));
110
+ for (const v of details.vulnerabilities) {
111
+ const severityColor = getSeverityColor(v.severity);
112
+ console.log(severityColor(`[${v.severity.toUpperCase()}] ${v.name}`));
113
+ console.log(chalk.gray(` via: ${v.via}`));
114
+ console.log();
115
+ }
116
+ }
117
+ } catch (error) {
118
+ console.log();
119
+ console.log(chalk.red(`❌ 安全审计异常: ${error instanceof Error ? error.message : String(error)}`));
120
+ process.exit(1);
121
+ }
122
+ }