@soleri/core 9.15.0 → 9.16.7

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 (288) hide show
  1. package/data/flows/deliver.flow.yaml +11 -0
  2. package/data/flows/design.flow.yaml +4 -14
  3. package/data/flows/enhance.flow.yaml +10 -0
  4. package/data/flows/explore.flow.yaml +16 -0
  5. package/data/flows/fix.flow.yaml +1 -1
  6. package/data/flows/review.flow.yaml +13 -4
  7. package/dist/capabilities/chain-mapping.d.ts.map +1 -1
  8. package/dist/capabilities/chain-mapping.js +5 -4
  9. package/dist/capabilities/chain-mapping.js.map +1 -1
  10. package/dist/capabilities/registry.d.ts +6 -0
  11. package/dist/capabilities/registry.d.ts.map +1 -1
  12. package/dist/capabilities/registry.js +3 -2
  13. package/dist/capabilities/registry.js.map +1 -1
  14. package/dist/context/context-engine.js +1 -1
  15. package/dist/context/context-engine.js.map +1 -1
  16. package/dist/engine/core-ops.d.ts.map +1 -1
  17. package/dist/engine/core-ops.js +38 -1
  18. package/dist/engine/core-ops.js.map +1 -1
  19. package/dist/flows/epilogue.d.ts +5 -1
  20. package/dist/flows/epilogue.d.ts.map +1 -1
  21. package/dist/flows/epilogue.js +11 -3
  22. package/dist/flows/epilogue.js.map +1 -1
  23. package/dist/flows/executor.d.ts.map +1 -1
  24. package/dist/flows/executor.js +13 -5
  25. package/dist/flows/executor.js.map +1 -1
  26. package/dist/flows/index.d.ts +1 -2
  27. package/dist/flows/index.d.ts.map +1 -1
  28. package/dist/flows/index.js +1 -0
  29. package/dist/flows/index.js.map +1 -1
  30. package/dist/flows/plan-builder.d.ts +17 -1
  31. package/dist/flows/plan-builder.d.ts.map +1 -1
  32. package/dist/flows/plan-builder.js +67 -6
  33. package/dist/flows/plan-builder.js.map +1 -1
  34. package/dist/flows/probes.d.ts +1 -1
  35. package/dist/flows/probes.d.ts.map +1 -1
  36. package/dist/flows/probes.js +15 -3
  37. package/dist/flows/probes.js.map +1 -1
  38. package/dist/flows/types.d.ts +31 -4
  39. package/dist/flows/types.d.ts.map +1 -1
  40. package/dist/flows/types.js +6 -1
  41. package/dist/flows/types.js.map +1 -1
  42. package/dist/index.d.ts +8 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +7 -0
  45. package/dist/index.js.map +1 -1
  46. package/dist/packs/pack-installer.d.ts.map +1 -1
  47. package/dist/packs/pack-installer.js +28 -2
  48. package/dist/packs/pack-installer.js.map +1 -1
  49. package/dist/planning/planner-types.d.ts +2 -0
  50. package/dist/planning/planner-types.d.ts.map +1 -1
  51. package/dist/planning/planner.d.ts +1 -0
  52. package/dist/planning/planner.d.ts.map +1 -1
  53. package/dist/planning/planner.js +7 -0
  54. package/dist/planning/planner.js.map +1 -1
  55. package/dist/playbooks/playbook-executor.d.ts +10 -1
  56. package/dist/playbooks/playbook-executor.d.ts.map +1 -1
  57. package/dist/playbooks/playbook-executor.js +8 -2
  58. package/dist/playbooks/playbook-executor.js.map +1 -1
  59. package/dist/playbooks/playbook-types.d.ts +8 -0
  60. package/dist/playbooks/playbook-types.d.ts.map +1 -1
  61. package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
  62. package/dist/runtime/admin-extra-ops.js +30 -0
  63. package/dist/runtime/admin-extra-ops.js.map +1 -1
  64. package/dist/runtime/admin-ops.d.ts.map +1 -1
  65. package/dist/runtime/admin-ops.js +60 -21
  66. package/dist/runtime/admin-ops.js.map +1 -1
  67. package/dist/runtime/admin-setup-ops.d.ts +11 -0
  68. package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
  69. package/dist/runtime/admin-setup-ops.js +87 -17
  70. package/dist/runtime/admin-setup-ops.js.map +1 -1
  71. package/dist/runtime/capture-ops.d.ts.map +1 -1
  72. package/dist/runtime/capture-ops.js +38 -12
  73. package/dist/runtime/capture-ops.js.map +1 -1
  74. package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
  75. package/dist/runtime/facades/brain-facade.js +16 -4
  76. package/dist/runtime/facades/brain-facade.js.map +1 -1
  77. package/dist/runtime/facades/context-facade.d.ts.map +1 -1
  78. package/dist/runtime/facades/context-facade.js +9 -3
  79. package/dist/runtime/facades/context-facade.js.map +1 -1
  80. package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
  81. package/dist/runtime/facades/memory-facade.js +20 -7
  82. package/dist/runtime/facades/memory-facade.js.map +1 -1
  83. package/dist/runtime/facades/orchestrate-facade.d.ts.map +1 -1
  84. package/dist/runtime/facades/orchestrate-facade.js +12 -0
  85. package/dist/runtime/facades/orchestrate-facade.js.map +1 -1
  86. package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
  87. package/dist/runtime/facades/plan-facade.js +113 -4
  88. package/dist/runtime/facades/plan-facade.js.map +1 -1
  89. package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
  90. package/dist/runtime/facades/vault-facade.js +24 -3
  91. package/dist/runtime/facades/vault-facade.js.map +1 -1
  92. package/dist/runtime/orchestrate-ops.d.ts +21 -0
  93. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  94. package/dist/runtime/orchestrate-ops.js +132 -38
  95. package/dist/runtime/orchestrate-ops.js.map +1 -1
  96. package/dist/runtime/schema-helpers.d.ts.map +1 -1
  97. package/dist/runtime/schema-helpers.js +4 -0
  98. package/dist/runtime/schema-helpers.js.map +1 -1
  99. package/dist/runtime/vault-linking-ops.d.ts.map +1 -1
  100. package/dist/runtime/vault-linking-ops.js +16 -3
  101. package/dist/runtime/vault-linking-ops.js.map +1 -1
  102. package/dist/scheduler/cron-validator.d.ts +15 -0
  103. package/dist/scheduler/cron-validator.d.ts.map +1 -0
  104. package/dist/scheduler/cron-validator.js +93 -0
  105. package/dist/scheduler/cron-validator.js.map +1 -0
  106. package/dist/scheduler/platform-linux.d.ts +14 -0
  107. package/dist/scheduler/platform-linux.d.ts.map +1 -0
  108. package/dist/scheduler/platform-linux.js +107 -0
  109. package/dist/scheduler/platform-linux.js.map +1 -0
  110. package/dist/scheduler/platform-macos.d.ts +15 -0
  111. package/dist/scheduler/platform-macos.d.ts.map +1 -0
  112. package/dist/scheduler/platform-macos.js +131 -0
  113. package/dist/scheduler/platform-macos.js.map +1 -0
  114. package/dist/scheduler/scheduler-ops.d.ts +14 -0
  115. package/dist/scheduler/scheduler-ops.d.ts.map +1 -0
  116. package/dist/scheduler/scheduler-ops.js +77 -0
  117. package/dist/scheduler/scheduler-ops.js.map +1 -0
  118. package/dist/scheduler/scheduler.d.ts +55 -0
  119. package/dist/scheduler/scheduler.d.ts.map +1 -0
  120. package/dist/scheduler/scheduler.js +144 -0
  121. package/dist/scheduler/scheduler.js.map +1 -0
  122. package/dist/scheduler/types.d.ts +48 -0
  123. package/dist/scheduler/types.d.ts.map +1 -0
  124. package/dist/scheduler/types.js +6 -0
  125. package/dist/scheduler/types.js.map +1 -0
  126. package/dist/skills/sync-skills.d.ts +11 -0
  127. package/dist/skills/sync-skills.d.ts.map +1 -1
  128. package/dist/skills/sync-skills.js +132 -38
  129. package/dist/skills/sync-skills.js.map +1 -1
  130. package/dist/utils/worktree-reaper.d.ts +38 -0
  131. package/dist/utils/worktree-reaper.d.ts.map +1 -0
  132. package/dist/utils/worktree-reaper.js +85 -0
  133. package/dist/utils/worktree-reaper.js.map +1 -0
  134. package/dist/vault/scope-detector.d.ts.map +1 -1
  135. package/dist/vault/scope-detector.js +37 -4
  136. package/dist/vault/scope-detector.js.map +1 -1
  137. package/dist/vault/vault-entries.d.ts.map +1 -1
  138. package/dist/vault/vault-entries.js +3 -1
  139. package/dist/vault/vault-entries.js.map +1 -1
  140. package/package.json +1 -1
  141. package/src/agency/agency-manager.test.ts +4 -4
  142. package/src/agency/default-rules.test.ts +0 -13
  143. package/src/brain/brain-intelligence.test.ts +0 -5
  144. package/src/brain/second-brain-features.test.ts +2 -14
  145. package/src/capabilities/chain-mapping.test.ts +1 -6
  146. package/src/capabilities/chain-mapping.ts +6 -4
  147. package/src/capabilities/registry.test.ts +1 -1
  148. package/src/capabilities/registry.ts +9 -2
  149. package/src/chat/agent-loop.test.ts +1 -1
  150. package/src/chat/chat-enhanced.test.ts +0 -8
  151. package/src/claudemd/compose.test.ts +0 -5
  152. package/src/context/context-engine.test.ts +0 -1
  153. package/src/context/context-engine.ts +1 -1
  154. package/src/control/intent-router.test.ts +2 -2
  155. package/src/curator/tag-manager.test.ts +0 -4
  156. package/src/domain-packs/types.test.ts +0 -5
  157. package/src/dream/dream.test.ts +0 -7
  158. package/src/enforcement/registry.test.ts +2 -2
  159. package/src/engine/core-ops.test.ts +4 -22
  160. package/src/engine/core-ops.ts +36 -1
  161. package/src/engine/module-manifest.test.ts +1 -31
  162. package/src/engine/register-engine.test.ts +3 -33
  163. package/src/errors/retry.test.ts +3 -1
  164. package/src/flows/chain-runner.test.ts +0 -6
  165. package/src/flows/context-router.test.ts +3 -3
  166. package/src/flows/epilogue.test.ts +40 -2
  167. package/src/flows/epilogue.ts +11 -2
  168. package/src/flows/executor.test.ts +48 -2
  169. package/src/flows/executor.ts +15 -5
  170. package/src/flows/index.ts +1 -3
  171. package/src/flows/plan-builder.test.ts +201 -0
  172. package/src/flows/plan-builder.ts +81 -5
  173. package/src/flows/probes.ts +17 -3
  174. package/src/flows/types.ts +31 -2
  175. package/src/health/health-registry.test.ts +3 -1
  176. package/src/index.ts +17 -0
  177. package/src/intake/dedup-gate.test.ts +2 -6
  178. package/src/intake/text-ingester.test.ts +3 -4
  179. package/src/llm/llm-client.test.ts +1 -1
  180. package/src/llm/utils.test.ts +1 -1
  181. package/src/migrations/migration-runner.test.ts +0 -1
  182. package/src/operator/operator-context-store.test.ts +0 -13
  183. package/src/operator/operator-profile.test.ts +2 -20
  184. package/src/packs/pack-installer.ts +28 -2
  185. package/src/packs/pack-system.test.ts +2 -2
  186. package/src/persona/defaults.test.ts +19 -19
  187. package/src/planning/gap-passes.test.ts +0 -46
  188. package/src/planning/gap-patterns.test.ts +0 -42
  189. package/src/planning/goal-ancestry.test.ts +3 -1
  190. package/src/planning/plan-lifecycle.test.ts +15 -7
  191. package/src/planning/planner-types.ts +2 -0
  192. package/src/planning/planner.ts +8 -0
  193. package/src/planning/reconciliation-engine.test.ts +3 -10
  194. package/src/planning/task-complexity-assessor.test.ts +0 -5
  195. package/src/planning/task-verifier.test.ts +3 -1
  196. package/src/playbooks/generic/generic-playbooks.test.ts +0 -28
  197. package/src/playbooks/index.test.ts +0 -55
  198. package/src/playbooks/playbook-executor.test.ts +76 -0
  199. package/src/playbooks/playbook-executor.ts +24 -3
  200. package/src/playbooks/playbook-types.ts +8 -0
  201. package/src/plugins/plugin-registry.test.ts +6 -2
  202. package/src/project/project-registry.test.ts +2 -0
  203. package/src/queue/async-infrastructure.test.ts +6 -4
  204. package/src/queue/job-queue.test.ts +13 -7
  205. package/src/runtime/admin-extra-ops.test.ts +35 -30
  206. package/src/runtime/admin-extra-ops.ts +30 -0
  207. package/src/runtime/admin-ops.test.ts +0 -4
  208. package/src/runtime/admin-ops.ts +63 -21
  209. package/src/runtime/admin-setup-ops.test.ts +185 -13
  210. package/src/runtime/admin-setup-ops.ts +86 -16
  211. package/src/runtime/archive-ops.test.ts +0 -28
  212. package/src/runtime/branching-ops.test.ts +0 -17
  213. package/src/runtime/capture-ops.test.ts +41 -16
  214. package/src/runtime/capture-ops.ts +78 -46
  215. package/src/runtime/chain-ops.test.ts +0 -21
  216. package/src/runtime/facades/admin-facade.test.ts +0 -34
  217. package/src/runtime/facades/agency-facade.test.ts +0 -39
  218. package/src/runtime/facades/archive-facade.test.ts +0 -43
  219. package/src/runtime/facades/brain-facade.test.ts +8 -99
  220. package/src/runtime/facades/brain-facade.ts +29 -12
  221. package/src/runtime/facades/branching-facade.test.ts +30 -17
  222. package/src/runtime/facades/chat-facade.test.ts +0 -91
  223. package/src/runtime/facades/chat-service-ops.test.ts +0 -24
  224. package/src/runtime/facades/chat-session-ops.test.ts +0 -12
  225. package/src/runtime/facades/chat-transport-ops.test.ts +0 -23
  226. package/src/runtime/facades/context-facade.test.ts +0 -17
  227. package/src/runtime/facades/context-facade.ts +11 -4
  228. package/src/runtime/facades/control-facade.test.ts +0 -30
  229. package/src/runtime/facades/curator-facade.test.ts +0 -33
  230. package/src/runtime/facades/intake-facade.test.ts +0 -33
  231. package/src/runtime/facades/links-facade.test.ts +0 -37
  232. package/src/runtime/facades/loop-facade.test.ts +0 -26
  233. package/src/runtime/facades/memory-facade.test.ts +0 -18
  234. package/src/runtime/facades/memory-facade.ts +27 -11
  235. package/src/runtime/facades/operator-facade.test.ts +0 -31
  236. package/src/runtime/facades/orchestrate-facade.test.ts +0 -21
  237. package/src/runtime/facades/orchestrate-facade.ts +12 -0
  238. package/src/runtime/facades/plan-facade.test.ts +7 -32
  239. package/src/runtime/facades/plan-facade.ts +137 -4
  240. package/src/runtime/facades/review-facade.test.ts +1 -49
  241. package/src/runtime/facades/sync-facade.test.ts +24 -41
  242. package/src/runtime/facades/tier-facade.test.ts +30 -22
  243. package/src/runtime/facades/vault-facade.test.ts +0 -41
  244. package/src/runtime/facades/vault-facade.ts +26 -3
  245. package/src/runtime/grading-ops.test.ts +0 -27
  246. package/src/runtime/intake-ops.test.ts +0 -19
  247. package/src/runtime/loop-ops.test.ts +0 -48
  248. package/src/runtime/memory-cross-project-ops.test.ts +0 -14
  249. package/src/runtime/memory-extra-ops.test.ts +4 -8
  250. package/src/runtime/orchestrate-ops.test.ts +238 -19
  251. package/src/runtime/orchestrate-ops.ts +166 -41
  252. package/src/runtime/pack-ops.test.ts +0 -26
  253. package/src/runtime/planning-extra-ops.test.ts +2 -14
  254. package/src/runtime/playbook-ops-execution.test.ts +9 -20
  255. package/src/runtime/playbook-ops.test.ts +4 -67
  256. package/src/runtime/review-ops.test.ts +0 -15
  257. package/src/runtime/schema-helpers.ts +4 -0
  258. package/src/runtime/sync-ops.test.ts +0 -18
  259. package/src/runtime/tier-ops.test.ts +0 -21
  260. package/src/runtime/vault-extra-ops.test.ts +0 -12
  261. package/src/runtime/vault-linking-ops.test.ts +0 -4
  262. package/src/runtime/vault-linking-ops.ts +26 -8
  263. package/src/runtime/vault-sharing-ops.test.ts +0 -9
  264. package/src/scheduler/cron-validator.ts +101 -0
  265. package/src/scheduler/platform-linux.ts +122 -0
  266. package/src/scheduler/platform-macos.ts +150 -0
  267. package/src/scheduler/scheduler-ops.ts +77 -0
  268. package/src/scheduler/scheduler.test.ts +247 -0
  269. package/src/scheduler/scheduler.ts +174 -0
  270. package/src/scheduler/types.ts +52 -0
  271. package/src/skills/__tests__/sync-skills.test.ts +6 -17
  272. package/src/skills/global-claude-md.test.ts +113 -0
  273. package/src/skills/sync-skills.ts +143 -35
  274. package/src/skills/validate-skills.test.ts +12 -11
  275. package/src/telemetry/telemetry.test.ts +1 -0
  276. package/src/transport/http-server.test.ts +3 -0
  277. package/src/transport/session-manager.test.ts +3 -1
  278. package/src/transport/token-auth.test.ts +6 -9
  279. package/src/transport/ws-server.test.ts +10 -2
  280. package/src/utils/worktree-reaper.ts +113 -0
  281. package/src/vault/__tests__/vault-characterization.test.ts +0 -108
  282. package/src/vault/linking.test.ts +0 -2
  283. package/src/vault/playbook.test.ts +4 -1
  284. package/src/vault/scope-detector.test.ts +3 -1
  285. package/src/vault/scope-detector.ts +42 -4
  286. package/src/vault/vault-connect.test.ts +1 -1
  287. package/src/vault/vault-entries.ts +3 -1
  288. package/src/vault/vault.test.ts +23 -8
@@ -219,7 +219,7 @@ describe('AgencyManager', () => {
219
219
  it('returns patterns from vault for .ts files', () => {
220
220
  seedVaultWithPattern(vault);
221
221
  const p = manager.surfacePatterns('/project/src/module.ts');
222
- expect(p.length).toBeGreaterThan(0);
222
+ expect(p.length).toBe(1);
223
223
  expect(p[0].trigger).toBe('/project/src/module.ts');
224
224
  expect(p[0].entryId).toBe('ts-pattern-1');
225
225
  });
@@ -238,14 +238,14 @@ describe('AgencyManager', () => {
238
238
  it('different files are independent of each other cooldown', () => {
239
239
  seedVaultWithPattern(vault);
240
240
  manager.surfacePatterns('/project/src/a.ts');
241
- expect(manager.surfacePatterns('/project/src/b.ts').length).toBeGreaterThan(0);
241
+ expect(manager.surfacePatterns('/project/src/b.ts').length).toBe(1);
242
242
  });
243
243
 
244
244
  it('accumulates in getSurfacedPatterns', () => {
245
245
  seedVaultWithPattern(vault);
246
246
  manager.surfacePatterns('/project/a.ts');
247
247
  manager.surfacePatterns('/project/b.tsx');
248
- expect(manager.getSurfacedPatterns().length).toBeGreaterThanOrEqual(2);
248
+ expect(manager.getSurfacedPatterns().length).toBe(2);
249
249
  });
250
250
 
251
251
  it('clearSurfacedPatterns resets accumulator', () => {
@@ -536,7 +536,7 @@ describe('AgencyManager', () => {
536
536
  it('creates notifications for each suggestion', () => {
537
537
  expect(manager.getPendingNotificationCount()).toBe(0);
538
538
  manager.generateSuggestions(); // first-session fires
539
- expect(manager.getPendingNotificationCount()).toBeGreaterThan(0);
539
+ expect(manager.getPendingNotificationCount()).toBe(1);
540
540
  });
541
541
  });
542
542
 
@@ -47,19 +47,6 @@ function findRule(name: string) {
47
47
  }
48
48
 
49
49
  describe('DEFAULT_SUGGESTION_RULES', () => {
50
- it('exports exactly 6 rules', () => {
51
- expect(DEFAULT_SUGGESTION_RULES).toHaveLength(6);
52
- });
53
-
54
- it('each rule has name, description, condition, and generate', () => {
55
- for (const rule of DEFAULT_SUGGESTION_RULES) {
56
- expect(typeof rule.name).toBe('string');
57
- expect(typeof rule.description).toBe('string');
58
- expect(typeof rule.condition).toBe('function');
59
- expect(typeof rule.generate).toBe('function');
60
- }
61
- });
62
-
63
50
  // ─── many-warnings ────────────────────────────────────────────────
64
51
 
65
52
  describe('many-warnings', () => {
@@ -38,11 +38,6 @@ describe('BrainIntelligence', () => {
38
38
  expect(stats.domainProfiles).toBe(0);
39
39
  });
40
40
 
41
- it('should be accessible from runtime', () => {
42
- expect(runtime.brainIntelligence).toBeDefined();
43
- expect(typeof runtime.brainIntelligence.getStats).toBe('function');
44
- });
45
-
46
41
  // ─── Session Lifecycle ──────────────────────────────────────────
47
42
 
48
43
  it('should start a session', () => {
@@ -33,7 +33,7 @@ import type { IntelligenceEntry } from '../intelligence/types.js';
33
33
 
34
34
  let vault: Vault;
35
35
  let brain: Brain;
36
- let brainIntelligence: BrainIntelligence;
36
+ let _brainIntelligence: BrainIntelligence;
37
37
  let planner: Planner;
38
38
  let curator: Curator;
39
39
  let intentRouter: IntentRouter;
@@ -99,7 +99,7 @@ beforeAll(() => {
99
99
  vault = new Vault(':memory:');
100
100
  vault.seed(SEED);
101
101
  brain = new Brain(vault);
102
- brainIntelligence = new BrainIntelligence(vault, brain);
102
+ _brainIntelligence = new BrainIntelligence(vault, brain);
103
103
  planner = new Planner(join(tempDir, 'plans.json'));
104
104
  curator = new Curator(vault);
105
105
  intentRouter = new IntentRouter(vault);
@@ -160,18 +160,6 @@ describe('Two-pass vault retrieval (#205)', () => {
160
160
  // ─── 2. Session Briefing ─────────────────────────────────────────────
161
161
 
162
162
  describe('Session briefing (#202)', () => {
163
- // Session briefing is an op — tested via the module imports directly
164
- it('brainIntelligence.listSessions returns sessions', () => {
165
- const sessions = brainIntelligence.listSessions({ limit: 5 });
166
- // May be empty in a fresh vault, but shouldn't throw
167
- expect(Array.isArray(sessions)).toBe(true);
168
- });
169
-
170
- it('planner.list returns plans array', () => {
171
- const plans = planner.list();
172
- expect(Array.isArray(plans)).toBe(true);
173
- });
174
-
175
163
  it('vault.getRecent returns recent entries', () => {
176
164
  const recent = vault.getRecent(5);
177
165
  expect(recent.length).toBeGreaterThan(0);
@@ -6,10 +6,6 @@ describe('chainToCapability', () => {
6
6
  expect(chainToCapability('vault-search')).toBe('vault.search');
7
7
  });
8
8
 
9
- it('maps vault-search-antipatterns to vault.search', () => {
10
- expect(chainToCapability('vault-search-antipatterns')).toBe('vault.search');
11
- });
12
-
13
9
  it('maps memory-search to memory.search', () => {
14
10
  expect(chainToCapability('memory-search')).toBe('memory.search');
15
11
  });
@@ -39,9 +35,8 @@ describe('chainToCapability', () => {
39
35
  expect(chainToCapability('get-stack-guidelines')).toBe('stack.guidelines');
40
36
  });
41
37
 
42
- it('maps architecture and cognee chains', () => {
38
+ it('maps architecture chains', () => {
43
39
  expect(chainToCapability('architecture-search')).toBe('architecture.search');
44
- expect(chainToCapability('cognee-design-search')).toBe('cognee.search');
45
40
  });
46
41
 
47
42
  it('maps planning chains', () => {
@@ -22,7 +22,7 @@
22
22
  * deliver.flow.yaml — validate-component, validate-tokens,
23
23
  * design-rules-check, test-coverage-check,
24
24
  * performance-audit, delivery-checklist
25
- * design.flow.yaml — vault-search, memory-search, cognee-design-search,
25
+ * design.flow.yaml — vault-search, memory-search,
26
26
  * recommend-design-system, recommend-style,
27
27
  * recommend-palette, recommend-typography,
28
28
  * get-stack-guidelines, brain-recommend
@@ -30,7 +30,7 @@
30
30
  * brain-recommend, validate-component, validate-tokens
31
31
  * explore.flow.yaml — vault-search, memory-search, brain-strengths,
32
32
  * brain-recommend, playbook-search
33
- * fix.flow.yaml — vault-search-antipatterns, memory-search,
33
+ * fix.flow.yaml — vault-search, memory-search,
34
34
  * error-pattern-search, brain-recommend,
35
35
  * validate-component, validate-tokens
36
36
  * plan.flow.yaml — vault-search, memory-search, brain-recommend,
@@ -42,7 +42,6 @@
42
42
  const CHAIN_TO_CAPABILITY: Record<string, string> = {
43
43
  // Vault & Knowledge
44
44
  'vault-search': 'vault.search',
45
- 'vault-search-antipatterns': 'vault.search',
46
45
  'memory-search': 'memory.search',
47
46
  'playbook-search': 'vault.playbook',
48
47
 
@@ -67,11 +66,14 @@ const CHAIN_TO_CAPABILITY: Record<string, string> = {
67
66
 
68
67
  // Architecture
69
68
  'architecture-search': 'architecture.search',
70
- 'cognee-design-search': 'cognee.search',
71
69
 
72
70
  // Planning
73
71
  'plan-create': 'plan.create',
74
72
 
73
+ // Capture & Synthesis
74
+ 'capture-baseline-state': 'vault.capture',
75
+ 'vault-synthesize': 'vault.synthesize',
76
+
75
77
  // Review & Quality
76
78
  'review-report': 'review.report',
77
79
  'accessibility-audit': 'a11y.audit',
@@ -237,7 +237,7 @@ describe('CapabilityRegistry', () => {
237
237
  it('classifies blocking capabilities correctly', () => {
238
238
  const result = registry.validateFlow({
239
239
  steps: [{ needs: ['vault.search', 'auth.validate'] }],
240
- onMissingCapability: { blocking: ['auth.validate'] },
240
+ 'on-missing-capability': { blocking: ['auth.validate'] },
241
241
  });
242
242
 
243
243
  expect(result.valid).toBe(false);
@@ -33,6 +33,12 @@ export interface FlowForValidation {
33
33
  needs?: string[];
34
34
  chains?: string[];
35
35
  }>;
36
+ /** Kebab-case (YAML / flow file format). */
37
+ 'on-missing-capability'?: {
38
+ default?: string;
39
+ blocking?: string[];
40
+ };
41
+ /** CamelCase alias for programmatic callers. */
36
42
  onMissingCapability?: {
37
43
  default?: string;
38
44
  blocking?: string[];
@@ -236,8 +242,9 @@ export class CapabilityRegistry {
236
242
  }
237
243
  }
238
244
 
239
- // Classify missing capabilities by impact
240
- const blockingSet = new Set(flow.onMissingCapability?.blocking ?? []);
245
+ // Classify missing capabilities by impact (accept both kebab and camelCase keys)
246
+ const missingCapConfig = flow['on-missing-capability'] ?? flow.onMissingCapability;
247
+ const blockingSet = new Set(missingCapConfig?.blocking ?? []);
241
248
 
242
249
  const degraded = missing.map((capability) => ({
243
250
  capability,
@@ -286,7 +286,7 @@ describe('runAgentLoop', () => {
286
286
  onToolUse: (name) => toolUses.push(name),
287
287
  onToolResult: (name, result, ms) => {
288
288
  toolResults.push(`${name}:${result.output}`);
289
- expect(ms).toBeGreaterThanOrEqual(0);
289
+ expect(typeof ms).toBe('number');
290
290
  },
291
291
  },
292
292
  );
@@ -14,7 +14,6 @@ import {
14
14
  cleanupTempFiles,
15
15
  sanitizeForPersistence,
16
16
  MAX_FILE_SIZE,
17
- TEXT_EXTENSIONS,
18
17
  } from './file-handler.js';
19
18
  import { NotificationEngine } from './notifications.js';
20
19
  import type { FileInfo, MultimodalContent } from './file-handler.js';
@@ -231,13 +230,6 @@ describe('File Handler', () => {
231
230
  });
232
231
  });
233
232
 
234
- test('TEXT_EXTENSIONS includes common types', () => {
235
- expect(TEXT_EXTENSIONS.has('.ts')).toBe(true);
236
- expect(TEXT_EXTENSIONS.has('.py')).toBe(true);
237
- expect(TEXT_EXTENSIONS.has('.json')).toBe(true);
238
- expect(TEXT_EXTENSIONS.has('.md')).toBe(true);
239
- });
240
-
241
233
  test('MAX_FILE_SIZE is 20MB', () => {
242
234
  expect(MAX_FILE_SIZE).toBe(20 * 1024 * 1024);
243
235
  });
@@ -35,11 +35,6 @@ const facades: FacadeConfig[] = [
35
35
  ];
36
36
 
37
37
  describe('compose — constants', () => {
38
- it('FORMAT_VERSION is a positive integer', () => {
39
- expect(FORMAT_VERSION).toBeGreaterThan(0);
40
- expect(Number.isInteger(FORMAT_VERSION)).toBe(true);
41
- });
42
-
43
38
  it('markers contain version', () => {
44
39
  expect(OPEN_MARKER).toContain(`v${FORMAT_VERSION}`);
45
40
  });
@@ -398,7 +398,6 @@ describe('ContextEngine', () => {
398
398
 
399
399
  it('processing time is a non-negative number', async () => {
400
400
  const result = await engine.analyze('any prompt');
401
- expect(result.processingTimeMs).toBeGreaterThanOrEqual(0);
402
401
  expect(typeof result.processingTimeMs).toBe('number');
403
402
  });
404
403
 
@@ -48,7 +48,7 @@ const ENTITY_PATTERNS: Array<{ type: EntityType; pattern: RegExp; confidence: nu
48
48
  {
49
49
  type: 'technology',
50
50
  pattern:
51
- /\b(?:react|vue|svelte|angular|typescript|javascript|node\.?js|python|rust|go|docker|kubernetes|postgres|sqlite|redis|tailwind|css|html|graphql|rest|grpc)\b/gi,
51
+ /\b(?:react|vue|svelte|angular|typescript|javascript|node\.?js|python|rust|go|docker|kubernetes|postgres|sqlite|redis|tailwind|css|html|graphql|rest|grpc|vitest|jest|mocha|playwright|cypress)\b/gi,
52
52
  confidence: 0.85,
53
53
  },
54
54
  // Patterns: kebab-case compound terms that look like patterns
@@ -57,7 +57,7 @@ describe('IntentRouter', () => {
57
57
  expect(result.mode).toBe('FIX-MODE');
58
58
  expect(result.method).toBe('keyword');
59
59
  expect(result.confidence).toBeGreaterThan(0);
60
- expect(result.matchedKeywords.length).toBeGreaterThan(0);
60
+ expect(result.matchedKeywords.length).toBe(2);
61
61
  });
62
62
 
63
63
  it('classifies "build a new component" as BUILD intent', () => {
@@ -117,7 +117,7 @@ describe('IntentRouter', () => {
117
117
  // "fix bug broken error" has 4 FIX keywords vs anything else
118
118
  const result = router.routeIntent('fix bug broken error');
119
119
  expect(result.intent).toBe('fix');
120
- expect(result.matchedKeywords.length).toBeGreaterThanOrEqual(4);
120
+ expect(result.matchedKeywords.length).toBe(4);
121
121
  });
122
122
 
123
123
  it('confidence is capped at 1.0', () => {
@@ -41,10 +41,6 @@ describe('tag-manager', () => {
41
41
  });
42
42
 
43
43
  describe('DEFAULT_TAG_ALIASES', () => {
44
- it('exports expected alias count', () => {
45
- expect(DEFAULT_TAG_ALIASES.length).toBe(13);
46
- });
47
-
48
44
  it('includes common aliases', () => {
49
45
  const aliasMap = new Map(DEFAULT_TAG_ALIASES);
50
46
  expect(aliasMap.get('a11y')).toBe('accessibility');
@@ -118,11 +118,6 @@ describe('validateDomainPack', () => {
118
118
  });
119
119
 
120
120
  describe('SEMANTIC_FACADE_NAMES', () => {
121
- it('is a readonly array (TypeScript enforced)', () => {
122
- expect(Array.isArray(SEMANTIC_FACADE_NAMES)).toBe(true);
123
- expect(SEMANTIC_FACADE_NAMES.length).toBeGreaterThan(0);
124
- });
125
-
126
121
  it('contains all core engine facades', () => {
127
122
  const expected = [
128
123
  'vault',
@@ -134,13 +134,6 @@ describe('dream ops', () => {
134
134
  vault.close();
135
135
  });
136
136
 
137
- it('creates 3 ops with correct names', () => {
138
- expect(ops).toHaveLength(3);
139
- expect(ops.map((o) => o.name).sort()).toEqual(
140
- ['dream_check_gate', 'dream_run', 'dream_status'].sort(),
141
- );
142
- });
143
-
144
137
  it('dream_status returns status', async () => {
145
138
  const result = (await findOp('dream_status').handler({})) as Record<string, unknown>;
146
139
  expect(result).toHaveProperty('sessionsSinceLastDream');
@@ -136,7 +136,7 @@ describe('EnforcementRegistry', () => {
136
136
  const result = registry.translate('claude-code');
137
137
  expect(result.host).toBe('claude-code');
138
138
  // Only r1 should be translated (r2 is disabled)
139
- expect(result.files.length).toBeGreaterThan(0);
139
+ expect(result.files.length).toBe(1);
140
140
  });
141
141
  });
142
142
 
@@ -250,7 +250,7 @@ describe('ClaudeCodeAdapter', () => {
250
250
  makeRule({ id: 'bad', trigger: 'on-save' }),
251
251
  ],
252
252
  });
253
- expect(result.files.length).toBeGreaterThan(0);
253
+ expect(result.files.length).toBe(1);
254
254
  expect(result.skipped).toHaveLength(1);
255
255
  expect(result.skipped[0].ruleId).toBe('bad');
256
256
  });
@@ -38,24 +38,6 @@ afterAll(() => {
38
38
  runtime.close();
39
39
  });
40
40
 
41
- describe('createCoreOps', () => {
42
- it('returns exactly 5 ops', () => {
43
- const opDefs = createCoreOps(runtime, TEST_IDENTITY);
44
- expect(opDefs).toHaveLength(5);
45
- });
46
-
47
- it('returns ops with expected names', () => {
48
- const names = [...ops.keys()];
49
- expect(names).toEqual(['health', 'identity', 'activate', 'session_start', 'setup']);
50
- });
51
-
52
- it('all ops have read or write auth level', () => {
53
- for (const op of ops.values()) {
54
- expect(['read', 'write']).toContain(op.auth);
55
- }
56
- });
57
- });
58
-
59
41
  describe('health op', () => {
60
42
  it('returns status ok with agent info', async () => {
61
43
  const result = await executeOp(ops, 'health');
@@ -75,7 +57,7 @@ describe('health op', () => {
75
57
  const data = result.data as Record<string, unknown>;
76
58
  const vault = data.vault as Record<string, unknown>;
77
59
  expect(typeof vault.entries).toBe('number');
78
- expect(Array.isArray(vault.domains)).toBe(true);
60
+ expect(vault.domains).toEqual([]);
79
61
  });
80
62
 
81
63
  it('has read auth level', () => {
@@ -122,7 +104,7 @@ describe('activate op', () => {
122
104
  const vault = data.vault as Record<string, unknown>;
123
105
  expect(vault.connected).toBe(true);
124
106
  expect(typeof vault.entries).toBe('number');
125
- expect(Array.isArray(vault.domains)).toBe(true);
107
+ expect(vault.domains).toEqual([]);
126
108
  });
127
109
 
128
110
  it('returns deactivation response when deactivate=true', async () => {
@@ -202,8 +184,8 @@ describe('setup op', () => {
202
184
  const data = result.data as Record<string, unknown>;
203
185
  const vault = data.vault as Record<string, unknown>;
204
186
  expect(typeof vault.entries).toBe('number');
205
- expect(Array.isArray(vault.domains)).toBe(true);
206
- expect(vault.byType).toBeDefined();
187
+ expect(vault.domains).toEqual([]);
188
+ expect(vault.byType).toEqual({});
207
189
  });
208
190
 
209
191
  it('recommends action when vault is empty', async () => {
@@ -8,10 +8,31 @@
8
8
  * Now they're created dynamically by the engine at startup.
9
9
  */
10
10
 
11
+ import { readFileSync } from 'node:fs';
12
+ import { dirname, join } from 'node:path';
13
+ import { fileURLToPath } from 'node:url';
11
14
  import { z } from 'zod';
12
15
  import type { OpDefinition } from '../facades/types.js';
13
16
  import type { AgentRuntime } from '../runtime/types.js';
14
17
 
18
+ function getCoreVersion(): string {
19
+ try {
20
+ const thisDir = dirname(fileURLToPath(import.meta.url));
21
+ let dir = thisDir;
22
+ for (let i = 0; i < 5; i++) {
23
+ try {
24
+ const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf-8'));
25
+ return pkg.version ?? 'unknown';
26
+ } catch {
27
+ dir = dirname(dir);
28
+ }
29
+ }
30
+ } catch {
31
+ // import.meta.url unavailable in some test envs
32
+ }
33
+ return 'unknown';
34
+ }
35
+
15
36
  export interface AgentIdentityConfig {
16
37
  id: string;
17
38
  name: string;
@@ -38,10 +59,24 @@ export function createCoreOps(
38
59
  auth: 'read',
39
60
  handler: async () => {
40
61
  const s = runtime.vault.stats();
62
+ let vaultConnected = true;
63
+ try {
64
+ runtime.vault.stats();
65
+ } catch {
66
+ vaultConnected = false;
67
+ }
68
+ const runtimeAny = runtime as unknown as Record<string, unknown>;
69
+ const brainReady = typeof runtimeAny.brain === 'object' && runtimeAny.brain !== null;
41
70
  return {
42
71
  status: 'ok',
72
+ version: getCoreVersion(),
43
73
  agent: { name: identity.name, role: identity.role, format: 'filetree' },
44
- vault: { entries: s.totalEntries, domains: Object.keys(s.byDomain) },
74
+ vault: {
75
+ connected: vaultConnected,
76
+ entries: s.totalEntries,
77
+ domains: Object.keys(s.byDomain),
78
+ },
79
+ brain: { ready: brainReady },
45
80
  };
46
81
  },
47
82
  },
@@ -6,12 +6,7 @@
6
6
  */
7
7
 
8
8
  import { describe, it, expect } from 'vitest';
9
- import {
10
- ENGINE_MODULE_MANIFEST,
11
- CORE_KEY_OPS,
12
- ENGINE_MAJOR_VERSION,
13
- type ModuleManifestEntry,
14
- } from './module-manifest.js';
9
+ import { ENGINE_MODULE_MANIFEST, CORE_KEY_OPS, ENGINE_MAJOR_VERSION } from './module-manifest.js';
15
10
 
16
11
  describe('ENGINE_MODULE_MANIFEST', () => {
17
12
  it('contains all expected engine modules', () => {
@@ -32,10 +27,6 @@ describe('ENGINE_MODULE_MANIFEST', () => {
32
27
  expect(suffixes).toContain('intake');
33
28
  });
34
29
 
35
- it('has exactly 22 modules', () => {
36
- expect(ENGINE_MODULE_MANIFEST).toHaveLength(22);
37
- });
38
-
39
30
  it('has no duplicate suffixes', () => {
40
31
  const suffixes = ENGINE_MODULE_MANIFEST.map((m) => m.suffix);
41
32
  expect(new Set(suffixes).size).toBe(suffixes.length);
@@ -86,16 +77,6 @@ describe('ENGINE_MODULE_MANIFEST', () => {
86
77
  }
87
78
  });
88
79
 
89
- it('satisfies ModuleManifestEntry interface shape', () => {
90
- const testEntry: ModuleManifestEntry = {
91
- suffix: 'test',
92
- description: 'Test module',
93
- keyOps: ['op1'],
94
- };
95
- expect(testEntry.suffix).toBe('test');
96
- expect(testEntry.conditional).toBeUndefined();
97
- });
98
-
99
80
  it('intentSignals is optional and a Record<string, string> when present', () => {
100
81
  for (const entry of ENGINE_MODULE_MANIFEST) {
101
82
  if (entry.intentSignals !== undefined) {
@@ -144,20 +125,9 @@ describe('CORE_KEY_OPS', () => {
144
125
  it('contains the 4 core ops', () => {
145
126
  expect(CORE_KEY_OPS).toEqual(['health', 'identity', 'session_start', 'activate']);
146
127
  });
147
-
148
- it('is a string array', () => {
149
- for (const op of CORE_KEY_OPS) {
150
- expect(typeof op).toBe('string');
151
- }
152
- });
153
128
  });
154
129
 
155
130
  describe('ENGINE_MAJOR_VERSION', () => {
156
- it('is a positive integer', () => {
157
- expect(Number.isInteger(ENGINE_MAJOR_VERSION)).toBe(true);
158
- expect(ENGINE_MAJOR_VERSION).toBeGreaterThan(0);
159
- });
160
-
161
131
  it('is currently version 9', () => {
162
132
  expect(ENGINE_MAJOR_VERSION).toBe(9);
163
133
  });
@@ -63,10 +63,6 @@ describe('registerEngine — module completeness', () => {
63
63
  expect(moduleSuffixes).toEqual(manifestSuffixes);
64
64
  });
65
65
 
66
- it('ENGINE_MODULES and manifest have same count', () => {
67
- expect(ENGINE_MODULES.length).toBe(ENGINE_MODULE_MANIFEST.length);
68
- });
69
-
70
66
  it('registers all unconditional modules', () => {
71
67
  const server = makeServer();
72
68
  const result = registerEngine(server, runtime, { agentId: 'check' });
@@ -203,10 +199,9 @@ describe('registerEngine — return value', () => {
203
199
  it('returns tools array, totalOps count, and registerTool function', () => {
204
200
  const server = makeServer();
205
201
  const result = registerEngine(server, runtime, { agentId: 'ret' });
206
- expect(Array.isArray(result.tools)).toBe(true);
202
+ expect(result.tools.length).toBeGreaterThan(0);
207
203
  expect(typeof result.totalOps).toBe('number');
208
204
  expect(typeof result.registerTool).toBe('function');
209
- expect(result.totalOps).toBeGreaterThan(0);
210
205
  });
211
206
 
212
207
  it('registerTool adds a new tool at runtime', () => {
@@ -247,8 +242,8 @@ describe('registerEngine — op visibility', () => {
247
242
  expect(INTERNAL_OPS.has('create_plan')).toBe(false);
248
243
  });
249
244
 
250
- it('INTERNAL_OPS has at least 25 entries', () => {
251
- expect(INTERNAL_OPS.size).toBeGreaterThanOrEqual(25);
245
+ it('INTERNAL_OPS has exactly 29 entries', () => {
246
+ expect(INTERNAL_OPS.size).toBe(29);
252
247
  });
253
248
 
254
249
  it('ops without visibility field default to user (backward compat)', () => {
@@ -266,31 +261,6 @@ describe('registerEngine — op visibility', () => {
266
261
  expect(result.tools).toContain('vis_test');
267
262
  });
268
263
 
269
- it('ops with visibility: internal are excluded from MCP tool description but remain callable', () => {
270
- const server = makeServer();
271
- const visibleOp: OpDefinition = {
272
- name: 'public_op',
273
- description: 'Public op',
274
- auth: 'read',
275
- handler: async () => 'visible',
276
- };
277
- const internalOp: OpDefinition = {
278
- name: 'secret_op',
279
- description: 'Internal op',
280
- auth: 'admin',
281
- visibility: 'internal',
282
- handler: async () => 'hidden',
283
- };
284
- // Register both ops under a pack facade
285
- registerEngine(server, runtime, {
286
- agentId: 'vt',
287
- domainPacks: [{ name: 'test', facades: [{ name: 'check', ops: [visibleOp, internalOp] }] }],
288
- });
289
- // We can't easily inspect the MCP schema description string, but we verify
290
- // that registration succeeds with mixed visibility ops
291
- expect(true).toBe(true);
292
- });
293
-
294
264
  it('every INTERNAL_OPS entry corresponds to a real op in some facade', () => {
295
265
  // Collect all op names across all engine modules
296
266
  const allOpNames = new Set<string>();
@@ -33,9 +33,11 @@ describe('shouldRetry', () => {
33
33
  });
34
34
 
35
35
  describe('getRetryDelay', () => {
36
- it('should return a positive number', () => {
36
+ it('should return a non-negative number', () => {
37
37
  const delay = getRetryDelay(0, 'fast');
38
+ expect(typeof delay).toBe('number');
38
39
  expect(delay).toBeGreaterThanOrEqual(0);
40
+ expect(delay).toBeLessThanOrEqual(RETRY_PRESETS.fast.maxIntervalMs * 1.25);
39
41
  });
40
42
 
41
43
  it('should increase with attempt number', () => {
@@ -98,12 +98,6 @@ describe('ChainRunner', () => {
98
98
  runner = new ChainRunner(provider);
99
99
  });
100
100
 
101
- it('initializes the chain_instances table on construction', () => {
102
- expect(provider.execSql).toHaveBeenCalledWith(
103
- expect.stringContaining('CREATE TABLE IF NOT EXISTS chain_instances'),
104
- );
105
- });
106
-
107
101
  describe('execute', () => {
108
102
  it('runs all steps to completion', async () => {
109
103
  const dispatch: DispatchFn = vi.fn(async () => ({ result: 'ok' }));
@@ -11,7 +11,7 @@ import { getFlowOverrides, detectContext } from './context-router.js';
11
11
  describe('getFlowOverrides', () => {
12
12
  it('returns overrides for BUILD-flow', () => {
13
13
  const overrides = getFlowOverrides('BUILD-flow');
14
- expect(overrides.length).toBeGreaterThan(0);
14
+ expect(overrides).toHaveLength(4);
15
15
  const contexts = overrides.map((o) => o.context);
16
16
  expect(contexts).toContain('small-component');
17
17
  expect(contexts).toContain('large-component');
@@ -19,7 +19,7 @@ describe('getFlowOverrides', () => {
19
19
 
20
20
  it('returns overrides for FIX-flow', () => {
21
21
  const overrides = getFlowOverrides('FIX-flow');
22
- expect(overrides.length).toBeGreaterThan(0);
22
+ expect(overrides).toHaveLength(2);
23
23
  const contexts = overrides.map((o) => o.context);
24
24
  expect(contexts).toContain('design-fix');
25
25
  expect(contexts).toContain('a11y-fix');
@@ -27,7 +27,7 @@ describe('getFlowOverrides', () => {
27
27
 
28
28
  it('returns overrides for REVIEW-flow', () => {
29
29
  const overrides = getFlowOverrides('REVIEW-flow');
30
- expect(overrides.length).toBeGreaterThan(0);
30
+ expect(overrides).toHaveLength(2);
31
31
  const contexts = overrides.map((o) => o.context);
32
32
  expect(contexts).toContain('pr-review');
33
33
  expect(contexts).toContain('architecture-review');