cognitive-core 0.2.3 → 0.2.5
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/dist/surfacing/skill-publisher.d.ts +3 -3
- package/dist/surfacing/skill-publisher.d.ts.map +1 -1
- package/dist/surfacing/skill-publisher.js +90 -41
- package/dist/surfacing/skill-publisher.js.map +1 -1
- package/dist/surfacing/sqlite-storage-adapter.d.ts +2 -2
- package/dist/surfacing/sqlite-storage-adapter.d.ts.map +1 -1
- package/dist/surfacing/sqlite-storage-adapter.js +15 -10
- package/dist/surfacing/sqlite-storage-adapter.js.map +1 -1
- package/dist/types/playbook.d.ts +11 -0
- package/dist/types/playbook.d.ts.map +1 -1
- package/dist/types/playbook.js +2 -0
- package/dist/types/playbook.js.map +1 -1
- package/dist/workspace/templates/index.d.ts +1 -0
- package/dist/workspace/templates/index.d.ts.map +1 -1
- package/dist/workspace/templates/index.js +2 -0
- package/dist/workspace/templates/index.js.map +1 -1
- package/dist/workspace/templates/skill-enrichment.d.ts +48 -0
- package/dist/workspace/templates/skill-enrichment.d.ts.map +1 -0
- package/dist/workspace/templates/skill-enrichment.js +175 -0
- package/dist/workspace/templates/skill-enrichment.js.map +1 -0
- package/package.json +4 -4
- package/src/surfacing/skill-publisher.ts +116 -49
- package/src/surfacing/sqlite-storage-adapter.ts +14 -12
- package/src/types/playbook.ts +15 -0
- package/src/workspace/templates/index.ts +7 -0
- package/src/workspace/templates/skill-enrichment.ts +275 -0
- package/tests/integration/ranking-driven-loadout-e2e.test.ts +185 -0
- package/tests/integration/skill-publishing-filesystem-e2e.test.ts +216 -0
- package/tests/surfacing/skill-publisher.test.ts +86 -18
- package/tests/surfacing/sqlite-storage-adapter.test.ts +0 -9
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Enrichment Template
|
|
3
|
+
*
|
|
4
|
+
* Agent-in-the-loop step between playbook extraction and skill publishing.
|
|
5
|
+
* Given a Playbook and its procedurally generated SKILL.md skeleton, an agent
|
|
6
|
+
* enriches the skill with narrative prose, worked examples, cross-references,
|
|
7
|
+
* and a trigger-rich description — things a procedural converter cannot produce.
|
|
8
|
+
*
|
|
9
|
+
* Complexity routing:
|
|
10
|
+
* - Simple playbooks (<=3 tactics, low complexity) → heuristic: keep procedural output as-is
|
|
11
|
+
* - Standard/complex playbooks → agent enrichment
|
|
12
|
+
*/
|
|
13
|
+
import { convertPlaybookToSkill } from '../../surfacing/skill-publisher.js';
|
|
14
|
+
// ============================================================
|
|
15
|
+
// Template Implementation
|
|
16
|
+
// ============================================================
|
|
17
|
+
export const skillEnrichmentTemplate = {
|
|
18
|
+
taskType: 'skill-enrichment',
|
|
19
|
+
domain: 'skill-publishing',
|
|
20
|
+
description: 'Enrich a procedurally generated SKILL.md with narrative prose, examples, and cross-references',
|
|
21
|
+
assessComplexity(input) {
|
|
22
|
+
const pb = input.playbook;
|
|
23
|
+
const tacticCount = pb.guidance.tactics.length;
|
|
24
|
+
const hasSteps = (pb.guidance.steps?.length ?? 0) > 0;
|
|
25
|
+
const isComplex = pb.complexity === 'complex';
|
|
26
|
+
if (tacticCount <= 3 && !hasSteps && !isComplex)
|
|
27
|
+
return 'heuristic';
|
|
28
|
+
if (isComplex || tacticCount > 8)
|
|
29
|
+
return 'thorough';
|
|
30
|
+
return 'standard';
|
|
31
|
+
},
|
|
32
|
+
async heuristicFallback(input) {
|
|
33
|
+
const skill = convertPlaybookToSkill(input.playbook);
|
|
34
|
+
return {
|
|
35
|
+
description: skill.description,
|
|
36
|
+
instructions: skill.instructions,
|
|
37
|
+
examples: [],
|
|
38
|
+
seeAlso: (input.relatedSkills ?? []).map((r) => ({
|
|
39
|
+
name: r.name,
|
|
40
|
+
relation: `Related: ${r.description}`,
|
|
41
|
+
})),
|
|
42
|
+
gaps: [],
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
async prepareWorkspace(input, handle) {
|
|
46
|
+
// Write the playbook as structured JSON
|
|
47
|
+
await handle.writeJson('input', 'playbook.json', {
|
|
48
|
+
name: input.playbook.name,
|
|
49
|
+
applicability: input.playbook.applicability,
|
|
50
|
+
guidance: input.playbook.guidance,
|
|
51
|
+
verification: input.playbook.verification,
|
|
52
|
+
complexity: input.playbook.complexity,
|
|
53
|
+
confidence: input.playbook.confidence,
|
|
54
|
+
evolution: {
|
|
55
|
+
version: input.playbook.evolution.version,
|
|
56
|
+
successCount: input.playbook.evolution.successCount,
|
|
57
|
+
failureCount: input.playbook.evolution.failureCount,
|
|
58
|
+
refinements: input.playbook.evolution.refinements,
|
|
59
|
+
},
|
|
60
|
+
provenance: input.playbook.provenance,
|
|
61
|
+
userInvocable: input.playbook.userInvocable,
|
|
62
|
+
publishMetadata: input.playbook.publishMetadata,
|
|
63
|
+
});
|
|
64
|
+
// Write the procedural skeleton for the agent to improve upon
|
|
65
|
+
const skill = convertPlaybookToSkill(input.playbook);
|
|
66
|
+
await handle.writeRaw('input', 'skeleton.md', skill.instructions);
|
|
67
|
+
await handle.writeRaw('input', 'skeleton-description.txt', skill.description);
|
|
68
|
+
// Style reference (if provided)
|
|
69
|
+
if (input.styleReference) {
|
|
70
|
+
await handle.writeRaw('input', 'style-reference.md', input.styleReference);
|
|
71
|
+
}
|
|
72
|
+
// Related skills for cross-referencing
|
|
73
|
+
if (input.relatedSkills && input.relatedSkills.length > 0) {
|
|
74
|
+
await handle.writeJson('input', 'related-skills.json', input.relatedSkills);
|
|
75
|
+
}
|
|
76
|
+
// Domain context
|
|
77
|
+
if (input.domainContext) {
|
|
78
|
+
await handle.writeRaw('input', 'domain-context.txt', input.domainContext);
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
buildTaskPrompt(input) {
|
|
82
|
+
const parts = [
|
|
83
|
+
`Enrich the skill "${input.playbook.name}" into a high-quality SKILL.md that an AI agent will load and follow.`,
|
|
84
|
+
'',
|
|
85
|
+
'## Inputs',
|
|
86
|
+
'',
|
|
87
|
+
'- `input/playbook.json` — the structured playbook (applicability, guidance, verification)',
|
|
88
|
+
'- `input/skeleton.md` — procedurally generated markdown body (your starting point)',
|
|
89
|
+
'- `input/skeleton-description.txt` — procedurally generated frontmatter description',
|
|
90
|
+
];
|
|
91
|
+
if (input.styleReference) {
|
|
92
|
+
parts.push('- `input/style-reference.md` — a hand-written SKILL.md to match in tone and structure');
|
|
93
|
+
}
|
|
94
|
+
if (input.relatedSkills && input.relatedSkills.length > 0) {
|
|
95
|
+
parts.push('- `input/related-skills.json` — related skills to cross-reference');
|
|
96
|
+
}
|
|
97
|
+
if (input.domainContext) {
|
|
98
|
+
parts.push('- `input/domain-context.txt` — domain context for accurate terminology');
|
|
99
|
+
}
|
|
100
|
+
parts.push('', '## What to produce', '', 'Read all inputs, then write `output/enrichment.json` with this schema:', '', '```json', '{', ' "description": "Trigger-rich frontmatter description, under 1024 chars. Structure: [What it does] + [Use when ...trigger phrases...]. Include concrete phrases users would say.",', ' "instructions": "Full markdown body. Must include:\\n- ## When to use (bulleted)\\n- ## When not to use (bulleted)\\n- ## Workflow (numbered tactics expanded into full prose — explain WHY each step matters, not just WHAT to do)\\n- ## Inputs / ## Outputs\\n- ## Verification (bulleted success/failure indicators)\\n- ## Edge cases (narrative, with recovery paths)\\n- ## Examples (2-3 worked scenarios with concrete commands)\\n- ## See also (cross-references)",', ' "examples": [{"title": "...", "scenario": "...", "steps": "..."}],', ' "seeAlso": [{"name": "skill-name", "relation": "why it is related"}],', ' "gaps": ["anything missing from the playbook that the skill should cover but cannot without more data"]', '}', '```', '', '## Guidelines', '', '- The skeleton is your starting point — improve it, do not discard it.', '- Expand each tactic in the Workflow section into a paragraph that explains the rationale, not just the command.', '- Generate 2-3 realistic examples with concrete tool calls (MCP tools, CLI commands, or library calls as appropriate for the domain).', '- Cross-reference related skills by name in the See Also section.', '- Flag gaps honestly — if the playbook is missing triggers, anti-patterns, or verification criteria, say so in the gaps array.', '- Keep the description under 1024 characters. It must include trigger phrases users would actually say.', '- Do not invent capabilities the playbook does not describe. Enrich what is there; do not fabricate.');
|
|
101
|
+
if (input.styleReference) {
|
|
102
|
+
parts.push('- Match the tone, section structure, and level of detail from the style reference.');
|
|
103
|
+
}
|
|
104
|
+
return parts.join('\n');
|
|
105
|
+
},
|
|
106
|
+
getSkills() { return []; },
|
|
107
|
+
getResources(input) {
|
|
108
|
+
const resources = [];
|
|
109
|
+
if (input.domainContext) {
|
|
110
|
+
resources.push({
|
|
111
|
+
type: 'file',
|
|
112
|
+
path: 'domain-context.txt',
|
|
113
|
+
source: input.domainContext,
|
|
114
|
+
description: 'Domain context for accurate terminology',
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return resources;
|
|
118
|
+
},
|
|
119
|
+
outputConfig: {
|
|
120
|
+
files: [
|
|
121
|
+
{
|
|
122
|
+
path: 'enrichment.json',
|
|
123
|
+
format: 'json',
|
|
124
|
+
required: true,
|
|
125
|
+
description: 'Enriched skill content with description, instructions, examples, cross-refs, and gaps',
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
async collectOutput(handle) {
|
|
130
|
+
const raw = await handle.readJson('output', 'enrichment.json');
|
|
131
|
+
return {
|
|
132
|
+
description: typeof raw.description === 'string'
|
|
133
|
+
? raw.description.slice(0, 1024)
|
|
134
|
+
: '',
|
|
135
|
+
instructions: typeof raw.instructions === 'string'
|
|
136
|
+
? raw.instructions
|
|
137
|
+
: '',
|
|
138
|
+
examples: Array.isArray(raw.examples)
|
|
139
|
+
? raw.examples.map((e) => ({
|
|
140
|
+
title: String(e.title ?? ''),
|
|
141
|
+
scenario: String(e.scenario ?? ''),
|
|
142
|
+
steps: String(e.steps ?? ''),
|
|
143
|
+
}))
|
|
144
|
+
: [],
|
|
145
|
+
seeAlso: Array.isArray(raw.seeAlso)
|
|
146
|
+
? raw.seeAlso.map((s) => ({
|
|
147
|
+
name: String(s.name ?? ''),
|
|
148
|
+
relation: String(s.relation ?? ''),
|
|
149
|
+
}))
|
|
150
|
+
: [],
|
|
151
|
+
gaps: Array.isArray(raw.gaps)
|
|
152
|
+
? raw.gaps.map(String)
|
|
153
|
+
: [],
|
|
154
|
+
};
|
|
155
|
+
},
|
|
156
|
+
async processOutput() {
|
|
157
|
+
// Caller handles merging the enriched output back into the Skill
|
|
158
|
+
// and publishing via SkillPublisher.
|
|
159
|
+
},
|
|
160
|
+
computeRequirements: {
|
|
161
|
+
mode: 'local',
|
|
162
|
+
complexity: 'standard',
|
|
163
|
+
},
|
|
164
|
+
getComputeRequirements(_input, complexity) {
|
|
165
|
+
return {
|
|
166
|
+
mode: 'local',
|
|
167
|
+
complexity,
|
|
168
|
+
timeout: complexity === 'thorough' ? 300_000 : 180_000,
|
|
169
|
+
};
|
|
170
|
+
},
|
|
171
|
+
agentType: 'claude-code',
|
|
172
|
+
timeout: 180_000,
|
|
173
|
+
captureToolCalls: true,
|
|
174
|
+
};
|
|
175
|
+
//# sourceMappingURL=skill-enrichment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-enrichment.js","sourceRoot":"","sources":["../../../src/workspace/templates/skill-enrichment.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognitive-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "TypeScript-native cognitive core for adaptive learning and abstraction",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"author": "Alex Ngai",
|
|
66
66
|
"license": "MIT",
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@types/better-sqlite3": "^7.6.
|
|
68
|
+
"@types/better-sqlite3": "^7.6.12",
|
|
69
69
|
"@types/node": "^20.10.0",
|
|
70
70
|
"eslint": "^8.55.0",
|
|
71
71
|
"typescript": "^5.3.0",
|
|
@@ -74,10 +74,10 @@
|
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"acp-factory": "^0.1.14",
|
|
76
76
|
"agent-workspace": "^0.1.5",
|
|
77
|
-
"better-sqlite3": "^
|
|
77
|
+
"better-sqlite3": "^12.0.0",
|
|
78
78
|
"minimem": "^0.1.0",
|
|
79
79
|
"sessionlog": "^0.0.4",
|
|
80
|
-
"skill-tree": "^0.
|
|
80
|
+
"skill-tree": "^0.2.0",
|
|
81
81
|
"sqlite-vec": "^0.1.6",
|
|
82
82
|
"yaml": "^2.8.2",
|
|
83
83
|
"zod": "^3.22.0"
|
|
@@ -6,64 +6,130 @@
|
|
|
6
6
|
* conversion at the publish boundary.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import type { Skill, StorageAdapter } from
|
|
10
|
-
import type { Playbook } from
|
|
11
|
-
import type { PublishResult, DeprecateResult } from
|
|
12
|
-
|
|
9
|
+
import type { Skill, StorageAdapter } from "skill-tree";
|
|
10
|
+
import type { Playbook } from "../types/index.js";
|
|
11
|
+
import type { PublishResult, DeprecateResult } from "./publisher.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Maximum length for the generated `description` field.
|
|
15
|
+
* Claude Code's skill format caps description at 1024 chars, so we truncate
|
|
16
|
+
* to stay safely within that boundary.
|
|
17
|
+
*/
|
|
18
|
+
const MAX_DESCRIPTION_LENGTH = 1024;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Build the `description` field for a published Skill.
|
|
22
|
+
*
|
|
23
|
+
* The description is what lightweight trigger matchers — notably Claude Code's
|
|
24
|
+
* skill loader — key off to decide whether to load a skill. It needs two things:
|
|
25
|
+
*
|
|
26
|
+
* 1. A short "what it does" lead (pulled from the first situation, or the
|
|
27
|
+
* strategy if no situation is set).
|
|
28
|
+
* 2. The concrete trigger phrases, surfaced inline so substring/keyword
|
|
29
|
+
* matchers catch them. These live in `applicability.triggers` on the
|
|
30
|
+
* playbook but are invisible to downstream consumers unless we lift them.
|
|
31
|
+
*
|
|
32
|
+
* Shape: `<lead>. Use when "<t1>", "<t2>", ..., "<tN>".`
|
|
33
|
+
*/
|
|
34
|
+
function buildDescription(playbook: Playbook): string {
|
|
35
|
+
let lead = playbook.applicability.situations[0]
|
|
36
|
+
?? `${playbook.name}: ${playbook.guidance.strategy.slice(0, 100)}`;
|
|
37
|
+
|
|
38
|
+
// Ensure a sentence terminator before appending the trigger clause.
|
|
39
|
+
if (lead.length > 0 && !/[.!?]$/.test(lead)) {
|
|
40
|
+
lead += '.';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const triggers = playbook.applicability.triggers;
|
|
44
|
+
const triggerClause = triggers.length > 0
|
|
45
|
+
? ` Use when ${triggers.map((t) => `"${t}"`).join(', ')}.`
|
|
46
|
+
: '';
|
|
47
|
+
|
|
48
|
+
const full = lead + triggerClause;
|
|
49
|
+
if (full.length <= MAX_DESCRIPTION_LENGTH) return full;
|
|
50
|
+
return full.slice(0, MAX_DESCRIPTION_LENGTH - 3) + '...';
|
|
51
|
+
}
|
|
13
52
|
|
|
14
53
|
/**
|
|
15
54
|
* Convert a Playbook to a Skill
|
|
16
55
|
*/
|
|
17
56
|
export function convertPlaybookToSkill(playbook: Playbook): Skill {
|
|
18
|
-
const totalUses = playbook.evolution.successCount + playbook.evolution.failureCount;
|
|
19
|
-
const successRate = getPlaybookSuccessRate(playbook);
|
|
20
|
-
|
|
21
57
|
// Build solution text from guidance
|
|
22
58
|
let solution = playbook.guidance.strategy;
|
|
23
59
|
if (playbook.guidance.tactics.length > 0) {
|
|
24
|
-
solution +=
|
|
60
|
+
solution +=
|
|
61
|
+
"\n\nTactics:\n" +
|
|
62
|
+
playbook.guidance.tactics.map((t, i) => `${i + 1}. ${t}`).join("\n");
|
|
25
63
|
}
|
|
26
64
|
if (playbook.guidance.steps?.length) {
|
|
27
|
-
solution +=
|
|
65
|
+
solution +=
|
|
66
|
+
"\n\nSteps:\n" +
|
|
67
|
+
playbook.guidance.steps.map((s, i) => `${i + 1}. ${s}`).join("\n");
|
|
28
68
|
}
|
|
29
69
|
|
|
30
|
-
// Build
|
|
31
|
-
const
|
|
32
|
-
? playbook.verification.successIndicators.join('. ')
|
|
33
|
-
: 'Verify the approach worked as expected.';
|
|
70
|
+
// Build description for semantic matching and lightweight trigger routing
|
|
71
|
+
const description = buildDescription(playbook);
|
|
34
72
|
|
|
35
|
-
// Build
|
|
36
|
-
const
|
|
73
|
+
// Build structured instructions body
|
|
74
|
+
const instructionParts: string[] = [];
|
|
75
|
+
|
|
76
|
+
// --- When to use / When not to use (Change A) ---
|
|
77
|
+
if (playbook.applicability.situations.length > 0) {
|
|
78
|
+
instructionParts.push(
|
|
79
|
+
'## When to use\n\n'
|
|
80
|
+
+ playbook.applicability.situations.map((s) => `- ${s}`).join('\n'),
|
|
81
|
+
);
|
|
82
|
+
}
|
|
37
83
|
if (playbook.applicability.antiPatterns.length > 0) {
|
|
38
|
-
|
|
84
|
+
instructionParts.push(
|
|
85
|
+
'## When not to use\n\n'
|
|
86
|
+
+ playbook.applicability.antiPatterns.map((a) => `- ${a}`).join('\n'),
|
|
87
|
+
);
|
|
39
88
|
}
|
|
40
|
-
|
|
41
|
-
|
|
89
|
+
|
|
90
|
+
// --- Solution ---
|
|
91
|
+
instructionParts.push(`## Solution\n\n${solution}`);
|
|
92
|
+
|
|
93
|
+
// --- Verification with bulleted indicators (Change B) ---
|
|
94
|
+
const verificationParts: string[] = [];
|
|
95
|
+
if (playbook.verification.successIndicators.length > 0) {
|
|
96
|
+
verificationParts.push(
|
|
97
|
+
'Success:\n'
|
|
98
|
+
+ playbook.verification.successIndicators.map((s) => `- ${s}`).join('\n'),
|
|
99
|
+
);
|
|
42
100
|
}
|
|
43
|
-
if (playbook.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
101
|
+
if (playbook.verification.failureIndicators.length > 0) {
|
|
102
|
+
verificationParts.push(
|
|
103
|
+
'Failure:\n'
|
|
104
|
+
+ playbook.verification.failureIndicators.map((f) => `- ${f}`).join('\n'),
|
|
105
|
+
);
|
|
47
106
|
}
|
|
48
107
|
if (playbook.verification.rollbackStrategy) {
|
|
49
|
-
|
|
108
|
+
verificationParts.push(`Rollback: ${playbook.verification.rollbackStrategy}`);
|
|
109
|
+
}
|
|
110
|
+
if (verificationParts.length > 0) {
|
|
111
|
+
instructionParts.push(`## Verification\n\n${verificationParts.join('\n\n')}`);
|
|
112
|
+
} else {
|
|
113
|
+
instructionParts.push('## Verification\n\nVerify the approach worked as expected.');
|
|
50
114
|
}
|
|
51
115
|
|
|
52
|
-
//
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
instructionParts.push(`## Verification\n${verification}`);
|
|
116
|
+
// --- Notes (refinements only — anti-patterns now in their own section) ---
|
|
117
|
+
const notesParts: string[] = [];
|
|
118
|
+
if (playbook.evolution.refinements.length > 0) {
|
|
119
|
+
notesParts.push(
|
|
120
|
+
'Refinements:\n'
|
|
121
|
+
+ playbook.evolution.refinements.map((r) => `- In ${r.context}: ${r.addition}`).join('\n'),
|
|
122
|
+
);
|
|
123
|
+
}
|
|
61
124
|
if (notesParts.length > 0) {
|
|
62
|
-
instructionParts.push(`## Notes\n${notesParts.join('\n\n')}`);
|
|
125
|
+
instructionParts.push(`## Notes\n\n${notesParts.join('\n\n')}`);
|
|
63
126
|
}
|
|
127
|
+
|
|
128
|
+
// --- Example ---
|
|
64
129
|
if (playbook.guidance.codeExample) {
|
|
65
|
-
instructionParts.push(`## Example\n\`\`\`\n${playbook.guidance.codeExample}\n\`\`\``);
|
|
130
|
+
instructionParts.push(`## Example\n\n\`\`\`\n${playbook.guidance.codeExample}\n\`\`\``);
|
|
66
131
|
}
|
|
132
|
+
|
|
67
133
|
const instructions = instructionParts.join('\n\n');
|
|
68
134
|
|
|
69
135
|
// Estimate tokens (rough: 4 chars per token)
|
|
@@ -75,23 +141,19 @@ export function convertPlaybookToSkill(playbook: Playbook): Skill {
|
|
|
75
141
|
version: playbook.evolution.version,
|
|
76
142
|
description,
|
|
77
143
|
instructions,
|
|
78
|
-
author: 'cognitive-core',
|
|
144
|
+
author: playbook.provenance?.curatedBy ?? 'cognitive-core',
|
|
79
145
|
tags: playbook.applicability.domains,
|
|
80
|
-
status:
|
|
81
|
-
metrics: {
|
|
82
|
-
usageCount: totalUses,
|
|
83
|
-
successRate,
|
|
84
|
-
lastUsed: playbook.evolution.lastUsed,
|
|
85
|
-
feedbackScores: [],
|
|
86
|
-
averageConfidence: playbook.confidence,
|
|
87
|
-
},
|
|
146
|
+
status: "active",
|
|
88
147
|
source: {
|
|
89
|
-
type:
|
|
148
|
+
type: "extracted",
|
|
90
149
|
sessionId: playbook.evolution.createdFrom[0],
|
|
91
150
|
importedAt: playbook.createdAt,
|
|
92
151
|
},
|
|
93
152
|
serving: {
|
|
94
|
-
summary:
|
|
153
|
+
summary:
|
|
154
|
+
description.length > 150
|
|
155
|
+
? description.slice(0, 147) + "..."
|
|
156
|
+
: description,
|
|
95
157
|
tokenEstimate,
|
|
96
158
|
},
|
|
97
159
|
createdAt: playbook.createdAt,
|
|
@@ -152,15 +214,20 @@ export class SkillPublisher {
|
|
|
152
214
|
/**
|
|
153
215
|
* Deprecate a skill in storage
|
|
154
216
|
*/
|
|
155
|
-
async deprecateSkill(
|
|
217
|
+
async deprecateSkill(
|
|
218
|
+
skillId: string,
|
|
219
|
+
reason: string,
|
|
220
|
+
): Promise<DeprecateResult> {
|
|
156
221
|
try {
|
|
157
222
|
const existing = await this.storage.getSkill(skillId);
|
|
158
223
|
if (!existing) {
|
|
159
|
-
return { deprecated: false, skillId, error:
|
|
224
|
+
return { deprecated: false, skillId, error: "Skill not found" };
|
|
160
225
|
}
|
|
161
226
|
|
|
162
|
-
existing.status =
|
|
163
|
-
existing.description =
|
|
227
|
+
existing.status = "deprecated";
|
|
228
|
+
existing.description =
|
|
229
|
+
(existing.description ? existing.description + " " : "") +
|
|
230
|
+
`[Deprecated: ${reason}]`;
|
|
164
231
|
existing.updatedAt = new Date();
|
|
165
232
|
await this.storage.saveSkill(existing);
|
|
166
233
|
|
|
@@ -23,7 +23,6 @@ interface SkillRow {
|
|
|
23
23
|
author: string | null;
|
|
24
24
|
status: string;
|
|
25
25
|
tags: string;
|
|
26
|
-
metrics: string;
|
|
27
26
|
source: string;
|
|
28
27
|
serving: string;
|
|
29
28
|
related: string;
|
|
@@ -44,8 +43,8 @@ interface VersionRow {
|
|
|
44
43
|
* SQLite-backed StorageAdapter for skill-tree.
|
|
45
44
|
*
|
|
46
45
|
* Stores skills in a `skills` table with JSON columns for nested objects
|
|
47
|
-
* (tags,
|
|
48
|
-
* a separate `skill_versions` table. Dates are stored as ISO strings.
|
|
46
|
+
* (tags, namespace, taxonomy, lineage, etc.). Version history is tracked
|
|
47
|
+
* in a separate `skill_versions` table. Dates are stored as ISO strings.
|
|
49
48
|
*/
|
|
50
49
|
export class SqliteStorageAdapter implements StorageAdapter {
|
|
51
50
|
private db: Database.Database;
|
|
@@ -79,6 +78,16 @@ export class SqliteStorageAdapter implements StorageAdapter {
|
|
|
79
78
|
)
|
|
80
79
|
`);
|
|
81
80
|
|
|
81
|
+
// Backwards-compat: drop the legacy metrics column on existing
|
|
82
|
+
// installs. skill-tree 0.2 dropped Skill.metrics; the column is no
|
|
83
|
+
// longer read or written. SQLite >= 3.35 supports DROP COLUMN; older
|
|
84
|
+
// versions silently fail and leave the column as harmless dead weight.
|
|
85
|
+
try {
|
|
86
|
+
this.db.exec('ALTER TABLE skills DROP COLUMN metrics');
|
|
87
|
+
} catch {
|
|
88
|
+
// Column already absent or SQLite version doesn't support DROP COLUMN.
|
|
89
|
+
}
|
|
90
|
+
|
|
82
91
|
this.db.exec(`
|
|
83
92
|
CREATE TABLE IF NOT EXISTS skill_versions (
|
|
84
93
|
skill_id TEXT NOT NULL,
|
|
@@ -113,10 +122,10 @@ export class SqliteStorageAdapter implements StorageAdapter {
|
|
|
113
122
|
const stmt = this.db.prepare(`
|
|
114
123
|
INSERT OR REPLACE INTO skills
|
|
115
124
|
(id, name, version, description, instructions,
|
|
116
|
-
author, status, tags,
|
|
125
|
+
author, status, tags, source,
|
|
117
126
|
serving, related, created_at, updated_at)
|
|
118
127
|
VALUES
|
|
119
|
-
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
|
128
|
+
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
120
129
|
`);
|
|
121
130
|
|
|
122
131
|
stmt.run(
|
|
@@ -128,7 +137,6 @@ export class SqliteStorageAdapter implements StorageAdapter {
|
|
|
128
137
|
skill.author ?? null,
|
|
129
138
|
skill.status,
|
|
130
139
|
JSON.stringify(skill.tags ?? []),
|
|
131
|
-
JSON.stringify(skill.metrics ?? {}),
|
|
132
140
|
JSON.stringify(skill.source ?? {}),
|
|
133
141
|
JSON.stringify(skill.serving ?? {}),
|
|
134
142
|
JSON.stringify(skill.related ?? []),
|
|
@@ -237,8 +245,6 @@ export class SqliteStorageAdapter implements StorageAdapter {
|
|
|
237
245
|
* Convert a database row to a Skill object, parsing JSON columns and dates.
|
|
238
246
|
*/
|
|
239
247
|
private rowToSkill(row: SkillRow): Skill {
|
|
240
|
-
const metrics = JSON.parse(row.metrics);
|
|
241
|
-
|
|
242
248
|
return {
|
|
243
249
|
id: row.id,
|
|
244
250
|
name: row.name,
|
|
@@ -249,10 +255,6 @@ export class SqliteStorageAdapter implements StorageAdapter {
|
|
|
249
255
|
status: row.status as Skill['status'],
|
|
250
256
|
tags: JSON.parse(row.tags),
|
|
251
257
|
related: JSON.parse(row.related),
|
|
252
|
-
metrics: {
|
|
253
|
-
...metrics,
|
|
254
|
-
lastUsed: metrics.lastUsed ? new Date(metrics.lastUsed) : undefined,
|
|
255
|
-
},
|
|
256
258
|
source: JSON.parse(row.source),
|
|
257
259
|
serving: JSON.parse(row.serving),
|
|
258
260
|
createdAt: new Date(row.created_at),
|
package/src/types/playbook.ts
CHANGED
|
@@ -35,6 +35,19 @@ export interface Playbook {
|
|
|
35
35
|
embedding?: number[]; // For semantic search
|
|
36
36
|
createdAt: Date;
|
|
37
37
|
updatedAt: Date;
|
|
38
|
+
|
|
39
|
+
// === PUBLISH HINTS (optional, used by SkillPublisher) ===
|
|
40
|
+
/**
|
|
41
|
+
* Whether end-users can invoke this skill directly (e.g. via /slash-command).
|
|
42
|
+
* Propagated into the published SKILL.md frontmatter as `user-invocable`.
|
|
43
|
+
*/
|
|
44
|
+
userInvocable?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Arbitrary key-value metadata propagated verbatim into the published
|
|
47
|
+
* SKILL.md frontmatter `metadata:` block. Use for ecosystem-specific
|
|
48
|
+
* fields (audience, component, ecosystem) without changing the core schema.
|
|
49
|
+
*/
|
|
50
|
+
publishMetadata?: Record<string, unknown>;
|
|
38
51
|
}
|
|
39
52
|
|
|
40
53
|
/**
|
|
@@ -159,6 +172,8 @@ export function createPlaybook(
|
|
|
159
172
|
complexity: input.complexity ?? 'moderate',
|
|
160
173
|
estimatedEffort: input.estimatedEffort ?? 3,
|
|
161
174
|
embedding: input.embedding,
|
|
175
|
+
userInvocable: input.userInvocable,
|
|
176
|
+
publishMetadata: input.publishMetadata,
|
|
162
177
|
createdAt: input.createdAt ?? now,
|
|
163
178
|
updatedAt: input.updatedAt ?? now,
|
|
164
179
|
};
|
|
@@ -86,3 +86,10 @@ export {
|
|
|
86
86
|
type PlaybookLifecycleReviewOutput,
|
|
87
87
|
type LifecycleRecommendation,
|
|
88
88
|
} from './playbook-lifecycle-review.js';
|
|
89
|
+
|
|
90
|
+
// Skill Enrichment (publish pipeline — agent-enriched SKILL.md generation)
|
|
91
|
+
export {
|
|
92
|
+
skillEnrichmentTemplate,
|
|
93
|
+
type SkillEnrichmentInput,
|
|
94
|
+
type SkillEnrichmentOutput,
|
|
95
|
+
} from './skill-enrichment.js';
|