@dommaker/harness 0.19.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/bin/harness.js +136 -557
  3. package/dist/cli/commands/check.d.ts.map +1 -1
  4. package/dist/cli/commands/check.js +2 -13
  5. package/dist/cli/commands/check.js.map +1 -1
  6. package/dist/cli/commands/definitions.d.ts +90 -0
  7. package/dist/cli/commands/definitions.d.ts.map +1 -0
  8. package/dist/cli/commands/definitions.js +519 -0
  9. package/dist/cli/commands/definitions.js.map +1 -0
  10. package/dist/cli/commands/knowledge.js.map +1 -1
  11. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts +3 -25
  12. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts.map +1 -1
  13. package/dist/cli/commands/sync-docs/capabilities-syncer.js +3 -93
  14. package/dist/cli/commands/sync-docs/capabilities-syncer.js.map +1 -1
  15. package/dist/cli/commands/sync-docs/index.d.ts +1 -1
  16. package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
  17. package/dist/cli/commands/sync-docs/index.js +4 -4
  18. package/dist/cli/commands/sync-docs/index.js.map +1 -1
  19. package/dist/context/index.d.ts +1 -5
  20. package/dist/context/index.d.ts.map +1 -1
  21. package/dist/context/index.js +1 -5
  22. package/dist/context/index.js.map +1 -1
  23. package/dist/context/knowledge-injector.d.ts +3 -3
  24. package/dist/context/knowledge-injector.d.ts.map +1 -1
  25. package/dist/context/knowledge-injector.js +1 -1
  26. package/dist/context/session-manager.d.ts +1 -12
  27. package/dist/context/session-manager.d.ts.map +1 -1
  28. package/dist/context/session-manager.js +0 -63
  29. package/dist/context/session-manager.js.map +1 -1
  30. package/dist/context/types.d.ts +1 -39
  31. package/dist/context/types.d.ts.map +1 -1
  32. package/dist/context/types.js +2 -15
  33. package/dist/context/types.js.map +1 -1
  34. package/dist/core/constraints/agent-prompt-renderer.d.ts +1 -1
  35. package/dist/core/constraints/agent-prompt-renderer.js +1 -1
  36. package/dist/core/constraints/capabilities-parser.d.ts +17 -2
  37. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  38. package/dist/core/constraints/capabilities-parser.js +84 -2
  39. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  40. package/dist/core/constraints/checker.d.ts +3 -17
  41. package/dist/core/constraints/checker.d.ts.map +1 -1
  42. package/dist/core/constraints/checker.js +7 -47
  43. package/dist/core/constraints/checker.js.map +1 -1
  44. package/dist/core/constraints/definitions.d.ts +0 -7
  45. package/dist/core/constraints/definitions.d.ts.map +1 -1
  46. package/dist/core/constraints/definitions.js +1 -8
  47. package/dist/core/constraints/definitions.js.map +1 -1
  48. package/dist/core/constraints/doc-freshness/runner.d.ts +0 -2
  49. package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
  50. package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
  51. package/dist/core/constraints/index.d.ts +1 -1
  52. package/dist/core/constraints/index.d.ts.map +1 -1
  53. package/dist/core/constraints/index.js +2 -3
  54. package/dist/core/constraints/index.js.map +1 -1
  55. package/dist/core/constraints/interceptor.d.ts.map +1 -1
  56. package/dist/core/constraints/interceptor.js +1 -5
  57. package/dist/core/constraints/interceptor.js.map +1 -1
  58. package/dist/core/effective-constraints.d.ts.map +1 -1
  59. package/dist/core/effective-constraints.js +0 -1
  60. package/dist/core/effective-constraints.js.map +1 -1
  61. package/dist/core/project-config-loader.d.ts.map +1 -1
  62. package/dist/core/project-config-loader.js +1 -8
  63. package/dist/core/project-config-loader.js.map +1 -1
  64. package/dist/dashboard/stats.d.ts.map +1 -1
  65. package/dist/dashboard/stats.js.map +1 -1
  66. package/dist/dashboard/types.d.ts +2 -2
  67. package/dist/dashboard/types.d.ts.map +1 -1
  68. package/dist/failure/constraint-handler.d.ts.map +1 -1
  69. package/dist/failure/constraint-handler.js +0 -2
  70. package/dist/failure/constraint-handler.js.map +1 -1
  71. package/dist/gates/acceptance.d.ts +9 -1
  72. package/dist/gates/acceptance.d.ts.map +1 -1
  73. package/dist/gates/acceptance.js +21 -0
  74. package/dist/gates/acceptance.js.map +1 -1
  75. package/dist/gates/checker-gate.d.ts +23 -0
  76. package/dist/gates/checker-gate.d.ts.map +1 -0
  77. package/dist/gates/checker-gate.js +53 -0
  78. package/dist/gates/checker-gate.js.map +1 -0
  79. package/dist/gates/command.d.ts +9 -2
  80. package/dist/gates/command.d.ts.map +1 -1
  81. package/dist/gates/command.js +10 -0
  82. package/dist/gates/command.js.map +1 -1
  83. package/dist/gates/contract.d.ts +8 -2
  84. package/dist/gates/contract.d.ts.map +1 -1
  85. package/dist/gates/contract.js +9 -0
  86. package/dist/gates/contract.js.map +1 -1
  87. package/dist/gates/decision.d.ts +17 -0
  88. package/dist/gates/decision.d.ts.map +1 -0
  89. package/dist/gates/decision.js +25 -0
  90. package/dist/gates/decision.js.map +1 -0
  91. package/dist/gates/definitions.d.ts +63 -0
  92. package/dist/gates/definitions.d.ts.map +1 -0
  93. package/dist/gates/definitions.js +160 -0
  94. package/dist/gates/definitions.js.map +1 -0
  95. package/dist/gates/effective-gates.d.ts +30 -0
  96. package/dist/gates/effective-gates.d.ts.map +1 -0
  97. package/dist/gates/effective-gates.js +85 -0
  98. package/dist/gates/effective-gates.js.map +1 -0
  99. package/dist/gates/index.d.ts +25 -1
  100. package/dist/gates/index.d.ts.map +1 -1
  101. package/dist/gates/index.js +37 -1
  102. package/dist/gates/index.js.map +1 -1
  103. package/dist/gates/performance.d.ts +8 -2
  104. package/dist/gates/performance.d.ts.map +1 -1
  105. package/dist/gates/performance.js +9 -0
  106. package/dist/gates/performance.js.map +1 -1
  107. package/dist/gates/registry.d.ts +32 -0
  108. package/dist/gates/registry.d.ts.map +1 -0
  109. package/dist/gates/registry.js +90 -0
  110. package/dist/gates/registry.js.map +1 -0
  111. package/dist/gates/review.d.ts +8 -2
  112. package/dist/gates/review.d.ts.map +1 -1
  113. package/dist/gates/review.js +9 -0
  114. package/dist/gates/review.js.map +1 -1
  115. package/dist/gates/runner.d.ts +30 -0
  116. package/dist/gates/runner.d.ts.map +1 -0
  117. package/dist/gates/runner.js +38 -0
  118. package/dist/gates/runner.js.map +1 -0
  119. package/dist/gates/security.d.ts +8 -2
  120. package/dist/gates/security.d.ts.map +1 -1
  121. package/dist/gates/security.js +9 -0
  122. package/dist/gates/security.js.map +1 -1
  123. package/dist/gates/types.d.ts +41 -1
  124. package/dist/gates/types.d.ts.map +1 -1
  125. package/dist/hooks/bootstrap.d.ts.map +1 -1
  126. package/dist/hooks/bootstrap.js +0 -2
  127. package/dist/hooks/bootstrap.js.map +1 -1
  128. package/dist/hooks/config.d.ts +26 -0
  129. package/dist/hooks/config.d.ts.map +1 -0
  130. package/dist/hooks/config.js +30 -0
  131. package/dist/hooks/config.js.map +1 -0
  132. package/dist/hooks/index.d.ts +2 -1
  133. package/dist/hooks/index.d.ts.map +1 -1
  134. package/dist/hooks/index.js +4 -1
  135. package/dist/hooks/index.js.map +1 -1
  136. package/dist/hooks/registry.d.ts +18 -1
  137. package/dist/hooks/registry.d.ts.map +1 -1
  138. package/dist/hooks/registry.js +45 -0
  139. package/dist/hooks/registry.js.map +1 -1
  140. package/dist/hooks/types.d.ts +20 -0
  141. package/dist/hooks/types.d.ts.map +1 -1
  142. package/dist/index.d.ts +4 -8
  143. package/dist/index.d.ts.map +1 -1
  144. package/dist/index.js +5 -20
  145. package/dist/index.js.map +1 -1
  146. package/dist/knowledge/import.d.ts +2 -2
  147. package/dist/knowledge/import.d.ts.map +1 -1
  148. package/dist/knowledge/ingest.js.map +1 -1
  149. package/dist/knowledge/lifecycle-hooks.d.ts +2 -2
  150. package/dist/knowledge/lifecycle-hooks.d.ts.map +1 -1
  151. package/dist/knowledge/types.d.ts +5 -7
  152. package/dist/knowledge/types.d.ts.map +1 -1
  153. package/dist/knowledge/types.js +1 -1
  154. package/dist/knowledge/types.js.map +1 -1
  155. package/dist/monitoring/constraint-doctor.d.ts +4 -22
  156. package/dist/monitoring/constraint-doctor.d.ts.map +1 -1
  157. package/dist/monitoring/constraint-doctor.js +7 -94
  158. package/dist/monitoring/constraint-doctor.js.map +1 -1
  159. package/dist/presets/standard.d.ts +1 -1
  160. package/dist/presets/standard.d.ts.map +1 -1
  161. package/dist/presets/standard.js +1 -2
  162. package/dist/presets/standard.js.map +1 -1
  163. package/dist/spec/annotation-checker.d.ts.map +1 -1
  164. package/dist/spec/annotation-checker.js +6 -26
  165. package/dist/spec/annotation-checker.js.map +1 -1
  166. package/dist/tools/index.d.ts +0 -4
  167. package/dist/tools/index.d.ts.map +1 -1
  168. package/dist/tools/index.js +0 -4
  169. package/dist/tools/index.js.map +1 -1
  170. package/dist/types/constraint.d.ts +1 -12
  171. package/dist/types/constraint.d.ts.map +1 -1
  172. package/dist/types/constraint.js +0 -3
  173. package/dist/types/constraint.js.map +1 -1
  174. package/dist/types/project-config.d.ts +0 -2
  175. package/dist/types/project-config.d.ts.map +1 -1
  176. package/dist/utils/file-walk.d.ts +2 -2
  177. package/dist/utils/file-walk.js +2 -2
  178. package/package.json +6 -1
  179. package/src/CONTEXT.md +14 -0
  180. package/src/__tests__/checker-extra.test.ts +2 -59
  181. package/src/__tests__/constraint-doctor.test.ts +1 -140
  182. package/src/__tests__/constraint-handler.test.ts +0 -4
  183. package/src/__tests__/project-config-loader-extra.test.ts +0 -20
  184. package/src/__tests__/project-config-loader.test.ts +0 -1
  185. package/src/cli/commands/CONTEXT.md +15 -7
  186. package/src/cli/commands/__tests__/check-drift.test.ts +0 -3
  187. package/src/cli/commands/__tests__/check-skip-output.test.ts +0 -5
  188. package/src/cli/commands/__tests__/check.test.ts +7 -75
  189. package/src/cli/commands/__tests__/registry.test.ts +201 -0
  190. package/src/cli/commands/check.ts +2 -14
  191. package/src/cli/commands/definitions.ts +593 -0
  192. package/src/cli/commands/knowledge.ts +3 -3
  193. package/src/cli/commands/sync-docs/capabilities-syncer.ts +4 -110
  194. package/src/cli/commands/sync-docs/index.ts +8 -5
  195. package/src/context/CONTEXT.md +2 -7
  196. package/src/context/__tests__/session-manager.test.ts +0 -91
  197. package/src/context/index.ts +1 -5
  198. package/src/context/knowledge-injector.ts +3 -3
  199. package/src/context/session-manager.ts +0 -74
  200. package/src/context/types.ts +2 -63
  201. package/src/core/constraints/__tests__/interceptor.test.ts +0 -2
  202. package/src/core/constraints/agent-prompt-renderer.ts +1 -1
  203. package/src/core/constraints/capabilities-parser.ts +95 -2
  204. package/src/core/constraints/checker.ts +8 -53
  205. package/src/core/constraints/definitions.ts +0 -8
  206. package/src/core/constraints/doc-freshness/runner.ts +1 -2
  207. package/src/core/constraints/index.ts +1 -2
  208. package/src/core/constraints/interceptor.ts +1 -6
  209. package/src/core/effective-constraints.ts +0 -1
  210. package/src/core/project-config-loader.ts +1 -7
  211. package/src/dashboard/stats.ts +2 -2
  212. package/src/dashboard/types.ts +2 -2
  213. package/src/failure/constraint-handler.ts +0 -2
  214. package/src/gates/CONTEXT.md +16 -13
  215. package/src/gates/__tests__/checker-gate.test.ts +45 -0
  216. package/src/gates/__tests__/contract.test.ts +73 -0
  217. package/src/gates/__tests__/effective-gates.test.ts +82 -0
  218. package/src/gates/__tests__/gate-interface.test.ts +202 -0
  219. package/src/gates/__tests__/registry.test.ts +87 -0
  220. package/src/gates/__tests__/runner.test.ts +81 -0
  221. package/src/gates/acceptance.ts +24 -1
  222. package/src/gates/checker-gate.ts +54 -0
  223. package/src/gates/command.ts +13 -2
  224. package/src/gates/contract.ts +12 -2
  225. package/src/gates/decision.ts +27 -0
  226. package/src/gates/definitions.ts +207 -0
  227. package/src/gates/effective-gates.ts +106 -0
  228. package/src/gates/index.ts +38 -0
  229. package/src/gates/performance.ts +12 -2
  230. package/src/gates/registry.ts +107 -0
  231. package/src/gates/review.ts +12 -2
  232. package/src/gates/runner.ts +57 -0
  233. package/src/gates/security.ts +12 -2
  234. package/src/gates/types.ts +48 -1
  235. package/src/hooks/CONTEXT.md +12 -2
  236. package/src/hooks/__tests__/bootstrap.test.ts +0 -1
  237. package/src/hooks/__tests__/config.test.ts +19 -0
  238. package/src/hooks/__tests__/pipeline.test.ts +79 -0
  239. package/src/hooks/__tests__/registry.test.ts +67 -0
  240. package/src/hooks/bootstrap.ts +0 -2
  241. package/src/hooks/config.ts +29 -0
  242. package/src/hooks/index.ts +2 -1
  243. package/src/hooks/registry.ts +60 -1
  244. package/src/hooks/types.ts +21 -0
  245. package/src/index.ts +5 -22
  246. package/src/knowledge/import.ts +3 -3
  247. package/src/knowledge/ingest.ts +4 -4
  248. package/src/knowledge/lifecycle-hooks.ts +3 -3
  249. package/src/knowledge/types.ts +5 -8
  250. package/src/monitoring/constraint-doctor.ts +7 -106
  251. package/src/presets/__tests__/standard.test.ts +0 -2
  252. package/src/presets/standard.ts +1 -2
  253. package/src/spec/__tests__/annotation-checker.test.ts +9 -3
  254. package/src/spec/annotation-checker.ts +7 -29
  255. package/src/tools/CONTEXT.md +7 -14
  256. package/src/tools/index.ts +0 -4
  257. package/src/types/constraint.ts +1 -14
  258. package/src/types/project-config.ts +0 -3
  259. package/src/utils/file-walk.ts +2 -2
  260. package/dist/architecture/constraint-engine.d.ts +0 -67
  261. package/dist/architecture/constraint-engine.d.ts.map +0 -1
  262. package/dist/architecture/constraint-engine.js +0 -295
  263. package/dist/architecture/constraint-engine.js.map +0 -1
  264. package/dist/architecture/cross-project-checker.d.ts +0 -54
  265. package/dist/architecture/cross-project-checker.d.ts.map +0 -1
  266. package/dist/architecture/cross-project-checker.js +0 -467
  267. package/dist/architecture/cross-project-checker.js.map +0 -1
  268. package/dist/cli/commands/index.d.ts +0 -30
  269. package/dist/cli/commands/index.d.ts.map +0 -1
  270. package/dist/cli/commands/index.js +0 -91
  271. package/dist/cli/commands/index.js.map +0 -1
  272. package/dist/context/file-budget.d.ts +0 -40
  273. package/dist/context/file-budget.d.ts.map +0 -1
  274. package/dist/context/file-budget.js +0 -147
  275. package/dist/context/file-budget.js.map +0 -1
  276. package/dist/context/progressive-loader.d.ts +0 -109
  277. package/dist/context/progressive-loader.d.ts.map +0 -1
  278. package/dist/context/progressive-loader.js +0 -166
  279. package/dist/context/progressive-loader.js.map +0 -1
  280. package/dist/context/token-pipeline.d.ts +0 -55
  281. package/dist/context/token-pipeline.d.ts.map +0 -1
  282. package/dist/context/token-pipeline.js +0 -220
  283. package/dist/context/token-pipeline.js.map +0 -1
  284. package/dist/context/tool-output-budget.d.ts +0 -59
  285. package/dist/context/tool-output-budget.d.ts.map +0 -1
  286. package/dist/context/tool-output-budget.js +0 -177
  287. package/dist/context/tool-output-budget.js.map +0 -1
  288. package/dist/core/constraints/default-executors.d.ts +0 -10
  289. package/dist/core/constraints/default-executors.d.ts.map +0 -1
  290. package/dist/core/constraints/default-executors.js +0 -120
  291. package/dist/core/constraints/default-executors.js.map +0 -1
  292. package/dist/llm/adapter.d.ts +0 -36
  293. package/dist/llm/adapter.d.ts.map +0 -1
  294. package/dist/llm/adapter.js +0 -118
  295. package/dist/llm/adapter.js.map +0 -1
  296. package/dist/llm/index.d.ts +0 -3
  297. package/dist/llm/index.d.ts.map +0 -1
  298. package/dist/llm/index.js +0 -19
  299. package/dist/llm/index.js.map +0 -1
  300. package/dist/llm/types.d.ts +0 -62
  301. package/dist/llm/types.d.ts.map +0 -1
  302. package/dist/llm/types.js +0 -8
  303. package/dist/llm/types.js.map +0 -1
  304. package/dist/tools/core/index.d.ts +0 -13
  305. package/dist/tools/core/index.d.ts.map +0 -1
  306. package/dist/tools/core/index.js +0 -198
  307. package/dist/tools/core/index.js.map +0 -1
  308. package/dist/tools/loader.d.ts +0 -21
  309. package/dist/tools/loader.d.ts.map +0 -1
  310. package/dist/tools/loader.js +0 -199
  311. package/dist/tools/loader.js.map +0 -1
  312. package/dist/tools/registry.d.ts +0 -59
  313. package/dist/tools/registry.d.ts.map +0 -1
  314. package/dist/tools/registry.js +0 -115
  315. package/dist/tools/registry.js.map +0 -1
  316. package/dist/tools/types.d.ts +0 -38
  317. package/dist/tools/types.d.ts.map +0 -1
  318. package/dist/tools/types.js +0 -6
  319. package/dist/tools/types.js.map +0 -1
  320. package/src/__tests__/architecture-engine.test.ts +0 -619
  321. package/src/__tests__/context/progressive-loader.test.ts +0 -131
  322. package/src/__tests__/cross-project-checker.test.ts +0 -318
  323. package/src/architecture/CONTEXT.md +0 -22
  324. package/src/architecture/constraint-engine.ts +0 -351
  325. package/src/architecture/cross-project-checker.ts +0 -545
  326. package/src/cli/commands/index.ts +0 -30
  327. package/src/context/__tests__/file-budget.test.ts +0 -142
  328. package/src/context/__tests__/progressive-loader.test.ts +0 -264
  329. package/src/context/__tests__/token-pipeline.test.ts +0 -178
  330. package/src/context/__tests__/tool-output-budget.test.ts +0 -95
  331. package/src/context/file-budget.ts +0 -142
  332. package/src/context/progressive-loader.ts +0 -260
  333. package/src/context/token-pipeline.ts +0 -265
  334. package/src/context/tool-output-budget.ts +0 -178
  335. package/src/core/constraints/__tests__/default-executors.test.ts +0 -57
  336. package/src/core/constraints/default-executors.ts +0 -92
  337. package/src/llm/CONTEXT.md +0 -21
  338. package/src/llm/__tests__/adapter.test.ts +0 -172
  339. package/src/llm/adapter.ts +0 -149
  340. package/src/llm/index.ts +0 -2
  341. package/src/llm/types.ts +0 -81
  342. package/src/tools/__tests__/loader.test.ts +0 -252
  343. package/src/tools/__tests__/registry.test.ts +0 -157
  344. package/src/tools/core/__tests__/core.test.ts +0 -122
  345. package/src/tools/core/index.ts +0 -201
  346. package/src/tools/loader.ts +0 -216
  347. package/src/tools/registry.ts +0 -128
  348. package/src/tools/types.ts +0 -46
@@ -1,131 +0,0 @@
1
- /**
2
- * @spec HZ-002
3
- * @acceptance AC-001-1, AC-001-2, AC-001-3, AC-001-4
4
- *
5
- * Progressive Loader 测试
6
- */
7
-
8
- import { ProgressiveLoader } from '../../context/progressive-loader';
9
- import { TokenEstimator, TokenBudget, AdaptiveTokenBudget } from '../../context/token-budget';
10
-
11
- describe('TokenEstimator', () => {
12
- it('should estimate English text', () => {
13
- const tokens = TokenEstimator.estimateText('Hello World');
14
- expect(tokens).toBeGreaterThan(0);
15
- });
16
-
17
- it('should estimate Chinese text', () => {
18
- const tokens = TokenEstimator.estimateText('你好世界');
19
- expect(tokens).toBeGreaterThan(0);
20
- });
21
-
22
- it('should estimate object', () => {
23
- const tokens = TokenEstimator.estimateObject({ foo: 'bar', num: 123 });
24
- expect(tokens).toBeGreaterThan(0);
25
- });
26
- });
27
-
28
- describe('TokenBudget', () => {
29
- it('should manage budget correctly', () => {
30
- const budget = new TokenBudget(1000);
31
- expect(budget.total).toBe(1000);
32
- expect(budget.remaining).toBe(1000);
33
-
34
- budget.consume(300);
35
- expect(budget.used).toBe(300);
36
- expect(budget.remaining).toBe(700);
37
- expect(budget.status).toBe('healthy');
38
- });
39
-
40
- it('should reserve and release budget', () => {
41
- const budget = new TokenBudget(1000);
42
- budget.reserve(200);
43
- expect(budget.remaining).toBe(800);
44
-
45
- budget.release(100);
46
- expect(budget.remaining).toBe(900);
47
- });
48
-
49
- it('should detect budget exceeded', () => {
50
- const budget = new TokenBudget(100);
51
- budget.consume(80);
52
- expect(budget.status).toBe('critical');
53
- });
54
- });
55
-
56
- describe('ProgressiveLoader', () => {
57
- it('should load in chunks', async () => {
58
- const loader = new ProgressiveLoader();
59
- const items = Array.from({ length: 100 }, (_, i) => i);
60
- const chunks: number[][] = [];
61
-
62
- await loader.loadInChunks(items, {
63
- chunkSize: 10,
64
- onChunk: (chunk: number[]) => { chunks.push(chunk); }
65
- });
66
-
67
- expect(chunks.length).toBe(10);
68
- expect(chunks[0].length).toBe(10);
69
- });
70
-
71
- it('should respect token budget with truncate', async () => {
72
- const loader = new ProgressiveLoader();
73
- const items = [
74
- { content: 'a'.repeat(100) },
75
- { content: 'b'.repeat(100) },
76
- { content: 'c'.repeat(100) },
77
- { content: 'd'.repeat(100) },
78
- ];
79
-
80
- const result = await loader.loadWithBudget(items, {
81
- budget: 60,
82
- estimator: (item: { content: string }) => TokenEstimator.estimateText(item.content),
83
- onBudgetExceeded: 'truncate',
84
- minItems: 1
85
- });
86
-
87
- expect(result.items.length).toBeLessThanOrEqual(3);
88
- expect(result.truncated).toBe(true);
89
- });
90
-
91
- it('should respect token budget with skip', async () => {
92
- const loader = new ProgressiveLoader();
93
- const items = [
94
- { content: 'a'.repeat(100) },
95
- { content: 'b'.repeat(1000) },
96
- { content: 'c'.repeat(100) },
97
- ];
98
-
99
- const result = await loader.loadWithBudget(items, {
100
- budget: 60,
101
- estimator: (item: { content: string }) => TokenEstimator.estimateText(item.content),
102
- onBudgetExceeded: 'skip',
103
- minItems: 1
104
- });
105
-
106
- expect(result.skipped).toBeGreaterThan(0);
107
- });
108
- });
109
-
110
- describe('AdaptiveTokenBudget', () => {
111
- it('should suggest budget adjustment', () => {
112
- const budget = new AdaptiveTokenBudget(1000);
113
-
114
- for (let i = 0; i < 5; i++) {
115
- budget.recordActualUsage(950);
116
- }
117
-
118
- const suggestion = budget.suggestBudgetAdjustment();
119
- expect(suggestion.action).toBe('increase');
120
- });
121
-
122
- it('should predict future needs', () => {
123
- const budget = new AdaptiveTokenBudget(1000);
124
- budget.recordActualUsage(500);
125
- budget.recordActualUsage(600);
126
- budget.recordActualUsage(550);
127
-
128
- const prediction = budget.predictNeed();
129
- expect(prediction).toBeGreaterThan(0);
130
- });
131
- });
@@ -1,318 +0,0 @@
1
- /**
2
- * CrossProjectChecker 测试
3
- */
4
-
5
- import { describe, it, expect, beforeAll, afterAll, beforeEach, jest } from '@jest/globals';
6
- import { checkCrossProjectContracts, checkDocCodeConsistency, type CrossProjectConfig } from '../architecture/cross-project-checker';
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
-
10
- const TEST_CONFIG: CrossProjectConfig = {
11
- dependencies: {
12
- 'agent-studio': ['agent-runtime', 'harness'],
13
- 'agent-runtime': ['harness', 'agent-workflows'],
14
- 'agent-workflows': ['harness'],
15
- 'harness': [],
16
- },
17
- contractLocations: {
18
- 'studio-runtime': [
19
- 'agent-runtime/src/api/types.ts',
20
- 'agent-studio/src/services/runtime-client.ts',
21
- ],
22
- 'runtime-harness': [
23
- 'harness/src/index.ts',
24
- 'agent-runtime/src/core/harness-adapter.ts',
25
- ],
26
- },
27
- };
28
-
29
- // Mock utils/exec
30
- jest.mock('../utils/exec', () => ({
31
- runCommand: jest.fn((() => Promise.resolve('')) as any),
32
- }));
33
-
34
- import { runCommand } from '../utils/exec';
35
- const mockRunCommand = runCommand as jest.MockedFunction<typeof runCommand>;
36
-
37
- describe('CrossProjectChecker', () => {
38
- const tempDir = path.join(process.cwd(), 'temp-test-cross');
39
-
40
- beforeAll(() => {
41
- fs.mkdirSync(tempDir, { recursive: true });
42
- });
43
-
44
- afterAll(() => {
45
- try {
46
- fs.rmSync(tempDir, { recursive: true, force: true });
47
- } catch {
48
- // ignore
49
- }
50
- });
51
-
52
- beforeEach(() => {
53
- jest.clearAllMocks();
54
- });
55
-
56
- describe('checkCrossProjectContracts', () => {
57
- it('应该检查跨项目依赖', async () => {
58
- mockRunCommand.mockResolvedValue('');
59
-
60
- const result = await checkCrossProjectContracts({
61
- baseBranch: 'main',
62
- changedProjects: [],
63
- changedFiles: [],
64
- }, TEST_CONFIG);
65
-
66
- expect(result).toBeDefined();
67
- expect(Array.isArray(result)).toBe(true);
68
- });
69
-
70
- it('空变更列表应该返回空数组', async () => {
71
- mockRunCommand.mockResolvedValue('');
72
-
73
- const result = await checkCrossProjectContracts({
74
- baseBranch: 'main',
75
- changedProjects: [],
76
- changedFiles: [],
77
- }, TEST_CONFIG);
78
-
79
- expect(result).toEqual([]);
80
- });
81
-
82
- it('runtime API 变更未同步到 studio 应该报错', async () => {
83
- mockRunCommand.mockResolvedValueOnce('projects/agent-runtime/src/api/types.ts\nprojects/agent-runtime/src/api/client.ts');
84
- mockRunCommand.mockResolvedValue('');
85
-
86
- const result = await checkCrossProjectContracts({
87
- baseBranch: 'main',
88
- changedProjects: ['agent-runtime'],
89
- changedFiles: ['projects/agent-runtime/src/api/types.ts'],
90
- }, TEST_CONFIG);
91
-
92
- expect(result.length).toBeGreaterThan(0);
93
- expect(result[0].type).toBe('api-mismatch');
94
- expect(result[0].fromProject).toBe('agent-runtime');
95
- expect(result[0].toProject).toBe('agent-studio');
96
- });
97
-
98
- it('runtime 和 studio 同时变更不应该报错', async () => {
99
- mockRunCommand.mockResolvedValueOnce('projects/agent-runtime/src/api/types.ts');
100
- mockRunCommand.mockResolvedValue('');
101
-
102
- const result = await checkCrossProjectContracts({
103
- baseBranch: 'main',
104
- changedProjects: ['agent-runtime', 'agent-studio'],
105
- changedFiles: [
106
- 'projects/agent-runtime/src/api/types.ts',
107
- 'projects/agent-studio/src/services/runtime-client.ts',
108
- ],
109
- }, TEST_CONFIG);
110
-
111
- // API 变更已同步,不应该有 api-mismatch 错误
112
- const apiMismatches = result.filter(v => v.type === 'api-mismatch');
113
- expect(apiMismatches.length).toBe(0);
114
- });
115
-
116
- it('破坏性变更未适配依赖项目应该报错', async () => {
117
- // checkApiSync 和 checkBreakingChanges 都调用 getApiChanges,需要两轮 mock
118
- // checkApiSync → getApiChanges → runCommand(name-only) + detectChangeType → runCommand(name-status)
119
- // checkBreakingChanges → getApiChanges → runCommand(name-only) + detectChangeType → runCommand(name-status)
120
- mockRunCommand
121
- .mockResolvedValueOnce('projects/harness/src/core/checkpoint.ts') // checkApiSync: name-only
122
- .mockResolvedValueOnce('D\tprojects/harness/src/core/checkpoint.ts') // checkApiSync: name-status
123
- .mockResolvedValueOnce('projects/harness/src/core/checkpoint.ts') // checkBreakingChanges: name-only
124
- .mockResolvedValueOnce('D\tprojects/harness/src/core/checkpoint.ts'); // checkBreakingChanges: name-status
125
-
126
- const result = await checkCrossProjectContracts({
127
- baseBranch: 'main',
128
- changedProjects: ['harness'],
129
- changedFiles: ['projects/harness/src/core/checkpoint.ts'],
130
- }, TEST_CONFIG);
131
-
132
- // 删除文件是破坏性变更,应产生 breaking-change 违规
133
- const breakingChanges = result.filter(v => v.type === 'breaking-change');
134
- expect(breakingChanges.length).toBeGreaterThan(0);
135
- });
136
-
137
- it('签名变更应该被检测为破坏性变更', async () => {
138
- // checkApiSync 和 checkBreakingChanges 都调用 getApiChanges
139
- mockRunCommand
140
- .mockResolvedValueOnce('projects/agent-runtime/src/api/types.ts') // checkApiSync: name-only
141
- .mockResolvedValueOnce('M\tprojects/agent-runtime/src/api/types.ts') // checkApiSync: name-status
142
- .mockResolvedValueOnce('-export function createAgent(config: Config): void\n+export function createAgent(config: Config, opts: Options): void') // checkApiSync: signature diff
143
- .mockResolvedValueOnce('projects/agent-runtime/src/api/types.ts') // checkBreakingChanges: name-only
144
- .mockResolvedValueOnce('M\tprojects/agent-runtime/src/api/types.ts') // checkBreakingChanges: name-status
145
- .mockResolvedValueOnce('-export function createAgent(config: Config): void\n+export function createAgent(config: Config, opts: Options): void'); // checkBreakingChanges: signature diff
146
-
147
- const result = await checkCrossProjectContracts({
148
- baseBranch: 'main',
149
- changedProjects: ['agent-runtime'],
150
- changedFiles: ['projects/agent-runtime/src/api/types.ts'],
151
- }, TEST_CONFIG);
152
-
153
- const breakingChanges = result.filter(v => v.type === 'breaking-change');
154
- expect(breakingChanges.length).toBeGreaterThan(0);
155
- });
156
-
157
- it('git 命令失败时应该返回空数组', async () => {
158
- mockRunCommand.mockRejectedValue(new Error('git error'));
159
-
160
- const result = await checkCrossProjectContracts({
161
- baseBranch: 'main',
162
- changedProjects: ['agent-runtime'],
163
- changedFiles: [],
164
- }, TEST_CONFIG);
165
-
166
- expect(result).toEqual([]);
167
- });
168
- });
169
-
170
- describe('checkDocCodeConsistency', () => {
171
- it('文档接口未实现应该报错', async () => {
172
- const docPath = path.join(tempDir, 'api-doc.md');
173
- fs.writeFileSync(docPath, '# API\n\n## agent-runtime\n- `createAgent(config)` - 创建 Agent');
174
-
175
- const result = await checkDocCodeConsistency(docPath, ['agent-runtime']);
176
-
177
- expect(result).toBeDefined();
178
- expect(Array.isArray(result)).toBe(true);
179
- });
180
-
181
- it('项目不在列表中应该跳过', async () => {
182
- const docPath = path.join(tempDir, 'api-doc-2.md');
183
- fs.writeFileSync(docPath, '# API\n\n## unknown-project\n- `test()`');
184
-
185
- const result = await checkDocCodeConsistency(docPath, ['agent-runtime']);
186
-
187
- // unknown-project 不在 projects 列表中,应该跳过
188
- expect(result).toBeDefined();
189
- });
190
-
191
- it('extractExportedApis 应该返回数组', async () => {
192
- // 测试内部函数的行为
193
- const docPath = path.join(tempDir, 'api-doc-3.md');
194
- fs.writeFileSync(docPath, '# API\n\n## agent-runtime\n- `createAgent(config)` - 创建 Agent');
195
-
196
- const result = await checkDocCodeConsistency(docPath, ['agent-runtime']);
197
-
198
- // 结果应该是数组
199
- expect(Array.isArray(result)).toBe(true);
200
- });
201
-
202
- it('isCompatible 检查签名一致性', async () => {
203
- const docPath = path.join(tempDir, 'api-doc-4.md');
204
- fs.writeFileSync(docPath, '# API\n\n## test-project\n- `testFunction(x: number)`');
205
-
206
- const result = await checkDocCodeConsistency(docPath, ['test-project']);
207
-
208
- expect(result).toBeDefined();
209
- });
210
-
211
- it('解析文档接口测试', async () => {
212
- const docPath = path.join(tempDir, 'complex-doc.md');
213
- fs.writeFileSync(docPath, `# API
214
-
215
- ## project-a
216
- - \`funcA(a: string, b: number): boolean\`
217
- - \`funcB(config: Config): void\`
218
-
219
- ## project-b
220
- - \`funcC()\`
221
- `);
222
-
223
- const result = await checkDocCodeConsistency(docPath, ['project-a', 'project-b']);
224
-
225
- // parseDocInterfaces 现在应该解析出 3 个接口
226
- // 由于 extractExportedApis 也已实现但项目目录不存在,应产生 missing-implementation 违规
227
- expect(Array.isArray(result)).toBe(true);
228
- expect(result.length).toBeGreaterThan(0);
229
- expect(result[0].type).toBe('missing-implementation');
230
- });
231
-
232
- it('项目目录存在时应该提取导出 API', async () => {
233
- // 创建项目目录结构
234
- const projectDir = path.join(process.cwd(), 'projects', 'test-proj', 'src');
235
- fs.mkdirSync(projectDir, { recursive: true });
236
- fs.writeFileSync(path.join(projectDir, 'index.ts'), `
237
- export function hello(name: string): string {
238
- return name;
239
- }
240
- export class MyService {
241
- run() {}
242
- }
243
- export const helper = (x: number) => x + 1;
244
- export interface Config { key: string; }
245
- export type Result = { ok: boolean; }
246
- `);
247
-
248
- const docPath = path.join(tempDir, 'api-with-impl.md');
249
- fs.writeFileSync(docPath, `# API
250
-
251
- ## test-proj
252
- - \`hello(name: string): string\`
253
- `);
254
-
255
- const result = await checkDocCodeConsistency(docPath, ['test-proj']);
256
-
257
- // 应该能匹配到 hello 函数
258
- expect(Array.isArray(result)).toBe(true);
259
-
260
- // 清理
261
- fs.rmSync(path.join(process.cwd(), 'projects'), { recursive: true, force: true });
262
- });
263
-
264
- it('文档签名不匹配应该报 doc-code-mismatch', async () => {
265
- const projectDir = path.join(process.cwd(), 'projects', 'mismatch-proj', 'src');
266
- fs.mkdirSync(projectDir, { recursive: true });
267
- fs.writeFileSync(path.join(projectDir, 'api.ts'), `
268
- export function createAgent(config: object): void {}
269
- `);
270
-
271
- const docPath = path.join(tempDir, 'api-mismatch.md');
272
- fs.writeFileSync(docPath, `# API
273
-
274
- ## mismatch-proj
275
- - \`createAgent(config: string, opts: object): boolean\`
276
- `);
277
-
278
- const result = await checkDocCodeConsistency(docPath, ['mismatch-proj']);
279
-
280
- // 签名不匹配,应产生 doc-code-mismatch
281
- const mismatches = result.filter(v => v.type === 'doc-code-mismatch');
282
- expect(mismatches.length).toBeGreaterThan(0);
283
-
284
- fs.rmSync(path.join(process.cwd(), 'projects'), { recursive: true, force: true });
285
- });
286
-
287
- it('findTsFiles 应该排除 node_modules 和 dist', async () => {
288
- const projectDir = path.join(process.cwd(), 'projects', 'filter-proj', 'src');
289
- fs.mkdirSync(path.join(projectDir, 'node_modules'), { recursive: true });
290
- fs.mkdirSync(path.join(projectDir, 'dist'), { recursive: true });
291
- fs.mkdirSync(path.join(projectDir, '__tests__'), { recursive: true });
292
- fs.writeFileSync(path.join(projectDir, 'valid.ts'), 'export const x = 1;');
293
- fs.writeFileSync(path.join(projectDir, 'node_modules', 'dep.ts'), 'export const y = 2;');
294
- fs.writeFileSync(path.join(projectDir, 'dist', 'built.js'), 'var x = 1;');
295
- fs.writeFileSync(path.join(projectDir, '__tests__', 'test.ts'), 'export const z = 3;');
296
- fs.writeFileSync(path.join(projectDir, 'types.d.ts'), 'export interface I {}');
297
-
298
- const docPath = path.join(tempDir, 'api-filter.md');
299
- fs.writeFileSync(docPath, `# API
300
-
301
- ## filter-proj
302
- - \`nonexistent()\`
303
- `);
304
-
305
- const result = await checkDocCodeConsistency(docPath, ['filter-proj']);
306
-
307
- // 应该只找到 valid.ts,不包含 node_modules/dist/__tests__/.d.ts
308
- expect(Array.isArray(result)).toBe(true);
309
-
310
- fs.rmSync(path.join(process.cwd(), 'projects'), { recursive: true, force: true });
311
- });
312
-
313
- it('parseDocInterfaces 不存在的文件应该返回空', async () => {
314
- const result = await checkDocCodeConsistency('/nonexistent/doc.md', ['any']);
315
- expect(result).toEqual([]);
316
- });
317
- });
318
- });
@@ -1,22 +0,0 @@
1
- # architecture/
2
-
3
- ## 职责
4
- 架构级约束检查:架构约束引擎(规则加载/检查/报告)、跨项目接口契约检查(API 同步/类型一致性/破坏性变更/文档-代码一致性)。
5
-
6
- ## 核心导出
7
- - `constraint-engine.ts` — ArchitectureEngine: 加载规则(.architect/rules.yml)、执行检查、生成报告
8
- - `cross-project-checker.ts` — CrossProjectChecker: 跨项目依赖检查(异步化)
9
-
10
- ## 依赖关系
11
- - 依赖 `src/core/` 约束引擎类型
12
- - 依赖 `src/utils/exec` 异步命令执行
13
- - 被 `src/cli/` 架构相关命令消费
14
-
15
- ## 约定
16
- - 规则由项目提供(.architect/rules.yml),harness 只提供引擎
17
- - 跨项目检查异步执行(不阻塞主流程)
18
- - 注意与 constraint 模块的类型区分
19
-
20
- ## 注意事项
21
- - 无 index.ts 统一导出,各模块独立导入
22
- - cross-project-checker 已从 execSync 迁移到异步 runCommand