@soleri/core 9.14.4 → 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 (355) 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/brain/brain.d.ts +9 -0
  8. package/dist/brain/brain.d.ts.map +1 -1
  9. package/dist/brain/brain.js +11 -1
  10. package/dist/brain/brain.js.map +1 -1
  11. package/dist/brain/intelligence.d.ts.map +1 -1
  12. package/dist/brain/intelligence.js +24 -0
  13. package/dist/brain/intelligence.js.map +1 -1
  14. package/dist/brain/types.d.ts +1 -0
  15. package/dist/brain/types.d.ts.map +1 -1
  16. package/dist/capabilities/chain-mapping.d.ts.map +1 -1
  17. package/dist/capabilities/chain-mapping.js +5 -4
  18. package/dist/capabilities/chain-mapping.js.map +1 -1
  19. package/dist/capabilities/registry.d.ts +6 -0
  20. package/dist/capabilities/registry.d.ts.map +1 -1
  21. package/dist/capabilities/registry.js +3 -2
  22. package/dist/capabilities/registry.js.map +1 -1
  23. package/dist/chat/chat-session.d.ts +6 -0
  24. package/dist/chat/chat-session.d.ts.map +1 -1
  25. package/dist/chat/chat-session.js +68 -17
  26. package/dist/chat/chat-session.js.map +1 -1
  27. package/dist/context/context-engine.js +1 -1
  28. package/dist/context/context-engine.js.map +1 -1
  29. package/dist/curator/curator.d.ts +6 -0
  30. package/dist/curator/curator.d.ts.map +1 -1
  31. package/dist/curator/curator.js +138 -0
  32. package/dist/curator/curator.js.map +1 -1
  33. package/dist/curator/types.d.ts +10 -0
  34. package/dist/curator/types.d.ts.map +1 -1
  35. package/dist/engine/bin/soleri-engine.js +0 -0
  36. package/dist/engine/core-ops.d.ts.map +1 -1
  37. package/dist/engine/core-ops.js +38 -1
  38. package/dist/engine/core-ops.js.map +1 -1
  39. package/dist/flows/epilogue.d.ts +5 -1
  40. package/dist/flows/epilogue.d.ts.map +1 -1
  41. package/dist/flows/epilogue.js +11 -3
  42. package/dist/flows/epilogue.js.map +1 -1
  43. package/dist/flows/executor.d.ts.map +1 -1
  44. package/dist/flows/executor.js +13 -5
  45. package/dist/flows/executor.js.map +1 -1
  46. package/dist/flows/index.d.ts +1 -2
  47. package/dist/flows/index.d.ts.map +1 -1
  48. package/dist/flows/index.js +1 -0
  49. package/dist/flows/index.js.map +1 -1
  50. package/dist/flows/plan-builder.d.ts +17 -1
  51. package/dist/flows/plan-builder.d.ts.map +1 -1
  52. package/dist/flows/plan-builder.js +67 -6
  53. package/dist/flows/plan-builder.js.map +1 -1
  54. package/dist/flows/probes.d.ts +1 -1
  55. package/dist/flows/probes.d.ts.map +1 -1
  56. package/dist/flows/probes.js +15 -3
  57. package/dist/flows/probes.js.map +1 -1
  58. package/dist/flows/types.d.ts +47 -20
  59. package/dist/flows/types.d.ts.map +1 -1
  60. package/dist/flows/types.js +6 -1
  61. package/dist/flows/types.js.map +1 -1
  62. package/dist/index.d.ts +10 -0
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +9 -0
  65. package/dist/index.js.map +1 -1
  66. package/dist/intake/content-classifier.d.ts +10 -4
  67. package/dist/intake/content-classifier.d.ts.map +1 -1
  68. package/dist/intake/content-classifier.js +19 -5
  69. package/dist/intake/content-classifier.js.map +1 -1
  70. package/dist/intake/text-ingester.d.ts +18 -0
  71. package/dist/intake/text-ingester.d.ts.map +1 -1
  72. package/dist/intake/text-ingester.js +37 -13
  73. package/dist/intake/text-ingester.js.map +1 -1
  74. package/dist/packs/pack-installer.d.ts.map +1 -1
  75. package/dist/packs/pack-installer.js +28 -2
  76. package/dist/packs/pack-installer.js.map +1 -1
  77. package/dist/planning/planner-types.d.ts +2 -0
  78. package/dist/planning/planner-types.d.ts.map +1 -1
  79. package/dist/planning/planner.d.ts +4 -0
  80. package/dist/planning/planner.d.ts.map +1 -1
  81. package/dist/planning/planner.js +50 -4
  82. package/dist/planning/planner.js.map +1 -1
  83. package/dist/playbooks/playbook-executor.d.ts +10 -1
  84. package/dist/playbooks/playbook-executor.d.ts.map +1 -1
  85. package/dist/playbooks/playbook-executor.js +8 -2
  86. package/dist/playbooks/playbook-executor.js.map +1 -1
  87. package/dist/playbooks/playbook-types.d.ts +8 -0
  88. package/dist/playbooks/playbook-types.d.ts.map +1 -1
  89. package/dist/plugins/types.d.ts +2 -2
  90. package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
  91. package/dist/runtime/admin-extra-ops.js +30 -0
  92. package/dist/runtime/admin-extra-ops.js.map +1 -1
  93. package/dist/runtime/admin-ops.d.ts.map +1 -1
  94. package/dist/runtime/admin-ops.js +60 -21
  95. package/dist/runtime/admin-ops.js.map +1 -1
  96. package/dist/runtime/admin-setup-ops.d.ts +11 -0
  97. package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
  98. package/dist/runtime/admin-setup-ops.js +146 -37
  99. package/dist/runtime/admin-setup-ops.js.map +1 -1
  100. package/dist/runtime/capture-ops.d.ts.map +1 -1
  101. package/dist/runtime/capture-ops.js +38 -12
  102. package/dist/runtime/capture-ops.js.map +1 -1
  103. package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
  104. package/dist/runtime/facades/brain-facade.js +16 -4
  105. package/dist/runtime/facades/brain-facade.js.map +1 -1
  106. package/dist/runtime/facades/context-facade.d.ts.map +1 -1
  107. package/dist/runtime/facades/context-facade.js +9 -3
  108. package/dist/runtime/facades/context-facade.js.map +1 -1
  109. package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
  110. package/dist/runtime/facades/memory-facade.js +20 -7
  111. package/dist/runtime/facades/memory-facade.js.map +1 -1
  112. package/dist/runtime/facades/orchestrate-facade.d.ts.map +1 -1
  113. package/dist/runtime/facades/orchestrate-facade.js +40 -1
  114. package/dist/runtime/facades/orchestrate-facade.js.map +1 -1
  115. package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
  116. package/dist/runtime/facades/plan-facade.js +113 -4
  117. package/dist/runtime/facades/plan-facade.js.map +1 -1
  118. package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
  119. package/dist/runtime/facades/vault-facade.js +24 -3
  120. package/dist/runtime/facades/vault-facade.js.map +1 -1
  121. package/dist/runtime/orchestrate-ops.d.ts +21 -0
  122. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  123. package/dist/runtime/orchestrate-ops.js +132 -38
  124. package/dist/runtime/orchestrate-ops.js.map +1 -1
  125. package/dist/runtime/runtime.d.ts.map +1 -1
  126. package/dist/runtime/runtime.js +16 -0
  127. package/dist/runtime/runtime.js.map +1 -1
  128. package/dist/runtime/schema-helpers.d.ts.map +1 -1
  129. package/dist/runtime/schema-helpers.js +4 -0
  130. package/dist/runtime/schema-helpers.js.map +1 -1
  131. package/dist/runtime/types.d.ts +19 -0
  132. package/dist/runtime/types.d.ts.map +1 -1
  133. package/dist/runtime/vault-linking-ops.d.ts.map +1 -1
  134. package/dist/runtime/vault-linking-ops.js +16 -3
  135. package/dist/runtime/vault-linking-ops.js.map +1 -1
  136. package/dist/scheduler/cron-validator.d.ts +15 -0
  137. package/dist/scheduler/cron-validator.d.ts.map +1 -0
  138. package/dist/scheduler/cron-validator.js +93 -0
  139. package/dist/scheduler/cron-validator.js.map +1 -0
  140. package/dist/scheduler/platform-linux.d.ts +14 -0
  141. package/dist/scheduler/platform-linux.d.ts.map +1 -0
  142. package/dist/scheduler/platform-linux.js +107 -0
  143. package/dist/scheduler/platform-linux.js.map +1 -0
  144. package/dist/scheduler/platform-macos.d.ts +15 -0
  145. package/dist/scheduler/platform-macos.d.ts.map +1 -0
  146. package/dist/scheduler/platform-macos.js +131 -0
  147. package/dist/scheduler/platform-macos.js.map +1 -0
  148. package/dist/scheduler/scheduler-ops.d.ts +14 -0
  149. package/dist/scheduler/scheduler-ops.d.ts.map +1 -0
  150. package/dist/scheduler/scheduler-ops.js +77 -0
  151. package/dist/scheduler/scheduler-ops.js.map +1 -0
  152. package/dist/scheduler/scheduler.d.ts +55 -0
  153. package/dist/scheduler/scheduler.d.ts.map +1 -0
  154. package/dist/scheduler/scheduler.js +144 -0
  155. package/dist/scheduler/scheduler.js.map +1 -0
  156. package/dist/scheduler/types.d.ts +48 -0
  157. package/dist/scheduler/types.d.ts.map +1 -0
  158. package/dist/scheduler/types.js +6 -0
  159. package/dist/scheduler/types.js.map +1 -0
  160. package/dist/skills/sync-skills.d.ts +11 -0
  161. package/dist/skills/sync-skills.d.ts.map +1 -1
  162. package/dist/skills/sync-skills.js +132 -38
  163. package/dist/skills/sync-skills.js.map +1 -1
  164. package/dist/skills/validate-skills.d.ts +32 -0
  165. package/dist/skills/validate-skills.d.ts.map +1 -0
  166. package/dist/skills/validate-skills.js +396 -0
  167. package/dist/skills/validate-skills.js.map +1 -0
  168. package/dist/utils/worktree-reaper.d.ts +38 -0
  169. package/dist/utils/worktree-reaper.d.ts.map +1 -0
  170. package/dist/utils/worktree-reaper.js +85 -0
  171. package/dist/utils/worktree-reaper.js.map +1 -0
  172. package/dist/vault/default-canonical-tags.d.ts +15 -0
  173. package/dist/vault/default-canonical-tags.d.ts.map +1 -0
  174. package/dist/vault/default-canonical-tags.js +65 -0
  175. package/dist/vault/default-canonical-tags.js.map +1 -0
  176. package/dist/vault/scope-detector.d.ts.map +1 -1
  177. package/dist/vault/scope-detector.js +37 -4
  178. package/dist/vault/scope-detector.js.map +1 -1
  179. package/dist/vault/tag-normalizer.d.ts +42 -0
  180. package/dist/vault/tag-normalizer.d.ts.map +1 -0
  181. package/dist/vault/tag-normalizer.js +157 -0
  182. package/dist/vault/tag-normalizer.js.map +1 -0
  183. package/dist/vault/vault-entries.d.ts.map +1 -1
  184. package/dist/vault/vault-entries.js +3 -1
  185. package/dist/vault/vault-entries.js.map +1 -1
  186. package/package.json +5 -1
  187. package/src/__tests__/embeddings.test.ts +3 -3
  188. package/src/agency/agency-manager.test.ts +4 -4
  189. package/src/agency/default-rules.test.ts +0 -13
  190. package/src/brain/brain-intelligence.test.ts +0 -5
  191. package/src/brain/brain.ts +25 -1
  192. package/src/brain/intelligence.ts +25 -0
  193. package/src/brain/second-brain-features.test.ts +2 -14
  194. package/src/brain/types.ts +1 -0
  195. package/src/capabilities/chain-mapping.test.ts +1 -6
  196. package/src/capabilities/chain-mapping.ts +6 -4
  197. package/src/capabilities/registry.test.ts +1 -1
  198. package/src/capabilities/registry.ts +9 -2
  199. package/src/chat/agent-loop.test.ts +1 -1
  200. package/src/chat/chat-enhanced.test.ts +0 -8
  201. package/src/chat/chat-session.ts +75 -17
  202. package/src/chat/chat-transport.test.ts +31 -1
  203. package/src/claudemd/compose.test.ts +0 -5
  204. package/src/context/context-engine.test.ts +0 -1
  205. package/src/context/context-engine.ts +1 -1
  206. package/src/control/intent-router.test.ts +2 -2
  207. package/src/curator/curator.ts +180 -0
  208. package/src/curator/tag-manager.test.ts +0 -4
  209. package/src/curator/types.ts +10 -0
  210. package/src/domain-packs/types.test.ts +0 -5
  211. package/src/dream/dream.test.ts +0 -7
  212. package/src/enforcement/registry.test.ts +2 -2
  213. package/src/engine/core-ops.test.ts +4 -22
  214. package/src/engine/core-ops.ts +36 -1
  215. package/src/engine/module-manifest.test.ts +1 -31
  216. package/src/engine/register-engine.test.ts +3 -33
  217. package/src/errors/retry.test.ts +3 -1
  218. package/src/flows/chain-runner.test.ts +0 -6
  219. package/src/flows/context-router.test.ts +3 -3
  220. package/src/flows/epilogue.test.ts +40 -2
  221. package/src/flows/epilogue.ts +11 -2
  222. package/src/flows/executor.test.ts +48 -2
  223. package/src/flows/executor.ts +15 -5
  224. package/src/flows/index.ts +1 -3
  225. package/src/flows/plan-builder.test.ts +201 -0
  226. package/src/flows/plan-builder.ts +81 -5
  227. package/src/flows/probes.ts +17 -3
  228. package/src/flows/types.ts +31 -2
  229. package/src/health/health-registry.test.ts +3 -1
  230. package/src/index.ts +24 -0
  231. package/src/intake/content-classifier.ts +22 -4
  232. package/src/intake/dedup-gate.test.ts +2 -6
  233. package/src/intake/text-ingester.test.ts +3 -4
  234. package/src/intake/text-ingester.ts +61 -12
  235. package/src/llm/llm-client.test.ts +1 -1
  236. package/src/llm/utils.test.ts +1 -1
  237. package/src/migrations/migration-runner.test.ts +0 -1
  238. package/src/operator/operator-context-store.test.ts +0 -13
  239. package/src/operator/operator-profile.test.ts +2 -20
  240. package/src/packs/pack-installer.ts +28 -2
  241. package/src/packs/pack-system.test.ts +2 -2
  242. package/src/persona/defaults.test.ts +19 -19
  243. package/src/planning/gap-passes.test.ts +0 -46
  244. package/src/planning/gap-patterns.test.ts +0 -42
  245. package/src/planning/goal-ancestry.test.ts +3 -1
  246. package/src/planning/plan-lifecycle.test.ts +15 -7
  247. package/src/planning/planner-types.ts +2 -0
  248. package/src/planning/planner.test.ts +86 -90
  249. package/src/planning/planner.ts +56 -4
  250. package/src/planning/reconciliation-engine.test.ts +3 -10
  251. package/src/planning/task-complexity-assessor.test.ts +0 -5
  252. package/src/planning/task-verifier.test.ts +3 -1
  253. package/src/playbooks/generic/generic-playbooks.test.ts +0 -28
  254. package/src/playbooks/index.test.ts +0 -55
  255. package/src/playbooks/playbook-executor.test.ts +76 -0
  256. package/src/playbooks/playbook-executor.ts +24 -3
  257. package/src/playbooks/playbook-types.ts +8 -0
  258. package/src/plugins/plugin-registry.test.ts +6 -2
  259. package/src/project/project-registry.test.ts +2 -0
  260. package/src/queue/async-infrastructure.test.ts +6 -4
  261. package/src/queue/job-queue.test.ts +13 -7
  262. package/src/runtime/admin-extra-ops.test.ts +35 -30
  263. package/src/runtime/admin-extra-ops.ts +30 -0
  264. package/src/runtime/admin-ops.test.ts +0 -4
  265. package/src/runtime/admin-ops.ts +63 -21
  266. package/src/runtime/admin-setup-ops.test.ts +229 -13
  267. package/src/runtime/admin-setup-ops.ts +145 -36
  268. package/src/runtime/archive-ops.test.ts +0 -28
  269. package/src/runtime/branching-ops.test.ts +0 -17
  270. package/src/runtime/capture-ops.test.ts +41 -16
  271. package/src/runtime/capture-ops.ts +78 -46
  272. package/src/runtime/chain-ops.test.ts +0 -21
  273. package/src/runtime/facades/admin-facade.test.ts +0 -34
  274. package/src/runtime/facades/agency-facade.test.ts +0 -39
  275. package/src/runtime/facades/archive-facade.test.ts +0 -43
  276. package/src/runtime/facades/brain-facade.test.ts +8 -99
  277. package/src/runtime/facades/brain-facade.ts +29 -12
  278. package/src/runtime/facades/branching-facade.test.ts +30 -17
  279. package/src/runtime/facades/chat-facade.test.ts +0 -91
  280. package/src/runtime/facades/chat-service-ops.test.ts +0 -24
  281. package/src/runtime/facades/chat-session-ops.test.ts +0 -12
  282. package/src/runtime/facades/chat-transport-ops.test.ts +0 -23
  283. package/src/runtime/facades/context-facade.test.ts +0 -17
  284. package/src/runtime/facades/context-facade.ts +11 -4
  285. package/src/runtime/facades/control-facade.test.ts +0 -30
  286. package/src/runtime/facades/curator-facade.test.ts +0 -33
  287. package/src/runtime/facades/intake-facade.test.ts +0 -33
  288. package/src/runtime/facades/links-facade.test.ts +0 -37
  289. package/src/runtime/facades/loop-facade.test.ts +0 -26
  290. package/src/runtime/facades/memory-facade.test.ts +0 -18
  291. package/src/runtime/facades/memory-facade.ts +27 -11
  292. package/src/runtime/facades/operator-facade.test.ts +0 -31
  293. package/src/runtime/facades/orchestrate-facade.test.ts +0 -21
  294. package/src/runtime/facades/orchestrate-facade.ts +39 -1
  295. package/src/runtime/facades/plan-facade.test.ts +7 -32
  296. package/src/runtime/facades/plan-facade.ts +137 -4
  297. package/src/runtime/facades/review-facade.test.ts +1 -49
  298. package/src/runtime/facades/sync-facade.test.ts +24 -41
  299. package/src/runtime/facades/tier-facade.test.ts +30 -22
  300. package/src/runtime/facades/vault-facade.test.ts +0 -41
  301. package/src/runtime/facades/vault-facade.ts +26 -3
  302. package/src/runtime/grading-ops.test.ts +0 -27
  303. package/src/runtime/intake-ops.test.ts +0 -19
  304. package/src/runtime/loop-ops.test.ts +0 -48
  305. package/src/runtime/memory-cross-project-ops.test.ts +0 -14
  306. package/src/runtime/memory-extra-ops.test.ts +4 -8
  307. package/src/runtime/orchestrate-ops.test.ts +238 -19
  308. package/src/runtime/orchestrate-ops.ts +166 -41
  309. package/src/runtime/pack-ops.test.ts +0 -26
  310. package/src/runtime/planning-extra-ops.test.ts +2 -14
  311. package/src/runtime/playbook-ops-execution.test.ts +9 -20
  312. package/src/runtime/playbook-ops.test.ts +4 -67
  313. package/src/runtime/review-ops.test.ts +0 -15
  314. package/src/runtime/runtime.ts +18 -0
  315. package/src/runtime/schema-helpers.ts +4 -0
  316. package/src/runtime/sync-ops.test.ts +0 -18
  317. package/src/runtime/tier-ops.test.ts +0 -21
  318. package/src/runtime/types.ts +19 -0
  319. package/src/runtime/vault-extra-ops.test.ts +0 -12
  320. package/src/runtime/vault-linking-ops.test.ts +0 -4
  321. package/src/runtime/vault-linking-ops.ts +26 -8
  322. package/src/runtime/vault-sharing-ops.test.ts +0 -9
  323. package/src/scheduler/cron-validator.ts +101 -0
  324. package/src/scheduler/platform-linux.ts +122 -0
  325. package/src/scheduler/platform-macos.ts +150 -0
  326. package/src/scheduler/scheduler-ops.ts +77 -0
  327. package/src/scheduler/scheduler.test.ts +247 -0
  328. package/src/scheduler/scheduler.ts +174 -0
  329. package/src/scheduler/types.ts +52 -0
  330. package/src/skills/__tests__/sync-skills.test.ts +6 -17
  331. package/src/skills/global-claude-md.test.ts +113 -0
  332. package/src/skills/sync-skills.ts +143 -35
  333. package/src/skills/validate-skills.test.ts +206 -0
  334. package/src/skills/validate-skills.ts +470 -0
  335. package/src/telemetry/telemetry.test.ts +1 -0
  336. package/src/transport/http-server.test.ts +3 -0
  337. package/src/transport/session-manager.test.ts +3 -1
  338. package/src/transport/token-auth.test.ts +6 -9
  339. package/src/transport/ws-server.test.ts +10 -2
  340. package/src/utils/worktree-reaper.ts +113 -0
  341. package/src/vault/__tests__/vault-characterization.test.ts +0 -108
  342. package/src/vault/default-canonical-tags.ts +64 -0
  343. package/src/vault/linking.test.ts +0 -2
  344. package/src/vault/playbook.test.ts +4 -1
  345. package/src/vault/scope-detector.test.ts +3 -1
  346. package/src/vault/scope-detector.ts +42 -4
  347. package/src/vault/tag-normalizer.test.ts +214 -0
  348. package/src/vault/tag-normalizer.ts +188 -0
  349. package/src/vault/vault-connect.test.ts +1 -1
  350. package/src/vault/vault-entries.ts +3 -1
  351. package/src/vault/vault.test.ts +23 -8
  352. package/dist/embeddings/index.d.ts +0 -5
  353. package/dist/embeddings/index.d.ts.map +0 -1
  354. package/dist/embeddings/index.js +0 -3
  355. package/dist/embeddings/index.js.map +0 -1
@@ -30,42 +30,56 @@ export function createCaptureOps(runtime: AgentRuntime): OpDefinition[] {
30
30
  description:
31
31
  'Batch-capture knowledge entries with governance gating and auto-enrichment via TF-IDF tagging.',
32
32
  auth: 'write',
33
- schema: z.object({
34
- projectPath: z.string().optional().default('.'),
35
- tier: z
36
- .enum(['agent', 'project', 'team'])
37
- .optional()
38
- .describe('Manual tier override. If omitted, tier is auto-detected from content.'),
39
- entries: coerceArray(
40
- z.object({
41
- id: z.string().optional(),
42
- type: z
43
- .enum([
44
- 'pattern',
45
- 'anti-pattern',
46
- 'rule',
47
- 'playbook',
48
- 'workflow',
49
- 'principle',
50
- 'reference',
51
- ])
52
- .describe('Entry type'),
53
- domain: z.string(),
54
- title: z.string(),
55
- severity: z.enum(['critical', 'warning', 'info']).optional().default('info'),
56
- description: z.string(),
57
- tags: z.array(z.string()).optional().default([]),
58
- context: z.string().optional(),
59
- example: z.string().optional(),
60
- counterExample: z.string().optional(),
61
- why: z.string().optional(),
62
- tier: z
63
- .enum(['agent', 'project', 'team'])
64
- .optional()
65
- .describe('Per-entry tier override. Falls back to top-level tier, then auto-detect.'),
66
- }),
67
- ),
68
- }),
33
+ schema: z.preprocess(
34
+ (val) => {
35
+ // Auto-wrap flat entry fields into { entries: [val] } so callers don't need the wrapper
36
+ if (val !== null && typeof val === 'object' && !Array.isArray(val)) {
37
+ const obj = val as Record<string, unknown>;
38
+ if (obj.entries === undefined && (obj.type !== undefined || obj.title !== undefined)) {
39
+ return { entries: [obj] };
40
+ }
41
+ }
42
+ return val;
43
+ },
44
+ z.object({
45
+ projectPath: z.string().optional().default('.'),
46
+ tier: z
47
+ .enum(['agent', 'project', 'team'])
48
+ .optional()
49
+ .describe('Manual tier override. If omitted, tier is auto-detected from content.'),
50
+ entries: coerceArray(
51
+ z.object({
52
+ id: z.string().optional(),
53
+ type: z
54
+ .enum([
55
+ 'pattern',
56
+ 'anti-pattern',
57
+ 'rule',
58
+ 'playbook',
59
+ 'workflow',
60
+ 'principle',
61
+ 'reference',
62
+ ])
63
+ .describe('Entry type'),
64
+ domain: z.string(),
65
+ title: z.string(),
66
+ severity: z.enum(['critical', 'warning', 'info']).optional().default('info'),
67
+ description: z.string(),
68
+ tags: z.array(z.string()).optional().default([]),
69
+ context: z.string().optional(),
70
+ example: z.string().optional(),
71
+ counterExample: z.string().optional(),
72
+ why: z.string().optional(),
73
+ tier: z
74
+ .enum(['agent', 'project', 'team'])
75
+ .optional()
76
+ .describe(
77
+ 'Per-entry tier override. Falls back to top-level tier, then auto-detect.',
78
+ ),
79
+ }),
80
+ ),
81
+ }),
82
+ ),
69
83
  handler: async (params) => {
70
84
  const projectPath = (params.projectPath as string | undefined) ?? '.';
71
85
  const topTier = params.tier as ScopeTier | undefined;
@@ -326,10 +340,13 @@ export function createCaptureOps(runtime: AgentRuntime): OpDefinition[] {
326
340
  'principle',
327
341
  'reference',
328
342
  ])
329
- .describe('Entry type'),
330
- domain: z.string(),
343
+ .optional()
344
+ .default('pattern')
345
+ .describe('Entry type (default: "pattern")'),
346
+ domain: z.string().optional().default('general'),
331
347
  title: z.string(),
332
- description: z.string(),
348
+ description: z.string().optional().describe('Knowledge description (alias: content)'),
349
+ content: z.string().optional().describe('Alias for description'),
333
350
  tags: z.array(z.string()).optional().default([]),
334
351
  tier: z
335
352
  .enum(['agent', 'project', 'team'])
@@ -338,10 +355,13 @@ export function createCaptureOps(runtime: AgentRuntime): OpDefinition[] {
338
355
  }),
339
356
  handler: async (params) => {
340
357
  const projectPath = (params.projectPath as string | undefined) ?? '.';
341
- const entryType = params.type as string;
342
- const domain = params.domain as string;
358
+ const entryType = (params.type as string | undefined) ?? 'pattern';
359
+ const domain = (params.domain as string | undefined) ?? 'general';
343
360
  const title = params.title as string;
344
- const description = params.description as string;
361
+ const description =
362
+ (params.description as string | undefined) ??
363
+ (params.content as string | undefined) ??
364
+ '';
345
365
  const tags = (params.tags as string[] | undefined) ?? [];
346
366
  const manualTier = params.tier as ScopeTier | undefined;
347
367
 
@@ -405,6 +425,15 @@ export function createCaptureOps(runtime: AgentRuntime): OpDefinition[] {
405
425
  result.reviewNote =
406
426
  'Low confidence scope detection — consider reviewing tier assignment';
407
427
  }
428
+ const PLANNING_TYPES = new Set(['anti-pattern', 'pattern']);
429
+ const PLANNING_TAGS = new Set(['planning-gate', 'rules', 'quality']);
430
+ const hasPlanningType = PLANNING_TYPES.has(mappedType);
431
+ const hasPlanningTag = tags.some((t) => PLANNING_TAGS.has(t));
432
+ if (hasPlanningType || hasPlanningTag) {
433
+ result.planningNote =
434
+ 'This entry type influences planning but has no content body (context/example/why). ' +
435
+ 'Use capture_knowledge to add those fields — without them, the orchestrator cannot apply this rule during planning.';
436
+ }
408
437
  // Fire-and-forget markdown sync
409
438
  fireAndForgetSync(
410
439
  {
@@ -566,10 +595,13 @@ export function createCaptureOps(runtime: AgentRuntime): OpDefinition[] {
566
595
  'Record feedback on search results to improve future ranking via brain learning.',
567
596
  auth: 'write',
568
597
  schema: z.object({
569
- query: z.string(),
570
- entryId: z.string(),
571
- helpful: z.boolean(),
572
- context: z.string().optional(),
598
+ query: z.string().describe('The search query that produced this result (required)'),
599
+ entryId: z.string().describe('ID of the vault entry being rated (required)'),
600
+ helpful: z.boolean().describe('Whether the result was helpful — true or false (required)'),
601
+ context: z
602
+ .string()
603
+ .optional()
604
+ .describe('Optional context about why it was or was not helpful'),
573
605
  }),
574
606
  handler: async (params) => {
575
607
  const query = params.query as string;
@@ -25,27 +25,6 @@ const VALID_CHAIN = {
25
25
  };
26
26
 
27
27
  describe('createChainOps', () => {
28
- it('returns exactly 5 ops', () => {
29
- const ops = createChainOps(mockRuntime());
30
- expect(ops).toHaveLength(5);
31
- expect(ops.map((o) => o.name)).toEqual([
32
- 'chain_execute',
33
- 'chain_status',
34
- 'chain_resume',
35
- 'chain_list',
36
- 'chain_step_approve',
37
- ]);
38
- });
39
-
40
- it('assigns correct auth levels', () => {
41
- const ops = captureOps(createChainOps(mockRuntime()));
42
- expect(ops.get('chain_execute')!.auth).toBe('write');
43
- expect(ops.get('chain_status')!.auth).toBe('read');
44
- expect(ops.get('chain_resume')!.auth).toBe('write');
45
- expect(ops.get('chain_list')!.auth).toBe('read');
46
- expect(ops.get('chain_step_approve')!.auth).toBe('write');
47
- });
48
-
49
28
  describe('chain_execute', () => {
50
29
  it('calls chainRunner.execute with chain def and input', async () => {
51
30
  const rt = mockRuntime();
@@ -108,40 +108,6 @@ describe('createAdminFacadeOps', () => {
108
108
  ops = createAdminFacadeOps(runtime);
109
109
  });
110
110
 
111
- it('returns inline ops (llm_rotate, llm_call, render_prompt, list_templates)', () => {
112
- const names = ops.map((o) => o.name);
113
- expect(names).toContain('llm_rotate');
114
- expect(names).toContain('llm_call');
115
- expect(names).toContain('render_prompt');
116
- expect(names).toContain('list_templates');
117
- });
118
-
119
- it('includes satellite ops from admin-ops', () => {
120
- const names = ops.map((o) => o.name);
121
- expect(names).toContain('admin_health');
122
- expect(names).toContain('admin_diagnostic');
123
- expect(names).toContain('admin_config');
124
- });
125
-
126
- it('includes satellite ops from admin-extra-ops', () => {
127
- const names = ops.map((o) => o.name);
128
- expect(names).toContain('admin_telemetry');
129
- expect(names).toContain('admin_permissions');
130
- expect(names).toContain('admin_vault_analytics');
131
- });
132
-
133
- it('includes satellite ops from admin-setup-ops', () => {
134
- const names = ops.map((o) => o.name);
135
- expect(names).toContain('admin_inject_claude_md');
136
- expect(names).toContain('admin_setup_global');
137
- expect(names).toContain('admin_check_persistence');
138
- });
139
-
140
- it('includes session briefing ops', () => {
141
- const names = ops.map((o) => o.name);
142
- expect(names).toContain('session_briefing');
143
- });
144
-
145
111
  describe('llm_rotate', () => {
146
112
  it('rotates openai key pool', async () => {
147
113
  const result = (await findOp(ops, 'llm_rotate').handler({
@@ -40,45 +40,6 @@ describe('createAgencyFacadeOps', () => {
40
40
  ops = createAgencyFacadeOps(runtime);
41
41
  });
42
42
 
43
- it('returns all expected ops', () => {
44
- const names = ops.map((o) => o.name);
45
- expect(names).toEqual([
46
- 'agency_enable',
47
- 'agency_disable',
48
- 'agency_status',
49
- 'agency_config',
50
- 'agency_scan_file',
51
- 'agency_warnings',
52
- 'agency_surface_patterns',
53
- 'agency_clarify',
54
- 'agency_suggestions',
55
- 'agency_rich_clarify',
56
- 'agency_suppress_warning',
57
- 'agency_unsuppress_warning',
58
- 'agency_dismiss_pattern',
59
- 'agency_notifications',
60
- 'agency_full_status',
61
- ]);
62
- });
63
-
64
- it('assigns correct auth levels', () => {
65
- expect(findOp(ops, 'agency_enable').auth).toBe('write');
66
- expect(findOp(ops, 'agency_disable').auth).toBe('write');
67
- expect(findOp(ops, 'agency_status').auth).toBe('read');
68
- expect(findOp(ops, 'agency_config').auth).toBe('write');
69
- expect(findOp(ops, 'agency_scan_file').auth).toBe('read');
70
- expect(findOp(ops, 'agency_warnings').auth).toBe('read');
71
- expect(findOp(ops, 'agency_surface_patterns').auth).toBe('read');
72
- expect(findOp(ops, 'agency_clarify').auth).toBe('read');
73
- expect(findOp(ops, 'agency_suggestions').auth).toBe('read');
74
- expect(findOp(ops, 'agency_rich_clarify').auth).toBe('read');
75
- expect(findOp(ops, 'agency_suppress_warning').auth).toBe('write');
76
- expect(findOp(ops, 'agency_unsuppress_warning').auth).toBe('write');
77
- expect(findOp(ops, 'agency_dismiss_pattern').auth).toBe('write');
78
- expect(findOp(ops, 'agency_notifications').auth).toBe('read');
79
- expect(findOp(ops, 'agency_full_status').auth).toBe('read');
80
- });
81
-
82
43
  describe('agency_enable', () => {
83
44
  it('enables with default project path', async () => {
84
45
  const status = { enabled: true, watching: true };
@@ -82,49 +82,6 @@ describe('archive-facade', () => {
82
82
  ops = captureOps(createArchiveFacadeOps(runtime));
83
83
  });
84
84
 
85
- // ─── Registration ─────────────────────────────────────────────────
86
-
87
- it('registers 12 ops', () => {
88
- expect(ops.size).toBe(12);
89
- });
90
-
91
- it('includes all expected op names', () => {
92
- const expected = [
93
- 'vault_archive',
94
- 'vault_restore',
95
- 'vault_optimize',
96
- 'vault_backup',
97
- 'vault_age_report',
98
- 'vault_set_temporal',
99
- 'vault_find_expiring',
100
- 'vault_find_expired',
101
- 'knowledge_audit',
102
- 'knowledge_health',
103
- 'knowledge_merge',
104
- 'knowledge_reorganize',
105
- ];
106
- for (const name of expected) {
107
- expect(ops.has(name), `missing op: ${name}`).toBe(true);
108
- }
109
- });
110
-
111
- // ─── Auth levels ─────────────────────────────────────────────────
112
-
113
- it('has correct auth levels', () => {
114
- expect(ops.get('vault_archive')!.auth).toBe('write');
115
- expect(ops.get('vault_restore')!.auth).toBe('write');
116
- expect(ops.get('vault_optimize')!.auth).toBe('write');
117
- expect(ops.get('vault_backup')!.auth).toBe('read');
118
- expect(ops.get('vault_age_report')!.auth).toBe('read');
119
- expect(ops.get('vault_set_temporal')!.auth).toBe('write');
120
- expect(ops.get('vault_find_expiring')!.auth).toBe('read');
121
- expect(ops.get('vault_find_expired')!.auth).toBe('read');
122
- expect(ops.get('knowledge_audit')!.auth).toBe('read');
123
- expect(ops.get('knowledge_health')!.auth).toBe('read');
124
- expect(ops.get('knowledge_merge')!.auth).toBe('write');
125
- expect(ops.get('knowledge_reorganize')!.auth).toBe('write');
126
- });
127
-
128
85
  // ─── vault_archive ──────────────────────────────────────────────
129
86
 
130
87
  describe('vault_archive', () => {
@@ -117,98 +117,6 @@ describe('brain-facade', () => {
117
117
  ops = captureOps(createBrainFacadeOps(runtime));
118
118
  });
119
119
 
120
- // ─── Registration ─────────────────────────────────────────────────
121
-
122
- it('registers all 30 ops', () => {
123
- expect(ops.size).toBe(30);
124
- });
125
-
126
- it('includes all expected op names', () => {
127
- const expected = [
128
- 'record_feedback',
129
- 'brain_feedback',
130
- 'brain_feedback_stats',
131
- 'rebuild_vocabulary',
132
- 'brain_stats',
133
- 'brain_decay_report',
134
- 'llm_status',
135
- 'brain_session_context',
136
- 'brain_strengths',
137
- 'brain_global_patterns',
138
- 'brain_recommend',
139
- 'brain_build_intelligence',
140
- 'brain_export',
141
- 'brain_import',
142
- 'brain_extract_knowledge',
143
- 'brain_archive_sessions',
144
- 'brain_promote_proposals',
145
- 'brain_lifecycle',
146
- 'session_list',
147
- 'session_get',
148
- 'session_quality',
149
- 'session_replay',
150
- 'brain_reset_extracted',
151
- 'radar_analyze',
152
- 'radar_candidates',
153
- 'radar_approve',
154
- 'radar_dismiss',
155
- 'radar_flush',
156
- 'radar_stats',
157
- 'synthesize',
158
- ];
159
- for (const name of expected) {
160
- expect(ops.has(name), `missing op: ${name}`).toBe(true);
161
- }
162
- });
163
-
164
- // ─── Auth levels ─────────────────────────────────────────────────
165
-
166
- it('has correct auth levels for read ops', () => {
167
- const readOps = [
168
- 'brain_feedback_stats',
169
- 'brain_stats',
170
- 'brain_decay_report',
171
- 'llm_status',
172
- 'brain_session_context',
173
- 'brain_strengths',
174
- 'brain_global_patterns',
175
- 'brain_recommend',
176
- 'brain_export',
177
- 'session_list',
178
- 'session_get',
179
- 'session_quality',
180
- 'session_replay',
181
- 'radar_candidates',
182
- 'radar_stats',
183
- 'synthesize',
184
- ];
185
- for (const name of readOps) {
186
- expect(ops.get(name)!.auth, `${name} should be read`).toBe('read');
187
- }
188
- });
189
-
190
- it('has correct auth levels for write ops', () => {
191
- const writeOps = [
192
- 'record_feedback',
193
- 'brain_feedback',
194
- 'rebuild_vocabulary',
195
- 'brain_build_intelligence',
196
- 'brain_import',
197
- 'brain_extract_knowledge',
198
- 'brain_archive_sessions',
199
- 'brain_promote_proposals',
200
- 'brain_lifecycle',
201
- 'brain_reset_extracted',
202
- 'radar_analyze',
203
- 'radar_approve',
204
- 'radar_dismiss',
205
- 'radar_flush',
206
- ];
207
- for (const name of writeOps) {
208
- expect(ops.get(name)!.auth, `${name} should be write`).toBe('write');
209
- }
210
- });
211
-
212
120
  // ─── record_feedback ───────────────────────────────────────────────
213
121
 
214
122
  describe('record_feedback', () => {
@@ -290,13 +198,14 @@ describe('brain-facade', () => {
290
198
  });
291
199
 
292
200
  it('accepts all 4 action types', async () => {
293
- for (const action of ['accepted', 'dismissed', 'modified', 'failed']) {
294
- const result = await executeOp(ops, 'brain_feedback', {
295
- query: 'q',
296
- entryId: 'e',
297
- action,
298
- });
299
- expect(result.success, `action ${action} should succeed`).toBe(true);
201
+ const actions = ['accepted', 'dismissed', 'modified', 'failed'];
202
+ const results = await Promise.all(
203
+ actions.map((action) =>
204
+ executeOp(ops, 'brain_feedback', { query: 'q', entryId: 'e', action }),
205
+ ),
206
+ );
207
+ for (const [i, result] of results.entries()) {
208
+ expect(result.success, `action ${actions[i]} should succeed`).toBe(true);
300
209
  }
301
210
  });
302
211
  });
@@ -513,18 +513,35 @@ export function createBrainFacadeOps(runtime: AgentRuntime): OpDefinition[] {
513
513
  'then uses LLM to produce a brief, outline, talking points, or post draft. ' +
514
514
  'Includes source attribution, coverage score, and knowledge gap detection.',
515
515
  auth: 'read',
516
- schema: z.object({
517
- query: z.string().describe('Topic to synthesize knowledge about'),
518
- format: z
519
- .enum(['brief', 'outline', 'talking-points', 'post-draft'])
520
- .describe('Output format'),
521
- maxEntries: z.number().optional().default(10).describe('Max vault entries to consult'),
522
- audience: z
523
- .enum(['technical', 'executive', 'general'])
524
- .optional()
525
- .default('general')
526
- .describe('Target audience for tone and language'),
527
- }),
516
+ schema: z.preprocess(
517
+ (val) => {
518
+ if (val !== null && typeof val === 'object' && !Array.isArray(val)) {
519
+ const obj = val as Record<string, unknown>;
520
+ // Accept "topic" as alias for "query"
521
+ if (obj.topic !== undefined && obj.query === undefined) {
522
+ return { ...obj, query: obj.topic };
523
+ }
524
+ }
525
+ return val;
526
+ },
527
+ z.object({
528
+ query: z.string().describe('Topic to synthesize knowledge about (alias: topic)'),
529
+ topic: z.string().optional().describe('Alias for query'),
530
+ format: z
531
+ .enum(['brief', 'outline', 'talking-points', 'post-draft'])
532
+ .optional()
533
+ .default('brief')
534
+ .describe(
535
+ 'Output format: brief | outline | talking-points | post-draft (default: "brief")',
536
+ ),
537
+ maxEntries: z.number().optional().default(10).describe('Max vault entries to consult'),
538
+ audience: z
539
+ .enum(['technical', 'executive', 'general'])
540
+ .optional()
541
+ .default('general')
542
+ .describe('Target audience for tone and language'),
543
+ }),
544
+ ),
528
545
  handler: async (params) => {
529
546
  return knowledgeSynthesizer.synthesize(params.query as string, {
530
547
  format: params.format as 'brief' | 'outline' | 'talking-points' | 'post-draft',
@@ -1,6 +1,5 @@
1
1
  /**
2
2
  * Colocated contract tests for branching-facade.ts.
3
- * Verifies the facade wrapper delegates to branching-ops.
4
3
  */
5
4
 
6
5
  import { describe, it, expect, vi } from 'vitest';
@@ -21,23 +20,37 @@ function makeRuntime(): AgentRuntime {
21
20
  }
22
21
 
23
22
  describe('branching-facade', () => {
24
- it('returns all 5 branching ops', () => {
25
- const ops = createBranchingFacadeOps(makeRuntime());
26
- expect(ops).toHaveLength(5);
27
- const names = ops.map((o) => o.name);
28
- expect(names).toContain('vault_branch');
29
- expect(names).toContain('vault_branch_add');
30
- expect(names).toContain('vault_branch_list');
31
- expect(names).toContain('vault_merge_branch');
32
- expect(names).toContain('vault_delete_branch');
23
+ describe('vault_branch', () => {
24
+ it('creates branch and returns created: true', async () => {
25
+ const runtime = makeRuntime();
26
+ const ops = createBranchingFacadeOps(runtime);
27
+ const op = ops.find((o) => o.name === 'vault_branch')!;
28
+ const result = (await op.handler({ name: 'feature-x' })) as {
29
+ created: boolean;
30
+ name: string;
31
+ };
32
+ expect(result.created).toBe(true);
33
+ expect(result.name).toBe('feature-x');
34
+ });
33
35
  });
34
36
 
35
- it('every op has name, handler, and auth', () => {
36
- const ops = createBranchingFacadeOps(makeRuntime());
37
- for (const op of ops) {
38
- expect(typeof op.name).toBe('string');
39
- expect(typeof op.handler).toBe('function');
40
- expect(typeof op.auth).toBe('string');
41
- }
37
+ describe('vault_branch_list', () => {
38
+ it('returns empty list when no branches exist', async () => {
39
+ const runtime = makeRuntime();
40
+ const ops = createBranchingFacadeOps(runtime);
41
+ const op = ops.find((o) => o.name === 'vault_branch_list')!;
42
+ const result = (await op.handler({})) as { branches: unknown[] };
43
+ expect(result.branches).toEqual([]);
44
+ });
45
+ });
46
+
47
+ describe('vault_delete_branch', () => {
48
+ it('returns deleted: true on success', async () => {
49
+ const runtime = makeRuntime();
50
+ const ops = createBranchingFacadeOps(runtime);
51
+ const op = ops.find((o) => o.name === 'vault_delete_branch')!;
52
+ const result = (await op.handler({ name: 'feature-x' })) as { deleted: boolean };
53
+ expect(result.deleted).toBe(true);
54
+ });
42
55
  });
43
56
  });
@@ -120,100 +120,9 @@ vi.mock('../../chat/output-compressor.js', () => ({
120
120
  describe('createChatFacadeOps', () => {
121
121
  const mockRuntime = {} as AgentRuntime;
122
122
 
123
- it('returns all 41 ops (6 session + 17 transport + 18 service)', () => {
124
- const ops = createChatFacadeOps(mockRuntime);
125
- expect(ops.length).toBe(41);
126
- });
127
-
128
- it('session ops come first', () => {
129
- const ops = createChatFacadeOps(mockRuntime);
130
- expect(ops[0].name).toBe('chat_session_init');
131
- expect(ops[5].name).toBe('chat_session_list');
132
- });
133
-
134
- it('transport ops follow session ops', () => {
135
- const ops = createChatFacadeOps(mockRuntime);
136
- expect(ops[6].name).toBe('chat_chunk_response');
137
- });
138
-
139
- it('service ops follow transport ops', () => {
140
- const ops = createChatFacadeOps(mockRuntime);
141
- // 6 session + 17 transport = index 23 is first service op
142
- expect(ops[23].name).toBe('chat_cancel_create');
143
- });
144
-
145
123
  it('all op names are unique', () => {
146
124
  const ops = createChatFacadeOps(mockRuntime);
147
125
  const names = ops.map((o) => o.name);
148
126
  expect(new Set(names).size).toBe(names.length);
149
127
  });
150
-
151
- it('all ops have valid auth levels', () => {
152
- const ops = createChatFacadeOps(mockRuntime);
153
- for (const op of ops) {
154
- expect(['read', 'write', 'admin']).toContain(op.auth);
155
- }
156
- });
157
-
158
- it('all ops have async handlers', () => {
159
- const ops = createChatFacadeOps(mockRuntime);
160
- for (const op of ops) {
161
- expect(typeof op.handler).toBe('function');
162
- }
163
- });
164
-
165
- it('contains all expected op names', () => {
166
- const ops = createChatFacadeOps(mockRuntime);
167
- const names = new Set(ops.map((o) => o.name));
168
- const expectedOps = [
169
- // Session ops (6)
170
- 'chat_session_init',
171
- 'chat_session_get',
172
- 'chat_session_append',
173
- 'chat_session_clear',
174
- 'chat_session_delete',
175
- 'chat_session_list',
176
- // Transport ops (17)
177
- 'chat_chunk_response',
178
- 'chat_auth_init',
179
- 'chat_auth_check',
180
- 'chat_auth_authenticate',
181
- 'chat_auth_revoke',
182
- 'chat_auth_status',
183
- 'chat_bridge_init',
184
- 'chat_bridge_register',
185
- 'chat_bridge_list',
186
- 'chat_bridge_execute',
187
- 'chat_compress_output',
188
- 'chat_voice_transcribe',
189
- 'chat_voice_synthesize',
190
- 'chat_queue_init',
191
- 'chat_queue_inbox',
192
- 'chat_queue_reply',
193
- 'chat_queue_drain',
194
- // Service ops (18)
195
- 'chat_cancel_create',
196
- 'chat_cancel_stop',
197
- 'chat_cancel_status',
198
- 'chat_update_init',
199
- 'chat_update_request',
200
- 'chat_update_confirm',
201
- 'chat_file_detect_intent',
202
- 'chat_file_build_content',
203
- 'chat_file_cleanup',
204
- 'chat_notify_init',
205
- 'chat_notify_start',
206
- 'chat_notify_stop',
207
- 'chat_notify_poll',
208
- 'chat_notify_status',
209
- 'chat_browser_init',
210
- 'chat_browser_acquire',
211
- 'chat_browser_release',
212
- 'chat_browser_status',
213
- ];
214
- for (const name of expectedOps) {
215
- expect(names.has(name)).toBe(true);
216
- }
217
- expect(names.size).toBe(expectedOps.length);
218
- });
219
128
  });