@soleri/forge 5.14.0 → 5.14.2

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 (105) hide show
  1. package/dist/index.js +0 -0
  2. package/dist/lib.d.ts +2 -0
  3. package/dist/lib.js +2 -0
  4. package/dist/lib.js.map +1 -1
  5. package/dist/skills/brain-debrief.md +47 -19
  6. package/dist/skills/brainstorming.md +19 -9
  7. package/dist/skills/code-patrol.md +21 -19
  8. package/dist/skills/context-resume.md +14 -11
  9. package/dist/skills/executing-plans.md +30 -15
  10. package/dist/skills/fix-and-learn.md +17 -14
  11. package/dist/skills/health-check.md +29 -23
  12. package/dist/skills/knowledge-harvest.md +27 -20
  13. package/dist/skills/onboard-me.md +16 -15
  14. package/dist/skills/retrospective.md +34 -18
  15. package/dist/skills/second-opinion.md +16 -9
  16. package/dist/skills/systematic-debugging.md +40 -29
  17. package/dist/skills/test-driven-development.md +45 -30
  18. package/dist/skills/vault-capture.md +31 -15
  19. package/dist/skills/vault-navigator.md +24 -13
  20. package/dist/skills/verification-before-completion.md +38 -26
  21. package/dist/skills/writing-plans.md +21 -13
  22. package/dist/templates/claude-md-template.d.ts +9 -8
  23. package/dist/templates/claude-md-template.js +29 -11
  24. package/dist/templates/claude-md-template.js.map +1 -1
  25. package/dist/templates/inject-claude-md.js +65 -25
  26. package/dist/templates/inject-claude-md.js.map +1 -1
  27. package/dist/templates/shared-rules.d.ts +10 -6
  28. package/dist/templates/shared-rules.js +242 -199
  29. package/dist/templates/shared-rules.js.map +1 -1
  30. package/dist/templates/test-facades.js +6 -4
  31. package/dist/templates/test-facades.js.map +1 -1
  32. package/package.json +1 -1
  33. package/src/lib.ts +2 -0
  34. package/src/templates/claude-md-template.ts +30 -12
  35. package/src/templates/inject-claude-md.ts +65 -25
  36. package/src/templates/shared-rules.ts +259 -210
  37. package/src/templates/test-facades.ts +6 -4
  38. package/dist/skills/skills/brain-debrief.md +0 -214
  39. package/dist/skills/skills/brainstorming.md +0 -180
  40. package/dist/skills/skills/code-patrol.md +0 -178
  41. package/dist/skills/skills/context-resume.md +0 -146
  42. package/dist/skills/skills/executing-plans.md +0 -216
  43. package/dist/skills/skills/fix-and-learn.md +0 -167
  44. package/dist/skills/skills/health-check.md +0 -231
  45. package/dist/skills/skills/knowledge-harvest.md +0 -185
  46. package/dist/skills/skills/onboard-me.md +0 -198
  47. package/dist/skills/skills/retrospective.md +0 -205
  48. package/dist/skills/skills/second-opinion.md +0 -149
  49. package/dist/skills/skills/systematic-debugging.md +0 -241
  50. package/dist/skills/skills/test-driven-development.md +0 -281
  51. package/dist/skills/skills/vault-capture.md +0 -170
  52. package/dist/skills/skills/vault-navigator.md +0 -140
  53. package/dist/skills/skills/verification-before-completion.md +0 -182
  54. package/dist/skills/skills/writing-plans.md +0 -215
  55. package/dist/templates/brain.d.ts +0 -6
  56. package/dist/templates/brain.js +0 -478
  57. package/dist/templates/brain.js.map +0 -1
  58. package/dist/templates/core-facade.d.ts +0 -6
  59. package/dist/templates/core-facade.js +0 -564
  60. package/dist/templates/core-facade.js.map +0 -1
  61. package/dist/templates/facade-factory.d.ts +0 -1
  62. package/dist/templates/facade-factory.js +0 -63
  63. package/dist/templates/facade-factory.js.map +0 -1
  64. package/dist/templates/facade-types.d.ts +0 -1
  65. package/dist/templates/facade-types.js +0 -46
  66. package/dist/templates/facade-types.js.map +0 -1
  67. package/dist/templates/intelligence-loader.d.ts +0 -1
  68. package/dist/templates/intelligence-loader.js +0 -43
  69. package/dist/templates/intelligence-loader.js.map +0 -1
  70. package/dist/templates/intelligence-types.d.ts +0 -1
  71. package/dist/templates/intelligence-types.js +0 -24
  72. package/dist/templates/intelligence-types.js.map +0 -1
  73. package/dist/templates/llm-client.d.ts +0 -7
  74. package/dist/templates/llm-client.js +0 -300
  75. package/dist/templates/llm-client.js.map +0 -1
  76. package/dist/templates/llm-key-pool.d.ts +0 -7
  77. package/dist/templates/llm-key-pool.js +0 -211
  78. package/dist/templates/llm-key-pool.js.map +0 -1
  79. package/dist/templates/llm-types.d.ts +0 -5
  80. package/dist/templates/llm-types.js +0 -161
  81. package/dist/templates/llm-types.js.map +0 -1
  82. package/dist/templates/llm-utils.d.ts +0 -5
  83. package/dist/templates/llm-utils.js +0 -260
  84. package/dist/templates/llm-utils.js.map +0 -1
  85. package/dist/templates/planner.d.ts +0 -5
  86. package/dist/templates/planner.js +0 -150
  87. package/dist/templates/planner.js.map +0 -1
  88. package/dist/templates/test-brain.d.ts +0 -6
  89. package/dist/templates/test-brain.js +0 -474
  90. package/dist/templates/test-brain.js.map +0 -1
  91. package/dist/templates/test-llm.d.ts +0 -7
  92. package/dist/templates/test-llm.js +0 -574
  93. package/dist/templates/test-llm.js.map +0 -1
  94. package/dist/templates/test-loader.d.ts +0 -5
  95. package/dist/templates/test-loader.js +0 -146
  96. package/dist/templates/test-loader.js.map +0 -1
  97. package/dist/templates/test-planner.d.ts +0 -5
  98. package/dist/templates/test-planner.js +0 -271
  99. package/dist/templates/test-planner.js.map +0 -1
  100. package/dist/templates/test-vault.d.ts +0 -5
  101. package/dist/templates/test-vault.js +0 -380
  102. package/dist/templates/test-vault.js.map +0 -1
  103. package/dist/templates/vault.d.ts +0 -5
  104. package/dist/templates/vault.js +0 -263
  105. package/dist/templates/vault.js.map +0 -1
@@ -1,564 +0,0 @@
1
- /**
2
- * Generate the core facade that every agent gets — vault stats, search all,
3
- * health, identity, plus activation system (activate, deactivate, inject_claude_md, setup).
4
- */
5
- export function generateCoreFacade(config) {
6
- return `import { z } from 'zod';
7
- import type { FacadeConfig, Vault, IntelligenceEntry, Planner, Brain, KeyPool, Curator } from '@soleri/core';
8
- import { PERSONA } from '../identity/persona.js';
9
- import { activateAgent, deactivateAgent } from '../activation/activate.js';
10
- import { injectClaudeMd, injectClaudeMdGlobal, hasAgentMarker } from '../activation/inject-claude-md.js';
11
- import type { LLMClient } from '../llm/llm-client.js';
12
-
13
- export function createCoreFacade(vault: Vault, planner: Planner, brain: Brain, llmClient?: LLMClient, openaiKeyPool?: KeyPool, anthropicKeyPool?: KeyPool, curator?: Curator): FacadeConfig {
14
- return {
15
- name: '${config.id}_core',
16
- description: 'Core operations — vault stats, cross-domain search, health check, identity, and activation system.',
17
- ops: [
18
- {
19
- name: 'search',
20
- description: 'Search across all knowledge domains. Results ranked by TF-IDF + severity + recency + tag overlap + domain match.',
21
- auth: 'read',
22
- schema: z.object({
23
- query: z.string(),
24
- domain: z.string().optional(),
25
- type: z.enum(['pattern', 'anti-pattern', 'rule']).optional(),
26
- severity: z.enum(['critical', 'warning', 'suggestion']).optional(),
27
- tags: z.array(z.string()).optional(),
28
- limit: z.number().optional(),
29
- }),
30
- handler: async (params) => {
31
- return brain.intelligentSearch(params.query as string, {
32
- domain: params.domain as string | undefined,
33
- type: params.type as string | undefined,
34
- severity: params.severity as string | undefined,
35
- tags: params.tags as string[] | undefined,
36
- limit: (params.limit as number) ?? 10,
37
- });
38
- },
39
- },
40
- {
41
- name: 'vault_stats',
42
- description: 'Get vault statistics — entry counts by type, domain, severity.',
43
- auth: 'read',
44
- handler: async () => vault.stats(),
45
- },
46
- {
47
- name: 'list_all',
48
- description: 'List all knowledge entries with optional filters.',
49
- auth: 'read',
50
- schema: z.object({
51
- domain: z.string().optional(),
52
- type: z.enum(['pattern', 'anti-pattern', 'rule']).optional(),
53
- severity: z.enum(['critical', 'warning', 'suggestion']).optional(),
54
- tags: z.array(z.string()).optional(),
55
- limit: z.number().optional(),
56
- offset: z.number().optional(),
57
- }),
58
- handler: async (params) => {
59
- return vault.list({
60
- domain: params.domain as string | undefined,
61
- type: params.type as string | undefined,
62
- severity: params.severity as string | undefined,
63
- tags: params.tags as string[] | undefined,
64
- limit: (params.limit as number) ?? 50,
65
- offset: (params.offset as number) ?? 0,
66
- });
67
- },
68
- },
69
- {
70
- name: 'health',
71
- description: 'Health check — vault status and agent info.',
72
- auth: 'read',
73
- handler: async () => {
74
- const stats = vault.stats();
75
- return {
76
- status: 'ok',
77
- agent: { name: PERSONA.name, role: PERSONA.role },
78
- vault: { entries: stats.totalEntries, domains: Object.keys(stats.byDomain) },
79
- };
80
- },
81
- },
82
- {
83
- name: 'identity',
84
- description: 'Get agent identity — name, role, principles.',
85
- auth: 'read',
86
- handler: async () => PERSONA,
87
- },
88
- {
89
- name: 'activate',
90
- description: 'Activate agent persona — returns full context for Claude to adopt. Say "Hello, ${config.name}!" to trigger.',
91
- auth: 'read',
92
- schema: z.object({
93
- projectPath: z.string().optional().default('.'),
94
- deactivate: z.boolean().optional(),
95
- }),
96
- handler: async (params) => {
97
- if (params.deactivate) {
98
- return deactivateAgent();
99
- }
100
- return activateAgent(vault, (params.projectPath as string) ?? '.', planner);
101
- },
102
- },
103
- {
104
- name: 'inject_claude_md',
105
- description: 'Inject agent sections into CLAUDE.md — project-level or global (~/.claude/CLAUDE.md). Idempotent.',
106
- auth: 'write',
107
- schema: z.object({
108
- projectPath: z.string().optional().default('.'),
109
- global: z.boolean().optional().describe('If true, inject into ~/.claude/CLAUDE.md instead of project-level'),
110
- }),
111
- handler: async (params) => {
112
- if (params.global) {
113
- return injectClaudeMdGlobal();
114
- }
115
- return injectClaudeMd((params.projectPath as string) ?? '.');
116
- },
117
- },
118
- {
119
- name: 'setup',
120
- description: 'Check setup status — CLAUDE.md configured? Vault has entries? What to do next?',
121
- auth: 'read',
122
- schema: z.object({
123
- projectPath: z.string().optional().default('.'),
124
- }),
125
- handler: async (params) => {
126
- const { existsSync } = await import('node:fs');
127
- const { join } = await import('node:path');
128
- const { homedir } = await import('node:os');
129
- const projectPath = (params.projectPath as string) ?? '.';
130
-
131
- const projectClaudeMd = join(projectPath, 'CLAUDE.md');
132
- const globalClaudeMd = join(homedir(), '.claude', 'CLAUDE.md');
133
-
134
- const projectExists = existsSync(projectClaudeMd);
135
- const projectHasAgent = hasAgentMarker(projectClaudeMd);
136
- const globalExists = existsSync(globalClaudeMd);
137
- const globalHasAgent = hasAgentMarker(globalClaudeMd);
138
-
139
- const stats = vault.stats();
140
-
141
- const recommendations: string[] = [];
142
- if (!globalHasAgent && !projectHasAgent) {
143
- recommendations.push('No CLAUDE.md configured — run inject_claude_md with global: true for all projects, or without for this project');
144
- } else if (!globalHasAgent) {
145
- recommendations.push('Global ~/.claude/CLAUDE.md not configured — run inject_claude_md with global: true to enable in all projects');
146
- }
147
- if (stats.totalEntries === 0) {
148
- recommendations.push('Vault is empty — add intelligence data or capture knowledge via domain facades');
149
- }
150
- if (recommendations.length === 0) {
151
- recommendations.push('${config.name} is fully set up and ready!');
152
- }
153
-
154
- return {
155
- agent: { name: PERSONA.name, role: PERSONA.role },
156
- claude_md: {
157
- project: { exists: projectExists, has_agent_section: projectHasAgent },
158
- global: { exists: globalExists, has_agent_section: globalHasAgent },
159
- },
160
- vault: { entries: stats.totalEntries, domains: Object.keys(stats.byDomain) },
161
- recommendations,
162
- };
163
- },
164
- },
165
- {
166
- name: 'register',
167
- description: 'Register a project for this session. Call on every new session to track usage and get context.',
168
- auth: 'write',
169
- schema: z.object({
170
- projectPath: z.string().optional().default('.'),
171
- name: z.string().optional().describe('Project display name (derived from path if omitted)'),
172
- }),
173
- handler: async (params) => {
174
- const { resolve } = await import('node:path');
175
- const projectPath = resolve((params.projectPath as string) ?? '.');
176
- const project = vault.registerProject(projectPath, params.name as string | undefined);
177
- const stats = vault.stats();
178
- const isNew = project.sessionCount === 1;
179
-
180
- return {
181
- project,
182
- is_new: isNew,
183
- message: isNew
184
- ? 'Welcome! New project registered. Say "Hello, ${config.name}!" to activate.'
185
- : 'Welcome back! Session #' + project.sessionCount + ' for ' + project.name + '.',
186
- vault: { entries: stats.totalEntries, domains: Object.keys(stats.byDomain) },
187
- };
188
- },
189
- },
190
- {
191
- name: 'memory_search',
192
- description: 'Search memories using full-text search.',
193
- auth: 'read',
194
- schema: z.object({
195
- query: z.string(),
196
- type: z.enum(['session', 'lesson', 'preference']).optional(),
197
- projectPath: z.string().optional(),
198
- limit: z.number().optional(),
199
- }),
200
- handler: async (params) => {
201
- return vault.searchMemories(params.query as string, {
202
- type: params.type as string | undefined,
203
- projectPath: params.projectPath as string | undefined,
204
- limit: (params.limit as number) ?? 10,
205
- });
206
- },
207
- },
208
- {
209
- name: 'memory_capture',
210
- description: 'Capture a memory — session summary, lesson learned, or preference.',
211
- auth: 'write',
212
- schema: z.object({
213
- projectPath: z.string(),
214
- type: z.enum(['session', 'lesson', 'preference']),
215
- context: z.string(),
216
- summary: z.string(),
217
- topics: z.array(z.string()).optional().default([]),
218
- filesModified: z.array(z.string()).optional().default([]),
219
- toolsUsed: z.array(z.string()).optional().default([]),
220
- }),
221
- handler: async (params) => {
222
- const memory = vault.captureMemory({
223
- projectPath: params.projectPath as string,
224
- type: params.type as 'session' | 'lesson' | 'preference',
225
- context: params.context as string,
226
- summary: params.summary as string,
227
- topics: (params.topics as string[]) ?? [],
228
- filesModified: (params.filesModified as string[]) ?? [],
229
- toolsUsed: (params.toolsUsed as string[]) ?? [],
230
- });
231
- return { captured: true, memory };
232
- },
233
- },
234
- {
235
- name: 'memory_list',
236
- description: 'List memories with optional filters.',
237
- auth: 'read',
238
- schema: z.object({
239
- type: z.enum(['session', 'lesson', 'preference']).optional(),
240
- projectPath: z.string().optional(),
241
- limit: z.number().optional(),
242
- offset: z.number().optional(),
243
- }),
244
- handler: async (params) => {
245
- const memories = vault.listMemories({
246
- type: params.type as string | undefined,
247
- projectPath: params.projectPath as string | undefined,
248
- limit: (params.limit as number) ?? 50,
249
- offset: (params.offset as number) ?? 0,
250
- });
251
- const stats = vault.memoryStats();
252
- return { memories, stats };
253
- },
254
- },
255
- {
256
- name: 'session_capture',
257
- description: 'Capture a session summary before context compaction. Called automatically by PreCompact hook.',
258
- auth: 'write',
259
- schema: z.object({
260
- projectPath: z.string().optional().default('.'),
261
- summary: z.string().describe('Brief summary of what was accomplished in this session'),
262
- topics: z.array(z.string()).optional().default([]),
263
- filesModified: z.array(z.string()).optional().default([]),
264
- toolsUsed: z.array(z.string()).optional().default([]),
265
- }),
266
- handler: async (params) => {
267
- const { resolve } = await import('node:path');
268
- const projectPath = resolve((params.projectPath as string) ?? '.');
269
- const memory = vault.captureMemory({
270
- projectPath,
271
- type: 'session',
272
- context: 'Auto-captured before context compaction',
273
- summary: params.summary as string,
274
- topics: (params.topics as string[]) ?? [],
275
- filesModified: (params.filesModified as string[]) ?? [],
276
- toolsUsed: (params.toolsUsed as string[]) ?? [],
277
- });
278
- return { captured: true, memory, message: 'Session summary saved to memory.' };
279
- },
280
- },
281
- {
282
- name: 'export',
283
- description: 'Export vault entries as JSON intelligence bundles — one per domain. Enables version control and sharing.',
284
- auth: 'read',
285
- schema: z.object({
286
- domain: z.string().optional().describe('Export only this domain. Omit to export all.'),
287
- }),
288
- handler: async (params) => {
289
- const stats = vault.stats();
290
- const domains = params.domain
291
- ? [params.domain as string]
292
- : Object.keys(stats.byDomain);
293
- const bundles: Array<{ domain: string; version: string; entries: IntelligenceEntry[] }> = [];
294
- for (const d of domains) {
295
- const entries = vault.list({ domain: d, limit: 10000 });
296
- bundles.push({ domain: d, version: '1.0.0', entries });
297
- }
298
- return {
299
- exported: true,
300
- bundles,
301
- totalEntries: bundles.reduce((sum, b) => sum + b.entries.length, 0),
302
- domains: bundles.map((b) => b.domain),
303
- };
304
- },
305
- },
306
- {
307
- name: 'create_plan',
308
- description: 'Create a new plan in draft status. Plans track multi-step tasks with decisions and sub-tasks.',
309
- auth: 'write',
310
- schema: z.object({
311
- objective: z.string().describe('What the plan aims to achieve'),
312
- scope: z.string().describe('Which parts of the codebase are affected'),
313
- decisions: z.array(z.string()).optional().default([]),
314
- tasks: z.array(z.object({ title: z.string(), description: z.string() })).optional().default([]),
315
- }),
316
- handler: async (params) => {
317
- const plan = planner.create({
318
- objective: params.objective as string,
319
- scope: params.scope as string,
320
- decisions: (params.decisions as string[]) ?? [],
321
- tasks: (params.tasks as Array<{ title: string; description: string }>) ?? [],
322
- });
323
- return { created: true, plan };
324
- },
325
- },
326
- {
327
- name: 'get_plan',
328
- description: 'Get a plan by ID, or list all active plans if no ID provided.',
329
- auth: 'read',
330
- schema: z.object({
331
- planId: z.string().optional().describe('Plan ID. Omit to list all active plans.'),
332
- }),
333
- handler: async (params) => {
334
- if (params.planId) {
335
- const plan = planner.get(params.planId as string);
336
- if (!plan) return { error: 'Plan not found: ' + params.planId };
337
- return plan;
338
- }
339
- return { active: planner.getActive(), executing: planner.getExecuting() };
340
- },
341
- },
342
- {
343
- name: 'approve_plan',
344
- description: 'Approve a draft plan and optionally start execution.',
345
- auth: 'write',
346
- schema: z.object({
347
- planId: z.string(),
348
- startExecution: z.boolean().optional().default(false).describe('If true, immediately start execution after approval'),
349
- }),
350
- handler: async (params) => {
351
- let plan = planner.approve(params.planId as string);
352
- if (params.startExecution) {
353
- plan = planner.startExecution(plan.id);
354
- }
355
- return { approved: true, executing: plan.status === 'executing', plan };
356
- },
357
- },
358
- {
359
- name: 'update_task',
360
- description: 'Update a task status within an executing plan.',
361
- auth: 'write',
362
- schema: z.object({
363
- planId: z.string(),
364
- taskId: z.string(),
365
- status: z.enum(['pending', 'in_progress', 'completed', 'skipped', 'failed']),
366
- }),
367
- handler: async (params) => {
368
- const plan = planner.updateTask(
369
- params.planId as string,
370
- params.taskId as string,
371
- params.status as 'pending' | 'in_progress' | 'completed' | 'skipped' | 'failed',
372
- );
373
- const task = plan.tasks.find((t) => t.id === params.taskId);
374
- return { updated: true, task, plan: { id: plan.id, status: plan.status } };
375
- },
376
- },
377
- {
378
- name: 'complete_plan',
379
- description: 'Mark an executing plan as completed.',
380
- auth: 'write',
381
- schema: z.object({
382
- planId: z.string(),
383
- }),
384
- handler: async (params) => {
385
- const plan = planner.complete(params.planId as string);
386
- const taskSummary = {
387
- completed: plan.tasks.filter((t) => t.status === 'completed').length,
388
- skipped: plan.tasks.filter((t) => t.status === 'skipped').length,
389
- failed: plan.tasks.filter((t) => t.status === 'failed').length,
390
- total: plan.tasks.length,
391
- };
392
- return { completed: true, plan, taskSummary };
393
- },
394
- },
395
- {
396
- name: 'record_feedback',
397
- description: 'Record feedback on a search result — accepted or dismissed. Used for adaptive weight tuning.',
398
- auth: 'write',
399
- schema: z.object({
400
- query: z.string().describe('The original search query'),
401
- entryId: z.string().describe('The entry ID that was accepted or dismissed'),
402
- action: z.enum(['accepted', 'dismissed']),
403
- }),
404
- handler: async (params) => {
405
- brain.recordFeedback(
406
- params.query as string,
407
- params.entryId as string,
408
- params.action as 'accepted' | 'dismissed',
409
- );
410
- return { recorded: true, query: params.query, entryId: params.entryId, action: params.action };
411
- },
412
- },
413
- {
414
- name: 'rebuild_vocabulary',
415
- description: 'Force rebuild the TF-IDF vocabulary from all vault entries.',
416
- auth: 'write',
417
- handler: async () => {
418
- brain.rebuildVocabulary();
419
- return { rebuilt: true, vocabularySize: brain.getVocabularySize() };
420
- },
421
- },
422
- {
423
- name: 'brain_stats',
424
- description: 'Get brain intelligence stats — vocabulary size, feedback count, current scoring weights.',
425
- auth: 'read',
426
- handler: async () => {
427
- return brain.getStats();
428
- },
429
- },
430
- {
431
- name: 'llm_status',
432
- description: 'LLM client status — provider availability, key pool status, model routing config.',
433
- auth: 'read',
434
- handler: async () => {
435
- const available = llmClient?.isAvailable() ?? { openai: false, anthropic: false };
436
- return {
437
- providers: {
438
- openai: {
439
- available: available.openai,
440
- keyPool: openaiKeyPool?.hasKeys ? openaiKeyPool.getStatus() : null,
441
- },
442
- anthropic: {
443
- available: available.anthropic,
444
- keyPool: anthropicKeyPool?.hasKeys ? anthropicKeyPool.getStatus() : null,
445
- },
446
- },
447
- routes: llmClient?.getRoutes() ?? [],
448
- };
449
- },
450
- },
451
- // ─── Curator ops ───────────────────────────────────────────
452
- {
453
- name: 'curator_status',
454
- description: 'Curator status — table row counts, last groomed timestamp.',
455
- auth: 'read',
456
- handler: async () => {
457
- if (!curator) return { error: 'Curator not initialized' };
458
- return curator.getStatus();
459
- },
460
- },
461
- {
462
- name: 'curator_detect_duplicates',
463
- description: 'Detect duplicate entries using TF-IDF cosine similarity.',
464
- auth: 'read',
465
- schema: z.object({
466
- entryId: z.string().optional().describe('Check a specific entry. Omit to scan all.'),
467
- threshold: z.number().optional().describe('Similarity threshold (0-1). Default 0.45.'),
468
- }),
469
- handler: async (params) => {
470
- if (!curator) return { error: 'Curator not initialized' };
471
- return curator.detectDuplicates(
472
- params.entryId as string | undefined,
473
- params.threshold as number | undefined,
474
- );
475
- },
476
- },
477
- {
478
- name: 'curator_contradictions',
479
- description: 'List or detect contradictions between patterns and anti-patterns.',
480
- auth: 'read',
481
- schema: z.object({
482
- status: z.enum(['open', 'resolved', 'dismissed']).optional().describe('Filter by status.'),
483
- detect: z.boolean().optional().describe('If true, run detection before listing.'),
484
- }),
485
- handler: async (params) => {
486
- if (!curator) return { error: 'Curator not initialized' };
487
- if (params.detect) {
488
- curator.detectContradictions();
489
- }
490
- return curator.getContradictions(params.status as 'open' | 'resolved' | 'dismissed' | undefined);
491
- },
492
- },
493
- {
494
- name: 'curator_resolve_contradiction',
495
- description: 'Resolve or dismiss a contradiction.',
496
- auth: 'write',
497
- schema: z.object({
498
- id: z.number().describe('Contradiction ID.'),
499
- resolution: z.enum(['resolved', 'dismissed']),
500
- }),
501
- handler: async (params) => {
502
- if (!curator) return { error: 'Curator not initialized' };
503
- return curator.resolveContradiction(
504
- params.id as number,
505
- params.resolution as 'resolved' | 'dismissed',
506
- );
507
- },
508
- },
509
- {
510
- name: 'curator_groom',
511
- description: 'Groom a single entry — normalize tags, check staleness.',
512
- auth: 'write',
513
- schema: z.object({
514
- entryId: z.string().describe('Entry ID to groom.'),
515
- }),
516
- handler: async (params) => {
517
- if (!curator) return { error: 'Curator not initialized' };
518
- return curator.groomEntry(params.entryId as string);
519
- },
520
- },
521
- {
522
- name: 'curator_groom_all',
523
- description: 'Groom all vault entries — normalize tags, detect staleness.',
524
- auth: 'write',
525
- handler: async () => {
526
- if (!curator) return { error: 'Curator not initialized' };
527
- return curator.groomAll();
528
- },
529
- },
530
- {
531
- name: 'curator_consolidate',
532
- description: 'Consolidate vault — find duplicates, stale entries, contradictions. Dry-run by default.',
533
- auth: 'write',
534
- schema: z.object({
535
- dryRun: z.boolean().optional().describe('Default true. Set false to apply mutations.'),
536
- staleDaysThreshold: z.number().optional().describe('Days before entry is stale. Default 90.'),
537
- duplicateThreshold: z.number().optional().describe('Cosine similarity threshold. Default 0.45.'),
538
- contradictionThreshold: z.number().optional().describe('Contradiction threshold. Default 0.4.'),
539
- }),
540
- handler: async (params) => {
541
- if (!curator) return { error: 'Curator not initialized' };
542
- return curator.consolidate({
543
- dryRun: params.dryRun as boolean | undefined,
544
- staleDaysThreshold: params.staleDaysThreshold as number | undefined,
545
- duplicateThreshold: params.duplicateThreshold as number | undefined,
546
- contradictionThreshold: params.contradictionThreshold as number | undefined,
547
- });
548
- },
549
- },
550
- {
551
- name: 'curator_health_audit',
552
- description: 'Audit vault health — score (0-100), coverage, freshness, quality, tag health, recommendations.',
553
- auth: 'read',
554
- handler: async () => {
555
- if (!curator) return { error: 'Curator not initialized' };
556
- return curator.healthAudit();
557
- },
558
- },
559
- ],
560
- };
561
- }
562
- `;
563
- }
564
- //# sourceMappingURL=core-facade.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"core-facade.js","sourceRoot":"","sources":["../../src/templates/core-facade.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAmB;IACpD,OAAO;;;;;;;;;aASI,MAAM,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uGA2EiF,MAAM,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCA6D9E,MAAM,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gEAiCiB,MAAM,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0X1E,CAAC;AACF,CAAC"}
@@ -1 +0,0 @@
1
- export declare function generateFacadeFactory(): string;
@@ -1,63 +0,0 @@
1
- export function generateFacadeFactory() {
2
- return `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
- import { z } from 'zod';
4
- import type { FacadeConfig, FacadeResponse } from './types.js';
5
-
6
- export function registerFacade(server: McpServer, facade: FacadeConfig): void {
7
- const opNames = facade.ops.map((o) => o.name);
8
-
9
- server.tool(
10
- facade.name,
11
- \`\${facade.description}\\n\\nOperations: \${opNames.join(', ')}\`,
12
- {
13
- op: z.string().describe(\`Operation: \${opNames.join(' | ')}\`),
14
- params: z.record(z.unknown()).optional().default({}).describe('Operation parameters'),
15
- },
16
- async ({ op, params }): Promise<{ content: Array<{ type: 'text'; text: string }> }> => {
17
- const response = await dispatchOp(facade, op, params);
18
- return { content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }] };
19
- },
20
- );
21
- }
22
-
23
- async function dispatchOp(
24
- facade: FacadeConfig,
25
- opName: string,
26
- params: Record<string, unknown>,
27
- ): Promise<FacadeResponse> {
28
- const op = facade.ops.find((o) => o.name === opName);
29
- if (!op) {
30
- return {
31
- success: false,
32
- error: \`Unknown operation "\${opName}" on \${facade.name}. Available: \${facade.ops.map((o) => o.name).join(', ')}\`,
33
- op: opName,
34
- facade: facade.name,
35
- };
36
- }
37
-
38
- try {
39
- let validatedParams = params;
40
- if (op.schema) {
41
- const result = op.schema.safeParse(params);
42
- if (!result.success) {
43
- return { success: false, error: \`Invalid params for \${opName}: \${result.error.message}\`, op: opName, facade: facade.name };
44
- }
45
- validatedParams = result.data as Record<string, unknown>;
46
- }
47
-
48
- const data = await op.handler(validatedParams);
49
- return { success: true, data, op: opName, facade: facade.name };
50
- } catch (err) {
51
- const message = err instanceof Error ? err.message : String(err);
52
- return { success: false, error: message, op: opName, facade: facade.name };
53
- }
54
- }
55
-
56
- export function registerAllFacades(server: McpServer, facades: FacadeConfig[]): void {
57
- for (const facade of facades) {
58
- registerFacade(server, facade);
59
- }
60
- }
61
- `;
62
- }
63
- //# sourceMappingURL=facade-factory.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"facade-factory.js","sourceRoot":"","sources":["../../src/templates/facade-factory.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,qBAAqB;IACnC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2DR,CAAC;AACF,CAAC"}
@@ -1 +0,0 @@
1
- export declare function generateFacadeTypes(): string;
@@ -1,46 +0,0 @@
1
- export function generateFacadeTypes() {
2
- return `import { z } from 'zod';
3
-
4
- /** Handler function for a single facade operation */
5
- export type OpHandler = (params: Record<string, unknown>) => Promise<unknown>;
6
-
7
- /** Auth level required for an operation */
8
- export type AuthLevel = 'read' | 'write' | 'admin';
9
-
10
- /** Operation definition within a facade */
11
- export interface OpDefinition {
12
- name: string;
13
- description: string;
14
- auth: AuthLevel;
15
- handler: OpHandler;
16
- schema?: z.ZodType;
17
- }
18
-
19
- /** Facade configuration — one MCP tool */
20
- export interface FacadeConfig {
21
- /** MCP tool name */
22
- name: string;
23
- /** Human-readable description */
24
- description: string;
25
- /** Domain operations */
26
- ops: OpDefinition[];
27
- }
28
-
29
- /** Standard facade response envelope */
30
- export interface FacadeResponse {
31
- success: boolean;
32
- data?: unknown;
33
- error?: string;
34
- op?: string;
35
- facade?: string;
36
- }
37
-
38
- export const facadeInputSchema = z.object({
39
- op: z.string().describe('Operation name'),
40
- params: z.record(z.unknown()).optional().default({}),
41
- });
42
-
43
- export type FacadeInput = z.infer<typeof facadeInputSchema>;
44
- `;
45
- }
46
- //# sourceMappingURL=facade-types.js.map