cognitive-core 0.2.4 → 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/bin/cognitive-core.js +0 -0
- 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 +16 -18
- 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/package.json +2 -2
- package/src/surfacing/skill-publisher.ts +24 -23
- package/src/surfacing/sqlite-storage-adapter.ts +14 -12
- 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 +6 -11
- package/tests/surfacing/sqlite-storage-adapter.test.ts +0 -9
- package/dist/learning/pipeline.d.ts +0 -89
- package/dist/learning/pipeline.d.ts.map +0 -1
- package/dist/learning/pipeline.js +0 -236
- package/dist/learning/pipeline.js.map +0 -1
|
File without changes
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* writes them directly to a StorageAdapter. Handles the Playbook → Skill
|
|
6
6
|
* conversion at the publish boundary.
|
|
7
7
|
*/
|
|
8
|
-
import type { Skill, StorageAdapter } from
|
|
9
|
-
import type { Playbook } from
|
|
10
|
-
import type { PublishResult, DeprecateResult } from
|
|
8
|
+
import type { Skill, StorageAdapter } from "skill-tree";
|
|
9
|
+
import type { Playbook } from "../types/index.js";
|
|
10
|
+
import type { PublishResult, DeprecateResult } from "./publisher.js";
|
|
11
11
|
/**
|
|
12
12
|
* Convert a Playbook to a Skill
|
|
13
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-publisher.d.ts","sourceRoot":"","sources":["../../src/surfacing/skill-publisher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"skill-publisher.d.ts","sourceRoot":"","sources":["../../src/surfacing/skill-publisher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AA0CrE;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,GAAG,KAAK,CA0GhE;AAED;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,YAAY,CAA0B;gBAElC,OAAO,EAAE,cAAc;IAInC;;OAEG;IACG,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC;IAyBjE;;OAEG;IACG,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAQvE;;OAEG;IACG,cAAc,CAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,CAAC;IAyB3B;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAIxC;;OAEG;IACH,iBAAiB,IAAI,MAAM;CAG5B"}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* writes them directly to a StorageAdapter. Handles the Playbook → Skill
|
|
6
6
|
* conversion at the publish boundary.
|
|
7
7
|
*/
|
|
8
|
-
import { getPlaybookSuccessRate } from '../types/playbook.js';
|
|
9
8
|
/**
|
|
10
9
|
* Maximum length for the generated `description` field.
|
|
11
10
|
* Claude Code's skill format caps description at 1024 chars, so we truncate
|
|
@@ -46,15 +45,17 @@ function buildDescription(playbook) {
|
|
|
46
45
|
* Convert a Playbook to a Skill
|
|
47
46
|
*/
|
|
48
47
|
export function convertPlaybookToSkill(playbook) {
|
|
49
|
-
const totalUses = playbook.evolution.successCount + playbook.evolution.failureCount;
|
|
50
|
-
const successRate = getPlaybookSuccessRate(playbook);
|
|
51
48
|
// Build solution text from guidance
|
|
52
49
|
let solution = playbook.guidance.strategy;
|
|
53
50
|
if (playbook.guidance.tactics.length > 0) {
|
|
54
|
-
solution +=
|
|
51
|
+
solution +=
|
|
52
|
+
"\n\nTactics:\n" +
|
|
53
|
+
playbook.guidance.tactics.map((t, i) => `${i + 1}. ${t}`).join("\n");
|
|
55
54
|
}
|
|
56
55
|
if (playbook.guidance.steps?.length) {
|
|
57
|
-
solution +=
|
|
56
|
+
solution +=
|
|
57
|
+
"\n\nSteps:\n" +
|
|
58
|
+
playbook.guidance.steps.map((s, i) => `${i + 1}. ${s}`).join("\n");
|
|
58
59
|
}
|
|
59
60
|
// Build description for semantic matching and lightweight trigger routing
|
|
60
61
|
const description = buildDescription(playbook);
|
|
@@ -114,21 +115,16 @@ export function convertPlaybookToSkill(playbook) {
|
|
|
114
115
|
instructions,
|
|
115
116
|
author: playbook.provenance?.curatedBy ?? 'cognitive-core',
|
|
116
117
|
tags: playbook.applicability.domains,
|
|
117
|
-
status:
|
|
118
|
-
metrics: {
|
|
119
|
-
usageCount: totalUses,
|
|
120
|
-
successRate,
|
|
121
|
-
lastUsed: playbook.evolution.lastUsed,
|
|
122
|
-
feedbackScores: [],
|
|
123
|
-
averageConfidence: playbook.confidence,
|
|
124
|
-
},
|
|
118
|
+
status: "active",
|
|
125
119
|
source: {
|
|
126
|
-
type:
|
|
120
|
+
type: "extracted",
|
|
127
121
|
sessionId: playbook.evolution.createdFrom[0],
|
|
128
122
|
importedAt: playbook.createdAt,
|
|
129
123
|
},
|
|
130
124
|
serving: {
|
|
131
|
-
summary: description.length > 150
|
|
125
|
+
summary: description.length > 150
|
|
126
|
+
? description.slice(0, 147) + "..."
|
|
127
|
+
: description,
|
|
132
128
|
tokenEstimate,
|
|
133
129
|
},
|
|
134
130
|
createdAt: playbook.createdAt,
|
|
@@ -187,10 +183,12 @@ export class SkillPublisher {
|
|
|
187
183
|
try {
|
|
188
184
|
const existing = await this.storage.getSkill(skillId);
|
|
189
185
|
if (!existing) {
|
|
190
|
-
return { deprecated: false, skillId, error:
|
|
186
|
+
return { deprecated: false, skillId, error: "Skill not found" };
|
|
191
187
|
}
|
|
192
|
-
existing.status =
|
|
193
|
-
existing.description =
|
|
188
|
+
existing.status = "deprecated";
|
|
189
|
+
existing.description =
|
|
190
|
+
(existing.description ? existing.description + " " : "") +
|
|
191
|
+
`[Deprecated: ${reason}]`;
|
|
194
192
|
existing.updatedAt = new Date();
|
|
195
193
|
await this.storage.saveSkill(existing);
|
|
196
194
|
this.publishedIds.delete(skillId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-publisher.js","sourceRoot":"","sources":["../../src/surfacing/skill-publisher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"skill-publisher.js","sourceRoot":"","sources":["../../src/surfacing/skill-publisher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH;;;;GAIG;AACH,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAEpC;;;;;;;;;;;;;GAaG;AACH,SAAS,gBAAgB,CAAC,QAAkB;IAC1C,IAAI,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;WAC1C,GAAG,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IAErE,oEAAoE;IACpE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5C,IAAI,IAAI,GAAG,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;IACjD,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC;QACvC,CAAC,CAAC,aAAa,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QAC1D,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,IAAI,GAAG,IAAI,GAAG,aAAa,CAAC;IAClC,IAAI,IAAI,CAAC,MAAM,IAAI,sBAAsB;QAAE,OAAO,IAAI,CAAC;IACvD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAkB;IACvD,oCAAoC;IACpC,IAAI,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC1C,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,QAAQ;YACN,gBAAgB;gBAChB,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QACpC,QAAQ;YACN,cAAc;gBACd,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvE,CAAC;IAED,0EAA0E;IAC1E,MAAM,WAAW,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE/C,qCAAqC;IACrC,MAAM,gBAAgB,GAAa,EAAE,CAAC;IAEtC,mDAAmD;IACnD,IAAI,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjD,gBAAgB,CAAC,IAAI,CACnB,oBAAoB;cAClB,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CACpE,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnD,gBAAgB,CAAC,IAAI,CACnB,wBAAwB;cACtB,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CACtE,CAAC;IACJ,CAAC;IAED,mBAAmB;IACnB,gBAAgB,CAAC,IAAI,CAAC,kBAAkB,QAAQ,EAAE,CAAC,CAAC;IAEpD,2DAA2D;IAC3D,MAAM,iBAAiB,GAAa,EAAE,CAAC;IACvC,IAAI,QAAQ,CAAC,YAAY,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvD,iBAAiB,CAAC,IAAI,CACpB,YAAY;cACV,QAAQ,CAAC,YAAY,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAC1E,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,YAAY,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvD,iBAAiB,CAAC,IAAI,CACpB,YAAY;cACV,QAAQ,CAAC,YAAY,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAC1E,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC;QAC3C,iBAAiB,CAAC,IAAI,CAAC,aAAa,QAAQ,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,gBAAgB,CAAC,IAAI,CAAC,sBAAsB,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC;SAAM,CAAC;QACN,gBAAgB,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;IACtF,CAAC;IAED,4EAA4E;IAC5E,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,UAAU,CAAC,IAAI,CACb,gBAAgB;cACd,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAC3F,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,gBAAgB,CAAC,IAAI,CAAC,eAAe,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,kBAAkB;IAClB,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QAClC,gBAAgB,CAAC,IAAI,CAAC,yBAAyB,QAAQ,CAAC,QAAQ,CAAC,WAAW,UAAU,CAAC,CAAC;IAC1F,CAAC;IAED,MAAM,YAAY,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEnD,6CAA6C;IAC7C,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEzD,OAAO;QACL,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,OAAO;QACnC,WAAW;QACX,YAAY;QACZ,MAAM,EAAE,QAAQ,CAAC,UAAU,EAAE,SAAS,IAAI,gBAAgB;QAC1D,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,OAAO;QACpC,MAAM,EAAE,QAAQ;QAChB,MAAM,EAAE;YACN,IAAI,EAAE,WAAW;YACjB,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC;YAC5C,UAAU,EAAE,QAAQ,CAAC,SAAS;SAC/B;QACD,OAAO,EAAE;YACP,OAAO,EACL,WAAW,CAAC,MAAM,GAAG,GAAG;gBACtB,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK;gBACnC,CAAC,CAAC,WAAW;YACjB,aAAa;SACd;QACD,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,SAAS,EAAE,QAAQ,CAAC,SAAS;KAC9B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,cAAc;IACjB,OAAO,CAAiB;IACxB,YAAY,GAAgB,IAAI,GAAG,EAAE,CAAC;IAE9C,YAAY,OAAuB;QACjC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,QAAkB;QACtC,MAAM,KAAK,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QAE/C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACvD,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAEhC,OAAO;gBACL,SAAS,EAAE,IAAI;gBACf,OAAO,EAAE,KAAK,CAAC,EAAE;gBACjB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,QAAQ,EAAE,QAAQ,KAAK,IAAI;aAC5B,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,SAAS,EAAE,KAAK;gBAChB,OAAO,EAAE,KAAK,CAAC,EAAE;gBACjB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,QAAQ,EAAE,KAAK;gBACf,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAAC,SAAqB;QAC1C,MAAM,OAAO,GAAoB,EAAE,CAAC;QACpC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAClB,OAAe,EACf,MAAc;QAEd,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;YAClE,CAAC;YAED,QAAQ,CAAC,MAAM,GAAG,YAAY,CAAC;YAC/B,QAAQ,CAAC,WAAW;gBAClB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;oBACxD,gBAAgB,MAAM,GAAG,CAAC;YAC5B,QAAQ,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;YAChC,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAEvC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAClC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QACvC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,UAAU,EAAE,KAAK;gBACjB,OAAO;gBACP,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,UAAkB;QAC5B,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,iBAAiB;QACf,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;IAChC,CAAC;CACF"}
|
|
@@ -12,8 +12,8 @@ import type { Skill, StorageAdapter, SkillVersion, SkillLineage } from 'skill-tr
|
|
|
12
12
|
* SQLite-backed StorageAdapter for skill-tree.
|
|
13
13
|
*
|
|
14
14
|
* Stores skills in a `skills` table with JSON columns for nested objects
|
|
15
|
-
* (tags,
|
|
16
|
-
* a separate `skill_versions` table. Dates are stored as ISO strings.
|
|
15
|
+
* (tags, namespace, taxonomy, lineage, etc.). Version history is tracked
|
|
16
|
+
* in a separate `skill_versions` table. Dates are stored as ISO strings.
|
|
17
17
|
*/
|
|
18
18
|
export declare class SqliteStorageAdapter implements StorageAdapter {
|
|
19
19
|
private db;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-storage-adapter.d.ts","sourceRoot":"","sources":["../../src/surfacing/sqlite-storage-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"sqlite-storage-adapter.d.ts","sourceRoot":"","sources":["../../src/surfacing/sqlite-storage-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA8BpF;;;;;;GAMG;AACH,qBAAa,oBAAqB,YAAW,cAAc;IACzD,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,WAAW,CAAS;gBAEhB,MAAM,EAAE,MAAM;IAMpB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAuD3B,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAK3C,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAgDtC,UAAU,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAyB7E,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMzC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAe3D,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAWzD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAanD;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,OAAO,CAAC,UAAU;CAiBnB"}
|
|
@@ -12,8 +12,8 @@ import Database from 'better-sqlite3';
|
|
|
12
12
|
* SQLite-backed StorageAdapter for skill-tree.
|
|
13
13
|
*
|
|
14
14
|
* Stores skills in a `skills` table with JSON columns for nested objects
|
|
15
|
-
* (tags,
|
|
16
|
-
* a separate `skill_versions` table. Dates are stored as ISO strings.
|
|
15
|
+
* (tags, namespace, taxonomy, lineage, etc.). Version history is tracked
|
|
16
|
+
* in a separate `skill_versions` table. Dates are stored as ISO strings.
|
|
17
17
|
*/
|
|
18
18
|
export class SqliteStorageAdapter {
|
|
19
19
|
db;
|
|
@@ -44,6 +44,16 @@ export class SqliteStorageAdapter {
|
|
|
44
44
|
updated_at TEXT NOT NULL
|
|
45
45
|
)
|
|
46
46
|
`);
|
|
47
|
+
// Backwards-compat: drop the legacy metrics column on existing
|
|
48
|
+
// installs. skill-tree 0.2 dropped Skill.metrics; the column is no
|
|
49
|
+
// longer read or written. SQLite >= 3.35 supports DROP COLUMN; older
|
|
50
|
+
// versions silently fail and leave the column as harmless dead weight.
|
|
51
|
+
try {
|
|
52
|
+
this.db.exec('ALTER TABLE skills DROP COLUMN metrics');
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// Column already absent or SQLite version doesn't support DROP COLUMN.
|
|
56
|
+
}
|
|
47
57
|
this.db.exec(`
|
|
48
58
|
CREATE TABLE IF NOT EXISTS skill_versions (
|
|
49
59
|
skill_id TEXT NOT NULL,
|
|
@@ -73,12 +83,12 @@ export class SqliteStorageAdapter {
|
|
|
73
83
|
const stmt = this.db.prepare(`
|
|
74
84
|
INSERT OR REPLACE INTO skills
|
|
75
85
|
(id, name, version, description, instructions,
|
|
76
|
-
author, status, tags,
|
|
86
|
+
author, status, tags, source,
|
|
77
87
|
serving, related, created_at, updated_at)
|
|
78
88
|
VALUES
|
|
79
|
-
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
|
89
|
+
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
80
90
|
`);
|
|
81
|
-
stmt.run(skill.id, skill.name, skill.version, skill.description ?? null, skill.instructions, skill.author ?? null, skill.status, JSON.stringify(skill.tags ?? []), JSON.stringify(skill.
|
|
91
|
+
stmt.run(skill.id, skill.name, skill.version, skill.description ?? null, skill.instructions, skill.author ?? null, skill.status, JSON.stringify(skill.tags ?? []), JSON.stringify(skill.source ?? {}), JSON.stringify(skill.serving ?? {}), JSON.stringify(skill.related ?? []), toISOString(skill.createdAt), toISOString(skill.updatedAt));
|
|
82
92
|
// Record version snapshot
|
|
83
93
|
const versionStmt = this.db.prepare(`
|
|
84
94
|
INSERT OR IGNORE INTO skill_versions
|
|
@@ -151,7 +161,6 @@ export class SqliteStorageAdapter {
|
|
|
151
161
|
* Convert a database row to a Skill object, parsing JSON columns and dates.
|
|
152
162
|
*/
|
|
153
163
|
rowToSkill(row) {
|
|
154
|
-
const metrics = JSON.parse(row.metrics);
|
|
155
164
|
return {
|
|
156
165
|
id: row.id,
|
|
157
166
|
name: row.name,
|
|
@@ -162,10 +171,6 @@ export class SqliteStorageAdapter {
|
|
|
162
171
|
status: row.status,
|
|
163
172
|
tags: JSON.parse(row.tags),
|
|
164
173
|
related: JSON.parse(row.related),
|
|
165
|
-
metrics: {
|
|
166
|
-
...metrics,
|
|
167
|
-
lastUsed: metrics.lastUsed ? new Date(metrics.lastUsed) : undefined,
|
|
168
|
-
},
|
|
169
174
|
source: JSON.parse(row.source),
|
|
170
175
|
serving: JSON.parse(row.serving),
|
|
171
176
|
createdAt: new Date(row.created_at),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-storage-adapter.js","sourceRoot":"","sources":["../../src/surfacing/sqlite-storage-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"sqlite-storage-adapter.js","sourceRoot":"","sources":["../../src/surfacing/sqlite-storage-adapter.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",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
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,10 +6,9 @@
|
|
|
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
|
-
import { getPlaybookSuccessRate } from '../types/playbook.js';
|
|
9
|
+
import type { Skill, StorageAdapter } from "skill-tree";
|
|
10
|
+
import type { Playbook } from "../types/index.js";
|
|
11
|
+
import type { PublishResult, DeprecateResult } from "./publisher.js";
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
14
|
* Maximum length for the generated `description` field.
|
|
@@ -55,16 +54,17 @@ function buildDescription(playbook: Playbook): string {
|
|
|
55
54
|
* Convert a Playbook to a Skill
|
|
56
55
|
*/
|
|
57
56
|
export function convertPlaybookToSkill(playbook: Playbook): Skill {
|
|
58
|
-
const totalUses = playbook.evolution.successCount + playbook.evolution.failureCount;
|
|
59
|
-
const successRate = getPlaybookSuccessRate(playbook);
|
|
60
|
-
|
|
61
57
|
// Build solution text from guidance
|
|
62
58
|
let solution = playbook.guidance.strategy;
|
|
63
59
|
if (playbook.guidance.tactics.length > 0) {
|
|
64
|
-
solution +=
|
|
60
|
+
solution +=
|
|
61
|
+
"\n\nTactics:\n" +
|
|
62
|
+
playbook.guidance.tactics.map((t, i) => `${i + 1}. ${t}`).join("\n");
|
|
65
63
|
}
|
|
66
64
|
if (playbook.guidance.steps?.length) {
|
|
67
|
-
solution +=
|
|
65
|
+
solution +=
|
|
66
|
+
"\n\nSteps:\n" +
|
|
67
|
+
playbook.guidance.steps.map((s, i) => `${i + 1}. ${s}`).join("\n");
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
// Build description for semantic matching and lightweight trigger routing
|
|
@@ -143,21 +143,17 @@ export function convertPlaybookToSkill(playbook: Playbook): Skill {
|
|
|
143
143
|
instructions,
|
|
144
144
|
author: playbook.provenance?.curatedBy ?? 'cognitive-core',
|
|
145
145
|
tags: playbook.applicability.domains,
|
|
146
|
-
status:
|
|
147
|
-
metrics: {
|
|
148
|
-
usageCount: totalUses,
|
|
149
|
-
successRate,
|
|
150
|
-
lastUsed: playbook.evolution.lastUsed,
|
|
151
|
-
feedbackScores: [],
|
|
152
|
-
averageConfidence: playbook.confidence,
|
|
153
|
-
},
|
|
146
|
+
status: "active",
|
|
154
147
|
source: {
|
|
155
|
-
type:
|
|
148
|
+
type: "extracted",
|
|
156
149
|
sessionId: playbook.evolution.createdFrom[0],
|
|
157
150
|
importedAt: playbook.createdAt,
|
|
158
151
|
},
|
|
159
152
|
serving: {
|
|
160
|
-
summary:
|
|
153
|
+
summary:
|
|
154
|
+
description.length > 150
|
|
155
|
+
? description.slice(0, 147) + "..."
|
|
156
|
+
: description,
|
|
161
157
|
tokenEstimate,
|
|
162
158
|
},
|
|
163
159
|
createdAt: playbook.createdAt,
|
|
@@ -218,15 +214,20 @@ export class SkillPublisher {
|
|
|
218
214
|
/**
|
|
219
215
|
* Deprecate a skill in storage
|
|
220
216
|
*/
|
|
221
|
-
async deprecateSkill(
|
|
217
|
+
async deprecateSkill(
|
|
218
|
+
skillId: string,
|
|
219
|
+
reason: string,
|
|
220
|
+
): Promise<DeprecateResult> {
|
|
222
221
|
try {
|
|
223
222
|
const existing = await this.storage.getSkill(skillId);
|
|
224
223
|
if (!existing) {
|
|
225
|
-
return { deprecated: false, skillId, error:
|
|
224
|
+
return { deprecated: false, skillId, error: "Skill not found" };
|
|
226
225
|
}
|
|
227
226
|
|
|
228
|
-
existing.status =
|
|
229
|
-
existing.description =
|
|
227
|
+
existing.status = "deprecated";
|
|
228
|
+
existing.description =
|
|
229
|
+
(existing.description ? existing.description + " " : "") +
|
|
230
|
+
`[Deprecated: ${reason}]`;
|
|
230
231
|
existing.updatedAt = new Date();
|
|
231
232
|
await this.storage.saveSkill(existing);
|
|
232
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),
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E: ranking-driven loadout — the canonical replacement for skill-tree's
|
|
3
|
+
* removed `LoadoutCriteria.minSuccessRate`.
|
|
4
|
+
*
|
|
5
|
+
* The 0.2 deprecation moved live ranking responsibility upstream of the
|
|
6
|
+
* `include: [...]` list. This test proves that pattern works end-to-end:
|
|
7
|
+
*
|
|
8
|
+
* 1. Build playbooks with different evolution states.
|
|
9
|
+
* 2. Publish all of them as skills via SkillPublisher.
|
|
10
|
+
* 3. Rank the playbooks externally by `getPlaybookSuccessRate`.
|
|
11
|
+
* 4. Pass the top-N IDs to skill-tree's LoadoutCompiler via `include`.
|
|
12
|
+
* 5. Verify the compiled loadout matches the ranking — no metric
|
|
13
|
+
* filter inside skill-tree, no snapshot drift.
|
|
14
|
+
*
|
|
15
|
+
* Real components only:
|
|
16
|
+
* - cognitive-core's Playbook + SkillPublisher
|
|
17
|
+
* - skill-tree's createSkillBank + LoadoutCompiler
|
|
18
|
+
* - real filesystem storage in a temp dir
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
22
|
+
import * as fs from 'node:fs/promises';
|
|
23
|
+
import * as path from 'node:path';
|
|
24
|
+
import * as os from 'node:os';
|
|
25
|
+
|
|
26
|
+
import {
|
|
27
|
+
createPlaybook,
|
|
28
|
+
getPlaybookSuccessRate,
|
|
29
|
+
type Playbook,
|
|
30
|
+
} from '../../src/types/playbook.js';
|
|
31
|
+
import { SkillPublisher } from '../../src/surfacing/skill-publisher.js';
|
|
32
|
+
import { createSkillBank, LoadoutCompiler } from 'skill-tree';
|
|
33
|
+
|
|
34
|
+
let testDir: string;
|
|
35
|
+
|
|
36
|
+
beforeEach(async () => {
|
|
37
|
+
testDir = await fs.mkdtemp(path.join(os.tmpdir(), 'cc-rank-loadout-e2e-'));
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
afterEach(async () => {
|
|
41
|
+
await fs.rm(testDir, { recursive: true, force: true });
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
function pb(
|
|
45
|
+
id: string,
|
|
46
|
+
successCount: number,
|
|
47
|
+
failureCount: number,
|
|
48
|
+
overrides: Partial<Playbook['guidance']> = {},
|
|
49
|
+
): Playbook {
|
|
50
|
+
return createPlaybook({
|
|
51
|
+
id,
|
|
52
|
+
name: id,
|
|
53
|
+
applicability: {
|
|
54
|
+
situations: [`Situation for ${id}`],
|
|
55
|
+
triggers: [],
|
|
56
|
+
antiPatterns: [],
|
|
57
|
+
domains: ['testing'],
|
|
58
|
+
},
|
|
59
|
+
guidance: {
|
|
60
|
+
strategy: `Strategy for ${id}`,
|
|
61
|
+
tactics: [],
|
|
62
|
+
...overrides,
|
|
63
|
+
},
|
|
64
|
+
verification: { successIndicators: [], failureIndicators: [] },
|
|
65
|
+
evolution: {
|
|
66
|
+
version: '1.0.0',
|
|
67
|
+
createdFrom: ['session-x'],
|
|
68
|
+
failures: [],
|
|
69
|
+
refinements: [],
|
|
70
|
+
successCount,
|
|
71
|
+
failureCount,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
describe('ranking-driven loadout e2e (cognitive-core ranks → skill-tree compiles)', () => {
|
|
77
|
+
it('top-N by successRate flows through skill-tree compile via include list', async () => {
|
|
78
|
+
const bank = createSkillBank({ storage: { basePath: testDir } });
|
|
79
|
+
await bank.initialize();
|
|
80
|
+
const publisher = new SkillPublisher(bank.getStorage());
|
|
81
|
+
|
|
82
|
+
// Build playbooks with disparate success rates
|
|
83
|
+
const playbooks: Playbook[] = [
|
|
84
|
+
pb('hot-skill', 18, 2), // 0.90
|
|
85
|
+
pb('warm-skill', 12, 8), // 0.60
|
|
86
|
+
pb('cold-skill', 1, 9), // 0.10
|
|
87
|
+
pb('lukewarm-skill', 6, 4), // 0.60
|
|
88
|
+
pb('zero-skill', 0, 0), // 0.00 (untested)
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
// Publish every playbook
|
|
92
|
+
for (const p of playbooks) {
|
|
93
|
+
const result = await publisher.publishPlaybook(p);
|
|
94
|
+
expect(result.published).toBe(true);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Rank externally — the new pattern that replaces the removed
|
|
98
|
+
// LoadoutCriteria.minSuccessRate filter
|
|
99
|
+
const ranked = [...playbooks].sort(
|
|
100
|
+
(a, b) => getPlaybookSuccessRate(b) - getPlaybookSuccessRate(a),
|
|
101
|
+
);
|
|
102
|
+
const topThreeIds = ranked.slice(0, 3).map((p) => p.id);
|
|
103
|
+
expect(topThreeIds).toContain('hot-skill');
|
|
104
|
+
expect(topThreeIds).not.toContain('zero-skill');
|
|
105
|
+
expect(topThreeIds).not.toContain('cold-skill');
|
|
106
|
+
|
|
107
|
+
// Pass top-N to skill-tree's compiler via include + maxSkills cap.
|
|
108
|
+
//
|
|
109
|
+
// skill-tree 0.2 makes `include` a presence guarantee — included
|
|
110
|
+
// skills are always in the result, in the order listed. Combine
|
|
111
|
+
// with `maxSkills: include.length` to express "exactly these N
|
|
112
|
+
// skills" (the documented restrict-to-list pattern).
|
|
113
|
+
const compiler = new LoadoutCompiler(bank.getStorage());
|
|
114
|
+
const selected = await compiler.compile({
|
|
115
|
+
include: topThreeIds,
|
|
116
|
+
maxSkills: topThreeIds.length,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// include preserves order; we passed top-1, top-2, top-3
|
|
120
|
+
expect(selected.map((s) => s.id)).toEqual(topThreeIds);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('include preserves caller-specified order from the ranking', async () => {
|
|
124
|
+
const bank = createSkillBank({ storage: { basePath: testDir } });
|
|
125
|
+
await bank.initialize();
|
|
126
|
+
const publisher = new SkillPublisher(bank.getStorage());
|
|
127
|
+
|
|
128
|
+
const playbooks: Playbook[] = [
|
|
129
|
+
pb('alpha', 5, 0), // 1.00
|
|
130
|
+
pb('beta', 3, 1), // 0.75
|
|
131
|
+
pb('gamma', 2, 2), // 0.50
|
|
132
|
+
];
|
|
133
|
+
for (const p of playbooks) {
|
|
134
|
+
await publisher.publishPlaybook(p);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const ranked = [...playbooks].sort(
|
|
138
|
+
(a, b) => getPlaybookSuccessRate(b) - getPlaybookSuccessRate(a),
|
|
139
|
+
);
|
|
140
|
+
const orderedIds = ranked.map((p) => p.id);
|
|
141
|
+
|
|
142
|
+
// skill-tree 0.2 preserves include order — included skills appear
|
|
143
|
+
// at the front in the order listed. This makes include a viable
|
|
144
|
+
// surface for caller-driven ranking.
|
|
145
|
+
const compiler = new LoadoutCompiler(bank.getStorage());
|
|
146
|
+
const selected = await compiler.compile({ include: orderedIds });
|
|
147
|
+
|
|
148
|
+
expect(selected.map((s) => s.id)).toEqual(orderedIds);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('demonstrates why the old minSuccessRate filter was lossy', async () => {
|
|
152
|
+
// The old skill-tree had `LoadoutCriteria.minSuccessRate` which
|
|
153
|
+
// filtered against `Skill.metrics.successRate`, a SNAPSHOT taken at
|
|
154
|
+
// publish time. If the playbook evolved after publish (more
|
|
155
|
+
// successes/failures), the stored snapshot would drift from reality.
|
|
156
|
+
//
|
|
157
|
+
// Now: rank live, then pass IDs. No snapshot, no drift.
|
|
158
|
+
const bank = createSkillBank({ storage: { basePath: testDir } });
|
|
159
|
+
await bank.initialize();
|
|
160
|
+
const publisher = new SkillPublisher(bank.getStorage());
|
|
161
|
+
|
|
162
|
+
const playbook = pb('evolving', 5, 5); // 0.50 at publish
|
|
163
|
+
await publisher.publishPlaybook(playbook);
|
|
164
|
+
|
|
165
|
+
// Drift: more successes after publish — playbook's live rate
|
|
166
|
+
// diverges from anything we could have captured at publish time
|
|
167
|
+
playbook.evolution.successCount = 50;
|
|
168
|
+
playbook.evolution.failureCount = 5;
|
|
169
|
+
const liveRate = getPlaybookSuccessRate(playbook);
|
|
170
|
+
expect(liveRate).toBeCloseTo(50 / 55, 4); // ~0.909
|
|
171
|
+
|
|
172
|
+
// Re-publishing IS the way to refresh; the stored skill content is
|
|
173
|
+
// a frozen snapshot, but we're not relying on metric values inside
|
|
174
|
+
// that snapshot anymore.
|
|
175
|
+
const compiler = new LoadoutCompiler(bank.getStorage());
|
|
176
|
+
const selected = await compiler.compile({ include: ['evolving'] });
|
|
177
|
+
expect(selected).toHaveLength(1);
|
|
178
|
+
expect((selected[0] as Record<string, unknown>).metrics).toBeUndefined();
|
|
179
|
+
|
|
180
|
+
// The "is this skill effective" decision happens upstream — the
|
|
181
|
+
// include caller (cognitive-core consumer) knows liveRate ~0.909
|
|
182
|
+
// and would include this skill in a top-N selection.
|
|
183
|
+
expect(liveRate).toBeGreaterThan(0.7);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E: cognitive-core publishing to skill-tree's FilesystemStorageAdapter.
|
|
3
|
+
*
|
|
4
|
+
* Validates the cross-repo handshake after the skill-tree 0.2 metrics
|
|
5
|
+
* deprecation. Uses real components throughout — no mocks:
|
|
6
|
+
* - real Playbook objects with evolution mutations
|
|
7
|
+
* - real cognitive-core SkillPublisher
|
|
8
|
+
* - real skill-tree FilesystemStorageAdapter (file-backed in temp dir)
|
|
9
|
+
* - real on-disk SKILL.md + .skilltree.json sidecar inspection
|
|
10
|
+
*
|
|
11
|
+
* The contract verified:
|
|
12
|
+
* 1. The published Skill has NO `metrics` field (Phase 2/3 invariant).
|
|
13
|
+
* 2. The on-disk artifacts contain the playbook content but no metric
|
|
14
|
+
* JSON in the sidecar.
|
|
15
|
+
* 3. Reopening the bank and retrieving via getSkill returns the same
|
|
16
|
+
* content with no metrics.
|
|
17
|
+
* 4. Live evolution data still lives on the playbook side — recording
|
|
18
|
+
* success after publish updates the playbook but does NOT update the
|
|
19
|
+
* stored skill (republish required).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
23
|
+
import * as fs from 'node:fs/promises';
|
|
24
|
+
import * as fss from 'node:fs';
|
|
25
|
+
import * as path from 'node:path';
|
|
26
|
+
import * as os from 'node:os';
|
|
27
|
+
|
|
28
|
+
import {
|
|
29
|
+
createPlaybook,
|
|
30
|
+
getPlaybookSuccessRate,
|
|
31
|
+
type Playbook,
|
|
32
|
+
} from '../../src/types/playbook.js';
|
|
33
|
+
import { SkillPublisher, convertPlaybookToSkill } from '../../src/surfacing/skill-publisher.js';
|
|
34
|
+
import { createSkillBank } from 'skill-tree';
|
|
35
|
+
|
|
36
|
+
let testDir: string;
|
|
37
|
+
|
|
38
|
+
beforeEach(async () => {
|
|
39
|
+
testDir = await fs.mkdtemp(path.join(os.tmpdir(), 'cc-publish-fs-e2e-'));
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
afterEach(async () => {
|
|
43
|
+
await fs.rm(testDir, { recursive: true, force: true });
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
function makePlaybook(overrides: Partial<Playbook> = {}): Playbook {
|
|
47
|
+
return createPlaybook({
|
|
48
|
+
id: overrides.id ?? 'pb-test',
|
|
49
|
+
name: overrides.name ?? 'fix-typescript-imports',
|
|
50
|
+
applicability: {
|
|
51
|
+
situations: ['TypeScript ESM build emits "Cannot find module" errors'],
|
|
52
|
+
triggers: ['build error', 'esm migration'],
|
|
53
|
+
antiPatterns: ['CommonJS-only project'],
|
|
54
|
+
domains: ['typescript', 'esm'],
|
|
55
|
+
...overrides.applicability,
|
|
56
|
+
},
|
|
57
|
+
guidance: {
|
|
58
|
+
strategy: 'Add .js extensions to all relative imports',
|
|
59
|
+
tactics: ['Use codemod or sed -i', 'Verify with tsc --noEmit'],
|
|
60
|
+
...overrides.guidance,
|
|
61
|
+
},
|
|
62
|
+
verification: {
|
|
63
|
+
successIndicators: ['tsc --noEmit passes', 'tests run'],
|
|
64
|
+
failureIndicators: [],
|
|
65
|
+
...overrides.verification,
|
|
66
|
+
},
|
|
67
|
+
evolution: {
|
|
68
|
+
version: '1.0.0',
|
|
69
|
+
createdFrom: ['session-init'],
|
|
70
|
+
failures: [],
|
|
71
|
+
refinements: [],
|
|
72
|
+
successCount: 8,
|
|
73
|
+
failureCount: 2,
|
|
74
|
+
lastUsed: new Date('2025-06-01T12:00:00Z'),
|
|
75
|
+
...overrides.evolution,
|
|
76
|
+
},
|
|
77
|
+
confidence: overrides.confidence ?? 0.85,
|
|
78
|
+
...overrides,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
describe('cognitive-core → skill-tree filesystem publish e2e', () => {
|
|
83
|
+
it('publishes a playbook to filesystem storage with no metrics field on disk', async () => {
|
|
84
|
+
const bank = createSkillBank({ storage: { basePath: testDir } });
|
|
85
|
+
await bank.initialize();
|
|
86
|
+
const publisher = new SkillPublisher(bank.getStorage());
|
|
87
|
+
|
|
88
|
+
const playbook = makePlaybook();
|
|
89
|
+
const result = await publisher.publishPlaybook(playbook);
|
|
90
|
+
expect(result.published).toBe(true);
|
|
91
|
+
expect(result.skillId).toBe(playbook.id);
|
|
92
|
+
|
|
93
|
+
// Inspect the on-disk artifacts
|
|
94
|
+
const skillsRoot = path.join(testDir, '.skilltree', 'skills', playbook.id);
|
|
95
|
+
expect(fss.existsSync(skillsRoot)).toBe(true);
|
|
96
|
+
|
|
97
|
+
const skillMd = await fs.readFile(path.join(skillsRoot, 'SKILL.md'), 'utf-8');
|
|
98
|
+
// Frontmatter must NOT carry any metric fields
|
|
99
|
+
expect(skillMd).not.toMatch(/^successRate:/m);
|
|
100
|
+
expect(skillMd).not.toMatch(/^usageCount:/m);
|
|
101
|
+
expect(skillMd).not.toMatch(/^feedbackScores:/m);
|
|
102
|
+
expect(skillMd).not.toMatch(/^lastUsed:/m);
|
|
103
|
+
// Body should carry the playbook's strategy
|
|
104
|
+
expect(skillMd).toContain('Add .js extensions');
|
|
105
|
+
|
|
106
|
+
// Sidecar carries source/lineage but no metrics block
|
|
107
|
+
const sidecar = JSON.parse(
|
|
108
|
+
await fs.readFile(path.join(skillsRoot, '.skilltree.json'), 'utf-8'),
|
|
109
|
+
);
|
|
110
|
+
expect(sidecar.metrics).toBeUndefined();
|
|
111
|
+
expect(sidecar.source?.type).toBe('extracted');
|
|
112
|
+
|
|
113
|
+
await bank.shutdown();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('roundtrips through getSkill without exposing metrics', async () => {
|
|
117
|
+
const bank0 = createSkillBank({ storage: { basePath: testDir } });
|
|
118
|
+
await bank0.initialize();
|
|
119
|
+
const publisher = new SkillPublisher(bank0.getStorage());
|
|
120
|
+
|
|
121
|
+
const playbook = makePlaybook({ id: 'pb-roundtrip' });
|
|
122
|
+
await publisher.publishPlaybook(playbook);
|
|
123
|
+
|
|
124
|
+
// Reopen via SkillBank and retrieve
|
|
125
|
+
const bank = createSkillBank({ storage: { basePath: testDir } });
|
|
126
|
+
await bank.initialize();
|
|
127
|
+
const skill = await bank.getSkill('pb-roundtrip');
|
|
128
|
+
|
|
129
|
+
expect(skill).not.toBeNull();
|
|
130
|
+
expect(skill!.id).toBe('pb-roundtrip');
|
|
131
|
+
expect(skill!.name).toBe('fix-typescript-imports');
|
|
132
|
+
expect(skill!.instructions).toContain('Add .js extensions');
|
|
133
|
+
// Skill-tree 0.2 has no metrics on the type at all
|
|
134
|
+
expect((skill as Record<string, unknown>).metrics).toBeUndefined();
|
|
135
|
+
|
|
136
|
+
await bank.shutdown();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('keeps live evolution data on the playbook after publish (no skill-side mutation on recordSuccess)', async () => {
|
|
140
|
+
const bank0 = createSkillBank({ storage: { basePath: testDir } });
|
|
141
|
+
await bank0.initialize();
|
|
142
|
+
const publisher = new SkillPublisher(bank0.getStorage());
|
|
143
|
+
|
|
144
|
+
const playbook = makePlaybook({ id: 'pb-live-evolution' });
|
|
145
|
+
await publisher.publishPlaybook(playbook);
|
|
146
|
+
|
|
147
|
+
const initialRate = getPlaybookSuccessRate(playbook);
|
|
148
|
+
expect(initialRate).toBe(0.8); // 8 / (8 + 2)
|
|
149
|
+
|
|
150
|
+
// Mutate playbook (this would normally happen via PlaybookLibrary.recordSuccess)
|
|
151
|
+
playbook.evolution.successCount += 5;
|
|
152
|
+
playbook.evolution.lastUsed = new Date();
|
|
153
|
+
playbook.confidence = 0.92;
|
|
154
|
+
|
|
155
|
+
const newRate = getPlaybookSuccessRate(playbook);
|
|
156
|
+
expect(newRate).toBeCloseTo(13 / 15, 4);
|
|
157
|
+
|
|
158
|
+
// Without re-publishing, the stored skill is unchanged — it never
|
|
159
|
+
// tracked the metric values in the first place
|
|
160
|
+
const bank = createSkillBank({ storage: { basePath: testDir } });
|
|
161
|
+
await bank.initialize();
|
|
162
|
+
const skill = await bank.getSkill('pb-live-evolution');
|
|
163
|
+
expect(skill).not.toBeNull();
|
|
164
|
+
expect((skill as Record<string, unknown>).metrics).toBeUndefined();
|
|
165
|
+
// Content is unchanged (same playbook strategy text)
|
|
166
|
+
expect(skill!.instructions).toContain('Add .js extensions');
|
|
167
|
+
await bank.shutdown();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('republishing after evolution updates updates the on-disk skill content', async () => {
|
|
171
|
+
const bank0 = createSkillBank({ storage: { basePath: testDir } });
|
|
172
|
+
await bank0.initialize();
|
|
173
|
+
const publisher = new SkillPublisher(bank0.getStorage());
|
|
174
|
+
|
|
175
|
+
const playbook = makePlaybook({ id: 'pb-republish' });
|
|
176
|
+
await publisher.publishPlaybook(playbook);
|
|
177
|
+
|
|
178
|
+
// Evolve the playbook — add a refinement and bump version
|
|
179
|
+
playbook.evolution.version = '1.1.0';
|
|
180
|
+
playbook.evolution.refinements.push({
|
|
181
|
+
context: 'mixed CJS/ESM project',
|
|
182
|
+
addition: 'Run tsc with --moduleResolution bundler',
|
|
183
|
+
addedAt: new Date(),
|
|
184
|
+
source: 'success',
|
|
185
|
+
});
|
|
186
|
+
playbook.guidance.strategy = 'Add .js extensions; for bundler-resolution projects, prefer the bundler moduleResolution flag';
|
|
187
|
+
|
|
188
|
+
const update = await publisher.publishPlaybook(playbook);
|
|
189
|
+
expect(update.published).toBe(true);
|
|
190
|
+
expect(update.isUpdate).toBe(true);
|
|
191
|
+
expect(update.version).toBe('1.1.0');
|
|
192
|
+
|
|
193
|
+
const bank = createSkillBank({ storage: { basePath: testDir } });
|
|
194
|
+
await bank.initialize();
|
|
195
|
+
const skill = await bank.getSkill('pb-republish');
|
|
196
|
+
expect(skill!.version).toBe('1.1.0');
|
|
197
|
+
expect(skill!.instructions).toContain('bundler moduleResolution');
|
|
198
|
+
expect(skill!.instructions).toContain('Refinements:');
|
|
199
|
+
await bank.shutdown();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('convertPlaybookToSkill does not emit a metrics field at the type level', () => {
|
|
203
|
+
const playbook = makePlaybook({ id: 'pb-shape' });
|
|
204
|
+
const skill = convertPlaybookToSkill(playbook);
|
|
205
|
+
|
|
206
|
+
// Belt-and-suspenders: even at the conversion boundary there should
|
|
207
|
+
// be no metrics field. (TypeScript already enforces this; the
|
|
208
|
+
// runtime check guards against accidental object-spread regressions.)
|
|
209
|
+
expect((skill as Record<string, unknown>).metrics).toBeUndefined();
|
|
210
|
+
expect(skill.id).toBe('pb-shape');
|
|
211
|
+
expect(skill.name).toBe('fix-typescript-imports');
|
|
212
|
+
expect(skill.author).toBe('cognitive-core');
|
|
213
|
+
expect(skill.tags).toEqual(['typescript', 'esm']);
|
|
214
|
+
expect(skill.serving?.tokenEstimate).toBeGreaterThan(0);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
@@ -176,15 +176,9 @@ describe('SkillPublisher', () => {
|
|
|
176
176
|
expect(skill.instructions).toContain('Refinements:');
|
|
177
177
|
});
|
|
178
178
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
expect(skill.metrics.usageCount).toBe(10); // 8 + 2
|
|
184
|
-
expect(skill.metrics.successRate).toBe(0.8); // 8/10
|
|
185
|
-
expect(skill.metrics.averageConfidence).toBe(0.85);
|
|
186
|
-
expect(skill.metrics.lastUsed).toBeDefined();
|
|
187
|
-
});
|
|
179
|
+
// skill-tree >= 0.2 dropped Skill.metrics — usage data lives on
|
|
180
|
+
// playbook.evolution.* in cognitive-core. The publisher no longer
|
|
181
|
+
// emits a metrics snapshot. See SKILL_TREE_METRICS_DEPRECATION plan.
|
|
188
182
|
|
|
189
183
|
it('should include code example in instructions', () => {
|
|
190
184
|
const playbook = createSamplePlaybook();
|
|
@@ -430,8 +424,9 @@ describe('SkillPublisher', () => {
|
|
|
430
424
|
|
|
431
425
|
skill = await storage.getSkill('evolve-1');
|
|
432
426
|
expect(skill!.version).toBe('2.0.0');
|
|
433
|
-
|
|
434
|
-
|
|
427
|
+
// Live evolution data (usageCount, confidence) stays on the
|
|
428
|
+
// playbook in cognitive-core; the published Skill no longer
|
|
429
|
+
// carries metrics snapshots.
|
|
435
430
|
});
|
|
436
431
|
});
|
|
437
432
|
});
|
|
@@ -16,13 +16,6 @@ function createSampleSkill(overrides?: Partial<Skill>): Skill {
|
|
|
16
16
|
author: 'cognitive-core',
|
|
17
17
|
status: 'active',
|
|
18
18
|
tags: ['typescript', 'nodejs'],
|
|
19
|
-
metrics: {
|
|
20
|
-
usageCount: 8,
|
|
21
|
-
successRate: 0.9,
|
|
22
|
-
lastUsed: now,
|
|
23
|
-
feedbackScores: [],
|
|
24
|
-
averageConfidence: 0.85,
|
|
25
|
-
},
|
|
26
19
|
source: {
|
|
27
20
|
type: 'extracted',
|
|
28
21
|
sessionId: 'session-abc',
|
|
@@ -126,8 +119,6 @@ describe('SqliteStorageAdapter', () => {
|
|
|
126
119
|
|
|
127
120
|
const retrieved = await adapter.getSkill('skill-json');
|
|
128
121
|
expect(retrieved!.tags).toEqual(['typescript', 'nodejs']);
|
|
129
|
-
expect(retrieved!.metrics.usageCount).toBe(8);
|
|
130
|
-
expect(retrieved!.metrics.successRate).toBe(0.9);
|
|
131
122
|
expect(retrieved!.source!.type).toBe('extracted');
|
|
132
123
|
expect(retrieved!.serving!.tokenEstimate).toBe(150);
|
|
133
124
|
});
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import type { Trajectory, LearningConfig } from '../types/index.js';
|
|
2
|
-
import type { TrajectoryWithAnalysis } from '../types/trajectory-source.js';
|
|
3
|
-
import type { MemorySystem } from '../memory/system.js';
|
|
4
|
-
import { type AnalysisResult } from './analyzer.js';
|
|
5
|
-
import type { AgenticTaskRunner } from '../workspace/runner.js';
|
|
6
|
-
/**
|
|
7
|
-
* Result of processing a single trajectory
|
|
8
|
-
*/
|
|
9
|
-
export interface ProcessResult {
|
|
10
|
-
trajectoryId: string;
|
|
11
|
-
stored: boolean;
|
|
12
|
-
analysis: AnalysisResult;
|
|
13
|
-
abstractable: boolean;
|
|
14
|
-
playbookExtracted: boolean;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Result of batch learning
|
|
18
|
-
*/
|
|
19
|
-
export interface BatchResult {
|
|
20
|
-
trajectoriesProcessed: number;
|
|
21
|
-
playbooksExtracted: number;
|
|
22
|
-
experiencesPruned: number;
|
|
23
|
-
successRate: number;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Learning Pipeline
|
|
27
|
-
* Orchestrates trajectory analysis, playbook extraction, and memory updates
|
|
28
|
-
*/
|
|
29
|
-
export declare class LearningPipeline {
|
|
30
|
-
private analyzer;
|
|
31
|
-
private playbookExtractor;
|
|
32
|
-
private memory;
|
|
33
|
-
private config;
|
|
34
|
-
private taskRunner;
|
|
35
|
-
private accumulated;
|
|
36
|
-
private accumulatedAnalyses;
|
|
37
|
-
private lastBatchTime;
|
|
38
|
-
constructor(memory: MemorySystem, config?: Partial<LearningConfig>);
|
|
39
|
-
/**
|
|
40
|
-
* Set the agentic task runner for workspace-based analysis.
|
|
41
|
-
* When set, analysis tasks are delegated to templates (with heuristic fallback).
|
|
42
|
-
*/
|
|
43
|
-
setTaskRunner(runner: AgenticTaskRunner): void;
|
|
44
|
-
/**
|
|
45
|
-
* Process a single trajectory
|
|
46
|
-
*/
|
|
47
|
-
processTrajectory(trajectory: Trajectory): Promise<ProcessResult>;
|
|
48
|
-
/**
|
|
49
|
-
* Run trajectory analysis via the workspace template.
|
|
50
|
-
* The template's assessComplexity() routes simple cases to heuristicFallback()
|
|
51
|
-
* (which calls the existing TrajectoryAnalyzer), so this is safe for all inputs.
|
|
52
|
-
*/
|
|
53
|
-
private analyzeWithTemplate;
|
|
54
|
-
/**
|
|
55
|
-
* Check if batch learning should run
|
|
56
|
-
*/
|
|
57
|
-
shouldRunBatch(): boolean;
|
|
58
|
-
/**
|
|
59
|
-
* Run batch learning on accumulated trajectories
|
|
60
|
-
*/
|
|
61
|
-
runBatchLearning(): Promise<BatchResult>;
|
|
62
|
-
/**
|
|
63
|
-
* Run playbook extraction via the workspace template.
|
|
64
|
-
* Falls back to heuristic extractor on failure.
|
|
65
|
-
*/
|
|
66
|
-
private extractPlaybooks;
|
|
67
|
-
/**
|
|
68
|
-
* Get accumulated trajectory count
|
|
69
|
-
*/
|
|
70
|
-
getAccumulatedCount(): number;
|
|
71
|
-
/**
|
|
72
|
-
* Get accumulated trajectories with their analyses.
|
|
73
|
-
* Read-only view — does not clear the accumulator.
|
|
74
|
-
*/
|
|
75
|
-
getAccumulated(): TrajectoryWithAnalysis[];
|
|
76
|
-
/**
|
|
77
|
-
* Clear accumulated trajectories
|
|
78
|
-
*/
|
|
79
|
-
clearAccumulated(): void;
|
|
80
|
-
/**
|
|
81
|
-
* Update configuration
|
|
82
|
-
*/
|
|
83
|
-
updateConfig(config: Partial<LearningConfig>): void;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Create a learning pipeline
|
|
87
|
-
*/
|
|
88
|
-
export declare function createLearningPipeline(memory: MemorySystem, config?: Partial<LearningConfig>): LearningPipeline;
|
|
89
|
-
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/learning/pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,eAAe,CAAC;AAKvB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,cAAc,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,MAAM,CAAiB;IAG/B,OAAO,CAAC,UAAU,CAAkC;IAGpD,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,mBAAmB,CAAwB;IACnD,OAAO,CAAC,aAAa,CAAqB;gBAE9B,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;IAoBlE;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAI9C;;OAEG;IACG,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IAyBvE;;;;OAIG;YACW,mBAAmB;IAiBjC;;OAEG;IACH,cAAc,IAAI,OAAO;IA6BzB;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,WAAW,CAAC;IA4E9C;;;OAGG;YACW,gBAAgB;IA0B9B;;OAEG;IACH,mBAAmB,IAAI,MAAM;IAI7B;;;OAGG;IACH,cAAc,IAAI,sBAAsB,EAAE;IAO1C;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAKxB;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;CAMpD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAC/B,gBAAgB,CAElB"}
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
import { createAnalyzer, } from './analyzer.js';
|
|
2
|
-
import { createPlaybookExtractor, } from './playbook-extractor.js';
|
|
3
|
-
import { trajectoryAnalysisTemplate } from '../workspace/templates/trajectory-analysis.js';
|
|
4
|
-
import { playbookExtractionTemplate } from '../workspace/templates/playbook-extraction.js';
|
|
5
|
-
/**
|
|
6
|
-
* Learning Pipeline
|
|
7
|
-
* Orchestrates trajectory analysis, playbook extraction, and memory updates
|
|
8
|
-
*/
|
|
9
|
-
export class LearningPipeline {
|
|
10
|
-
analyzer;
|
|
11
|
-
playbookExtractor;
|
|
12
|
-
memory;
|
|
13
|
-
config;
|
|
14
|
-
// Optional agentic task runner for workspace-based analysis
|
|
15
|
-
taskRunner = null;
|
|
16
|
-
// Accumulated trajectories for batch learning
|
|
17
|
-
accumulated = [];
|
|
18
|
-
accumulatedAnalyses = [];
|
|
19
|
-
lastBatchTime = null;
|
|
20
|
-
constructor(memory, config) {
|
|
21
|
-
this.memory = memory;
|
|
22
|
-
this.config = {
|
|
23
|
-
creditStrategy: config?.creditStrategy ?? 'simple',
|
|
24
|
-
patternExtractor: config?.patternExtractor ?? 'llm',
|
|
25
|
-
minTrajectories: config?.minTrajectories ?? 10,
|
|
26
|
-
minHoursSinceLast: config?.minHoursSinceLast,
|
|
27
|
-
minSuccessRate: config?.minSuccessRate,
|
|
28
|
-
deduplicationThreshold: config?.deduplicationThreshold ?? 0.9,
|
|
29
|
-
maxExperiences: config?.maxExperiences ?? 1000,
|
|
30
|
-
};
|
|
31
|
-
this.analyzer = createAnalyzer(this.config.creditStrategy);
|
|
32
|
-
this.playbookExtractor = createPlaybookExtractor({
|
|
33
|
-
minTrajectories: this.config.minTrajectories,
|
|
34
|
-
mergeThreshold: this.config.deduplicationThreshold,
|
|
35
|
-
minSuccessRate: this.config.minSuccessRate ?? 0.6,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Set the agentic task runner for workspace-based analysis.
|
|
40
|
-
* When set, analysis tasks are delegated to templates (with heuristic fallback).
|
|
41
|
-
*/
|
|
42
|
-
setTaskRunner(runner) {
|
|
43
|
-
this.taskRunner = runner;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Process a single trajectory
|
|
47
|
-
*/
|
|
48
|
-
async processTrajectory(trajectory) {
|
|
49
|
-
// Store in experience memory
|
|
50
|
-
await this.memory.storeTrajectory(trajectory);
|
|
51
|
-
// Analyze: workspace-based when runner available, heuristic otherwise
|
|
52
|
-
let analysis;
|
|
53
|
-
if (this.taskRunner) {
|
|
54
|
-
analysis = await this.analyzeWithTemplate(trajectory);
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
analysis = await this.analyzer.analyze(trajectory);
|
|
58
|
-
}
|
|
59
|
-
// Accumulate for batch learning
|
|
60
|
-
this.accumulated.push(trajectory);
|
|
61
|
-
this.accumulatedAnalyses.push(analysis);
|
|
62
|
-
return {
|
|
63
|
-
trajectoryId: trajectory.id,
|
|
64
|
-
stored: true,
|
|
65
|
-
analysis,
|
|
66
|
-
abstractable: analysis.abstractable,
|
|
67
|
-
playbookExtracted: false, // Playbooks are extracted in batch
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Run trajectory analysis via the workspace template.
|
|
72
|
-
* The template's assessComplexity() routes simple cases to heuristicFallback()
|
|
73
|
-
* (which calls the existing TrajectoryAnalyzer), so this is safe for all inputs.
|
|
74
|
-
*/
|
|
75
|
-
async analyzeWithTemplate(trajectory) {
|
|
76
|
-
try {
|
|
77
|
-
const result = await this.taskRunner.run(trajectoryAnalysisTemplate, {
|
|
78
|
-
trajectory,
|
|
79
|
-
creditStrategy: this.config.creditStrategy,
|
|
80
|
-
});
|
|
81
|
-
return result.output;
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
// If workspace-based analysis fails, fall back to heuristic
|
|
85
|
-
console.error('Workspace-based trajectory analysis failed, falling back to heuristic:', error instanceof Error ? error.message : error);
|
|
86
|
-
return this.analyzer.analyze(trajectory);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Check if batch learning should run
|
|
91
|
-
*/
|
|
92
|
-
shouldRunBatch() {
|
|
93
|
-
// Check minimum trajectories
|
|
94
|
-
if (this.accumulated.length < this.config.minTrajectories) {
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
// Check time since last batch
|
|
98
|
-
if (this.config.minHoursSinceLast && this.lastBatchTime) {
|
|
99
|
-
const hoursSinceLast = (Date.now() - this.lastBatchTime.getTime()) / (1000 * 60 * 60);
|
|
100
|
-
if (hoursSinceLast < this.config.minHoursSinceLast) {
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
// Check success rate
|
|
105
|
-
if (this.config.minSuccessRate) {
|
|
106
|
-
const successCount = this.accumulatedAnalyses.filter((a) => a.success).length;
|
|
107
|
-
const successRate = successCount / this.accumulated.length;
|
|
108
|
-
if (successRate < this.config.minSuccessRate) {
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return true;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Run batch learning on accumulated trajectories
|
|
116
|
-
*/
|
|
117
|
-
async runBatchLearning() {
|
|
118
|
-
if (this.accumulated.length === 0) {
|
|
119
|
-
return {
|
|
120
|
-
trajectoriesProcessed: 0,
|
|
121
|
-
playbooksExtracted: 0,
|
|
122
|
-
experiencesPruned: 0,
|
|
123
|
-
successRate: 0,
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
// Extract playbooks: workspace-based when runner available, heuristic otherwise
|
|
127
|
-
let playbooksAdded = 0;
|
|
128
|
-
const existingPlaybooks = await this.memory.playbooks.getAll();
|
|
129
|
-
const playbookExtraction = await this.extractPlaybooks(existingPlaybooks);
|
|
130
|
-
// Add new playbooks
|
|
131
|
-
for (const playbook of playbookExtraction.new) {
|
|
132
|
-
const exists = await this.memory.playbooks.exists(playbook.name, this.config.deduplicationThreshold);
|
|
133
|
-
if (!exists) {
|
|
134
|
-
await this.memory.playbooks.add(playbook);
|
|
135
|
-
playbooksAdded++;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
// Apply updates to existing playbooks
|
|
139
|
-
for (const update of playbookExtraction.updates) {
|
|
140
|
-
if (update.refinement) {
|
|
141
|
-
await this.memory.playbooks.addRefinement(update.id, update.refinement.context, update.refinement.addition, update.refinement.source);
|
|
142
|
-
}
|
|
143
|
-
if (update.newTrigger) {
|
|
144
|
-
const playbook = await this.memory.playbooks.get(update.id);
|
|
145
|
-
if (playbook && !playbook.applicability.triggers.includes(update.newTrigger)) {
|
|
146
|
-
playbook.applicability.triggers.push(update.newTrigger);
|
|
147
|
-
await this.memory.playbooks.add(playbook);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
if (update.newAntiPattern) {
|
|
151
|
-
const playbook = await this.memory.playbooks.get(update.id);
|
|
152
|
-
if (playbook && !playbook.applicability.antiPatterns.includes(update.newAntiPattern)) {
|
|
153
|
-
playbook.applicability.antiPatterns.push(update.newAntiPattern);
|
|
154
|
-
await this.memory.playbooks.add(playbook);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
// Prune experiences if needed
|
|
159
|
-
const pruned = await this.memory.experiences.prune({
|
|
160
|
-
maxCount: this.config.maxExperiences,
|
|
161
|
-
});
|
|
162
|
-
// Calculate success rate
|
|
163
|
-
const successCount = this.accumulatedAnalyses.filter((a) => a.success).length;
|
|
164
|
-
const successRate = successCount / this.accumulated.length;
|
|
165
|
-
// Clear accumulated and update time
|
|
166
|
-
const trajectoriesProcessed = this.accumulated.length;
|
|
167
|
-
this.accumulated = [];
|
|
168
|
-
this.accumulatedAnalyses = [];
|
|
169
|
-
this.lastBatchTime = new Date();
|
|
170
|
-
return {
|
|
171
|
-
trajectoriesProcessed,
|
|
172
|
-
playbooksExtracted: playbooksAdded,
|
|
173
|
-
experiencesPruned: pruned.totalPruned,
|
|
174
|
-
successRate,
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Run playbook extraction via the workspace template.
|
|
179
|
-
* Falls back to heuristic extractor on failure.
|
|
180
|
-
*/
|
|
181
|
-
async extractPlaybooks(existingPlaybooks) {
|
|
182
|
-
if (this.taskRunner) {
|
|
183
|
-
try {
|
|
184
|
-
const result = await this.taskRunner.run(playbookExtractionTemplate, {
|
|
185
|
-
trajectories: this.accumulated,
|
|
186
|
-
analyses: this.accumulatedAnalyses,
|
|
187
|
-
existingPlaybooks,
|
|
188
|
-
});
|
|
189
|
-
return result.output;
|
|
190
|
-
}
|
|
191
|
-
catch (error) {
|
|
192
|
-
console.error('Workspace-based playbook extraction failed, falling back to heuristic:', error instanceof Error ? error.message : error);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
return this.playbookExtractor.extract(this.accumulated, this.accumulatedAnalyses, existingPlaybooks);
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Get accumulated trajectory count
|
|
199
|
-
*/
|
|
200
|
-
getAccumulatedCount() {
|
|
201
|
-
return this.accumulated.length;
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Get accumulated trajectories with their analyses.
|
|
205
|
-
* Read-only view — does not clear the accumulator.
|
|
206
|
-
*/
|
|
207
|
-
getAccumulated() {
|
|
208
|
-
return this.accumulated.map((trajectory, i) => ({
|
|
209
|
-
trajectory,
|
|
210
|
-
analysis: this.accumulatedAnalyses[i],
|
|
211
|
-
}));
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Clear accumulated trajectories
|
|
215
|
-
*/
|
|
216
|
-
clearAccumulated() {
|
|
217
|
-
this.accumulated = [];
|
|
218
|
-
this.accumulatedAnalyses = [];
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Update configuration
|
|
222
|
-
*/
|
|
223
|
-
updateConfig(config) {
|
|
224
|
-
this.config = { ...this.config, ...config };
|
|
225
|
-
if (config.creditStrategy) {
|
|
226
|
-
this.analyzer.setStrategy(config.creditStrategy);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Create a learning pipeline
|
|
232
|
-
*/
|
|
233
|
-
export function createLearningPipeline(memory, config) {
|
|
234
|
-
return new LearningPipeline(memory, config);
|
|
235
|
-
}
|
|
236
|
-
//# sourceMappingURL=pipeline.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/learning/pipeline.ts"],"names":[],"mappings":"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"}
|