@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
@@ -1,276 +0,0 @@
1
- /**
2
- * PerformanceCollector 测试
3
- */
4
-
5
- import { describe, it, expect, beforeAll, afterAll, beforeEach } from '@jest/globals';
6
- import { PerformanceCollector } from '../monitoring/performance-collector';
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
-
10
- describe('PerformanceCollector', () => {
11
- const tempDir = path.join(process.cwd(), 'temp-test-perf');
12
- const logFile = path.join(tempDir, 'performance.log');
13
- let collector: PerformanceCollector;
14
-
15
- beforeAll(() => {
16
- fs.mkdirSync(tempDir, { recursive: true });
17
- });
18
-
19
- afterAll(() => {
20
- try {
21
- fs.rmSync(tempDir, { recursive: true, force: true });
22
- } catch {
23
- // ignore
24
- }
25
- });
26
-
27
- beforeEach(() => {
28
- fs.writeFileSync(logFile, '');
29
- collector = new PerformanceCollector({ logFile, enabled: true });
30
- });
31
-
32
- describe('record', () => {
33
- it('应该记录性能数据', () => {
34
- collector.record({
35
- operation: 'test_op',
36
- timestamp: Date.now(),
37
- duration: 100,
38
- result: 'ok',
39
- });
40
-
41
- const content = fs.readFileSync(logFile, 'utf-8');
42
- expect(content).toContain('test_op');
43
- expect(content).toContain('ok');
44
- });
45
-
46
- it('禁用时应该不记录', () => {
47
- const disabledCollector = new PerformanceCollector({
48
- logFile,
49
- enabled: false,
50
- });
51
-
52
- disabledCollector.record({
53
- operation: 'test',
54
- timestamp: Date.now(),
55
- duration: 100,
56
- result: 'ok',
57
- });
58
-
59
- const content = fs.readFileSync(logFile, 'utf-8');
60
- expect(content).toBe('');
61
- });
62
- });
63
-
64
- describe('recordOk', () => {
65
- it('应该记录正常执行', () => {
66
- collector.recordOk('extract', 150);
67
-
68
- const content = fs.readFileSync(logFile, 'utf-8');
69
- expect(content).toContain('extract');
70
- expect(content).toContain('150');
71
- expect(content).toContain('ok');
72
- });
73
-
74
- it('应该支持元数据', () => {
75
- collector.recordOk('extract', 150, { files: 10 });
76
-
77
- const content = fs.readFileSync(logFile, 'utf-8');
78
- expect(content).toContain('files');
79
- });
80
- });
81
-
82
- describe('recordExceeded', () => {
83
- it('应该记录超阈值执行', () => {
84
- collector.recordExceeded('invokeAgent', 35000, 30000);
85
-
86
- const content = fs.readFileSync(logFile, 'utf-8');
87
- expect(content).toContain('invokeAgent');
88
- expect(content).toContain('exceeded');
89
- expect(content).toContain('35000');
90
- });
91
- });
92
-
93
- describe('read', () => {
94
- it('应该读取性能数据', () => {
95
- collector.recordOk('op1', 100);
96
- collector.recordOk('op2', 200);
97
-
98
- const traces = collector.read();
99
- expect(traces.length).toBe(2);
100
- });
101
-
102
- it('空文件应该返回空数组', () => {
103
- fs.writeFileSync(logFile, '');
104
- const traces = collector.read();
105
- expect(traces).toEqual([]);
106
- });
107
- });
108
-
109
- describe('getStats', () => {
110
- it('应该返回统计信息', () => {
111
- collector.recordOk('op1', 100);
112
- collector.recordOk('op2', 200);
113
- collector.recordExceeded('op3', 500, 400);
114
-
115
- const stats = collector.getStats();
116
-
117
- expect(stats.totalRecords).toBe(3);
118
- });
119
-
120
- it('应该正确读取数据', () => {
121
- collector.recordOk('op1', 100);
122
- collector.recordOk('op2', 200);
123
-
124
- const traces = collector.read();
125
-
126
- expect(traces.length).toBe(2);
127
- });
128
-
129
- it('文件不存在时应该返回空统计', () => {
130
- fs.unlinkSync(logFile);
131
- const tmpFile = path.join(require('os').tmpdir(), 'harness-test-nonexistent', 'perf.log');
132
- const newCollector = new PerformanceCollector({ logFile: tmpFile });
133
-
134
- const stats = newCollector.getStats();
135
-
136
- expect(stats.fileExists).toBe(false);
137
- expect(stats.totalRecords).toBe(0);
138
- });
139
- });
140
-
141
- describe('recordError', () => {
142
- it('应该记录错误', () => {
143
- collector.recordError('failing-op', 100, 'Something went wrong');
144
-
145
- const content = fs.readFileSync(logFile, 'utf-8');
146
- expect(content).toContain('error');
147
- expect(content).toContain('Something went wrong');
148
- });
149
-
150
- it('应该支持 Error 对象', () => {
151
- collector.recordError('failing-op', 100, new Error('Test error'));
152
-
153
- const content = fs.readFileSync(logFile, 'utf-8');
154
- expect(content).toContain('Test error');
155
- });
156
-
157
- it('应该支持元数据', () => {
158
- collector.recordError('failing-op', 100, 'Error', { retryCount: 3 });
159
-
160
- const content = fs.readFileSync(logFile, 'utf-8');
161
- expect(content).toContain('retryCount');
162
- });
163
- });
164
-
165
- describe('readRecent', () => {
166
- it('应该读取最近 N 小时的数据', () => {
167
- collector.recordOk('recent-op', 100);
168
-
169
- const traces = collector.readRecent(1);
170
- expect(traces.length).toBe(1);
171
- });
172
- });
173
-
174
- describe('readByOperation', () => {
175
- it('应该过滤特定操作', () => {
176
- collector.recordOk('op1', 100);
177
- collector.recordOk('op2', 200);
178
- collector.recordOk('op1', 150);
179
-
180
- const traces = collector.readByOperation('op1');
181
- expect(traces.length).toBe(2);
182
- });
183
- });
184
-
185
- describe('过滤条件', () => {
186
- it('应该按时间范围过滤', () => {
187
- const now = Date.now();
188
- collector.record({ operation: 'old', timestamp: now - 100000, duration: 100, result: 'ok' });
189
- collector.record({ operation: 'new', timestamp: now, duration: 100, result: 'ok' });
190
-
191
- const traces = collector.read({
192
- timeRange: { start: now - 50000, end: now + 1000 },
193
- });
194
-
195
- expect(traces.length).toBe(1);
196
- expect(traces[0]?.operation).toBe('new');
197
- });
198
-
199
- it('应该按结果类型过滤', () => {
200
- collector.recordOk('ok-op', 100);
201
- collector.recordError('err-op', 200, 'error');
202
-
203
- const traces = collector.read({ result: 'error' });
204
- expect(traces.length).toBe(1);
205
- expect(traces[0]?.operation).toBe('err-op');
206
- });
207
-
208
- it('应该按项目路径过滤', () => {
209
- collector.record({ operation: 'op1', timestamp: Date.now(), duration: 100, result: 'ok', projectPath: '/project1' });
210
- collector.record({ operation: 'op2', timestamp: Date.now(), duration: 100, result: 'ok', projectPath: '/project2' });
211
-
212
- const traces = collector.read({ projectPath: '/project1' });
213
- expect(traces.length).toBe(1);
214
- });
215
-
216
- it('应该按会话 ID 过滤', () => {
217
- collector.record({ operation: 'op1', timestamp: Date.now(), duration: 100, result: 'ok', sessionId: 'session-1' });
218
- collector.record({ operation: 'op2', timestamp: Date.now(), duration: 100, result: 'ok', sessionId: 'session-2' });
219
-
220
- const traces = collector.read({ sessionId: 'session-1' });
221
- expect(traces.length).toBe(1);
222
- });
223
-
224
- it('应该按任务 ID 过滤', () => {
225
- collector.record({ operation: 'op1', timestamp: Date.now(), duration: 100, result: 'ok', taskId: 'task-1' });
226
- collector.record({ operation: 'op2', timestamp: Date.now(), duration: 100, result: 'ok', taskId: 'task-2' });
227
-
228
- const traces = collector.read({ taskId: 'task-1' });
229
- expect(traces.length).toBe(1);
230
- });
231
-
232
- it('应该按角色 ID 过滤', () => {
233
- collector.record({ operation: 'op1', timestamp: Date.now(), duration: 100, result: 'ok', roleId: 'role-1' });
234
- collector.record({ operation: 'op2', timestamp: Date.now(), duration: 100, result: 'ok', roleId: 'role-2' });
235
-
236
- const traces = collector.read({ roleId: 'role-1' });
237
- expect(traces.length).toBe(1);
238
- });
239
- });
240
-
241
- describe('cleanupOldFiles', () => {
242
- it('应该清理旧备份文件', () => {
243
- // 创建一些备份文件(模拟滚动)
244
- const backupFile = logFile.replace('.log', '-2026-01-01.log');
245
- fs.writeFileSync(backupFile, 'old data');
246
-
247
- // 由于文件是新建的,需要修改 mtime
248
- // 简单验证函数运行不崩溃
249
- const deleted = collector.cleanupOldFiles(0);
250
- expect(deleted).toBeGreaterThanOrEqual(0);
251
-
252
- // 清理备份文件
253
- try { fs.unlinkSync(backupFile); } catch {}
254
- });
255
-
256
- it('不存在目录时应该返回 0', () => {
257
- // 创建新的 collector,使用临时目录
258
- const nonexistentDir = path.join(process.cwd(), 'temp-nonexistent-perf');
259
- const nonexistentLogFile = path.join(nonexistentDir, 'perf.log');
260
- const newCollector = new PerformanceCollector({ logFile: nonexistentLogFile });
261
-
262
- const deleted = newCollector.cleanupOldFiles(30);
263
- expect(deleted).toBe(0);
264
- });
265
- });
266
-
267
- describe('文件滚动', () => {
268
- it('应该检查文件大小', () => {
269
- // 创建大文件触发滚动检查
270
- collector.recordOk('test', 100);
271
-
272
- // 文件应该存在
273
- expect(fs.existsSync(logFile)).toBe(true);
274
- });
275
- });
276
- });
@@ -1,65 +0,0 @@
1
- /**
2
- * presets 测试
3
- */
4
-
5
- import { describe, it, expect } from '@jest/globals';
6
- import { STRICT_PRESET, STANDARD_PRESET, RELAXED_PRESET, getPreset } from '../presets/standard';
7
-
8
- describe('Presets', () => {
9
- describe('STRICT_PRESET', () => {
10
- it('应该启用所有约束', () => {
11
- expect(STRICT_PRESET.name).toBe('strict');
12
- expect(STRICT_PRESET.ironLaws).toBeNull();
13
- expect(STRICT_PRESET.guidelines).toBeNull();
14
- expect(STRICT_PRESET.prompts).toBeNull();
15
- });
16
- });
17
-
18
- describe('STANDARD_PRESET', () => {
19
- it('应该启用所有约束', () => {
20
- expect(STANDARD_PRESET.name).toBe('standard');
21
- expect(STANDARD_PRESET.ironLaws).toBeNull();
22
- expect(STANDARD_PRESET.guidelines).toBeNull();
23
- expect(STANDARD_PRESET.prompts).toBeNull();
24
- });
25
- });
26
-
27
- describe('RELAXED_PRESET', () => {
28
- it('应该只启用核心约束', () => {
29
- expect(RELAXED_PRESET.name).toBe('relaxed');
30
- expect(RELAXED_PRESET.ironLaws).not.toBeNull();
31
- expect(RELAXED_PRESET.guidelines).not.toBeNull();
32
- expect(RELAXED_PRESET.prompts).toEqual([]);
33
- });
34
-
35
- it('应该包含 no_completion_without_verification', () => {
36
- expect(RELAXED_PRESET.ironLaws).toContain('no_completion_without_verification');
37
- });
38
-
39
- it('应该包含 no_bypass_checkpoint', () => {
40
- expect(RELAXED_PRESET.guidelines).toContain('no_bypass_checkpoint');
41
- });
42
- });
43
-
44
- describe('getPreset', () => {
45
- it('应该返回 strict 预设', () => {
46
- const preset = getPreset('strict');
47
- expect(preset.name).toBe('strict');
48
- });
49
-
50
- it('应该返回 standard 预设', () => {
51
- const preset = getPreset('standard');
52
- expect(preset.name).toBe('standard');
53
- });
54
-
55
- it('应该返回 relaxed 预设', () => {
56
- const preset = getPreset('relaxed');
57
- expect(preset.name).toBe('relaxed');
58
- });
59
-
60
- it('未知预设应该返回 standard', () => {
61
- const preset = getPreset('unknown');
62
- expect(preset.name).toBe('standard');
63
- });
64
- });
65
- });
@@ -1,267 +0,0 @@
1
- /**
2
- * ConstraintInterceptor 测试
3
- */
4
-
5
- import { ConstraintInterceptor } from '../interceptor';
6
- import { constraintChecker } from '../checker';
7
- import type { ConstraintContext } from '../../../types/constraint';
8
- import type { EnforcementExecutor } from '../../../types/enforcement';
9
-
10
- // Mock constraintChecker
11
- jest.mock('../checker', () => ({
12
- constraintChecker: {
13
- getConstraints: jest.fn(),
14
- check: jest.fn().mockResolvedValue({ satisfied: true }),
15
- },
16
- }));
17
-
18
- const mockChecker = constraintChecker as jest.Mocked<typeof constraintChecker>;
19
-
20
- describe('ConstraintInterceptor', () => {
21
- let interceptor: ConstraintInterceptor;
22
-
23
- const mockCheck = jest.fn().mockResolvedValue({ satisfied: true });
24
-
25
- const mockIronLaw = {
26
- id: 'test_iron_law',
27
- kind: 'check' as const,
28
- rule: 'Test Iron Law',
29
- message: 'Test iron law message',
30
- level: 'iron_law' as const,
31
- trigger: 'code_implementation',
32
- enforcement: 'test-enforcement',
33
- check: mockCheck,
34
- };
35
-
36
- const mockGuideline = {
37
- id: 'test_guideline',
38
- kind: 'check' as const,
39
- rule: 'Test Guideline',
40
- message: 'Test guideline message',
41
- level: 'guideline' as const,
42
- trigger: 'code_implementation',
43
- enforcement: 'guideline-enforcement',
44
- check: mockCheck,
45
- };
46
-
47
- const mockContext: ConstraintContext = {
48
- operation: 'code_implementation',
49
- projectPath: '/test',
50
- };
51
-
52
- const mockExecutor: EnforcementExecutor = {
53
- execute: jest.fn(),
54
- };
55
-
56
- beforeEach(() => {
57
- jest.clearAllMocks();
58
- // Use the singleton instance
59
- interceptor = ConstraintInterceptor.getInstance();
60
- // Clear any previous state
61
- interceptor.clearSkips();
62
- interceptor.setEnabled(true);
63
-
64
- mockChecker.getConstraints.mockReturnValue({
65
- ironLaws: { test_iron_law: mockIronLaw },
66
- guidelines: { test_guideline: mockGuideline },
67
- prompts: {},
68
- });
69
- });
70
-
71
- describe('getInstance', () => {
72
- it('should return singleton instance', () => {
73
- const instance1 = ConstraintInterceptor.getInstance();
74
- const instance2 = ConstraintInterceptor.getInstance();
75
- expect(instance1).toBe(instance2);
76
- });
77
- });
78
-
79
- describe('register', () => {
80
- it('should register executor', () => {
81
- interceptor.register('test-enforcement', mockExecutor);
82
- expect(interceptor.hasExecutor('test-enforcement')).toBe(true);
83
- });
84
- });
85
-
86
- describe('registerBatch', () => {
87
- it('should register multiple executors', () => {
88
- interceptor.registerBatch([
89
- { enforcementId: 'exec1', executor: mockExecutor },
90
- { enforcementId: 'exec2', executor: mockExecutor },
91
- ]);
92
- expect(interceptor.hasExecutor('exec1')).toBe(true);
93
- expect(interceptor.hasExecutor('exec2')).toBe(true);
94
- });
95
- });
96
-
97
- describe('unregister', () => {
98
- it('should unregister executor', () => {
99
- interceptor.register('test-enforcement', mockExecutor);
100
- const result = interceptor.unregister('test-enforcement');
101
- expect(result).toBe(true);
102
- expect(interceptor.hasExecutor('test-enforcement')).toBe(false);
103
- });
104
-
105
- it('should return false if not exists', () => {
106
- const result = interceptor.unregister('nonexistent');
107
- expect(result).toBe(false);
108
- });
109
- });
110
-
111
- describe('getExecutor', () => {
112
- it('should return registered executor', () => {
113
- interceptor.register('test-enforcement', mockExecutor);
114
- const executor = interceptor.getExecutor('test-enforcement');
115
- expect(executor).toBe(mockExecutor);
116
- });
117
-
118
- it('should return undefined if not registered', () => {
119
- const executor = interceptor.getExecutor('nonexistent');
120
- expect(executor).toBeUndefined();
121
- });
122
- });
123
-
124
- describe('getRegistrations', () => {
125
- it('should return all registrations', () => {
126
- interceptor.unregister('test-enforcement'); // Clear any existing
127
- interceptor.register('test-enforcement', mockExecutor);
128
- const registrations = interceptor.getRegistrations();
129
- const found = registrations.find(r => r.id === 'test-enforcement');
130
- expect(found).toBeDefined();
131
- });
132
- });
133
-
134
- describe('setEnabled', () => {
135
- it('should disable interceptor', () => {
136
- interceptor.setEnabled(false);
137
- interceptor.register('test-enforcement', mockExecutor);
138
-
139
- const result = interceptor.intercept('code_implementation', mockContext);
140
- // When disabled, should pass without checking
141
- expect(result).resolves.toHaveProperty('passed', true);
142
- });
143
- });
144
-
145
- describe('skip', () => {
146
- it('should skip specified enforcements', async () => {
147
- interceptor.register('test-enforcement', mockExecutor);
148
- interceptor.skip(['test-enforcement']);
149
-
150
- const result = await interceptor.intercept('code_implementation', mockContext);
151
- expect(result.constraints.some(c => c.skipped)).toBe(true);
152
- });
153
- });
154
-
155
- describe('clearSkips', () => {
156
- it('should clear all skips', async () => {
157
- interceptor.register('test-enforcement', mockExecutor);
158
- interceptor.skip(['test-enforcement']);
159
- interceptor.clearSkips();
160
-
161
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: true });
162
- await interceptor.intercept('code_implementation', mockContext);
163
- expect(mockExecutor.execute).toHaveBeenCalled();
164
- });
165
- });
166
-
167
- describe('intercept', () => {
168
- it('should pass when all constraints satisfied', async () => {
169
- interceptor.register('test-enforcement', mockExecutor);
170
- interceptor.register('guideline-enforcement', mockExecutor);
171
-
172
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: true });
173
-
174
- const result = await interceptor.intercept('code_implementation', mockContext);
175
- expect(result.passed).toBe(true);
176
- expect(result.violations.length).toBe(0);
177
- });
178
-
179
- it('should fail on iron law violation', async () => {
180
- interceptor.register('test-enforcement', mockExecutor);
181
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: false });
182
-
183
- await expect(interceptor.intercept('code_implementation', mockContext)).rejects.toThrow();
184
- });
185
-
186
- it('should record guideline violation without throwing', async () => {
187
- interceptor.register('test-enforcement', mockExecutor);
188
- interceptor.register('guideline-enforcement', mockExecutor);
189
-
190
- (mockExecutor.execute as jest.Mock)
191
- .mockResolvedValueOnce({ passed: true }) // iron law passes
192
- .mockResolvedValueOnce({ passed: false }); // guideline fails
193
-
194
- const result = await interceptor.intercept('code_implementation', mockContext);
195
- expect(result.passed).toBe(true); // guidelines don't block
196
- expect(result.violations.length).toBe(1);
197
- });
198
-
199
- it('should handle missing executor', async () => {
200
- // No constraints at all
201
- mockChecker.getConstraints.mockReturnValue({
202
- ironLaws: {},
203
- guidelines: {},
204
- prompts: {},
205
- });
206
-
207
- const result = await interceptor.intercept('code_implementation', mockContext);
208
- expect(result.passed).toBe(true);
209
- expect(result.constraints.length).toBe(0);
210
- });
211
-
212
- it('should handle executor error for iron law', async () => {
213
- interceptor.register('test-enforcement', mockExecutor);
214
- (mockExecutor.execute as jest.Mock).mockRejectedValue(new Error('Executor error'));
215
-
216
- await expect(interceptor.intercept('code_implementation', mockContext)).rejects.toThrow();
217
- });
218
-
219
- it('should forward customConfig to checker.getConstraints', async () => {
220
- interceptor.register('test-enforcement', mockExecutor);
221
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: true });
222
-
223
- const customConfig = {
224
- ironLaws: { test_iron_law: mockIronLaw },
225
- guidelines: {},
226
- prompts: {},
227
- } as any;
228
-
229
- await interceptor.intercept('code_implementation', mockContext, customConfig);
230
- expect(mockChecker.getConstraints).toHaveBeenCalledWith(customConfig);
231
- });
232
- });
233
-
234
- describe('claim', () => {
235
- it('should pass when constraints satisfied', async () => {
236
- interceptor.register('test-enforcement', mockExecutor);
237
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: true });
238
-
239
- await expect(interceptor.claim('code_implementation', mockContext)).resolves.not.toThrow();
240
- });
241
-
242
- it('should throw on violation', async () => {
243
- interceptor.register('test-enforcement', mockExecutor);
244
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: false });
245
-
246
- await expect(interceptor.claim('code_implementation', mockContext)).rejects.toThrow();
247
- });
248
- });
249
-
250
- describe('canProceed', () => {
251
- it('should return true when passed', async () => {
252
- interceptor.register('test-enforcement', mockExecutor);
253
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: true });
254
-
255
- const result = await interceptor.canProceed('code_implementation', mockContext);
256
- expect(result).toBe(true);
257
- });
258
-
259
- it('should return false on error', async () => {
260
- interceptor.register('test-enforcement', mockExecutor);
261
- (mockExecutor.execute as jest.Mock).mockRejectedValue(new Error('Error'));
262
-
263
- const result = await interceptor.canProceed('code_implementation', mockContext);
264
- expect(result).toBe(false);
265
- });
266
- });
267
- });