oh-my-second-brain 0.3.0 → 0.6.2
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/ACKNOWLEDGMENTS.md +8 -0
- package/CHANGELOG-assets.md +10 -0
- package/CHANGELOG-cli.md +11 -0
- package/CHANGELOG-kernel.md +31 -0
- package/CHANGELOG-mcp.md +12 -0
- package/CHANGELOG-vendors.md +6 -0
- package/CHANGELOG.md +35 -0
- package/assets/hermes-manifest.json +1 -1
- package/assets/skills/doctor/SKILL.md +2 -2
- package/assets/skills/search/SKILL.md +17 -1
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.js +13 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/host-commands.js +2 -1
- package/dist/cli/host-commands.js.map +1 -1
- package/dist/cli/oms.d.ts +1 -1
- package/dist/cli/oms.js +26 -3
- package/dist/cli/oms.js.map +1 -1
- package/dist/cli/semantic-args.js +102 -3
- package/dist/cli/semantic-args.js.map +1 -1
- package/dist/cli/semantic.js +30 -6
- package/dist/cli/semantic.js.map +1 -1
- package/dist/cli/setup-command.d.ts +16 -0
- package/dist/cli/setup-command.js +50 -1
- package/dist/cli/setup-command.js.map +1 -1
- package/dist/kernel/contracts/index.d.ts +144 -0
- package/dist/kernel/contracts/index.js +401 -0
- package/dist/kernel/contracts/index.js.map +1 -0
- package/dist/kernel/conventions/note-exclude.d.ts +14 -0
- package/dist/kernel/conventions/note-exclude.js +95 -0
- package/dist/kernel/conventions/note-exclude.js.map +1 -0
- package/dist/kernel/engine/assemble.d.ts +22 -1
- package/dist/kernel/engine/assemble.js +202 -19
- package/dist/kernel/engine/assemble.js.map +1 -1
- package/dist/kernel/engine/axes/store.d.ts +90 -0
- package/dist/kernel/engine/axes/store.js +422 -0
- package/dist/kernel/engine/axes/store.js.map +1 -0
- package/dist/kernel/engine/conventions/vault-lint.d.ts +7 -2
- package/dist/kernel/engine/conventions/vault-lint.js +7 -21
- package/dist/kernel/engine/conventions/vault-lint.js.map +1 -1
- package/dist/kernel/engine/embed/identity.d.ts +14 -4
- package/dist/kernel/engine/embed/identity.js +33 -1
- package/dist/kernel/engine/embed/identity.js.map +1 -1
- package/dist/kernel/engine/embed/model.d.ts +134 -0
- package/dist/kernel/engine/embed/model.js +302 -0
- package/dist/kernel/engine/embed/model.js.map +1 -0
- package/dist/kernel/engine/embed/provider.d.ts +36 -5
- package/dist/kernel/engine/embed/provider.js +240 -103
- package/dist/kernel/engine/embed/provider.js.map +1 -1
- package/dist/kernel/engine/embed/store.d.ts +5 -1
- package/dist/kernel/engine/embed/store.js +136 -26
- package/dist/kernel/engine/embed/store.js.map +1 -1
- package/dist/kernel/engine/embed/sync.d.ts +53 -0
- package/dist/kernel/engine/embed/sync.js +489 -59
- package/dist/kernel/engine/embed/sync.js.map +1 -1
- package/dist/kernel/engine/graph/builder.d.ts +9 -5
- package/dist/kernel/engine/graph/builder.js +225 -82
- package/dist/kernel/engine/graph/builder.js.map +1 -1
- package/dist/kernel/engine/graph/node.d.ts +49 -1
- package/dist/kernel/engine/graph/node.js +205 -0
- package/dist/kernel/engine/graph/node.js.map +1 -1
- package/dist/kernel/engine/mcp/facade.d.ts +21 -1
- package/dist/kernel/engine/mcp/facade.js +523 -28
- package/dist/kernel/engine/mcp/facade.js.map +1 -1
- package/dist/kernel/engine/mcp/query-mapper.d.ts +27 -2
- package/dist/kernel/engine/mcp/query-mapper.js +157 -12
- package/dist/kernel/engine/mcp/query-mapper.js.map +1 -1
- package/dist/kernel/engine/mcp/types.d.ts +64 -2
- package/dist/kernel/engine/retrieval/dispatcher.d.ts +22 -0
- package/dist/kernel/engine/retrieval/dispatcher.js +84 -8
- package/dist/kernel/engine/retrieval/dispatcher.js.map +1 -1
- package/dist/kernel/engine/retrieval/index.d.ts +2 -1
- package/dist/kernel/engine/retrieval/index.js +1 -1
- package/dist/kernel/engine/retrieval/index.js.map +1 -1
- package/dist/kernel/engine/retrieval/reranker.d.ts +82 -4
- package/dist/kernel/engine/retrieval/reranker.js +178 -3
- package/dist/kernel/engine/retrieval/reranker.js.map +1 -1
- package/dist/kernel/engine/retrieval/rrf.d.ts +10 -2
- package/dist/kernel/engine/retrieval/rrf.js +39 -16
- package/dist/kernel/engine/retrieval/rrf.js.map +1 -1
- package/dist/kernel/engine/tracer.d.ts +13 -0
- package/dist/kernel/engine/tracer.js +63 -6
- package/dist/kernel/engine/tracer.js.map +1 -1
- package/dist/kernel/graph/cache.js +174 -23
- package/dist/kernel/graph/cache.js.map +1 -1
- package/dist/kernel/index.d.ts +2 -0
- package/dist/kernel/index.js +2 -0
- package/dist/kernel/index.js.map +1 -1
- package/dist/kernel/measurement/no-default-contract.d.ts +17 -0
- package/dist/kernel/measurement/no-default-contract.js +84 -0
- package/dist/kernel/measurement/no-default-contract.js.map +1 -0
- package/dist/kernel/searchbackend/engine-search-backend.js +93 -7
- package/dist/kernel/searchbackend/engine-search-backend.js.map +1 -1
- package/dist/kernel/searchbackend/search-backend.d.ts +11 -1
- package/dist/kernel/searchbackend/search-backend.js +66 -5
- package/dist/kernel/searchbackend/search-backend.js.map +1 -1
- package/dist/kernel/semantic/semantic-engine.js +31 -5
- package/dist/kernel/semantic/semantic-engine.js.map +1 -1
- package/dist/kernel/semantic/semantic-retrieve-args.d.ts +19 -2
- package/dist/kernel/semantic/semantic-retrieve-args.js +81 -7
- package/dist/kernel/semantic/semantic-retrieve-args.js.map +1 -1
- package/dist/kernel/update/update.d.ts +7 -0
- package/dist/kernel/update/update.js +106 -8
- package/dist/kernel/update/update.js.map +1 -1
- package/dist/mcp/server.js +84 -34
- package/dist/mcp/server.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, readdir, realpath, stat } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import Database from "better-sqlite3";
|
|
5
|
+
import { parseNote } from "../../conventions/frontmatter.js";
|
|
6
|
+
import { excludedNoteMatcher } from "../../conventions/note-exclude.js";
|
|
7
|
+
function isAxisKind(value) {
|
|
8
|
+
return value === "folder" || value === "field" || value === "link";
|
|
9
|
+
}
|
|
10
|
+
function canonicalAxisKey(value) {
|
|
11
|
+
const key = value.trim().toLowerCase();
|
|
12
|
+
if (key.length === 0)
|
|
13
|
+
throw new Error("Axis key must be non-empty.");
|
|
14
|
+
return key;
|
|
15
|
+
}
|
|
16
|
+
function scalarType(value) {
|
|
17
|
+
if (value instanceof Date)
|
|
18
|
+
return "date";
|
|
19
|
+
if (typeof value === "string")
|
|
20
|
+
return "string";
|
|
21
|
+
if (typeof value === "number")
|
|
22
|
+
return "number";
|
|
23
|
+
return "boolean";
|
|
24
|
+
}
|
|
25
|
+
function canonicalScalar(value) {
|
|
26
|
+
if (value instanceof Date) {
|
|
27
|
+
if (Number.isNaN(value.getTime()))
|
|
28
|
+
throw new Error("Axis date value must be valid.");
|
|
29
|
+
return value.toISOString();
|
|
30
|
+
}
|
|
31
|
+
if (typeof value === "string") {
|
|
32
|
+
const normalized = value.trim().toLowerCase();
|
|
33
|
+
if (normalized.length === 0)
|
|
34
|
+
throw new Error("Axis string value must be non-empty.");
|
|
35
|
+
return normalized;
|
|
36
|
+
}
|
|
37
|
+
if (typeof value === "number") {
|
|
38
|
+
if (!Number.isFinite(value))
|
|
39
|
+
throw new Error("Axis number value must be finite.");
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
function flattenValue(value) {
|
|
45
|
+
if (Array.isArray(value))
|
|
46
|
+
return value.flatMap(flattenValue);
|
|
47
|
+
if (value instanceof Date || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
48
|
+
return [value];
|
|
49
|
+
}
|
|
50
|
+
if (value === null || value === undefined)
|
|
51
|
+
return [];
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
function normalizedLookup(value, type) {
|
|
55
|
+
if (type === "date")
|
|
56
|
+
return (value instanceof Date ? value.toISOString() : String(value)).toLowerCase();
|
|
57
|
+
return String(value).trim().toLowerCase();
|
|
58
|
+
}
|
|
59
|
+
export function normalizeAxisValue(value) {
|
|
60
|
+
const canonical = canonicalScalar(value);
|
|
61
|
+
const type = scalarType(value);
|
|
62
|
+
return { value: canonical, type, normalizedValue: normalizedLookup(canonical, type) };
|
|
63
|
+
}
|
|
64
|
+
function decodeValue(type, json) {
|
|
65
|
+
let value;
|
|
66
|
+
try {
|
|
67
|
+
value = JSON.parse(json);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
throw new Error("Axis observation contains invalid stored JSON.");
|
|
71
|
+
}
|
|
72
|
+
if (type === "string" && typeof value === "string")
|
|
73
|
+
return value;
|
|
74
|
+
if (type === "number" && typeof value === "number" && Number.isFinite(value))
|
|
75
|
+
return value;
|
|
76
|
+
if (type === "boolean" && typeof value === "boolean")
|
|
77
|
+
return value;
|
|
78
|
+
if (type === "date" && typeof value === "string") {
|
|
79
|
+
const date = new Date(value);
|
|
80
|
+
if (!Number.isNaN(date.getTime()))
|
|
81
|
+
return date;
|
|
82
|
+
}
|
|
83
|
+
throw new Error(`Axis observation value does not match stored type ${type}.`);
|
|
84
|
+
}
|
|
85
|
+
function toObservation(row) {
|
|
86
|
+
if (!isAxisKind(row.axis_kind))
|
|
87
|
+
throw new Error(`Axis observation has unknown kind ${row.axis_kind}.`);
|
|
88
|
+
return {
|
|
89
|
+
notePath: row.note_path,
|
|
90
|
+
axisKind: row.axis_kind,
|
|
91
|
+
axisKey: row.axis_key,
|
|
92
|
+
value: decodeValue(row.value_type, row.value_json),
|
|
93
|
+
valueType: row.value_type,
|
|
94
|
+
normalizedValue: row.normalized_value,
|
|
95
|
+
count: row.count,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const CREATE_SCHEMA = `
|
|
99
|
+
CREATE TABLE IF NOT EXISTS axis_observation (
|
|
100
|
+
note_path TEXT NOT NULL,
|
|
101
|
+
axis_kind TEXT NOT NULL CHECK (axis_kind IN ('folder', 'field', 'link')),
|
|
102
|
+
axis_key TEXT NOT NULL,
|
|
103
|
+
value_type TEXT NOT NULL CHECK (value_type IN ('string', 'number', 'boolean', 'date')),
|
|
104
|
+
value_json TEXT NOT NULL,
|
|
105
|
+
normalized_value TEXT NOT NULL,
|
|
106
|
+
count INTEGER NOT NULL DEFAULT 1 CHECK (count > 0),
|
|
107
|
+
PRIMARY KEY (note_path, axis_kind, axis_key, value_type, normalized_value)
|
|
108
|
+
);
|
|
109
|
+
CREATE INDEX IF NOT EXISTS axis_observation_lookup
|
|
110
|
+
ON axis_observation (axis_kind, axis_key, normalized_value);
|
|
111
|
+
CREATE TABLE IF NOT EXISTS axis_meta (
|
|
112
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
113
|
+
source_signature TEXT NOT NULL
|
|
114
|
+
);
|
|
115
|
+
`;
|
|
116
|
+
/** Dedicated EAV repository; never shares the embedding engine database. */
|
|
117
|
+
export class AxisObservationStore {
|
|
118
|
+
dbPath;
|
|
119
|
+
db;
|
|
120
|
+
closed = false;
|
|
121
|
+
transactionDepth = 0;
|
|
122
|
+
constructor(dbPath, options = {}) {
|
|
123
|
+
this.dbPath = dbPath;
|
|
124
|
+
if (options.readonly === true || options.readOnly === true) {
|
|
125
|
+
this.db = new Database(dbPath, { readonly: true, fileMustExist: true });
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
this.db = new Database(dbPath);
|
|
129
|
+
this.db.pragma("journal_mode = WAL");
|
|
130
|
+
this.db.exec(CREATE_SCHEMA);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
ensureOpen() {
|
|
134
|
+
if (this.closed)
|
|
135
|
+
throw new Error("Axis observation store is closed.");
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Run a group of writes as one rollback-safe publication. Nested writes from
|
|
139
|
+
* record/replaceNote participate in the outer transaction rather than
|
|
140
|
+
* attempting to open a second SQLite transaction.
|
|
141
|
+
*/
|
|
142
|
+
runInTransaction(fn) {
|
|
143
|
+
this.ensureOpen();
|
|
144
|
+
if (this.transactionDepth > 0)
|
|
145
|
+
return fn();
|
|
146
|
+
this.transactionDepth += 1;
|
|
147
|
+
try {
|
|
148
|
+
return this.db.transaction(fn)();
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
this.transactionDepth -= 1;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
insertValues(notePath, axisKind, axisKey, value, statement) {
|
|
155
|
+
for (const original of flattenValue(value)) {
|
|
156
|
+
// An empty or whitespace-only string carries no axis information, so
|
|
157
|
+
// it is dropped exactly like the null/undefined that flattenValue
|
|
158
|
+
// already discards. `field: ""` is a normal "declared but unset"
|
|
159
|
+
// frontmatter state, not vault corruption; it must not abort the
|
|
160
|
+
// whole vault scan.
|
|
161
|
+
if (typeof original === "string" && original.trim().length === 0)
|
|
162
|
+
continue;
|
|
163
|
+
let normalized;
|
|
164
|
+
try {
|
|
165
|
+
normalized = normalizeAxisValue(original);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
// canonicalScalar's own errors carry no note path, which makes them
|
|
169
|
+
// undiagnosable from the message alone during a whole-vault scan.
|
|
170
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
171
|
+
throw new Error(`${notePath}: ${message}`, { cause: error });
|
|
172
|
+
}
|
|
173
|
+
statement.run(notePath, axisKind, axisKey, normalized.type, JSON.stringify(normalized.value), normalized.normalizedValue);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/** Source signature of the markdown set used for the last reconciliation. */
|
|
177
|
+
sourceSignature() {
|
|
178
|
+
this.ensureOpen();
|
|
179
|
+
const row = this.db.prepare("SELECT source_signature FROM axis_meta WHERE id = 1").get();
|
|
180
|
+
return row?.source_signature ?? null;
|
|
181
|
+
}
|
|
182
|
+
setSourceSignature(signature) {
|
|
183
|
+
this.ensureOpen();
|
|
184
|
+
this.db.prepare("INSERT INTO axis_meta (id, source_signature) VALUES (1, ?) ON CONFLICT(id) DO UPDATE SET source_signature = excluded.source_signature").run(signature);
|
|
185
|
+
}
|
|
186
|
+
/** Record one scalar or every scalar in a frontmatter list. */
|
|
187
|
+
record(input) {
|
|
188
|
+
this.ensureOpen();
|
|
189
|
+
const axisKind = input.axisKind ?? "field";
|
|
190
|
+
if (!isAxisKind(axisKind))
|
|
191
|
+
throw new Error(`Unknown axis kind ${String(axisKind)}.`);
|
|
192
|
+
const axisKey = canonicalAxisKey(input.axisKey);
|
|
193
|
+
const values = flattenValue(input.value);
|
|
194
|
+
const statement = this.db.prepare(`
|
|
195
|
+
INSERT INTO axis_observation
|
|
196
|
+
(note_path, axis_kind, axis_key, value_type, value_json, normalized_value, count)
|
|
197
|
+
VALUES (?, ?, ?, ?, ?, ?, 1)
|
|
198
|
+
ON CONFLICT(note_path, axis_kind, axis_key, value_type, normalized_value)
|
|
199
|
+
DO UPDATE SET count = axis_observation.count + 1
|
|
200
|
+
`);
|
|
201
|
+
this.runInTransaction(() => {
|
|
202
|
+
for (const value of values)
|
|
203
|
+
this.insertValues(input.notePath, axisKind, axisKey, value, statement);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/** Remove all observations for a note, then atomically replace them. */
|
|
207
|
+
replaceNote(notePath, fields, options = {}) {
|
|
208
|
+
this.ensureOpen();
|
|
209
|
+
this.runInTransaction(() => {
|
|
210
|
+
this.db.prepare("DELETE FROM axis_observation WHERE note_path = ?").run(notePath);
|
|
211
|
+
const statement = this.db.prepare(`
|
|
212
|
+
INSERT INTO axis_observation
|
|
213
|
+
(note_path, axis_kind, axis_key, value_type, value_json, normalized_value, count)
|
|
214
|
+
VALUES (?, ?, ?, ?, ?, ?, 1)
|
|
215
|
+
ON CONFLICT(note_path, axis_kind, axis_key, value_type, normalized_value)
|
|
216
|
+
DO UPDATE SET count = 1
|
|
217
|
+
`);
|
|
218
|
+
if (options.folder !== undefined)
|
|
219
|
+
this.insertValues(notePath, "folder", "folder", options.folder, statement);
|
|
220
|
+
for (const [axisKey, value] of Object.entries(fields)) {
|
|
221
|
+
this.insertValues(notePath, "field", canonicalAxisKey(axisKey), value, statement);
|
|
222
|
+
}
|
|
223
|
+
for (const link of options.links ?? [])
|
|
224
|
+
this.insertValues(notePath, "link", "link", link, statement);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
/** Delete stale observations when a markdown note is removed. */
|
|
228
|
+
deleteNote(notePath) {
|
|
229
|
+
this.ensureOpen();
|
|
230
|
+
this.db.prepare("DELETE FROM axis_observation WHERE note_path = ?").run(notePath);
|
|
231
|
+
}
|
|
232
|
+
list(options = {}) {
|
|
233
|
+
this.ensureOpen();
|
|
234
|
+
const clauses = [];
|
|
235
|
+
const params = [];
|
|
236
|
+
if (options.axisKind !== undefined) {
|
|
237
|
+
if (!isAxisKind(options.axisKind))
|
|
238
|
+
throw new Error(`Unknown axis kind ${String(options.axisKind)}.`);
|
|
239
|
+
clauses.push("axis_kind = ?");
|
|
240
|
+
params.push(options.axisKind);
|
|
241
|
+
}
|
|
242
|
+
if (options.axisKey !== undefined) {
|
|
243
|
+
clauses.push("axis_key = ?");
|
|
244
|
+
params.push(canonicalAxisKey(options.axisKey));
|
|
245
|
+
}
|
|
246
|
+
if (options.notePath !== undefined) {
|
|
247
|
+
clauses.push("note_path = ?");
|
|
248
|
+
params.push(options.notePath);
|
|
249
|
+
}
|
|
250
|
+
const where = clauses.length === 0 ? "" : ` WHERE ${clauses.join(" AND ")}`;
|
|
251
|
+
const rows = this.db.prepare(`SELECT note_path, axis_kind, axis_key, value_type, value_json, normalized_value, count
|
|
252
|
+
FROM axis_observation${where}
|
|
253
|
+
ORDER BY note_path, axis_kind, axis_key, normalized_value`).all(...params);
|
|
254
|
+
return rows.map(toObservation);
|
|
255
|
+
}
|
|
256
|
+
/** Aggregate facets before any result limit is applied. */
|
|
257
|
+
facets(options = {}) {
|
|
258
|
+
const observations = this.list(options);
|
|
259
|
+
const grouped = new Map();
|
|
260
|
+
for (const observation of observations) {
|
|
261
|
+
const id = `${observation.axisKind}\0${observation.axisKey}\0${observation.valueType}\0${observation.normalizedValue}`;
|
|
262
|
+
const prior = grouped.get(id);
|
|
263
|
+
if (prior === undefined) {
|
|
264
|
+
grouped.set(id, {
|
|
265
|
+
axisKind: observation.axisKind,
|
|
266
|
+
axisKey: observation.axisKey,
|
|
267
|
+
value: observation.value,
|
|
268
|
+
valueType: observation.valueType,
|
|
269
|
+
normalizedValue: observation.normalizedValue,
|
|
270
|
+
count: observation.count,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
grouped.set(id, { ...prior, count: prior.count + observation.count });
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return [...grouped.values()].sort((left, right) => left.axisKind.localeCompare(right.axisKind) || left.axisKey.localeCompare(right.axisKey) || left.normalizedValue.localeCompare(right.normalizedValue));
|
|
278
|
+
}
|
|
279
|
+
count(options = {}) {
|
|
280
|
+
return this.list(options).reduce((sum, row) => sum + row.count, 0);
|
|
281
|
+
}
|
|
282
|
+
close() {
|
|
283
|
+
if (this.closed)
|
|
284
|
+
return;
|
|
285
|
+
this.db.close();
|
|
286
|
+
this.closed = true;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
export const openAxisStore = (dbPath, options = {}) => new AxisObservationStore(dbPath, options);
|
|
290
|
+
export function axisStorePath(vault) {
|
|
291
|
+
return path.resolve(vault, ".oms", "cache", "axes.sqlite");
|
|
292
|
+
}
|
|
293
|
+
export function openVaultAxisStore(vault, options = {}) {
|
|
294
|
+
return new AxisObservationStore(axisStorePath(vault), options);
|
|
295
|
+
}
|
|
296
|
+
function firstFolder(notePath) {
|
|
297
|
+
const slash = notePath.indexOf("/");
|
|
298
|
+
return slash > 0 ? notePath.slice(0, slash) : undefined;
|
|
299
|
+
}
|
|
300
|
+
function extractLinks(body) {
|
|
301
|
+
const links = [];
|
|
302
|
+
const pattern = /\[\[([^\]|#]+)(?:[#|][^\]]*)?\]\]/gu;
|
|
303
|
+
for (const match of body.matchAll(pattern)) {
|
|
304
|
+
const target = match[1]?.trim();
|
|
305
|
+
if (target)
|
|
306
|
+
links.push(target);
|
|
307
|
+
}
|
|
308
|
+
return [...new Set(links)];
|
|
309
|
+
}
|
|
310
|
+
const AXIS_SKIP_DIRS = new Set([
|
|
311
|
+
".oms",
|
|
312
|
+
".obsidian",
|
|
313
|
+
".trash",
|
|
314
|
+
".git",
|
|
315
|
+
".claude",
|
|
316
|
+
"_archive",
|
|
317
|
+
"node_modules",
|
|
318
|
+
]);
|
|
319
|
+
function ensureInsideVault(root, candidate, label) {
|
|
320
|
+
const relative = path.relative(root, candidate);
|
|
321
|
+
if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
322
|
+
throw new Error(`${label} escapes the configured vault root.`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Strict scanner for EAV reconciliation. The shared convention walker is
|
|
327
|
+
* intentionally permissive for linting, but a persisted derived snapshot
|
|
328
|
+
* must fail when a directory/file disappears or a symlink leaves the vault.
|
|
329
|
+
*/
|
|
330
|
+
async function* walkVaultMarkdownStrict(dir, base, isExcluded, rootRealPath, visitedDirectories = new Set()) {
|
|
331
|
+
const root = rootRealPath ?? await realpath(base);
|
|
332
|
+
const realDir = await realpath(dir);
|
|
333
|
+
ensureInsideVault(root, realDir, `Vault directory "${dir}"`);
|
|
334
|
+
if (visitedDirectories.has(realDir))
|
|
335
|
+
return;
|
|
336
|
+
visitedDirectories.add(realDir);
|
|
337
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
338
|
+
for (const entry of entries) {
|
|
339
|
+
const fullPath = path.join(dir, entry.name);
|
|
340
|
+
const realEntry = await realpath(fullPath);
|
|
341
|
+
ensureInsideVault(root, realEntry, `Vault entry "${fullPath}"`);
|
|
342
|
+
if (AXIS_SKIP_DIRS.has(entry.name) || entry.name.startsWith("."))
|
|
343
|
+
continue;
|
|
344
|
+
const entryStat = await stat(fullPath);
|
|
345
|
+
if (entryStat.isDirectory()) {
|
|
346
|
+
yield* walkVaultMarkdownStrict(fullPath, base, isExcluded, root, visitedDirectories);
|
|
347
|
+
}
|
|
348
|
+
else if (entryStat.isFile() && entry.name.toLowerCase().endsWith(".md")) {
|
|
349
|
+
const notePath = path.relative(base, fullPath).replace(/\\/g, "/");
|
|
350
|
+
// Taxonomy-declared non-notes (template sources above all) never enter
|
|
351
|
+
// the EAV scan: their frontmatter is intentionally not valid YAML.
|
|
352
|
+
if (!isExcluded(notePath))
|
|
353
|
+
yield notePath;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
/** Scan markdown into the dedicated EAV cache. Malformed YAML is loud. */
|
|
358
|
+
export async function collectVaultAxisObservations(vault, suppliedStore) {
|
|
359
|
+
const ownsStore = suppliedStore === undefined;
|
|
360
|
+
let store = suppliedStore;
|
|
361
|
+
const liveNotes = new Set();
|
|
362
|
+
const sourceFiles = new Map();
|
|
363
|
+
const parsedNotes = [];
|
|
364
|
+
try {
|
|
365
|
+
const isExcluded = await excludedNoteMatcher(vault);
|
|
366
|
+
// Read and parse the complete source set before touching the existing
|
|
367
|
+
// snapshot. This keeps read/parse failures from exposing a partial scan.
|
|
368
|
+
for await (const notePath of walkVaultMarkdownStrict(vault, vault, isExcluded)) {
|
|
369
|
+
const raw = await readFile(path.join(vault, notePath), "utf-8");
|
|
370
|
+
sourceFiles.set(notePath, Buffer.from(raw, "utf8"));
|
|
371
|
+
const parsed = parseNote(raw);
|
|
372
|
+
if (parsed.diagnostics.length > 0) {
|
|
373
|
+
throw new Error(`${notePath}: malformed frontmatter (${parsed.diagnostics.map((item) => item.message).join("; ")})`);
|
|
374
|
+
}
|
|
375
|
+
liveNotes.add(notePath);
|
|
376
|
+
parsedNotes.push({ notePath, parsed });
|
|
377
|
+
}
|
|
378
|
+
const digest = createHash("sha256");
|
|
379
|
+
for (const notePath of [...sourceFiles.keys()].sort()) {
|
|
380
|
+
digest.update(notePath);
|
|
381
|
+
digest.update("\0");
|
|
382
|
+
digest.update(sourceFiles.get(notePath));
|
|
383
|
+
digest.update("\0");
|
|
384
|
+
}
|
|
385
|
+
// Do not create or open the derived database until the complete source
|
|
386
|
+
// scan has succeeded. A failed first scan must not publish an empty cache.
|
|
387
|
+
if (store === undefined) {
|
|
388
|
+
await ensureAxisStoreDirectory(vault);
|
|
389
|
+
store = openVaultAxisStore(vault);
|
|
390
|
+
}
|
|
391
|
+
const activeStore = store;
|
|
392
|
+
activeStore.runInTransaction(() => {
|
|
393
|
+
for (const { notePath, parsed } of parsedNotes) {
|
|
394
|
+
activeStore.replaceNote(notePath, parsed.frontmatter, {
|
|
395
|
+
folder: firstFolder(notePath),
|
|
396
|
+
links: extractLinks(parsed.body),
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
// A scan is a reconciliation, not an append-only import. Remove rows
|
|
400
|
+
// for notes that were present in an earlier snapshot but no longer
|
|
401
|
+
// exist.
|
|
402
|
+
const staleNotes = new Set(activeStore.list().map((observation) => observation.notePath));
|
|
403
|
+
for (const notePath of staleNotes) {
|
|
404
|
+
if (!liveNotes.has(notePath))
|
|
405
|
+
activeStore.deleteNote(notePath);
|
|
406
|
+
}
|
|
407
|
+
activeStore.setSourceSignature(digest.digest("hex"));
|
|
408
|
+
});
|
|
409
|
+
return activeStore;
|
|
410
|
+
}
|
|
411
|
+
catch (error) {
|
|
412
|
+
if (ownsStore)
|
|
413
|
+
store?.close();
|
|
414
|
+
throw error;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
// `mkdir` is intentionally kept in the module so callers can create an empty
|
|
418
|
+
// cache path without touching the embedding engine store.
|
|
419
|
+
export async function ensureAxisStoreDirectory(vault) {
|
|
420
|
+
await mkdir(path.dirname(axisStorePath(vault)), { recursive: true });
|
|
421
|
+
}
|
|
422
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/kernel/engine/axes/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
*
|
|
18
18
|
* Invalid folder scopes throw clear caller-facing errors; individual notes that cannot be parsed are skipped.
|
|
19
19
|
*/
|
|
20
|
+
import { DEFAULT_EXCLUDE_GLOBS, matchesAnyGlob } from "../../conventions/note-exclude.js";
|
|
20
21
|
import type { Concept, Ontology } from "../../ontology/types.js";
|
|
21
22
|
/** One of the five check layers. */
|
|
22
23
|
export type VaultLintRule = "allowlist" | "required" | "type" | "enum" | "routing-law";
|
|
@@ -62,9 +63,13 @@ export interface VaultLintOptions {
|
|
|
62
63
|
/**
|
|
63
64
|
* Default audit exemptions — deliberately not contract violations: build artifacts,
|
|
64
65
|
* self-documenting templates, and skill files that intentionally carry no frontmatter.
|
|
66
|
+
*
|
|
67
|
+
* Defined in `../../conventions/note-exclude.js` (below the engine layer) and
|
|
68
|
+
* re-exported here so existing importers of this module are unaffected; the
|
|
69
|
+
* scanning walkers that also need this policy (graph builder, EAV axis scan,
|
|
70
|
+
* graph cache) import it from there directly instead of duplicating it.
|
|
65
71
|
*/
|
|
66
|
-
export
|
|
67
|
-
export declare function matchesAnyGlob(notePath: string, globs: readonly string[]): boolean;
|
|
72
|
+
export { DEFAULT_EXCLUDE_GLOBS, matchesAnyGlob };
|
|
68
73
|
/** Merge built-in defaults with vault-declared and caller-supplied exclude globs. */
|
|
69
74
|
export declare function resolveExcludeGlobs(ontology: Ontology, extra?: readonly string[]): string[];
|
|
70
75
|
export declare function validateVaultLintFolder(vaultRoot: string, ontology: Ontology, folder: string | undefined): Promise<void>;
|
|
@@ -23,33 +23,19 @@ import { parseNote } from "../../conventions/frontmatter.js";
|
|
|
23
23
|
import { validateFrontmatter } from "../../conventions/validate.js";
|
|
24
24
|
import { enumViolations, routingLawStrictFolders as writeContractStrictFolders, routingLawViolations, } from "../../conventions/write-contract.js";
|
|
25
25
|
import { walkVaultMarkdown } from "../../conventions/vault-walk.js";
|
|
26
|
+
import { DEFAULT_EXCLUDE_GLOBS, matchesAnyGlob } from "../../conventions/note-exclude.js";
|
|
26
27
|
import { resolveConcept } from "../../ontology/resolver.js";
|
|
27
28
|
// ── Internals ─────────────────────────────────────────────────────────────────
|
|
28
29
|
/**
|
|
29
30
|
* Default audit exemptions — deliberately not contract violations: build artifacts,
|
|
30
31
|
* self-documenting templates, and skill files that intentionally carry no frontmatter.
|
|
32
|
+
*
|
|
33
|
+
* Defined in `../../conventions/note-exclude.js` (below the engine layer) and
|
|
34
|
+
* re-exported here so existing importers of this module are unaffected; the
|
|
35
|
+
* scanning walkers that also need this policy (graph builder, EAV axis scan,
|
|
36
|
+
* graph cache) import it from there directly instead of duplicating it.
|
|
31
37
|
*/
|
|
32
|
-
export
|
|
33
|
-
"25. Digital Garden/.deploy-staging/**",
|
|
34
|
-
"**/*.template.md",
|
|
35
|
-
"**/SKILL.md",
|
|
36
|
-
".obsidian/**",
|
|
37
|
-
".trash/**",
|
|
38
|
-
".oms/**",
|
|
39
|
-
"_attachments/**",
|
|
40
|
-
];
|
|
41
|
-
/** Convert a `*`/`**` glob into an anchored RegExp. `**` matches across `/`, `*` does not. */
|
|
42
|
-
function globToRegExp(glob) {
|
|
43
|
-
const GLOBSTAR = "\u0000";
|
|
44
|
-
const withPlaceholder = glob.replace(/\*\*/g, GLOBSTAR);
|
|
45
|
-
const escaped = withPlaceholder.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
46
|
-
const withStar = escaped.replace(/\*/g, "[^/]*");
|
|
47
|
-
const pattern = withStar.split(GLOBSTAR).join(".*");
|
|
48
|
-
return new RegExp(`^${pattern}$`);
|
|
49
|
-
}
|
|
50
|
-
export function matchesAnyGlob(notePath, globs) {
|
|
51
|
-
return globs.some((glob) => globToRegExp(glob).test(notePath));
|
|
52
|
-
}
|
|
38
|
+
export { DEFAULT_EXCLUDE_GLOBS, matchesAnyGlob };
|
|
53
39
|
/** Merge built-in defaults with vault-declared and caller-supplied exclude globs. */
|
|
54
40
|
export function resolveExcludeGlobs(ontology, extra = []) {
|
|
55
41
|
return [...DEFAULT_EXCLUDE_GLOBS, ...(ontology.taxonomy.exclude ?? []), ...extra];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vault-lint.js","sourceRoot":"","sources":["../../../../src/kernel/engine/conventions/vault-lint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EACL,cAAc,EACd,uBAAuB,IAAI,0BAA0B,EACrD,oBAAoB,GACrB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"vault-lint.js","sourceRoot":"","sources":["../../../../src/kernel/engine/conventions/vault-lint.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { type EmbeddingIdentity } from "./store.js";
|
|
2
|
+
/**
|
|
3
|
+
* The five model-shape fields are part of the fingerprint. Provider/model
|
|
4
|
+
* remain explicit labels as well, so changing either the runtime or model
|
|
5
|
+
* cannot silently reuse vectors produced by another configuration.
|
|
6
|
+
*/
|
|
7
|
+
export interface EmbeddingShapeIdentity {
|
|
8
|
+
readonly dimensions: number;
|
|
9
|
+
readonly contextLength: number;
|
|
10
|
+
readonly mrlDim: number;
|
|
11
|
+
readonly normalization: string;
|
|
12
|
+
readonly prefixScheme: string;
|
|
13
|
+
}
|
|
2
14
|
export declare function fingerprintEmbeddingIdentity(input: {
|
|
3
15
|
provider: string;
|
|
4
16
|
model: string;
|
|
5
|
-
|
|
6
|
-
}): string;
|
|
17
|
+
} & EmbeddingShapeIdentity): string;
|
|
7
18
|
export declare function makeEmbeddingIdentity(input: {
|
|
8
19
|
provider: string;
|
|
9
20
|
model: string;
|
|
10
|
-
|
|
11
|
-
}): EmbeddingIdentity;
|
|
21
|
+
} & EmbeddingShapeIdentity): EmbeddingIdentity;
|
|
@@ -1,14 +1,46 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { ENGINE_EMBED_META_VERSION } from "./store.js";
|
|
3
|
+
function assertShape(input) {
|
|
4
|
+
if (!Number.isInteger(input.dimensions) || input.dimensions <= 0) {
|
|
5
|
+
throw new Error("Embedding identity dimensions must be a positive integer.");
|
|
6
|
+
}
|
|
7
|
+
if (!Number.isInteger(input.contextLength) || input.contextLength <= 0) {
|
|
8
|
+
throw new Error("Embedding identity contextLength must be a positive integer.");
|
|
9
|
+
}
|
|
10
|
+
if (!Number.isInteger(input.mrlDim) || input.mrlDim < 0) {
|
|
11
|
+
throw new Error("Embedding identity mrlDim must be a non-negative integer.");
|
|
12
|
+
}
|
|
13
|
+
if (typeof input.normalization !== "string" || input.normalization.trim() === "") {
|
|
14
|
+
throw new Error("Embedding identity normalization is required.");
|
|
15
|
+
}
|
|
16
|
+
if (typeof input.prefixScheme !== "string" || input.prefixScheme.trim() === "") {
|
|
17
|
+
throw new Error("Embedding identity prefixScheme is required.");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
3
20
|
export function fingerprintEmbeddingIdentity(input) {
|
|
4
|
-
|
|
21
|
+
assertShape(input);
|
|
22
|
+
const raw = [
|
|
23
|
+
ENGINE_EMBED_META_VERSION,
|
|
24
|
+
input.provider,
|
|
25
|
+
input.model,
|
|
26
|
+
String(input.dimensions),
|
|
27
|
+
String(input.contextLength),
|
|
28
|
+
String(input.mrlDim),
|
|
29
|
+
input.normalization,
|
|
30
|
+
input.prefixScheme,
|
|
31
|
+
].join("\u0000");
|
|
5
32
|
return createHash("sha256").update(raw).digest("hex");
|
|
6
33
|
}
|
|
7
34
|
export function makeEmbeddingIdentity(input) {
|
|
35
|
+
assertShape(input);
|
|
8
36
|
return {
|
|
9
37
|
provider: input.provider,
|
|
10
38
|
model: input.model,
|
|
11
39
|
dimensions: input.dimensions,
|
|
40
|
+
contextLength: input.contextLength,
|
|
41
|
+
mrlDim: input.mrlDim,
|
|
42
|
+
normalization: input.normalization,
|
|
43
|
+
prefixScheme: input.prefixScheme,
|
|
12
44
|
fingerprint: fingerprintEmbeddingIdentity(input),
|
|
13
45
|
};
|
|
14
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../../src/kernel/engine/embed/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,yBAAyB,EAA0B,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../../src/kernel/engine/embed/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,yBAAyB,EAA0B,MAAM,YAAY,CAAC;AAe/E,SAAS,WAAW,CAAC,KAA6B;IAChD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC,EAAE,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;IAClF,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,aAAa,KAAK,QAAQ,IAAI,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACjF,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ,IAAI,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC/E,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,KAGnB;IACxB,WAAW,CAAC,KAAK,CAAC,CAAC;IACnB,MAAM,GAAG,GAAG;QACV,yBAAyB;QACzB,KAAK,CAAC,QAAQ;QACd,KAAK,CAAC,KAAK;QACX,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC;QACxB,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;QACpB,KAAK,CAAC,aAAa;QACnB,KAAK,CAAC,YAAY;KACnB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjB,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAGZ;IACxB,WAAW,CAAC,KAAK,CAAC,CAAC;IACnB,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,WAAW,EAAE,4BAA4B,CAAC,KAAK,CAAC;KACjD,CAAC;AACJ,CAAC"}
|