@dommaker/harness 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +2 -4
  3. package/bin/harness.js +12 -37
  4. package/dist/cli/commands/check.d.ts +2 -2
  5. package/dist/cli/commands/check.d.ts.map +1 -1
  6. package/dist/cli/commands/check.js +7 -32
  7. package/dist/cli/commands/check.js.map +1 -1
  8. package/dist/cli/commands/definitions.d.ts +2 -0
  9. package/dist/cli/commands/definitions.d.ts.map +1 -1
  10. package/dist/cli/commands/definitions.js.map +1 -1
  11. package/dist/cli/commands/init.d.ts.map +1 -1
  12. package/dist/cli/commands/init.js +6 -37
  13. package/dist/cli/commands/init.js.map +1 -1
  14. package/dist/cli/commands/knowledge.d.ts.map +1 -1
  15. package/dist/cli/commands/knowledge.js +1 -12
  16. package/dist/cli/commands/knowledge.js.map +1 -1
  17. package/dist/cli/commands/report.d.ts.map +1 -1
  18. package/dist/cli/commands/report.js +0 -2
  19. package/dist/cli/commands/report.js.map +1 -1
  20. package/dist/cli/commands/status.js +2 -2
  21. package/dist/cli/commands/status.js.map +1 -1
  22. package/dist/context/index.d.ts +9 -6
  23. package/dist/context/index.d.ts.map +1 -1
  24. package/dist/context/index.js +18 -20
  25. package/dist/context/index.js.map +1 -1
  26. package/dist/core/constraints/capabilities-parser.d.ts +3 -2
  27. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  28. package/dist/core/constraints/capabilities-parser.js +25 -47
  29. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  30. package/dist/core/constraints/checker.d.ts +29 -32
  31. package/dist/core/constraints/checker.d.ts.map +1 -1
  32. package/dist/core/constraints/checker.js +34 -126
  33. package/dist/core/constraints/checker.js.map +1 -1
  34. package/dist/core/constraints/checkers/index.d.ts +2 -1
  35. package/dist/core/constraints/checkers/index.d.ts.map +1 -1
  36. package/dist/core/constraints/checkers/index.js +3 -0
  37. package/dist/core/constraints/checkers/index.js.map +1 -1
  38. package/dist/core/constraints/checkers/types.d.ts +25 -0
  39. package/dist/core/constraints/checkers/types.d.ts.map +1 -1
  40. package/dist/core/constraints/checkers/types.js +24 -0
  41. package/dist/core/constraints/checkers/types.js.map +1 -1
  42. package/dist/core/constraints/definitions/guidelines.d.ts.map +1 -1
  43. package/dist/core/constraints/definitions/guidelines.js +0 -2
  44. package/dist/core/constraints/definitions/guidelines.js.map +1 -1
  45. package/dist/core/constraints/definitions/prompts.d.ts.map +1 -1
  46. package/dist/core/constraints/definitions/prompts.js +0 -5
  47. package/dist/core/constraints/definitions/prompts.js.map +1 -1
  48. package/dist/core/constraints/index.d.ts +1 -2
  49. package/dist/core/constraints/index.d.ts.map +1 -1
  50. package/dist/core/constraints/index.js +1 -7
  51. package/dist/core/constraints/index.js.map +1 -1
  52. package/dist/core/constraints/usage-report.d.ts +1 -2
  53. package/dist/core/constraints/usage-report.d.ts.map +1 -1
  54. package/dist/core/constraints/usage-report.js +2 -5
  55. package/dist/core/constraints/usage-report.js.map +1 -1
  56. package/dist/core/effective-constraints.d.ts +24 -4
  57. package/dist/core/effective-constraints.d.ts.map +1 -1
  58. package/dist/core/effective-constraints.js +28 -7
  59. package/dist/core/effective-constraints.js.map +1 -1
  60. package/dist/core/effective-set.d.ts +30 -0
  61. package/dist/core/effective-set.d.ts.map +1 -0
  62. package/dist/core/effective-set.js +35 -0
  63. package/dist/core/effective-set.js.map +1 -0
  64. package/dist/core/index.d.ts +13 -6
  65. package/dist/core/index.d.ts.map +1 -1
  66. package/dist/core/index.js +44 -21
  67. package/dist/core/index.js.map +1 -1
  68. package/dist/core/project-config-loader.d.ts +3 -6
  69. package/dist/core/project-config-loader.d.ts.map +1 -1
  70. package/dist/core/project-config-loader.js +47 -61
  71. package/dist/core/project-config-loader.js.map +1 -1
  72. package/dist/failure/constraint-handler.d.ts +1 -1
  73. package/dist/failure/constraint-handler.js +1 -1
  74. package/dist/gates/checker-gate.d.ts +1 -4
  75. package/dist/gates/checker-gate.d.ts.map +1 -1
  76. package/dist/gates/checker-gate.js +3 -11
  77. package/dist/gates/checker-gate.js.map +1 -1
  78. package/dist/gates/definitions.d.ts +9 -38
  79. package/dist/gates/definitions.d.ts.map +1 -1
  80. package/dist/gates/definitions.js +24 -13
  81. package/dist/gates/definitions.js.map +1 -1
  82. package/dist/gates/effective-gates.d.ts.map +1 -1
  83. package/dist/gates/effective-gates.js +14 -18
  84. package/dist/gates/effective-gates.js.map +1 -1
  85. package/dist/gates/index.d.ts +1 -1
  86. package/dist/gates/index.d.ts.map +1 -1
  87. package/dist/gates/index.js.map +1 -1
  88. package/dist/hooks/bootstrap.d.ts.map +1 -1
  89. package/dist/hooks/bootstrap.js +0 -3
  90. package/dist/hooks/bootstrap.js.map +1 -1
  91. package/dist/index.d.ts +43 -60
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +180 -143
  94. package/dist/index.js.map +1 -1
  95. package/dist/knowledge/query.d.ts +15 -0
  96. package/dist/knowledge/query.d.ts.map +1 -1
  97. package/dist/knowledge/query.js +23 -0
  98. package/dist/knowledge/query.js.map +1 -1
  99. package/dist/monitoring/analyzer-base.d.ts +0 -4
  100. package/dist/monitoring/analyzer-base.d.ts.map +1 -1
  101. package/dist/monitoring/analyzer-base.js +0 -21
  102. package/dist/monitoring/analyzer-base.js.map +1 -1
  103. package/dist/monitoring/index.d.ts +6 -12
  104. package/dist/monitoring/index.d.ts.map +1 -1
  105. package/dist/monitoring/index.js +13 -29
  106. package/dist/monitoring/index.js.map +1 -1
  107. package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
  108. package/dist/monitoring/trace-analyzer.js +2 -68
  109. package/dist/monitoring/trace-analyzer.js.map +1 -1
  110. package/dist/monitoring/traces.d.ts +0 -4
  111. package/dist/monitoring/traces.d.ts.map +1 -1
  112. package/dist/monitoring/traces.js +0 -14
  113. package/dist/monitoring/traces.js.map +1 -1
  114. package/dist/presets/index.d.ts +2 -2
  115. package/dist/presets/index.d.ts.map +1 -1
  116. package/dist/presets/index.js +3 -4
  117. package/dist/presets/index.js.map +1 -1
  118. package/dist/presets/standard.d.ts +10 -22
  119. package/dist/presets/standard.d.ts.map +1 -1
  120. package/dist/presets/standard.js +15 -75
  121. package/dist/presets/standard.js.map +1 -1
  122. package/dist/types/constraint.d.ts +1 -29
  123. package/dist/types/constraint.d.ts.map +1 -1
  124. package/dist/types/constraint.js +1 -1
  125. package/dist/types/constraint.js.map +1 -1
  126. package/dist/types/index.d.ts +0 -3
  127. package/dist/types/index.d.ts.map +1 -1
  128. package/dist/types/index.js +0 -4
  129. package/dist/types/index.js.map +1 -1
  130. package/dist/types/project-config.d.ts +4 -8
  131. package/dist/types/project-config.d.ts.map +1 -1
  132. package/dist/types/trace.d.ts +5 -18
  133. package/dist/types/trace.d.ts.map +1 -1
  134. package/package.json +2 -2
  135. package/src/CONTEXT.md +4 -5
  136. package/src/__tests__/checker-extra.test.ts +33 -139
  137. package/src/__tests__/checker.test.ts +0 -376
  138. package/src/__tests__/project-config-loader-extra.test.ts +42 -29
  139. package/src/__tests__/public-exports.test.ts +138 -0
  140. package/src/__tests__/trace-analyzer-extra.test.ts +6 -86
  141. package/src/__tests__/trace-analyzer.test.ts +4 -5
  142. package/src/__tests__/trace-collector.test.ts +0 -11
  143. package/src/__tests__/traces.test.ts +3 -22
  144. package/src/cli/commands/CONTEXT.md +2 -2
  145. package/src/cli/commands/__tests__/check-skip-output.test.ts +10 -7
  146. package/src/cli/commands/__tests__/check.test.ts +29 -69
  147. package/src/cli/commands/__tests__/constraints-report.test.ts +1 -1
  148. package/src/cli/commands/__tests__/knowledge.test.ts +90 -1
  149. package/src/cli/commands/__tests__/registry.test.ts +8 -6
  150. package/src/cli/commands/__tests__/status-extra.test.ts +6 -6
  151. package/src/cli/commands/__tests__/status.test.ts +6 -6
  152. package/src/cli/commands/check.ts +8 -34
  153. package/src/cli/commands/definitions.ts +2 -0
  154. package/src/cli/commands/init.ts +6 -37
  155. package/src/cli/commands/knowledge.ts +1 -16
  156. package/src/cli/commands/report.ts +0 -2
  157. package/src/cli/commands/status.ts +2 -2
  158. package/src/context/index.ts +29 -6
  159. package/src/core/CONTEXT.md +4 -3
  160. package/src/core/__tests__/effective-set.test.ts +80 -0
  161. package/src/core/constraints/capabilities-parser.ts +43 -49
  162. package/src/core/constraints/checker.ts +51 -145
  163. package/src/core/constraints/checkers/index.ts +2 -1
  164. package/src/core/constraints/checkers/types.ts +42 -0
  165. package/src/core/constraints/definitions/guidelines.ts +0 -2
  166. package/src/core/constraints/definitions/prompts.ts +0 -5
  167. package/src/core/constraints/index.ts +2 -17
  168. package/src/core/constraints/usage-report.ts +5 -8
  169. package/src/core/effective-constraints.ts +35 -7
  170. package/src/core/effective-set.ts +56 -0
  171. package/src/core/index.ts +80 -6
  172. package/src/core/project-config-loader.ts +53 -68
  173. package/src/failure/CONTEXT.md +1 -1
  174. package/src/failure/constraint-handler.ts +1 -1
  175. package/src/gates/CONTEXT.md +3 -3
  176. package/src/gates/checker-gate.ts +4 -12
  177. package/src/gates/definitions.ts +27 -50
  178. package/src/gates/effective-gates.ts +14 -21
  179. package/src/gates/index.ts +1 -1
  180. package/src/hooks/bootstrap.ts +0 -3
  181. package/src/index.ts +384 -148
  182. package/src/knowledge/CONTEXT.md +2 -2
  183. package/src/knowledge/__tests__/query.test.ts +64 -0
  184. package/src/knowledge/query.ts +28 -0
  185. package/src/monitoring/CONTEXT.md +7 -13
  186. package/src/monitoring/__tests__/traces.test.ts +0 -10
  187. package/src/monitoring/analyzer-base.ts +0 -22
  188. package/src/monitoring/index.ts +6 -12
  189. package/src/monitoring/trace-analyzer.ts +2 -73
  190. package/src/monitoring/traces.ts +0 -20
  191. package/src/presets/__tests__/standard.test.ts +48 -69
  192. package/src/presets/index.ts +3 -5
  193. package/src/presets/standard.ts +14 -79
  194. package/src/spec/CONTEXT.md +5 -13
  195. package/src/types/constraint.ts +1 -51
  196. package/src/types/index.ts +0 -12
  197. package/src/types/project-config.ts +4 -10
  198. package/src/types/trace.ts +5 -30
  199. package/dist/core/constraints/interceptor.d.ts +0 -39
  200. package/dist/core/constraints/interceptor.d.ts.map +0 -1
  201. package/dist/core/constraints/interceptor.js +0 -166
  202. package/dist/core/constraints/interceptor.js.map +0 -1
  203. package/dist/dashboard/data.d.ts +0 -31
  204. package/dist/dashboard/data.d.ts.map +0 -1
  205. package/dist/dashboard/data.js +0 -81
  206. package/dist/dashboard/data.js.map +0 -1
  207. package/dist/dashboard/index.d.ts +0 -4
  208. package/dist/dashboard/index.d.ts.map +0 -1
  209. package/dist/dashboard/index.js +0 -20
  210. package/dist/dashboard/index.js.map +0 -1
  211. package/dist/dashboard/stats.d.ts +0 -20
  212. package/dist/dashboard/stats.d.ts.map +0 -1
  213. package/dist/dashboard/stats.js +0 -115
  214. package/dist/dashboard/stats.js.map +0 -1
  215. package/dist/dashboard/types.d.ts +0 -110
  216. package/dist/dashboard/types.d.ts.map +0 -1
  217. package/dist/dashboard/types.js +0 -8
  218. package/dist/dashboard/types.js.map +0 -1
  219. package/dist/monitoring/constraint-doctor.d.ts +0 -76
  220. package/dist/monitoring/constraint-doctor.d.ts.map +0 -1
  221. package/dist/monitoring/constraint-doctor.js +0 -189
  222. package/dist/monitoring/constraint-doctor.js.map +0 -1
  223. package/dist/monitoring/diagnosis-rules.d.ts +0 -18
  224. package/dist/monitoring/diagnosis-rules.d.ts.map +0 -1
  225. package/dist/monitoring/diagnosis-rules.js +0 -119
  226. package/dist/monitoring/diagnosis-rules.js.map +0 -1
  227. package/dist/monitoring/knowledge-doctor.d.ts +0 -78
  228. package/dist/monitoring/knowledge-doctor.d.ts.map +0 -1
  229. package/dist/monitoring/knowledge-doctor.js +0 -266
  230. package/dist/monitoring/knowledge-doctor.js.map +0 -1
  231. package/dist/monitoring/knowledge-evolver.d.ts +0 -72
  232. package/dist/monitoring/knowledge-evolver.d.ts.map +0 -1
  233. package/dist/monitoring/knowledge-evolver.js +0 -205
  234. package/dist/monitoring/knowledge-evolver.js.map +0 -1
  235. package/dist/monitoring/performance-analyzer.d.ts +0 -92
  236. package/dist/monitoring/performance-analyzer.d.ts.map +0 -1
  237. package/dist/monitoring/performance-analyzer.js +0 -343
  238. package/dist/monitoring/performance-analyzer.js.map +0 -1
  239. package/dist/monitoring/performance-collector.d.ts +0 -103
  240. package/dist/monitoring/performance-collector.d.ts.map +0 -1
  241. package/dist/monitoring/performance-collector.js +0 -298
  242. package/dist/monitoring/performance-collector.js.map +0 -1
  243. package/dist/safety/index.d.ts +0 -6
  244. package/dist/safety/index.d.ts.map +0 -1
  245. package/dist/safety/index.js +0 -22
  246. package/dist/safety/index.js.map +0 -1
  247. package/dist/safety/input-guardrail.d.ts +0 -36
  248. package/dist/safety/input-guardrail.d.ts.map +0 -1
  249. package/dist/safety/input-guardrail.js +0 -118
  250. package/dist/safety/input-guardrail.js.map +0 -1
  251. package/dist/safety/output-guardrail.d.ts +0 -39
  252. package/dist/safety/output-guardrail.d.ts.map +0 -1
  253. package/dist/safety/output-guardrail.js +0 -147
  254. package/dist/safety/output-guardrail.js.map +0 -1
  255. package/dist/safety/sandbox.d.ts +0 -45
  256. package/dist/safety/sandbox.d.ts.map +0 -1
  257. package/dist/safety/sandbox.js +0 -134
  258. package/dist/safety/sandbox.js.map +0 -1
  259. package/dist/safety/tool-guardrail.d.ts +0 -51
  260. package/dist/safety/tool-guardrail.d.ts.map +0 -1
  261. package/dist/safety/tool-guardrail.js +0 -147
  262. package/dist/safety/tool-guardrail.js.map +0 -1
  263. package/dist/safety/types.d.ts +0 -104
  264. package/dist/safety/types.d.ts.map +0 -1
  265. package/dist/safety/types.js +0 -6
  266. package/dist/safety/types.js.map +0 -1
  267. package/dist/spec/annotation-checker.d.ts +0 -47
  268. package/dist/spec/annotation-checker.d.ts.map +0 -1
  269. package/dist/spec/annotation-checker.js +0 -279
  270. package/dist/spec/annotation-checker.js.map +0 -1
  271. package/dist/types/enforcement.d.ts +0 -42
  272. package/dist/types/enforcement.d.ts.map +0 -1
  273. package/dist/types/enforcement.js +0 -6
  274. package/dist/types/enforcement.js.map +0 -1
  275. package/dist/types/monitoring-types.d.ts +0 -53
  276. package/dist/types/monitoring-types.d.ts.map +0 -1
  277. package/dist/types/monitoring-types.js +0 -10
  278. package/dist/types/monitoring-types.js.map +0 -1
  279. package/dist/types/performance.d.ts +0 -204
  280. package/dist/types/performance.d.ts.map +0 -1
  281. package/dist/types/performance.js +0 -12
  282. package/dist/types/performance.js.map +0 -1
  283. package/dist/verification/index.d.ts +0 -4
  284. package/dist/verification/index.d.ts.map +0 -1
  285. package/dist/verification/index.js +0 -20
  286. package/dist/verification/index.js.map +0 -1
  287. package/dist/verification/loop.d.ts +0 -30
  288. package/dist/verification/loop.d.ts.map +0 -1
  289. package/dist/verification/loop.js +0 -114
  290. package/dist/verification/loop.js.map +0 -1
  291. package/dist/verification/rules-based.d.ts +0 -40
  292. package/dist/verification/rules-based.d.ts.map +0 -1
  293. package/dist/verification/rules-based.js +0 -130
  294. package/dist/verification/rules-based.js.map +0 -1
  295. package/dist/verification/types.d.ts +0 -69
  296. package/dist/verification/types.d.ts.map +0 -1
  297. package/dist/verification/types.js +0 -6
  298. package/dist/verification/types.js.map +0 -1
  299. package/src/__tests__/annotation-checker.test.ts +0 -183
  300. package/src/__tests__/constraint-doctor.test.ts +0 -271
  301. package/src/__tests__/doctor-extra.test.ts +0 -155
  302. package/src/__tests__/extend-exceptions.test.ts +0 -149
  303. package/src/__tests__/interceptor.test.ts +0 -89
  304. package/src/__tests__/performance-analyzer.test.ts +0 -499
  305. package/src/__tests__/performance-collector.test.ts +0 -276
  306. package/src/__tests__/presets.test.ts +0 -65
  307. package/src/core/constraints/__tests__/interceptor.test.ts +0 -267
  308. package/src/core/constraints/interceptor.ts +0 -217
  309. package/src/dashboard/CONTEXT.md +0 -21
  310. package/src/dashboard/__tests__/data.test.ts +0 -111
  311. package/src/dashboard/__tests__/stats.test.ts +0 -159
  312. package/src/dashboard/data.ts +0 -103
  313. package/src/dashboard/index.ts +0 -3
  314. package/src/dashboard/stats.ts +0 -127
  315. package/src/dashboard/types.ts +0 -130
  316. package/src/monitoring/__tests__/knowledge-doctor.test.ts +0 -278
  317. package/src/monitoring/__tests__/knowledge-evolver.test.ts +0 -368
  318. package/src/monitoring/__tests__/performance-analyzer.test.ts +0 -137
  319. package/src/monitoring/__tests__/performance-collector.test.ts +0 -331
  320. package/src/monitoring/constraint-doctor.ts +0 -228
  321. package/src/monitoring/diagnosis-rules.ts +0 -132
  322. package/src/monitoring/knowledge-doctor.ts +0 -322
  323. package/src/monitoring/knowledge-evolver.ts +0 -289
  324. package/src/monitoring/performance-analyzer.ts +0 -400
  325. package/src/monitoring/performance-collector.ts +0 -326
  326. package/src/safety/CONTEXT.md +0 -23
  327. package/src/safety/__tests__/input-guardrail.test.ts +0 -105
  328. package/src/safety/__tests__/output-guardrail.test.ts +0 -108
  329. package/src/safety/__tests__/sandbox.test.ts +0 -158
  330. package/src/safety/__tests__/tool-guardrail.test.ts +0 -127
  331. package/src/safety/index.ts +0 -5
  332. package/src/safety/input-guardrail.ts +0 -133
  333. package/src/safety/output-guardrail.ts +0 -170
  334. package/src/safety/sandbox.ts +0 -148
  335. package/src/safety/tool-guardrail.ts +0 -176
  336. package/src/safety/types.ts +0 -124
  337. package/src/spec/__tests__/annotation-checker.test.ts +0 -294
  338. package/src/spec/annotation-checker.ts +0 -320
  339. package/src/types/enforcement.ts +0 -48
  340. package/src/types/monitoring-types.ts +0 -68
  341. package/src/types/performance.ts +0 -295
  342. package/src/verification/CONTEXT.md +0 -23
  343. package/src/verification/__tests__/loop.test.ts +0 -303
  344. package/src/verification/__tests__/rules-based.test.ts +0 -240
  345. package/src/verification/index.ts +0 -3
  346. package/src/verification/loop.ts +0 -137
  347. package/src/verification/rules-based.ts +0 -152
  348. package/src/verification/types.ts +0 -81
@@ -86,6 +86,34 @@ export class KnowledgeQuery {
86
86
  return result;
87
87
  }
88
88
 
89
+ /**
90
+ * Full-text search over the entire corpus.
91
+ *
92
+ * Unlike query(), this is NOT budget-constrained: text matching runs on the
93
+ * full (filtered) corpus first, then results are sorted by
94
+ * maturity desc → lastReferenced desc and capped at `limit`.
95
+ * Token budgets only make sense for prompt injection (query()); interactive
96
+ * search must see every entry or low-ranked entries become unfindable.
97
+ *
98
+ * No caching and no recordReference side effect — searching is not citing.
99
+ */
100
+ search(query: string, options?: { limit?: number; filter?: QueryFilter }): KnowledgeEntry[] {
101
+ const limit = options?.limit ?? 20;
102
+ const candidates = this.store.list({
103
+ excludeArchived: true,
104
+ ...options?.filter,
105
+ });
106
+
107
+ const q = query.toLowerCase();
108
+ const matched = candidates.filter(e =>
109
+ e.title.toLowerCase().includes(q) ||
110
+ e.content.toLowerCase().includes(q) ||
111
+ e.tags.some(t => t.toLowerCase().includes(q))
112
+ );
113
+
114
+ return this.sortEntries(matched).slice(0, limit);
115
+ }
116
+
89
117
  /**
90
118
  * Estimate token count for a piece of text.
91
119
  * Rule of thumb: 1 CJK char ≈ 2 tokens, 1 ASCII char ≈ 0.25 tokens.
@@ -1,28 +1,22 @@
1
1
  # monitoring/
2
2
 
3
3
  ## 职责
4
- 运行时监控:Execution Trace(收集/分析/诊断)、Performance Trace(收集/分析)、知识进化、上下文追踪。
4
+ 运行时监控:Execution Trace(收集/分析)+ 上下文使用追踪。
5
5
 
6
6
  ## 核心导出
7
- - `TraceCollector` — 执行追踪收集(append-only JSONL,`.harness/logs/traces.log`)
8
- - `TraceAnalyzer` — 追踪统计分析 + 异常检测
9
- - `ConstraintDoctor` — 约束诊断接口(Agent 消费)
10
- - `PerformanceCollector` — 性能日志收集
11
- - `PerformanceAnalyzer` — 性能统计分析
12
- - `ContextTracker` — 上下文追踪
13
- - `KnowledgeDoctor` — 知识健康诊断
14
- - `KnowledgeEvolver` — 知识进化引擎
7
+ - `TraceCollector` — 执行追踪收集(append-only JSONL,`.harness/logs/traces.log`)
8
+ - `TraceAnalyzer` — 追踪统计分析 + 异常检测(共用 analyzer-base 纯函数)
9
+ - `ContextTracker` — LLM 调用上下文使用快照记录
15
10
 
16
11
  ## 依赖关系
17
- - 依赖 `src/core/constraints/` 约束定义
18
12
  - 依赖 `src/types/trace` ExecutionTrace 类型
19
- - 被 `src/cli/` 命令消费
13
+ - 被 `src/core/constraints/checker`(惰性接线 getTraceCollector,ADR-0003)与 `src/cli/` 命令消费
20
14
 
21
15
  ## 约定
22
- - Trace 文件存储在 .harness/ 目录(不提交)
16
+ - Trace 文件存储在 .harness/ 目录(不提交)
23
17
  - 追加写入,单行 JSON,自动滚动
24
18
  - 零 Token 成本:不调用 LLM
25
19
 
26
20
  ## 注意事项
27
21
  - 追踪数据供 `harness constraints report` 统计与退役候选诊断消费(观测用途,不做自动降级)
28
- - PerformanceCollector TraceCollector 独立运作
22
+ - ADR-0003 起移除 recordBypass 链(绕过观测后续单独立项)与断链的诊断/性能/知识医生文件
@@ -79,16 +79,6 @@ describe('TraceCollector', () => {
79
79
  });
80
80
  });
81
81
 
82
- describe('recordBypass()', () => {
83
- it('should record bypass trace', () => {
84
- collector.recordBypass('test', 'guideline', 'Emergency');
85
- const call = mockFs.appendFileSync.mock.calls[0];
86
- const content = JSON.parse(call[1] as string);
87
- expect(content.result).toBe('bypassed');
88
- expect(content.bypassReason).toBe('Emergency');
89
- });
90
- });
91
-
92
82
  describe('read()', () => {
93
83
  it('should return empty array if file not exists', () => {
94
84
  mockFs.existsSync.mockReturnValueOnce(true);
@@ -35,28 +35,6 @@ export function timeRangeOf(timestamps: number[]): { start: number; end: number
35
35
  };
36
36
  }
37
37
 
38
- /**
39
- * 找出出现次数最多的元素
40
- */
41
- export function findMostCommon(items: string[]): string | undefined {
42
- if (items.length === 0) return undefined;
43
-
44
- const counts = new Map<string, number>();
45
- for (const item of items) {
46
- counts.set(item, (counts.get(item) || 0) + 1);
47
- }
48
-
49
- let maxCount = 0;
50
- let mostCommon: string | undefined;
51
- for (const [item, count] of counts) {
52
- if (count > maxCount) {
53
- maxCount = count;
54
- mostCommon = item;
55
- }
56
- }
57
- return mostCommon;
58
- }
59
-
60
38
  /**
61
39
  * 平均值
62
40
  */
@@ -4,18 +4,12 @@
4
4
  * Execution Trace 系统:
5
5
  * - TraceCollector:轻量收集,零 Token
6
6
  * - TraceAnalyzer:统计汇总,异常检测
7
- * - ConstraintDoctor:Agent 诊断接口
8
7
  *
9
- * Performance Trace 系统:
10
- * - PerformanceCollector:性能日志收集,零 Token
11
- * - PerformanceAnalyzer:统计汇总,异常检测
8
+ * 上下文使用追踪:
9
+ * - ContextTracker:LLM 调用上下文快照记录
12
10
  */
13
11
 
14
- export * from './traces';
15
- export * from './trace-analyzer';
16
- export * from './constraint-doctor';
17
- export * from './performance-collector';
18
- export * from './performance-analyzer';
19
- export * from './context-tracker';
20
- export { KnowledgeDoctor } from './knowledge-doctor';
21
- export { KnowledgeEvolver } from './knowledge-evolver';
12
+ export { TraceCollector, getTraceCollector, configureTraceCollector, DEFAULT_TRACE_FILE } from './traces';
13
+ export { TraceAnalyzer, createAnalyzer } from './trace-analyzer';
14
+ export { ContextTracker } from './context-tracker';
15
+ export type { ContextAverages } from './context-tracker';
@@ -19,7 +19,6 @@ import { TraceCollector } from './traces';
19
19
  import {
20
20
  groupByKey,
21
21
  timeRangeOf,
22
- findMostCommon,
23
22
  splitByTime,
24
23
  writeSummaryJson,
25
24
  readSummaryJson,
@@ -33,9 +32,7 @@ const DEFAULT_CONFIG: TraceAnalyzerConfig = {
33
32
  summaryFile: '.harness/logs/traces-summary.json',
34
33
  periodMs: 3600 * 1000, // 1 小时
35
34
  thresholds: {
36
- bypassRate: 0.3, // 绕过率 > 30% 视为异常
37
35
  failRate: 0.5, // 失败率 > 50% 视为异常
38
- exceptionRate: 0.4, // 例外率 > 40% 视为滥用
39
36
  },
40
37
  };
41
38
 
@@ -76,13 +73,12 @@ export class TraceAnalyzer {
76
73
  // 计算时间范围
77
74
  const timeRange = timeRangeOf(group.map(t => t.timestamp));
78
75
 
79
- // 单次遍历计算核心统计(skip 单独计数,不计入 pass/fail/bypass 率分母,ADR-0001)
76
+ // 单次遍历计算核心统计(skip 单独计数,不计入 pass/fail 率分母,ADR-0001)
80
77
  const totalChecks = group.length;
81
- let passCount = 0, failCount = 0, bypassCount = 0, ignoreCount = 0, skipCount = 0;
78
+ let passCount = 0, failCount = 0, ignoreCount = 0, skipCount = 0;
82
79
  for (const t of group) {
83
80
  if (t.result === 'pass') passCount++;
84
81
  else if (t.result === 'fail') failCount++;
85
- else if (t.result === 'bypassed') bypassCount++;
86
82
  else if (t.result === 'skip') skipCount++;
87
83
  if (t.userAction === 'ignore') ignoreCount++;
88
84
  }
@@ -91,13 +87,6 @@ export class TraceAnalyzer {
91
87
  const evaluatedChecks = totalChecks - skipCount;
92
88
  const passRate = evaluatedChecks > 0 ? passCount / evaluatedChecks : 0;
93
89
  const failRate = evaluatedChecks > 0 ? failCount / evaluatedChecks : 0;
94
- const bypassRate = evaluatedChecks > 0 ? bypassCount / evaluatedChecks : 0;
95
-
96
- // 计算例外统计
97
- const exceptionTraces = group.filter(t => t.exceptionApplied);
98
- const exceptionCount = exceptionTraces.length;
99
- const exceptionTypes = exceptionTraces.map(t => t.exceptionApplied!);
100
- const mostCommonException = findMostCommon(exceptionTypes);
101
90
 
102
91
  // 计算趋势
103
92
  const recentTrend = this.calculateTrend(group);
@@ -109,15 +98,11 @@ export class TraceAnalyzer {
109
98
  totalChecks,
110
99
  passCount,
111
100
  failCount,
112
- bypassCount,
113
101
  skipCount,
114
102
  ignoreCount,
115
103
  passRate,
116
104
  failRate,
117
- bypassRate,
118
105
  recentTrend,
119
- exceptionCount,
120
- mostCommonException,
121
106
  });
122
107
  }
123
108
 
@@ -150,23 +135,6 @@ export class TraceAnalyzer {
150
135
  const thresholds = this.config.thresholds!;
151
136
 
152
137
  for (const summary of summaries) {
153
- // 检测高绕过率
154
- if (summary.bypassRate > thresholds.bypassRate!) {
155
- anomalies.push({
156
- type: 'high_bypass_rate',
157
- constraintId: summary.constraintId,
158
- level: summary.level,
159
- message: `约束 ${summary.constraintId} 绕过率 ${Math.round(summary.bypassRate * 100)}%,超过阈值 ${thresholds.bypassRate! * 100}%`,
160
- data: {
161
- currentRate: summary.bypassRate,
162
- threshold: thresholds.bypassRate!,
163
- trend: summary.recentTrend,
164
- },
165
- detectedAt: Date.now(),
166
- suggestedAction: 'diagnose',
167
- });
168
- }
169
-
170
138
  // 检测失败率上升
171
139
  if (summary.failRate > thresholds.failRate! && summary.recentTrend === 'rising') {
172
140
  anomalies.push({
@@ -184,23 +152,6 @@ export class TraceAnalyzer {
184
152
  });
185
153
  }
186
154
 
187
- // 检测绕过率上升
188
- if (summary.bypassRate > 0.1 && summary.recentTrend === 'rising') {
189
- anomalies.push({
190
- type: 'rising_bypass_rate',
191
- constraintId: summary.constraintId,
192
- level: summary.level,
193
- message: `约束 ${summary.constraintId} 绕过率 ${Math.round(summary.bypassRate * 100)}% 且趋势上升`,
194
- data: {
195
- currentRate: summary.bypassRate,
196
- threshold: 0.1,
197
- trend: 'rising',
198
- },
199
- detectedAt: Date.now(),
200
- suggestedAction: 'diagnose',
201
- });
202
- }
203
-
204
155
  // 检测低通过率
205
156
  if (summary.passRate < 0.3) {
206
157
  anomalies.push({
@@ -217,26 +168,6 @@ export class TraceAnalyzer {
217
168
  suggestedAction: 'adjust_threshold',
218
169
  });
219
170
  }
220
-
221
- // 检测例外滥用
222
- const exceptionRate = summary.totalChecks > 0
223
- ? summary.exceptionCount / summary.totalChecks
224
- : 0;
225
-
226
- if (exceptionRate > thresholds.exceptionRate!) {
227
- anomalies.push({
228
- type: 'exception_overuse',
229
- constraintId: summary.constraintId,
230
- level: summary.level,
231
- message: `约束 ${summary.constraintId} 例外使用率 ${Math.round(exceptionRate * 100)}%,可能过度依赖例外`,
232
- data: {
233
- currentRate: exceptionRate,
234
- threshold: thresholds.exceptionRate!,
235
- },
236
- detectedAt: Date.now(),
237
- suggestedAction: 'add_exception',
238
- });
239
- }
240
171
  }
241
172
 
242
173
  return anomalies;
@@ -262,7 +193,6 @@ export class TraceAnalyzer {
262
193
  summary.changeFromLastPeriod = {
263
194
  passRateDelta: summary.passRate - prev.passRate,
264
195
  failRateDelta: summary.failRate - prev.failRate,
265
- bypassRateDelta: summary.bypassRate - prev.bypassRate,
266
196
  };
267
197
  }
268
198
 
@@ -386,7 +316,6 @@ export class TraceAnalyzer {
386
316
  lines.push(` - Checks: ${summary.totalChecks}`);
387
317
  lines.push(` - Pass: ${Math.round(summary.passRate * 100)}%`);
388
318
  lines.push(` - Fail: ${Math.round(summary.failRate * 100)}%`);
389
- lines.push(` - Bypass: ${Math.round(summary.bypassRate * 100)}%`);
390
319
  lines.push(` - Trend: ${summary.recentTrend}`);
391
320
  lines.push('');
392
321
  }
@@ -117,26 +117,6 @@ export class TraceCollector {
117
117
  });
118
118
  }
119
119
 
120
- /**
121
- * 快捷方法:记录绕过
122
- */
123
- recordBypass(
124
- constraintId: string,
125
- level: 'iron_law' | 'guideline',
126
- bypassReason?: string,
127
- options?: Partial<ExecutionTrace>
128
- ): void {
129
- this.record({
130
- constraintId,
131
- level,
132
- timestamp: Date.now(),
133
- result: 'bypassed',
134
- userAction: 'bypass',
135
- bypassReason,
136
- ...options,
137
- });
138
- }
139
-
140
120
  /**
141
121
  * 批量读取 traces
142
122
  *
@@ -1,89 +1,68 @@
1
1
  /**
2
- * Tests for standard.ts — applyPreset, getPreset
2
+ * presets 纯数据测试
3
3
  *
4
- * Pure logic, no I/O — tests preset selection and constraint filtering.
4
+ * 预设只保留数据(ADR-0001:筛选逻辑统一在 mergeConstraints),
5
+ * 这里锁定数据形状与 strict→standard 别名语义。
5
6
  */
6
7
 
7
- import { applyPreset, getPreset } from '../standard';
8
+ import {
9
+ STRICT_PRESET,
10
+ STANDARD_PRESET,
11
+ RELAXED_PRESET,
12
+ PRESETS_BY_NAME,
13
+ } from '../standard';
8
14
 
9
- describe('getPreset', () => {
10
- it('returns strict preset', () => {
11
- const preset = getPreset('strict');
12
- expect(preset.name).toBe('strict');
13
- expect(preset.ironLaws).toBeNull();
14
- expect(preset.guidelines).toBeNull();
15
- expect(preset.prompts).toBeNull();
16
- });
17
-
18
- it('returns standard preset', () => {
19
- const preset = getPreset('standard');
20
- expect(preset.name).toBe('standard');
15
+ describe('预设数据', () => {
16
+ describe('STRICT_PRESET', () => {
17
+ it('应该启用所有约束', () => {
18
+ expect(STRICT_PRESET.name).toBe('strict');
19
+ expect(STRICT_PRESET.ironLaws).toBeNull();
20
+ expect(STRICT_PRESET.guidelines).toBeNull();
21
+ expect(STRICT_PRESET.prompts).toBeNull();
22
+ });
21
23
  });
22
24
 
23
- it('returns relaxed preset', () => {
24
- const preset = getPreset('relaxed');
25
- expect(preset.name).toBe('relaxed');
26
- expect(preset.ironLaws).toHaveLength(3);
27
- expect(preset.guidelines).toHaveLength(2);
28
- expect(preset.prompts).toEqual([]);
25
+ describe('STANDARD_PRESET', () => {
26
+ it('应该启用所有约束', () => {
27
+ expect(STANDARD_PRESET.name).toBe('standard');
28
+ expect(STANDARD_PRESET.ironLaws).toBeNull();
29
+ expect(STANDARD_PRESET.guidelines).toBeNull();
30
+ expect(STANDARD_PRESET.prompts).toBeNull();
31
+ });
29
32
  });
30
33
 
31
- it('defaults to standard for unknown preset name', () => {
32
- const preset = getPreset('unknown' as any);
33
- expect(preset.name).toBe('standard');
34
- });
35
- });
34
+ describe('RELAXED_PRESET', () => {
35
+ it('应该只启用核心约束', () => {
36
+ expect(RELAXED_PRESET.name).toBe('relaxed');
37
+ expect(RELAXED_PRESET.ironLaws).toHaveLength(3);
38
+ expect(RELAXED_PRESET.guidelines).toHaveLength(2);
39
+ expect(RELAXED_PRESET.prompts).toEqual([]);
40
+ });
36
41
 
37
- describe('applyPreset with string preset names', () => {
38
- it('strict enables all iron laws and guidelines', () => {
39
- const config = applyPreset('strict');
40
- expect(config.ironLaws).toBeDefined();
41
- expect(Object.keys(config.ironLaws).length).toBeGreaterThan(0);
42
- expect(config.guidelines).toBeDefined();
43
- expect(Object.keys(config.guidelines).length).toBeGreaterThan(0);
44
- expect(config.disabled).toEqual([]);
45
- });
42
+ it('应该包含 no_completion_without_verification', () => {
43
+ expect(RELAXED_PRESET.ironLaws).toContain('no_completion_without_verification');
44
+ });
46
45
 
47
- it('relaxed enables only specific constraints', () => {
48
- const config = applyPreset('relaxed');
49
- expect(config.ironLaws).toBeDefined();
50
- expect(config.ironLaws.no_completion_without_verification).toBeDefined();
51
- expect(Object.keys(config.prompts ?? {}).length).toBe(0);
52
- expect(config.disabled.length).toBeGreaterThan(0);
46
+ it('应该包含 no_bypass_checkpoint', () => {
47
+ expect(RELAXED_PRESET.guidelines).toContain('no_bypass_checkpoint');
48
+ });
53
49
  });
54
- });
55
50
 
56
- describe('applyPreset with PresetConfig object', () => {
57
- it('filters iron laws when ids are provided', () => {
58
- const config = applyPreset({
59
- name: 'custom',
60
- ironLaws: ['no_completion_without_verification', 'incremental_progress'],
61
- guidelines: null,
62
- prompts: null,
51
+ describe('PRESETS_BY_NAME', () => {
52
+ it('strict standard 的别名(同为全部启用)', () => {
53
+ expect(PRESETS_BY_NAME['strict']?.ironLaws).toBeNull();
54
+ expect(PRESETS_BY_NAME['strict']?.guidelines).toBeNull();
55
+ expect(PRESETS_BY_NAME['strict']?.prompts).toBeNull();
63
56
  });
64
- expect(Object.keys(config.ironLaws)).toHaveLength(2);
65
- expect(config.ironLaws.no_completion_without_verification).toBeDefined();
66
- expect(config.ironLaws.no_implementation_without_requirement).toBeUndefined();
67
- });
68
57
 
69
- it('includes all guidelines when null', () => {
70
- const config = applyPreset({
71
- name: 'custom',
72
- ironLaws: null,
73
- guidelines: null,
74
- prompts: [],
58
+ it('三个预设名均可解析', () => {
59
+ expect(PRESETS_BY_NAME['strict']).toBe(STRICT_PRESET);
60
+ expect(PRESETS_BY_NAME['standard']).toBe(STANDARD_PRESET);
61
+ expect(PRESETS_BY_NAME['relaxed']).toBe(RELAXED_PRESET);
75
62
  });
76
- expect(Object.keys(config.guidelines).length).toBeGreaterThan(0);
77
- expect(Object.keys(config.prompts ?? {}).length).toBe(0);
78
- });
79
63
 
80
- it('creates disabled list for omitted constraints', () => {
81
- const config = applyPreset({
82
- name: 'custom',
83
- ironLaws: [],
84
- guidelines: [],
85
- prompts: [],
64
+ it('未知预设名不在表中(由 mergeConstraints 回落 standard)', () => {
65
+ expect(PRESETS_BY_NAME['unknown']).toBeUndefined();
86
66
  });
87
- expect(config.disabled.length).toBeGreaterThan(0);
88
67
  });
89
68
  });
@@ -1,14 +1,12 @@
1
1
  /**
2
- * 预设模块入口
2
+ * 预设模块入口(纯数据,ADR-0001:筛选逻辑统一在 mergeConstraints)
3
3
  */
4
4
 
5
5
  export {
6
6
  STRICT_PRESET,
7
7
  STANDARD_PRESET,
8
8
  RELAXED_PRESET,
9
- getPreset,
10
- applyPreset,
11
-
9
+ PRESETS_BY_NAME,
12
10
  } from './standard';
13
11
 
14
- export type { PresetConfig } from './standard';
12
+ export type { PresetConfig } from './standard';
@@ -1,15 +1,13 @@
1
1
  /**
2
- * 约束预设
2
+ * 约束预设(纯数据)
3
3
  *
4
- * 预设定义哪些约束被启用
4
+ * 预设定义哪些内置约束被启用。筛选与合并逻辑统一在
5
+ * core/project-config-loader.ts 的 mergeConstraints(ADR-0001 生效集链路),
6
+ * 本文件只保留预设数据,不再含函数。
5
7
  *
6
8
  * ADR-0001:kind 二元(check + prompt 纯注入层)。
7
9
  */
8
10
 
9
- import type { Constraint } from '../types/constraint';
10
- import type { MergedConstraintsConfig } from '../types/project-config';
11
- import { IRON_LAWS, GUIDELINES, PROMPTS } from '../core/constraints/definitions';
12
-
13
11
  /**
14
12
  * 预设配置
15
13
  */
@@ -27,69 +25,10 @@ export interface PresetConfig {
27
25
  prompts: string[] | null;
28
26
  }
29
27
 
30
- /**
31
- * 应用预设,生成 MergedConstraintsConfig(S12)
32
- *
33
- * 将 PresetConfig 转换为 ConstraintChecker.checkConstraints() 所需的 customConfig。
34
- * 支持 per-request 预设切换,不再局限于 CLI。
35
- *
36
- * @param preset 预设名称('strict' | 'standard' | 'relaxed')或 PresetConfig 对象
37
- * @returns 可直接传入 checkConstraints() 的 merged config
38
- *
39
- * 用法:
40
- * ```typescript
41
- * const config = applyPreset('relaxed');
42
- * await checker.checkConstraints(ctx, config);
43
- * ```
44
- */
45
- export function applyPreset(
46
- preset: string | PresetConfig
47
- ): MergedConstraintsConfig {
48
- const cfg = typeof preset === 'string' ? getPreset(preset) : preset;
49
-
50
- const filterByIds = (
51
- source: Record<string, Constraint>,
52
- ids: string[] | null,
53
- ): Record<string, Constraint> => {
54
- if (ids === null) return { ...source };
55
- const filtered: Record<string, Constraint> = {};
56
- for (const id of ids) {
57
- if (source[id]) filtered[id] = source[id];
58
- }
59
- return filtered;
60
- };
61
-
62
- const disabled: string[] = [];
63
- if (cfg.ironLaws !== null) {
64
- for (const id of Object.keys(IRON_LAWS)) {
65
- if (!cfg.ironLaws.includes(id)) disabled.push(id);
66
- }
67
- }
68
- if (cfg.guidelines !== null) {
69
- for (const id of Object.keys(GUIDELINES)) {
70
- if (!cfg.guidelines.includes(id)) disabled.push(id);
71
- }
72
- }
73
- if (cfg.prompts !== null) {
74
- for (const id of Object.keys(PROMPTS)) {
75
- if (!cfg.prompts.includes(id)) disabled.push(id);
76
- }
77
- }
78
-
79
- return {
80
- ironLaws: filterByIds(IRON_LAWS, cfg.ironLaws),
81
- guidelines: filterByIds(GUIDELINES, cfg.guidelines),
82
- prompts: filterByIds(PROMPTS, cfg.prompts),
83
- disabled,
84
- custom: [],
85
- unknownIds: [],
86
- };
87
- }
88
-
89
28
  /**
90
29
  * 严格预设
91
30
  *
92
- * 所有约束全部启用
31
+ * 所有约束全部启用(与 standard 同集,保留别名兼容历史配置)
93
32
  */
94
33
  export const STRICT_PRESET: PresetConfig = {
95
34
  name: 'strict',
@@ -130,17 +69,13 @@ export const RELAXED_PRESET: PresetConfig = {
130
69
  };
131
70
 
132
71
  /**
133
- * 获取预设
72
+ * 预设名 → 预设数据
73
+ *
74
+ * strict 是 standard 的别名(两者同为全部启用)。未知名不在此表,
75
+ * 由 mergeConstraints 回落 standard + stderr 警告。
134
76
  */
135
- export function getPreset(name: string): PresetConfig {
136
- switch (name) {
137
- case 'strict':
138
- return STRICT_PRESET;
139
- case 'standard':
140
- return STANDARD_PRESET;
141
- case 'relaxed':
142
- return RELAXED_PRESET;
143
- default:
144
- return STANDARD_PRESET;
145
- }
146
- }
77
+ export const PRESETS_BY_NAME: Record<string, PresetConfig> = {
78
+ strict: STRICT_PRESET,
79
+ standard: STANDARD_PRESET,
80
+ relaxed: RELAXED_PRESET,
81
+ };
@@ -1,19 +1,11 @@
1
1
  # spec/
2
2
 
3
3
  ## 职责
4
- 代码注释规范检查:验证代码中的 @spec 注释是否符合规范。
4
+ (空目录)原 @spec 注释规范检查(annotation-checker)已随 ADR-0003 删除。
5
5
 
6
- ## 核心导出
7
- - `annotation-checker.ts` — AnnotationChecker: 检查 @spec 注释规范(有效/无效/警告)
8
-
9
- ## 依赖关系
10
- - 依赖 `fs` / `path` 文件系统操作
11
- - 被 `src/cli/commands/spec.ts` CLI 命令消费
12
-
13
- ## 约定
14
- - Spec 注释格式由 @spec 标签定义
15
- - 检查结果包含 valid: boolean + errors + warnings
6
+ ## 已接线的 spec 故事
7
+ - `src/core/spec/validator.ts` — SpecValidator:spec 文档结构/内容验证(CLI `harness spec` 消费)
8
+ - `src/gates/acceptance.ts` — SpecAcceptanceGate:验收标准门禁
16
9
 
17
10
  ## 注意事项
18
- - index.ts 统一导出,独立模块导入
19
- - 扫描指定目录下所有 TS 文件的 @spec 注释
11
+ - @spec 注释检查若需恢复,应迁移为 ConstraintCheck 注册进闭环注册表(ADR-0003 后续立项),不在本目录重建独立子系统