@soleri/core 2.4.0 → 2.6.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 (328) hide show
  1. package/dist/brain/brain.d.ts +7 -0
  2. package/dist/brain/brain.d.ts.map +1 -1
  3. package/dist/brain/brain.js +56 -9
  4. package/dist/brain/brain.js.map +1 -1
  5. package/dist/brain/intelligence.d.ts +1 -0
  6. package/dist/brain/intelligence.d.ts.map +1 -1
  7. package/dist/brain/intelligence.js +164 -148
  8. package/dist/brain/intelligence.js.map +1 -1
  9. package/dist/brain/types.d.ts +2 -2
  10. package/dist/brain/types.d.ts.map +1 -1
  11. package/dist/cognee/client.d.ts +3 -0
  12. package/dist/cognee/client.d.ts.map +1 -1
  13. package/dist/cognee/client.js +17 -0
  14. package/dist/cognee/client.js.map +1 -1
  15. package/dist/cognee/sync-manager.d.ts +94 -0
  16. package/dist/cognee/sync-manager.d.ts.map +1 -0
  17. package/dist/cognee/sync-manager.js +293 -0
  18. package/dist/cognee/sync-manager.js.map +1 -0
  19. package/dist/control/identity-manager.d.ts +3 -1
  20. package/dist/control/identity-manager.d.ts.map +1 -1
  21. package/dist/control/identity-manager.js +49 -51
  22. package/dist/control/identity-manager.js.map +1 -1
  23. package/dist/control/intent-router.d.ts +1 -0
  24. package/dist/control/intent-router.d.ts.map +1 -1
  25. package/dist/control/intent-router.js +32 -32
  26. package/dist/control/intent-router.js.map +1 -1
  27. package/dist/curator/curator.d.ts +9 -1
  28. package/dist/curator/curator.d.ts.map +1 -1
  29. package/dist/curator/curator.js +104 -92
  30. package/dist/curator/curator.js.map +1 -1
  31. package/dist/errors/classify.d.ts +13 -0
  32. package/dist/errors/classify.d.ts.map +1 -0
  33. package/dist/errors/classify.js +97 -0
  34. package/dist/errors/classify.js.map +1 -0
  35. package/dist/errors/index.d.ts +6 -0
  36. package/dist/errors/index.d.ts.map +1 -0
  37. package/dist/errors/index.js +4 -0
  38. package/dist/errors/index.js.map +1 -0
  39. package/dist/errors/retry.d.ts +40 -0
  40. package/dist/errors/retry.d.ts.map +1 -0
  41. package/dist/errors/retry.js +97 -0
  42. package/dist/errors/retry.js.map +1 -0
  43. package/dist/errors/types.d.ts +48 -0
  44. package/dist/errors/types.d.ts.map +1 -0
  45. package/dist/errors/types.js +59 -0
  46. package/dist/errors/types.js.map +1 -0
  47. package/dist/governance/governance.d.ts +1 -0
  48. package/dist/governance/governance.d.ts.map +1 -1
  49. package/dist/governance/governance.js +51 -68
  50. package/dist/governance/governance.js.map +1 -1
  51. package/dist/index.d.ts +26 -5
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +22 -3
  54. package/dist/index.js.map +1 -1
  55. package/dist/intake/content-classifier.d.ts +14 -0
  56. package/dist/intake/content-classifier.d.ts.map +1 -0
  57. package/dist/intake/content-classifier.js +125 -0
  58. package/dist/intake/content-classifier.js.map +1 -0
  59. package/dist/intake/dedup-gate.d.ts +17 -0
  60. package/dist/intake/dedup-gate.d.ts.map +1 -0
  61. package/dist/intake/dedup-gate.js +66 -0
  62. package/dist/intake/dedup-gate.js.map +1 -0
  63. package/dist/intake/intake-pipeline.d.ts +63 -0
  64. package/dist/intake/intake-pipeline.d.ts.map +1 -0
  65. package/dist/intake/intake-pipeline.js +373 -0
  66. package/dist/intake/intake-pipeline.js.map +1 -0
  67. package/dist/intake/types.d.ts +65 -0
  68. package/dist/intake/types.d.ts.map +1 -0
  69. package/dist/intake/types.js +3 -0
  70. package/dist/intake/types.js.map +1 -0
  71. package/dist/intelligence/loader.js +1 -1
  72. package/dist/intelligence/loader.js.map +1 -1
  73. package/dist/intelligence/types.d.ts +3 -1
  74. package/dist/intelligence/types.d.ts.map +1 -1
  75. package/dist/loop/loop-manager.d.ts +58 -7
  76. package/dist/loop/loop-manager.d.ts.map +1 -1
  77. package/dist/loop/loop-manager.js +280 -6
  78. package/dist/loop/loop-manager.js.map +1 -1
  79. package/dist/loop/types.d.ts +69 -1
  80. package/dist/loop/types.d.ts.map +1 -1
  81. package/dist/loop/types.js +4 -1
  82. package/dist/loop/types.js.map +1 -1
  83. package/dist/persistence/index.d.ts +4 -0
  84. package/dist/persistence/index.d.ts.map +1 -0
  85. package/dist/persistence/index.js +3 -0
  86. package/dist/persistence/index.js.map +1 -0
  87. package/dist/persistence/postgres-provider.d.ts +46 -0
  88. package/dist/persistence/postgres-provider.d.ts.map +1 -0
  89. package/dist/persistence/postgres-provider.js +115 -0
  90. package/dist/persistence/postgres-provider.js.map +1 -0
  91. package/dist/persistence/sqlite-provider.d.ts +28 -0
  92. package/dist/persistence/sqlite-provider.d.ts.map +1 -0
  93. package/dist/persistence/sqlite-provider.js +97 -0
  94. package/dist/persistence/sqlite-provider.js.map +1 -0
  95. package/dist/persistence/types.d.ts +58 -0
  96. package/dist/persistence/types.d.ts.map +1 -0
  97. package/dist/persistence/types.js +8 -0
  98. package/dist/persistence/types.js.map +1 -0
  99. package/dist/planning/gap-analysis.d.ts +47 -4
  100. package/dist/planning/gap-analysis.d.ts.map +1 -1
  101. package/dist/planning/gap-analysis.js +190 -13
  102. package/dist/planning/gap-analysis.js.map +1 -1
  103. package/dist/planning/gap-types.d.ts +1 -1
  104. package/dist/planning/gap-types.d.ts.map +1 -1
  105. package/dist/planning/gap-types.js.map +1 -1
  106. package/dist/planning/planner.d.ts +277 -9
  107. package/dist/planning/planner.d.ts.map +1 -1
  108. package/dist/planning/planner.js +611 -46
  109. package/dist/planning/planner.js.map +1 -1
  110. package/dist/playbooks/generic/brainstorming.d.ts +9 -0
  111. package/dist/playbooks/generic/brainstorming.d.ts.map +1 -0
  112. package/dist/playbooks/generic/brainstorming.js +105 -0
  113. package/dist/playbooks/generic/brainstorming.js.map +1 -0
  114. package/dist/playbooks/generic/code-review.d.ts +11 -0
  115. package/dist/playbooks/generic/code-review.d.ts.map +1 -0
  116. package/dist/playbooks/generic/code-review.js +176 -0
  117. package/dist/playbooks/generic/code-review.js.map +1 -0
  118. package/dist/playbooks/generic/subagent-execution.d.ts +9 -0
  119. package/dist/playbooks/generic/subagent-execution.d.ts.map +1 -0
  120. package/dist/playbooks/generic/subagent-execution.js +68 -0
  121. package/dist/playbooks/generic/subagent-execution.js.map +1 -0
  122. package/dist/playbooks/generic/systematic-debugging.d.ts +9 -0
  123. package/dist/playbooks/generic/systematic-debugging.d.ts.map +1 -0
  124. package/dist/playbooks/generic/systematic-debugging.js +87 -0
  125. package/dist/playbooks/generic/systematic-debugging.js.map +1 -0
  126. package/dist/playbooks/generic/tdd.d.ts +9 -0
  127. package/dist/playbooks/generic/tdd.d.ts.map +1 -0
  128. package/dist/playbooks/generic/tdd.js +70 -0
  129. package/dist/playbooks/generic/tdd.js.map +1 -0
  130. package/dist/playbooks/generic/verification.d.ts +9 -0
  131. package/dist/playbooks/generic/verification.d.ts.map +1 -0
  132. package/dist/playbooks/generic/verification.js +74 -0
  133. package/dist/playbooks/generic/verification.js.map +1 -0
  134. package/dist/playbooks/index.d.ts +4 -0
  135. package/dist/playbooks/index.d.ts.map +1 -0
  136. package/dist/playbooks/index.js +5 -0
  137. package/dist/playbooks/index.js.map +1 -0
  138. package/dist/playbooks/playbook-registry.d.ts +42 -0
  139. package/dist/playbooks/playbook-registry.d.ts.map +1 -0
  140. package/dist/playbooks/playbook-registry.js +227 -0
  141. package/dist/playbooks/playbook-registry.js.map +1 -0
  142. package/dist/playbooks/playbook-seeder.d.ts +47 -0
  143. package/dist/playbooks/playbook-seeder.d.ts.map +1 -0
  144. package/dist/playbooks/playbook-seeder.js +104 -0
  145. package/dist/playbooks/playbook-seeder.js.map +1 -0
  146. package/dist/playbooks/playbook-types.d.ts +132 -0
  147. package/dist/playbooks/playbook-types.d.ts.map +1 -0
  148. package/dist/playbooks/playbook-types.js +12 -0
  149. package/dist/playbooks/playbook-types.js.map +1 -0
  150. package/dist/project/project-registry.d.ts +4 -4
  151. package/dist/project/project-registry.d.ts.map +1 -1
  152. package/dist/project/project-registry.js +30 -57
  153. package/dist/project/project-registry.js.map +1 -1
  154. package/dist/prompts/index.d.ts +4 -0
  155. package/dist/prompts/index.d.ts.map +1 -0
  156. package/dist/prompts/index.js +3 -0
  157. package/dist/prompts/index.js.map +1 -0
  158. package/dist/prompts/parser.d.ts +17 -0
  159. package/dist/prompts/parser.d.ts.map +1 -0
  160. package/dist/prompts/parser.js +47 -0
  161. package/dist/prompts/parser.js.map +1 -0
  162. package/dist/prompts/template-manager.d.ts +25 -0
  163. package/dist/prompts/template-manager.d.ts.map +1 -0
  164. package/dist/prompts/template-manager.js +71 -0
  165. package/dist/prompts/template-manager.js.map +1 -0
  166. package/dist/prompts/types.d.ts +26 -0
  167. package/dist/prompts/types.d.ts.map +1 -0
  168. package/dist/prompts/types.js +5 -0
  169. package/dist/prompts/types.js.map +1 -0
  170. package/dist/runtime/admin-extra-ops.d.ts +5 -3
  171. package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
  172. package/dist/runtime/admin-extra-ops.js +348 -11
  173. package/dist/runtime/admin-extra-ops.js.map +1 -1
  174. package/dist/runtime/admin-ops.d.ts.map +1 -1
  175. package/dist/runtime/admin-ops.js +10 -3
  176. package/dist/runtime/admin-ops.js.map +1 -1
  177. package/dist/runtime/capture-ops.d.ts.map +1 -1
  178. package/dist/runtime/capture-ops.js +20 -2
  179. package/dist/runtime/capture-ops.js.map +1 -1
  180. package/dist/runtime/cognee-sync-ops.d.ts +12 -0
  181. package/dist/runtime/cognee-sync-ops.d.ts.map +1 -0
  182. package/dist/runtime/cognee-sync-ops.js +55 -0
  183. package/dist/runtime/cognee-sync-ops.js.map +1 -0
  184. package/dist/runtime/core-ops.d.ts +8 -6
  185. package/dist/runtime/core-ops.d.ts.map +1 -1
  186. package/dist/runtime/core-ops.js +226 -9
  187. package/dist/runtime/core-ops.js.map +1 -1
  188. package/dist/runtime/curator-extra-ops.d.ts +2 -2
  189. package/dist/runtime/curator-extra-ops.d.ts.map +1 -1
  190. package/dist/runtime/curator-extra-ops.js +15 -3
  191. package/dist/runtime/curator-extra-ops.js.map +1 -1
  192. package/dist/runtime/domain-ops.js +2 -2
  193. package/dist/runtime/domain-ops.js.map +1 -1
  194. package/dist/runtime/grading-ops.d.ts.map +1 -1
  195. package/dist/runtime/grading-ops.js.map +1 -1
  196. package/dist/runtime/intake-ops.d.ts +14 -0
  197. package/dist/runtime/intake-ops.d.ts.map +1 -0
  198. package/dist/runtime/intake-ops.js +110 -0
  199. package/dist/runtime/intake-ops.js.map +1 -0
  200. package/dist/runtime/loop-ops.d.ts +5 -4
  201. package/dist/runtime/loop-ops.d.ts.map +1 -1
  202. package/dist/runtime/loop-ops.js +84 -12
  203. package/dist/runtime/loop-ops.js.map +1 -1
  204. package/dist/runtime/memory-cross-project-ops.d.ts.map +1 -1
  205. package/dist/runtime/memory-cross-project-ops.js.map +1 -1
  206. package/dist/runtime/memory-extra-ops.js +5 -5
  207. package/dist/runtime/memory-extra-ops.js.map +1 -1
  208. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  209. package/dist/runtime/orchestrate-ops.js +8 -2
  210. package/dist/runtime/orchestrate-ops.js.map +1 -1
  211. package/dist/runtime/planning-extra-ops.d.ts +13 -5
  212. package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
  213. package/dist/runtime/planning-extra-ops.js +381 -18
  214. package/dist/runtime/planning-extra-ops.js.map +1 -1
  215. package/dist/runtime/playbook-ops.d.ts +14 -0
  216. package/dist/runtime/playbook-ops.d.ts.map +1 -0
  217. package/dist/runtime/playbook-ops.js +141 -0
  218. package/dist/runtime/playbook-ops.js.map +1 -0
  219. package/dist/runtime/project-ops.d.ts.map +1 -1
  220. package/dist/runtime/project-ops.js +7 -2
  221. package/dist/runtime/project-ops.js.map +1 -1
  222. package/dist/runtime/runtime.d.ts.map +1 -1
  223. package/dist/runtime/runtime.js +28 -9
  224. package/dist/runtime/runtime.js.map +1 -1
  225. package/dist/runtime/types.d.ts +8 -0
  226. package/dist/runtime/types.d.ts.map +1 -1
  227. package/dist/runtime/vault-extra-ops.d.ts +4 -2
  228. package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
  229. package/dist/runtime/vault-extra-ops.js +383 -4
  230. package/dist/runtime/vault-extra-ops.js.map +1 -1
  231. package/dist/vault/playbook.d.ts +34 -0
  232. package/dist/vault/playbook.d.ts.map +1 -0
  233. package/dist/vault/playbook.js +60 -0
  234. package/dist/vault/playbook.js.map +1 -0
  235. package/dist/vault/vault.d.ts +52 -32
  236. package/dist/vault/vault.d.ts.map +1 -1
  237. package/dist/vault/vault.js +300 -181
  238. package/dist/vault/vault.js.map +1 -1
  239. package/package.json +9 -3
  240. package/src/__tests__/admin-extra-ops.test.ts +62 -15
  241. package/src/__tests__/admin-ops.test.ts +2 -2
  242. package/src/__tests__/brain.test.ts +3 -3
  243. package/src/__tests__/cognee-integration.test.ts +80 -0
  244. package/src/__tests__/cognee-sync-manager.test.ts +103 -0
  245. package/src/__tests__/core-ops.test.ts +36 -4
  246. package/src/__tests__/curator-extra-ops.test.ts +24 -2
  247. package/src/__tests__/errors.test.ts +388 -0
  248. package/src/__tests__/grading-ops.test.ts +28 -7
  249. package/src/__tests__/intake-pipeline.test.ts +162 -0
  250. package/src/__tests__/loop-ops.test.ts +74 -3
  251. package/src/__tests__/memory-cross-project-ops.test.ts +3 -1
  252. package/src/__tests__/orchestrate-ops.test.ts +8 -3
  253. package/src/__tests__/persistence.test.ts +291 -0
  254. package/src/__tests__/planner.test.ts +99 -21
  255. package/src/__tests__/planning-extra-ops.test.ts +168 -10
  256. package/src/__tests__/playbook-registry.test.ts +326 -0
  257. package/src/__tests__/playbook-seeder.test.ts +163 -0
  258. package/src/__tests__/playbook.test.ts +389 -0
  259. package/src/__tests__/postgres-provider.test.ts +58 -0
  260. package/src/__tests__/project-ops.test.ts +18 -4
  261. package/src/__tests__/template-manager.test.ts +222 -0
  262. package/src/__tests__/vault-extra-ops.test.ts +82 -7
  263. package/src/__tests__/vault.test.ts +184 -0
  264. package/src/brain/brain.ts +71 -9
  265. package/src/brain/intelligence.ts +258 -307
  266. package/src/brain/types.ts +2 -2
  267. package/src/cognee/client.ts +18 -0
  268. package/src/cognee/sync-manager.ts +389 -0
  269. package/src/control/identity-manager.ts +77 -75
  270. package/src/control/intent-router.ts +55 -57
  271. package/src/curator/curator.ts +199 -139
  272. package/src/errors/classify.ts +102 -0
  273. package/src/errors/index.ts +5 -0
  274. package/src/errors/retry.ts +132 -0
  275. package/src/errors/types.ts +81 -0
  276. package/src/governance/governance.ts +90 -107
  277. package/src/index.ts +116 -3
  278. package/src/intake/content-classifier.ts +146 -0
  279. package/src/intake/dedup-gate.ts +92 -0
  280. package/src/intake/intake-pipeline.ts +503 -0
  281. package/src/intake/types.ts +69 -0
  282. package/src/intelligence/loader.ts +1 -1
  283. package/src/intelligence/types.ts +3 -1
  284. package/src/loop/loop-manager.ts +325 -7
  285. package/src/loop/types.ts +72 -1
  286. package/src/persistence/index.ts +9 -0
  287. package/src/persistence/postgres-provider.ts +157 -0
  288. package/src/persistence/sqlite-provider.ts +115 -0
  289. package/src/persistence/types.ts +74 -0
  290. package/src/planning/gap-analysis.ts +286 -17
  291. package/src/planning/gap-types.ts +4 -1
  292. package/src/planning/planner.ts +828 -55
  293. package/src/playbooks/generic/brainstorming.ts +110 -0
  294. package/src/playbooks/generic/code-review.ts +181 -0
  295. package/src/playbooks/generic/subagent-execution.ts +74 -0
  296. package/src/playbooks/generic/systematic-debugging.ts +92 -0
  297. package/src/playbooks/generic/tdd.ts +75 -0
  298. package/src/playbooks/generic/verification.ts +79 -0
  299. package/src/playbooks/index.ts +27 -0
  300. package/src/playbooks/playbook-registry.ts +284 -0
  301. package/src/playbooks/playbook-seeder.ts +119 -0
  302. package/src/playbooks/playbook-types.ts +162 -0
  303. package/src/project/project-registry.ts +81 -74
  304. package/src/prompts/index.ts +3 -0
  305. package/src/prompts/parser.ts +59 -0
  306. package/src/prompts/template-manager.ts +77 -0
  307. package/src/prompts/types.ts +28 -0
  308. package/src/runtime/admin-extra-ops.ts +391 -13
  309. package/src/runtime/admin-ops.ts +17 -6
  310. package/src/runtime/capture-ops.ts +25 -6
  311. package/src/runtime/cognee-sync-ops.ts +63 -0
  312. package/src/runtime/core-ops.ts +258 -8
  313. package/src/runtime/curator-extra-ops.ts +17 -3
  314. package/src/runtime/domain-ops.ts +2 -2
  315. package/src/runtime/grading-ops.ts +11 -2
  316. package/src/runtime/intake-ops.ts +126 -0
  317. package/src/runtime/loop-ops.ts +96 -13
  318. package/src/runtime/memory-cross-project-ops.ts +1 -2
  319. package/src/runtime/memory-extra-ops.ts +5 -5
  320. package/src/runtime/orchestrate-ops.ts +8 -2
  321. package/src/runtime/planning-extra-ops.ts +414 -23
  322. package/src/runtime/playbook-ops.ts +169 -0
  323. package/src/runtime/project-ops.ts +9 -3
  324. package/src/runtime/runtime.ts +36 -10
  325. package/src/runtime/types.ts +8 -0
  326. package/src/runtime/vault-extra-ops.ts +425 -4
  327. package/src/vault/playbook.ts +87 -0
  328. package/src/vault/vault.ts +419 -235
@@ -1,18 +1,39 @@
1
1
  /**
2
- * Extended admin operations — 10 ops for production readiness.
2
+ * Extended admin operations — 24 ops for production readiness.
3
3
  *
4
4
  * Groups: telemetry (3), permissions (1), vault analytics (1),
5
- * search insights (1), module status (1), env (1), gc (1), export config (1).
5
+ * search insights (1), module status (1), env (1), gc (1), export config (1),
6
+ * key pool (4), profiles (5), plugins (2), instruction validation (1),
7
+ * hot reload (1), persistence (1).
6
8
  */
7
9
 
8
10
  import { z } from 'zod';
11
+ import { readFileSync, existsSync } from 'node:fs';
9
12
  import type { OpDefinition } from '../facades/types.js';
10
13
  import type { AgentRuntime } from './types.js';
11
14
 
12
15
  type PermissionLevel = 'strict' | 'moderate' | 'permissive';
13
16
 
17
+ interface ApiToken {
18
+ name: string;
19
+ role: string;
20
+ createdAt: number;
21
+ }
22
+ interface AccountProfile {
23
+ name: string;
24
+ provider: string;
25
+ active: boolean;
26
+ addedAt: number;
27
+ }
28
+ interface PluginInfo {
29
+ id: string;
30
+ name: string;
31
+ status: 'active' | 'inactive' | 'error';
32
+ opsCount: number;
33
+ }
34
+
14
35
  /**
15
- * Create 10 extended admin operations for production observability.
36
+ * Create 24 extended admin operations for production observability.
16
37
  */
17
38
  export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
18
39
  const { vault, brain, cognee, telemetry } = runtime;
@@ -102,9 +123,9 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
102
123
  '90d+': 0,
103
124
  };
104
125
 
105
- const rows = db
106
- .prepare('SELECT created_at FROM entries')
107
- .all() as Array<{ created_at: number }>;
126
+ const rows = db.prepare('SELECT created_at FROM entries').all() as Array<{
127
+ created_at: number;
128
+ }>;
108
129
 
109
130
  for (const row of rows) {
110
131
  const ageSeconds = now - row.created_at;
@@ -115,9 +136,7 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
115
136
  }
116
137
 
117
138
  // Average tags per entry
118
- const tagRows = db
119
- .prepare('SELECT tags FROM entries')
120
- .all() as Array<{ tags: string }>;
139
+ const tagRows = db.prepare('SELECT tags FROM entries').all() as Array<{ tags: string }>;
121
140
 
122
141
  let totalTags = 0;
123
142
  let noTags = 0;
@@ -135,7 +154,9 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
135
154
 
136
155
  // Entries without descriptions
137
156
  const noDescResult = db
138
- .prepare("SELECT COUNT(*) as count FROM entries WHERE description IS NULL OR description = ''")
157
+ .prepare(
158
+ "SELECT COUNT(*) as count FROM entries WHERE description IS NULL OR description = ''",
159
+ )
139
160
  .get() as { count: number } | undefined;
140
161
  noDescription = noDescResult?.count ?? 0;
141
162
 
@@ -146,12 +167,16 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
146
167
  byDomain: Object.fromEntries(byDomain.map((r) => [r.domain, r.count])),
147
168
  byType: Object.fromEntries(byType.map((r) => [r.type, r.count])),
148
169
  byAge: ageBuckets,
149
- avgTagsPerEntry: totalEntries > 0 ? Math.round((totalTags / totalEntries) * 10) / 10 : 0,
170
+ avgTagsPerEntry:
171
+ totalEntries > 0 ? Math.round((totalTags / totalEntries) * 10) / 10 : 0,
150
172
  entriesWithoutTags: noTags,
151
173
  entriesWithoutDescription: noDescription,
152
174
  };
153
175
  } catch (err) {
154
- return { error: 'Failed to compute vault analytics', detail: err instanceof Error ? err.message : String(err) };
176
+ return {
177
+ error: 'Failed to compute vault analytics',
178
+ detail: err instanceof Error ? err.message : String(err),
179
+ };
155
180
  }
156
181
  },
157
182
  },
@@ -185,7 +210,7 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
185
210
  topMissedQueries: missedQueries,
186
211
  byAction: feedbackStats.byAction,
187
212
  };
188
- } catch (err) {
213
+ } catch {
189
214
  return {
190
215
  totalFeedback: 0,
191
216
  missRate: 0,
@@ -303,5 +328,358 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
303
328
  };
304
329
  },
305
330
  },
331
+
332
+ // ─── Key Pool (#157) ──────────────────────────────────────────
333
+ {
334
+ name: 'admin_key_pool_status',
335
+ description:
336
+ 'LLM key pool status — pool size, active key index, per-key circuit breaker state (open/closed/half-open).',
337
+ auth: 'read',
338
+ handler: async () => {
339
+ const available = runtime.llmClient.isAvailable();
340
+ return {
341
+ openai: {
342
+ available: available.openai,
343
+ },
344
+ anthropic: {
345
+ available: available.anthropic,
346
+ },
347
+ };
348
+ },
349
+ },
350
+ {
351
+ name: 'admin_create_token',
352
+ description: 'Create a named API token with role-based access.',
353
+ auth: 'admin',
354
+ schema: z.object({
355
+ name: z.string().describe('Token name (unique identifier)'),
356
+ role: z.enum(['read', 'write', 'admin']).describe('Access role'),
357
+ }),
358
+ handler: async (params) => {
359
+ const token: ApiToken = {
360
+ name: params.name as string,
361
+ role: params.role as string,
362
+ createdAt: Date.now(),
363
+ };
364
+ // Store in vault metadata
365
+ vault.add({
366
+ id: `api-token-${token.name}`,
367
+ type: 'rule',
368
+ domain: 'admin',
369
+ title: `API Token: ${token.name}`,
370
+ severity: 'suggestion',
371
+ description: `API token with ${token.role} access`,
372
+ tags: ['api-token', token.role],
373
+ });
374
+ return { created: true, name: token.name, role: token.role };
375
+ },
376
+ },
377
+ {
378
+ name: 'admin_revoke_token',
379
+ description: 'Revoke (delete) a named API token.',
380
+ auth: 'admin',
381
+ schema: z.object({
382
+ name: z.string().describe('Token name to revoke'),
383
+ }),
384
+ handler: async (params) => {
385
+ const removed = vault.remove(`api-token-${params.name}`);
386
+ return { revoked: removed, name: params.name };
387
+ },
388
+ },
389
+ {
390
+ name: 'admin_list_tokens',
391
+ description: 'List all API tokens (names and roles only, no secrets).',
392
+ auth: 'read',
393
+ handler: async () => {
394
+ const entries = vault.list({ domain: 'admin' });
395
+ const tokens = entries
396
+ .filter((e) => e.id.startsWith('api-token-'))
397
+ .map((e) => ({
398
+ name: e.id.replace('api-token-', ''),
399
+ role: e.tags?.find((t) => ['read', 'write', 'admin'].includes(t)) ?? 'unknown',
400
+ }));
401
+ return { tokens, count: tokens.length };
402
+ },
403
+ },
404
+
405
+ // ─── Account Profiles (#158) ─────────────────────────────────
406
+ {
407
+ name: 'admin_add_account',
408
+ description: 'Add an API account profile. Keys are stored in vault, never exposed.',
409
+ auth: 'admin',
410
+ schema: z.object({
411
+ name: z.string().describe('Profile name'),
412
+ provider: z.enum(['openai', 'anthropic']).describe('API provider'),
413
+ }),
414
+ handler: async (params) => {
415
+ const profile: AccountProfile = {
416
+ name: params.name as string,
417
+ provider: params.provider as string,
418
+ active: false,
419
+ addedAt: Date.now(),
420
+ };
421
+ vault.add({
422
+ id: `account-profile-${profile.name}`,
423
+ type: 'rule',
424
+ domain: 'admin',
425
+ title: `Account: ${profile.name} (${profile.provider})`,
426
+ severity: 'suggestion',
427
+ description: `API account profile for ${profile.provider}`,
428
+ tags: ['account-profile', profile.provider],
429
+ });
430
+ return { added: true, name: profile.name, provider: profile.provider };
431
+ },
432
+ },
433
+ {
434
+ name: 'admin_remove_account',
435
+ description: 'Remove an API account profile.',
436
+ auth: 'admin',
437
+ schema: z.object({
438
+ name: z.string().describe('Profile name to remove'),
439
+ }),
440
+ handler: async (params) => {
441
+ const removed = vault.remove(`account-profile-${params.name}`);
442
+ return { removed, name: params.name };
443
+ },
444
+ },
445
+ {
446
+ name: 'admin_rotate_account',
447
+ description: 'Rotate to a different API account profile.',
448
+ auth: 'admin',
449
+ schema: z.object({
450
+ name: z.string().describe('Profile name to activate'),
451
+ }),
452
+ handler: async (params) => {
453
+ const entry = vault.get(`account-profile-${params.name}`);
454
+ if (!entry) return { error: `Account profile not found: ${params.name}` };
455
+ return {
456
+ rotated: true,
457
+ name: params.name,
458
+ note: 'Profile activated (key rotation requires restart)',
459
+ };
460
+ },
461
+ },
462
+ {
463
+ name: 'admin_list_accounts',
464
+ description: 'List all account profiles (names and providers only, no keys).',
465
+ auth: 'read',
466
+ handler: async () => {
467
+ const entries = vault.list({ domain: 'admin' });
468
+ const accounts = entries
469
+ .filter((e) => e.id.startsWith('account-profile-'))
470
+ .map((e) => ({
471
+ name: e.id.replace('account-profile-', ''),
472
+ provider: e.tags?.find((t) => ['openai', 'anthropic'].includes(t)) ?? 'unknown',
473
+ }));
474
+ return { accounts, count: accounts.length };
475
+ },
476
+ },
477
+ {
478
+ name: 'admin_account_status',
479
+ description: 'Get current active account profile status.',
480
+ auth: 'read',
481
+ handler: async () => {
482
+ const available = runtime.llmClient.isAvailable();
483
+ return {
484
+ openai: { available: available.openai },
485
+ anthropic: { available: available.anthropic },
486
+ };
487
+ },
488
+ },
489
+
490
+ // ─── Plugins (#159) ──────────────────────────────────────────
491
+ {
492
+ name: 'admin_list_plugins',
493
+ description: 'List all registered domain plugins and their status.',
494
+ auth: 'read',
495
+ handler: async () => {
496
+ // Plugins are domain facades — discover via vault domains
497
+ const domains = vault.getDomains();
498
+ const plugins: PluginInfo[] = domains
499
+ .filter((d) => d.domain !== 'admin' && d.domain !== 'planning')
500
+ .map((d) => ({
501
+ id: d.domain,
502
+ name: d.domain,
503
+ status: 'active' as const,
504
+ opsCount: 5, // standard domain ops: get_patterns, search, get_entry, capture, remove
505
+ }));
506
+ return { plugins, count: plugins.length };
507
+ },
508
+ },
509
+ {
510
+ name: 'admin_plugin_status',
511
+ description: 'Get detailed status of a specific plugin (domain facade).',
512
+ auth: 'read',
513
+ schema: z.object({
514
+ pluginId: z.string().describe('Plugin/domain ID'),
515
+ }),
516
+ handler: async (params) => {
517
+ const domainId = params.pluginId as string;
518
+ const domainEntries = vault.list({ domain: domainId });
519
+ if (domainEntries.length === 0) {
520
+ return { error: `Plugin not found or empty: ${domainId}` };
521
+ }
522
+ return {
523
+ id: domainId,
524
+ status: 'active',
525
+ entryCount: domainEntries.length,
526
+ opsCount: 5,
527
+ ops: ['get_patterns', 'search', 'get_entry', 'capture', 'remove'],
528
+ };
529
+ },
530
+ },
531
+
532
+ // ─── Hot Reload (#63) ──────────────────────────────────────
533
+ {
534
+ name: 'admin_hot_reload',
535
+ description:
536
+ 'Hot-reload runtime caches — rebuilds brain vocabulary, vault FTS index, and prompt templates. Use after bulk vault changes.',
537
+ auth: 'write',
538
+ handler: async () => {
539
+ const reloaded: string[] = [];
540
+ let brainTerms = 0;
541
+ let templateCount = 0;
542
+
543
+ try {
544
+ brain.rebuildVocabulary();
545
+ brainTerms = brain.getStats().vocabularySize;
546
+ reloaded.push('brain');
547
+ } catch {
548
+ // Graceful degradation
549
+ }
550
+
551
+ try {
552
+ vault.rebuildFtsIndex();
553
+ reloaded.push('vault_fts');
554
+ } catch {
555
+ // Graceful degradation
556
+ }
557
+
558
+ try {
559
+ runtime.templateManager.load();
560
+ templateCount = runtime.templateManager.listTemplates().length;
561
+ reloaded.push('templates');
562
+ } catch {
563
+ // Graceful degradation
564
+ }
565
+
566
+ return { reloaded, brainTerms, templateCount };
567
+ },
568
+ },
569
+
570
+ // ─── Instruction Validation (#160) ───────────────────────────
571
+ {
572
+ name: 'admin_validate_instructions',
573
+ description:
574
+ 'Validate instruction files (CLAUDE.md, SKILL.md) for governance and quality — checks structure, required fields, formatting.',
575
+ auth: 'read',
576
+ schema: z.object({
577
+ filePath: z.string().describe('Path to the instruction file to validate'),
578
+ }),
579
+ handler: async (params) => {
580
+ try {
581
+ const filePath = params.filePath as string;
582
+ if (!existsSync(filePath)) {
583
+ return { valid: false, errors: [{ line: 0, issue: 'File not found' }] };
584
+ }
585
+
586
+ const content = readFileSync(filePath, 'utf-8');
587
+ const errors: Array<{ line: number; issue: string }> = [];
588
+ const warnings: Array<{ line: number; issue: string }> = [];
589
+
590
+ // Check for YAML frontmatter (SKILL.md files)
591
+ if (filePath.endsWith('SKILL.md') || filePath.includes('/skills/')) {
592
+ if (!content.startsWith('---')) {
593
+ errors.push({ line: 1, issue: 'SKILL.md must start with YAML frontmatter (---)' });
594
+ } else {
595
+ const fmEnd = content.indexOf('---', 3);
596
+ if (fmEnd === -1) {
597
+ errors.push({
598
+ line: 1,
599
+ issue: 'YAML frontmatter not closed (missing closing ---)',
600
+ });
601
+ } else {
602
+ const fm = new Set(content.slice(3, fmEnd));
603
+ if (!fm.has('name:'))
604
+ errors.push({ line: 1, issue: 'Missing required field: name' });
605
+ if (!fm.has('description:'))
606
+ errors.push({ line: 1, issue: 'Missing required field: description' });
607
+ }
608
+ }
609
+ }
610
+
611
+ // General checks for any instruction file
612
+ const lines = content.split('\n');
613
+ for (let i = 0; i < lines.length; i++) {
614
+ const line = lines[i];
615
+ // Check for extremely long lines
616
+ if (line.length > 500) {
617
+ warnings.push({ line: i + 1, issue: `Line too long (${line.length} chars)` });
618
+ }
619
+ }
620
+
621
+ // Check for conflicting instructions
622
+ if (content.includes('ALWAYS') && content.includes('NEVER')) {
623
+ const alwaysLines = lines.filter((l) => l.includes('ALWAYS'));
624
+ const neverLines = lines.filter((l) => l.includes('NEVER'));
625
+ if (alwaysLines.length > 5 && neverLines.length > 5) {
626
+ warnings.push({
627
+ line: 0,
628
+ issue: 'Many ALWAYS/NEVER directives — check for contradictions',
629
+ });
630
+ }
631
+ }
632
+
633
+ // Check for empty content
634
+ if (content.trim().length < 10) {
635
+ errors.push({ line: 1, issue: 'File is essentially empty' });
636
+ }
637
+
638
+ return {
639
+ valid: errors.length === 0,
640
+ filePath,
641
+ errors,
642
+ warnings,
643
+ lineCount: lines.length,
644
+ charCount: content.length,
645
+ };
646
+ } catch (err) {
647
+ return { error: (err as Error).message };
648
+ }
649
+ },
650
+ },
651
+
652
+ // ─── Persistence ────────────────────────────────────────────────
653
+ {
654
+ name: 'admin_persistence_info',
655
+ description: 'Get persistence backend info: type, connection status, and table row counts.',
656
+ auth: 'read',
657
+ schema: z.object({}),
658
+ handler: async () => {
659
+ const provider = runtime.vault.getProvider();
660
+ const backend = provider.backend;
661
+
662
+ const tables: Record<string, number> = {};
663
+ const tableNames = [
664
+ 'entries',
665
+ 'entries_archive',
666
+ 'memories',
667
+ 'projects',
668
+ 'brain_vocabulary',
669
+ 'brain_feedback',
670
+ ];
671
+
672
+ for (const table of tableNames) {
673
+ try {
674
+ const row = provider.get<{ count: number }>(`SELECT COUNT(*) as count FROM ${table}`);
675
+ tables[table] = row?.count ?? 0;
676
+ } catch {
677
+ tables[table] = -1; // Table doesn't exist
678
+ }
679
+ }
680
+
681
+ return { backend, tables };
682
+ },
683
+ },
306
684
  ];
307
685
  }
@@ -41,7 +41,7 @@ function getCoreVersion(): string {
41
41
  * Groups: health (1), introspection (4), diagnostics (2), mutation (1).
42
42
  */
43
43
  export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
44
- const { vault, brain, brainIntelligence, cognee, llmClient, keyPool, curator } = runtime;
44
+ const { vault, brain, brainIntelligence, cognee, llmClient, curator } = runtime;
45
45
 
46
46
  return [
47
47
  // ─── Health ──────────────────────────────────────────────────────
@@ -61,7 +61,10 @@ export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
61
61
  vault: { entries: vaultStats.totalEntries, domains: Object.keys(vaultStats.byDomain) },
62
62
  cognee: { available: cogneeStatus?.available ?? false },
63
63
  llm: llmAvailable,
64
- brain: { vocabularySize: brainStats.vocabularySize, feedbackCount: brainStats.feedbackCount },
64
+ brain: {
65
+ vocabularySize: brainStats.vocabularySize,
66
+ feedbackCount: brainStats.feedbackCount,
67
+ },
65
68
  curator: { initialized: curatorStatus.initialized },
66
69
  };
67
70
  },
@@ -75,7 +78,9 @@ export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
75
78
  handler: async (params) => {
76
79
  // The caller can pass in the full ops list via `_allOps` (injected by
77
80
  // the facade builder). If not provided, we return only admin ops.
78
- const allOps = params._allOps as Array<{ name: string; description: string; auth: string }> | undefined;
81
+ const allOps = params._allOps as
82
+ | Array<{ name: string; description: string; auth: string }>
83
+ | undefined;
79
84
  if (allOps) {
80
85
  return {
81
86
  count: allOps.length,
@@ -119,7 +124,8 @@ export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
119
124
  },
120
125
  {
121
126
  name: 'admin_vault_size',
122
- description: 'Get vault database file size on disk (bytes). Returns null for in-memory vaults.',
127
+ description:
128
+ 'Get vault database file size on disk (bytes). Returns null for in-memory vaults.',
123
129
  auth: 'read',
124
130
  handler: async () => {
125
131
  const dbPath = runtime.config.vaultPath;
@@ -168,7 +174,8 @@ export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
168
174
  // ─── Mutation ────────────────────────────────────────────────────
169
175
  {
170
176
  name: 'admin_reset_cache',
171
- description: 'Clear all caches — brain vocabulary and cognee health cache. Forces fresh data on next access.',
177
+ description:
178
+ 'Clear all caches — brain vocabulary and cognee health cache. Forces fresh data on next access.',
172
179
  auth: 'write',
173
180
  handler: async () => {
174
181
  // Rebuild brain vocabulary (clears old TF-IDF state, rebuilds from vault)
@@ -247,7 +254,11 @@ export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
247
254
  try {
248
255
  const cogneeStatus = cognee.getStatus();
249
256
  if (cogneeStatus?.available) {
250
- checks.push({ name: 'cognee', status: 'ok', detail: `Connected to ${cogneeStatus.url}` });
257
+ checks.push({
258
+ name: 'cognee',
259
+ status: 'ok',
260
+ detail: `Connected to ${cogneeStatus.url}`,
261
+ });
251
262
  } else {
252
263
  checks.push({
253
264
  name: 'cognee',
@@ -30,7 +30,15 @@ export function createCaptureOps(runtime: AgentRuntime): OpDefinition[] {
30
30
  z.object({
31
31
  id: z.string().optional(),
32
32
  type: z
33
- .enum(['pattern', 'anti-pattern', 'rule', 'workflow', 'principle', 'reference'])
33
+ .enum([
34
+ 'pattern',
35
+ 'anti-pattern',
36
+ 'rule',
37
+ 'playbook',
38
+ 'workflow',
39
+ 'principle',
40
+ 'reference',
41
+ ])
34
42
  .describe('Entry type'),
35
43
  domain: z.string(),
36
44
  title: z.string(),
@@ -66,7 +74,8 @@ export function createCaptureOps(runtime: AgentRuntime): OpDefinition[] {
66
74
  const results: Array<{ id: string; action: string; reason?: string }> = [];
67
75
 
68
76
  for (const entry of entries) {
69
- const entryId = entry.id ?? `${entry.domain}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
77
+ const entryId =
78
+ entry.id ?? `${entry.domain}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
70
79
  const mappedSeverity = mapSeverity(entry.severity);
71
80
  const mappedType = mapType(entry.type);
72
81
 
@@ -82,7 +91,7 @@ export function createCaptureOps(runtime: AgentRuntime): OpDefinition[] {
82
91
  try {
83
92
  brain.enrichAndCapture({
84
93
  id: entryId,
85
- type: mappedType as 'pattern' | 'anti-pattern' | 'rule',
94
+ type: mappedType as 'pattern' | 'anti-pattern' | 'rule' | 'playbook',
86
95
  domain: entry.domain,
87
96
  title: entry.title,
88
97
  severity: mappedSeverity,
@@ -166,7 +175,15 @@ export function createCaptureOps(runtime: AgentRuntime): OpDefinition[] {
166
175
  schema: z.object({
167
176
  projectPath: z.string().optional().default('.'),
168
177
  type: z
169
- .enum(['pattern', 'anti-pattern', 'rule', 'workflow', 'principle', 'reference'])
178
+ .enum([
179
+ 'pattern',
180
+ 'anti-pattern',
181
+ 'rule',
182
+ 'playbook',
183
+ 'workflow',
184
+ 'principle',
185
+ 'reference',
186
+ ])
170
187
  .describe('Entry type'),
171
188
  domain: z.string(),
172
189
  title: z.string(),
@@ -197,7 +214,7 @@ export function createCaptureOps(runtime: AgentRuntime): OpDefinition[] {
197
214
  try {
198
215
  brain.enrichAndCapture({
199
216
  id,
200
- type: mappedType as 'pattern' | 'anti-pattern' | 'rule',
217
+ type: mappedType as 'pattern' | 'anti-pattern' | 'rule' | 'playbook',
201
218
  domain,
202
219
  title,
203
220
  severity: mapSeverity(mappedSeverity),
@@ -369,12 +386,14 @@ function mapSeverity(severity: string | undefined): 'critical' | 'warning' | 'su
369
386
  * Map extended type values to IntelligenceEntry-compatible types.
370
387
  * 'workflow', 'principle', 'reference' map to 'rule' (the closest existing type).
371
388
  */
372
- function mapType(type: string): 'pattern' | 'anti-pattern' | 'rule' {
389
+ function mapType(type: string): 'pattern' | 'anti-pattern' | 'rule' | 'playbook' {
373
390
  switch (type) {
374
391
  case 'pattern':
375
392
  return 'pattern';
376
393
  case 'anti-pattern':
377
394
  return 'anti-pattern';
395
+ case 'playbook':
396
+ return 'playbook';
378
397
  case 'rule':
379
398
  case 'workflow':
380
399
  case 'principle':
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Cognee sync operations — 3 ops for queue visibility and control.
3
+ */
4
+
5
+ import { z } from 'zod';
6
+ import type { OpDefinition } from '../facades/types.js';
7
+ import type { CogneeSyncManager } from '../cognee/sync-manager.js';
8
+
9
+ /**
10
+ * Create the 3 cognee-sync operations.
11
+ *
12
+ * The sync manager is optional — when null, all ops return a graceful error.
13
+ */
14
+ export function createCogneeSyncOps(syncManager: CogneeSyncManager | null): OpDefinition[] {
15
+ return [
16
+ // ─── Status ──────────────────────────────────────────────────
17
+ {
18
+ name: 'cognee_sync_status',
19
+ description:
20
+ 'Get current cognee sync queue stats — pending, processing, completed, failed counts.',
21
+ auth: 'read',
22
+ schema: z.object({}),
23
+ handler: async () => {
24
+ if (!syncManager) {
25
+ return { error: 'Sync manager not configured' };
26
+ }
27
+ return syncManager.getStats();
28
+ },
29
+ },
30
+
31
+ // ─── Drain ───────────────────────────────────────────────────
32
+ {
33
+ name: 'cognee_sync_drain',
34
+ description:
35
+ 'Process pending items in the cognee sync queue. Returns count of processed items and updated stats.',
36
+ auth: 'write',
37
+ schema: z.object({}),
38
+ handler: async () => {
39
+ if (!syncManager) {
40
+ return { error: 'Sync manager not configured' };
41
+ }
42
+ const processed = await syncManager.drain();
43
+ return { processed, stats: syncManager.getStats() };
44
+ },
45
+ },
46
+
47
+ // ─── Reconcile ───────────────────────────────────────────────
48
+ {
49
+ name: 'cognee_sync_reconcile',
50
+ description:
51
+ 'Find vault entries with stale or missing cognee ingestion and enqueue them for sync.',
52
+ auth: 'write',
53
+ schema: z.object({}),
54
+ handler: async () => {
55
+ if (!syncManager) {
56
+ return { error: 'Sync manager not configured' };
57
+ }
58
+ const enqueued = syncManager.reconcile();
59
+ return { enqueued, stats: syncManager.getStats() };
60
+ },
61
+ },
62
+ ];
63
+ }