@soleri/core 2.1.0 → 2.4.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 (207) hide show
  1. package/dist/brain/brain.d.ts +3 -1
  2. package/dist/brain/brain.d.ts.map +1 -1
  3. package/dist/brain/brain.js +60 -4
  4. package/dist/brain/brain.js.map +1 -1
  5. package/dist/brain/intelligence.d.ts +36 -1
  6. package/dist/brain/intelligence.d.ts.map +1 -1
  7. package/dist/brain/intelligence.js +119 -14
  8. package/dist/brain/intelligence.js.map +1 -1
  9. package/dist/brain/types.d.ts +32 -0
  10. package/dist/brain/types.d.ts.map +1 -1
  11. package/dist/control/identity-manager.d.ts +22 -0
  12. package/dist/control/identity-manager.d.ts.map +1 -0
  13. package/dist/control/identity-manager.js +233 -0
  14. package/dist/control/identity-manager.js.map +1 -0
  15. package/dist/control/intent-router.d.ts +32 -0
  16. package/dist/control/intent-router.d.ts.map +1 -0
  17. package/dist/control/intent-router.js +242 -0
  18. package/dist/control/intent-router.js.map +1 -0
  19. package/dist/control/types.d.ts +68 -0
  20. package/dist/control/types.d.ts.map +1 -0
  21. package/dist/control/types.js +9 -0
  22. package/dist/control/types.js.map +1 -0
  23. package/dist/curator/curator.d.ts +29 -0
  24. package/dist/curator/curator.d.ts.map +1 -1
  25. package/dist/curator/curator.js +135 -0
  26. package/dist/curator/curator.js.map +1 -1
  27. package/dist/facades/types.d.ts +1 -1
  28. package/dist/governance/governance.d.ts +42 -0
  29. package/dist/governance/governance.d.ts.map +1 -0
  30. package/dist/governance/governance.js +488 -0
  31. package/dist/governance/governance.js.map +1 -0
  32. package/dist/governance/index.d.ts +3 -0
  33. package/dist/governance/index.d.ts.map +1 -0
  34. package/dist/governance/index.js +2 -0
  35. package/dist/governance/index.js.map +1 -0
  36. package/dist/governance/types.d.ts +102 -0
  37. package/dist/governance/types.d.ts.map +1 -0
  38. package/dist/governance/types.js +3 -0
  39. package/dist/governance/types.js.map +1 -0
  40. package/dist/index.d.ts +32 -3
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +29 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/logging/logger.d.ts +37 -0
  45. package/dist/logging/logger.d.ts.map +1 -0
  46. package/dist/logging/logger.js +145 -0
  47. package/dist/logging/logger.js.map +1 -0
  48. package/dist/logging/types.d.ts +19 -0
  49. package/dist/logging/types.d.ts.map +1 -0
  50. package/dist/logging/types.js +2 -0
  51. package/dist/logging/types.js.map +1 -0
  52. package/dist/loop/loop-manager.d.ts +49 -0
  53. package/dist/loop/loop-manager.d.ts.map +1 -0
  54. package/dist/loop/loop-manager.js +105 -0
  55. package/dist/loop/loop-manager.js.map +1 -0
  56. package/dist/loop/types.d.ts +35 -0
  57. package/dist/loop/types.d.ts.map +1 -0
  58. package/dist/loop/types.js +8 -0
  59. package/dist/loop/types.js.map +1 -0
  60. package/dist/planning/gap-analysis.d.ts +29 -0
  61. package/dist/planning/gap-analysis.d.ts.map +1 -0
  62. package/dist/planning/gap-analysis.js +265 -0
  63. package/dist/planning/gap-analysis.js.map +1 -0
  64. package/dist/planning/gap-types.d.ts +29 -0
  65. package/dist/planning/gap-types.d.ts.map +1 -0
  66. package/dist/planning/gap-types.js +28 -0
  67. package/dist/planning/gap-types.js.map +1 -0
  68. package/dist/planning/planner.d.ts +150 -1
  69. package/dist/planning/planner.d.ts.map +1 -1
  70. package/dist/planning/planner.js +365 -2
  71. package/dist/planning/planner.js.map +1 -1
  72. package/dist/project/project-registry.d.ts +79 -0
  73. package/dist/project/project-registry.d.ts.map +1 -0
  74. package/dist/project/project-registry.js +276 -0
  75. package/dist/project/project-registry.js.map +1 -0
  76. package/dist/project/types.d.ts +28 -0
  77. package/dist/project/types.d.ts.map +1 -0
  78. package/dist/project/types.js +5 -0
  79. package/dist/project/types.js.map +1 -0
  80. package/dist/runtime/admin-extra-ops.d.ts +13 -0
  81. package/dist/runtime/admin-extra-ops.d.ts.map +1 -0
  82. package/dist/runtime/admin-extra-ops.js +284 -0
  83. package/dist/runtime/admin-extra-ops.js.map +1 -0
  84. package/dist/runtime/admin-ops.d.ts +15 -0
  85. package/dist/runtime/admin-ops.d.ts.map +1 -0
  86. package/dist/runtime/admin-ops.js +322 -0
  87. package/dist/runtime/admin-ops.js.map +1 -0
  88. package/dist/runtime/capture-ops.d.ts +15 -0
  89. package/dist/runtime/capture-ops.d.ts.map +1 -0
  90. package/dist/runtime/capture-ops.js +345 -0
  91. package/dist/runtime/capture-ops.js.map +1 -0
  92. package/dist/runtime/core-ops.d.ts +7 -3
  93. package/dist/runtime/core-ops.d.ts.map +1 -1
  94. package/dist/runtime/core-ops.js +474 -8
  95. package/dist/runtime/core-ops.js.map +1 -1
  96. package/dist/runtime/curator-extra-ops.d.ts +9 -0
  97. package/dist/runtime/curator-extra-ops.d.ts.map +1 -0
  98. package/dist/runtime/curator-extra-ops.js +59 -0
  99. package/dist/runtime/curator-extra-ops.js.map +1 -0
  100. package/dist/runtime/domain-ops.d.ts.map +1 -1
  101. package/dist/runtime/domain-ops.js +59 -13
  102. package/dist/runtime/domain-ops.js.map +1 -1
  103. package/dist/runtime/grading-ops.d.ts +14 -0
  104. package/dist/runtime/grading-ops.d.ts.map +1 -0
  105. package/dist/runtime/grading-ops.js +105 -0
  106. package/dist/runtime/grading-ops.js.map +1 -0
  107. package/dist/runtime/loop-ops.d.ts +13 -0
  108. package/dist/runtime/loop-ops.d.ts.map +1 -0
  109. package/dist/runtime/loop-ops.js +179 -0
  110. package/dist/runtime/loop-ops.js.map +1 -0
  111. package/dist/runtime/memory-cross-project-ops.d.ts +12 -0
  112. package/dist/runtime/memory-cross-project-ops.d.ts.map +1 -0
  113. package/dist/runtime/memory-cross-project-ops.js +165 -0
  114. package/dist/runtime/memory-cross-project-ops.js.map +1 -0
  115. package/dist/runtime/memory-extra-ops.d.ts +13 -0
  116. package/dist/runtime/memory-extra-ops.d.ts.map +1 -0
  117. package/dist/runtime/memory-extra-ops.js +173 -0
  118. package/dist/runtime/memory-extra-ops.js.map +1 -0
  119. package/dist/runtime/orchestrate-ops.d.ts +17 -0
  120. package/dist/runtime/orchestrate-ops.d.ts.map +1 -0
  121. package/dist/runtime/orchestrate-ops.js +240 -0
  122. package/dist/runtime/orchestrate-ops.js.map +1 -0
  123. package/dist/runtime/planning-extra-ops.d.ts +17 -0
  124. package/dist/runtime/planning-extra-ops.d.ts.map +1 -0
  125. package/dist/runtime/planning-extra-ops.js +300 -0
  126. package/dist/runtime/planning-extra-ops.js.map +1 -0
  127. package/dist/runtime/project-ops.d.ts +15 -0
  128. package/dist/runtime/project-ops.d.ts.map +1 -0
  129. package/dist/runtime/project-ops.js +181 -0
  130. package/dist/runtime/project-ops.js.map +1 -0
  131. package/dist/runtime/runtime.d.ts.map +1 -1
  132. package/dist/runtime/runtime.js +44 -1
  133. package/dist/runtime/runtime.js.map +1 -1
  134. package/dist/runtime/types.d.ts +21 -0
  135. package/dist/runtime/types.d.ts.map +1 -1
  136. package/dist/runtime/vault-extra-ops.d.ts +9 -0
  137. package/dist/runtime/vault-extra-ops.d.ts.map +1 -0
  138. package/dist/runtime/vault-extra-ops.js +195 -0
  139. package/dist/runtime/vault-extra-ops.js.map +1 -0
  140. package/dist/telemetry/telemetry.d.ts +48 -0
  141. package/dist/telemetry/telemetry.d.ts.map +1 -0
  142. package/dist/telemetry/telemetry.js +87 -0
  143. package/dist/telemetry/telemetry.js.map +1 -0
  144. package/dist/vault/vault.d.ts +94 -0
  145. package/dist/vault/vault.d.ts.map +1 -1
  146. package/dist/vault/vault.js +340 -1
  147. package/dist/vault/vault.js.map +1 -1
  148. package/package.json +1 -1
  149. package/src/__tests__/admin-extra-ops.test.ts +420 -0
  150. package/src/__tests__/admin-ops.test.ts +271 -0
  151. package/src/__tests__/brain-intelligence.test.ts +205 -0
  152. package/src/__tests__/brain.test.ts +131 -0
  153. package/src/__tests__/capture-ops.test.ts +509 -0
  154. package/src/__tests__/core-ops.test.ts +266 -2
  155. package/src/__tests__/curator-extra-ops.test.ts +359 -0
  156. package/src/__tests__/domain-ops.test.ts +66 -0
  157. package/src/__tests__/governance.test.ts +522 -0
  158. package/src/__tests__/grading-ops.test.ts +340 -0
  159. package/src/__tests__/identity-manager.test.ts +243 -0
  160. package/src/__tests__/intent-router.test.ts +222 -0
  161. package/src/__tests__/logger.test.ts +200 -0
  162. package/src/__tests__/loop-ops.test.ts +398 -0
  163. package/src/__tests__/memory-cross-project-ops.test.ts +246 -0
  164. package/src/__tests__/memory-extra-ops.test.ts +352 -0
  165. package/src/__tests__/orchestrate-ops.test.ts +284 -0
  166. package/src/__tests__/planner.test.ts +331 -0
  167. package/src/__tests__/planning-extra-ops.test.ts +548 -0
  168. package/src/__tests__/project-ops.test.ts +367 -0
  169. package/src/__tests__/vault-extra-ops.test.ts +407 -0
  170. package/src/brain/brain.ts +114 -7
  171. package/src/brain/intelligence.ts +179 -10
  172. package/src/brain/types.ts +38 -0
  173. package/src/control/identity-manager.ts +354 -0
  174. package/src/control/intent-router.ts +326 -0
  175. package/src/control/types.ts +102 -0
  176. package/src/curator/curator.ts +213 -0
  177. package/src/governance/governance.ts +698 -0
  178. package/src/governance/index.ts +18 -0
  179. package/src/governance/types.ts +111 -0
  180. package/src/index.ts +102 -2
  181. package/src/logging/logger.ts +154 -0
  182. package/src/logging/types.ts +21 -0
  183. package/src/loop/loop-manager.ts +130 -0
  184. package/src/loop/types.ts +44 -0
  185. package/src/planning/gap-analysis.ts +506 -0
  186. package/src/planning/gap-types.ts +58 -0
  187. package/src/planning/planner.ts +478 -2
  188. package/src/project/project-registry.ts +358 -0
  189. package/src/project/types.ts +31 -0
  190. package/src/runtime/admin-extra-ops.ts +307 -0
  191. package/src/runtime/admin-ops.ts +329 -0
  192. package/src/runtime/capture-ops.ts +385 -0
  193. package/src/runtime/core-ops.ts +535 -7
  194. package/src/runtime/curator-extra-ops.ts +71 -0
  195. package/src/runtime/domain-ops.ts +65 -13
  196. package/src/runtime/grading-ops.ts +121 -0
  197. package/src/runtime/loop-ops.ts +194 -0
  198. package/src/runtime/memory-cross-project-ops.ts +192 -0
  199. package/src/runtime/memory-extra-ops.ts +186 -0
  200. package/src/runtime/orchestrate-ops.ts +272 -0
  201. package/src/runtime/planning-extra-ops.ts +327 -0
  202. package/src/runtime/project-ops.ts +196 -0
  203. package/src/runtime/runtime.ts +49 -1
  204. package/src/runtime/types.ts +21 -0
  205. package/src/runtime/vault-extra-ops.ts +225 -0
  206. package/src/telemetry/telemetry.ts +118 -0
  207. package/src/vault/vault.ts +412 -1
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Extended memory operations — 8 ops for advanced memory management.
3
+ *
4
+ * These complement the 4 base memory ops in core-ops.ts:
5
+ * memory_search, memory_capture, memory_list, session_capture
6
+ *
7
+ * New ops: memory_delete, memory_stats, memory_export, memory_import,
8
+ * memory_prune, memory_deduplicate, memory_topics, memory_by_project
9
+ */
10
+
11
+ import { z } from 'zod';
12
+ import type { OpDefinition } from '../facades/types.js';
13
+ import type { AgentRuntime } from './types.js';
14
+
15
+ export function createMemoryExtraOps(runtime: AgentRuntime): OpDefinition[] {
16
+ const { vault } = runtime;
17
+
18
+ return [
19
+ {
20
+ name: 'memory_delete',
21
+ description: 'Delete a memory by ID. Returns whether the deletion was successful.',
22
+ auth: 'write',
23
+ schema: z.object({
24
+ memoryId: z.string().describe('The memory ID to delete'),
25
+ }),
26
+ handler: async (params) => {
27
+ const memoryId = params.memoryId as string;
28
+ const existing = vault.getMemory(memoryId);
29
+ if (!existing) {
30
+ return { deleted: false, error: `Memory "${memoryId}" not found.` };
31
+ }
32
+ const deleted = vault.deleteMemory(memoryId);
33
+ return { deleted, memoryId };
34
+ },
35
+ },
36
+ {
37
+ name: 'memory_stats',
38
+ description:
39
+ 'Detailed memory statistics — counts by type, project, date range, plus oldest/newest timestamps and archived count.',
40
+ auth: 'read',
41
+ schema: z.object({
42
+ projectPath: z.string().optional().describe('Filter stats to a specific project'),
43
+ fromDate: z
44
+ .number()
45
+ .optional()
46
+ .describe('Unix timestamp — only include memories created after this date'),
47
+ toDate: z
48
+ .number()
49
+ .optional()
50
+ .describe('Unix timestamp — only include memories created before this date'),
51
+ }),
52
+ handler: async (params) => {
53
+ return vault.memoryStatsDetailed({
54
+ projectPath: params.projectPath as string | undefined,
55
+ fromDate: params.fromDate as number | undefined,
56
+ toDate: params.toDate as number | undefined,
57
+ });
58
+ },
59
+ },
60
+ {
61
+ name: 'memory_export',
62
+ description:
63
+ 'Export memories as a JSON array. Optionally filter by project or type. Useful for backup and migration.',
64
+ auth: 'read',
65
+ schema: z.object({
66
+ projectPath: z.string().optional().describe('Filter to a specific project'),
67
+ type: z.enum(['session', 'lesson', 'preference']).optional().describe('Filter by memory type'),
68
+ includeArchived: z
69
+ .boolean()
70
+ .optional()
71
+ .default(false)
72
+ .describe('Whether to include archived memories'),
73
+ }),
74
+ handler: async (params) => {
75
+ const memories = vault.exportMemories({
76
+ projectPath: params.projectPath as string | undefined,
77
+ type: params.type as string | undefined,
78
+ includeArchived: (params.includeArchived as boolean | undefined) ?? false,
79
+ });
80
+ return { exported: true, count: memories.length, memories };
81
+ },
82
+ },
83
+ {
84
+ name: 'memory_import',
85
+ description:
86
+ 'Import memories from a JSON array. Duplicates (same ID) are skipped. Returns imported and skipped counts.',
87
+ auth: 'write',
88
+ schema: z.object({
89
+ memories: z
90
+ .array(
91
+ z.object({
92
+ id: z.string(),
93
+ projectPath: z.string(),
94
+ type: z.enum(['session', 'lesson', 'preference']),
95
+ context: z.string(),
96
+ summary: z.string(),
97
+ topics: z.array(z.string()).optional().default([]),
98
+ filesModified: z.array(z.string()).optional().default([]),
99
+ toolsUsed: z.array(z.string()).optional().default([]),
100
+ createdAt: z.number(),
101
+ archivedAt: z.number().nullable().optional().default(null),
102
+ }),
103
+ )
104
+ .describe('Array of memory objects to import'),
105
+ }),
106
+ handler: async (params) => {
107
+ const memories = (params.memories as Array<Record<string, unknown>>).map((m) => ({
108
+ id: m.id as string,
109
+ projectPath: m.projectPath as string,
110
+ type: m.type as 'session' | 'lesson' | 'preference',
111
+ context: m.context as string,
112
+ summary: m.summary as string,
113
+ topics: (m.topics as string[]) ?? [],
114
+ filesModified: (m.filesModified as string[]) ?? [],
115
+ toolsUsed: (m.toolsUsed as string[]) ?? [],
116
+ createdAt: m.createdAt as number,
117
+ archivedAt: (m.archivedAt as number | null) ?? null,
118
+ }));
119
+ const result = vault.importMemories(memories);
120
+ return { ...result, total: memories.length };
121
+ },
122
+ },
123
+ {
124
+ name: 'memory_prune',
125
+ description:
126
+ 'Delete non-archived memories older than N days. Destructive — cannot be undone.',
127
+ auth: 'admin',
128
+ schema: z.object({
129
+ olderThanDays: z
130
+ .number()
131
+ .min(1)
132
+ .describe('Delete memories older than this many days'),
133
+ }),
134
+ handler: async (params) => {
135
+ const days = params.olderThanDays as number;
136
+ const result = vault.pruneMemories(days);
137
+ return { ...result, olderThanDays: days };
138
+ },
139
+ },
140
+ {
141
+ name: 'memory_deduplicate',
142
+ description:
143
+ 'Find and remove duplicate memories (same summary + project + type). Keeps the earliest entry in each duplicate group.',
144
+ auth: 'admin',
145
+ schema: z.object({}),
146
+ handler: async () => {
147
+ return vault.deduplicateMemories();
148
+ },
149
+ },
150
+ {
151
+ name: 'memory_topics',
152
+ description:
153
+ 'List all unique topics across memories, with occurrence counts. Sorted by frequency descending.',
154
+ auth: 'read',
155
+ schema: z.object({}),
156
+ handler: async () => {
157
+ const topics = vault.memoryTopics();
158
+ return { count: topics.length, topics };
159
+ },
160
+ },
161
+ {
162
+ name: 'memory_by_project',
163
+ description:
164
+ 'List memories grouped by project path. Each group includes the project path, count, and the memories themselves.',
165
+ auth: 'read',
166
+ schema: z.object({
167
+ includeMemories: z
168
+ .boolean()
169
+ .optional()
170
+ .default(true)
171
+ .describe('Whether to include full memory objects or just counts'),
172
+ }),
173
+ handler: async (params) => {
174
+ const includeMemories = (params.includeMemories as boolean | undefined) ?? true;
175
+ const groups = vault.memoriesByProject();
176
+ if (!includeMemories) {
177
+ return {
178
+ count: groups.length,
179
+ projects: groups.map((g) => ({ project: g.project, count: g.count })),
180
+ };
181
+ }
182
+ return { count: groups.length, projects: groups };
183
+ },
184
+ },
185
+ ];
186
+ }
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Orchestration operations — compose planning + brain + vault into high-level workflows.
3
+ *
4
+ * These ops are convenience wrappers that sequence multiple module calls:
5
+ * - orchestrate_plan: brain-informed plan creation
6
+ * - orchestrate_execute: start plan + brain session together
7
+ * - orchestrate_complete: finish plan + brain session + extract knowledge
8
+ * - orchestrate_status: combined status across all modules
9
+ * - orchestrate_quick_capture: one-call knowledge capture without full planning
10
+ */
11
+
12
+ import { z } from 'zod';
13
+ import type { OpDefinition } from '../facades/types.js';
14
+ import type { AgentRuntime } from './types.js';
15
+
16
+ /**
17
+ * Create the 5 orchestration operations for an agent runtime.
18
+ */
19
+ export function createOrchestrateOps(runtime: AgentRuntime): OpDefinition[] {
20
+ const { planner, brainIntelligence, vault } = runtime;
21
+
22
+ return [
23
+ // ─── orchestrate_plan ─────────────────────────────────────────
24
+ {
25
+ name: 'orchestrate_plan',
26
+ description:
27
+ 'Create a brain-informed plan with recommendations from pattern strengths. ' +
28
+ 'Fetches relevant brain recommendations for the domain/task, then creates a plan ' +
29
+ 'with those recommendations injected as decisions.',
30
+ auth: 'write',
31
+ schema: z.object({
32
+ objective: z.string().describe('What the plan aims to achieve'),
33
+ scope: z.string().describe('Boundaries of the work'),
34
+ domain: z.string().optional().describe('Domain for brain recommendations (e.g. "component", "styling")'),
35
+ tasks: z
36
+ .array(z.object({ title: z.string(), description: z.string() }))
37
+ .optional()
38
+ .describe('Optional pre-defined tasks'),
39
+ }),
40
+ handler: async (params) => {
41
+ const objective = params.objective as string;
42
+ const scope = params.scope as string;
43
+ const domain = params.domain as string | undefined;
44
+ const tasks = (params.tasks as Array<{ title: string; description: string }>) ?? [];
45
+
46
+ // Get brain recommendations — graceful degradation if no data
47
+ let recommendations: Array<{ pattern: string; strength: number }> = [];
48
+ try {
49
+ const raw = brainIntelligence.recommend({
50
+ domain,
51
+ task: objective,
52
+ limit: 5,
53
+ });
54
+ recommendations = raw.map((r) => ({
55
+ pattern: r.pattern,
56
+ strength: r.strength,
57
+ }));
58
+ } catch {
59
+ // Brain has no data yet — proceed without recommendations
60
+ }
61
+
62
+ // Build decisions from recommendations
63
+ const decisions = recommendations.map(
64
+ (r) => `Brain pattern: ${r.pattern} (strength: ${r.strength.toFixed(1)})`,
65
+ );
66
+
67
+ // Create plan with recommendations as context
68
+ const plan = planner.create({
69
+ objective,
70
+ scope,
71
+ decisions,
72
+ tasks,
73
+ });
74
+
75
+ return { plan, recommendations };
76
+ },
77
+ },
78
+
79
+ // ─── orchestrate_execute ──────────────────────────────────────
80
+ {
81
+ name: 'orchestrate_execute',
82
+ description:
83
+ 'Start plan execution and open a brain session to track the work. ' +
84
+ 'The plan must be in "approved" status. Returns both the updated plan and session ID.',
85
+ auth: 'write',
86
+ schema: z.object({
87
+ planId: z.string().describe('ID of the approved plan to start executing'),
88
+ domain: z.string().optional().describe('Domain for brain session tracking'),
89
+ context: z.string().optional().describe('Additional context for the brain session'),
90
+ }),
91
+ handler: async (params) => {
92
+ const planId = params.planId as string;
93
+ const domain = params.domain as string | undefined;
94
+ const context = params.context as string | undefined;
95
+
96
+ // Start plan execution
97
+ const plan = planner.startExecution(planId);
98
+
99
+ // Start brain session linked to this plan
100
+ const session = brainIntelligence.lifecycle({
101
+ action: 'start',
102
+ domain,
103
+ context,
104
+ planId,
105
+ });
106
+
107
+ return { plan, session };
108
+ },
109
+ },
110
+
111
+ // ─── orchestrate_complete ─────────────────────────────────────
112
+ {
113
+ name: 'orchestrate_complete',
114
+ description:
115
+ 'Complete plan execution, end brain session, and extract knowledge. ' +
116
+ 'Performs three steps: marks plan completed, ends the brain session with outcome, ' +
117
+ 'and runs knowledge extraction on the session.',
118
+ auth: 'write',
119
+ schema: z.object({
120
+ planId: z.string().describe('ID of the executing plan to complete'),
121
+ sessionId: z.string().describe('ID of the brain session to end'),
122
+ outcome: z
123
+ .enum(['completed', 'abandoned', 'partial'])
124
+ .optional()
125
+ .default('completed')
126
+ .describe('Plan outcome'),
127
+ toolsUsed: z.array(z.string()).optional().describe('Tools used during execution'),
128
+ filesModified: z.array(z.string()).optional().describe('Files modified during execution'),
129
+ }),
130
+ handler: async (params) => {
131
+ const planId = params.planId as string;
132
+ const sessionId = params.sessionId as string;
133
+ const outcome = (params.outcome as string) ?? 'completed';
134
+ const toolsUsed = (params.toolsUsed as string[]) ?? [];
135
+ const filesModified = (params.filesModified as string[]) ?? [];
136
+
137
+ // Complete the plan
138
+ const plan = planner.complete(planId);
139
+
140
+ // End brain session with outcome
141
+ const session = brainIntelligence.lifecycle({
142
+ action: 'end',
143
+ sessionId,
144
+ planId,
145
+ planOutcome: outcome,
146
+ toolsUsed,
147
+ filesModified,
148
+ });
149
+
150
+ // Extract knowledge from the session — graceful if nothing to extract
151
+ let extraction = null;
152
+ try {
153
+ extraction = brainIntelligence.extractKnowledge(sessionId);
154
+ } catch {
155
+ // Session may not have enough signal for extraction — that's OK
156
+ }
157
+
158
+ return { plan, session, extraction };
159
+ },
160
+ },
161
+
162
+ // ─── orchestrate_status ───────────────────────────────────────
163
+ {
164
+ name: 'orchestrate_status',
165
+ description:
166
+ 'Get combined orchestration status: active plans, brain session context, ' +
167
+ 'vault stats, and recent brain recommendations.',
168
+ auth: 'read',
169
+ schema: z.object({
170
+ domain: z.string().optional().describe('Filter recommendations by domain'),
171
+ sessionLimit: z.number().optional().describe('Number of recent sessions to include (default 5)'),
172
+ }),
173
+ handler: async (params) => {
174
+ const domain = params.domain as string | undefined;
175
+ const sessionLimit = (params.sessionLimit as number) ?? 5;
176
+
177
+ // Active plans
178
+ const activePlans = planner.getActive();
179
+
180
+ // Brain session context
181
+ const sessionContext = brainIntelligence.getSessionContext(sessionLimit);
182
+
183
+ // Vault stats
184
+ const vaultStats = vault.stats();
185
+
186
+ // Recent recommendations — graceful degradation
187
+ let recommendations: Array<{ pattern: string; strength: number }> = [];
188
+ try {
189
+ const raw = brainIntelligence.recommend({
190
+ domain,
191
+ limit: 5,
192
+ });
193
+ recommendations = raw.map((r) => ({
194
+ pattern: r.pattern,
195
+ strength: r.strength,
196
+ }));
197
+ } catch {
198
+ // No recommendations available
199
+ }
200
+
201
+ // Brain intelligence stats
202
+ const brainStats = brainIntelligence.getStats();
203
+
204
+ return {
205
+ activePlans,
206
+ sessionContext,
207
+ vaultStats,
208
+ recommendations,
209
+ brainStats,
210
+ };
211
+ },
212
+ },
213
+
214
+ // ─── orchestrate_quick_capture ────────────────────────────────
215
+ {
216
+ name: 'orchestrate_quick_capture',
217
+ description:
218
+ 'Capture knowledge from a completed task without full plan lifecycle. ' +
219
+ 'Creates a brain session, records the context, ends it, and extracts knowledge — all in one call.',
220
+ auth: 'write',
221
+ schema: z.object({
222
+ domain: z.string().describe('Knowledge domain (e.g. "component", "accessibility")'),
223
+ context: z.string().describe('What was done — summary of the task'),
224
+ toolsUsed: z.array(z.string()).optional().describe('Tools used during the task'),
225
+ filesModified: z.array(z.string()).optional().describe('Files modified during the task'),
226
+ outcome: z
227
+ .enum(['completed', 'abandoned', 'partial'])
228
+ .optional()
229
+ .default('completed')
230
+ .describe('Task outcome'),
231
+ }),
232
+ handler: async (params) => {
233
+ const domain = params.domain as string;
234
+ const context = params.context as string;
235
+ const toolsUsed = (params.toolsUsed as string[]) ?? [];
236
+ const filesModified = (params.filesModified as string[]) ?? [];
237
+ const outcome = (params.outcome as string) ?? 'completed';
238
+
239
+ // Start session
240
+ const startedSession = brainIntelligence.lifecycle({
241
+ action: 'start',
242
+ domain,
243
+ context,
244
+ toolsUsed,
245
+ filesModified,
246
+ });
247
+
248
+ // End session immediately with outcome
249
+ const endedSession = brainIntelligence.lifecycle({
250
+ action: 'end',
251
+ sessionId: startedSession.id,
252
+ toolsUsed,
253
+ filesModified,
254
+ planOutcome: outcome,
255
+ });
256
+
257
+ // Extract knowledge — graceful if nothing to extract
258
+ let extraction = null;
259
+ try {
260
+ extraction = brainIntelligence.extractKnowledge(startedSession.id);
261
+ } catch {
262
+ // Not enough signal — that's fine
263
+ }
264
+
265
+ return {
266
+ session: endedSession,
267
+ extraction,
268
+ };
269
+ },
270
+ },
271
+ ];
272
+ }