@soleri/core 9.2.0 → 9.3.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 (298) hide show
  1. package/data/flows/build.flow.yaml +8 -9
  2. package/data/flows/deliver.flow.yaml +9 -10
  3. package/data/flows/design.flow.yaml +3 -4
  4. package/data/flows/enhance.flow.yaml +5 -6
  5. package/data/flows/explore.flow.yaml +3 -4
  6. package/data/flows/fix.flow.yaml +5 -6
  7. package/data/flows/plan.flow.yaml +4 -5
  8. package/data/flows/review.flow.yaml +3 -4
  9. package/dist/curator/curator.d.ts.map +1 -1
  10. package/dist/curator/curator.js +98 -22
  11. package/dist/curator/curator.js.map +1 -1
  12. package/dist/engine/bin/soleri-engine.js.map +1 -1
  13. package/dist/engine/module-manifest.d.ts.map +1 -1
  14. package/dist/engine/module-manifest.js +21 -1
  15. package/dist/engine/module-manifest.js.map +1 -1
  16. package/dist/engine/register-engine.d.ts.map +1 -1
  17. package/dist/engine/register-engine.js +25 -1
  18. package/dist/engine/register-engine.js.map +1 -1
  19. package/dist/flows/gate-evaluator.js.map +1 -1
  20. package/dist/operator/operator-profile.d.ts.map +1 -1
  21. package/dist/operator/operator-profile.js +11 -5
  22. package/dist/operator/operator-profile.js.map +1 -1
  23. package/dist/operator/operator-signals.d.ts.map +1 -1
  24. package/dist/operator/operator-signals.js.map +1 -1
  25. package/dist/planning/evidence-collector.js.map +1 -1
  26. package/dist/planning/gap-passes.d.ts.map +1 -1
  27. package/dist/planning/gap-passes.js +23 -6
  28. package/dist/planning/gap-passes.js.map +1 -1
  29. package/dist/planning/gap-patterns.d.ts.map +1 -1
  30. package/dist/planning/gap-patterns.js +57 -11
  31. package/dist/planning/gap-patterns.js.map +1 -1
  32. package/dist/planning/github-projection.d.ts.map +1 -1
  33. package/dist/planning/github-projection.js +39 -20
  34. package/dist/planning/github-projection.js.map +1 -1
  35. package/dist/planning/impact-analyzer.d.ts.map +1 -1
  36. package/dist/planning/impact-analyzer.js +20 -18
  37. package/dist/planning/impact-analyzer.js.map +1 -1
  38. package/dist/planning/plan-lifecycle.d.ts.map +1 -1
  39. package/dist/planning/plan-lifecycle.js +22 -9
  40. package/dist/planning/plan-lifecycle.js.map +1 -1
  41. package/dist/planning/planner.d.ts.map +1 -1
  42. package/dist/planning/planner.js +60 -17
  43. package/dist/planning/planner.js.map +1 -1
  44. package/dist/planning/rationalization-detector.d.ts.map +1 -1
  45. package/dist/planning/rationalization-detector.js.map +1 -1
  46. package/dist/planning/reconciliation-engine.d.ts.map +1 -1
  47. package/dist/planning/reconciliation-engine.js.map +1 -1
  48. package/dist/planning/task-verifier.d.ts.map +1 -1
  49. package/dist/planning/task-verifier.js +14 -6
  50. package/dist/planning/task-verifier.js.map +1 -1
  51. package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
  52. package/dist/runtime/admin-setup-ops.js +2 -1
  53. package/dist/runtime/admin-setup-ops.js.map +1 -1
  54. package/dist/runtime/branching-ops.d.ts +12 -0
  55. package/dist/runtime/branching-ops.d.ts.map +1 -0
  56. package/dist/runtime/branching-ops.js +100 -0
  57. package/dist/runtime/branching-ops.js.map +1 -0
  58. package/dist/runtime/context-health.d.ts.map +1 -1
  59. package/dist/runtime/context-health.js.map +1 -1
  60. package/dist/runtime/facades/branching-facade.d.ts +7 -0
  61. package/dist/runtime/facades/branching-facade.d.ts.map +1 -0
  62. package/dist/runtime/facades/branching-facade.js +8 -0
  63. package/dist/runtime/facades/branching-facade.js.map +1 -0
  64. package/dist/runtime/facades/chat-service-ops.d.ts.map +1 -1
  65. package/dist/runtime/facades/chat-service-ops.js +3 -1
  66. package/dist/runtime/facades/chat-service-ops.js.map +1 -1
  67. package/dist/runtime/facades/chat-transport-ops.d.ts.map +1 -1
  68. package/dist/runtime/facades/chat-transport-ops.js.map +1 -1
  69. package/dist/runtime/facades/index.d.ts.map +1 -1
  70. package/dist/runtime/facades/index.js +42 -0
  71. package/dist/runtime/facades/index.js.map +1 -1
  72. package/dist/runtime/facades/intake-facade.d.ts +9 -0
  73. package/dist/runtime/facades/intake-facade.d.ts.map +1 -0
  74. package/dist/runtime/facades/intake-facade.js +11 -0
  75. package/dist/runtime/facades/intake-facade.js.map +1 -0
  76. package/dist/runtime/facades/links-facade.d.ts +9 -0
  77. package/dist/runtime/facades/links-facade.d.ts.map +1 -0
  78. package/dist/runtime/facades/links-facade.js +10 -0
  79. package/dist/runtime/facades/links-facade.js.map +1 -0
  80. package/dist/runtime/facades/operator-facade.d.ts.map +1 -1
  81. package/dist/runtime/facades/operator-facade.js.map +1 -1
  82. package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
  83. package/dist/runtime/facades/plan-facade.js +4 -1
  84. package/dist/runtime/facades/plan-facade.js.map +1 -1
  85. package/dist/runtime/facades/tier-facade.d.ts +7 -0
  86. package/dist/runtime/facades/tier-facade.d.ts.map +1 -0
  87. package/dist/runtime/facades/tier-facade.js +8 -0
  88. package/dist/runtime/facades/tier-facade.js.map +1 -0
  89. package/dist/runtime/facades/vault-facade.d.ts +9 -1
  90. package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
  91. package/dist/runtime/facades/vault-facade.js +44 -187
  92. package/dist/runtime/facades/vault-facade.js.map +1 -1
  93. package/dist/runtime/github-integration.d.ts.map +1 -1
  94. package/dist/runtime/github-integration.js +11 -4
  95. package/dist/runtime/github-integration.js.map +1 -1
  96. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  97. package/dist/runtime/orchestrate-ops.js +32 -10
  98. package/dist/runtime/orchestrate-ops.js.map +1 -1
  99. package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
  100. package/dist/runtime/planning-extra-ops.js.map +1 -1
  101. package/dist/runtime/runtime.d.ts.map +1 -1
  102. package/dist/runtime/runtime.js +3 -1
  103. package/dist/runtime/runtime.js.map +1 -1
  104. package/dist/runtime/session-briefing.d.ts.map +1 -1
  105. package/dist/runtime/session-briefing.js +5 -1
  106. package/dist/runtime/session-briefing.js.map +1 -1
  107. package/dist/runtime/tier-ops.d.ts +13 -0
  108. package/dist/runtime/tier-ops.d.ts.map +1 -0
  109. package/dist/runtime/tier-ops.js +110 -0
  110. package/dist/runtime/tier-ops.js.map +1 -0
  111. package/dist/skills/sync-skills.d.ts.map +1 -1
  112. package/dist/skills/sync-skills.js +1 -1
  113. package/dist/skills/sync-skills.js.map +1 -1
  114. package/dist/vault/linking.d.ts.map +1 -1
  115. package/dist/vault/linking.js +41 -5
  116. package/dist/vault/linking.js.map +1 -1
  117. package/dist/vault/vault-entries.d.ts.map +1 -1
  118. package/dist/vault/vault-entries.js +68 -26
  119. package/dist/vault/vault-entries.js.map +1 -1
  120. package/dist/vault/vault-maintenance.d.ts.map +1 -1
  121. package/dist/vault/vault-maintenance.js +6 -2
  122. package/dist/vault/vault-maintenance.js.map +1 -1
  123. package/dist/vault/vault-markdown-sync.d.ts.map +1 -1
  124. package/dist/vault/vault-markdown-sync.js.map +1 -1
  125. package/dist/vault/vault-memories.d.ts.map +1 -1
  126. package/dist/vault/vault-memories.js +3 -1
  127. package/dist/vault/vault-memories.js.map +1 -1
  128. package/dist/vault/vault-schema.js +36 -10
  129. package/dist/vault/vault-schema.js.map +1 -1
  130. package/dist/vault/vault.d.ts.map +1 -1
  131. package/dist/vault/vault.js +5 -1
  132. package/dist/vault/vault.js.map +1 -1
  133. package/package.json +7 -7
  134. package/src/agency/agency-manager.test.ts +60 -40
  135. package/src/agency/default-rules.test.ts +17 -9
  136. package/src/capabilities/registry.test.ts +2 -12
  137. package/src/chat/agent-loop.test.ts +33 -43
  138. package/src/chat/mcp-bridge.test.ts +7 -2
  139. package/src/claudemd/inject.test.ts +2 -12
  140. package/src/context/context-engine.test.ts +96 -51
  141. package/src/control/intent-router.test.ts +3 -3
  142. package/src/curator/classifier.test.ts +14 -8
  143. package/src/curator/contradiction-detector.test.ts +30 -5
  144. package/src/curator/curator.ts +278 -56
  145. package/src/curator/duplicate-detector.test.ts +77 -15
  146. package/src/curator/quality-gate.test.ts +71 -31
  147. package/src/curator/tag-manager.test.ts +12 -4
  148. package/src/domain-packs/knowledge-installer.test.ts +2 -10
  149. package/src/domain-packs/token-resolver.test.ts +1 -3
  150. package/src/domain-packs/types.test.ts +16 -2
  151. package/src/enforcement/registry.test.ts +2 -8
  152. package/src/engine/bin/soleri-engine.ts +3 -1
  153. package/src/engine/module-manifest.test.ts +5 -4
  154. package/src/engine/module-manifest.ts +21 -1
  155. package/src/engine/register-engine.test.ts +6 -1
  156. package/src/engine/register-engine.ts +26 -3
  157. package/src/errors/classify.test.ts +6 -2
  158. package/src/errors/retry.test.ts +1 -4
  159. package/src/facades/facade-factory.test.ts +110 -64
  160. package/src/flows/epilogue.test.ts +16 -10
  161. package/src/flows/gate-evaluator.test.ts +12 -6
  162. package/src/flows/gate-evaluator.ts +1 -3
  163. package/src/governance/governance.test.ts +137 -21
  164. package/src/health/health-registry.test.ts +8 -1
  165. package/src/intake/content-classifier.test.ts +121 -51
  166. package/src/intake/dedup-gate.test.ts +38 -22
  167. package/src/intake/intake-pipeline.test.ts +5 -3
  168. package/src/intake/text-ingester.test.ts +26 -20
  169. package/src/llm/key-pool.test.ts +1 -3
  170. package/src/llm/llm-client.test.ts +1 -4
  171. package/src/llm/oauth-discovery.test.ts +16 -16
  172. package/src/llm/utils.test.ts +62 -18
  173. package/src/logging/logger.test.ts +4 -1
  174. package/src/loop/loop-manager.test.ts +2 -6
  175. package/src/migrations/migration-runner.edge-cases.test.ts +2 -7
  176. package/src/operator/operator-profile-extended.test.ts +15 -5
  177. package/src/operator/operator-profile.test.ts +26 -8
  178. package/src/operator/operator-profile.ts +38 -22
  179. package/src/operator/operator-signals-extended.test.ts +35 -23
  180. package/src/operator/operator-signals.test.ts +6 -10
  181. package/src/operator/operator-signals.ts +2 -1
  182. package/src/operator/prompts/hook-precompact-operator-dispatch.md +10 -6
  183. package/src/operator/prompts/subagent-soft-signal-extractor.md +5 -0
  184. package/src/operator/prompts/subagent-synthesis-cognition.md +19 -10
  185. package/src/operator/prompts/subagent-synthesis-communication.md +13 -7
  186. package/src/operator/prompts/subagent-synthesis-technical.md +19 -9
  187. package/src/operator/prompts/subagent-synthesis-trust.md +27 -21
  188. package/src/persona/defaults.test.ts +1 -5
  189. package/src/planning/evidence-collector.test.ts +147 -38
  190. package/src/planning/evidence-collector.ts +1 -4
  191. package/src/planning/gap-analysis-alternatives.test.ts +41 -11
  192. package/src/planning/gap-passes.test.ts +215 -33
  193. package/src/planning/gap-passes.ts +115 -46
  194. package/src/planning/gap-patterns.test.ts +87 -13
  195. package/src/planning/gap-patterns.ts +114 -31
  196. package/src/planning/github-projection.test.ts +6 -1
  197. package/src/planning/github-projection.ts +41 -20
  198. package/src/planning/impact-analyzer.test.ts +10 -23
  199. package/src/planning/impact-analyzer.ts +33 -46
  200. package/src/planning/plan-lifecycle.test.ts +103 -36
  201. package/src/planning/plan-lifecycle.ts +49 -18
  202. package/src/planning/planner.test.ts +12 -2
  203. package/src/planning/planner.ts +198 -58
  204. package/src/planning/rationalization-detector.test.ts +5 -20
  205. package/src/planning/rationalization-detector.ts +14 -16
  206. package/src/planning/reconciliation-engine.test.ts +20 -3
  207. package/src/planning/reconciliation-engine.ts +1 -2
  208. package/src/planning/task-verifier.test.ts +59 -27
  209. package/src/planning/task-verifier.ts +15 -9
  210. package/src/playbooks/playbook-executor.test.ts +1 -3
  211. package/src/plugins/plugin-loader.test.ts +19 -14
  212. package/src/plugins/plugin-registry.test.ts +45 -33
  213. package/src/project/project-registry.test.ts +23 -12
  214. package/src/prompts/template-manager.test.ts +4 -1
  215. package/src/queue/job-queue.test.ts +10 -14
  216. package/src/runtime/admin-extra-ops.test.ts +5 -19
  217. package/src/runtime/admin-ops.test.ts +1 -3
  218. package/src/runtime/admin-setup-ops.test.ts +3 -4
  219. package/src/runtime/admin-setup-ops.ts +9 -2
  220. package/src/runtime/archive-ops.test.ts +4 -1
  221. package/src/runtime/branching-ops.test.ts +144 -0
  222. package/src/runtime/branching-ops.ts +107 -0
  223. package/src/runtime/capture-ops.test.ts +7 -21
  224. package/src/runtime/chain-ops.test.ts +16 -6
  225. package/src/runtime/claude-md-helpers.test.ts +1 -3
  226. package/src/runtime/context-health.test.ts +1 -3
  227. package/src/runtime/context-health.ts +1 -3
  228. package/src/runtime/curator-extra-ops.test.ts +3 -1
  229. package/src/runtime/domain-ops.test.ts +46 -36
  230. package/src/runtime/facades/admin-facade.test.ts +1 -4
  231. package/src/runtime/facades/archive-facade.test.ts +21 -7
  232. package/src/runtime/facades/brain-facade.test.ts +176 -72
  233. package/src/runtime/facades/branching-facade.test.ts +43 -0
  234. package/src/runtime/facades/branching-facade.ts +11 -0
  235. package/src/runtime/facades/chat-facade.test.ts +81 -28
  236. package/src/runtime/facades/chat-service-ops.test.ts +178 -73
  237. package/src/runtime/facades/chat-service-ops.ts +3 -1
  238. package/src/runtime/facades/chat-session-ops.test.ts +25 -10
  239. package/src/runtime/facades/chat-transport-ops.test.ts +101 -34
  240. package/src/runtime/facades/chat-transport-ops.ts +0 -1
  241. package/src/runtime/facades/context-facade.test.ts +19 -4
  242. package/src/runtime/facades/control-facade.test.ts +3 -3
  243. package/src/runtime/facades/index.ts +42 -0
  244. package/src/runtime/facades/intake-facade.test.ts +215 -0
  245. package/src/runtime/facades/intake-facade.ts +14 -0
  246. package/src/runtime/facades/links-facade.test.ts +203 -0
  247. package/src/runtime/facades/links-facade.ts +13 -0
  248. package/src/runtime/facades/loop-facade.test.ts +22 -5
  249. package/src/runtime/facades/memory-facade.test.ts +19 -5
  250. package/src/runtime/facades/operator-facade.test.ts +17 -4
  251. package/src/runtime/facades/operator-facade.ts +11 -3
  252. package/src/runtime/facades/orchestrate-facade.test.ts +7 -1
  253. package/src/runtime/facades/plan-facade.test.ts +29 -12
  254. package/src/runtime/facades/plan-facade.ts +7 -2
  255. package/src/runtime/facades/tier-facade.test.ts +47 -0
  256. package/src/runtime/facades/tier-facade.ts +11 -0
  257. package/src/runtime/facades/vault-facade.test.ts +174 -242
  258. package/src/runtime/facades/vault-facade.ts +55 -199
  259. package/src/runtime/github-integration.ts +11 -8
  260. package/src/runtime/grading-ops.test.ts +39 -8
  261. package/src/runtime/intake-ops.test.ts +69 -16
  262. package/src/runtime/loop-ops.test.ts +16 -6
  263. package/src/runtime/memory-cross-project-ops.test.ts +25 -14
  264. package/src/runtime/orchestrate-ops.ts +54 -27
  265. package/src/runtime/pack-ops.test.ts +23 -6
  266. package/src/runtime/planning-extra-ops.test.ts +17 -7
  267. package/src/runtime/planning-extra-ops.ts +3 -1
  268. package/src/runtime/playbook-ops.test.ts +26 -3
  269. package/src/runtime/plugin-ops.test.ts +83 -25
  270. package/src/runtime/project-ops.test.ts +26 -6
  271. package/src/runtime/runtime.ts +3 -1
  272. package/src/runtime/session-briefing.test.ts +183 -54
  273. package/src/runtime/session-briefing.ts +8 -2
  274. package/src/runtime/sync-ops.test.ts +3 -12
  275. package/src/runtime/telemetry-ops.test.ts +31 -6
  276. package/src/runtime/tier-ops.test.ts +159 -0
  277. package/src/runtime/tier-ops.ts +119 -0
  278. package/src/runtime/vault-extra-ops.test.ts +32 -8
  279. package/src/runtime/vault-sharing-ops.test.ts +1 -4
  280. package/src/skills/sync-skills.ts +2 -12
  281. package/src/transport/ws-server.test.ts +7 -4
  282. package/src/vault/__tests__/vault-characterization.test.ts +492 -81
  283. package/src/vault/linking.test.ts +50 -17
  284. package/src/vault/linking.ts +48 -7
  285. package/src/vault/obsidian-sync.test.ts +6 -3
  286. package/src/vault/scope-detector.test.ts +1 -3
  287. package/src/vault/vault-branching.test.ts +9 -7
  288. package/src/vault/vault-entries.ts +209 -65
  289. package/src/vault/vault-maintenance.ts +7 -12
  290. package/src/vault/vault-manager.test.ts +10 -10
  291. package/src/vault/vault-markdown-sync.ts +4 -1
  292. package/src/vault/vault-memories.ts +7 -7
  293. package/src/vault/vault-schema.ts +72 -15
  294. package/src/vault/vault.ts +55 -9
  295. package/src/brain/strength-scorer.ts +0 -404
  296. package/src/engine/index.ts +0 -21
  297. package/src/persona/index.ts +0 -9
  298. package/src/vault/vault-interfaces.ts +0 -56
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Colocated contract tests for tier-ops.ts.
3
+ * Tests the 7 multi-vault tier and named source ops extracted from vault-facade.
4
+ */
5
+
6
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
7
+ import { createTierOps } from './tier-ops.js';
8
+ import { captureOps, executeOp } from '../engine/test-helpers.js';
9
+ import type { CapturedOp } from '../engine/test-helpers.js';
10
+ import type { AgentRuntime } from './types.js';
11
+
12
+ function makeMockVaultManager() {
13
+ return {
14
+ open: vi.fn(),
15
+ disconnect: vi.fn().mockReturnValue(true),
16
+ listTiers: vi.fn().mockReturnValue([{ tier: 'agent', connected: true, entries: 25 }]),
17
+ search: vi.fn().mockReturnValue([{ id: 'e1', tier: 'agent', score: 0.9 }]),
18
+ connect: vi.fn(),
19
+ disconnectNamed: vi.fn().mockReturnValue(true),
20
+ listConnected: vi.fn().mockReturnValue([{ name: 'team-shared', priority: 0.5 }]),
21
+ };
22
+ }
23
+
24
+ function makeRuntime(): AgentRuntime {
25
+ return {
26
+ vaultManager: makeMockVaultManager(),
27
+ config: { agentId: 'test-agent' },
28
+ } as unknown as AgentRuntime;
29
+ }
30
+
31
+ describe('tier-ops', () => {
32
+ let runtime: AgentRuntime;
33
+ let ops: Map<string, CapturedOp>;
34
+
35
+ beforeEach(() => {
36
+ runtime = makeRuntime();
37
+ ops = captureOps(createTierOps(runtime));
38
+ });
39
+
40
+ it('registers all 7 tier/source ops', () => {
41
+ expect(ops.size).toBe(7);
42
+ expect(ops.has('vault_connect')).toBe(true);
43
+ expect(ops.has('vault_disconnect')).toBe(true);
44
+ expect(ops.has('vault_tiers')).toBe(true);
45
+ expect(ops.has('vault_search_all')).toBe(true);
46
+ expect(ops.has('vault_connect_source')).toBe(true);
47
+ expect(ops.has('vault_disconnect_source')).toBe(true);
48
+ expect(ops.has('vault_list_sources')).toBe(true);
49
+ });
50
+
51
+ it('has correct auth levels', () => {
52
+ expect(ops.get('vault_connect')!.auth).toBe('admin');
53
+ expect(ops.get('vault_disconnect')!.auth).toBe('admin');
54
+ expect(ops.get('vault_tiers')!.auth).toBe('read');
55
+ expect(ops.get('vault_search_all')!.auth).toBe('read');
56
+ expect(ops.get('vault_connect_source')!.auth).toBe('admin');
57
+ expect(ops.get('vault_disconnect_source')!.auth).toBe('admin');
58
+ expect(ops.get('vault_list_sources')!.auth).toBe('read');
59
+ });
60
+
61
+ // ─── Multi-vault ops ──────────────────────────────────────────────
62
+
63
+ describe('vault_connect', () => {
64
+ it('connects a vault tier', async () => {
65
+ const result = await executeOp(ops, 'vault_connect', {
66
+ tier: 'project',
67
+ path: '/tmp/project.db',
68
+ });
69
+ expect(result.success).toBe(true);
70
+ const data = result.data as { connected: boolean; tier: string; path: string };
71
+ expect(data.connected).toBe(true);
72
+ expect(data.tier).toBe('project');
73
+ expect(data.path).toBe('/tmp/project.db');
74
+ });
75
+ });
76
+
77
+ describe('vault_disconnect', () => {
78
+ it('disconnects a vault tier', async () => {
79
+ const result = await executeOp(ops, 'vault_disconnect', { tier: 'team' });
80
+ expect(result.success).toBe(true);
81
+ const data = result.data as { disconnected: boolean; tier: string };
82
+ expect(data.disconnected).toBe(true);
83
+ expect(data.tier).toBe('team');
84
+ });
85
+ });
86
+
87
+ describe('vault_tiers', () => {
88
+ it('lists vault tiers', async () => {
89
+ const result = await executeOp(ops, 'vault_tiers', {});
90
+ expect(result.success).toBe(true);
91
+ const data = result.data as { tiers: Array<{ tier: string }> };
92
+ expect(data.tiers).toHaveLength(1);
93
+ expect(data.tiers[0].tier).toBe('agent');
94
+ });
95
+ });
96
+
97
+ describe('vault_search_all', () => {
98
+ it('searches across all tiers', async () => {
99
+ const result = await executeOp(ops, 'vault_search_all', { query: 'tokens' });
100
+ expect(result.success).toBe(true);
101
+ const data = result.data as { results: unknown[]; count: number };
102
+ expect(data.count).toBe(1);
103
+ const vm = runtime.vaultManager as ReturnType<typeof makeMockVaultManager>;
104
+ expect(vm.search).toHaveBeenCalledWith('tokens', 20);
105
+ });
106
+
107
+ it('passes custom limit', async () => {
108
+ await executeOp(ops, 'vault_search_all', { query: 'test', limit: 5 });
109
+ const vm = runtime.vaultManager as ReturnType<typeof makeMockVaultManager>;
110
+ expect(vm.search).toHaveBeenCalledWith('test', 5);
111
+ });
112
+ });
113
+
114
+ // ─── Named vault connections ───────────────────────────────────────
115
+
116
+ describe('vault_connect_source', () => {
117
+ it('connects with default priority', async () => {
118
+ const result = await executeOp(ops, 'vault_connect_source', {
119
+ name: 'team-kb',
120
+ path: '/tmp/team.db',
121
+ });
122
+ expect(result.success).toBe(true);
123
+ const data = result.data as { connected: boolean; priority: number };
124
+ expect(data.connected).toBe(true);
125
+ expect(data.priority).toBe(0.5);
126
+ });
127
+
128
+ it('connects with custom priority', async () => {
129
+ const result = await executeOp(ops, 'vault_connect_source', {
130
+ name: 'primary',
131
+ path: '/tmp/p.db',
132
+ priority: 1.5,
133
+ });
134
+ expect(result.success).toBe(true);
135
+ const vm = runtime.vaultManager as ReturnType<typeof makeMockVaultManager>;
136
+ expect(vm.connect).toHaveBeenCalledWith('primary', '/tmp/p.db', 1.5);
137
+ });
138
+ });
139
+
140
+ describe('vault_disconnect_source', () => {
141
+ it('disconnects a named source', async () => {
142
+ const result = await executeOp(ops, 'vault_disconnect_source', { name: 'team-kb' });
143
+ expect(result.success).toBe(true);
144
+ const data = result.data as { disconnected: boolean; name: string };
145
+ expect(data.disconnected).toBe(true);
146
+ expect(data.name).toBe('team-kb');
147
+ });
148
+ });
149
+
150
+ describe('vault_list_sources', () => {
151
+ it('lists connected sources', async () => {
152
+ const result = await executeOp(ops, 'vault_list_sources', {});
153
+ expect(result.success).toBe(true);
154
+ const data = result.data as { sources: Array<{ name: string }> };
155
+ expect(data.sources).toHaveLength(1);
156
+ expect(data.sources[0].name).toBe('team-shared');
157
+ });
158
+ });
159
+ });
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Tier Ops — multi-vault tier and named source operations.
3
+ *
4
+ * Covers:
5
+ * - Connect/disconnect vault tiers (project, team)
6
+ * - List tiers with connection status
7
+ * - Search across all connected tiers
8
+ * - Named vault source connections with configurable priority
9
+ */
10
+
11
+ import { z } from 'zod';
12
+ import type { OpDefinition } from '../facades/types.js';
13
+ import type { VaultTier } from '../vault/vault-types.js';
14
+ import type { AgentRuntime } from './types.js';
15
+
16
+ export function createTierOps(runtime: AgentRuntime): OpDefinition[] {
17
+ const { vaultManager } = runtime;
18
+
19
+ return [
20
+ // ─── Multi-vault ops ────────────────────────────────────────
21
+ {
22
+ name: 'vault_connect',
23
+ description:
24
+ 'Connect an additional vault tier (project or team). Opens a separate SQLite database.',
25
+ auth: 'admin',
26
+ schema: z.object({
27
+ tier: z.enum(['project', 'team']).describe('Vault tier to connect'),
28
+ path: z.string().describe('Path to the SQLite database file'),
29
+ }),
30
+ handler: async (params) => {
31
+ const tier = params.tier as VaultTier;
32
+ const path = params.path as string;
33
+ vaultManager.open(tier, path);
34
+ return { connected: true, tier, path };
35
+ },
36
+ },
37
+ {
38
+ name: 'vault_disconnect',
39
+ description: 'Disconnect a vault tier. Cannot disconnect the agent tier.',
40
+ auth: 'admin',
41
+ schema: z.object({
42
+ tier: z.enum(['project', 'team']).describe('Vault tier to disconnect'),
43
+ }),
44
+ handler: async (params) => {
45
+ const tier = params.tier as VaultTier;
46
+ const removed = vaultManager.disconnect(tier);
47
+ return { disconnected: removed, tier };
48
+ },
49
+ },
50
+ {
51
+ name: 'vault_tiers',
52
+ description: 'List all vault tiers with connection status and entry counts.',
53
+ auth: 'read',
54
+ handler: async () => {
55
+ return { tiers: vaultManager.listTiers() };
56
+ },
57
+ },
58
+ {
59
+ name: 'vault_search_all',
60
+ description:
61
+ 'Search across all connected vault tiers with priority-weighted cascading. Agent tier results ranked highest.',
62
+ auth: 'read',
63
+ schema: z.object({
64
+ query: z.string(),
65
+ limit: z.number().optional(),
66
+ }),
67
+ handler: async (params) => {
68
+ const results = vaultManager.search(params.query as string, (params.limit as number) ?? 20);
69
+ return { results, count: results.length };
70
+ },
71
+ },
72
+
73
+ // ─── Named vault connections ────────────────────────────────
74
+ {
75
+ name: 'vault_connect_source',
76
+ description:
77
+ 'Connect a named vault source (e.g., shared team knowledge base) with a configurable search priority.',
78
+ auth: 'admin',
79
+ schema: z.object({
80
+ name: z.string().describe('Unique name for this vault connection'),
81
+ path: z.string().describe('Path to the SQLite database file'),
82
+ priority: z
83
+ .number()
84
+ .min(0)
85
+ .max(2)
86
+ .optional()
87
+ .describe('Search priority weight (default: 0.5)'),
88
+ }),
89
+ handler: async (params) => {
90
+ const name = params.name as string;
91
+ const path = params.path as string;
92
+ const priority = (params.priority as number) ?? 0.5;
93
+ vaultManager.connect(name, path, priority);
94
+ return { connected: true, name, path, priority };
95
+ },
96
+ },
97
+ {
98
+ name: 'vault_disconnect_source',
99
+ description: 'Disconnect a named vault source.',
100
+ auth: 'admin',
101
+ schema: z.object({
102
+ name: z.string().describe('Name of the vault connection to remove'),
103
+ }),
104
+ handler: async (params) => {
105
+ const name = params.name as string;
106
+ const removed = vaultManager.disconnectNamed(name);
107
+ return { disconnected: removed, name };
108
+ },
109
+ },
110
+ {
111
+ name: 'vault_list_sources',
112
+ description: 'List all dynamically connected vault sources with their priorities.',
113
+ auth: 'read',
114
+ handler: async () => {
115
+ return { sources: vaultManager.listConnected() };
116
+ },
117
+ },
118
+ ];
119
+ }
@@ -91,12 +91,18 @@ describe('createVaultExtraOps', () => {
91
91
 
92
92
  describe('vault_get', () => {
93
93
  it('returns entry by ID', async () => {
94
- const result = (await findOp(ops, 'vault_get').handler({ id: 'entry-1' })) as Record<string, unknown>;
94
+ const result = (await findOp(ops, 'vault_get').handler({ id: 'entry-1' })) as Record<
95
+ string,
96
+ unknown
97
+ >;
95
98
  expect(result.id).toBe('entry-1');
96
99
  });
97
100
 
98
101
  it('returns error for missing entry', async () => {
99
- const result = (await findOp(ops, 'vault_get').handler({ id: 'missing' })) as Record<string, unknown>;
102
+ const result = (await findOp(ops, 'vault_get').handler({ id: 'missing' })) as Record<
103
+ string,
104
+ unknown
105
+ >;
100
106
  expect(result.error).toContain('not found');
101
107
  });
102
108
  });
@@ -112,7 +118,10 @@ describe('createVaultExtraOps', () => {
112
118
  });
113
119
 
114
120
  it('returns error when no fields provided', async () => {
115
- const result = (await findOp(ops, 'vault_update').handler({ id: 'entry-1' })) as Record<string, unknown>;
121
+ const result = (await findOp(ops, 'vault_update').handler({ id: 'entry-1' })) as Record<
122
+ string,
123
+ unknown
124
+ >;
116
125
  expect(result.error).toBe('No fields to update');
117
126
  });
118
127
 
@@ -128,7 +137,10 @@ describe('createVaultExtraOps', () => {
128
137
 
129
138
  describe('vault_remove', () => {
130
139
  it('removes entry by ID', async () => {
131
- const result = (await findOp(ops, 'vault_remove').handler({ id: 'entry-1' })) as Record<string, unknown>;
140
+ const result = (await findOp(ops, 'vault_remove').handler({ id: 'entry-1' })) as Record<
141
+ string,
142
+ unknown
143
+ >;
132
144
  expect(result.removed).toBe(true);
133
145
  expect(result.id).toBe('entry-1');
134
146
  });
@@ -137,7 +149,10 @@ describe('createVaultExtraOps', () => {
137
149
  describe('vault_bulk_add', () => {
138
150
  it('seeds multiple entries', async () => {
139
151
  const entries = [makeEntry({ id: 'a' }), makeEntry({ id: 'b' })];
140
- const result = (await findOp(ops, 'vault_bulk_add').handler({ entries })) as Record<string, unknown>;
152
+ const result = (await findOp(ops, 'vault_bulk_add').handler({ entries })) as Record<
153
+ string,
154
+ unknown
155
+ >;
141
156
  expect(result.added).toBe(2);
142
157
  expect(result.total).toBe(10);
143
158
  });
@@ -186,7 +201,10 @@ describe('createVaultExtraOps', () => {
186
201
  .mockReturnValueOnce({ totalEntries: 10 } as unknown)
187
202
  .mockReturnValueOnce({ totalEntries: 12 } as unknown);
188
203
  const entries = [makeEntry({ id: 'x' }), makeEntry({ id: 'y' })];
189
- const result = (await findOp(ops, 'vault_import').handler({ entries })) as Record<string, unknown>;
204
+ const result = (await findOp(ops, 'vault_import').handler({ entries })) as Record<
205
+ string,
206
+ unknown
207
+ >;
190
208
  expect(result.imported).toBe(2);
191
209
  expect(result.newEntries).toBe(2);
192
210
  expect(result.total).toBe(12);
@@ -196,7 +214,10 @@ describe('createVaultExtraOps', () => {
196
214
  describe('vault_seed', () => {
197
215
  it('seeds entries idempotently', async () => {
198
216
  const entries = [makeEntry()];
199
- const result = (await findOp(ops, 'vault_seed').handler({ entries })) as Record<string, unknown>;
217
+ const result = (await findOp(ops, 'vault_seed').handler({ entries })) as Record<
218
+ string,
219
+ unknown
220
+ >;
200
221
  expect(result.seeded).toBe(1);
201
222
  });
202
223
  });
@@ -237,7 +258,10 @@ describe('createVaultExtraOps', () => {
237
258
 
238
259
  describe('vault_dedup_status', () => {
239
260
  it('reports dedup statistics with coverage', async () => {
240
- const result = (await findOp(ops, 'vault_dedup_status').handler({})) as Record<string, unknown>;
261
+ const result = (await findOp(ops, 'vault_dedup_status').handler({})) as Record<
262
+ string,
263
+ unknown
264
+ >;
241
265
  expect(result.total).toBe(10);
242
266
  expect(result.duplicates).toBe(2);
243
267
  expect(result.coverage).toBe(90);
@@ -83,10 +83,7 @@ describe('createVaultSharingOps', () => {
83
83
  it('returns error when entry not found', async () => {
84
84
  const op = findOp(ops, 'vault_set_scope');
85
85
  vi.mocked(rt.vault.get).mockReturnValue(undefined as never);
86
- const result = (await op.handler({ id: 'missing', tier: 'team' })) as Record<
87
- string,
88
- unknown
89
- >;
86
+ const result = (await op.handler({ id: 'missing', tier: 'team' })) as Record<string, unknown>;
90
87
  expect(result.error).toContain('not found');
91
88
  });
92
89
 
@@ -6,14 +6,7 @@
6
6
  * Called automatically at engine startup and by admin_setup_global.
7
7
  */
8
8
 
9
- import {
10
- existsSync,
11
- readdirSync,
12
- readFileSync,
13
- writeFileSync,
14
- mkdirSync,
15
- statSync,
16
- } from 'node:fs';
9
+ import { existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, statSync } from 'node:fs';
17
10
  import { join } from 'node:path';
18
11
  import { homedir } from 'node:os';
19
12
 
@@ -68,10 +61,7 @@ function brandSkillContent(content: string, agentName: string): string {
68
61
  * - Changed skills are overwritten (compared by mtime)
69
62
  * - Missing source skills leave target untouched (other agents may own them)
70
63
  */
71
- export function syncSkillsToClaudeCode(
72
- skillsDirs: string[],
73
- agentName?: string,
74
- ): SyncResult {
64
+ export function syncSkillsToClaudeCode(skillsDirs: string[], agentName?: string): SyncResult {
75
65
  const commandsDir = join(homedir(), '.claude', 'commands');
76
66
  const skills = discoverSkills(skillsDirs);
77
67
  const result: SyncResult = { installed: [], updated: [], skipped: [], failed: [] };
@@ -48,11 +48,11 @@ function encodeTextFrame(text: string, masked = true): Buffer {
48
48
  if (len < 126) {
49
49
  header = Buffer.alloc(2);
50
50
  header[0] = 0x81; // FIN + TEXT
51
- header[1] = masked ? (len | 0x80) : len;
51
+ header[1] = masked ? len | 0x80 : len;
52
52
  } else {
53
53
  header = Buffer.alloc(4);
54
54
  header[0] = 0x81;
55
- header[1] = masked ? (126 | 0x80) : 126;
55
+ header[1] = masked ? 126 | 0x80 : 126;
56
56
  header.writeUInt16BE(len, 2);
57
57
  }
58
58
 
@@ -86,7 +86,8 @@ describe('WsMcpServer', () => {
86
86
  const httpServer = (server as unknown).server as Server | undefined;
87
87
  if (httpServer) {
88
88
  // Force immediate close of all tracked sockets
89
- for (const conn of ((server as unknown).connections as Map<string, unknown>)?.values() ?? []) {
89
+ for (const conn of ((server as unknown).connections as Map<string, unknown>)?.values() ??
90
+ []) {
90
91
  conn.socket?.destroy();
91
92
  }
92
93
  ((server as unknown).connections as Map<string, unknown>)?.clear();
@@ -160,7 +161,9 @@ describe('WsMcpServer', () => {
160
161
  if (!addr || typeof addr === 'string') return;
161
162
 
162
163
  const wsKey = 'dGhlIHNhbXBsZSBub25jZQ==';
163
- const expectedAccept = createHash('sha1').update(wsKey + WS_MAGIC).digest('base64');
164
+ const expectedAccept = createHash('sha1')
165
+ .update(wsKey + WS_MAGIC)
166
+ .digest('base64');
164
167
 
165
168
  const socket = connect(addr.port, '127.0.0.1');
166
169
  await new Promise<void>((resolve) => socket.on('connect', resolve));