wyrm-mcp 6.12.0 → 6.14.1
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/auto-capture.d.ts +32 -0
- package/dist/auto-capture.d.ts.map +1 -0
- package/dist/auto-capture.js +136 -0
- package/dist/auto-capture.js.map +1 -0
- package/dist/database.d.ts +61 -3
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +155 -9
- package/dist/database.js.map +1 -1
- package/dist/http-fast.d.ts.map +1 -1
- package/dist/http-fast.js +28 -7
- package/dist/http-fast.js.map +1 -1
- package/dist/http-server.d.ts.map +1 -1
- package/dist/http-server.js +9 -5
- package/dist/http-server.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +209 -20
- package/dist/index.js.map +1 -1
- package/dist/indexer.d.ts.map +1 -1
- package/dist/indexer.js +6 -0
- package/dist/indexer.js.map +1 -1
- package/dist/mcp-client.d.ts.map +1 -1
- package/dist/mcp-client.js +18 -1
- package/dist/mcp-client.js.map +1 -1
- package/dist/memory-artifacts.d.ts.map +1 -1
- package/dist/memory-artifacts.js +13 -3
- package/dist/memory-artifacts.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +50 -0
- package/dist/migrations.js.map +1 -1
- package/dist/resilience.d.ts.map +1 -1
- package/dist/resilience.js +6 -4
- package/dist/resilience.js.map +1 -1
- package/dist/security.d.ts.map +1 -1
- package/dist/security.js +10 -1
- package/dist/security.js.map +1 -1
- package/dist/spec-kit.d.ts +56 -0
- package/dist/spec-kit.d.ts.map +1 -0
- package/dist/spec-kit.js +191 -0
- package/dist/spec-kit.js.map +1 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +5 -2
- package/dist/sync.js.map +1 -1
- package/dist/tool-profiles.d.ts.map +1 -1
- package/dist/tool-profiles.js +3 -0
- package/dist/tool-profiles.js.map +1 -1
- package/dist/vault.d.ts.map +1 -1
- package/dist/vault.js +23 -3
- package/dist/vault.js.map +1 -1
- package/dist/wyrm-cli.js +3 -2
- package/dist/wyrm-cli.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ArtifactKind } from './memory-artifacts.js';
|
|
2
|
+
export type CandidateKind = 'truth' | 'failure' | 'decision' | 'pattern' | 'lesson';
|
|
3
|
+
export interface MemoryCandidate {
|
|
4
|
+
kind: CandidateKind;
|
|
5
|
+
text: string;
|
|
6
|
+
confidence: number;
|
|
7
|
+
}
|
|
8
|
+
export interface ExtractResult {
|
|
9
|
+
candidates: MemoryCandidate[];
|
|
10
|
+
method: 'llm' | 'deterministic';
|
|
11
|
+
model?: string;
|
|
12
|
+
}
|
|
13
|
+
/** Robustly pull a candidate array out of an LLM response (small models wrap JSON in prose/markdown). */
|
|
14
|
+
export declare function parseCandidates(raw: string): MemoryCandidate[];
|
|
15
|
+
/** No-LLM extractor: segment into statements, keep durable-looking ones, classify. */
|
|
16
|
+
export declare function extractDeterministic(text: string): MemoryCandidate[];
|
|
17
|
+
/**
|
|
18
|
+
* Extract candidate memories from text. Tries the configured local LLM first
|
|
19
|
+
* (if any), falls back to deterministic. Never throws.
|
|
20
|
+
*/
|
|
21
|
+
export declare function extractCandidates(text: string, opts?: {
|
|
22
|
+
model?: string;
|
|
23
|
+
ollamaUrl?: string;
|
|
24
|
+
}): Promise<ExtractResult>;
|
|
25
|
+
/** Map a candidate to its review-queue memory-artifact shape (needs_review=1). */
|
|
26
|
+
export declare function candidateToArtifact(c: MemoryCandidate): {
|
|
27
|
+
kind: ArtifactKind;
|
|
28
|
+
problem: string;
|
|
29
|
+
tags: string[];
|
|
30
|
+
confidence: number;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=auto-capture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-capture.d.ts","sourceRoot":"","sources":["../src/auto-capture.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;AACpF,MAAM,WAAW,eAAe;IAAG,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;CAAE;AAC3F,MAAM,WAAW,aAAa;IAAG,UAAU,EAAE,eAAe,EAAE,CAAC;IAAC,MAAM,EAAE,KAAK,GAAG,eAAe,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CAAE;AAoBlH,yGAAyG;AACzG,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,EAAE,CAqB9D;AAgBD,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CAmBpE;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAChD,OAAO,CAAC,aAAa,CAAC,CAQxB;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,eAAe,GAAG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAWnI"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extraction (bet #2) — turn freeform text (a session, notes, a transcript)
|
|
3
|
+
* into candidate memories that land in the REVIEW QUEUE for operator approval.
|
|
4
|
+
*
|
|
5
|
+
* Closes the "just talk, it remembers" gap WITHOUT an expensive cloud LLM, via a
|
|
6
|
+
* pluggable LOCAL extractor:
|
|
7
|
+
* - LLM: any Ollama model (`WYRM_EXTRACT_MODEL`) — the slot the future DragonSpark
|
|
8
|
+
* nano-LLM drops into. Structured JSON out, robustly parsed.
|
|
9
|
+
* - Deterministic fallback: sentence segmentation + signal markers + classifyCapture,
|
|
10
|
+
* used when no model is configured or the LLM is unreachable.
|
|
11
|
+
* Always produces candidates, never blocks a write, never throws. Candidates are
|
|
12
|
+
* stored with needs_review=1 so the operator vets them (wyrm_review) — nothing
|
|
13
|
+
* auto-trusted, matching Wyrm's distillation-queue discipline.
|
|
14
|
+
*
|
|
15
|
+
* @copyright 2024-2026 Ghost Protocol (Pvt) Ltd.
|
|
16
|
+
* @license AGPL-3.0-or-later — dual-licensed; commercial terms: ghosts.lk@proton.me. See LICENSE.
|
|
17
|
+
*/
|
|
18
|
+
import { classifyCapture } from './capture.js';
|
|
19
|
+
const KINDS = ['truth', 'failure', 'decision', 'pattern', 'lesson'];
|
|
20
|
+
const EXTRACT_PROMPT = (text) => `You extract DURABLE, REUSABLE memories from a developer's working notes/transcript.
|
|
21
|
+
Output ONLY a JSON array, no prose. Each item: {"kind": one of ["truth","failure","decision","pattern","lesson"], "text": "<one self-contained sentence>"}.
|
|
22
|
+
- truth: a validated fact/constraint ("X uses Y", "Z is required").
|
|
23
|
+
- failure: an approach that FAILED and why (so it is not repeated).
|
|
24
|
+
- decision: a choice made + the reason ("chose A because B").
|
|
25
|
+
- pattern: a reusable approach that worked.
|
|
26
|
+
- lesson: a general insight learned.
|
|
27
|
+
Skip chit-chat, questions, and ephemeral status. Extract 0-8 items; fewer + higher-quality wins. If nothing durable, output [].
|
|
28
|
+
|
|
29
|
+
NOTES:
|
|
30
|
+
"""
|
|
31
|
+
${text.slice(0, 8000)}
|
|
32
|
+
"""
|
|
33
|
+
JSON:`;
|
|
34
|
+
/** Robustly pull a candidate array out of an LLM response (small models wrap JSON in prose/markdown). */
|
|
35
|
+
export function parseCandidates(raw) {
|
|
36
|
+
const m = raw.match(/\[[\s\S]*\]/);
|
|
37
|
+
if (!m)
|
|
38
|
+
return [];
|
|
39
|
+
let arr;
|
|
40
|
+
try {
|
|
41
|
+
arr = JSON.parse(m[0]);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
if (!Array.isArray(arr))
|
|
47
|
+
return [];
|
|
48
|
+
const out = [];
|
|
49
|
+
const seen = new Set();
|
|
50
|
+
for (const it of arr) {
|
|
51
|
+
if (!it || typeof it !== 'object')
|
|
52
|
+
continue;
|
|
53
|
+
const kind = it.kind;
|
|
54
|
+
const text = it.text;
|
|
55
|
+
if (typeof text !== 'string' || text.trim().length < 8)
|
|
56
|
+
continue;
|
|
57
|
+
const t = text.trim().slice(0, 1000);
|
|
58
|
+
const key = t.toLowerCase().replace(/\s+/g, ' ').slice(0, 80);
|
|
59
|
+
if (seen.has(key))
|
|
60
|
+
continue;
|
|
61
|
+
seen.add(key);
|
|
62
|
+
out.push({ kind: KINDS.includes(kind) ? kind : 'pattern', text: t, confidence: 0.6 });
|
|
63
|
+
if (out.length >= 12)
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
async function extractViaLLM(text, model, url) {
|
|
69
|
+
try {
|
|
70
|
+
const res = await fetch(`${url.replace(/\/$/, '')}/api/generate`, {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: { 'Content-Type': 'application/json' },
|
|
73
|
+
body: JSON.stringify({ model, prompt: EXTRACT_PROMPT(text), stream: false, options: { temperature: 0 } }),
|
|
74
|
+
signal: AbortSignal.timeout(120_000),
|
|
75
|
+
});
|
|
76
|
+
if (!res.ok)
|
|
77
|
+
return null;
|
|
78
|
+
const data = await res.json();
|
|
79
|
+
return data.response ? parseCandidates(data.response) : null;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** No-LLM extractor: segment into statements, keep durable-looking ones, classify. */
|
|
86
|
+
export function extractDeterministic(text) {
|
|
87
|
+
const segs = text.split(/(?<=[.!?])\s+|\n+/).map((s) => s.trim()).filter((s) => s.length >= 20 && s.length <= 400);
|
|
88
|
+
const out = [];
|
|
89
|
+
const seen = new Set();
|
|
90
|
+
for (const s of segs) {
|
|
91
|
+
if (!/\b(use[sd]?|decided|because|fail(s|ed)?|error|always|never|must|should|learned|lesson|turned out|prefer|avoid|root cause|fixed|broke|requires?)\b/i.test(s))
|
|
92
|
+
continue;
|
|
93
|
+
const key = s.toLowerCase().replace(/\s+/g, ' ').slice(0, 80);
|
|
94
|
+
if (seen.has(key))
|
|
95
|
+
continue;
|
|
96
|
+
seen.add(key);
|
|
97
|
+
const c = classifyCapture(s);
|
|
98
|
+
const kind = /\b(fail(s|ed)?|error|broke|bug|mistake)\b/i.test(s) ? 'failure'
|
|
99
|
+
: c.type === 'truth' ? 'truth'
|
|
100
|
+
: /\bbecause\b/i.test(s) ? 'decision'
|
|
101
|
+
: c.subtype === 'lesson' ? 'lesson'
|
|
102
|
+
: 'pattern';
|
|
103
|
+
out.push({ kind, text: s, confidence: (c.confidence ?? 60) / 100 });
|
|
104
|
+
if (out.length >= 8)
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Extract candidate memories from text. Tries the configured local LLM first
|
|
111
|
+
* (if any), falls back to deterministic. Never throws.
|
|
112
|
+
*/
|
|
113
|
+
export async function extractCandidates(text, opts = {}) {
|
|
114
|
+
const url = opts.ollamaUrl || process.env.WYRM_OLLAMA_URL || 'http://localhost:11434';
|
|
115
|
+
const model = opts.model || process.env.WYRM_EXTRACT_MODEL || '';
|
|
116
|
+
if (model) {
|
|
117
|
+
const llm = await extractViaLLM(text, model, url);
|
|
118
|
+
if (llm && llm.length)
|
|
119
|
+
return { candidates: llm, method: 'llm', model };
|
|
120
|
+
}
|
|
121
|
+
return { candidates: extractDeterministic(text), method: 'deterministic' };
|
|
122
|
+
}
|
|
123
|
+
/** Map a candidate to its review-queue memory-artifact shape (needs_review=1). */
|
|
124
|
+
export function candidateToArtifact(c) {
|
|
125
|
+
const map = {
|
|
126
|
+
failure: 'anti_pattern',
|
|
127
|
+
decision: 'reasoning_trace',
|
|
128
|
+
lesson: 'lesson',
|
|
129
|
+
pattern: 'pattern',
|
|
130
|
+
truth: 'heuristic',
|
|
131
|
+
};
|
|
132
|
+
// A stable signature for dedup against re-extraction of the same text.
|
|
133
|
+
const sig = 'ax:' + c.text.toLowerCase().replace(/\s+/g, ' ').trim().slice(0, 64);
|
|
134
|
+
return { kind: map[c.kind], problem: c.text, tags: ['auto-extract', `intent:${c.kind}`, sig], confidence: c.confidence };
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=auto-capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-capture.js","sourceRoot":"","sources":["../src/auto-capture.ts"],"names":[],"mappings":"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"}
|
package/dist/database.d.ts
CHANGED
|
@@ -81,12 +81,41 @@ export interface Skill {
|
|
|
81
81
|
author?: string;
|
|
82
82
|
version?: string;
|
|
83
83
|
tags?: string;
|
|
84
|
+
/** GOD-SKILL SPEC v2 apex tier: 'atomic' (default) | 'mega' | 'god'. */
|
|
85
|
+
tier: 'atomic' | 'mega' | 'god';
|
|
86
|
+
/** JSON string array of skill names this node governs (routes DOWN to). */
|
|
87
|
+
governs?: string;
|
|
88
|
+
/** JSON string array of skill names this node composes (pulls in laterally). */
|
|
89
|
+
composes?: string;
|
|
84
90
|
is_active: boolean;
|
|
85
91
|
usage_count: number;
|
|
86
92
|
last_used?: string;
|
|
87
93
|
created_at: string;
|
|
88
94
|
updated_at: string;
|
|
89
95
|
}
|
|
96
|
+
/** A registered spec-kit spec directory linked to a project. */
|
|
97
|
+
export interface Spec {
|
|
98
|
+
id: number;
|
|
99
|
+
project_id: number;
|
|
100
|
+
spec_dir: string;
|
|
101
|
+
title?: string;
|
|
102
|
+
summary?: string;
|
|
103
|
+
task_count: number;
|
|
104
|
+
created_at: string;
|
|
105
|
+
updated_at: string;
|
|
106
|
+
}
|
|
107
|
+
/** A node in the skill governance graph (god → mega → atomic). */
|
|
108
|
+
export interface SkillGraphNode {
|
|
109
|
+
name: string;
|
|
110
|
+
tier: 'atomic' | 'mega' | 'god';
|
|
111
|
+
description: string;
|
|
112
|
+
governs: string[];
|
|
113
|
+
composes: string[];
|
|
114
|
+
/** Resolved child nodes (only the governed ones that exist as registered skills). */
|
|
115
|
+
children: SkillGraphNode[];
|
|
116
|
+
/** True when a governs/composes target name is not a registered skill. */
|
|
117
|
+
missing?: string[];
|
|
118
|
+
}
|
|
90
119
|
export declare class WyrmDB {
|
|
91
120
|
private db;
|
|
92
121
|
private readonly BATCH_SIZE;
|
|
@@ -163,10 +192,23 @@ export declare class WyrmDB {
|
|
|
163
192
|
setGlobalContext(key: string, value: string): void;
|
|
164
193
|
getGlobalContext(key: string): string | undefined;
|
|
165
194
|
getAllGlobalContext(): Record<string, string>;
|
|
166
|
-
registerSkill(name: string, description: string, skillPath: string, category?: string, author?: string, version?: string, tags?: string
|
|
195
|
+
registerSkill(name: string, description: string, skillPath: string, category?: string, author?: string, version?: string, tags?: string, governance?: {
|
|
196
|
+
tier?: 'atomic' | 'mega' | 'god';
|
|
197
|
+
governs?: string[];
|
|
198
|
+
composes?: string[];
|
|
199
|
+
}): Skill;
|
|
167
200
|
getSkill(name: string): Skill | undefined;
|
|
168
|
-
listSkills(active?: boolean, category?: string, search?: string): Skill[];
|
|
169
|
-
searchSkills(query: string, limit?: number): Skill[];
|
|
201
|
+
listSkills(active?: boolean, category?: string, search?: string, tier?: 'atomic' | 'mega' | 'god'): Skill[];
|
|
202
|
+
searchSkills(query: string, limit?: number, tier?: 'atomic' | 'mega' | 'god'): Skill[];
|
|
203
|
+
/**
|
|
204
|
+
* Build the GOD-SKILL SPEC v2 governance graph.
|
|
205
|
+
*
|
|
206
|
+
* Walks tier routing edges: a node's `governs` list names the skills it routes
|
|
207
|
+
* DOWN to (god → mega → atomic). Each node also exposes its `composes` list
|
|
208
|
+
* (lateral pull-ins). When `root` is given, returns that single tree; otherwise
|
|
209
|
+
* returns a forest of every 'god' tier skill (the apexes). Cycle-safe.
|
|
210
|
+
*/
|
|
211
|
+
getSkillGraph(root?: string): SkillGraphNode[];
|
|
170
212
|
updateSkill(name: string, updates: Partial<Skill>): Skill | undefined;
|
|
171
213
|
deleteSkill(name: string): boolean;
|
|
172
214
|
deactivateSkill(name: string): Skill | undefined;
|
|
@@ -176,6 +218,22 @@ export declare class WyrmDB {
|
|
|
176
218
|
active: number;
|
|
177
219
|
byCategory: Record<string, number>;
|
|
178
220
|
};
|
|
221
|
+
/** Upsert a spec→project link (idempotent by project_id + spec_dir). */
|
|
222
|
+
upsertSpec(projectId: number, specDir: string, title?: string, summary?: string, taskCount?: number): Spec;
|
|
223
|
+
getSpec(projectId: number, specDir: string): Spec | undefined;
|
|
224
|
+
listSpecs(projectId?: number): Spec[];
|
|
225
|
+
/**
|
|
226
|
+
* Find an existing quest for a project carrying a specific spec-task tag
|
|
227
|
+
* signature. Used by wyrm_spec_register to dedupe (update-not-duplicate) on
|
|
228
|
+
* re-run. The signature lives in the quest's comma-separated `tags` column.
|
|
229
|
+
*/
|
|
230
|
+
findQuestBySpecSignature(projectId: number, signature: string): Quest | undefined;
|
|
231
|
+
/** Update a quest's title/description/tags in place (used by spec re-registration). */
|
|
232
|
+
updateQuestFields(id: number, fields: {
|
|
233
|
+
title?: string;
|
|
234
|
+
description?: string;
|
|
235
|
+
tags?: string;
|
|
236
|
+
}): Quest | undefined;
|
|
179
237
|
insertData(projectId: number, category: string, key: string, value: string, metadata?: Record<string, unknown>): DataPoint;
|
|
180
238
|
/**
|
|
181
239
|
* Batch insert with resilience - uses checkpointing for large batches
|
package/dist/database.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"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"}
|
package/dist/database.js
CHANGED
|
@@ -553,10 +553,15 @@ export class WyrmDB {
|
|
|
553
553
|
return result;
|
|
554
554
|
}
|
|
555
555
|
// ==================== SKILLS MANAGEMENT ====================
|
|
556
|
-
registerSkill(name, description, skillPath, category, author, version, tags) {
|
|
556
|
+
registerSkill(name, description, skillPath, category, author, version, tags, governance) {
|
|
557
|
+
// Normalize governance to safe defaults so existing callers (no 8th arg)
|
|
558
|
+
// keep producing 'atomic' / '[]' / '[]' — fully backward-compatible.
|
|
559
|
+
const tier = governance?.tier ?? 'atomic';
|
|
560
|
+
const governsJson = JSON.stringify(Array.isArray(governance?.governs) ? governance.governs : []);
|
|
561
|
+
const composesJson = JSON.stringify(Array.isArray(governance?.composes) ? governance.composes : []);
|
|
557
562
|
const result = this.resilience.withRetrySync(() => this.db.prepare(`
|
|
558
|
-
INSERT INTO skills (name, description, skill_path, category, author, version, tags, is_active, usage_count)
|
|
559
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, 1, 0)
|
|
563
|
+
INSERT INTO skills (name, description, skill_path, category, author, version, tags, tier, governs, composes, is_active, usage_count)
|
|
564
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0)
|
|
560
565
|
ON CONFLICT(name) DO UPDATE SET
|
|
561
566
|
description = excluded.description,
|
|
562
567
|
skill_path = excluded.skill_path,
|
|
@@ -564,10 +569,13 @@ export class WyrmDB {
|
|
|
564
569
|
author = excluded.author,
|
|
565
570
|
version = excluded.version,
|
|
566
571
|
tags = excluded.tags,
|
|
572
|
+
tier = excluded.tier,
|
|
573
|
+
governs = excluded.governs,
|
|
574
|
+
composes = excluded.composes,
|
|
567
575
|
updated_at = datetime('now'),
|
|
568
576
|
is_active = 1
|
|
569
577
|
RETURNING *
|
|
570
|
-
`).get(name, description, skillPath, category || null, author || null, version || null, tags || null), 'registerSkill');
|
|
578
|
+
`).get(name, description, skillPath, category || null, author || null, version || null, tags || null, tier, governsJson, composesJson), 'registerSkill');
|
|
571
579
|
if (!result.success) {
|
|
572
580
|
throw result.error || new Error('Failed to register skill');
|
|
573
581
|
}
|
|
@@ -581,7 +589,7 @@ export class WyrmDB {
|
|
|
581
589
|
}
|
|
582
590
|
return skill;
|
|
583
591
|
}
|
|
584
|
-
listSkills(active, category, search) {
|
|
592
|
+
listSkills(active, category, search, tier) {
|
|
585
593
|
let query = 'SELECT * FROM skills WHERE 1=1';
|
|
586
594
|
const params = [];
|
|
587
595
|
if (active !== undefined) {
|
|
@@ -592,6 +600,10 @@ export class WyrmDB {
|
|
|
592
600
|
query += ' AND category = ?';
|
|
593
601
|
params.push(category);
|
|
594
602
|
}
|
|
603
|
+
if (tier) {
|
|
604
|
+
query += ' AND tier = ?';
|
|
605
|
+
params.push(tier);
|
|
606
|
+
}
|
|
595
607
|
if (search) {
|
|
596
608
|
const match = buildFtsMatchQuery(search);
|
|
597
609
|
if (match) {
|
|
@@ -602,17 +614,90 @@ export class WyrmDB {
|
|
|
602
614
|
query += ' ORDER BY updated_at DESC';
|
|
603
615
|
return this.db.prepare(query).all(...params);
|
|
604
616
|
}
|
|
605
|
-
searchSkills(query, limit = 20) {
|
|
617
|
+
searchSkills(query, limit = 20, tier) {
|
|
606
618
|
const match = buildFtsMatchQuery(query);
|
|
607
619
|
if (!match)
|
|
608
620
|
return [];
|
|
609
|
-
|
|
621
|
+
// Optional tier filter is applied in SQL so the FTS rank ordering is preserved.
|
|
622
|
+
const tierClause = tier ? ' AND s.tier = ?' : '';
|
|
623
|
+
const stmt = this.db.prepare(`
|
|
610
624
|
SELECT s.* FROM skills s
|
|
611
625
|
JOIN skills_fts ON s.id = skills_fts.rowid
|
|
612
|
-
WHERE skills_fts MATCH
|
|
626
|
+
WHERE skills_fts MATCH ?${tierClause}
|
|
613
627
|
ORDER BY rank
|
|
614
628
|
LIMIT ?
|
|
615
|
-
`)
|
|
629
|
+
`);
|
|
630
|
+
return (tier ? stmt.all(match, tier, limit) : stmt.all(match, limit));
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Build the GOD-SKILL SPEC v2 governance graph.
|
|
634
|
+
*
|
|
635
|
+
* Walks tier routing edges: a node's `governs` list names the skills it routes
|
|
636
|
+
* DOWN to (god → mega → atomic). Each node also exposes its `composes` list
|
|
637
|
+
* (lateral pull-ins). When `root` is given, returns that single tree; otherwise
|
|
638
|
+
* returns a forest of every 'god' tier skill (the apexes). Cycle-safe.
|
|
639
|
+
*/
|
|
640
|
+
getSkillGraph(root) {
|
|
641
|
+
const all = this.db.prepare('SELECT * FROM skills').all();
|
|
642
|
+
const byName = new Map();
|
|
643
|
+
for (const s of all)
|
|
644
|
+
byName.set(s.name, s);
|
|
645
|
+
const parseArr = (v) => {
|
|
646
|
+
if (!v)
|
|
647
|
+
return [];
|
|
648
|
+
try {
|
|
649
|
+
const parsed = JSON.parse(v);
|
|
650
|
+
return Array.isArray(parsed) ? parsed.filter((x) => typeof x === 'string') : [];
|
|
651
|
+
}
|
|
652
|
+
catch {
|
|
653
|
+
return [];
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
const build = (name, seen) => {
|
|
657
|
+
const skill = byName.get(name);
|
|
658
|
+
if (!skill)
|
|
659
|
+
return null;
|
|
660
|
+
const governs = parseArr(skill.governs);
|
|
661
|
+
const composes = parseArr(skill.composes);
|
|
662
|
+
const node = {
|
|
663
|
+
name: skill.name,
|
|
664
|
+
tier: skill.tier ?? 'atomic',
|
|
665
|
+
description: skill.description,
|
|
666
|
+
governs,
|
|
667
|
+
composes,
|
|
668
|
+
children: [],
|
|
669
|
+
};
|
|
670
|
+
const missing = [];
|
|
671
|
+
if (!seen.has(name)) {
|
|
672
|
+
const nextSeen = new Set(seen).add(name);
|
|
673
|
+
for (const childName of governs) {
|
|
674
|
+
const child = build(childName, nextSeen);
|
|
675
|
+
if (child)
|
|
676
|
+
node.children.push(child);
|
|
677
|
+
else
|
|
678
|
+
missing.push(childName);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
if (missing.length)
|
|
682
|
+
node.missing = missing;
|
|
683
|
+
return node;
|
|
684
|
+
};
|
|
685
|
+
if (root) {
|
|
686
|
+
const node = build(root, new Set());
|
|
687
|
+
return node ? [node] : [];
|
|
688
|
+
}
|
|
689
|
+
// No root → forest of all god-tier apexes (deterministic by name).
|
|
690
|
+
const gods = all
|
|
691
|
+
.filter((s) => (s.tier ?? 'atomic') === 'god')
|
|
692
|
+
.map((s) => s.name)
|
|
693
|
+
.sort();
|
|
694
|
+
const forest = [];
|
|
695
|
+
for (const g of gods) {
|
|
696
|
+
const node = build(g, new Set());
|
|
697
|
+
if (node)
|
|
698
|
+
forest.push(node);
|
|
699
|
+
}
|
|
700
|
+
return forest;
|
|
616
701
|
}
|
|
617
702
|
updateSkill(name, updates) {
|
|
618
703
|
const setClauses = [];
|
|
@@ -672,6 +757,67 @@ export class WyrmDB {
|
|
|
672
757
|
}
|
|
673
758
|
return { total, active, byCategory };
|
|
674
759
|
}
|
|
760
|
+
// ==================== SPEC-KIT REGISTRY ====================
|
|
761
|
+
/** Upsert a spec→project link (idempotent by project_id + spec_dir). */
|
|
762
|
+
upsertSpec(projectId, specDir, title, summary, taskCount = 0) {
|
|
763
|
+
return this.db.prepare(`
|
|
764
|
+
INSERT INTO specs (project_id, spec_dir, title, summary, task_count)
|
|
765
|
+
VALUES (?, ?, ?, ?, ?)
|
|
766
|
+
ON CONFLICT(project_id, spec_dir) DO UPDATE SET
|
|
767
|
+
title = excluded.title,
|
|
768
|
+
summary = excluded.summary,
|
|
769
|
+
task_count = excluded.task_count,
|
|
770
|
+
updated_at = datetime('now')
|
|
771
|
+
RETURNING *
|
|
772
|
+
`).get(projectId, specDir, title || null, summary || null, taskCount);
|
|
773
|
+
}
|
|
774
|
+
getSpec(projectId, specDir) {
|
|
775
|
+
return this.db.prepare('SELECT * FROM specs WHERE project_id = ? AND spec_dir = ?').get(projectId, specDir);
|
|
776
|
+
}
|
|
777
|
+
listSpecs(projectId) {
|
|
778
|
+
if (projectId !== undefined) {
|
|
779
|
+
return this.db.prepare('SELECT * FROM specs WHERE project_id = ? ORDER BY updated_at DESC').all(projectId);
|
|
780
|
+
}
|
|
781
|
+
return this.db.prepare('SELECT * FROM specs ORDER BY updated_at DESC').all();
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* Find an existing quest for a project carrying a specific spec-task tag
|
|
785
|
+
* signature. Used by wyrm_spec_register to dedupe (update-not-duplicate) on
|
|
786
|
+
* re-run. The signature lives in the quest's comma-separated `tags` column.
|
|
787
|
+
*/
|
|
788
|
+
findQuestBySpecSignature(projectId, signature) {
|
|
789
|
+
return this.db.prepare(`
|
|
790
|
+
SELECT * FROM quests
|
|
791
|
+
WHERE project_id = ?
|
|
792
|
+
AND (tags = ? OR tags LIKE ? OR tags LIKE ? OR tags LIKE ?)
|
|
793
|
+
LIMIT 1
|
|
794
|
+
`).get(projectId, signature, `${signature},%`, `%,${signature}`, `%,${signature},%`);
|
|
795
|
+
}
|
|
796
|
+
/** Update a quest's title/description/tags in place (used by spec re-registration). */
|
|
797
|
+
updateQuestFields(id, fields) {
|
|
798
|
+
const setClauses = [];
|
|
799
|
+
const values = [];
|
|
800
|
+
if (fields.title !== undefined) {
|
|
801
|
+
setClauses.push('title = ?');
|
|
802
|
+
values.push(fields.title);
|
|
803
|
+
}
|
|
804
|
+
if (fields.description !== undefined) {
|
|
805
|
+
setClauses.push('description = ?');
|
|
806
|
+
values.push(fields.description);
|
|
807
|
+
}
|
|
808
|
+
if (fields.tags !== undefined) {
|
|
809
|
+
setClauses.push('tags = ?');
|
|
810
|
+
values.push(fields.tags);
|
|
811
|
+
}
|
|
812
|
+
if (setClauses.length === 0) {
|
|
813
|
+
return this.db.prepare('SELECT * FROM quests WHERE id = ?').get(id);
|
|
814
|
+
}
|
|
815
|
+
values.push(id);
|
|
816
|
+
const quest = this.db.prepare(`UPDATE quests SET ${setClauses.join(', ')} WHERE id = ? RETURNING *`).get(...values);
|
|
817
|
+
if (quest)
|
|
818
|
+
emitEvent(this.db, { projectId: quest.project_id, kind: 'quest', refTable: 'quests', refId: id });
|
|
819
|
+
return quest;
|
|
820
|
+
}
|
|
675
821
|
// ==================== DATA LAKE ====================
|
|
676
822
|
insertData(projectId, category, key, value, metadata) {
|
|
677
823
|
const result = this.resilience.withRetrySync(() => this.db.prepare(`
|