cognitive-core 0.0.2 → 0.1.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.
- package/README.md +302 -116
- package/SKILL.md +193 -0
- package/dist/agents/index.d.ts +3 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +5 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/mock-provider.d.ts +23 -0
- package/dist/agents/mock-provider.d.ts.map +1 -0
- package/dist/agents/mock-provider.js +71 -0
- package/dist/agents/mock-provider.js.map +1 -0
- package/dist/agents/types.d.ts +98 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +44 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/atlas.d.ts +196 -0
- package/dist/atlas.d.ts.map +1 -0
- package/dist/atlas.js +373 -0
- package/dist/atlas.js.map +1 -0
- package/dist/bin/cognitive-core.d.ts +18 -0
- package/dist/bin/cognitive-core.d.ts.map +1 -0
- package/dist/bin/cognitive-core.js +419 -0
- package/dist/bin/cognitive-core.js.map +1 -0
- package/dist/embeddings/bm25.d.ts +104 -0
- package/dist/embeddings/bm25.d.ts.map +1 -0
- package/dist/embeddings/bm25.js +264 -0
- package/dist/embeddings/bm25.js.map +1 -0
- package/dist/embeddings/index.d.ts +12 -0
- package/dist/embeddings/index.d.ts.map +1 -0
- package/dist/embeddings/index.js +16 -0
- package/dist/embeddings/index.js.map +1 -0
- package/dist/embeddings/manager.d.ts +112 -0
- package/dist/embeddings/manager.d.ts.map +1 -0
- package/dist/embeddings/manager.js +215 -0
- package/dist/embeddings/manager.js.map +1 -0
- package/dist/embeddings/provider.d.ts +101 -0
- package/dist/embeddings/provider.d.ts.map +1 -0
- package/dist/embeddings/provider.js +232 -0
- package/dist/embeddings/provider.js.map +1 -0
- package/dist/embeddings/vector-store.d.ts +101 -0
- package/dist/embeddings/vector-store.d.ts.map +1 -0
- package/dist/embeddings/vector-store.js +256 -0
- package/dist/embeddings/vector-store.js.map +1 -0
- package/dist/factory.d.ts +193 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +109 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +30 -453
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -509
- package/dist/index.js.map +1 -0
- package/dist/learning/analyzer.d.ts +110 -0
- package/dist/learning/analyzer.d.ts.map +1 -0
- package/dist/learning/analyzer.js +213 -0
- package/dist/learning/analyzer.js.map +1 -0
- package/dist/learning/effectiveness.d.ts +158 -0
- package/dist/learning/effectiveness.d.ts.map +1 -0
- package/dist/learning/effectiveness.js +251 -0
- package/dist/learning/effectiveness.js.map +1 -0
- package/dist/learning/index.d.ts +8 -0
- package/dist/learning/index.d.ts.map +1 -0
- package/dist/learning/index.js +11 -0
- package/dist/learning/index.js.map +1 -0
- package/dist/learning/llm-extractor.d.ts +88 -0
- package/dist/learning/llm-extractor.d.ts.map +1 -0
- package/dist/learning/llm-extractor.js +372 -0
- package/dist/learning/llm-extractor.js.map +1 -0
- package/dist/learning/meta-learner.d.ts +80 -0
- package/dist/learning/meta-learner.d.ts.map +1 -0
- package/dist/learning/meta-learner.js +355 -0
- package/dist/learning/meta-learner.js.map +1 -0
- package/dist/learning/pipeline.d.ts +65 -0
- package/dist/learning/pipeline.d.ts.map +1 -0
- package/dist/learning/pipeline.js +170 -0
- package/dist/learning/pipeline.js.map +1 -0
- package/dist/learning/playbook-extractor.d.ts +113 -0
- package/dist/learning/playbook-extractor.d.ts.map +1 -0
- package/dist/learning/playbook-extractor.js +523 -0
- package/dist/learning/playbook-extractor.js.map +1 -0
- package/dist/learning/usage-inference.d.ts +82 -0
- package/dist/learning/usage-inference.d.ts.map +1 -0
- package/dist/learning/usage-inference.js +261 -0
- package/dist/learning/usage-inference.js.map +1 -0
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +6 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/playbook-server.d.ts +120 -0
- package/dist/mcp/playbook-server.d.ts.map +1 -0
- package/dist/mcp/playbook-server.js +427 -0
- package/dist/mcp/playbook-server.js.map +1 -0
- package/dist/memory/curated-loader.d.ts +62 -0
- package/dist/memory/curated-loader.d.ts.map +1 -0
- package/dist/memory/curated-loader.js +106 -0
- package/dist/memory/curated-loader.js.map +1 -0
- package/dist/memory/experience.d.ts +122 -0
- package/dist/memory/experience.d.ts.map +1 -0
- package/dist/memory/experience.js +392 -0
- package/dist/memory/experience.js.map +1 -0
- package/dist/memory/index.d.ts +6 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +9 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/meta.d.ts +90 -0
- package/dist/memory/meta.d.ts.map +1 -0
- package/dist/memory/meta.js +362 -0
- package/dist/memory/meta.js.map +1 -0
- package/dist/memory/playbook.d.ts +133 -0
- package/dist/memory/playbook.d.ts.map +1 -0
- package/dist/memory/playbook.js +357 -0
- package/dist/memory/playbook.js.map +1 -0
- package/dist/memory/system.d.ts +167 -0
- package/dist/memory/system.d.ts.map +1 -0
- package/dist/memory/system.js +383 -0
- package/dist/memory/system.js.map +1 -0
- package/dist/runtime/backends/acp.d.ts +67 -0
- package/dist/runtime/backends/acp.d.ts.map +1 -0
- package/dist/runtime/backends/acp.js +290 -0
- package/dist/runtime/backends/acp.js.map +1 -0
- package/dist/runtime/backends/index.d.ts +5 -0
- package/dist/runtime/backends/index.d.ts.map +1 -0
- package/dist/runtime/backends/index.js +6 -0
- package/dist/runtime/backends/index.js.map +1 -0
- package/dist/runtime/backends/mock.d.ts +67 -0
- package/dist/runtime/backends/mock.d.ts.map +1 -0
- package/dist/runtime/backends/mock.js +153 -0
- package/dist/runtime/backends/mock.js.map +1 -0
- package/dist/runtime/backends/subprocess.d.ts +56 -0
- package/dist/runtime/backends/subprocess.d.ts.map +1 -0
- package/dist/runtime/backends/subprocess.js +260 -0
- package/dist/runtime/backends/subprocess.js.map +1 -0
- package/dist/runtime/flows/learning.d.ts +73 -0
- package/dist/runtime/flows/learning.d.ts.map +1 -0
- package/dist/runtime/flows/learning.js +116 -0
- package/dist/runtime/flows/learning.js.map +1 -0
- package/dist/runtime/flows/validation.d.ts +122 -0
- package/dist/runtime/flows/validation.d.ts.map +1 -0
- package/dist/runtime/flows/validation.js +223 -0
- package/dist/runtime/flows/validation.js.map +1 -0
- package/dist/runtime/index.d.ts +6 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +8 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/manager.d.ts +116 -0
- package/dist/runtime/manager.d.ts.map +1 -0
- package/dist/runtime/manager.js +416 -0
- package/dist/runtime/manager.js.map +1 -0
- package/dist/runtime/types.d.ts +138 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/search/evaluator.d.ts +102 -0
- package/dist/search/evaluator.d.ts.map +1 -0
- package/dist/search/evaluator.js +352 -0
- package/dist/search/evaluator.js.map +1 -0
- package/dist/search/index.d.ts +7 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +11 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/refinement-loop.d.ts +73 -0
- package/dist/search/refinement-loop.d.ts.map +1 -0
- package/dist/search/refinement-loop.js +245 -0
- package/dist/search/refinement-loop.js.map +1 -0
- package/dist/search/refinement-types.d.ts +154 -0
- package/dist/search/refinement-types.d.ts.map +1 -0
- package/dist/search/refinement-types.js +99 -0
- package/dist/search/refinement-types.js.map +1 -0
- package/dist/search/router.d.ts +61 -0
- package/dist/search/router.d.ts.map +1 -0
- package/dist/search/router.js +197 -0
- package/dist/search/router.js.map +1 -0
- package/dist/search/solver.d.ts +75 -0
- package/dist/search/solver.d.ts.map +1 -0
- package/dist/search/solver.js +216 -0
- package/dist/search/solver.js.map +1 -0
- package/dist/search/verification-runner.d.ts +125 -0
- package/dist/search/verification-runner.d.ts.map +1 -0
- package/dist/search/verification-runner.js +440 -0
- package/dist/search/verification-runner.js.map +1 -0
- package/dist/surfacing/index.d.ts +2 -0
- package/dist/surfacing/index.d.ts.map +1 -0
- package/dist/surfacing/index.js +2 -0
- package/dist/surfacing/index.js.map +1 -0
- package/dist/surfacing/skill-library.d.ts +158 -0
- package/dist/surfacing/skill-library.d.ts.map +1 -0
- package/dist/surfacing/skill-library.js +429 -0
- package/dist/surfacing/skill-library.js.map +1 -0
- package/dist/types/config.d.ts +1113 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +274 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +14 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/memory.d.ts +339 -0
- package/dist/types/memory.d.ts.map +1 -0
- package/dist/types/memory.js +207 -0
- package/dist/types/memory.js.map +1 -0
- package/dist/types/meta.d.ts +146 -0
- package/dist/types/meta.d.ts.map +1 -0
- package/dist/types/meta.js +51 -0
- package/dist/types/meta.js.map +1 -0
- package/dist/types/outcome.d.ts +42 -0
- package/dist/types/outcome.d.ts.map +1 -0
- package/dist/types/outcome.js +50 -0
- package/dist/types/outcome.js.map +1 -0
- package/dist/types/playbook.d.ts +119 -0
- package/dist/types/playbook.d.ts.map +1 -0
- package/dist/types/playbook.js +71 -0
- package/dist/types/playbook.js.map +1 -0
- package/dist/types/step.d.ts +44 -0
- package/dist/types/step.d.ts.map +1 -0
- package/dist/types/step.js +32 -0
- package/dist/types/step.js.map +1 -0
- package/dist/types/task.d.ts +91 -0
- package/dist/types/task.d.ts.map +1 -0
- package/dist/types/task.js +39 -0
- package/dist/types/task.js.map +1 -0
- package/dist/types/trajectory.d.ts +221 -0
- package/dist/types/trajectory.d.ts.map +1 -0
- package/dist/types/trajectory.js +60 -0
- package/dist/types/trajectory.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/similarity.d.ts +31 -0
- package/dist/utils/similarity.d.ts.map +1 -0
- package/dist/utils/similarity.js +107 -0
- package/dist/utils/similarity.js.map +1 -0
- package/dist/utils/storage.d.ts +106 -0
- package/dist/utils/storage.d.ts.map +1 -0
- package/dist/utils/storage.js +203 -0
- package/dist/utils/storage.js.map +1 -0
- package/dist/utils/validation.d.ts +129 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +171 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +50 -34
- package/scripts/migrate-to-playbooks.ts +307 -0
- package/src/agents/index.ts +14 -0
- package/src/agents/mock-provider.ts +93 -0
- package/src/agents/types.ts +137 -0
- package/src/atlas.ts +560 -0
- package/src/bin/cognitive-core.ts +470 -0
- package/src/embeddings/bm25.ts +337 -0
- package/src/embeddings/index.ts +39 -0
- package/src/embeddings/manager.ts +288 -0
- package/src/embeddings/provider.ts +311 -0
- package/src/embeddings/vector-store.ts +353 -0
- package/src/factory.ts +263 -0
- package/src/index.ts +246 -0
- package/src/learning/analyzer.ts +335 -0
- package/src/learning/effectiveness.ts +428 -0
- package/src/learning/index.ts +58 -0
- package/src/learning/llm-extractor.ts +542 -0
- package/src/learning/meta-learner.ts +516 -0
- package/src/learning/pipeline.ts +244 -0
- package/src/learning/playbook-extractor.ts +702 -0
- package/src/learning/usage-inference.ts +372 -0
- package/src/mcp/index.ts +12 -0
- package/src/mcp/playbook-server.ts +565 -0
- package/src/memory/curated-loader.ts +160 -0
- package/src/memory/experience.ts +515 -0
- package/src/memory/index.ts +27 -0
- package/src/memory/meta.ts +506 -0
- package/src/memory/playbook.ts +493 -0
- package/src/memory/system.ts +551 -0
- package/src/runtime/backends/acp.ts +378 -0
- package/src/runtime/backends/index.ts +24 -0
- package/src/runtime/backends/mock.ts +218 -0
- package/src/runtime/backends/subprocess.ts +356 -0
- package/src/runtime/flows/learning.ts +183 -0
- package/src/runtime/flows/validation.ts +381 -0
- package/src/runtime/index.ts +53 -0
- package/src/runtime/manager.ts +541 -0
- package/src/runtime/types.ts +157 -0
- package/src/search/evaluator.ts +474 -0
- package/src/search/index.ts +59 -0
- package/src/search/refinement-loop.ts +363 -0
- package/src/search/refinement-types.ts +159 -0
- package/src/search/router.ts +261 -0
- package/src/search/solver.ts +303 -0
- package/src/search/verification-runner.ts +570 -0
- package/src/surfacing/index.ts +6 -0
- package/src/surfacing/skill-library.ts +594 -0
- package/src/types/config.ts +333 -0
- package/src/types/index.ts +130 -0
- package/src/types/memory.ts +270 -0
- package/src/types/meta.ts +218 -0
- package/src/types/outcome.ts +66 -0
- package/src/types/playbook.ts +196 -0
- package/src/types/step.ts +40 -0
- package/src/types/task.ts +52 -0
- package/src/types/trajectory.ts +80 -0
- package/src/utils/index.ts +38 -0
- package/src/utils/similarity.ts +139 -0
- package/src/utils/storage.ts +249 -0
- package/src/utils/validation.ts +286 -0
- package/tests/embeddings/bm25.test.ts +130 -0
- package/tests/embeddings/manager.test.ts +205 -0
- package/tests/integration/atlas.test.ts +266 -0
- package/tests/integration/e2e.test.ts +929 -0
- package/tests/learning/analyzer.test.ts +426 -0
- package/tests/learning/effectiveness.test.ts +542 -0
- package/tests/learning/pipeline.test.ts +176 -0
- package/tests/learning/playbook-extractor-provenance.test.ts +114 -0
- package/tests/learning/usage-inference.test.ts +254 -0
- package/tests/mcp/playbook-server.test.ts +252 -0
- package/tests/memory/experience.test.ts +198 -0
- package/tests/memory/playbook.test.ts +338 -0
- package/tests/memory/provenance.test.ts +639 -0
- package/tests/memory/system.test.ts +325 -0
- package/tests/runtime/agent-manager.test.ts +512 -0
- package/tests/runtime/mock-backend.test.ts +248 -0
- package/tests/search/refinement-loop.test.ts +468 -0
- package/tests/search/refinement.test.ts +267 -0
- package/tests/search/router.test.ts +427 -0
- package/tests/surfacing/skill-library.test.ts +292 -0
- package/tests/types/outcome.test.ts +147 -0
- package/tests/types/step.test.ts +133 -0
- package/tests/types/task.test.ts +158 -0
- package/tests/types/trajectory.test.ts +253 -0
- package/tests/utils/similarity.test.ts +188 -0
- package/tests/utils/validation.test.ts +252 -0
- package/tsconfig.json +25 -0
- package/vitest.config.ts +22 -0
- package/dist/index.d.mts +0 -466
- package/dist/index.mjs +0 -478
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Playbook Server
|
|
3
|
+
* Exposes playbook retrieval via Model Context Protocol
|
|
4
|
+
*
|
|
5
|
+
* @deprecated This module is deprecated in favor of the CLI interface and SKILL.md approach.
|
|
6
|
+
* See /SKILL.md for instructions on how agents should interact with cognitive-core.
|
|
7
|
+
* Use the CLI at bin/cognitive-core instead of this MCP server.
|
|
8
|
+
*
|
|
9
|
+
* This server provides on-demand access to the full playbook library,
|
|
10
|
+
* allowing agents to search for specific guidance beyond what's in their
|
|
11
|
+
* system prompt.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { Playbook } from '../types/index.js';
|
|
15
|
+
import type { PlaybookLibrary, PlaybookMatch } from '../memory/playbook.js';
|
|
16
|
+
import type { SkillLibrary } from '../surfacing/skill-library.js';
|
|
17
|
+
import type { MCPServerConfig } from '../types/config.js';
|
|
18
|
+
import {
|
|
19
|
+
validateMCPArgs,
|
|
20
|
+
MCPSearchPlaybooksSchema,
|
|
21
|
+
MCPGetPlaybookDetailsSchema,
|
|
22
|
+
MCPGetPlaybooksByDomainSchema,
|
|
23
|
+
} from '../utils/validation.js';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* MCP Tool definition
|
|
27
|
+
*/
|
|
28
|
+
export interface MCPTool {
|
|
29
|
+
name: string;
|
|
30
|
+
description: string;
|
|
31
|
+
inputSchema: {
|
|
32
|
+
type: 'object';
|
|
33
|
+
properties: Record<string, unknown>;
|
|
34
|
+
required?: string[];
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* MCP Tool call request
|
|
40
|
+
*/
|
|
41
|
+
export interface MCPToolCall {
|
|
42
|
+
name: string;
|
|
43
|
+
arguments: Record<string, unknown>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* MCP Tool call result
|
|
48
|
+
*/
|
|
49
|
+
export interface MCPToolResult {
|
|
50
|
+
content: Array<{
|
|
51
|
+
type: 'text';
|
|
52
|
+
text: string;
|
|
53
|
+
}>;
|
|
54
|
+
isError?: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Search result for MCP
|
|
59
|
+
*/
|
|
60
|
+
export interface PlaybookSearchResult {
|
|
61
|
+
id: string;
|
|
62
|
+
name: string;
|
|
63
|
+
confidence: number;
|
|
64
|
+
matchScore: number;
|
|
65
|
+
matchType: string;
|
|
66
|
+
strategy: string;
|
|
67
|
+
tactics: string[];
|
|
68
|
+
successRate: number;
|
|
69
|
+
domains: string[];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Default configuration
|
|
74
|
+
*/
|
|
75
|
+
const DEFAULT_CONFIG: MCPServerConfig = {
|
|
76
|
+
enabled: true,
|
|
77
|
+
exposeResources: true,
|
|
78
|
+
exposeTools: true,
|
|
79
|
+
maxResults: 5,
|
|
80
|
+
minConfidence: 0.3,
|
|
81
|
+
includeRefinements: true,
|
|
82
|
+
enableDomainFiltering: true,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* MCP Playbook Server
|
|
87
|
+
* Provides playbook search tools for agents
|
|
88
|
+
*/
|
|
89
|
+
export class PlaybookMCPServer {
|
|
90
|
+
private playbooks: PlaybookLibrary;
|
|
91
|
+
private config: MCPServerConfig;
|
|
92
|
+
|
|
93
|
+
constructor(
|
|
94
|
+
playbooks: PlaybookLibrary,
|
|
95
|
+
_skillLibrary?: SkillLibrary,
|
|
96
|
+
config?: Partial<MCPServerConfig>
|
|
97
|
+
) {
|
|
98
|
+
this.playbooks = playbooks;
|
|
99
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get available MCP tools
|
|
104
|
+
*/
|
|
105
|
+
getTools(): MCPTool[] {
|
|
106
|
+
return [
|
|
107
|
+
{
|
|
108
|
+
name: 'search_playbooks',
|
|
109
|
+
description:
|
|
110
|
+
'Search for playbooks that provide guidance for solving a problem. ' +
|
|
111
|
+
'Returns strategies, tactics, and success indicators for matching playbooks.',
|
|
112
|
+
inputSchema: {
|
|
113
|
+
type: 'object',
|
|
114
|
+
properties: {
|
|
115
|
+
query: {
|
|
116
|
+
type: 'string',
|
|
117
|
+
description: 'Description of the problem or task to find playbooks for',
|
|
118
|
+
},
|
|
119
|
+
domain: {
|
|
120
|
+
type: 'string',
|
|
121
|
+
description: 'Optional domain to filter results (e.g., "code", "testing", "refactoring")',
|
|
122
|
+
},
|
|
123
|
+
maxResults: {
|
|
124
|
+
type: 'number',
|
|
125
|
+
description: 'Maximum number of playbooks to return (default: 5)',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
required: ['query'],
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: 'get_playbook_details',
|
|
133
|
+
description:
|
|
134
|
+
'Get detailed information about a specific playbook by ID, ' +
|
|
135
|
+
'including full tactics, steps, refinements, and usage statistics.',
|
|
136
|
+
inputSchema: {
|
|
137
|
+
type: 'object',
|
|
138
|
+
properties: {
|
|
139
|
+
playbookId: {
|
|
140
|
+
type: 'string',
|
|
141
|
+
description: 'The ID of the playbook to retrieve',
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
required: ['playbookId'],
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: 'list_domains',
|
|
149
|
+
description: 'List all domains that have playbooks available.',
|
|
150
|
+
inputSchema: {
|
|
151
|
+
type: 'object',
|
|
152
|
+
properties: {},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: 'get_playbooks_by_domain',
|
|
157
|
+
description: 'Get all playbooks for a specific domain.',
|
|
158
|
+
inputSchema: {
|
|
159
|
+
type: 'object',
|
|
160
|
+
properties: {
|
|
161
|
+
domain: {
|
|
162
|
+
type: 'string',
|
|
163
|
+
description: 'The domain to get playbooks for',
|
|
164
|
+
},
|
|
165
|
+
maxResults: {
|
|
166
|
+
type: 'number',
|
|
167
|
+
description: 'Maximum number of playbooks to return (default: 10)',
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
required: ['domain'],
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Handle an MCP tool call
|
|
178
|
+
*/
|
|
179
|
+
async handleToolCall(call: MCPToolCall): Promise<MCPToolResult> {
|
|
180
|
+
try {
|
|
181
|
+
switch (call.name) {
|
|
182
|
+
case 'search_playbooks':
|
|
183
|
+
return await this.handleSearchPlaybooks(call.arguments);
|
|
184
|
+
case 'get_playbook_details':
|
|
185
|
+
return await this.handleGetPlaybookDetails(call.arguments);
|
|
186
|
+
case 'list_domains':
|
|
187
|
+
return await this.handleListDomains();
|
|
188
|
+
case 'get_playbooks_by_domain':
|
|
189
|
+
return await this.handleGetPlaybooksByDomain(call.arguments);
|
|
190
|
+
default:
|
|
191
|
+
return {
|
|
192
|
+
content: [{ type: 'text', text: `Unknown tool: ${call.name}` }],
|
|
193
|
+
isError: true,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
} catch (error) {
|
|
197
|
+
return {
|
|
198
|
+
content: [
|
|
199
|
+
{
|
|
200
|
+
type: 'text',
|
|
201
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
202
|
+
},
|
|
203
|
+
],
|
|
204
|
+
isError: true,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Handle search_playbooks tool call
|
|
211
|
+
*/
|
|
212
|
+
private async handleSearchPlaybooks(
|
|
213
|
+
args: Record<string, unknown>
|
|
214
|
+
): Promise<MCPToolResult> {
|
|
215
|
+
// Validate arguments
|
|
216
|
+
const validated = validateMCPArgs(
|
|
217
|
+
MCPSearchPlaybooksSchema,
|
|
218
|
+
args,
|
|
219
|
+
'search_playbooks'
|
|
220
|
+
);
|
|
221
|
+
const { query, domain } = validated;
|
|
222
|
+
const maxResults = validated.maxResults ?? this.config.maxResults;
|
|
223
|
+
|
|
224
|
+
const matches = await this.playbooks.findMatching(query, {
|
|
225
|
+
k: maxResults,
|
|
226
|
+
domains: domain ? [domain] : undefined,
|
|
227
|
+
minConfidence: this.config.minConfidence,
|
|
228
|
+
excludeAntiPatterns: true,
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
if (matches.length === 0) {
|
|
232
|
+
return {
|
|
233
|
+
content: [
|
|
234
|
+
{
|
|
235
|
+
type: 'text',
|
|
236
|
+
text: 'No playbooks found matching your query. Try a different description or broader search terms.',
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const results: PlaybookSearchResult[] = matches.map((m) =>
|
|
243
|
+
this.formatPlaybookForSearch(m)
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
const formattedResults = results
|
|
247
|
+
.map((r) => this.formatSearchResultAsText(r))
|
|
248
|
+
.join('\n\n---\n\n');
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
content: [{ type: 'text', text: formattedResults }],
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Handle get_playbook_details tool call
|
|
257
|
+
*/
|
|
258
|
+
private async handleGetPlaybookDetails(
|
|
259
|
+
args: Record<string, unknown>
|
|
260
|
+
): Promise<MCPToolResult> {
|
|
261
|
+
// Validate arguments
|
|
262
|
+
const validated = validateMCPArgs(
|
|
263
|
+
MCPGetPlaybookDetailsSchema,
|
|
264
|
+
args,
|
|
265
|
+
'get_playbook_details'
|
|
266
|
+
);
|
|
267
|
+
const playbook = await this.playbooks.get(validated.playbookId);
|
|
268
|
+
|
|
269
|
+
if (!playbook) {
|
|
270
|
+
return {
|
|
271
|
+
content: [
|
|
272
|
+
{
|
|
273
|
+
type: 'text',
|
|
274
|
+
text: `Playbook not found: ${validated.playbookId}`,
|
|
275
|
+
},
|
|
276
|
+
],
|
|
277
|
+
isError: true,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const details = this.formatPlaybookDetails(playbook);
|
|
282
|
+
return {
|
|
283
|
+
content: [{ type: 'text', text: details }],
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Handle list_domains tool call
|
|
289
|
+
*/
|
|
290
|
+
private async handleListDomains(): Promise<MCPToolResult> {
|
|
291
|
+
const allPlaybooks = await this.playbooks.getAll();
|
|
292
|
+
const domains = new Set<string>();
|
|
293
|
+
|
|
294
|
+
for (const playbook of allPlaybooks) {
|
|
295
|
+
for (const domain of playbook.applicability.domains) {
|
|
296
|
+
domains.add(domain);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const domainList = Array.from(domains).sort();
|
|
301
|
+
|
|
302
|
+
if (domainList.length === 0) {
|
|
303
|
+
return {
|
|
304
|
+
content: [
|
|
305
|
+
{
|
|
306
|
+
type: 'text',
|
|
307
|
+
text: 'No domains found. Playbooks may not have domain assignments yet.',
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const text = `Available domains:\n${domainList.map((d) => ` - ${d}`).join('\n')}`;
|
|
314
|
+
return {
|
|
315
|
+
content: [{ type: 'text', text }],
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Handle get_playbooks_by_domain tool call
|
|
321
|
+
*/
|
|
322
|
+
private async handleGetPlaybooksByDomain(
|
|
323
|
+
args: Record<string, unknown>
|
|
324
|
+
): Promise<MCPToolResult> {
|
|
325
|
+
// Validate arguments
|
|
326
|
+
const validated = validateMCPArgs(
|
|
327
|
+
MCPGetPlaybooksByDomainSchema,
|
|
328
|
+
args,
|
|
329
|
+
'get_playbooks_by_domain'
|
|
330
|
+
);
|
|
331
|
+
const { domain } = validated;
|
|
332
|
+
const maxResults = validated.maxResults ?? 10;
|
|
333
|
+
|
|
334
|
+
const allPlaybooks = await this.playbooks.getAll();
|
|
335
|
+
const domainPlaybooks = allPlaybooks
|
|
336
|
+
.filter((p) => p.applicability.domains.includes(domain))
|
|
337
|
+
.sort((a, b) => b.confidence - a.confidence)
|
|
338
|
+
.slice(0, maxResults);
|
|
339
|
+
|
|
340
|
+
if (domainPlaybooks.length === 0) {
|
|
341
|
+
return {
|
|
342
|
+
content: [
|
|
343
|
+
{
|
|
344
|
+
type: 'text',
|
|
345
|
+
text: `No playbooks found for domain: ${domain}`,
|
|
346
|
+
},
|
|
347
|
+
],
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const formatted = domainPlaybooks
|
|
352
|
+
.map((p) => this.formatPlaybookSummary(p))
|
|
353
|
+
.join('\n\n');
|
|
354
|
+
|
|
355
|
+
return {
|
|
356
|
+
content: [{ type: 'text', text: formatted }],
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Format playbook match for search results
|
|
362
|
+
*/
|
|
363
|
+
private formatPlaybookForSearch(match: PlaybookMatch): PlaybookSearchResult {
|
|
364
|
+
const { playbook, score, matchType } = match;
|
|
365
|
+
const { successCount, failureCount } = playbook.evolution;
|
|
366
|
+
const totalUses = successCount + failureCount;
|
|
367
|
+
|
|
368
|
+
return {
|
|
369
|
+
id: playbook.id,
|
|
370
|
+
name: playbook.name,
|
|
371
|
+
confidence: playbook.confidence,
|
|
372
|
+
matchScore: score,
|
|
373
|
+
matchType,
|
|
374
|
+
strategy: playbook.guidance.strategy,
|
|
375
|
+
tactics: playbook.guidance.tactics,
|
|
376
|
+
successRate: totalUses > 0 ? successCount / totalUses : 0,
|
|
377
|
+
domains: playbook.applicability.domains,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Format search result as text
|
|
383
|
+
*/
|
|
384
|
+
private formatSearchResultAsText(result: PlaybookSearchResult): string {
|
|
385
|
+
const lines: string[] = [];
|
|
386
|
+
|
|
387
|
+
lines.push(`## ${result.name}`);
|
|
388
|
+
lines.push(`ID: ${result.id}`);
|
|
389
|
+
lines.push(`Match: ${Math.round(result.matchScore * 100)}% (${result.matchType})`);
|
|
390
|
+
lines.push(`Confidence: ${Math.round(result.confidence * 100)}%`);
|
|
391
|
+
lines.push(`Success Rate: ${Math.round(result.successRate * 100)}%`);
|
|
392
|
+
|
|
393
|
+
if (result.domains.length > 0) {
|
|
394
|
+
lines.push(`Domains: ${result.domains.join(', ')}`);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
lines.push('');
|
|
398
|
+
lines.push(`**Strategy**: ${result.strategy}`);
|
|
399
|
+
|
|
400
|
+
if (result.tactics.length > 0) {
|
|
401
|
+
lines.push('**Tactics**:');
|
|
402
|
+
for (const tactic of result.tactics.slice(0, 5)) {
|
|
403
|
+
lines.push(` - ${tactic}`);
|
|
404
|
+
}
|
|
405
|
+
if (result.tactics.length > 5) {
|
|
406
|
+
lines.push(` ... and ${result.tactics.length - 5} more`);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
return lines.join('\n');
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Format playbook summary
|
|
415
|
+
*/
|
|
416
|
+
private formatPlaybookSummary(playbook: Playbook): string {
|
|
417
|
+
const lines: string[] = [];
|
|
418
|
+
const { successCount, failureCount } = playbook.evolution;
|
|
419
|
+
const totalUses = successCount + failureCount;
|
|
420
|
+
const successRate = totalUses > 0 ? successCount / totalUses : 0;
|
|
421
|
+
|
|
422
|
+
lines.push(`## ${playbook.name}`);
|
|
423
|
+
lines.push(`ID: ${playbook.id}`);
|
|
424
|
+
lines.push(`Confidence: ${Math.round(playbook.confidence * 100)}%`);
|
|
425
|
+
lines.push(`Uses: ${totalUses} (${Math.round(successRate * 100)}% success)`);
|
|
426
|
+
lines.push('');
|
|
427
|
+
lines.push(`**Strategy**: ${playbook.guidance.strategy}`);
|
|
428
|
+
|
|
429
|
+
return lines.join('\n');
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Format full playbook details
|
|
434
|
+
*/
|
|
435
|
+
private formatPlaybookDetails(playbook: Playbook): string {
|
|
436
|
+
const lines: string[] = [];
|
|
437
|
+
const { successCount, failureCount } = playbook.evolution;
|
|
438
|
+
const totalUses = successCount + failureCount;
|
|
439
|
+
const successRate = totalUses > 0 ? successCount / totalUses : 0;
|
|
440
|
+
|
|
441
|
+
lines.push(`# ${playbook.name}`);
|
|
442
|
+
lines.push(`ID: ${playbook.id}`);
|
|
443
|
+
lines.push(`Version: ${playbook.evolution.version}`);
|
|
444
|
+
lines.push(`Confidence: ${Math.round(playbook.confidence * 100)}%`);
|
|
445
|
+
lines.push(`Complexity: ${playbook.complexity}`);
|
|
446
|
+
lines.push(`Estimated Effort: ${playbook.estimatedEffort} steps`);
|
|
447
|
+
lines.push('');
|
|
448
|
+
|
|
449
|
+
// Applicability
|
|
450
|
+
lines.push('## Applicability');
|
|
451
|
+
if (playbook.applicability.situations.length > 0) {
|
|
452
|
+
lines.push('**When to use**:');
|
|
453
|
+
for (const sit of playbook.applicability.situations) {
|
|
454
|
+
lines.push(` - ${sit}`);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (playbook.applicability.triggers.length > 0) {
|
|
458
|
+
lines.push('**Triggers**:');
|
|
459
|
+
for (const trigger of playbook.applicability.triggers) {
|
|
460
|
+
lines.push(` - ${trigger}`);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
if (playbook.applicability.antiPatterns.length > 0) {
|
|
464
|
+
lines.push('**Avoid when**:');
|
|
465
|
+
for (const anti of playbook.applicability.antiPatterns) {
|
|
466
|
+
lines.push(` - ${anti}`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
if (playbook.applicability.domains.length > 0) {
|
|
470
|
+
lines.push(`**Domains**: ${playbook.applicability.domains.join(', ')}`);
|
|
471
|
+
}
|
|
472
|
+
lines.push('');
|
|
473
|
+
|
|
474
|
+
// Guidance
|
|
475
|
+
lines.push('## Guidance');
|
|
476
|
+
lines.push(`**Strategy**: ${playbook.guidance.strategy}`);
|
|
477
|
+
if (playbook.guidance.tactics.length > 0) {
|
|
478
|
+
lines.push('**Tactics**:');
|
|
479
|
+
for (const tactic of playbook.guidance.tactics) {
|
|
480
|
+
lines.push(` - ${tactic}`);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (playbook.guidance.steps && playbook.guidance.steps.length > 0) {
|
|
484
|
+
lines.push('**Steps**:');
|
|
485
|
+
for (let i = 0; i < playbook.guidance.steps.length; i++) {
|
|
486
|
+
lines.push(` ${i + 1}. ${playbook.guidance.steps[i]}`);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
lines.push('');
|
|
490
|
+
|
|
491
|
+
// Verification
|
|
492
|
+
lines.push('## Verification');
|
|
493
|
+
if (playbook.verification.successIndicators.length > 0) {
|
|
494
|
+
lines.push('**Success indicators**:');
|
|
495
|
+
for (const ind of playbook.verification.successIndicators) {
|
|
496
|
+
lines.push(` - ${ind}`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
if (playbook.verification.failureIndicators.length > 0) {
|
|
500
|
+
lines.push('**Failure indicators**:');
|
|
501
|
+
for (const ind of playbook.verification.failureIndicators) {
|
|
502
|
+
lines.push(` - ${ind}`);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
lines.push('');
|
|
506
|
+
|
|
507
|
+
// Statistics
|
|
508
|
+
lines.push('## Statistics');
|
|
509
|
+
lines.push(`- Total uses: ${totalUses}`);
|
|
510
|
+
lines.push(`- Success rate: ${Math.round(successRate * 100)}%`);
|
|
511
|
+
lines.push(`- Successes: ${successCount}`);
|
|
512
|
+
lines.push(`- Failures: ${failureCount}`);
|
|
513
|
+
lines.push('');
|
|
514
|
+
|
|
515
|
+
// Refinements (if enabled)
|
|
516
|
+
if (
|
|
517
|
+
this.config.includeRefinements &&
|
|
518
|
+
playbook.evolution.refinements.length > 0
|
|
519
|
+
) {
|
|
520
|
+
lines.push('## Context-Specific Refinements');
|
|
521
|
+
for (const ref of playbook.evolution.refinements) {
|
|
522
|
+
lines.push(`- **${ref.context}**: ${ref.addition}`);
|
|
523
|
+
}
|
|
524
|
+
lines.push('');
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Failure modes
|
|
528
|
+
if (playbook.evolution.failures.length > 0) {
|
|
529
|
+
lines.push('## Known Failure Modes');
|
|
530
|
+
for (const failure of playbook.evolution.failures.slice(0, 5)) {
|
|
531
|
+
lines.push(`- ${failure.context}: ${failure.failureMode}`);
|
|
532
|
+
}
|
|
533
|
+
lines.push('');
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
return lines.join('\n');
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Get server info for MCP protocol
|
|
541
|
+
*/
|
|
542
|
+
getServerInfo(): {
|
|
543
|
+
name: string;
|
|
544
|
+
version: string;
|
|
545
|
+
description: string;
|
|
546
|
+
} {
|
|
547
|
+
return {
|
|
548
|
+
name: 'atlas-playbook-server',
|
|
549
|
+
version: '1.0.0',
|
|
550
|
+
description:
|
|
551
|
+
'MCP server providing access to the Atlas playbook library for on-demand guidance retrieval',
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Create an MCP playbook server
|
|
558
|
+
*/
|
|
559
|
+
export function createPlaybookMCPServer(
|
|
560
|
+
playbooks: PlaybookLibrary,
|
|
561
|
+
skillLibrary?: SkillLibrary,
|
|
562
|
+
config?: Partial<MCPServerConfig>
|
|
563
|
+
): PlaybookMCPServer {
|
|
564
|
+
return new PlaybookMCPServer(playbooks, skillLibrary, config);
|
|
565
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Curated Playbook Loader
|
|
3
|
+
*
|
|
4
|
+
* Loads playbooks from JSON files on disk and manages them separately
|
|
5
|
+
* from runtime-extracted playbooks. Supports a --recreate workflow:
|
|
6
|
+
* drop all curated playbooks and reload from source files without
|
|
7
|
+
* losing extracted or imported playbooks.
|
|
8
|
+
*
|
|
9
|
+
* Inspired by Dash's separation of curated knowledge (file-loaded)
|
|
10
|
+
* vs learnings (runtime-discovered).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { readFile, readdir, stat } from 'node:fs/promises';
|
|
14
|
+
import { join, relative } from 'node:path';
|
|
15
|
+
import { existsSync } from 'node:fs';
|
|
16
|
+
import type { PlaybookProvenance } from '../types/index.js';
|
|
17
|
+
import { createPlaybook } from '../types/index.js';
|
|
18
|
+
import type { PlaybookLibrary } from './playbook.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Schema for a curated playbook JSON file
|
|
22
|
+
*/
|
|
23
|
+
export interface CuratedPlaybookFile {
|
|
24
|
+
name: string;
|
|
25
|
+
applicability: {
|
|
26
|
+
situations: string[];
|
|
27
|
+
triggers?: string[];
|
|
28
|
+
antiPatterns?: string[];
|
|
29
|
+
domains: string[];
|
|
30
|
+
};
|
|
31
|
+
guidance: {
|
|
32
|
+
strategy: string;
|
|
33
|
+
tactics: string[];
|
|
34
|
+
steps?: string[];
|
|
35
|
+
codeExample?: string;
|
|
36
|
+
};
|
|
37
|
+
verification?: {
|
|
38
|
+
successIndicators?: string[];
|
|
39
|
+
failureIndicators?: string[];
|
|
40
|
+
rollbackStrategy?: string;
|
|
41
|
+
};
|
|
42
|
+
confidence?: number;
|
|
43
|
+
complexity?: 'simple' | 'moderate' | 'complex';
|
|
44
|
+
estimatedEffort?: number;
|
|
45
|
+
curatedBy?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Result of a curated playbook load operation
|
|
50
|
+
*/
|
|
51
|
+
export interface CuratedLoadResult {
|
|
52
|
+
loaded: number;
|
|
53
|
+
skipped: number;
|
|
54
|
+
errors: Array<{ file: string; error: string }>;
|
|
55
|
+
recreated: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Load curated playbooks from a directory of JSON files into the library.
|
|
60
|
+
*
|
|
61
|
+
* @param curatedDir - Directory containing curated playbook JSON files
|
|
62
|
+
* @param library - PlaybookLibrary to load into
|
|
63
|
+
* @param options.recreate - If true, delete existing curated playbooks before loading
|
|
64
|
+
*/
|
|
65
|
+
export async function loadCuratedPlaybooks(
|
|
66
|
+
curatedDir: string,
|
|
67
|
+
library: PlaybookLibrary,
|
|
68
|
+
options?: { recreate?: boolean }
|
|
69
|
+
): Promise<CuratedLoadResult> {
|
|
70
|
+
const result: CuratedLoadResult = {
|
|
71
|
+
loaded: 0,
|
|
72
|
+
skipped: 0,
|
|
73
|
+
errors: [],
|
|
74
|
+
recreated: false,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
if (!existsSync(curatedDir)) {
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Recreate: drop all curated playbooks first
|
|
82
|
+
if (options?.recreate) {
|
|
83
|
+
await library.deleteByOrigin('curated');
|
|
84
|
+
result.recreated = true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Find all JSON files in the directory (non-recursive)
|
|
88
|
+
const files = await readdir(curatedDir);
|
|
89
|
+
const jsonFiles = files.filter((f) => f.endsWith('.json'));
|
|
90
|
+
|
|
91
|
+
for (const file of jsonFiles) {
|
|
92
|
+
const filePath = join(curatedDir, file);
|
|
93
|
+
const fileStat = await stat(filePath);
|
|
94
|
+
if (!fileStat.isFile()) continue;
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
const content = await readFile(filePath, 'utf-8');
|
|
98
|
+
const parsed = JSON.parse(content) as CuratedPlaybookFile;
|
|
99
|
+
|
|
100
|
+
// Validate required fields
|
|
101
|
+
if (!parsed.name || !parsed.applicability || !parsed.guidance) {
|
|
102
|
+
result.errors.push({
|
|
103
|
+
file,
|
|
104
|
+
error: 'Missing required fields: name, applicability, guidance',
|
|
105
|
+
});
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Check if this curated playbook already exists (by name)
|
|
110
|
+
const existing = await library.getByName(parsed.name);
|
|
111
|
+
if (existing && !options?.recreate) {
|
|
112
|
+
result.skipped++;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const relativePath = relative(process.cwd(), filePath);
|
|
117
|
+
const provenance: PlaybookProvenance = {
|
|
118
|
+
origin: 'curated',
|
|
119
|
+
sourceFile: relativePath,
|
|
120
|
+
curatedBy: parsed.curatedBy,
|
|
121
|
+
recordedAt: new Date(),
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const playbook = createPlaybook({
|
|
125
|
+
name: parsed.name,
|
|
126
|
+
applicability: {
|
|
127
|
+
situations: parsed.applicability.situations,
|
|
128
|
+
triggers: parsed.applicability.triggers ?? [],
|
|
129
|
+
antiPatterns: parsed.applicability.antiPatterns ?? [],
|
|
130
|
+
domains: parsed.applicability.domains,
|
|
131
|
+
},
|
|
132
|
+
guidance: {
|
|
133
|
+
strategy: parsed.guidance.strategy,
|
|
134
|
+
tactics: parsed.guidance.tactics,
|
|
135
|
+
steps: parsed.guidance.steps,
|
|
136
|
+
codeExample: parsed.guidance.codeExample,
|
|
137
|
+
},
|
|
138
|
+
verification: {
|
|
139
|
+
successIndicators: parsed.verification?.successIndicators ?? [],
|
|
140
|
+
failureIndicators: parsed.verification?.failureIndicators ?? [],
|
|
141
|
+
rollbackStrategy: parsed.verification?.rollbackStrategy,
|
|
142
|
+
},
|
|
143
|
+
provenance,
|
|
144
|
+
confidence: parsed.confidence ?? 0.7, // Curated starts higher than extracted (0.3)
|
|
145
|
+
complexity: parsed.complexity ?? 'moderate',
|
|
146
|
+
estimatedEffort: parsed.estimatedEffort ?? 3,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
await library.add(playbook);
|
|
150
|
+
result.loaded++;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
result.errors.push({
|
|
153
|
+
file,
|
|
154
|
+
error: error instanceof Error ? error.message : String(error),
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return result;
|
|
160
|
+
}
|