@soleri/core 2.12.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/flows/build.flow.yaml +128 -0
- package/data/flows/deliver.flow.yaml +110 -0
- package/data/flows/design.flow.yaml +108 -0
- package/data/flows/enhance.flow.yaml +90 -0
- package/data/flows/explore.flow.yaml +84 -0
- package/data/flows/fix.flow.yaml +90 -0
- package/data/flows/plan.flow.yaml +87 -0
- package/data/flows/review.flow.yaml +90 -0
- package/dist/brain/intelligence.d.ts.map +1 -1
- package/dist/brain/intelligence.js +16 -2
- package/dist/brain/intelligence.js.map +1 -1
- package/dist/capabilities/chain-mapping.d.ts +21 -0
- package/dist/capabilities/chain-mapping.d.ts.map +1 -0
- package/dist/capabilities/chain-mapping.js +86 -0
- package/dist/capabilities/chain-mapping.js.map +1 -0
- package/dist/capabilities/index.d.ts +10 -0
- package/dist/capabilities/index.d.ts.map +1 -0
- package/dist/capabilities/index.js +8 -0
- package/dist/capabilities/index.js.map +1 -0
- package/dist/capabilities/registry.d.ts +95 -0
- package/dist/capabilities/registry.d.ts.map +1 -0
- package/dist/capabilities/registry.js +227 -0
- package/dist/capabilities/registry.js.map +1 -0
- package/dist/capabilities/types.d.ts +106 -0
- package/dist/capabilities/types.d.ts.map +1 -0
- package/dist/capabilities/types.js +12 -0
- package/dist/capabilities/types.js.map +1 -0
- package/dist/control/intent-router.d.ts.map +1 -1
- package/dist/control/intent-router.js +58 -2
- package/dist/control/intent-router.js.map +1 -1
- package/dist/domain-packs/index.d.ts +8 -0
- package/dist/domain-packs/index.d.ts.map +1 -0
- package/dist/domain-packs/index.js +8 -0
- package/dist/domain-packs/index.js.map +1 -0
- package/dist/domain-packs/inject-rules.d.ts +24 -0
- package/dist/domain-packs/inject-rules.d.ts.map +1 -0
- package/dist/domain-packs/inject-rules.js +65 -0
- package/dist/domain-packs/inject-rules.js.map +1 -0
- package/dist/domain-packs/knowledge-installer.d.ts +27 -0
- package/dist/domain-packs/knowledge-installer.d.ts.map +1 -0
- package/dist/domain-packs/knowledge-installer.js +89 -0
- package/dist/domain-packs/knowledge-installer.js.map +1 -0
- package/dist/domain-packs/loader.d.ts +28 -0
- package/dist/domain-packs/loader.d.ts.map +1 -0
- package/dist/domain-packs/loader.js +105 -0
- package/dist/domain-packs/loader.js.map +1 -0
- package/dist/domain-packs/pack-runtime.d.ts +80 -0
- package/dist/domain-packs/pack-runtime.d.ts.map +1 -0
- package/dist/domain-packs/pack-runtime.js +36 -0
- package/dist/domain-packs/pack-runtime.js.map +1 -0
- package/dist/domain-packs/skills-installer.d.ts +21 -0
- package/dist/domain-packs/skills-installer.d.ts.map +1 -0
- package/dist/domain-packs/skills-installer.js +38 -0
- package/dist/domain-packs/skills-installer.js.map +1 -0
- package/dist/domain-packs/token-resolver.d.ts +37 -0
- package/dist/domain-packs/token-resolver.d.ts.map +1 -0
- package/dist/domain-packs/token-resolver.js +109 -0
- package/dist/domain-packs/token-resolver.js.map +1 -0
- package/dist/domain-packs/types.d.ts +91 -0
- package/dist/domain-packs/types.d.ts.map +1 -0
- package/dist/domain-packs/types.js +122 -0
- package/dist/domain-packs/types.js.map +1 -0
- package/dist/engine/bin/soleri-engine.d.ts +12 -0
- package/dist/engine/bin/soleri-engine.d.ts.map +1 -0
- package/dist/engine/bin/soleri-engine.js +183 -0
- package/dist/engine/bin/soleri-engine.js.map +1 -0
- package/dist/engine/core-ops.d.ts +27 -0
- package/dist/engine/core-ops.d.ts.map +1 -0
- package/dist/engine/core-ops.js +159 -0
- package/dist/engine/core-ops.js.map +1 -0
- package/dist/engine/index.d.ts +19 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +17 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/register-engine.d.ts +54 -0
- package/dist/engine/register-engine.d.ts.map +1 -0
- package/dist/engine/register-engine.js +270 -0
- package/dist/engine/register-engine.js.map +1 -0
- package/dist/engine/test-helpers.d.ts +30 -0
- package/dist/engine/test-helpers.d.ts.map +1 -0
- package/dist/engine/test-helpers.js +59 -0
- package/dist/engine/test-helpers.js.map +1 -0
- package/dist/flows/context-router.d.ts +39 -0
- package/dist/flows/context-router.d.ts.map +1 -0
- package/dist/flows/context-router.js +206 -0
- package/dist/flows/context-router.js.map +1 -0
- package/dist/flows/dispatch-registry.d.ts +24 -0
- package/dist/flows/dispatch-registry.d.ts.map +1 -0
- package/dist/flows/dispatch-registry.js +70 -0
- package/dist/flows/dispatch-registry.js.map +1 -0
- package/dist/flows/epilogue.d.ts +24 -0
- package/dist/flows/epilogue.d.ts.map +1 -0
- package/dist/flows/epilogue.js +52 -0
- package/dist/flows/epilogue.js.map +1 -0
- package/dist/flows/executor.d.ts +25 -0
- package/dist/flows/executor.d.ts.map +1 -0
- package/dist/flows/executor.js +153 -0
- package/dist/flows/executor.js.map +1 -0
- package/dist/flows/gate-evaluator.d.ts +26 -0
- package/dist/flows/gate-evaluator.d.ts.map +1 -0
- package/dist/flows/gate-evaluator.js +162 -0
- package/dist/flows/gate-evaluator.js.map +1 -0
- package/dist/flows/index.d.ts +14 -0
- package/dist/flows/index.d.ts.map +1 -0
- package/dist/flows/index.js +20 -0
- package/dist/flows/index.js.map +1 -0
- package/dist/flows/loader.d.ts +17 -0
- package/dist/flows/loader.d.ts.map +1 -0
- package/dist/flows/loader.js +61 -0
- package/dist/flows/loader.js.map +1 -0
- package/dist/flows/plan-builder.d.ts +40 -0
- package/dist/flows/plan-builder.d.ts.map +1 -0
- package/dist/flows/plan-builder.js +213 -0
- package/dist/flows/plan-builder.js.map +1 -0
- package/dist/flows/probes.d.ts +11 -0
- package/dist/flows/probes.d.ts.map +1 -0
- package/dist/flows/probes.js +62 -0
- package/dist/flows/probes.js.map +1 -0
- package/dist/flows/types.d.ts +950 -0
- package/dist/flows/types.d.ts.map +1 -0
- package/dist/flows/types.js +105 -0
- package/dist/flows/types.js.map +1 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/intelligence/loader.d.ts +19 -0
- package/dist/intelligence/loader.d.ts.map +1 -1
- package/dist/intelligence/loader.js +35 -0
- package/dist/intelligence/loader.js.map +1 -1
- package/dist/intelligence/types.d.ts +1 -0
- package/dist/intelligence/types.d.ts.map +1 -1
- package/dist/packs/types.d.ts +58 -19
- package/dist/packs/types.d.ts.map +1 -1
- package/dist/packs/types.js +14 -0
- package/dist/packs/types.js.map +1 -1
- package/dist/playbooks/generic/onboarding.d.ts +9 -0
- package/dist/playbooks/generic/onboarding.d.ts.map +1 -0
- package/dist/playbooks/generic/onboarding.js +74 -0
- package/dist/playbooks/generic/onboarding.js.map +1 -0
- package/dist/playbooks/playbook-registry.d.ts.map +1 -1
- package/dist/playbooks/playbook-registry.js +2 -0
- package/dist/playbooks/playbook-registry.js.map +1 -1
- package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
- package/dist/runtime/admin-extra-ops.js +15 -9
- package/dist/runtime/admin-extra-ops.js.map +1 -1
- package/dist/runtime/admin-ops.js +4 -4
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/capture-ops.d.ts.map +1 -1
- package/dist/runtime/capture-ops.js +33 -1
- package/dist/runtime/capture-ops.js.map +1 -1
- package/dist/runtime/domain-ops.d.ts +21 -5
- package/dist/runtime/domain-ops.d.ts.map +1 -1
- package/dist/runtime/domain-ops.js +64 -6
- package/dist/runtime/domain-ops.js.map +1 -1
- package/dist/runtime/facades/cognee-facade.d.ts.map +1 -1
- package/dist/runtime/facades/cognee-facade.js +3 -1
- package/dist/runtime/facades/cognee-facade.js.map +1 -1
- package/dist/runtime/facades/index.d.ts.map +1 -1
- package/dist/runtime/facades/index.js +10 -6
- package/dist/runtime/facades/index.js.map +1 -1
- package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
- package/dist/runtime/facades/vault-facade.js +2 -0
- package/dist/runtime/facades/vault-facade.js.map +1 -1
- package/dist/runtime/orchestrate-ops.d.ts +8 -7
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
- package/dist/runtime/orchestrate-ops.js +217 -61
- package/dist/runtime/orchestrate-ops.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +23 -17
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +6 -2
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/vault-linking-ops.d.ts +13 -0
- package/dist/runtime/vault-linking-ops.d.ts.map +1 -0
- package/dist/runtime/vault-linking-ops.js +367 -0
- package/dist/runtime/vault-linking-ops.js.map +1 -0
- package/dist/vault/linking.d.ts +46 -0
- package/dist/vault/linking.d.ts.map +1 -0
- package/dist/vault/linking.js +275 -0
- package/dist/vault/linking.js.map +1 -0
- package/dist/vault/vault-types.d.ts +37 -0
- package/dist/vault/vault-types.d.ts.map +1 -1
- package/dist/vault/vault.d.ts +12 -0
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +85 -6
- package/dist/vault/vault.js.map +1 -1
- package/package.json +4 -1
- package/src/__tests__/admin-extra-ops.test.ts +1 -1
- package/src/__tests__/admin-ops.test.ts +2 -1
- package/src/__tests__/cognee-client-gaps.test.ts +470 -0
- package/src/__tests__/cognee-hybrid-search.test.ts +478 -0
- package/src/__tests__/cognee-sync-manager-deep.test.ts +630 -0
- package/src/__tests__/cognee-sync-manager.test.ts +1 -0
- package/src/__tests__/core-ops.test.ts +9 -61
- package/src/__tests__/domain-packs.test.ts +421 -0
- package/src/__tests__/flows.test.ts +604 -0
- package/src/__tests__/playbook-registry.test.ts +2 -2
- package/src/__tests__/playbook-seeder.test.ts +8 -8
- package/src/__tests__/playbook.test.ts +5 -5
- package/src/__tests__/token-resolver.test.ts +79 -0
- package/src/brain/intelligence.ts +21 -2
- package/src/capabilities/chain-mapping.ts +93 -0
- package/src/capabilities/index.ts +21 -0
- package/src/capabilities/registry.ts +290 -0
- package/src/capabilities/types.ts +143 -0
- package/src/control/intent-router.ts +46 -2
- package/src/domain-packs/index.ts +27 -0
- package/src/domain-packs/inject-rules.ts +74 -0
- package/src/domain-packs/knowledge-installer.ts +116 -0
- package/src/domain-packs/loader.ts +124 -0
- package/src/domain-packs/pack-runtime.ts +99 -0
- package/src/domain-packs/skills-installer.ts +56 -0
- package/src/domain-packs/token-resolver.ts +126 -0
- package/src/domain-packs/types.ts +229 -0
- package/src/engine/__tests__/register-engine.test.ts +104 -0
- package/src/engine/bin/soleri-engine.ts +217 -0
- package/src/engine/core-ops.ts +178 -0
- package/src/engine/index.ts +19 -0
- package/src/engine/register-engine.ts +385 -0
- package/src/engine/test-helpers.ts +83 -0
- package/src/flows/context-router.ts +257 -0
- package/src/flows/dispatch-registry.ts +80 -0
- package/src/flows/epilogue.ts +65 -0
- package/src/flows/executor.ts +182 -0
- package/src/flows/gate-evaluator.ts +171 -0
- package/src/flows/index.ts +52 -0
- package/src/flows/loader.ts +63 -0
- package/src/flows/plan-builder.ts +250 -0
- package/src/flows/probes.ts +70 -0
- package/src/flows/types.ts +217 -0
- package/src/index.ts +68 -1
- package/src/intelligence/loader.ts +38 -0
- package/src/intelligence/types.ts +1 -0
- package/src/packs/types.ts +19 -0
- package/src/playbooks/generic/onboarding.ts +79 -0
- package/src/playbooks/playbook-registry.ts +2 -0
- package/src/runtime/admin-extra-ops.ts +14 -8
- package/src/runtime/admin-ops.ts +4 -4
- package/src/runtime/capture-ops.ts +40 -1
- package/src/runtime/domain-ops.ts +71 -5
- package/src/runtime/facades/cognee-facade.ts +3 -1
- package/src/runtime/facades/index.ts +12 -6
- package/src/runtime/facades/vault-facade.ts +2 -0
- package/src/runtime/orchestrate-ops.ts +261 -65
- package/src/runtime/runtime.ts +27 -18
- package/src/runtime/types.ts +6 -2
- package/src/runtime/vault-linking-ops.ts +454 -0
- package/src/vault/linking.ts +333 -0
- package/src/vault/vault-types.ts +46 -0
- package/src/vault/vault.ts +94 -7
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LinkManager — Zettelkasten bidirectional linking for vault entries.
|
|
3
|
+
*
|
|
4
|
+
* Provides typed links between entries (supports, contradicts, extends, sequences),
|
|
5
|
+
* backlink traversal, graph walking, orphan detection, and link suggestions via FTS5.
|
|
6
|
+
*
|
|
7
|
+
* Ported from Salvador MCP with improvements:
|
|
8
|
+
* - Uses PersistenceProvider (not raw SQLite) for backend abstraction
|
|
9
|
+
* - Uses FTS5 for suggest_links (Salvador used TF-IDF cosine similarity)
|
|
10
|
+
* - Graceful degradation — all methods return empty on table-not-found
|
|
11
|
+
*/
|
|
12
|
+
export class LinkManager {
|
|
13
|
+
provider;
|
|
14
|
+
initialized = false;
|
|
15
|
+
constructor(provider) {
|
|
16
|
+
this.provider = provider;
|
|
17
|
+
this.ensureTable();
|
|
18
|
+
}
|
|
19
|
+
// ===========================================================================
|
|
20
|
+
// SCHEMA
|
|
21
|
+
// ===========================================================================
|
|
22
|
+
ensureTable() {
|
|
23
|
+
if (this.initialized)
|
|
24
|
+
return;
|
|
25
|
+
try {
|
|
26
|
+
this.provider.execSql(`
|
|
27
|
+
CREATE TABLE IF NOT EXISTS vault_links (
|
|
28
|
+
source_id TEXT NOT NULL REFERENCES entries(id) ON DELETE CASCADE,
|
|
29
|
+
target_id TEXT NOT NULL REFERENCES entries(id) ON DELETE CASCADE,
|
|
30
|
+
link_type TEXT NOT NULL CHECK(link_type IN ('supports', 'contradicts', 'extends', 'sequences')),
|
|
31
|
+
note TEXT,
|
|
32
|
+
created_at INTEGER NOT NULL,
|
|
33
|
+
PRIMARY KEY (source_id, target_id)
|
|
34
|
+
);
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_links_target ON vault_links(target_id);
|
|
36
|
+
CREATE INDEX IF NOT EXISTS idx_links_type ON vault_links(link_type);
|
|
37
|
+
`);
|
|
38
|
+
this.initialized = true;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// Table may already exist or DB may be read-only — degrade gracefully
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// ===========================================================================
|
|
45
|
+
// CRUD
|
|
46
|
+
// ===========================================================================
|
|
47
|
+
/** Create a typed link between two entries. */
|
|
48
|
+
addLink(sourceId, targetId, linkType, note) {
|
|
49
|
+
this.provider.run(`INSERT OR REPLACE INTO vault_links (source_id, target_id, link_type, note, created_at)
|
|
50
|
+
VALUES (?, ?, ?, ?, ?)`, [sourceId, targetId, linkType, note ?? null, Date.now()]);
|
|
51
|
+
}
|
|
52
|
+
/** Remove a link between two entries. */
|
|
53
|
+
removeLink(sourceId, targetId) {
|
|
54
|
+
this.provider.run('DELETE FROM vault_links WHERE source_id = ? AND target_id = ?', [
|
|
55
|
+
sourceId,
|
|
56
|
+
targetId,
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
/** Get all outgoing links FROM an entry. */
|
|
60
|
+
getLinks(entryId) {
|
|
61
|
+
try {
|
|
62
|
+
const rows = this.provider.all('SELECT * FROM vault_links WHERE source_id = ?', [entryId]);
|
|
63
|
+
return rows.map(rowToVaultLink);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** Get all incoming links TO an entry (backlinks). */
|
|
70
|
+
getBacklinks(entryId) {
|
|
71
|
+
try {
|
|
72
|
+
const rows = this.provider.all('SELECT * FROM vault_links WHERE target_id = ?', [entryId]);
|
|
73
|
+
return rows.map(rowToVaultLink);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Get total link count (outgoing + incoming). */
|
|
80
|
+
getLinkCount(entryId) {
|
|
81
|
+
try {
|
|
82
|
+
const row = this.provider.get('SELECT COUNT(*) as count FROM vault_links WHERE source_id = ? OR target_id = ?', [entryId, entryId]);
|
|
83
|
+
return row?.count ?? 0;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// ===========================================================================
|
|
90
|
+
// GRAPH TRAVERSAL
|
|
91
|
+
// ===========================================================================
|
|
92
|
+
/**
|
|
93
|
+
* Walk the link graph from a starting entry up to `depth` hops.
|
|
94
|
+
* Returns all connected entries with link metadata.
|
|
95
|
+
* BFS — walks both outgoing and incoming links (undirected).
|
|
96
|
+
*/
|
|
97
|
+
traverse(entryId, depth = 2) {
|
|
98
|
+
const visited = new Set([entryId]);
|
|
99
|
+
const result = [];
|
|
100
|
+
let frontier = [entryId];
|
|
101
|
+
for (let d = 0; d < depth && frontier.length > 0; d++) {
|
|
102
|
+
const nextFrontier = [];
|
|
103
|
+
for (const currentId of frontier) {
|
|
104
|
+
// Outgoing
|
|
105
|
+
for (const link of this.getLinks(currentId)) {
|
|
106
|
+
if (!visited.has(link.targetId)) {
|
|
107
|
+
visited.add(link.targetId);
|
|
108
|
+
nextFrontier.push(link.targetId);
|
|
109
|
+
const entry = this.getEntryMeta(link.targetId);
|
|
110
|
+
if (entry) {
|
|
111
|
+
result.push({
|
|
112
|
+
...entry,
|
|
113
|
+
linkType: link.linkType,
|
|
114
|
+
linkDirection: 'outgoing',
|
|
115
|
+
linkNote: link.note,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Incoming
|
|
121
|
+
for (const link of this.getBacklinks(currentId)) {
|
|
122
|
+
if (!visited.has(link.sourceId)) {
|
|
123
|
+
visited.add(link.sourceId);
|
|
124
|
+
nextFrontier.push(link.sourceId);
|
|
125
|
+
const entry = this.getEntryMeta(link.sourceId);
|
|
126
|
+
if (entry) {
|
|
127
|
+
result.push({
|
|
128
|
+
...entry,
|
|
129
|
+
linkType: link.linkType,
|
|
130
|
+
linkDirection: 'incoming',
|
|
131
|
+
linkNote: link.note,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
frontier = nextFrontier;
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
// ===========================================================================
|
|
142
|
+
// ORPHAN DETECTION
|
|
143
|
+
// ===========================================================================
|
|
144
|
+
/** Find entries with zero links. */
|
|
145
|
+
getOrphans(limit = 50) {
|
|
146
|
+
try {
|
|
147
|
+
return this.provider.all(`SELECT id, title, type, domain FROM entries
|
|
148
|
+
WHERE id NOT IN (SELECT source_id FROM vault_links)
|
|
149
|
+
AND id NOT IN (SELECT target_id FROM vault_links)
|
|
150
|
+
ORDER BY updated_at DESC LIMIT ?`, [limit]);
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// ===========================================================================
|
|
157
|
+
// LINK SUGGESTIONS (FTS5-powered — improvement over Salvador's TF-IDF)
|
|
158
|
+
// ===========================================================================
|
|
159
|
+
/** Find semantically similar entries as link candidates using FTS5. */
|
|
160
|
+
suggestLinks(entryId, limit = 5) {
|
|
161
|
+
try {
|
|
162
|
+
// Get the entry to build a search query
|
|
163
|
+
const entry = this.provider.get('SELECT title, description, type, tags FROM entries WHERE id = ?', [entryId]);
|
|
164
|
+
if (!entry)
|
|
165
|
+
return [];
|
|
166
|
+
// Build FTS query from entry content — extract significant keywords only.
|
|
167
|
+
// FTS5 MATCH chokes on long raw text; use top keywords joined with OR.
|
|
168
|
+
const rawWords = `${entry.title} ${entry.description}`
|
|
169
|
+
.replace(/[^\w\s]/g, ' ')
|
|
170
|
+
.toLowerCase()
|
|
171
|
+
.split(/\s+/)
|
|
172
|
+
.filter((w) => w.length > 2);
|
|
173
|
+
// Deduplicate and take top 10 most significant words (skip common stop words)
|
|
174
|
+
const stopWords = new Set([
|
|
175
|
+
'the',
|
|
176
|
+
'and',
|
|
177
|
+
'for',
|
|
178
|
+
'with',
|
|
179
|
+
'from',
|
|
180
|
+
'this',
|
|
181
|
+
'that',
|
|
182
|
+
'are',
|
|
183
|
+
'was',
|
|
184
|
+
'not',
|
|
185
|
+
'but',
|
|
186
|
+
'have',
|
|
187
|
+
'has',
|
|
188
|
+
'use',
|
|
189
|
+
'can',
|
|
190
|
+
'will',
|
|
191
|
+
'all',
|
|
192
|
+
'each',
|
|
193
|
+
'than',
|
|
194
|
+
'its',
|
|
195
|
+
'more',
|
|
196
|
+
'when',
|
|
197
|
+
'into',
|
|
198
|
+
'also',
|
|
199
|
+
'any',
|
|
200
|
+
'may',
|
|
201
|
+
'only',
|
|
202
|
+
'should',
|
|
203
|
+
'which',
|
|
204
|
+
]);
|
|
205
|
+
const unique = [...new Set(rawWords)].filter((w) => !stopWords.has(w));
|
|
206
|
+
const keywords = unique.slice(0, 10);
|
|
207
|
+
if (keywords.length === 0)
|
|
208
|
+
return [];
|
|
209
|
+
const queryTerms = keywords.join(' OR ');
|
|
210
|
+
// FTS5 match with BM25 ranking
|
|
211
|
+
const matches = this.provider.all(`SELECT e.id, e.title, e.type, e.domain, rank
|
|
212
|
+
FROM entries_fts fts
|
|
213
|
+
JOIN entries e ON e.rowid = fts.rowid
|
|
214
|
+
WHERE entries_fts MATCH ?
|
|
215
|
+
ORDER BY rank
|
|
216
|
+
LIMIT ?`, [queryTerms, limit + 5]);
|
|
217
|
+
// Filter out self and already-linked entries
|
|
218
|
+
const existingLinks = new Set([
|
|
219
|
+
...this.getLinks(entryId).map((l) => l.targetId),
|
|
220
|
+
...this.getBacklinks(entryId).map((l) => l.sourceId),
|
|
221
|
+
]);
|
|
222
|
+
return matches
|
|
223
|
+
.filter((m) => m.id !== entryId && !existingLinks.has(m.id))
|
|
224
|
+
.slice(0, limit)
|
|
225
|
+
.map((m) => {
|
|
226
|
+
const suggestedType = inferLinkType(entry.type, m.type);
|
|
227
|
+
return {
|
|
228
|
+
entryId: m.id,
|
|
229
|
+
title: m.title,
|
|
230
|
+
type: m.type,
|
|
231
|
+
score: Math.abs(m.rank), // FTS5 rank is negative (lower = better)
|
|
232
|
+
suggestedType,
|
|
233
|
+
reason: `${m.type} in ${m.domain}`,
|
|
234
|
+
};
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
return [];
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// ===========================================================================
|
|
242
|
+
// PRIVATE
|
|
243
|
+
// ===========================================================================
|
|
244
|
+
getEntryMeta(entryId) {
|
|
245
|
+
try {
|
|
246
|
+
const row = this.provider.get('SELECT id, title, type, domain FROM entries WHERE id = ?', [entryId]);
|
|
247
|
+
return row ?? null;
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// =============================================================================
|
|
255
|
+
// HELPERS
|
|
256
|
+
// =============================================================================
|
|
257
|
+
function rowToVaultLink(row) {
|
|
258
|
+
return {
|
|
259
|
+
sourceId: row.source_id,
|
|
260
|
+
targetId: row.target_id,
|
|
261
|
+
linkType: row.link_type,
|
|
262
|
+
note: row.note ?? undefined,
|
|
263
|
+
createdAt: row.created_at,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function inferLinkType(sourceType, targetType) {
|
|
267
|
+
if (sourceType === 'pattern' && targetType === 'anti-pattern')
|
|
268
|
+
return 'contradicts';
|
|
269
|
+
if (sourceType === 'anti-pattern' && targetType === 'pattern')
|
|
270
|
+
return 'contradicts';
|
|
271
|
+
if (targetType === 'rule')
|
|
272
|
+
return 'supports';
|
|
273
|
+
return 'extends';
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=linking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linking.js","sourceRoot":"","sources":["../../src/vault/linking.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,4 +27,41 @@ export interface VaultTierInfo {
|
|
|
27
27
|
connected: boolean;
|
|
28
28
|
entryCount: number;
|
|
29
29
|
}
|
|
30
|
+
/** Typed relationship between two vault entries. */
|
|
31
|
+
export type LinkType = 'supports' | 'contradicts' | 'extends' | 'sequences';
|
|
32
|
+
/** A directional, typed link between two vault entries. */
|
|
33
|
+
export interface VaultLink {
|
|
34
|
+
sourceId: string;
|
|
35
|
+
targetId: string;
|
|
36
|
+
linkType: LinkType;
|
|
37
|
+
note?: string;
|
|
38
|
+
createdAt: number;
|
|
39
|
+
}
|
|
40
|
+
/** Raw SQLite row from vault_links table. */
|
|
41
|
+
export interface VaultLinkRow {
|
|
42
|
+
source_id: string;
|
|
43
|
+
target_id: string;
|
|
44
|
+
link_type: string;
|
|
45
|
+
note: string | null;
|
|
46
|
+
created_at: number;
|
|
47
|
+
}
|
|
48
|
+
/** Entry enriched with link context for graph traversal results. */
|
|
49
|
+
export interface LinkedEntry {
|
|
50
|
+
id: string;
|
|
51
|
+
title: string;
|
|
52
|
+
type: string;
|
|
53
|
+
domain: string;
|
|
54
|
+
linkType: LinkType;
|
|
55
|
+
linkDirection: 'outgoing' | 'incoming';
|
|
56
|
+
linkNote?: string;
|
|
57
|
+
}
|
|
58
|
+
/** Suggested link candidate from semantic/FTS similarity. */
|
|
59
|
+
export interface LinkSuggestion {
|
|
60
|
+
entryId: string;
|
|
61
|
+
title: string;
|
|
62
|
+
type: string;
|
|
63
|
+
score: number;
|
|
64
|
+
suggestedType: LinkType;
|
|
65
|
+
reason: string;
|
|
66
|
+
}
|
|
30
67
|
//# sourceMappingURL=vault-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vault-types.d.ts","sourceRoot":"","sources":["../../src/vault/vault-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,gEAAgE;AAChE,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAErD,0EAA0E;AAC1E,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAIlD,CAAC;AAMF,6CAA6C;AAC7C,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,CAAC;IAChB,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;IAC1B,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;CAC9C;AAMD,iDAAiD;AACjD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB"}
|
|
1
|
+
{"version":3,"file":"vault-types.d.ts","sourceRoot":"","sources":["../../src/vault/vault-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,gEAAgE;AAChE,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAErD,0EAA0E;AAC1E,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAIlD,CAAC;AAMF,6CAA6C;AAC7C,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,CAAC;IAChB,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;IAC1B,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;CAC9C;AAMD,iDAAiD;AACjD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD,oDAAoD;AACpD,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,GAAG,WAAW,CAAC;AAE5E,2DAA2D;AAC3D,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,6CAA6C;AAC7C,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,EAAE,UAAU,GAAG,UAAU,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,6DAA6D;AAC7D,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,QAAQ,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB"}
|
package/dist/vault/vault.d.ts
CHANGED
|
@@ -48,9 +48,19 @@ export declare class Vault {
|
|
|
48
48
|
private initialize;
|
|
49
49
|
private migrateTierColumn;
|
|
50
50
|
private migrateTemporalSchema;
|
|
51
|
+
private migrateOriginColumn;
|
|
51
52
|
private migrateContentHash;
|
|
52
53
|
private migrateBrainSchema;
|
|
53
54
|
seed(entries: IntelligenceEntry[]): number;
|
|
55
|
+
/**
|
|
56
|
+
* Install a knowledge pack — seeds entries with origin:'pack' and content-hash dedup.
|
|
57
|
+
* Packs are installable domain knowledge (UX laws, design tokens, clean code rules).
|
|
58
|
+
* Unlike seed(), this forces origin:'pack' regardless of what the entry says.
|
|
59
|
+
*/
|
|
60
|
+
installPack(entries: IntelligenceEntry[]): {
|
|
61
|
+
installed: number;
|
|
62
|
+
skipped: number;
|
|
63
|
+
};
|
|
54
64
|
/**
|
|
55
65
|
* Seed entries with content-hash dedup. Returns per-entry results.
|
|
56
66
|
* Unlike seed(), skips entries whose content already exists in the vault.
|
|
@@ -64,6 +74,7 @@ export declare class Vault {
|
|
|
64
74
|
domain?: string;
|
|
65
75
|
type?: string;
|
|
66
76
|
severity?: string;
|
|
77
|
+
origin?: 'agent' | 'pack' | 'user';
|
|
67
78
|
limit?: number;
|
|
68
79
|
includeExpired?: boolean;
|
|
69
80
|
}): SearchResult[];
|
|
@@ -72,6 +83,7 @@ export declare class Vault {
|
|
|
72
83
|
domain?: string;
|
|
73
84
|
type?: string;
|
|
74
85
|
severity?: string;
|
|
86
|
+
origin?: 'agent' | 'pack' | 'user';
|
|
75
87
|
tags?: string[];
|
|
76
88
|
limit?: number;
|
|
77
89
|
offset?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../../src/vault/vault.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,iBAAiB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AACD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AACD,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AACD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,cAAc,CAAmC;IACzD,OAAO,CAAC,WAAW,CAAsE;IAEzF;;OAEG;gBACS,cAAc,GAAE,mBAAmB,GAAG,MAAmB;IAiBrE,cAAc,CAAC,GAAG,EAAE,OAAO,2BAA2B,EAAE,iBAAiB,GAAG,IAAI;IAIhF,mCAAmC;IACnC,MAAM,CAAC,gBAAgB,CAAC,MAAM,GAAE,MAAmB,GAAG,KAAK;IAI3D,OAAO,CAAC,UAAU;
|
|
1
|
+
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../../src/vault/vault.ts"],"names":[],"mappings":"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"}
|
package/dist/vault/vault.js
CHANGED
|
@@ -137,6 +137,7 @@ export class Vault {
|
|
|
137
137
|
`);
|
|
138
138
|
this.migrateBrainSchema();
|
|
139
139
|
this.migrateTemporalSchema();
|
|
140
|
+
this.migrateOriginColumn();
|
|
140
141
|
this.migrateContentHash();
|
|
141
142
|
this.migrateTierColumn();
|
|
142
143
|
}
|
|
@@ -163,6 +164,15 @@ export class Vault {
|
|
|
163
164
|
// Column already exists
|
|
164
165
|
}
|
|
165
166
|
}
|
|
167
|
+
migrateOriginColumn() {
|
|
168
|
+
try {
|
|
169
|
+
this.provider.run("ALTER TABLE entries ADD COLUMN origin TEXT NOT NULL DEFAULT 'user' CHECK(origin IN ('agent', 'pack', 'user'))");
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
// Column already exists
|
|
173
|
+
}
|
|
174
|
+
this.provider.execSql('CREATE INDEX IF NOT EXISTS idx_entries_origin ON entries(origin)');
|
|
175
|
+
}
|
|
166
176
|
migrateContentHash() {
|
|
167
177
|
try {
|
|
168
178
|
this.provider.run('ALTER TABLE entries ADD COLUMN content_hash TEXT');
|
|
@@ -233,12 +243,12 @@ export class Vault {
|
|
|
233
243
|
}
|
|
234
244
|
seed(entries) {
|
|
235
245
|
const sql = `
|
|
236
|
-
INSERT INTO entries (id,type,domain,title,severity,description,context,example,counter_example,why,tags,applies_to,valid_from,valid_until,content_hash,tier)
|
|
237
|
-
VALUES (@id,@type,@domain,@title,@severity,@description,@context,@example,@counterExample,@why,@tags,@appliesTo,@validFrom,@validUntil,@contentHash,@tier)
|
|
246
|
+
INSERT INTO entries (id,type,domain,title,severity,description,context,example,counter_example,why,tags,applies_to,valid_from,valid_until,content_hash,tier,origin)
|
|
247
|
+
VALUES (@id,@type,@domain,@title,@severity,@description,@context,@example,@counterExample,@why,@tags,@appliesTo,@validFrom,@validUntil,@contentHash,@tier,@origin)
|
|
238
248
|
ON CONFLICT(id) DO UPDATE SET type=excluded.type,domain=excluded.domain,title=excluded.title,severity=excluded.severity,
|
|
239
249
|
description=excluded.description,context=excluded.context,example=excluded.example,counter_example=excluded.counter_example,
|
|
240
250
|
why=excluded.why,tags=excluded.tags,applies_to=excluded.applies_to,valid_from=excluded.valid_from,valid_until=excluded.valid_until,
|
|
241
|
-
content_hash=excluded.content_hash,tier=excluded.tier,updated_at=unixepoch()
|
|
251
|
+
content_hash=excluded.content_hash,tier=excluded.tier,origin=excluded.origin,updated_at=unixepoch()
|
|
242
252
|
`;
|
|
243
253
|
return this.provider.transaction(() => {
|
|
244
254
|
let count = 0;
|
|
@@ -260,6 +270,7 @@ export class Vault {
|
|
|
260
270
|
validUntil: entry.validUntil ?? null,
|
|
261
271
|
contentHash: computeContentHash(entry),
|
|
262
272
|
tier: entry.tier ?? 'agent',
|
|
273
|
+
origin: entry.origin ?? 'agent',
|
|
263
274
|
});
|
|
264
275
|
count++;
|
|
265
276
|
if (this.syncManager) {
|
|
@@ -269,6 +280,25 @@ export class Vault {
|
|
|
269
280
|
return count;
|
|
270
281
|
});
|
|
271
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Install a knowledge pack — seeds entries with origin:'pack' and content-hash dedup.
|
|
285
|
+
* Packs are installable domain knowledge (UX laws, design tokens, clean code rules).
|
|
286
|
+
* Unlike seed(), this forces origin:'pack' regardless of what the entry says.
|
|
287
|
+
*/
|
|
288
|
+
installPack(entries) {
|
|
289
|
+
let installed = 0;
|
|
290
|
+
let skipped = 0;
|
|
291
|
+
// Tag all entries with origin:'pack' and seed — seed() handles its own transaction
|
|
292
|
+
const tagged = entries.map((e) => ({ ...e, origin: 'pack' }));
|
|
293
|
+
const results = this.seedDedup(tagged);
|
|
294
|
+
for (const r of results) {
|
|
295
|
+
if (r.action === 'inserted')
|
|
296
|
+
installed++;
|
|
297
|
+
else
|
|
298
|
+
skipped++;
|
|
299
|
+
}
|
|
300
|
+
return { installed, skipped };
|
|
301
|
+
}
|
|
272
302
|
/**
|
|
273
303
|
* Seed entries with content-hash dedup. Returns per-entry results.
|
|
274
304
|
* Unlike seed(), skips entries whose content already exists in the vault.
|
|
@@ -306,6 +336,10 @@ export class Vault {
|
|
|
306
336
|
filters.push('e.severity = @severity');
|
|
307
337
|
fp.severity = options.severity;
|
|
308
338
|
}
|
|
339
|
+
if (options?.origin) {
|
|
340
|
+
filters.push('e.origin = @origin');
|
|
341
|
+
fp.origin = options.origin;
|
|
342
|
+
}
|
|
309
343
|
if (!options?.includeExpired) {
|
|
310
344
|
const now = Math.floor(Date.now() / 1000);
|
|
311
345
|
filters.push('(e.valid_until IS NULL OR e.valid_until > @now)');
|
|
@@ -313,12 +347,24 @@ export class Vault {
|
|
|
313
347
|
fp.now = now;
|
|
314
348
|
}
|
|
315
349
|
const wc = filters.length > 0 ? `AND ${filters.join(' AND ')}` : '';
|
|
350
|
+
// Build FTS5 query: use OR between terms for broader matching,
|
|
351
|
+
// with title column boosted 3x for relevance ranking.
|
|
352
|
+
// FTS5 BM25 with default AND degrades with more entries because
|
|
353
|
+
// fewer documents match ALL terms simultaneously.
|
|
354
|
+
const ftsQuery = buildFtsQuery(query);
|
|
316
355
|
try {
|
|
317
|
-
const rows = this.provider.all(`SELECT e.*,
|
|
356
|
+
const rows = this.provider.all(`SELECT e.*, bm25(entries_fts, 5.0, 10.0, 3.0, 1.0, 2.0) as score FROM entries_fts fts JOIN entries e ON e.rowid = fts.rowid WHERE entries_fts MATCH @query ${wc} ORDER BY score ASC LIMIT @limit`, { query: ftsQuery, limit, ...fp });
|
|
318
357
|
return rows.map(rowToSearchResult);
|
|
319
358
|
}
|
|
320
359
|
catch {
|
|
321
|
-
|
|
360
|
+
// Fallback: try original query if FTS5 syntax fails
|
|
361
|
+
try {
|
|
362
|
+
const rows = this.provider.all(`SELECT e.*, -rank as score FROM entries_fts fts JOIN entries e ON e.rowid = fts.rowid WHERE entries_fts MATCH @query ${wc} ORDER BY score DESC LIMIT @limit`, { query, limit, ...fp });
|
|
363
|
+
return rows.map(rowToSearchResult);
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
return [];
|
|
367
|
+
}
|
|
322
368
|
}
|
|
323
369
|
}
|
|
324
370
|
get(id) {
|
|
@@ -342,6 +388,10 @@ export class Vault {
|
|
|
342
388
|
filters.push('severity = @severity');
|
|
343
389
|
params.severity = options.severity;
|
|
344
390
|
}
|
|
391
|
+
if (options?.origin) {
|
|
392
|
+
filters.push('origin = @origin');
|
|
393
|
+
params.origin = options.origin;
|
|
394
|
+
}
|
|
345
395
|
if (options?.tags?.length) {
|
|
346
396
|
const c = options.tags.map((t, i) => {
|
|
347
397
|
params[`tag${i}`] = `%"${t}"%`;
|
|
@@ -866,12 +916,41 @@ function rowToEntry(row) {
|
|
|
866
916
|
tags: JSON.parse(row.tags || '[]'),
|
|
867
917
|
appliesTo: JSON.parse(row.applies_to || '[]'),
|
|
868
918
|
tier: row.tier ?? undefined,
|
|
919
|
+
origin: row.origin ?? undefined,
|
|
869
920
|
validFrom: row.valid_from ?? undefined,
|
|
870
921
|
validUntil: row.valid_until ?? undefined,
|
|
871
922
|
};
|
|
872
923
|
}
|
|
873
924
|
function rowToSearchResult(row) {
|
|
874
|
-
|
|
925
|
+
// bm25() returns negative scores (lower = better), normalize to positive
|
|
926
|
+
const rawScore = row.score;
|
|
927
|
+
const score = rawScore < 0 ? -rawScore : rawScore;
|
|
928
|
+
return { entry: rowToEntry(row), score };
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Build an FTS5 query from natural language input.
|
|
932
|
+
*
|
|
933
|
+
* Converts "React render performance memo" to:
|
|
934
|
+
* {title}: (react OR render OR performance OR memo) OR (react OR render OR performance OR memo)
|
|
935
|
+
*
|
|
936
|
+
* Uses OR matching (not AND) so results include partial matches.
|
|
937
|
+
* FTS5 BM25 ranks documents with more matching terms higher.
|
|
938
|
+
* Title column is boosted via bm25() weights in the SQL query.
|
|
939
|
+
*/
|
|
940
|
+
function buildFtsQuery(query) {
|
|
941
|
+
const terms = query
|
|
942
|
+
.toLowerCase()
|
|
943
|
+
.split(/\s+/)
|
|
944
|
+
.filter((t) => t.length >= 2)
|
|
945
|
+
.map((t) => t.replace(/[^a-z0-9]/g, ''))
|
|
946
|
+
.filter(Boolean);
|
|
947
|
+
if (terms.length === 0)
|
|
948
|
+
return query;
|
|
949
|
+
if (terms.length === 1)
|
|
950
|
+
return terms[0];
|
|
951
|
+
// Use OR to match any term — BM25 ranks by how many terms match
|
|
952
|
+
const orTerms = terms.join(' OR ');
|
|
953
|
+
return orTerms;
|
|
875
954
|
}
|
|
876
955
|
function rowToMemory(row) {
|
|
877
956
|
return {
|