@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
package/CHANGELOG.md ADDED
@@ -0,0 +1,169 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6
+
7
+ ## [0.13.0] - 2026-05-26
8
+
9
+ ### Breaking
10
+ - **prompt-injection 迁移**: `formatConstraintsForPrompt()` + `AgentRole` + `ROLE_TRIGGERS` 迁至 `@dommaker/studio-shared`。harness 保留 deprecated re-export。
11
+ - **`buildConstraintPrompt()` 移除**: 孤儿函数从未消费,且截断 80 字符。已删除。
12
+ - **死亡代码清理**: `changelog_freshness` 孤儿约束、`changelog_missing` DiffType、`sync-docs --changelog`、`auto_append` config。
13
+
14
+ ### Added
15
+ - **`detectSourceRoots()`**: 统一源码目录发现。支持 monorepo (packages/*, apps/*) 和单 repo (src/, lib/)。替代 5 种分散硬编码。
16
+ - **`harness constraints --json`**: 约束元数据导出(version, hash, counts, textSize)。
17
+ - **`harness init` → CLAUDE.md**: 写入标记段(HARNESS_CONSTRAINTS),含约束列表和版本号。
18
+ - **`module_creation` 触发**: `detectTrigger()` 识别新目录文件变更。
19
+ - **11 条约束补 `promptInjection`**: `no_code_without_test` 等从不可见变为 CLAUDE.md + Agent prompt 可见。
20
+
21
+ ### Changed
22
+ - **内置 Freshness 泛化**: 10 项 harness 特化 → 2 项通用(CONTEXT.md + CHANGELOG 版本)。
23
+ - **`findSourceFiles` 跳过 `index.ts`**: 与 `scanSourceModules` 一致。
24
+ - **管线运行时去重**: CLAUDE.md 已有约束段时注入引用而非全量文本。
25
+ - **预设 `required_dirs` 自动发现**: 不硬编码 `['src']`。
26
+
27
+ ### Fixed
28
+ - `@jest/globals` 缺失 → 安装后 119/119 测试通过。
29
+ - monorepo 工程 `harness init` 后全部检测盲过。
30
+ - `index.ts` 导致 `docs_freshness` 误报。
31
+
32
+ ## [0.12.2] - 2026-05-19
33
+
34
+ ### Added
35
+ - **fix_the_problem_not_the_gate guideline**: 质量门阻断时修复代码,不修复门禁
36
+
37
+ ## [0.12.1] - 2026-05-19
38
+
39
+ ### Added
40
+ - **first_principles_first guideline**:第一性优先分析方法论。injectPrompt=true。
41
+ - **5 behavioral guidelines**:surgical_changes_only / no_model_for_deterministic / no_conflict_blending / read_before_write / follow_conventions。全部 injectPrompt=true。
42
+ - **2 增强 promptInjection**:no_performative_agreement / simplest_solution_first 补充 prompt 注入文本。
43
+ - **interceptor 收敛**:无 executor 时 fallback 到 constraint.check(ctx)。
44
+
45
+ ### Changed
46
+ - **docs_freshness 升级为 iron_law**:guideline → iron_law (blocking)。
47
+ - **CONTEXT.md 删除**:17 个文件。目录描述集中在 CLAUDE.md Key Subsystems 表。
48
+ - 约束总数:13 Iron Laws + 13 Guidelines + 2 Tips = 28 条。
49
+ - promptInjection 优化:357→80 tokens (75% 缩减)。
50
+ - **约束生命周期修正**:退化基于拦截率(≥10 次检查 + 拦截率 < 30%),不基于日历时间。
51
+
52
+ ## [0.11.0] - 2026-05-03
53
+
54
+ ### Added
55
+ - **6 条新约束**:must_use_worktree / no_fuzzy_completion_claim / no_performative_agreement / two_stage_review_required(Iron Law)+ no_excuse_patterns / yagni_check(Guideline)
56
+ - **meeting_decision_check trigger**:会议决策质量检查
57
+ - **buildConstraintPrompt()**:收集约束 promptInjection 格式化为 Agent system prompt 片段
58
+ - **knowledge/failure CLI**:harness knowledge / harness failure 命令
59
+ - **sync-docs 命令**:文档新鲜度检查 + JSON 输出
60
+
61
+ ### Changed
62
+ - 约束总数:8 Iron Laws → 12,13 Guidelines → 15,共 29 条
63
+ - AI 治理简化:移除冗余 hook/apply,harness 只检测不修复
64
+ - interceptor 修复 + 覆盖率 85.4% + JSDoc
65
+ - `autoEvolve()` 纯计算 API + `evolution/auto-evolve.ts` 新模块
66
+ - `checkConstraints()` 新增 `onTrace` 回调参数
67
+
68
+ ## [0.9.0] - 2026-05-01
69
+
70
+ ### Added
71
+
72
+ #### Phase 1: 知识引擎核心
73
+ - KnowledgeStore: 知识条目 CRUD + 结构化存储
74
+ - KnowledgeQuery: 语义搜索 + 类型/标签过滤
75
+ - ReferenceTracker: 知识引用关系图谱
76
+ - KnowledgeLinter: 知识质量检查 (完整性/一致性/时效性)
77
+
78
+ #### Phase 2: 上下文管理
79
+ - TokenBudget: 多级 token 预算分配 (system/user/tool/reserve)
80
+ - SessionCompaction: 会话压缩策略 (摘要/截断/滑动窗口)
81
+ - AgentLifecycle: Agent 状态机 (init→running→paused→completed→failed)
82
+
83
+ #### Phase 3: 安全护栏
84
+ - InputGuardrail: 输入内容安全检查 (注入检测/敏感信息/格式校验)
85
+ - OutputGuardrail: 输出内容安全检查 (泄露检测/有害内容/格式合规)
86
+ - ToolGuardrail: 工具调用安全检查 (权限验证/参数校验/速率限制)
87
+ - Sandbox: 沙箱执行环境管理 (级别 L1-L4/资源限制/隔离策略)
88
+
89
+ #### Phase 4: 知识引擎集成
90
+ - KnowledgeService: 统一入口 (Store + Query + Tracker + Linter)
91
+ - 知识生命周期: draft → candidate → validated → canonical → archived
92
+ - 跨项目知识迁移: 模式识别 + 最佳实践提炼
93
+
94
+ #### Phase 5: 约束重构
95
+ - ConstraintContext 扩展: 新增 isExternalDependency/isExplicitInstruction/isEmergencyFix/isExistingDesign
96
+ - 自定义约束配置: .harness/config.yml 支持 extend_exceptions
97
+ - 约束进化提案: 基于 trace 分析自动生成优化建议
98
+
99
+ #### Phase 6: 冷启动
100
+ - progressive-loader.ts: 渐进式加载 + worker pool 并发
101
+ - cross-project-checker.ts: 跨项目依赖检查 (异步化)
102
+ - project-config-loader.ts: 项目配置加载 + 约束合并
103
+
104
+ ### Changed
105
+ - SafetyService/ContextService/AgentService 单例导出
106
+ - KnowledgeService 单例导出
107
+ - CLI 新增 harness flow --auto-apply 自动应用低风险提案
108
+
109
+ ## [0.8.4] - 2026-05-01
110
+
111
+ ### Changed
112
+
113
+ #### 重复代码消除
114
+ - 统一 `execAsync` 到 `utils/exec`:15 个文件的重复定义合并为单一来源
115
+ - 新增 `normalizeTriggers()` 泛型工具函数,消除 10+ 处 `Array.isArray` 重复模式
116
+ - 新增 `delay()` 公共函数,替换 3 处私有 `sleep/delay` 方法
117
+
118
+ #### 逻辑简化
119
+ - `checker.ts`:60 行 `switch` 例外匹配 → `EXCEPTION_FIELD_MAP` 映射表 + `some()` 一行
120
+ - `checker.ts`:3 个近似循环 → 提取 `matchesTrigger()` + `recordTrace()` 公共方法
121
+ - `interceptor.ts`:触发器规范化 → 复用 `normalizeTriggers`
122
+ - `trace-analyzer.ts` / `performance-analyzer.ts`:5 次/3 次遍历统计 → 单次遍历
123
+ - `failure/recorder.ts`:`getByType`/`getByLevel` 重复过滤 → 提取 `getFiltered()`
124
+
125
+ #### 健壮性修复
126
+ - 修复 `checker.ts` 中 Guidelines 循环直接引用 `GUIDELINES` 常量的 bug(未使用自定义约束配置)
127
+ - 修复 `project-config-loader.ts` 中 `mergeConstraints()` 的 for 循环缩进错误(方法体脱离类作用域)
128
+ - 修复 `progressive-loader.ts` 中 `delay` 参数名与导入函数冲突
129
+ - 补充 `ConstraintContext` 缺失字段:`isExternalDependency`、`isExplicitInstruction`、`isEmergencyFix`、`isExistingDesign`
130
+
131
+ #### 性能优化
132
+ - `cross-project-checker.ts`:`execSync`(阻塞式)→ 异步 `runCommand`
133
+ - `progressive-loader.ts` `processBatch`:并发结果顺序不保证 → worker pool 模式保证输入顺序
134
+
135
+ #### 代码规范
136
+ - `cli/commands/status.ts`:`any` 类型 → `TraceSummary` / `TraceAnomaly`
137
+ - `cross-project-checker.test.ts`:更新 mock 从 `child_process` → `utils/exec`
138
+ - 合并 10+ 处分散的 `import { exec } + promisify(exec)` 为统一导入
139
+
140
+ > 净减少约 157 行代码,零编译错误,零测试回归
141
+
142
+ ---
143
+
144
+ ## Recent Commits
145
+
146
+ - feat: add command CLI for blacklist checking (2026-04-29 23:24:07 +0800)
147
+ - feat: add CommandGate for command blacklist (SEC-006) (2026-04-29 23:09:44 +0800)
148
+ - fix: remove deprecated command tests (propose, diagnose, traces) (2026-04-29 01:10:46 +0800)
149
+ - chore: release v0.8.0 (2026-04-28 23:41:32 +0800)
150
+ - docs: decouple Trace section from business logic (2026-04-28 23:39:12 +0800)
151
+ - chore: remove docs and specs directories (moved to .gitignore) (2026-04-28 23:37:35 +0800)
152
+ - chore: ignore docs directory (2026-04-28 23:36:39 +0800)
153
+ - docs: remove deprecated note from README (2026-04-28 23:34:30 +0800)
154
+ - refactor(cli): remove deprecated commands (traces, diagnose, propose) (2026-04-28 23:32:26 +0800)
155
+ - docs: sync CLI commands to README (2026-04-28 23:23:47 +0800)
156
+ - feat(cli): add 5 gate commands - acceptance, performance, security, contract, review (2026-04-28 23:04:33 +0800)
157
+ - chore: ignore specs directory in gitignore (2026-04-28 22:56:59 +0800)
158
+ - chore: ignore specs/templates 目录 (2026-04-28 22:52:51 +0800)
159
+ - feat: 新增覆盖率约束机制 (2026-04-28 22:50:15 +0800)
160
+ - test: 覆盖率达标 85.43%! (2026-04-28 22:39:48 +0800)
161
+ - test: 覆盖率提升至 84.8% (2026-04-28 22:34:31 +0800)
162
+ - test: 覆盖率提升至 83.93% (2026-04-28 22:29:51 +0800)
163
+ - chore: 清理临时测试文件 (2026-04-28 22:21:01 +0800)
164
+ - test: 覆盖率提升至 84.17% (2026-04-28 22:20:54 +0800)
165
+ - init (2026-04-28 22:11:12 +0800)
166
+
167
+ ---
168
+
169
+ > 自动生成于 2026-04-30
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Harness Knowledge Capture Hook
4
+ *
5
+ * Runs as an afterTurn hook in Claude Code.
6
+ * Detects deep analysis (≥3 source files read) without knowledge-doc output,
7
+ * and warns the user that knowledge may need to be captured.
8
+ *
9
+ * Usage (in settings.json):
10
+ * "hooks": {
11
+ * "afterTurn": [{
12
+ * "command": "node ~/projects/harness/bin/harness-knowledge-capture.js"
13
+ * }]
14
+ * }
15
+ */
16
+
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+
20
+ // Read turn data from stdin
21
+ let input = '';
22
+ process.stdin.setEncoding('utf-8');
23
+ process.stdin.on('data', (chunk) => input += chunk);
24
+
25
+ process.stdin.on('end', () => {
26
+ try {
27
+ const turn = JSON.parse(input);
28
+ const result = checkTurn(turn);
29
+ if (result.shouldWarn) {
30
+ process.stderr.write(`\n${'='.repeat(60)}\n`);
31
+ process.stderr.write(' ⚠️ 可能遗漏了知识沉淀\n');
32
+ process.stderr.write(`${'='.repeat(60)}\n`);
33
+ process.stderr.write(` 本回合读取了 ${result.fileReads} 个文件\n`);
34
+ process.stderr.write(` 但未写入 .harness/knowledge-docs/\n`);
35
+ process.stderr.write(`\n`);
36
+ process.stderr.write(` 如果这是深度分析,请执行:\n`);
37
+ process.stderr.write(` npx harness knowledge upsert --scope <scope> --file <file> --source claude\n`);
38
+ process.stderr.write(`${'='.repeat(60)}\n\n`);
39
+ }
40
+ } catch (e) {
41
+ // Silently ignore parse errors — non-JSON input is fine
42
+ }
43
+ });
44
+
45
+ function checkTurn(turn) {
46
+ let fileReads = 0;
47
+ let knowledgeWrites = 0;
48
+
49
+ // Walk through messages looking for tool calls
50
+ const messages = turn.messages || [turn];
51
+ for (const msg of messages) {
52
+ // Claude Code format: tool_uses array
53
+ if (msg.role === 'assistant' && msg.tool_uses) {
54
+ for (const tool of msg.tool_uses) {
55
+ if (isFileRead(tool)) fileReads++;
56
+ if (isKnowledgeWrite(tool)) knowledgeWrites++;
57
+ }
58
+ }
59
+ // Plain tool_calls format
60
+ if (msg.tool_calls) {
61
+ for (const tool of msg.tool_calls) {
62
+ if (isFileRead(tool)) fileReads++;
63
+ if (isKnowledgeWrite(tool)) knowledgeWrites++;
64
+ }
65
+ }
66
+ // Messages content with tool use markers
67
+ if (msg.content && typeof msg.content === 'string') {
68
+ const readMatches = msg.content.match(/\bRead\b.*/g);
69
+ if (readMatches) fileReads += readMatches.length;
70
+ }
71
+ }
72
+
73
+ return {
74
+ fileReads,
75
+ knowledgeWrites,
76
+ shouldWarn: fileReads >= 3 && knowledgeWrites === 0,
77
+ };
78
+ }
79
+
80
+ function isFileRead(tool) {
81
+ const name = (tool.name || tool.function?.name || '').toLowerCase();
82
+ const isReadTool = ['read', 'glob', 'grep', 'agent'].includes(name);
83
+ if (!isReadTool) return false;
84
+
85
+ const params = tool.parameters || tool.function?.arguments || {};
86
+ const filePath = params.file_path || params.path || params.pattern || '';
87
+ // Only count actual source file reads, not config/memory/docs
88
+ const isSource = /\/(src|packages|apps)\/|\.(ts|tsx|js|jsx|py|go|rs)$/.test(filePath);
89
+ return isSource;
90
+ }
91
+
92
+ function isKnowledgeWrite(tool) {
93
+ const name = (tool.name || tool.function?.name || '').toLowerCase();
94
+ if (name !== 'write') return false;
95
+
96
+ const params = tool.parameters || tool.function?.arguments || {};
97
+ const filePath = params.file_path || '';
98
+ return filePath.includes('.harness/knowledge-docs/') || filePath.includes('.harness/knowledge/');
99
+ }
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Stop hook — check if deep analysis happened without knowledge capture
4
+ *
5
+ * Reads state file written by harness-knowledge-track.js.
6
+ * If EnterPlanMode was called, or Agent(Explore) was spawned, or 10+ unique
7
+ * directories were Read — and no knowledge files were Written — warn.
8
+ *
9
+ * Output: JSON with systemMessage (shown to user)
10
+ */
11
+
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+ const os = require('os');
15
+ const STATE_FILE = '/tmp/claude-knowledge-capture-state.json';
16
+ const LOG_FILE = '/tmp/claude-knowledge-hooks.log';
17
+ const EVENTS_FILE = path.join(os.homedir(), 'events', 'studio.jsonl');
18
+ const UNIQUE_DIR_THRESHOLD = 10;
19
+
20
+ function log(level, message, data) {
21
+ try {
22
+ const entry = JSON.stringify({ ts: new Date().toISOString(), level, message, ...data }) + '\n';
23
+ fs.appendFileSync(LOG_FILE, entry, 'utf-8');
24
+ } catch {}
25
+ }
26
+
27
+ try {
28
+ if (!fs.existsSync(STATE_FILE)) process.exit(0);
29
+
30
+ const state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
31
+ const deepAnalysis = state.planned || state.explored || state.readDirs.length >= UNIQUE_DIR_THRESHOLD;
32
+ const missingCapture = !state.captured;
33
+
34
+ log('info', 'stop-check', {
35
+ planned: state.planned, explored: state.explored,
36
+ readDirsCount: state.readDirs.length, captured: state.captured,
37
+ deepAnalysis, missingCapture,
38
+ });
39
+
40
+ // Check 1: deep analysis without knowledge capture
41
+ if (deepAnalysis && missingCapture) {
42
+ const signals = [];
43
+ if (state.planned) signals.push('EnterPlanMode called');
44
+ if (state.explored) signals.push('Agent(Explore) spawned');
45
+ if (state.readDirs.length >= UNIQUE_DIR_THRESHOLD) signals.push(`${state.readDirs.length} unique directories Read`);
46
+
47
+ log('warn', 'missing-capture', { signals });
48
+
49
+ const message = [
50
+ '⚠️ Deep analysis detected but no knowledge captured.',
51
+ ` Signals: ${signals.join(', ')}`,
52
+ '',
53
+ ' To capture:',
54
+ ' 1. Write .harness/knowledge-docs/<scope>.md',
55
+ ' 2. npx harness knowledge upsert --scope <scope> --file <file> --source claude',
56
+ '',
57
+ ' Or run `harness knowledge sync-status` to check staleness.',
58
+ ].join('\n');
59
+
60
+ console.log(JSON.stringify({ systemMessage: message }));
61
+ }
62
+
63
+ // Check 2: sensitive file operations without prior Read
64
+ const sensitiveOps = (state.sensitiveOps || []).filter(op => !op.verified);
65
+ if (sensitiveOps.length > 0) {
66
+ log('warn', 'unverified-sensitive-ops', { sensitiveOps });
67
+
68
+ const opsList = sensitiveOps.map(op => ` - ${op.tool}: ${op.file}`).join('\n');
69
+ const message = [
70
+ '⚠️ File operations on sensitive paths without prior verification.',
71
+ ` Operations:`,
72
+ opsList,
73
+ '',
74
+ ' These files were moved/edited/written without being Read first.',
75
+ ' Verify the changes were intentional and correct.',
76
+ '',
77
+ ' 📋 Rule: feedback_verify_before_move.md — Read before acting on file classification.',
78
+ ].join('\n');
79
+
80
+ console.log(JSON.stringify({ systemMessage: message }));
81
+ }
82
+ // Emit session summary event → events-daemon → knowledge extraction pipeline
83
+ try {
84
+ const now = Date.now();
85
+ const durationMs = state.startTime ? now - state.startTime : 0;
86
+ const durationMin = Math.round(durationMs / 60000);
87
+ const event = {
88
+ type: 'session:summary',
89
+ sessionType: 'development',
90
+ tool: state.tool || 'unknown', // claude | codex | opencode | etc
91
+ timestamp: new Date().toISOString(),
92
+ durationMs,
93
+ durationMin,
94
+ deepAnalysis: state.planned || state.explored || state.readDirs.length >= UNIQUE_DIR_THRESHOLD,
95
+ knowledgeCaptured: !!state.captured,
96
+ readDirsCount: state.readDirs.length,
97
+ planned: state.planned || false,
98
+ explored: state.explored || false,
99
+ sensitiveOpsCount: (state.sensitiveOps || []).filter(op => !op.verified).length,
100
+ turnCount: state.turnCount || 0,
101
+ };
102
+ const dir = path.dirname(EVENTS_FILE);
103
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
104
+ fs.appendFileSync(EVENTS_FILE, JSON.stringify(event) + '\n', 'utf-8');
105
+ log('info', 'session-summary-emitted', event);
106
+ } catch {}
107
+
108
+ // Auto-ingest: scan memory files with ingest:true → call local-rag API
109
+ // PostToolUse hooks don't fire in interactive mode, so Stop hook handles it
110
+ try {
111
+ const MEMORY_DIR = path.join(os.homedir(), '.claude', 'projects', '-root-projects', 'memory');
112
+ if (fs.existsSync(MEMORY_DIR)) {
113
+ const files = fs.readdirSync(MEMORY_DIR).filter(f => f.endsWith('.md'));
114
+ const ingested = [];
115
+ for (const f of files) {
116
+ const fp = path.join(MEMORY_DIR, f);
117
+ const head = fs.readFileSync(fp, 'utf-8').slice(0, 500);
118
+ if (/^---[\s\S]*?ingest:\s*true[\s\S]*?---/.test(head)) {
119
+ // Check if already ingested recently (skip if unchanged in last hour)
120
+ const stat = fs.statSync(fp);
121
+ const hourAgo = Date.now() - 3600_000;
122
+ if (stat.mtimeMs > hourAgo) {
123
+ ingested.push(fp);
124
+ }
125
+ }
126
+ }
127
+ if (ingested.length > 0) {
128
+ log('info', 'auto-ingest-start', { count: ingested.length, files: ingested });
129
+ const { execSync } = require('child_process');
130
+ const syncScript = '/root/projects/studio/bin/memory-knowledge-sync.js';
131
+ let successCount = 0;
132
+ for (const fp of ingested) {
133
+ try {
134
+ execSync(`node "${syncScript}" "${fp}"`, { timeout: 10_000, stdio: 'pipe' });
135
+ successCount++;
136
+ } catch (e) {
137
+ log('warn', 'auto-ingest-failed', { file: fp, error: (e.message || String(e)).slice(0, 100) });
138
+ }
139
+ }
140
+ log('info', 'auto-ingest-done', { success: successCount, total: ingested.length });
141
+ }
142
+ }
143
+ } catch {}
144
+ } catch (e) {
145
+ // Silently ignore errors
146
+ } finally {
147
+ // Clean up state file for next session
148
+ try { fs.unlinkSync(STATE_FILE); } catch {}
149
+ }
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * PostToolUse hook — track deep analysis signals
4
+ *
5
+ * Updates state file with:
6
+ * - planned: EnterPlanMode was called
7
+ * - explored: Agent(Explore) was spawned
8
+ * - readDirs: Set of unique directories Read was called on
9
+ * - captured: Write to .harness/knowledge-docs/ or .harness/knowledge/
10
+ * - turnCount: session turn counter
11
+ *
12
+ * Usage: PostToolUse hook with matcher "EnterPlanMode|Agent|Read|Write|Write"
13
+ */
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ const STATE_FILE = '/tmp/claude-knowledge-capture-state.json';
19
+ const LOG_FILE = '/tmp/claude-knowledge-hooks.log';
20
+
21
+ function log(level, message, data) {
22
+ try {
23
+ const entry = JSON.stringify({ ts: new Date().toISOString(), level, message, ...data }) + '\n';
24
+ fs.appendFileSync(LOG_FILE, entry, 'utf-8');
25
+ } catch {}
26
+ }
27
+
28
+ // Read hook input from stdin
29
+ let input = '';
30
+ process.stdin.setEncoding('utf-8');
31
+ process.stdin.on('data', (chunk) => input += chunk);
32
+
33
+ process.stdin.on('end', () => {
34
+ try {
35
+ const event = JSON.parse(input);
36
+ const state = loadState();
37
+ updateState(state, event);
38
+ saveState(state);
39
+ } catch (e) {
40
+ // Silently ignore parse errors
41
+ }
42
+ });
43
+
44
+ function loadState() {
45
+ try {
46
+ if (fs.existsSync(STATE_FILE)) {
47
+ return JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
48
+ }
49
+ } catch {}
50
+ return { planned: false, explored: false, readDirs: [], captured: false };
51
+ }
52
+
53
+ function updateState(state, event) {
54
+ const toolName = event.tool_name || '';
55
+
56
+ if (toolName === 'EnterPlanMode') {
57
+ state.planned = true;
58
+ log('info', 'planned', { tool: toolName });
59
+ }
60
+
61
+ if (toolName === 'Agent') {
62
+ const input = event.tool_input || {};
63
+ if (input.subagent_type === 'Explore') {
64
+ state.explored = true;
65
+ log('info', 'explored', { tool: toolName, subagent_type: input.subagent_type });
66
+ }
67
+ }
68
+
69
+ if (toolName === 'Read') {
70
+ const input = event.tool_input || {};
71
+ const filePath = input.file_path || '';
72
+ const dir = path.dirname(filePath);
73
+ if (dir && dir !== '.' && dir !== '/' && !state.readDirs.includes(dir)) {
74
+ state.readDirs.push(dir);
75
+ }
76
+ }
77
+
78
+ if (toolName === 'Write') {
79
+ const input = event.tool_input || {};
80
+ const filePath = input.file_path || '';
81
+ if (filePath.includes('.harness/knowledge-docs/') || filePath.includes('.harness/knowledge/')) {
82
+ state.captured = true;
83
+ log('info', 'captured', { file: filePath });
84
+ }
85
+ }
86
+ }
87
+
88
+ function saveState(state) {
89
+ try {
90
+ fs.writeFileSync(STATE_FILE, JSON.stringify(state), 'utf-8');
91
+ } catch {}
92
+ }
@@ -0,0 +1,47 @@
1
+ #!/bin/bash
2
+ # PostToolUse hook — track deep analysis + session metrics
3
+ # Matcher: EnterPlanMode|Agent|Read|Write|Edit|Bash (broad coverage)
4
+ # DailyReflection: enriched session:summary events for behavioral analysis
5
+
6
+ STATE_FILE=/tmp/claude-knowledge-capture-state.json
7
+ INPUT=$(cat)
8
+
9
+ tool_name=$(echo "$INPUT" | jq -r '.tool_name // ""')
10
+ file_path=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
11
+
12
+ # Init state file if missing (tool: claude|codex|opencode|etc)
13
+ _tool=$(echo "${CLAUDE_CODE_TOOL_NAME:-claude}" | tr '[:upper:]' '[:lower:]')
14
+ [ -f "$STATE_FILE" ] || echo "{\"planned\":false,\"explored\":false,\"readDirs\":[],\"captured\":false,\"turnCount\":0,\"startTime\":$(date +%s)000,\"tool\":\"$_tool\"}" > "$STATE_FILE"
15
+
16
+ # Always increment turn counter on substantive tools
17
+ case "$tool_name" in
18
+ EnterPlanMode)
19
+ jq '.planned = true | .turnCount += 1' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
20
+ ;;
21
+ Agent)
22
+ # Agent(Explore) spawned → deep analysis signal
23
+ _agent_type=$(echo "$INPUT" | jq -r '.tool_input.subagent_type // ""')
24
+ if [ "$_agent_type" = "Explore" ]; then
25
+ jq '.explored = true | .turnCount += 1' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
26
+ fi
27
+ ;;
28
+ Read)
29
+ if [ -n "$file_path" ]; then
30
+ dir=$(dirname "$file_path")
31
+ if [ "$dir" != "." ] && [ "$dir" != "/" ]; then
32
+ jq --arg d "$dir" '.readDirs += [$d] | .readDirs |= unique | .turnCount += 1' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
33
+ fi
34
+ fi
35
+ ;;
36
+ Write|Edit)
37
+ jq '.turnCount += 1' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
38
+ case "$file_path" in
39
+ *.harness/knowledge-docs/*|*.harness/knowledge/*|*/memory/*.md|*/docs/*.md)
40
+ jq '.captured = true' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
41
+ ;;
42
+ esac
43
+ ;;
44
+ Bash)
45
+ jq '.turnCount += 1' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
46
+ ;;
47
+ esac
@@ -0,0 +1,67 @@
1
+ #!/bin/bash
2
+ # PostToolUse hook — check for operations on sensitive files without prior Read
3
+ #
4
+ # Detects: Bash(mv/rm), Edit, or Write targeting files in bin/, .harness/, or
5
+ # package.json — and checks whether those files were Read earlier in this session.
6
+ #
7
+ # State file is maintained by harness-knowledge-track.sh which tracks all Read calls.
8
+
9
+ STATE_FILE=/tmp/claude-knowledge-capture-state.json
10
+ SENSITIVE_DIRS="bin/ .harness/"
11
+
12
+ INPUT=$(cat)
13
+ tool_name=$(echo "$INPUT" | jq -r '.tool_name // ""')
14
+ file_path=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
15
+ content=$(echo "$INPUT" | jq -r '.tool_input.content // ""')
16
+ command=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
17
+
18
+ # Check if this operation targets a sensitive file
19
+ is_sensitive=false
20
+ for dir in $SENSITIVE_DIRS; do
21
+ case "$file_path" in
22
+ *$dir*) is_sensitive=true; break ;;
23
+ esac
24
+ done
25
+
26
+ # For Bash, check if the command involves mv/rm on sensitive paths
27
+ if [ "$tool_name" = "Bash" ] && [ -n "$command" ]; then
28
+ for dir in $SENSITIVE_DIRS; do
29
+ if echo "$command" | grep -qE "(mv|rm|cp|git rm).*$dir"; then
30
+ is_sensitive=true
31
+ # Extract target from command for checking
32
+ file_path=$(echo "$command" | grep -oE "$dir[^ ]*" | head -1)
33
+ break
34
+ fi
35
+ done
36
+ fi
37
+
38
+ # Only check sensitive operations
39
+ if [ "$is_sensitive" != "true" ] || [ -z "$file_path" ]; then
40
+ exit 0
41
+ fi
42
+
43
+ # Check if this file was Read earlier in the session
44
+ if [ -f "$STATE_FILE" ]; then
45
+ read_dirs=$(jq -r '.readDirs // [] | join(" ")' "$STATE_FILE" 2>/dev/null || echo "")
46
+
47
+ # Check if any read_dir is an ancestor of file_path
48
+ verified=false
49
+ file_dir=$(dirname "$file_path")
50
+ for dir in $read_dirs; do
51
+ case "$file_dir" in
52
+ "$dir"|"$dir/"*) verified=true; break ;;
53
+ esac
54
+ done
55
+
56
+ if [ "$verified" != "true" ]; then
57
+ # Also check if the file itself was explicitly Read (file_path matches a read path)
58
+ # The track hook only records directories, not individual files — conservative check
59
+
60
+ # Emit warning via state file for Stop hook to pick up
61
+ jq --arg op "$tool_name" --arg fp "$file_path" \
62
+ '.sensitiveOps += [{"tool":$op,"file":$fp,"verified":false}]' \
63
+ "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
64
+ fi
65
+ fi
66
+
67
+ exit 0
@@ -496,6 +496,36 @@ custom_constraints:
496
496
  * - 如果存在 HARNESS_CONSTRAINTS_START/END 标记,替换标记间内容
497
497
  * - 如果不存在标记,在文件末尾追加约束段
498
498
  *
499
+ /**
500
+ * 在 CLAUDE.md 顶部写入 Output Style 段(仅首次创建,后续不覆盖)
501
+ */
502
+ const OUTPUT_STYLE_SECTION = [
503
+ '## Output Style',
504
+ '',
505
+ 'Terse like caveman. Technical substance exact. Only fluff die.',
506
+ 'Drop: articles, filler (just/really/basically), pleasantries (sure/certainly/happy to), hedging.',
507
+ 'Fragments OK. Short synonyms. Code blocks unchanged. Error messages quoted exact.',
508
+ 'Pattern: [thing] [action] [reason]. [next step].',
509
+ 'No sycophantic openers/closing fluff. No emojis or em-dashes.',
510
+ 'Read existing files before writing. Don\'t re-read unless changed.',
511
+ 'Skip files over 100KB unless required.',
512
+ 'Don\'t guess APIs, versions, flags, commit SHAs, or package names. Verify before asserting.',
513
+ '',
514
+ ].join('\n');
515
+ async function setupClaudeMdOutputStyle(projectPath) {
516
+ const claudeMdPath = path.join(projectPath, 'CLAUDE.md');
517
+ try {
518
+ const content = await fs.readFile(claudeMdPath, 'utf-8');
519
+ if (content.includes('## Output Style'))
520
+ return; // 已存在,不覆盖
521
+ const newContent = OUTPUT_STYLE_SECTION + '\n' + content;
522
+ await fs.writeFile(claudeMdPath, newContent, 'utf-8');
523
+ }
524
+ catch {
525
+ // CLAUDE.md 不存在——setupClaudeMdConstraints 会创建它
526
+ }
527
+ }
528
+ /**
499
529
  * 只写入包含 promptInjection 文本的约束
500
530
  */
501
531
  async function setupClaudeMdConstraints(projectPath) {
@@ -589,9 +619,11 @@ async function setupGovernance(projectPath, level) {
589
619
  console.log(chalk_1.default.blue('📋 设置治理文件...'));
590
620
  // 1. 生成 CHANGELOG.md
591
621
  await createChangelog(projectPath, governance);
592
- // 2. 在 CLAUDE.md 中写入/更新 Governance Rules 约束段
622
+ // 2. 在 CLAUDE.md 中写入 Output Style 段(仅在不存在时创建)
623
+ await setupClaudeMdOutputStyle(projectPath);
624
+ // 3. 在 CLAUDE.md 中写入/更新 Governance Rules 约束段
593
625
  await setupClaudeMdConstraints(projectPath);
594
- // 3. 生成 CONTEXT.md 文件
626
+ // 4. 生成 CONTEXT.md 文件
595
627
  const contextConfig = governance.context_files;
596
628
  if (contextConfig?.enabled) {
597
629
  let requiredDirs = contextConfig.required_dirs || [];