@bartolli/kmd 0.4.0 → 0.5.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/dist/kmd.mjs CHANGED
@@ -15,6 +15,10 @@ var __export = (target, all) => {
15
15
  };
16
16
 
17
17
  // ../db/src/database.ts
18
+ import { createHash } from "node:crypto";
19
+ import { realpathSync } from "node:fs";
20
+ import { homedir } from "node:os";
21
+ import { basename, join, resolve } from "node:path";
18
22
  import { DatabaseSync } from "node:sqlite";
19
23
  function openDatabase(dbPath) {
20
24
  const db = new DatabaseSync(dbPath);
@@ -23,6 +27,34 @@ function openDatabase(dbPath) {
23
27
  db.exec(SCHEMA);
24
28
  return db;
25
29
  }
30
+ function indexRootDir() {
31
+ const home = process.env.KMD_HOME ?? join(homedir(), ".kmd");
32
+ return join(home, "db");
33
+ }
34
+ function canonicalVaultRoot(vaultRoot2) {
35
+ try {
36
+ return realpathSync(vaultRoot2);
37
+ } catch {
38
+ return resolve(vaultRoot2);
39
+ }
40
+ }
41
+ function vaultKey(vaultRoot2) {
42
+ const canonical = canonicalVaultRoot(vaultRoot2);
43
+ const hash = createHash("sha256").update(canonical).digest("hex").slice(0, 8);
44
+ return `${basename(canonical)}-${hash}`;
45
+ }
46
+ function resolveIndexPath(vaultRoot2) {
47
+ return join(indexRootDir(), vaultKey(vaultRoot2), "index.db");
48
+ }
49
+ function getMeta(db, key) {
50
+ const row = db.prepare("SELECT value FROM meta WHERE key = ?").get(key);
51
+ return row?.value ?? null;
52
+ }
53
+ function setMeta(db, key, value) {
54
+ db.prepare(
55
+ "INSERT INTO meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
56
+ ).run(key, value);
57
+ }
26
58
  var SCHEMA;
27
59
  var init_database = __esm({
28
60
  "../db/src/database.ts"() {
@@ -73,20 +105,25 @@ CREATE TABLE IF NOT EXISTS events (
73
105
  );
74
106
 
75
107
  CREATE INDEX IF NOT EXISTS events_scope_ts ON events(scope, ts DESC);
108
+
109
+ CREATE TABLE IF NOT EXISTS meta (
110
+ key TEXT PRIMARY KEY,
111
+ value TEXT NOT NULL
112
+ );
76
113
  `;
77
114
  }
78
115
  });
79
116
 
80
117
  // ../cli/src/config.ts
81
118
  import { readFile } from "node:fs/promises";
82
- import { join } from "node:path";
119
+ import { join as join2 } from "node:path";
83
120
  import { parse } from "yaml";
84
121
  import { z } from "zod";
85
122
  function kindName(entry) {
86
123
  return typeof entry === "string" ? entry : entry.name;
87
124
  }
88
125
  async function loadVaultConfig(vaultRoot2) {
89
- const path = join(vaultRoot2, "vault.yaml");
126
+ const path = join2(vaultRoot2, "vault.yaml");
90
127
  let raw;
91
128
  try {
92
129
  raw = await readFile(path, "utf8");
@@ -184,11 +221,10 @@ var init_frontmatter = __esm({
184
221
  });
185
222
 
186
223
  // ../cli/src/sync.ts
187
- import { createHash } from "node:crypto";
224
+ import { createHash as createHash2 } from "node:crypto";
188
225
  import { mkdirSync } from "node:fs";
189
226
  import { readdir, readFile as readFile2 } from "node:fs/promises";
190
- import { homedir } from "node:os";
191
- import { join as join2, relative, sep } from "node:path";
227
+ import { dirname, join as join3, relative, sep } from "node:path";
192
228
  import { z as z2 } from "zod";
193
229
  function loadEnv() {
194
230
  const parsed = EnvSchema.safeParse({
@@ -209,20 +245,20 @@ async function walkMarkdown(root, domain) {
209
245
  for (const entry of entries) {
210
246
  if (entry.name.startsWith(".")) continue;
211
247
  if (entry.isDirectory()) {
212
- await recurse(join2(dir, entry.name));
248
+ await recurse(join3(dir, entry.name));
213
249
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
214
- out.push(join2(dir, entry.name));
250
+ out.push(join3(dir, entry.name));
215
251
  }
216
252
  }
217
253
  }
218
- await recurse(join2(root, domain));
254
+ await recurse(join3(root, domain));
219
255
  return out;
220
256
  }
221
257
  function toRelativePath(root, absolute) {
222
258
  return relative(root, absolute).split(sep).join("/");
223
259
  }
224
260
  function sha256(content) {
225
- return createHash("sha256").update(content).digest("hex");
261
+ return createHash2("sha256").update(content).digest("hex");
226
262
  }
227
263
  function extractWikilinks(body) {
228
264
  const links = [];
@@ -339,12 +375,11 @@ function syncPage(db, fields) {
339
375
  }
340
376
  async function runSync() {
341
377
  const env = loadEnv();
342
- const dbDir = join2(homedir(), ".kmd", "db");
343
- const dbPath = join2(dbDir, "index.db");
378
+ const dbPath = resolveIndexPath(env.WIKI_VAULT);
344
379
  console.log(`sync: ${env.WIKI_VAULT} \u2192 ${dbPath}`);
345
380
  const vaultConfig = await loadVaultConfig(env.WIKI_VAULT);
346
381
  const scopes = new Set(Object.keys(vaultConfig.scopes));
347
- mkdirSync(dbDir, { recursive: true });
382
+ mkdirSync(dirname(dbPath), { recursive: true });
348
383
  const db = openDatabase(dbPath);
349
384
  try {
350
385
  const files = [];
@@ -384,6 +419,8 @@ async function runSync() {
384
419
  console.warn("no indexable pages found; skipping orphan deletion (safety)");
385
420
  }
386
421
  db.exec("INSERT INTO pages_fts(pages_fts) VALUES('rebuild')");
422
+ setMeta(db, "vault_root", canonicalVaultRoot(env.WIKI_VAULT));
423
+ setMeta(db, "last_synced", (/* @__PURE__ */ new Date()).toISOString());
387
424
  console.log(
388
425
  `done: ${changed} changed, ${unchanged} unchanged, ${skipped} skipped, ${pagesDeleted} pages deleted, ${linksDeleted} link orphans cleared`
389
426
  );
@@ -418,7 +455,7 @@ var init_sync = __esm({
418
455
 
419
456
  // ../cli/src/validate.ts
420
457
  import { readFile as readFile3, stat } from "node:fs/promises";
421
- import { join as join3 } from "node:path";
458
+ import { join as join4 } from "node:path";
422
459
  function hasIndexableTitle(data) {
423
460
  return typeof data.title === "string" && data.title.trim() !== "";
424
461
  }
@@ -576,7 +613,7 @@ function checkScopePath(relPath, data) {
576
613
  function refTarget(value) {
577
614
  if (typeof value !== "string") return null;
578
615
  const trimmed = value.trim();
579
- return trimmed === "" ? null : basename(trimmed);
616
+ return trimmed === "" ? null : basename2(trimmed);
580
617
  }
581
618
  function refTargets(value) {
582
619
  if (Array.isArray(value)) {
@@ -592,7 +629,7 @@ function checkBodyLinks(relPath, body, refIndex) {
592
629
  const findings = [];
593
630
  for (const link of extractWikilinks(stripCode(body))) {
594
631
  if (!link.target.endsWith(".md")) continue;
595
- if (!refIndex.has(basename(link.target))) {
632
+ if (!refIndex.has(basename2(link.target))) {
596
633
  findings.push({
597
634
  path: relPath,
598
635
  rule: "dangling-link",
@@ -689,7 +726,7 @@ function validatePage(relPath, raw, cfg, refIndex) {
689
726
  function hasErrors(findings) {
690
727
  return findings.some((f) => f.severity === "error");
691
728
  }
692
- function basename(relPath) {
729
+ function basename2(relPath) {
693
730
  const last = relPath.split("/").pop() ?? relPath;
694
731
  return last.replace(/\.md$/, "");
695
732
  }
@@ -697,7 +734,7 @@ function validateSupersession(pages) {
697
734
  const adrs = /* @__PURE__ */ new Map();
698
735
  for (const { path, data } of pages) {
699
736
  if (data.kind !== "adr") continue;
700
- adrs.set(basename(path), {
737
+ adrs.set(basename2(path), {
701
738
  path,
702
739
  supersedes: refTargets(data.supersedes),
703
740
  supersededBy: refTargets(data.superseded_by)
@@ -743,7 +780,7 @@ function validateAmbiguousLinks(pages, basenameToPaths) {
743
780
  const here = locationKey(path);
744
781
  for (const link of extractWikilinks(stripCode(body))) {
745
782
  if (!link.target.endsWith(".md") || link.target.includes("/")) continue;
746
- const base = basename(link.target);
783
+ const base = basename2(link.target);
747
784
  const owners = basenameToPaths.get(base);
748
785
  if (!owners || owners.length < 2) continue;
749
786
  if (here !== null && owners.some((p) => locationKey(p) === here)) continue;
@@ -765,7 +802,7 @@ async function validateVault(root) {
765
802
  }));
766
803
  const basenameToPaths = /* @__PURE__ */ new Map();
767
804
  for (const f of all) {
768
- const b = basename(f.relPath);
805
+ const b = basename2(f.relPath);
769
806
  const owners = basenameToPaths.get(b);
770
807
  if (owners) owners.push(f.relPath);
771
808
  else basenameToPaths.set(b, [f.relPath]);
@@ -790,7 +827,7 @@ async function validateVault(root) {
790
827
  for (const name of customKindNames(cfg)) {
791
828
  const file = `templates/${name}.md`;
792
829
  try {
793
- await stat(join3(root, file));
830
+ await stat(join4(root, file));
794
831
  } catch {
795
832
  findings.push({
796
833
  path: file,
@@ -862,10 +899,14 @@ var cli_exports = {};
862
899
  __export(cli_exports, {
863
900
  main: () => main,
864
901
  resolveCli: () => resolveCli,
902
+ runConfig: () => runConfig,
903
+ runDbReset: () => runDbReset,
865
904
  runSyncCommand: () => runSyncCommand,
866
905
  runValidate: () => runValidate,
867
906
  vaultRoot: () => vaultRoot
868
907
  });
908
+ import { existsSync, readdirSync, rmSync } from "node:fs";
909
+ import { dirname as dirname2, join as join5 } from "node:path";
869
910
  import { parseArgs } from "node:util";
870
911
  function resolveCli(argv) {
871
912
  const { positionals: positionals2 } = parseArgs({ args: argv, allowPositionals: true, strict: false });
@@ -910,6 +951,76 @@ async function runSyncCommand() {
910
951
  }
911
952
  await runSync();
912
953
  }
954
+ function describeVault(root) {
955
+ const vault = canonicalVaultRoot(root);
956
+ const index = resolveIndexPath(vault);
957
+ let synced = "never";
958
+ if (existsSync(index)) {
959
+ const db = openDatabase(index);
960
+ try {
961
+ synced = getMeta(db, "last_synced") ?? "never";
962
+ } finally {
963
+ db.close();
964
+ }
965
+ }
966
+ return { vault, index, synced };
967
+ }
968
+ function printVault(d) {
969
+ console.log(`vault: ${d.vault}`);
970
+ console.log(`index: ${d.index}`);
971
+ console.log(`synced: ${d.synced}`);
972
+ }
973
+ function knownVaults() {
974
+ const root = indexRootDir();
975
+ if (!existsSync(root)) return [];
976
+ const known = [];
977
+ for (const entry of readdirSync(root, { withFileTypes: true })) {
978
+ if (!entry.isDirectory()) continue;
979
+ const index = join5(root, entry.name, "index.db");
980
+ if (!existsSync(index)) continue;
981
+ const db = openDatabase(index);
982
+ try {
983
+ const vault = getMeta(db, "vault_root");
984
+ if (vault === null) continue;
985
+ known.push({ vault, index, synced: getMeta(db, "last_synced") ?? "never" });
986
+ } finally {
987
+ db.close();
988
+ }
989
+ }
990
+ return known;
991
+ }
992
+ async function runConfig() {
993
+ const root = process.env.WIKI_VAULT;
994
+ if (root) {
995
+ printVault(describeVault(root));
996
+ return;
997
+ }
998
+ const known = knownVaults();
999
+ if (known.length === 0) {
1000
+ console.error(
1001
+ "no vault specified and none known \u2014 pass a vault root, set WIKI_VAULT, or run `kmd sync <vault-root>` once"
1002
+ );
1003
+ process.exit(1);
1004
+ }
1005
+ known.forEach((d, i) => {
1006
+ if (i > 0) console.log("");
1007
+ printVault(d);
1008
+ });
1009
+ }
1010
+ async function runDbReset() {
1011
+ const root = process.env.WIKI_VAULT;
1012
+ if (!root) {
1013
+ console.error("usage: kmd db reset [<vault-root>] (or set WIKI_VAULT)");
1014
+ process.exit(2);
1015
+ }
1016
+ const dir = dirname2(resolveIndexPath(root));
1017
+ if (!existsSync(dir)) {
1018
+ console.log(`${dir} does not exist \u2014 nothing to reset`);
1019
+ return;
1020
+ }
1021
+ rmSync(dir, { recursive: true, force: true });
1022
+ console.log(`deleted ${dir}`);
1023
+ }
913
1024
  async function main() {
914
1025
  const resolution = resolveCli(process.argv.slice(2));
915
1026
  if (resolution.kind === "error") {
@@ -925,6 +1036,7 @@ async function main() {
925
1036
  var init_cli = __esm({
926
1037
  "../cli/src/cli.ts"() {
927
1038
  "use strict";
1039
+ init_database();
928
1040
  init_sync();
929
1041
  init_validate();
930
1042
  }
@@ -961,13 +1073,13 @@ var init_config2 = __esm({
961
1073
 
962
1074
  // ../mcp/src/db.ts
963
1075
  import { mkdirSync as mkdirSync2 } from "node:fs";
964
- import { homedir as homedir2 } from "node:os";
965
- import { join as join4 } from "node:path";
966
- function createDatabase() {
967
- const dbDir = join4(homedir2(), ".kmd", "db");
968
- const dbPath = join4(dbDir, "index.db");
969
- mkdirSync2(dbDir, { recursive: true });
970
- return openDatabase(dbPath);
1076
+ import { dirname as dirname3 } from "node:path";
1077
+ function createDatabase(vaultRoot2) {
1078
+ const dbPath = resolveIndexPath(vaultRoot2);
1079
+ mkdirSync2(dirname3(dbPath), { recursive: true });
1080
+ const db = openDatabase(dbPath);
1081
+ setMeta(db, "vault_root", canonicalVaultRoot(vaultRoot2));
1082
+ return db;
971
1083
  }
972
1084
  var init_db = __esm({
973
1085
  "../mcp/src/db.ts"() {
@@ -978,8 +1090,8 @@ var init_db = __esm({
978
1090
 
979
1091
  // ../mcp/src/lib/diag.ts
980
1092
  import { appendFileSync, mkdirSync as mkdirSync3 } from "node:fs";
981
- import { homedir as homedir3 } from "node:os";
982
- import { join as join5 } from "node:path";
1093
+ import { homedir as homedir2 } from "node:os";
1094
+ import { join as join6 } from "node:path";
983
1095
  function diag(msg, data) {
984
1096
  try {
985
1097
  const line = data ? `${(/* @__PURE__ */ new Date()).toISOString()} pid=${process.pid} ${msg} ${JSON.stringify(data)}
@@ -993,8 +1105,8 @@ var DIAG_DIR, DIAG_LOG_PATH;
993
1105
  var init_diag = __esm({
994
1106
  "../mcp/src/lib/diag.ts"() {
995
1107
  "use strict";
996
- DIAG_DIR = join5(homedir3(), ".local", "state", "wiki-mcp");
997
- DIAG_LOG_PATH = join5(DIAG_DIR, "server.log");
1108
+ DIAG_DIR = join6(homedir2(), ".local", "state", "wiki-mcp");
1109
+ DIAG_LOG_PATH = join6(DIAG_DIR, "server.log");
998
1110
  try {
999
1111
  mkdirSync3(DIAG_DIR, { recursive: true });
1000
1112
  } catch {
@@ -1023,14 +1135,14 @@ var init_logger = __esm({
1023
1135
 
1024
1136
  // ../mcp/src/vault-config.ts
1025
1137
  import { readFile as readFile4 } from "node:fs/promises";
1026
- import { join as join6 } from "node:path";
1138
+ import { join as join7 } from "node:path";
1027
1139
  import { parse as parse2 } from "yaml";
1028
1140
  import { z as z4 } from "zod";
1029
1141
  function kindName2(entry) {
1030
1142
  return typeof entry === "string" ? entry : entry.name;
1031
1143
  }
1032
1144
  async function loadVaultConfig2(vaultRoot2) {
1033
- const path = join6(vaultRoot2, "vault.yaml");
1145
+ const path = join7(vaultRoot2, "vault.yaml");
1034
1146
  let raw;
1035
1147
  try {
1036
1148
  raw = await readFile4(path, "utf8");
@@ -1157,7 +1269,7 @@ function buildVocabulary(config) {
1157
1269
  }
1158
1270
  return lines.join("\n");
1159
1271
  }
1160
- function registerAuthoringResource(mcp, _vaultRoot, vaultConfig) {
1272
+ function registerAuthoringResource(mcp, vaultRoot2, vaultConfig) {
1161
1273
  mcp.registerResource(
1162
1274
  "Authoring guide",
1163
1275
  "wiki://authoring",
@@ -1169,6 +1281,8 @@ function registerAuthoringResource(mcp, _vaultRoot, vaultConfig) {
1169
1281
  const sections = [
1170
1282
  "# Wiki authoring guide",
1171
1283
  "",
1284
+ `Vault root: \`${canonicalVaultRoot(vaultRoot2)}\` \u2014 every page path below is relative to it; write files and run \`kmd validate\` / \`kmd sync\` against it.`,
1285
+ "",
1172
1286
  buildKindSelector(vaultConfig.kinds),
1173
1287
  "",
1174
1288
  buildVocabulary(vaultConfig),
@@ -1197,6 +1311,7 @@ var KIND_PEDAGOGY, DEFAULT_AUTHORING_RULES, DEFAULT_SYNC_PROTOCOL, CANONICAL_STA
1197
1311
  var init_authoring = __esm({
1198
1312
  "../mcp/src/resources/authoring.ts"() {
1199
1313
  "use strict";
1314
+ init_database();
1200
1315
  init_vault_config();
1201
1316
  KIND_PEDAGOGY = /* @__PURE__ */ new Map([
1202
1317
  [
@@ -1315,7 +1430,7 @@ var init_authoring = __esm({
1315
1430
 
1316
1431
  // ../mcp/src/resources/templates.ts
1317
1432
  import { readFile as readFile5 } from "node:fs/promises";
1318
- import { join as join7 } from "node:path";
1433
+ import { join as join8 } from "node:path";
1319
1434
  function customTemplates(config) {
1320
1435
  const specs = [];
1321
1436
  for (const entry of config.kinds) {
@@ -1330,7 +1445,7 @@ function customTemplates(config) {
1330
1445
  return specs;
1331
1446
  }
1332
1447
  function registerTemplateResources(mcp, vaultRoot2, vaultConfig) {
1333
- const dir = join7(vaultRoot2, "templates");
1448
+ const dir = join8(vaultRoot2, "templates");
1334
1449
  const templates = [...TEMPLATES, ...customTemplates(vaultConfig)];
1335
1450
  for (const tmpl of templates) {
1336
1451
  mcp.registerResource(
@@ -1340,7 +1455,7 @@ function registerTemplateResources(mcp, vaultRoot2, vaultConfig) {
1340
1455
  async (uri) => {
1341
1456
  let text;
1342
1457
  try {
1343
- text = await readFile5(join7(dir, tmpl.file), "utf8");
1458
+ text = await readFile5(join8(dir, tmpl.file), "utf8");
1344
1459
  } catch (err) {
1345
1460
  throw new Error(`template file missing: templates/${tmpl.file} (${tmpl.uri})`, {
1346
1461
  cause: err
@@ -1521,14 +1636,14 @@ var init_toolResponse = __esm({
1521
1636
 
1522
1637
  // ../mcp/src/tools/prime.ts
1523
1638
  import { readFile as readFile6 } from "node:fs/promises";
1524
- import { basename as basename2, join as join8 } from "node:path";
1639
+ import { basename as basename3, join as join9 } from "node:path";
1525
1640
  import { z as z5 } from "zod";
1526
1641
  function pathSlug(p) {
1527
- return basename2(p).replace(/\.md$/, "");
1642
+ return basename3(p).replace(/\.md$/, "");
1528
1643
  }
1529
1644
  async function readIndexFm(vaultRoot2, scope) {
1530
1645
  try {
1531
- const raw = await readFile6(join8(vaultRoot2, "projects", scope, "index.md"), "utf8");
1646
+ const raw = await readFile6(join9(vaultRoot2, "projects", scope, "index.md"), "utf8");
1532
1647
  return parseFrontmatter2(raw).data;
1533
1648
  } catch {
1534
1649
  return {};
@@ -1536,7 +1651,7 @@ async function readIndexFm(vaultRoot2, scope) {
1536
1651
  }
1537
1652
  async function readPrimer(vaultRoot2, scope) {
1538
1653
  try {
1539
- const raw = await readFile6(join8(vaultRoot2, "projects", scope, "primer.md"), "utf8");
1654
+ const raw = await readFile6(join9(vaultRoot2, "projects", scope, "primer.md"), "utf8");
1540
1655
  return parseFrontmatter2(raw).content.trim().replace(/^#\s+[^\n]+\n+/, "");
1541
1656
  } catch {
1542
1657
  return "";
@@ -1601,6 +1716,7 @@ async function prime(deps, input) {
1601
1716
  for (const row of counts) countsRecord[row.kind] = Number(row.count);
1602
1717
  const data = {
1603
1718
  scope,
1719
+ vault_root: canonicalVaultRoot(vaultRoot2),
1604
1720
  title: fm.title ?? null,
1605
1721
  methodology: fm.methodology ?? null,
1606
1722
  phase: typeof fm.phase === "number" ? fm.phase : null,
@@ -1644,6 +1760,7 @@ function renderMarkdown(d, config, task) {
1644
1760
  const header = phaseLabel ? `${d.scope} \u2014 ${phaseLabel}` : d.scope;
1645
1761
  lines.push(`# ${header}`);
1646
1762
  if (d.summary) lines.push(d.summary);
1763
+ lines.push(`Vault root: \`${d.vault_root}\``);
1647
1764
  if (d.primer) {
1648
1765
  lines.push("", "## Primer", d.primer);
1649
1766
  }
@@ -1723,6 +1840,7 @@ var PrimeInputSchema;
1723
1840
  var init_prime = __esm({
1724
1841
  "../mcp/src/tools/prime.ts"() {
1725
1842
  "use strict";
1843
+ init_database();
1726
1844
  init_frontmatter2();
1727
1845
  init_fts();
1728
1846
  init_toolResponse();
@@ -1853,7 +1971,7 @@ async function startMcpServer() {
1853
1971
  { vault: config.wikiVault, serverName: config.serverName, serverVersion: config.serverVersion },
1854
1972
  "starting wiki-mcp on stdio"
1855
1973
  );
1856
- const db = createDatabase();
1974
+ const db = createDatabase(config.wikiVault);
1857
1975
  diag("database opened");
1858
1976
  const mcp = buildServer({
1859
1977
  name: config.serverName,
@@ -1899,10 +2017,11 @@ import { parseArgs as parseArgs2 } from "node:util";
1899
2017
  var USAGE = `usage: kmd <command> [options]
1900
2018
 
1901
2019
  commands:
1902
- sync vault \u2192 index sync (runs validate first)
1903
- validate [<path>] deterministic vault checker (default: $WIKI_VAULT)
1904
- mcp [<vault-root>] start the stdio MCP server (default: $WIKI_VAULT)
1905
- db reset delete and recreate the index
2020
+ sync vault \u2192 index sync (runs validate first)
2021
+ validate [<path>] deterministic vault checker (default: $WIKI_VAULT)
2022
+ mcp [<vault-root>] start the stdio MCP server (default: $WIKI_VAULT)
2023
+ config [<vault-root>] print vault + index resolution; with no vault, list known vaults
2024
+ db reset [<vault-root>] delete the vault's index (default: $WIKI_VAULT)
1906
2025
 
1907
2026
  options:
1908
2027
  --version print version
@@ -1942,25 +2061,20 @@ async function run() {
1942
2061
  await startMcpServer2();
1943
2062
  break;
1944
2063
  }
2064
+ case "config": {
2065
+ applyVaultRoot(1);
2066
+ const { runConfig: runConfig2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
2067
+ await runConfig2();
2068
+ break;
2069
+ }
1945
2070
  case "db": {
1946
2071
  const sub = positionals[1];
1947
2072
  if (sub === "reset") {
1948
- const { homedir: homedir4 } = await import("node:os");
1949
- const { join: join9 } = await import("node:path");
1950
- const { unlinkSync } = await import("node:fs");
1951
- const dbPath = join9(homedir4(), ".kmd", "db", "index.db");
1952
- let deleted = false;
1953
- for (const suffix of ["", "-wal", "-shm"]) {
1954
- try {
1955
- unlinkSync(dbPath + suffix);
1956
- deleted = true;
1957
- } catch (err) {
1958
- if (err.code !== "ENOENT") throw err;
1959
- }
1960
- }
1961
- console.log(deleted ? `deleted ${dbPath}` : `${dbPath} does not exist \u2014 nothing to reset`);
2073
+ applyVaultRoot(2);
2074
+ const { runDbReset: runDbReset2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
2075
+ await runDbReset2();
1962
2076
  } else {
1963
- console.error(sub ? `unknown db subcommand: ${sub}` : "usage: kmd db reset");
2077
+ console.error(sub ? `unknown db subcommand: ${sub}` : "usage: kmd db reset [<vault-root>]");
1964
2078
  process.exit(2);
1965
2079
  }
1966
2080
  break;
@@ -1968,10 +2082,10 @@ async function run() {
1968
2082
  case "--version":
1969
2083
  case "-v": {
1970
2084
  const { readFileSync } = await import("node:fs");
1971
- const { join: join9, dirname } = await import("node:path");
2085
+ const { join: join10, dirname: dirname4 } = await import("node:path");
1972
2086
  const { fileURLToPath } = await import("node:url");
1973
- const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
1974
- const pkg = JSON.parse(readFileSync(join9(pkgDir, "package.json"), "utf8"));
2087
+ const pkgDir = dirname4(dirname4(fileURLToPath(import.meta.url)));
2088
+ const pkg = JSON.parse(readFileSync(join10(pkgDir, "package.json"), "utf8"));
1975
2089
  console.log(pkg.version);
1976
2090
  break;
1977
2091
  }
package/dist/kmd.mjs.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../db/src/database.ts", "../../cli/src/config.ts", "../../cli/src/frontmatter.ts", "../../cli/src/sync.ts", "../../cli/src/validate.ts", "../../cli/src/cli.ts", "../../mcp/src/config.ts", "../../mcp/src/db.ts", "../../mcp/src/lib/diag.ts", "../../mcp/src/lib/logger.ts", "../../mcp/src/vault-config.ts", "../../mcp/src/resources/authoring.ts", "../../mcp/src/resources/templates.ts", "../../mcp/src/frontmatter.ts", "../../mcp/src/lib/fts.ts", "../../mcp/src/lib/toolResponse.ts", "../../mcp/src/tools/prime.ts", "../../mcp/src/tools/search.ts", "../../mcp/src/server.ts", "../../mcp/src/start.ts", "../bin/kmd.ts"],
4
- "sourcesContent": ["import { DatabaseSync } from 'node:sqlite';\n\nconst SCHEMA = `\nCREATE TABLE IF NOT EXISTS pages (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n path TEXT UNIQUE NOT NULL,\n title TEXT NOT NULL,\n kind TEXT NOT NULL,\n scope TEXT,\n topic TEXT,\n status TEXT NOT NULL DEFAULT 'draft',\n summary TEXT,\n tags TEXT,\n updated TEXT,\n body TEXT,\n content_hash TEXT,\n meta TEXT\n);\n\nCREATE INDEX IF NOT EXISTS pages_scope_kind ON pages(scope, kind, status);\nCREATE INDEX IF NOT EXISTS pages_topic_kind ON pages(topic, kind, status);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS pages_fts USING fts5(\n title, summary, body,\n content='pages',\n content_rowid='id'\n);\n\nCREATE TABLE IF NOT EXISTS links (\n source_path TEXT NOT NULL,\n target_path TEXT NOT NULL,\n link_text TEXT,\n PRIMARY KEY (source_path, target_path)\n);\n\nCREATE INDEX IF NOT EXISTS links_source ON links(source_path);\nCREATE INDEX IF NOT EXISTS links_target ON links(target_path);\n\nCREATE TABLE IF NOT EXISTS events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n ts TEXT DEFAULT (datetime('now')),\n scope TEXT,\n operation TEXT NOT NULL,\n path TEXT,\n note TEXT\n);\n\nCREATE INDEX IF NOT EXISTS events_scope_ts ON events(scope, ts DESC);\n`;\n\nexport function openDatabase(dbPath: string): DatabaseSync {\n const db = new DatabaseSync(dbPath);\n db.exec('PRAGMA journal_mode = WAL');\n db.exec('PRAGMA foreign_keys = ON');\n db.exec(SCHEMA);\n return db;\n}\n", "import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parse } from 'yaml';\nimport { z } from 'zod';\n\nconst ScopeSchema = z.object({\n repo: z.string().optional(),\n methodology: z.string().optional(),\n status: z.string()\n});\n\nconst KindEntrySchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n signal: z.string(),\n where: z.string()\n })\n]);\n\nconst VaultConfigSchema = z\n .object({\n scopes: z.record(z.string(), ScopeSchema),\n kinds: z.array(KindEntrySchema),\n statuses: z.array(z.string()),\n methodologies: z.array(z.string()),\n tags: z.object({\n canonical: z.array(z.string()),\n aliases: z.record(z.string(), z.string())\n }),\n authoring_rules: z.string().optional(),\n authoring_rules_extra: z.string().optional(),\n sync_protocol: z.string().optional(),\n sync_protocol_extra: z.string().optional()\n })\n .superRefine((config, ctx) => {\n for (const [name, scope] of Object.entries(config.scopes)) {\n if (scope.methodology !== undefined && !config.methodologies.includes(scope.methodology)) {\n ctx.addIssue({\n code: 'custom',\n path: ['scopes', name, 'methodology'],\n message: `\"${scope.methodology}\" is not in the methodologies list`\n });\n }\n }\n });\n\nexport type KindEntry = z.infer<typeof KindEntrySchema>;\nexport type VaultConfig = z.infer<typeof VaultConfigSchema>;\n\n/** Kind name of a `kinds` entry \u2014 plain string, or the object form's `name`. */\nexport function kindName(entry: KindEntry): string {\n return typeof entry === 'string' ? entry : entry.name;\n}\n\n/**\n * Kinds with built-in engine pedagogy (kind-selector rows; most also carry a\n * served template). An object-form entry with one of these names rewords its\n * selector row only \u2014 it never creates custom-template expectations.\n */\nexport const BUILT_IN_KINDS: ReadonlySet<string> = new Set([\n 'project',\n 'spec',\n 'adr',\n 'plan',\n 'story',\n 'ops',\n 'topic',\n 'article',\n 'src',\n 'note',\n 'artifact',\n 'prompt'\n]);\n\n/**\n * Load and validate `$vaultRoot/vault.yaml` \u2014 the single source of truth for\n * the controlled vocabulary. Throws (fail-loud) when the file is missing or\n * the contents don't satisfy the schema; sync must not run on partial\n * vocabulary.\n */\nexport async function loadVaultConfig(vaultRoot: string): Promise<VaultConfig> {\n const path = join(vaultRoot, 'vault.yaml');\n let raw: string;\n try {\n raw = await readFile(path, 'utf8');\n } catch (err) {\n throw new Error(`vault.yaml not found at ${path}`, { cause: err });\n }\n const parsed = VaultConfigSchema.safeParse(parse(raw));\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` - ${i.path.join('.') || '(root)'}: ${i.message}`)\n .join('\\n');\n throw new Error(`Invalid vault.yaml at ${path}:\\n${issues}`);\n }\n return parsed.data;\n}\n", "import { parse as parseYaml } from 'yaml';\n\nexport interface ParsedFrontmatter {\n data: Record<string, unknown>;\n content: string;\n}\n\n// Leading `---` block, YAML, closing `---`, then one consumed newline. Matches\n// gray-matter's delimiter handling; the closing `---` must be on its own line so\n// `---` rules inside the body are left intact.\nconst FRONTMATTER_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n?---\\r?\\n?/;\n\n/**\n * Split a page's frontmatter from its body using the `yaml` parser. Throws\n * (deterministically, no cache) when the frontmatter is not valid YAML \u2014 this is\n * the failure mode `wiki validate` exists to catch. A page with no leading\n * delimiter parses to empty data and the whole input as body.\n */\nexport function parseFrontmatter(raw: string): ParsedFrontmatter {\n const match = FRONTMATTER_RE.exec(raw);\n if (!match) {\n return { data: {}, content: raw };\n }\n const yamlText = match[1] ?? '';\n const content = raw.slice(match[0].length);\n if (yamlText.trim() === '') {\n return { data: {}, content };\n }\n const parsed = parseYaml(yamlText);\n const data =\n parsed !== null && typeof parsed === 'object' ? (parsed as Record<string, unknown>) : {};\n return { data, content };\n}\n", "import { createHash } from 'node:crypto';\nimport { mkdirSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join, relative, sep } from 'node:path';\nimport type { DatabaseSync } from 'node:sqlite';\nimport { openDatabase } from '@llm-wiki/db/database';\nimport { z } from 'zod';\nimport { loadVaultConfig } from './config.js';\nimport { type ParsedFrontmatter, parseFrontmatter } from './frontmatter.js';\n\nconst EnvSchema = z.object({\n WIKI_VAULT: z.string().min(1)\n});\n\n// Scan only the three content domains. raw/, templates/, .obsidian/, .git/\n// are intentionally excluded by the design.\nexport const SCAN_DOMAINS = ['projects', 'research', 'notes'] as const;\n\n// [[target]], [[target|display]], [[target#heading]], [[target^block]]\nconst WIKILINK_RE = /\\[\\[([^\\]|#^]+)(?:[#^][^\\]|]*)?(?:\\|([^\\]]+))?\\]\\]/g;\n\ninterface Frontmatter {\n title?: string;\n kind?: string;\n status?: string;\n summary?: string;\n tags?: string[];\n updated?: string | Date;\n}\n\n// Frontmatter keys that already map to first-class indexed columns. Anything\n// outside this set flows into the `meta` JSONB column verbatim, so future\n// vocabulary extensions (e.g. story.triage_state, story.category) become\n// queryable without further schema changes.\nconst INDEXED_FRONTMATTER_KEYS = new Set<string>([\n 'title',\n 'kind',\n 'status',\n 'summary',\n 'tags',\n 'updated',\n 'scope',\n 'topic'\n]);\n\ninterface WikiLink {\n target: string;\n text: string | null;\n}\n\ninterface PageFields {\n path: string;\n title: string;\n kind: string;\n scope: string | null;\n topic: string | null;\n status: string;\n summary: string | null;\n tags: string[] | null;\n updated: string | null;\n body: string;\n hash: string;\n meta: Record<string, unknown> | null;\n}\n\ntype SyncResult = 'changed' | 'unchanged' | 'skipped';\n\nfunction loadEnv(): { WIKI_VAULT: string } {\n const parsed = EnvSchema.safeParse({\n WIKI_VAULT: process.env.WIKI_VAULT\n });\n if (!parsed.success) {\n console.error('invalid env:');\n console.error(parsed.error.format());\n process.exit(1);\n }\n return parsed.data;\n}\n\nexport async function walkMarkdown(root: string, domain: string): Promise<string[]> {\n const out: string[] = [];\n async function recurse(dir: string): Promise<void> {\n // null when the domain dir doesn't exist yet \u2014 fine, nothing to walk.\n const entries = await readdir(dir, { withFileTypes: true }).catch(() => null);\n if (!entries) return;\n for (const entry of entries) {\n if (entry.name.startsWith('.')) continue;\n if (entry.isDirectory()) {\n await recurse(join(dir, entry.name));\n } else if (entry.isFile() && entry.name.endsWith('.md')) {\n out.push(join(dir, entry.name));\n }\n }\n }\n await recurse(join(root, domain));\n return out;\n}\n\nexport function toRelativePath(root: string, absolute: string): string {\n return relative(root, absolute).split(sep).join('/');\n}\n\nfunction sha256(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nexport function extractWikilinks(body: string): WikiLink[] {\n const links: WikiLink[] = [];\n const seen = new Set<string>();\n for (const match of body.matchAll(WIKILINK_RE)) {\n const rawTarget = match[1]?.trim() ?? '';\n if (!rawTarget) continue;\n // Treat any existing extension as authoritative (handles embeds of\n // `.base`, `.png`, `.pdf`, etc.); only append `.md` when the target\n // is bare.\n const hasExt = /\\.[a-zA-Z0-9]+$/.test(rawTarget);\n const target = hasExt ? rawTarget : `${rawTarget}.md`;\n const text = match[2]?.trim() ?? null;\n const key = `${target}|${text ?? ''}`;\n if (seen.has(key)) continue;\n seen.add(key);\n links.push({ target, text });\n }\n return links;\n}\n\n/**\n * Path is authoritative for scope/topic. Frontmatter may also carry these\n * (for human readability) but sync trusts the filesystem.\n *\n * projects/{scope}/... \u2192 scope = first segment\n * research/{topic}/... \u2192 topic = first segment\n * notes/... \u2192 both null\n */\nexport function deriveLocation(relPath: string): { scope: string | null; topic: string | null } {\n const segments = relPath.split('/');\n const domain = segments[0];\n if (domain === 'projects' && segments.length >= 2 && segments[1]) {\n return { scope: segments[1], topic: null };\n }\n if (domain === 'research' && segments.length >= 2 && segments[1]) {\n return { scope: null, topic: segments[1] };\n }\n return { scope: null, topic: null };\n}\n\n/**\n * Build the page row from frontmatter + path. Returns `null` to signal\n * \"skip this file\" (intentionally not indexed).\n *\n * Skip rules:\n * - No `title` in frontmatter \u2192 narrative-only page (e.g., primer.md).\n * - No `kind` AND not under notes/ \u2192 authoring incomplete; warn.\n *\n * Notes are the one place where `kind` is implied by location.\n */\nexport function buildPageFields(\n relPath: string,\n raw: string,\n parsed: ParsedFrontmatter,\n knownScopes: ReadonlySet<string>\n): PageFields | null {\n const fm = parsed.data as Frontmatter;\n if (!fm.title) {\n return null;\n }\n\n let kind = fm.kind;\n if (!kind) {\n if (relPath.startsWith('notes/')) {\n kind = 'note';\n } else {\n console.warn(` skip: ${relPath} \u2014 has title but missing kind`);\n return null;\n }\n }\n\n const { scope, topic } = deriveLocation(relPath);\n if (scope !== null && !knownScopes.has(scope)) {\n throw new Error(\n `unknown scope \"${scope}\" for ${relPath} \u2014 add it to vault.yaml or remove the page`\n );\n }\n const updated =\n fm.updated instanceof Date\n ? fm.updated.toISOString().slice(0, 10)\n : typeof fm.updated === 'string'\n ? fm.updated.slice(0, 10)\n : null;\n\n const metaEntries = Object.entries(parsed.data as Record<string, unknown>).filter(\n ([k]) => !INDEXED_FRONTMATTER_KEYS.has(k)\n );\n const meta = metaEntries.length > 0 ? Object.fromEntries(metaEntries) : null;\n\n return {\n path: relPath,\n title: fm.title,\n kind,\n scope,\n topic,\n status: fm.status ?? (kind === 'note' ? 'active' : 'draft'),\n summary: fm.summary ?? null,\n tags: Array.isArray(fm.tags) ? fm.tags : null,\n updated,\n body: parsed.content,\n hash: sha256(raw),\n meta\n };\n}\n\nexport function syncPage(db: DatabaseSync, fields: PageFields): SyncResult {\n const existing = db.prepare('SELECT content_hash FROM pages WHERE path = ?').get(fields.path) as\n | { content_hash: string | null }\n | undefined;\n if (existing?.content_hash === fields.hash) {\n return 'unchanged';\n }\n\n const upsert = db.prepare(\n `INSERT INTO pages (path, title, kind, scope, topic, status, summary, tags, updated, body, content_hash, meta)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (path) DO UPDATE SET\n title = EXCLUDED.title,\n kind = EXCLUDED.kind,\n scope = EXCLUDED.scope,\n topic = EXCLUDED.topic,\n status = EXCLUDED.status,\n summary = EXCLUDED.summary,\n tags = EXCLUDED.tags,\n updated = EXCLUDED.updated,\n body = EXCLUDED.body,\n content_hash = EXCLUDED.content_hash,\n meta = EXCLUDED.meta`\n );\n\n upsert.run(\n fields.path,\n fields.title,\n fields.kind,\n fields.scope,\n fields.topic,\n fields.status,\n fields.summary,\n fields.tags ? JSON.stringify(fields.tags) : null,\n fields.updated,\n fields.body,\n fields.hash,\n fields.meta ? JSON.stringify(fields.meta) : null\n );\n\n db.prepare('DELETE FROM links WHERE source_path = ?').run(fields.path);\n const insertLink = db.prepare(\n `INSERT INTO links (source_path, target_path, link_text)\n VALUES (?, ?, ?)\n ON CONFLICT (source_path, target_path) DO NOTHING`\n );\n for (const link of extractWikilinks(fields.body)) {\n insertLink.run(fields.path, link.target, link.text);\n }\n\n return 'changed';\n}\n\nexport async function runSync(): Promise<void> {\n const env = loadEnv();\n const dbDir = join(homedir(), '.kmd', 'db');\n const dbPath = join(dbDir, 'index.db');\n console.log(`sync: ${env.WIKI_VAULT} \u2192 ${dbPath}`);\n\n const vaultConfig = await loadVaultConfig(env.WIKI_VAULT);\n const scopes = new Set(Object.keys(vaultConfig.scopes));\n\n mkdirSync(dbDir, { recursive: true });\n const db = openDatabase(dbPath);\n\n try {\n const files: string[] = [];\n for (const domain of SCAN_DOMAINS) {\n files.push(...(await walkMarkdown(env.WIKI_VAULT, domain)));\n }\n\n const indexedPaths: string[] = [];\n let changed = 0;\n let unchanged = 0;\n let skipped = 0;\n\n for (const file of files) {\n const path = toRelativePath(env.WIKI_VAULT, file);\n const raw = await readFile(file, 'utf8');\n const parsed = parseFrontmatter(raw);\n const fields = buildPageFields(path, raw, parsed, scopes);\n if (!fields) {\n skipped++;\n continue;\n }\n\n const result = syncPage(db, fields);\n if (result === 'changed') {\n changed++;\n } else {\n unchanged++;\n }\n indexedPaths.push(path);\n }\n\n let pagesDeleted = 0;\n let linksDeleted = 0;\n if (indexedPaths.length > 0) {\n const placeholders = indexedPaths.map(() => '?').join(', ');\n const pageResult = db\n .prepare(`DELETE FROM pages WHERE path NOT IN (${placeholders})`)\n .run(...indexedPaths);\n pagesDeleted = Number(pageResult.changes);\n const linkResult = db\n .prepare('DELETE FROM links WHERE source_path NOT IN (SELECT path FROM pages)')\n .run();\n linksDeleted = Number(linkResult.changes);\n } else {\n console.warn('no indexable pages found; skipping orphan deletion (safety)');\n }\n\n db.exec(\"INSERT INTO pages_fts(pages_fts) VALUES('rebuild')\");\n\n console.log(\n `done: ${changed} changed, ${unchanged} unchanged, ${skipped} skipped, ${pagesDeleted} pages deleted, ${linksDeleted} link orphans cleared`\n );\n } finally {\n db.close();\n }\n}\n", "import { readFile, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { BUILT_IN_KINDS, kindName, loadVaultConfig, type VaultConfig } from './config.js';\nimport { parseFrontmatter } from './frontmatter.js';\nimport {\n deriveLocation,\n extractWikilinks,\n SCAN_DOMAINS,\n toRelativePath,\n walkMarkdown\n} from './sync.js';\n\nexport type Severity = 'error' | 'warning';\n\nexport interface Finding {\n path: string;\n rule: string;\n severity: Severity;\n message: string;\n}\n\n/** Mirrors sync's indexability marker: `buildPageFields` skips any page whose\n * `title` is not a non-empty string. */\nfunction hasIndexableTitle(data: Record<string, unknown>): boolean {\n return typeof data.title === 'string' && data.title.trim() !== '';\n}\n\n/**\n * A page sync would index: it has a `title` and either a `kind` or lives under\n * notes/ (notes imply kind=note). Title-less narrative/reserved pages (primers,\n * the title-less ontology/alayacare pages) are skipped by sync, so the\n * sync-mirror checks are gated on this \u2014 validate governs what sync governs.\n * The kind-floor contract checks gate on kind intent instead: a missing or\n * empty title is itself a floor violation, and must not gate itself out.\n */\nfunction isIndexed(relPath: string, data: Record<string, unknown>): boolean {\n if (!hasIndexableTitle(data)) return false;\n if (typeof data.kind === 'string' && data.kind !== '') return true;\n return relPath.startsWith('notes/');\n}\n\n/**\n * A reserved `primer.md` (at any level). Title-less, so it is skipped by the\n * indexed-page checks \u2014 but it is the agent's first-read surface, so a stale\n * `[[link]]` there must not silently pass the gate. Its body links are checked.\n */\nfunction isPrimer(relPath: string): boolean {\n return relPath === 'primer.md' || relPath.endsWith('/primer.md');\n}\n\n// Required-field floor per kind \u2014 the set of keys present on 100% of existing\n// pages of that kind (corpus-scanned; spec-wiki-validate \u00A7 Required fields per\n// kind). Key-presence, not non-emptiness. Kinds absent here (artifact, prompt,\n// glossary-entry, pso-roster) carry no required-field contract. `tags` is\n// governed separately by the `tags-required` rule (non-empty), not this floor.\nconst REQUIRED_FIELDS: Record<string, readonly string[]> = {\n project: [\n 'title',\n 'kind',\n 'scope',\n 'status',\n 'summary',\n 'updated',\n 'methodology',\n 'phase',\n 'repo'\n ],\n spec: ['title', 'kind', 'scope', 'status', 'summary', 'updated', 'sources'],\n adr: ['title', 'kind', 'scope', 'status', 'updated'],\n plan: ['title', 'kind', 'scope', 'status', 'summary', 'updated'],\n ops: ['title', 'kind', 'scope', 'status', 'summary', 'updated'],\n story: [\n 'title',\n 'kind',\n 'scope',\n 'status',\n 'updated',\n 'parent',\n 'triage_state',\n 'category',\n 'blocked_by',\n 'sources'\n ],\n topic: ['title', 'kind', 'status', 'summary', 'updated', 'confidence'],\n article: ['title', 'kind', 'status', 'updated'],\n src: ['title', 'kind', 'topic', 'status', 'summary', 'updated'],\n note: ['title', 'updated']\n};\n\n// Kinds exempt from the tags-required floor: deliverable/package internals\n// (artifact, prompt) and registry stubs (glossary-entry, pso-roster), not\n// discoverable content pages. Mirrors the required-fields floor exemption.\nconst TAG_OPTIONAL_KINDS = new Set(['artifact', 'prompt', 'glossary-entry', 'pso-roster']);\n\n// Per-kind path patterns (spec-wiki-validate \u00A7 Folder and slug patterns). Kinds\n// absent here have no documented pattern and are exempt (article free naming,\n// notes, and the registered-but-undocumented ontology/alayacare kinds).\nconst FOLDER_PATTERNS: Record<string, RegExp> = {\n spec: /^projects\\/[^/]+\\/spec\\/spec-[^/]+\\.md$/,\n adr: /^projects\\/[^/]+\\/adr\\/adr-[^/]+\\.md$/,\n ops: /^projects\\/[^/]+\\/ops\\/ops-[^/]+\\.md$/,\n plan: /^projects\\/[^/]+\\/plan\\/plan-[^/]+\\.md$/,\n story: /^projects\\/[^/]+\\/plan\\/[^/]+\\/story-[^/]+\\.md$/,\n project: /^projects\\/[^/]+\\/index\\.md$/,\n topic: /^research\\/[^/]+\\/index\\.md$/,\n src: /^research\\/[^/]+\\/src-[^/]+\\.md$/\n};\n\nfunction checkRequiredFields(relPath: string, data: Record<string, unknown>): Finding[] {\n // Notes carry no `kind` key \u2014 sync infers `note` from location; mirror that so\n // the note floor is reachable rather than dead.\n const kind =\n typeof data.kind === 'string' && data.kind !== ''\n ? data.kind\n : relPath.startsWith('notes/')\n ? 'note'\n : undefined;\n const required = kind ? REQUIRED_FIELDS[kind] : undefined;\n if (!required) return [];\n const findings: Finding[] = [];\n for (const field of required) {\n if (!Object.hasOwn(data, field)) {\n findings.push({\n path: relPath,\n rule: 'required-fields',\n severity: 'error',\n message: `missing required field \"${field}\" for kind \"${kind}\"`\n });\n }\n }\n // Title carve-out from key-presence: the one floor field where emptiness is\n // a violation \u2014 sync skips any page without a non-empty title, silently\n // dropping it from the index.\n if (Object.hasOwn(data, 'title') && !hasIndexableTitle(data)) {\n findings.push({\n path: relPath,\n rule: 'required-fields',\n severity: 'error',\n message: `\"title\" must be a non-empty string for kind \"${kind}\" \u2014 sync skips the page otherwise`\n });\n }\n return findings;\n}\n\n// Universal floor for custom kinds: the fields the index serves. Warnings,\n// never errors \u2014 custom kinds keep their freedom; the nudge keeps pages\n// retrievable (title/summary feed FTS, updated feeds prime ordering).\nconst UNIVERSAL_FLOOR = ['title', 'summary', 'updated'] as const;\n\n/** Names of object-form kinds outside the built-in set \u2014 the explicit opt-in\n * to custom pedagogy. Plain-string unknown kinds stay floor-free. */\nfunction customKindNames(cfg: VaultConfig): Set<string> {\n const names = new Set<string>();\n for (const entry of cfg.kinds) {\n if (typeof entry !== 'string' && !BUILT_IN_KINDS.has(entry.name)) names.add(entry.name);\n }\n return names;\n}\n\nfunction checkCustomKindFloor(\n relPath: string,\n data: Record<string, unknown>,\n cfg: VaultConfig\n): Finding[] {\n const kind = data.kind;\n if (typeof kind !== 'string' || !customKindNames(cfg).has(kind)) return [];\n const findings: Finding[] = [];\n for (const field of UNIVERSAL_FLOOR) {\n if (!Object.hasOwn(data, field)) {\n findings.push({\n path: relPath,\n rule: 'custom-kind-floor',\n severity: 'warning',\n message: `custom kind \"${kind}\": missing \"${field}\" \u2014 the universal floor (title, summary, updated) keeps the page retrievable`\n });\n }\n }\n if (Object.hasOwn(data, 'title') && !hasIndexableTitle(data)) {\n findings.push({\n path: relPath,\n rule: 'custom-kind-floor',\n severity: 'warning',\n message: `custom kind \"${kind}\": \"title\" is empty \u2014 sync skips title-less pages; this page will not be indexed`\n });\n }\n return findings;\n}\n\n/**\n * Tags are an open dimension \u2014 any value, no controlled vocabulary \u2014 but every\n * content page must carry at least one. Indexed pages whose kind is not\n * tag-optional require a non-empty `tags` list.\n */\nfunction checkTagsRequired(relPath: string, data: Record<string, unknown>): Finding[] {\n const kind =\n typeof data.kind === 'string' && data.kind !== ''\n ? data.kind\n : relPath.startsWith('notes/')\n ? 'note'\n : undefined;\n if (kind && TAG_OPTIONAL_KINDS.has(kind)) return [];\n if (Array.isArray(data.tags) && data.tags.length > 0) return [];\n return [\n {\n path: relPath,\n rule: 'tags-required',\n severity: 'error',\n message:\n 'tags must be present and non-empty (tags are open \u2014 any values, every content page tagged)'\n }\n ];\n}\n\nfunction checkFolderSlug(relPath: string, data: Record<string, unknown>): Finding[] {\n const kind = data.kind;\n const pattern = typeof kind === 'string' ? FOLDER_PATTERNS[kind] : undefined;\n if (!pattern || pattern.test(relPath)) return [];\n return [\n {\n path: relPath,\n rule: 'folder-slug',\n severity: 'error',\n message: `path does not match the \"${kind}\" slug pattern ${pattern.source}`\n }\n ];\n}\n\nfunction checkVocabulary(\n relPath: string,\n data: Record<string, unknown>,\n cfg: VaultConfig\n): Finding[] {\n const findings: Finding[] = [];\n const kind = data.kind;\n if (typeof kind === 'string' && !cfg.kinds.some((k) => kindName(k) === kind)) {\n findings.push({\n path: relPath,\n rule: 'kind-vocabulary',\n severity: 'error',\n message: `kind \"${kind}\" is not in vault.yaml`\n });\n }\n const status = data.status;\n if (typeof status === 'string' && !cfg.statuses.includes(status)) {\n findings.push({\n path: relPath,\n rule: 'status-vocabulary',\n severity: 'error',\n message: `status \"${status}\" is not in vault.yaml`\n });\n }\n const { scope } = deriveLocation(relPath);\n if (scope !== null && !Object.hasOwn(cfg.scopes, scope)) {\n findings.push({\n path: relPath,\n rule: 'scope-vocabulary',\n severity: 'error',\n message: `scope \"${scope}\" is not in vault.yaml`\n });\n }\n const methodology = data.methodology;\n if (typeof methodology === 'string' && !cfg.methodologies.includes(methodology)) {\n findings.push({\n path: relPath,\n rule: 'methodology-vocabulary',\n severity: 'error',\n message: `methodology \"${methodology}\" is not in vault.yaml`\n });\n }\n return findings;\n}\n\n/**\n * Path is authoritative for `scope`/`topic`: sync derives them from the path and\n * ignores frontmatter. A frontmatter copy is allowed for readability but must not\n * lie \u2014 a mismatch means the label disagrees with where the file actually lives.\n * Fires only where the path defines the value (projects \u2192 scope, research \u2192 topic)\n * and the frontmatter carries it.\n */\nfunction checkScopePath(relPath: string, data: Record<string, unknown>): Finding[] {\n const { scope, topic } = deriveLocation(relPath);\n const findings: Finding[] = [];\n if (\n scope !== null &&\n typeof data.scope === 'string' &&\n data.scope !== '' &&\n data.scope !== scope\n ) {\n findings.push({\n path: relPath,\n rule: 'path-authority',\n severity: 'error',\n message: `frontmatter scope \"${data.scope}\" disagrees with path scope \"${scope}\"`\n });\n }\n if (\n topic !== null &&\n typeof data.topic === 'string' &&\n data.topic !== '' &&\n data.topic !== topic\n ) {\n findings.push({\n path: relPath,\n rule: 'path-authority',\n severity: 'error',\n message: `frontmatter topic \"${data.topic}\" disagrees with path topic \"${topic}\"`\n });\n }\n return findings;\n}\n\n/** A reference's basename target, or null if absent/empty/non-string. */\nfunction refTarget(value: unknown): string | null {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim();\n return trimmed === '' ? null : basename(trimmed);\n}\n\n/**\n * Basename targets of a reference field that may be scalar or array. `supersedes`\n * and `superseded_by` are list-valued in the wild (one ADR can supersede several),\n * so a scalar-only read would miss them and falsely fail reciprocity.\n */\nfunction refTargets(value: unknown): string[] {\n if (Array.isArray(value)) {\n return value.map(refTarget).filter((t): t is string => t !== null);\n }\n const single = refTarget(value);\n return single === null ? [] : [single];\n}\n\n/**\n * Strip code regions so `[[...]]`-shaped syntax inside them is not mistaken for a\n * wikilink: fenced ``` blocks (e.g. a bash `if [[ x == y ]]` test) and inline\n * `code` spans (e.g. a `[[wikilink]]` documentation example). Sync's own link\n * extraction is unaffected \u2014 its pseudo-links are a separate, pre-existing concern.\n */\nfunction stripCode(body: string): string {\n return body.replace(/```[\\s\\S]*?```/g, '').replace(/`[^`]*`/g, '');\n}\n\n/**\n * Body `[[wikilink]]` dangling check against the basename `refIndex`. Code\n * regions are stripped first (see `stripCode`) so `[[...]]`-shaped syntax inside\n * fences/inline-code is not mistaken for a link. Shared by the indexed-page\n * reference checks and the title-less primer carve-in.\n */\nfunction checkBodyLinks(relPath: string, body: string, refIndex: ReadonlySet<string>): Finding[] {\n const findings: Finding[] = [];\n for (const link of extractWikilinks(stripCode(body))) {\n if (!link.target.endsWith('.md')) continue;\n if (!refIndex.has(basename(link.target))) {\n findings.push({\n path: relPath,\n rule: 'dangling-link',\n severity: 'error',\n message: `wikilink target \"${link.target}\" does not resolve`\n });\n }\n }\n return findings;\n}\n\n/**\n * Reference resolution against the basename index: body `[[wikilinks]]` to `.md`\n * targets, plus the frontmatter reference fields. Empty values never fire (the\n * empty `supersedes:`/`superseded_by:` template keys are the 52/57). Non-`.md`\n * wikilink targets (images, `.base`, external) are not policed.\n */\nfunction checkReferences(\n relPath: string,\n data: Record<string, unknown>,\n body: string,\n refIndex: ReadonlySet<string>\n): Finding[] {\n const findings: Finding[] = checkBodyLinks(relPath, body, refIndex);\n const fieldRefs: string[] = [];\n const parent = refTarget(data.parent);\n if (parent !== null) fieldRefs.push(parent);\n for (const field of ['supersedes', 'superseded_by', 'blocked_by'] as const) {\n fieldRefs.push(...refTargets(data[field]));\n }\n for (const target of fieldRefs) {\n if (!refIndex.has(target)) {\n findings.push({\n path: relPath,\n rule: 'ref-resolves',\n severity: 'error',\n message: `frontmatter reference \"${target}\" does not resolve`\n });\n }\n }\n return findings;\n}\n\n/**\n * Tag policy: only the alias case is enforced, as a non-fatal warning. A full\n * canonical-membership check is deferred \u2014 the corpus carries ~211 distinct tags\n * against an 11-entry canonical list, so flagging non-canonical tags would fire\n * on nearly every page (spec-wiki-validate \u00A7 Tag policy).\n */\nfunction checkTags(relPath: string, data: Record<string, unknown>, cfg: VaultConfig): Finding[] {\n if (!Array.isArray(data.tags)) return [];\n const findings: Finding[] = [];\n for (const tag of data.tags) {\n if (typeof tag === 'string' && Object.hasOwn(cfg.tags.aliases, tag)) {\n findings.push({\n path: relPath,\n rule: 'tag-alias',\n severity: 'warning',\n message: `tag \"${tag}\" is an alias; use canonical \"${cfg.tags.aliases[tag]}\"`\n });\n }\n }\n return findings;\n}\n\n/** `status: superseded` requires a non-empty `superseded_by` (README \u00A76). */\nfunction checkSupersededLink(relPath: string, data: Record<string, unknown>): Finding[] {\n if (data.status === 'superseded' && refTargets(data.superseded_by).length === 0) {\n return [\n {\n path: relPath,\n rule: 'superseded-needs-link',\n severity: 'error',\n message: 'status is \"superseded\" but superseded_by is empty'\n }\n ];\n }\n return [];\n}\n\n/** Sync-mirror checks on already-parsed frontmatter \u2014 gated on indexability,\n * governing exactly what sync indexes. Pure. */\nfunction checkIndexedPage(\n relPath: string,\n data: Record<string, unknown>,\n body: string,\n cfg: VaultConfig,\n refIndex: ReadonlySet<string>\n): Finding[] {\n if (!isIndexed(relPath, data)) return [];\n return [\n ...checkTagsRequired(relPath, data),\n ...checkFolderSlug(relPath, data),\n ...checkVocabulary(relPath, data, cfg),\n ...checkScopePath(relPath, data),\n ...checkReferences(relPath, data, body, refIndex),\n ...checkSupersededLink(relPath, data),\n ...checkTags(relPath, data, cfg)\n ];\n}\n\n/**\n * Deterministic checks on a single page's raw content. Pure \u2014 no IO. Parses the\n * frontmatter first: a parse failure is the live bug that silently halts sync\n * mid-walk, reported regardless of the page's other fields. Well-formed pages\n * are then subjected to the indexed-page checks (vocabulary, \u2026) against the\n * controlled vocabulary `cfg` and the basename `refIndex` of valid link targets.\n */\nexport function validatePage(\n relPath: string,\n raw: string,\n cfg: VaultConfig,\n refIndex: ReadonlySet<string>\n): Finding[] {\n let parsed: ReturnType<typeof parseFrontmatter>;\n try {\n parsed = parseFrontmatter(raw);\n } catch (err) {\n return [\n {\n path: relPath,\n rule: 'frontmatter-parse',\n severity: 'error',\n message: err instanceof Error ? err.message : String(err)\n }\n ];\n }\n if (isPrimer(relPath)) {\n return checkBodyLinks(relPath, parsed.content, refIndex);\n }\n // Two-stage pipeline. Contract checks (the kind floors) gate on kind intent:\n // a floor violation must surface even when the violation is the very field\n // (title) that decides indexability \u2014 otherwise the page silently drops from\n // the index with zero findings. Sync-mirror checks gate on isIndexed.\n return [\n ...checkRequiredFields(relPath, parsed.data),\n ...checkCustomKindFloor(relPath, parsed.data, cfg),\n ...checkIndexedPage(relPath, parsed.data, parsed.content, cfg, refIndex)\n ];\n}\n\n/** Exit-code decision: any error-severity finding fails the run. */\nexport function hasErrors(findings: Finding[]): boolean {\n return findings.some((f) => f.severity === 'error');\n}\n\n/** Basename (no extension) of a vault-relative path. */\nfunction basename(relPath: string): string {\n const last = relPath.split('/').pop() ?? relPath;\n return last.replace(/\\.md$/, '');\n}\n\nexport interface PageData {\n path: string;\n data: Record<string, unknown>;\n}\n\n/**\n * Cross-page ADR supersession reciprocity: a non-empty `superseded_by: B` on\n * ADR A requires `supersedes: A` on B, and vice-versa. Fires only on non-empty\n * values; a value pointing at a non-existent ADR is a `ref-resolves` error\n * (checked per-page), not a reciprocity error, so unresolved targets are skipped\n * here. (spec-wiki-validate \u00A7 Supersession.)\n */\nexport function validateSupersession(pages: PageData[]): Finding[] {\n const adrs = new Map<string, { path: string; supersedes: string[]; supersededBy: string[] }>();\n for (const { path, data } of pages) {\n if (data.kind !== 'adr') continue;\n adrs.set(basename(path), {\n path,\n supersedes: refTargets(data.supersedes),\n supersededBy: refTargets(data.superseded_by)\n });\n }\n const findings: Finding[] = [];\n for (const [name, adr] of adrs) {\n for (const target of adr.supersededBy) {\n const other = adrs.get(target);\n if (other && !other.supersedes.includes(name)) {\n findings.push({\n path: adr.path,\n rule: 'supersession-reciprocal',\n severity: 'error',\n message: `superseded_by \"${target}\" which does not declare supersedes \"${name}\"`\n });\n }\n }\n for (const target of adr.supersedes) {\n const other = adrs.get(target);\n if (other && !other.supersededBy.includes(name)) {\n findings.push({\n path: adr.path,\n rule: 'supersession-reciprocal',\n severity: 'error',\n message: `supersedes \"${target}\" which does not declare superseded_by \"${name}\"`\n });\n }\n }\n }\n return findings;\n}\n\n/** Top-level scope/topic key of a path (`projects/{scope}` or `research/{topic}`), or\n * null for notes/root pages. Two pages \"share a scope\" iff their keys are equal. */\nfunction locationKey(relPath: string): string | null {\n const seg = relPath.split('/');\n if ((seg[0] === 'projects' || seg[0] === 'research') && seg[1]) {\n return `${seg[0]}/${seg[1]}`;\n }\n return null;\n}\n\nexport interface LinkPage {\n path: string;\n body: string;\n}\n\n/**\n * Cross-page ambiguity warning. A **bare** `[[wikilink]]` whose basename is owned by\n * more than one file is ambiguous only when none of those owners shares the linking\n * page's scope: a same-scope copy resolves it locally (the per-scope `spec-context`/\n * `primer`/`index` pattern), and a path-qualified link (`[[a/b/c]]`) is already\n * disambiguated. Warning, not error \u2014 the link resolves, just not uniquely.\n */\nexport function validateAmbiguousLinks(\n pages: LinkPage[],\n basenameToPaths: ReadonlyMap<string, string[]>\n): Finding[] {\n const findings: Finding[] = [];\n for (const { path, body } of pages) {\n const here = locationKey(path);\n for (const link of extractWikilinks(stripCode(body))) {\n if (!link.target.endsWith('.md') || link.target.includes('/')) continue;\n const base = basename(link.target);\n const owners = basenameToPaths.get(base);\n if (!owners || owners.length < 2) continue;\n if (here !== null && owners.some((p) => locationKey(p) === here)) continue;\n findings.push({\n path,\n rule: 'ambiguous-link',\n severity: 'warning',\n message: `bare link \"[[${base}]]\" is ambiguous \u2014 basename owned by ${owners.length} files, none in this scope`\n });\n }\n }\n return findings;\n}\n\n/**\n * Walk the vault's content domains (reusing the sync walker), build the basename\n * index of valid reference targets (all on-disk pages, including title-less ones),\n * then aggregate findings across all pages. No database \u2014 validation is a\n * pre-sync, read-only pass over the filesystem.\n */\nexport async function validateVault(root: string): Promise<Finding[]> {\n const cfg = await loadVaultConfig(root);\n\n // Reference target universe = every on-disk page, including title-less ones and\n // pages outside the scanned domains (raw/, templates/) that are legitimate link\n // targets. Walking from '.' covers the whole vault; dotdirs (.git, .obsidian)\n // are skipped by the walker.\n const all = (await walkMarkdown(root, '.')).map((abs) => ({\n relPath: toRelativePath(root, abs),\n abs\n }));\n // basename \u2192 [paths] (the spec's reference-resolution model). `refIndex` (dangling\n // checks: does the basename exist) is its key set; the multimap also backs the\n // cross-page ambiguity warning (does a basename have more than one owner).\n const basenameToPaths = new Map<string, string[]>();\n for (const f of all) {\n const b = basename(f.relPath);\n const owners = basenameToPaths.get(b);\n if (owners) owners.push(f.relPath);\n else basenameToPaths.set(b, [f.relPath]);\n }\n const refIndex = new Set<string>(basenameToPaths.keys());\n\n // Applicability = only the indexed content domains.\n const files = all.filter((f) => SCAN_DOMAINS.some((d) => f.relPath.startsWith(`${d}/`)));\n\n const findings: Finding[] = [];\n const pages: PageData[] = [];\n const linkPages: LinkPage[] = [];\n for (const { relPath, abs } of files) {\n const raw = await readFile(abs, 'utf8');\n findings.push(...validatePage(relPath, raw, cfg, refIndex));\n try {\n const parsed = parseFrontmatter(raw);\n pages.push({ path: relPath, data: parsed.data });\n linkPages.push({ path: relPath, body: parsed.content });\n } catch {\n // Parse failure already reported by validatePage; skip in the graph pass.\n }\n }\n findings.push(...validateSupersession(pages));\n findings.push(...validateAmbiguousLinks(linkPages, basenameToPaths));\n\n // A declared custom kind without its template file leaves the served\n // \"use the matching template\" rule unsatisfiable \u2014 warn, don't block.\n for (const name of customKindNames(cfg)) {\n const file = `templates/${name}.md`;\n try {\n await stat(join(root, file));\n } catch {\n findings.push({\n path: file,\n rule: 'custom-kind-template',\n severity: 'warning',\n message: `custom kind \"${name}\" declared in vault.yaml has no template file`\n });\n }\n }\n return findings;\n}\n", "import { parseArgs } from 'node:util';\nimport { runSync } from './sync.js';\nimport { type Finding, hasErrors, validateVault } from './validate.js';\n\nexport type Command = 'sync' | 'validate';\n\nexport type CliResolution = { kind: 'run'; command: Command } | { kind: 'error'; message: string };\n\n/**\n * Resolve a `wiki <command>` invocation to the command to run, or a usage\n * error. Pure \u2014 no side effects \u2014 so the routing is testable without executing\n * the (index-touching) command. `argv` is `process.argv.slice(2)`.\n */\nexport function resolveCli(argv: string[]): CliResolution {\n const { positionals } = parseArgs({ args: argv, allowPositionals: true, strict: false });\n const command = positionals[0];\n if (command === 'sync') {\n return { kind: 'run', command: 'sync' };\n }\n if (command === 'validate') {\n return { kind: 'run', command: 'validate' };\n }\n if (command === undefined) {\n return { kind: 'error', message: 'usage: wiki <sync|validate>' };\n }\n return { kind: 'error', message: `unknown command: ${command}` };\n}\n\nexport function vaultRoot(): string {\n const root = process.env.WIKI_VAULT;\n if (!root) {\n console.error('WIKI_VAULT is not set');\n process.exit(1);\n }\n return root;\n}\n\nfunction reportFindings(findings: Finding[]): void {\n for (const f of findings) {\n console.error(`${f.severity}: ${f.path} [${f.rule}] ${f.message}`);\n }\n}\n\nexport async function runValidate(): Promise<void> {\n const findings = await validateVault(vaultRoot());\n reportFindings(findings);\n console.log(`validate: ${findings.length} finding(s)`);\n process.exit(hasErrors(findings) ? 1 : 0);\n}\n\nexport async function runSyncCommand(): Promise<void> {\n const findings = await validateVault(vaultRoot());\n reportFindings(findings);\n if (hasErrors(findings)) {\n const errors = findings.filter((f) => f.severity === 'error').length;\n console.error(`sync aborted: ${errors} validation error(s); no database writes`);\n process.exit(1);\n }\n await runSync();\n}\n\nexport async function main(): Promise<void> {\n const resolution = resolveCli(process.argv.slice(2));\n if (resolution.kind === 'error') {\n console.error(resolution.message);\n process.exit(1);\n }\n if (resolution.command === 'sync') {\n await runSyncCommand();\n } else {\n await runValidate();\n }\n}\n", "import { z } from 'zod';\n\nconst EnvSchema = z.object({\n WIKI_VAULT: z.string().min(1).describe('Absolute path to the Obsidian vault root'),\n LOG_LEVEL: z\n .enum(['trace', 'debug', 'info', 'warn', 'error', 'fatal', 'silent'])\n .default('info')\n .describe('Pino log level. Logs go to stderr to keep the stdio JSON-RPC stream clean.'),\n SERVER_NAME: z.string().default('wiki-mcp'),\n SERVER_VERSION: z.string().default('0.0.0')\n});\n\nexport interface Config {\n readonly wikiVault: string;\n readonly logLevel: z.infer<typeof EnvSchema>['LOG_LEVEL'];\n readonly serverName: string;\n readonly serverVersion: string;\n}\n\nexport function loadConfig(env: NodeJS.ProcessEnv = process.env): Config {\n const parsed = EnvSchema.safeParse(env);\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` - ${i.path.join('.') || '(root)'}: ${i.message}`)\n .join('\\n');\n throw new Error(`Invalid environment configuration:\\n${issues}`);\n }\n return {\n wikiVault: parsed.data.WIKI_VAULT,\n logLevel: parsed.data.LOG_LEVEL,\n serverName: parsed.data.SERVER_NAME,\n serverVersion: parsed.data.SERVER_VERSION\n };\n}\n", "import { mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { DatabaseSync } from 'node:sqlite';\nimport { openDatabase } from '@llm-wiki/db/database';\n\nexport function createDatabase(): DatabaseSync {\n const dbDir = join(homedir(), '.kmd', 'db');\n const dbPath = join(dbDir, 'index.db');\n mkdirSync(dbDir, { recursive: true });\n return openDatabase(dbPath);\n}\n", "import { appendFileSync, mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nconst DIAG_DIR = join(homedir(), '.local', 'state', 'wiki-mcp');\nexport const DIAG_LOG_PATH = join(DIAG_DIR, 'server.log');\n\ntry {\n mkdirSync(DIAG_DIR, { recursive: true });\n} catch {\n // best-effort; do not block startup on log dir creation\n}\n\n/**\n * Synchronous file logger that survives even when pino, the MCP SDK, or any\n * import down the chain fails to load. Writes to ~/.local/state/wiki-mcp/server.log\n * regardless of stdio/stderr capture by the parent process. Use to trace\n * spawn-time failures that never reach pino.\n */\nexport function diag(msg: string, data?: Record<string, unknown>): void {\n try {\n const line = data\n ? `${new Date().toISOString()} pid=${process.pid} ${msg} ${JSON.stringify(data)}\\n`\n : `${new Date().toISOString()} pid=${process.pid} ${msg}\\n`;\n appendFileSync(DIAG_LOG_PATH, line);\n } catch {\n // best-effort; never crash the server on log write failure\n }\n}\n", "import pino from 'pino';\nimport { DIAG_LOG_PATH } from './diag.js';\n\n/**\n * Pino logger that fans out to BOTH stderr (fd 2, captured by Claude Code)\n * AND ~/.local/state/wiki-mcp/server.log (so logs survive when stderr capture\n * doesn't make it into the JSONL connection log). The file destination shares\n * the path with diag.ts so a single `tail -f` follows the entire startup +\n * runtime stream.\n */\nexport function createLogger(level: string, name: string): pino.Logger {\n const streams: pino.StreamEntry[] = [\n { level: level as pino.Level, stream: pino.destination(2) },\n {\n level: level as pino.Level,\n stream: pino.destination({ dest: DIAG_LOG_PATH, sync: false, mkdir: true })\n }\n ];\n return pino({ name, level, base: { pid: process.pid } }, pino.multistream(streams));\n}\n\nexport type Logger = pino.Logger;\n", "import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parse } from 'yaml';\nimport { z } from 'zod';\n\n// Verbatim mirror of @llm-wiki/cli's src/config.ts \u2014 the single definition of a\n// valid vault.yaml. Kept byte-identical (schema + error strings) so mcp and\n// sync/validate never disagree on what is valid. Collapse both into a shared\n// package only when a third separate consumer appears (CLAUDE.md YAGNI rule).\n\nconst ScopeSchema = z.object({\n repo: z.string().optional(),\n methodology: z.string().optional(),\n status: z.string()\n});\n\nconst KindEntrySchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n signal: z.string(),\n where: z.string()\n })\n]);\n\nconst VaultConfigSchema = z\n .object({\n scopes: z.record(z.string(), ScopeSchema),\n kinds: z.array(KindEntrySchema),\n statuses: z.array(z.string()),\n methodologies: z.array(z.string()),\n tags: z.object({\n canonical: z.array(z.string()),\n aliases: z.record(z.string(), z.string())\n }),\n authoring_rules: z.string().optional(),\n authoring_rules_extra: z.string().optional(),\n sync_protocol: z.string().optional(),\n sync_protocol_extra: z.string().optional()\n })\n .superRefine((config, ctx) => {\n for (const [name, scope] of Object.entries(config.scopes)) {\n if (scope.methodology !== undefined && !config.methodologies.includes(scope.methodology)) {\n ctx.addIssue({\n code: 'custom',\n path: ['scopes', name, 'methodology'],\n message: `\"${scope.methodology}\" is not in the methodologies list`\n });\n }\n }\n });\n\nexport type KindEntry = z.infer<typeof KindEntrySchema>;\nexport type VaultConfig = z.infer<typeof VaultConfigSchema>;\n\n/** Kind name of a `kinds` entry \u2014 plain string, or the object form's `name`. */\nexport function kindName(entry: KindEntry): string {\n return typeof entry === 'string' ? entry : entry.name;\n}\n\n/**\n * Kinds with built-in engine pedagogy (kind-selector rows; most also carry a\n * served template). An object-form entry with one of these names rewords its\n * selector row only \u2014 it never creates custom-template expectations.\n */\nexport const BUILT_IN_KINDS: ReadonlySet<string> = new Set([\n 'project',\n 'spec',\n 'adr',\n 'plan',\n 'story',\n 'ops',\n 'topic',\n 'article',\n 'src',\n 'note',\n 'artifact',\n 'prompt'\n]);\n\n/**\n * Load and validate `$vaultRoot/vault.yaml` \u2014 the single source of truth for\n * the controlled vocabulary. Throws (fail-loud) when the file is missing or\n * the contents don't satisfy the schema; the server must not start on partial\n * vocabulary.\n */\nexport async function loadVaultConfig(vaultRoot: string): Promise<VaultConfig> {\n const path = join(vaultRoot, 'vault.yaml');\n let raw: string;\n try {\n raw = await readFile(path, 'utf8');\n } catch (err) {\n throw new Error(`vault.yaml not found at ${path}`, { cause: err });\n }\n const parsed = VaultConfigSchema.safeParse(parse(raw));\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` - ${i.path.join('.') || '(root)'}: ${i.message}`)\n .join('\\n');\n throw new Error(`Invalid vault.yaml at ${path}:\\n${issues}`);\n }\n return parsed.data;\n}\n", "import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { type KindEntry, kindName, type VaultConfig } from '../vault-config.js';\n\ninterface KindPedagogy {\n readonly signal: string;\n readonly where: string;\n}\n\nconst KIND_PEDAGOGY: ReadonlyMap<string, KindPedagogy> = new Map([\n [\n 'project',\n {\n signal: 'Identity card for a project scope',\n where: '`projects/{scope}/index.md`'\n }\n ],\n [\n 'spec',\n {\n signal: 'How a system works (state of world, not decision)',\n where: '`projects/{scope}/spec/spec-{slug}.md`'\n }\n ],\n [\n 'adr',\n {\n signal: 'Decision between alternatives, commits direction',\n where: '`projects/{scope}/adr/adr-{slug}.md`'\n }\n ],\n [\n 'plan',\n {\n signal: 'Phase/initiative with milestones and stories',\n where: '`projects/{scope}/plan/plan-{slug}.md`'\n }\n ],\n [\n 'story',\n {\n signal: 'User story with Gherkin + slices (child of plan)',\n where: '`projects/{scope}/plan/{plan}/story-N-{slug}.md`'\n }\n ],\n [\n 'ops',\n {\n signal: 'Operational runbook, how to run/deploy',\n where: '`projects/{scope}/ops/ops-{slug}.md`'\n }\n ],\n [\n 'topic',\n {\n signal: 'Identity card for a research area',\n where: '`research/{topic}/index.md`'\n }\n ],\n [\n 'article',\n {\n signal: 'Original synthesis about a concept/entity',\n where: '`research/{topic}/{slug}.md`'\n }\n ],\n [\n 'src',\n {\n signal: 'Summary of external source with citation',\n where: '`research/{topic}/src-{slug}.md`'\n }\n ],\n ['note', { signal: 'Low-ceremony capture, sort later', where: '`notes/{slug}.md`' }],\n [\n 'artifact',\n {\n signal: 'Deployable configuration (scope-specific, versioned)',\n where: '`projects/{scope}/ops/{deployment}/{slug}.md`'\n }\n ],\n [\n 'prompt',\n {\n signal: 'LLM prompt template (scope-specific, versioned)',\n where: '`projects/{scope}/ops/{deployment}/prompts/{role}/{slug}.md`'\n }\n ]\n]);\n\nconst DEFAULT_AUTHORING_RULES = [\n '**Where things go**',\n '',\n \"- **Use the matching template** via `wiki://template/{domain}/{kind}` (MCP) or from `templates/` (filesystem). Don't hand-roll frontmatter.\",\n '- **Folder name = slug prefix in `projects/`.** `spec/spec-x.md`, `adr/adr-y.md`, `plan/plan-z.md`, `ops/ops-w.md`. Stories use `story-` prefix under `plan/{plan-name}/`.',\n '- **Research is flat.** Articles are `{subject}.md`; sources are `src-{slug}.md`. The topic folder names a *frame*, the article slug names a *subject*. Avoid generic slugs (`architecture.md`, `notes.md`) and slugs that collide with project scopes.',\n '- **Extend before you split.** Prefer sharpening the existing spec, ADR, or article over creating a near-duplicate page. A new page needs a new subject, not a new session.',\n '',\n '**Frontmatter**',\n '',\n '- **`summary` is the retrieval contract.** One sentence stating the page\\'s decision or claim, not its topic. Search and `prime` rank by it \u2014 \"Chose X over Y because Z\" surfaces; \"About the sync pipeline\" sinks.',\n '- **Quote prose-bearing scalars.** `summary: \"...\"` \u2014 unquoted `Word: phrase` patterns break the YAML parser.',\n '- **On any edit, update `updated`.** Never change `created` \u2014 it is write-once.',\n '- **Notes have no `kind` field** \u2014 implied by location. Sync sets `kind: note`.',\n '- **Reuse existing tags** (visible in `prime` response `top_tags`). No synonyms.',\n '',\n '**Content**',\n '',\n '- **ADR and ops pages are predicate-only.** No definitional preambles for established vocabulary, no narrative, no marketing. The audience is the project team \u2014 assume fluency.',\n \"- **Spec / ADR edits land inline with the change that surfaces them.** Don't queue corrections in plans \u2014 the spec reflects current code at every commit.\",\n '',\n '**Linking**',\n '',\n \"- **Cross-reference with `[[wikilinks]]`, and link every mention of another vault page** \u2014 backlinks are the navigation graph for humans and agents alike. Don't link pages that don't exist yet: dangling links fail validation.\",\n '- **ADR supersession is bidirectional**: `superseded_by` on the old ADR + `supersedes` on the new one.',\n \"- **Sources convention**: external paths/URLs go inline in body text. Vault-internal `raw/` paths go in frontmatter `sources:` array. Don't mix the two surfaces.\"\n].join('\\n');\n\nfunction buildAuthoringRules(config: VaultConfig): string {\n const parts = [(config.authoring_rules ?? DEFAULT_AUTHORING_RULES).trim()];\n if (config.authoring_rules_extra) parts.push(config.authoring_rules_extra.trim());\n return ['## Authoring rules', '', parts.join('\\n\\n')].join('\\n');\n}\n\nconst DEFAULT_SYNC_PROTOCOL = [\n 'Edit the smallest set of files that reflects the change. ' +\n \"A milestone tick is plan-only; don't cascade to index.md unless phase or status changed. \" +\n 'Controlled-vocabulary edits (`vault.yaml`) need explicit user approval.',\n 'After editing wiki pages, run `kmd validate` and fix findings before `kmd sync` \u2014 ' +\n 'it checks frontmatter shape, vocabulary membership, and link integrity.'\n].join('\\n');\n\nfunction buildSyncProtocol(config: VaultConfig): string {\n const parts = [(config.sync_protocol ?? DEFAULT_SYNC_PROTOCOL).trim()];\n if (config.sync_protocol_extra) parts.push(config.sync_protocol_extra.trim());\n return ['## Resync protocol', '', parts.join('\\n\\n')].join('\\n');\n}\n\nfunction buildKindSelector(kinds: ReadonlyArray<KindEntry>): string {\n const lines: string[] = ['## Kind selector', '', '| Signal | Kind | Where |', '|---|---|---|'];\n for (const entry of kinds) {\n const name = kindName(entry);\n const pedagogy = typeof entry === 'string' ? KIND_PEDAGOGY.get(entry) : entry;\n const signal = pedagogy?.signal ?? '\u2014';\n const where = pedagogy?.where ?? '\u2014';\n lines.push(`| ${signal} | **${name}** | ${where} |`);\n }\n const names = kinds.map(kindName);\n const hasNote = names.includes('note');\n const hasAdrAndSpec = names.includes('adr') && names.includes('spec');\n if (hasNote || hasAdrAndSpec) {\n const hints: string[] = [];\n if (hasNote) hints.push('If none fits \u2192 note.');\n if (hasAdrAndSpec) {\n hints.push(\n 'If torn between adr and spec \u2192 does it record a choice? adr. Does it describe how things work? spec.'\n );\n }\n lines.push('', hints.join(' '));\n }\n return lines.join('\\n');\n}\n\n// The arrow-and-annotation rendering asserts the default lifecycle; a custom\n// status list gets a plain enumeration rather than an invented ordering.\nconst CANONICAL_STATUS_FLOW = ['draft', 'active', 'superseded', 'archived'] as const;\n\nfunction buildStatusLine(statuses: ReadonlyArray<string>): string {\n const isCanonical =\n statuses.length === CANONICAL_STATUS_FLOW.length &&\n statuses.every((s, i) => s === CANONICAL_STATUS_FLOW[i]);\n return isCanonical\n ? `**Statuses:** ${statuses.join(' \u2192 ')} (one-directional; superseded requires superseded_by link)`\n : `**Statuses:** ${statuses.join(', ')}`;\n}\n\nfunction buildVocabulary(config: VaultConfig): string {\n const lines: string[] = [\n '## Controlled vocabulary',\n '',\n `**Kinds:** ${config.kinds.map(kindName).join(', ')}`,\n buildStatusLine(config.statuses),\n `**Methodologies:** ${config.methodologies.join(', ')}`,\n `**Canonical tags:** ${config.tags.canonical.join(', ')}`\n ];\n const aliases = Object.entries(config.tags.aliases);\n if (aliases.length > 0) {\n lines.push(`**Tag aliases:** ${aliases.map(([a, c]) => `${a} \u2192 ${c}`).join(', ')}`);\n }\n return lines.join('\\n');\n}\n\nexport function registerAuthoringResource(\n mcp: McpServer,\n _vaultRoot: string,\n vaultConfig: VaultConfig\n): void {\n mcp.registerResource(\n 'Authoring guide',\n 'wiki://authoring',\n {\n description:\n 'Wiki authoring pedagogy: kind selector, controlled vocabulary, authoring rules, resync protocol, and template URIs. Read before creating or editing wiki pages.',\n mimeType: 'text/markdown'\n },\n async (uri) => {\n const sections = [\n '# Wiki authoring guide',\n '',\n buildKindSelector(vaultConfig.kinds),\n '',\n buildVocabulary(vaultConfig),\n '',\n '## Templates',\n '',\n 'Full index with URIs and descriptions: `wiki://templates`',\n '',\n buildAuthoringRules(vaultConfig),\n '',\n buildSyncProtocol(vaultConfig)\n ];\n return {\n contents: [\n {\n uri: uri.toString(),\n mimeType: 'text/markdown' as const,\n text: sections.join('\\n')\n }\n ]\n };\n }\n );\n}\n", "import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { BUILT_IN_KINDS, type VaultConfig } from '../vault-config.js';\n\ninterface TemplateSpec {\n /** wiki://template/{domain}/{kind} \u2014 `note` collapses to single segment. */\n readonly uri: string;\n /** Human-readable name shown in resources/list. */\n readonly name: string;\n /** Filename in vault/templates/. */\n readonly file: string;\n /** Description shown in resources/list. */\n readonly description: string;\n}\n\n/**\n * The vault has 11 fixed templates, mirroring the v2 frontmatter schemas\n * (extended with `story` per adr-story-vocabulary-and-triage-fields).\n * URI scheme: `wiki://template/{domain}/{kind}` \u2014 the agent thinks\n * \"I'm authoring a {kind} in the {domain} domain\" and the URI matches\n * that mental model. `note` collapses to a single segment because the\n * notes domain has only one kind.\n */\nexport const TEMPLATES: ReadonlyArray<TemplateSpec> = [\n {\n uri: 'wiki://template/project/index',\n name: 'Project index',\n file: 'project-index.md',\n description:\n 'Identity card for a project. Frontmatter-heavy: methodology, phase, repo, scope, summary, tags. Short body.'\n },\n {\n uri: 'wiki://template/project/primer',\n name: 'Project primer',\n file: 'project-primer.md',\n description:\n 'Human-authored narrative context for a project. Free-form body. Inlined into the prime tool response.'\n },\n {\n uri: 'wiki://template/project/spec',\n name: 'Project spec',\n file: 'project-spec.md',\n description:\n 'Specification page \u2014 how a system or feature works (state of the world, not decision).'\n },\n {\n uri: 'wiki://template/project/adr',\n name: 'Project ADR',\n file: 'project-adr.md',\n description:\n 'Architecture Decision Record \u2014 pinned moment of choice. Sections: Status, Context, Decision, Rationale, Consequences.'\n },\n {\n uri: 'wiki://template/project/plan',\n name: 'Project plan',\n file: 'project-plan.md',\n description:\n 'Plan for a phase or initiative. Sections: Goal, Scope, Milestones, Dependencies, Status Log.'\n },\n {\n uri: 'wiki://template/project/ops',\n name: 'Project ops',\n file: 'project-ops.md',\n description: 'Operational runbook \u2014 how to run or operate a system. Procedural.'\n },\n {\n uri: 'wiki://template/project/story',\n name: 'Project story',\n file: 'project-story.md',\n description:\n 'User story with Gherkin scenarios and inline implementation slices. Lives at plan/{plan-name}/story-N-{slug}.md. Frontmatter carries triage_state, category, blocked_by, parent.'\n },\n {\n uri: 'wiki://template/research/index',\n name: 'Research index',\n file: 'research-index.md',\n description:\n 'Topic identity card for a research area. Frontmatter: confidence, source_count, summary, tags.'\n },\n {\n uri: 'wiki://template/research/article',\n name: 'Research article',\n file: 'research-article.md',\n description:\n 'Wikipedia-style article about a concept, entity, or system. Original synthesis with sources.'\n },\n {\n uri: 'wiki://template/research/src',\n name: 'Research source',\n file: 'research-src.md',\n description:\n 'Summary of an external source (paper, talk, doc) with citation. The only `src-` prefix in research.'\n },\n {\n uri: 'wiki://template/note',\n name: 'Note',\n file: 'note.md',\n description: 'Low-ceremony everyday note. Capture fast, sort later.'\n }\n];\n\n/**\n * Registry entries for custom kinds \u2014 object-form `kinds` entries outside the\n * built-in set. Single-segment URI (the `note` precedent: no domain to encode),\n * file by convention at `templates/{name}.md`, the kind's `signal` doubles as\n * the description.\n */\nfunction customTemplates(config: VaultConfig): TemplateSpec[] {\n const specs: TemplateSpec[] = [];\n for (const entry of config.kinds) {\n if (typeof entry === 'string' || BUILT_IN_KINDS.has(entry.name)) continue;\n specs.push({\n uri: `wiki://template/${entry.name}`,\n name: entry.name.charAt(0).toUpperCase() + entry.name.slice(1),\n file: `${entry.name}.md`,\n description: entry.signal\n });\n }\n return specs;\n}\n\n/**\n * Register all template resources with the MCP server. Each template is a\n * fixed URI; `resources/read` re-reads the file on every call, so edits to\n * vault/templates/*.md are picked up without restarting the server.\n */\nexport function registerTemplateResources(\n mcp: McpServer,\n vaultRoot: string,\n vaultConfig: VaultConfig\n): void {\n const dir = join(vaultRoot, 'templates');\n const templates = [...TEMPLATES, ...customTemplates(vaultConfig)];\n for (const tmpl of templates) {\n mcp.registerResource(\n tmpl.name,\n tmpl.uri,\n { description: tmpl.description, mimeType: 'text/markdown' },\n async (uri) => {\n let text: string;\n try {\n text = await readFile(join(dir, tmpl.file), 'utf8');\n } catch (err) {\n throw new Error(`template file missing: templates/${tmpl.file} (${tmpl.uri})`, {\n cause: err\n });\n }\n return {\n contents: [\n {\n uri: uri.toString(),\n mimeType: 'text/markdown' as const,\n text\n }\n ]\n };\n }\n );\n }\n\n const indexLines = ['# Wiki Templates', ''];\n for (const tmpl of templates) {\n indexLines.push(`- **${tmpl.name}** \u2014 \\`${tmpl.uri}\\` `);\n indexLines.push(` ${tmpl.description}`);\n }\n const indexText = indexLines.join('\\n');\n\n mcp.registerResource(\n 'Template index',\n 'wiki://templates',\n {\n description:\n 'Index of all wiki templates with URIs and descriptions. Read a specific template via its URI.',\n mimeType: 'text/markdown'\n },\n async (uri) => ({\n contents: [{ uri: uri.toString(), mimeType: 'text/markdown' as const, text: indexText }]\n })\n );\n}\n", "import { parse as parseYaml } from 'yaml';\n\n// Verbatim mirror of @llm-wiki/cli's src/frontmatter.ts. Kept byte-identical so\n// mcp parses frontmatter the same way sync/validate do. Collapse into a shared\n// package only when a third separate consumer appears (CLAUDE.md YAGNI rule).\n\nexport interface ParsedFrontmatter {\n data: Record<string, unknown>;\n content: string;\n}\n\n// Leading `---` block, YAML, closing `---`, then one consumed newline. Matches\n// gray-matter's delimiter handling; the closing `---` must be on its own line so\n// `---` rules inside the body are left intact.\nconst FRONTMATTER_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n?---\\r?\\n?/;\n\n/**\n * Split a page's frontmatter from its body using the `yaml` parser. Throws\n * (deterministically, no cache) when the frontmatter is not valid YAML. A page\n * with no leading delimiter parses to empty data and the whole input as body.\n */\nexport function parseFrontmatter(raw: string): ParsedFrontmatter {\n const match = FRONTMATTER_RE.exec(raw);\n if (!match) {\n return { data: {}, content: raw };\n }\n const yamlText = match[1] ?? '';\n const content = raw.slice(match[0].length);\n if (yamlText.trim() === '') {\n return { data: {}, content };\n }\n const parsed = parseYaml(yamlText);\n const data =\n parsed !== null && typeof parsed === 'object' ? (parsed as Record<string, unknown>) : {};\n return { data, content };\n}\n", "const FTS5_KEYWORDS = new Set(['AND', 'OR', 'NOT', 'NEAR']);\n\nexport function sanitizeFtsQuery(raw: string): string {\n return raw\n .replace(/[^\\p{L}\\p{N}\\s]/gu, ' ')\n .split(/\\s+/)\n .filter((t) => t.length > 0 && !FTS5_KEYWORDS.has(t))\n .join(' ');\n}\n", "/**\n * MCP CallToolResult helpers. `content[0].text` carries pretty-printed JSON\n * for LLM-facing clients; `structuredContent` carries the same payload as\n * raw JSON for clients that parse directly. Both fields kept in sync so\n * callers never choose one over the other.\n */\n\nexport function textJson(data: object) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }],\n structuredContent: data as Record<string, unknown>\n };\n}\n\n/**\n * Variant for tools whose model-facing surface is denser as markdown than as\n * pretty-printed JSON (~20% token savings on prose-heavy payloads). The\n * markdown goes to `content[0].text`; `structuredContent` keeps the machine\n * fields so a non-LLM client still gets a parseable shape.\n */\nexport function textWithStruct(markdown: string, data: object) {\n return {\n content: [{ type: 'text' as const, text: markdown }],\n structuredContent: data as Record<string, unknown>\n };\n}\n\nexport interface ToolErrorPayload {\n readonly code: string;\n readonly message: string;\n readonly details?: Record<string, unknown>;\n}\n\nexport function textError(error: ToolErrorPayload) {\n const payload = {\n code: error.code,\n message: error.message,\n details: error.details ?? {}\n };\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: JSON.stringify(payload) }],\n structuredContent: payload as Record<string, unknown>\n };\n}\n", "import { readFile } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\nimport type { DatabaseSync } from 'node:sqlite';\nimport { z } from 'zod';\nimport { parseFrontmatter } from '../frontmatter.js';\nimport { sanitizeFtsQuery } from '../lib/fts.js';\nimport { textError, textWithStruct } from '../lib/toolResponse.js';\nimport { kindName, type VaultConfig } from '../vault-config.js';\n\nexport const PrimeInputSchema = z.object({\n scope: z\n .string()\n .min(1)\n .describe('Project scope to prime (matches projects/{scope}/ in the vault).'),\n task: z\n .string()\n .optional()\n .describe('Optional task description; surfaces top-3 tsvector-ranked relevant pages.')\n});\n\nexport type PrimeInput = z.infer<typeof PrimeInputSchema>;\n\ninterface ProjectIndexFm {\n title?: string;\n methodology?: string;\n phase?: number;\n summary?: string;\n}\n\nexport interface PrimeData {\n scope: string;\n title: string | null;\n methodology: string | null;\n phase: number | null;\n summary: string;\n primer: string;\n counts: Record<string, number>;\n active_adrs: Array<{ path: string; slug: string; title: string; summary: string | null }>;\n current_plan: { path: string; slug: string; title: string } | null;\n top_tags: string[];\n hub_pages: Array<{ path: string; title: string; inbound: number }>;\n recent: Array<{ path: string; operation: string; date: string }>;\n relevant: Array<{ path: string; title: string; score: number }>;\n cross_scope: Array<{ from_scope: string; from_path: string; to_path: string }>;\n}\n\nexport interface PrimeDeps {\n readonly db: DatabaseSync;\n readonly vaultRoot: string;\n readonly vaultConfig: VaultConfig;\n}\n\nfunction pathSlug(p: string): string {\n return basename(p).replace(/\\.md$/, '');\n}\n\nasync function readIndexFm(vaultRoot: string, scope: string): Promise<ProjectIndexFm> {\n try {\n const raw = await readFile(join(vaultRoot, 'projects', scope, 'index.md'), 'utf8');\n return parseFrontmatter(raw).data as ProjectIndexFm;\n } catch {\n return {};\n }\n}\n\nasync function readPrimer(vaultRoot: string, scope: string): Promise<string> {\n try {\n const raw = await readFile(join(vaultRoot, 'projects', scope, 'primer.md'), 'utf8');\n return parseFrontmatter(raw)\n .content.trim()\n .replace(/^#\\s+[^\\n]+\\n+/, '');\n } catch {\n return '';\n }\n}\n\nexport async function prime(\n deps: PrimeDeps,\n input: PrimeInput\n): Promise<{ markdown: string; data: PrimeData }> {\n const { db, vaultRoot, vaultConfig } = deps;\n const { scope, task } = input;\n\n const [fm, primer] = await Promise.all([\n readIndexFm(vaultRoot, scope),\n readPrimer(vaultRoot, scope)\n ]);\n\n const counts = db\n .prepare('SELECT kind, count(*) AS count FROM pages WHERE scope = ? GROUP BY kind')\n .all(scope) as Array<{ kind: string; count: number | bigint }>;\n\n const adrs = db\n .prepare(\n \"SELECT path, title, summary FROM pages WHERE scope = ? AND kind = 'adr' AND status = 'active' ORDER BY updated DESC\"\n )\n .all(scope) as Array<{ path: string; title: string; summary: string | null }>;\n\n const planRow = db\n .prepare(\n \"SELECT path, title FROM pages WHERE scope = ? AND kind = 'plan' AND status = 'active' ORDER BY updated DESC LIMIT 1\"\n )\n .get(scope) as { path: string; title: string } | undefined;\n\n const tags = db\n .prepare(\n `SELECT j.value AS tag, count(*) AS cnt\n FROM pages, json_each(pages.tags) AS j\n WHERE scope = ?\n GROUP BY j.value\n ORDER BY cnt DESC\n LIMIT 10`\n )\n .all(scope) as Array<{ tag: string }>;\n\n const hubs = db\n .prepare(\n `SELECT p.path, p.title, count(*) AS inbound\n FROM links l JOIN pages p ON p.path = l.target_path\n WHERE p.scope = ?\n GROUP BY p.path, p.title\n ORDER BY inbound DESC LIMIT 5`\n )\n .all(scope) as Array<{ path: string; title: string; inbound: number | bigint }>;\n\n const events = db\n .prepare('SELECT path, operation, ts FROM events WHERE scope = ? ORDER BY ts DESC LIMIT 5')\n .all(scope) as Array<{ path: string; operation: string; ts: string }>;\n\n const crossScope = db\n .prepare(\n `SELECT pf.scope AS from_scope, l.source_path AS from_path, l.target_path AS to_path\n FROM links l\n JOIN pages pt ON pt.path = l.target_path\n JOIN pages pf ON pf.path = l.source_path\n WHERE pt.scope = ? AND pf.scope IS NOT NULL AND pf.scope != ?\n LIMIT 10`\n )\n .all(scope, scope) as Array<{ from_scope: string; from_path: string; to_path: string }>;\n\n let relevant: Array<{ path: string; title: string; score: number }> = [];\n if (task) {\n const ftsQuery = sanitizeFtsQuery(task);\n if (ftsQuery) {\n relevant = (\n db\n .prepare(\n `SELECT p.path, p.title, bm25(pages_fts) AS score\n FROM pages_fts\n JOIN pages p ON p.id = pages_fts.rowid\n WHERE pages_fts MATCH ? AND p.scope = ?\n ORDER BY bm25(pages_fts) LIMIT 3`\n )\n .all(ftsQuery, scope) as Array<{ path: string; title: string; score: number }>\n ).map((row) => ({\n path: row.path,\n title: row.title,\n score: row.score\n }));\n }\n }\n\n const countsRecord: Record<string, number> = {};\n for (const row of counts) countsRecord[row.kind] = Number(row.count);\n\n const data: PrimeData = {\n scope,\n title: fm.title ?? null,\n methodology: fm.methodology ?? null,\n phase: typeof fm.phase === 'number' ? fm.phase : null,\n summary: fm.summary ?? '',\n primer,\n counts: countsRecord,\n active_adrs: adrs.map((r) => ({\n path: r.path,\n slug: pathSlug(r.path),\n title: r.title,\n summary: r.summary\n })),\n current_plan: planRow\n ? {\n path: planRow.path,\n slug: pathSlug(planRow.path),\n title: planRow.title\n }\n : null,\n top_tags: tags.map((r) => r.tag),\n hub_pages: hubs.map((r) => ({\n path: r.path,\n title: r.title,\n inbound: Number(r.inbound)\n })),\n recent: events.map((r) => ({\n path: r.path,\n operation: r.operation,\n date: r.ts.slice(0, 10)\n })),\n relevant,\n cross_scope: crossScope.map((r) => ({\n from_scope: r.from_scope,\n from_path: r.from_path,\n to_path: r.to_path\n }))\n };\n\n return { markdown: renderMarkdown(data, vaultConfig, task), data };\n}\n\nexport function renderMarkdown(\n d: PrimeData,\n config: VaultConfig,\n task: string | undefined\n): string {\n const lines: string[] = [];\n\n const phaseLabel =\n d.phase !== null\n ? d.methodology\n ? `Phase ${d.phase} (${d.methodology})`\n : `Phase ${d.phase}`\n : '';\n const header = phaseLabel ? `${d.scope} \u2014 ${phaseLabel}` : d.scope;\n lines.push(`# ${header}`);\n if (d.summary) lines.push(d.summary);\n\n if (d.primer) {\n lines.push('', '## Primer', d.primer);\n }\n\n if (d.active_adrs.length > 0) {\n lines.push('', '## Active Decisions');\n for (const a of d.active_adrs) {\n lines.push(`- ${a.slug}: ${a.summary ?? a.title}`);\n }\n }\n\n if (d.current_plan) {\n lines.push('', '## Current Plan');\n lines.push(`${d.current_plan.slug}: ${d.current_plan.title}`);\n }\n\n const countEntries = Object.entries(d.counts);\n if (countEntries.length > 0) {\n lines.push('', '## Pages');\n lines.push(countEntries.map(([k, n]) => `${k}: ${n}`).join(' | '));\n }\n\n lines.push('', '## Vocabulary');\n lines.push(`kinds: ${config.kinds.map(kindName).join(', ')}`);\n lines.push(`statuses: ${config.statuses.join(', ')}`);\n lines.push(`tags: ${config.tags.canonical.join(', ')}`);\n\n if (d.top_tags.length > 0) {\n lines.push('', '## Tags');\n lines.push(d.top_tags.join(', '));\n }\n\n if (d.hub_pages.length > 0) {\n lines.push('', '## Hubs');\n for (const h of d.hub_pages) {\n lines.push(`- ${pathSlug(h.path)} (${h.inbound} inbound)`);\n }\n }\n\n if (d.recent.length > 0) {\n lines.push('', '## Recent');\n for (const r of d.recent) {\n lines.push(`- [${r.date}] ${pathSlug(r.path)} ${r.operation}`);\n }\n }\n\n if (d.relevant.length > 0) {\n lines.push('', `## Relevant (task: \"${task}\")`);\n for (const r of d.relevant) {\n lines.push(`- ${pathSlug(r.path)} (${r.score.toFixed(2)})`);\n }\n }\n\n if (d.cross_scope.length > 0) {\n lines.push('', '## Cross-scope');\n for (const c of d.cross_scope) {\n lines.push(`- ${c.from_scope}/${pathSlug(c.from_path)} \u2192 ${pathSlug(c.to_path)}`);\n }\n }\n\n lines.push(\n '',\n '---',\n 'Authoring wiki content? Read `wiki://authoring` for kind selector, rules, and templates. After edits: `kmd validate`, then `kmd sync`.'\n );\n\n return lines.join('\\n');\n}\n\nexport async function handlePrime(deps: PrimeDeps, input: PrimeInput) {\n if (!Object.hasOwn(deps.vaultConfig.scopes, input.scope)) {\n const valid = Object.keys(deps.vaultConfig.scopes).sort().join(', ');\n return textError({\n code: 'UNKNOWN_SCOPE',\n message: `unknown scope \"${input.scope}\"; valid scopes: ${valid}`\n });\n }\n try {\n const { markdown, data } = await prime(deps, input);\n return textWithStruct(markdown, data as unknown as Record<string, unknown>);\n } catch (err) {\n return textError({\n code: 'PRIME_FAILED',\n message: err instanceof Error ? err.message : String(err)\n });\n }\n}\n", "import type { DatabaseSync } from 'node:sqlite';\nimport { z } from 'zod';\nimport { sanitizeFtsQuery } from '../lib/fts.js';\nimport { textError, textJson } from '../lib/toolResponse.js';\n\nexport const SearchInputSchema = z.object({\n query: z\n .string()\n .min(1)\n .describe(\n 'Natural-language search query. Matched against title, summary, and body via SQLite FTS5.'\n ),\n scope: z\n .string()\n .optional()\n .describe('Optional: restrict to a project scope (e.g. \"ontology\", \"sotto\").'),\n kind: z\n .string()\n .optional()\n .describe(\n 'Optional: restrict to a kind. Project kinds: spec, adr, plan, ops. Research kinds: article, src. Misc: note.'\n ),\n limit: z\n .number()\n .int()\n .min(1)\n .max(50)\n .default(5)\n .describe('Maximum number of ranked results to return. Default 5.')\n});\n\nexport type SearchInput = z.infer<typeof SearchInputSchema>;\n\nexport interface SearchResult {\n readonly path: string;\n readonly title: string;\n readonly kind: string;\n readonly summary: string | null;\n readonly score: number;\n readonly scope?: string | null;\n}\n\nexport interface SearchDeps {\n readonly db: DatabaseSync;\n}\n\nexport function search(deps: SearchDeps, input: SearchInput): { results: SearchResult[] } {\n const ftsQuery = sanitizeFtsQuery(input.query);\n if (!ftsQuery) return { results: [] };\n\n let sql = `SELECT p.path, p.title, p.kind, p.summary, p.scope, bm25(pages_fts) AS score\n FROM pages_fts\n JOIN pages p ON p.id = pages_fts.rowid\n WHERE pages_fts MATCH ?`;\n const params: Array<string | number> = [ftsQuery];\n\n if (input.scope) {\n sql += ' AND p.scope = ?';\n params.push(input.scope);\n }\n if (input.kind) {\n sql += ' AND p.kind = ?';\n params.push(input.kind);\n }\n sql += ' ORDER BY bm25(pages_fts) LIMIT ?';\n params.push(input.limit);\n\n const rows = deps.db.prepare(sql).all(...params) as Array<{\n path: string;\n title: string;\n kind: string;\n summary: string | null;\n scope: string | null;\n score: number;\n }>;\n\n return {\n results: rows.map((r) => ({\n path: r.path,\n title: r.title,\n kind: r.kind,\n summary: r.summary,\n scope: r.scope,\n score: r.score\n }))\n };\n}\n\nexport function handleSearch(deps: SearchDeps, input: SearchInput) {\n try {\n return textJson(search(deps, input));\n } catch (err) {\n return textError({\n code: 'SEARCH_FAILED',\n message: err instanceof Error ? err.message : String(err)\n });\n }\n}\n", "import type { DatabaseSync } from 'node:sqlite';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { Logger } from './lib/logger.js';\nimport { registerAuthoringResource } from './resources/authoring.js';\nimport { registerTemplateResources } from './resources/templates.js';\nimport { handlePrime, PrimeInputSchema } from './tools/prime.js';\nimport { handleSearch, SearchInputSchema } from './tools/search.js';\nimport type { VaultConfig } from './vault-config.js';\n\nexport interface BuildServerArgs {\n readonly name: string;\n readonly version: string;\n readonly vaultRoot: string;\n readonly db: DatabaseSync;\n readonly logger: Logger;\n readonly vaultConfig: VaultConfig;\n}\n\nexport function buildServer(args: BuildServerArgs): McpServer {\n const { name, version, vaultRoot, db, logger, vaultConfig } = args;\n\n const mcp = new McpServer({ name, version }, { capabilities: { tools: {}, resources: {} } });\n\n mcp.tool(\n 'prime',\n 'Orient on a project. Returns a markdown briefing with: identity (scope, phase, methodology, summary), the human-authored primer.md inlined, active ADRs, current plan, page counts, top tags, hub pages (most-linked-to), recent events, cross-scope references, and \u2014 when `task` is provided \u2014 the top 3 tsvector-ranked relevant pages. Call once at session start. Empty sections are omitted to keep the surface lean.',\n PrimeInputSchema.shape,\n async (input) => {\n logger.debug({ tool: 'prime', input }, 'tool call');\n return handlePrime({ db, vaultRoot, vaultConfig }, input);\n }\n );\n\n mcp.tool(\n 'search',\n 'Full-text search across wiki pages via SQLite FTS5. Returns ranked candidates {path, title, kind, summary, score} \u2014 never page bodies. The agent reads the returned paths directly from the filesystem.',\n SearchInputSchema.shape,\n async (input) => {\n logger.debug({ tool: 'search', input }, 'tool call');\n return handleSearch({ db }, input);\n }\n );\n\n registerTemplateResources(mcp, vaultRoot, vaultConfig);\n registerAuthoringResource(mcp, vaultRoot, vaultConfig);\n\n return mcp;\n}\n", "import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { loadConfig } from './config.js';\nimport { createDatabase } from './db.js';\nimport { diag } from './lib/diag.js';\nimport { createLogger } from './lib/logger.js';\nimport { buildServer } from './server.js';\nimport { loadVaultConfig } from './vault-config.js';\n\nexport async function startMcpServer(): Promise<void> {\n diag('main entered');\n\n const config = loadConfig();\n diag('config loaded', { vault: config.wikiVault, level: config.logLevel });\n\n const vaultConfig = await loadVaultConfig(config.wikiVault);\n diag('vault config loaded', {\n scopes: Object.keys(vaultConfig.scopes).length,\n kinds: vaultConfig.kinds.length,\n statuses: vaultConfig.statuses.length\n });\n\n const logger = createLogger(config.logLevel, config.serverName);\n logger.info(\n { vault: config.wikiVault, serverName: config.serverName, serverVersion: config.serverVersion },\n 'starting wiki-mcp on stdio'\n );\n\n const db = createDatabase();\n diag('database opened');\n\n const mcp = buildServer({\n name: config.serverName,\n version: config.serverVersion,\n vaultRoot: config.wikiVault,\n db,\n logger,\n vaultConfig\n });\n diag('server built');\n\n const shutdown = async (signal: NodeJS.Signals) => {\n logger.info({ signal }, 'shutting down');\n diag('shutting down', { signal });\n try {\n await mcp.close();\n db.close();\n } catch (err) {\n logger.error({ err }, 'error during shutdown');\n }\n process.exit(0);\n };\n process.once('SIGINT', (s) => void shutdown(s));\n process.once('SIGTERM', (s) => void shutdown(s));\n\n const transport = new StdioServerTransport();\n await mcp.connect(transport);\n logger.info('wiki-mcp ready');\n diag('ready and connected to transport');\n}\n", "#!/usr/bin/env node\nimport { parseArgs } from 'node:util';\n\nconst USAGE = `usage: kmd <command> [options]\n\ncommands:\n sync vault \u2192 index sync (runs validate first)\n validate [<path>] deterministic vault checker (default: $WIKI_VAULT)\n mcp [<vault-root>] start the stdio MCP server (default: $WIKI_VAULT)\n db reset delete and recreate the index\n\noptions:\n --version print version\n --help show this help`;\n\nconst { positionals, values } = parseArgs({\n args: process.argv.slice(2),\n allowPositionals: true,\n strict: false,\n options: {\n version: { type: 'boolean', short: 'v' },\n help: { type: 'boolean', short: 'h' }\n }\n});\n\nconst command = values.version ? '--version' : values.help ? '--help' : positionals[0];\n\nfunction applyVaultRoot(positionalIndex: number): void {\n const arg = positionals[positionalIndex];\n if (arg) {\n process.env.WIKI_VAULT = arg;\n }\n}\n\nasync function run(): Promise<void> {\n switch (command) {\n case 'sync': {\n const { runSyncCommand } = await import('@llm-wiki/cli/cli');\n await runSyncCommand();\n break;\n }\n case 'validate': {\n applyVaultRoot(1);\n const { runValidate } = await import('@llm-wiki/cli/cli');\n await runValidate();\n break;\n }\n case 'mcp': {\n applyVaultRoot(1);\n const { startMcpServer } = await import('@llm-wiki/mcp/start');\n await startMcpServer();\n break;\n }\n case 'db': {\n const sub = positionals[1];\n if (sub === 'reset') {\n const { homedir } = await import('node:os');\n const { join } = await import('node:path');\n const { unlinkSync } = await import('node:fs');\n const dbPath = join(homedir(), '.kmd', 'db', 'index.db');\n let deleted = false;\n for (const suffix of ['', '-wal', '-shm']) {\n try {\n unlinkSync(dbPath + suffix);\n deleted = true;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n }\n console.log(deleted ? `deleted ${dbPath}` : `${dbPath} does not exist \u2014 nothing to reset`);\n } else {\n console.error(sub ? `unknown db subcommand: ${sub}` : 'usage: kmd db reset');\n process.exit(2);\n }\n break;\n }\n case '--version':\n case '-v': {\n const { readFileSync } = await import('node:fs');\n const { join, dirname } = await import('node:path');\n const { fileURLToPath } = await import('node:url');\n const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));\n const pkg = JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf8')) as {\n version: string;\n };\n console.log(pkg.version);\n break;\n }\n case '--help':\n case '-h':\n case undefined: {\n console.log(USAGE);\n if (command === undefined) process.exit(2);\n break;\n }\n default: {\n console.error(`unknown command: ${command}\\n\\n${USAGE}`);\n process.exit(2);\n }\n }\n}\n\nrun().catch((err) => {\n console.error('kmd failed:', err instanceof Error ? (err.stack ?? err.message) : err);\n process.exit(1);\n});\n"],
5
- "mappings": "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",
6
- "names": ["vaultRoot", "readFile", "join", "z", "readFile", "join", "positionals", "command", "z", "EnvSchema", "init_config", "mkdirSync", "homedir", "join", "mkdirSync", "homedir", "join", "readFile", "join", "parse", "z", "kindName", "loadVaultConfig", "vaultRoot", "VaultConfigSchema", "ScopeSchema", "KindEntrySchema", "BUILT_IN_KINDS", "kindName", "readFile", "join", "BUILT_IN_KINDS", "vaultRoot", "parseYaml", "parseFrontmatter", "FRONTMATTER_RE", "init_frontmatter", "readFile", "basename", "join", "z", "vaultRoot", "parseFrontmatter", "kindName", "init_frontmatter", "z", "vaultRoot", "loadVaultConfig", "init_config", "parseArgs", "runSyncCommand", "runValidate", "startMcpServer", "homedir", "join"]
4
+ "sourcesContent": ["import { createHash } from 'node:crypto';\nimport { realpathSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { basename, join, resolve } from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\n\nconst SCHEMA = `\nCREATE TABLE IF NOT EXISTS pages (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n path TEXT UNIQUE NOT NULL,\n title TEXT NOT NULL,\n kind TEXT NOT NULL,\n scope TEXT,\n topic TEXT,\n status TEXT NOT NULL DEFAULT 'draft',\n summary TEXT,\n tags TEXT,\n updated TEXT,\n body TEXT,\n content_hash TEXT,\n meta TEXT\n);\n\nCREATE INDEX IF NOT EXISTS pages_scope_kind ON pages(scope, kind, status);\nCREATE INDEX IF NOT EXISTS pages_topic_kind ON pages(topic, kind, status);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS pages_fts USING fts5(\n title, summary, body,\n content='pages',\n content_rowid='id'\n);\n\nCREATE TABLE IF NOT EXISTS links (\n source_path TEXT NOT NULL,\n target_path TEXT NOT NULL,\n link_text TEXT,\n PRIMARY KEY (source_path, target_path)\n);\n\nCREATE INDEX IF NOT EXISTS links_source ON links(source_path);\nCREATE INDEX IF NOT EXISTS links_target ON links(target_path);\n\nCREATE TABLE IF NOT EXISTS events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n ts TEXT DEFAULT (datetime('now')),\n scope TEXT,\n operation TEXT NOT NULL,\n path TEXT,\n note TEXT\n);\n\nCREATE INDEX IF NOT EXISTS events_scope_ts ON events(scope, ts DESC);\n\nCREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n);\n`;\n\nexport function openDatabase(dbPath: string): DatabaseSync {\n const db = new DatabaseSync(dbPath);\n db.exec('PRAGMA journal_mode = WAL');\n db.exec('PRAGMA foreign_keys = ON');\n db.exec(SCHEMA);\n return db;\n}\n\n/**\n * Directory holding all per-vault indexes: `$KMD_HOME/db/{vault-key}/index.db`\n * (default `~/.kmd`). One directory per vault keyed by resolved path, so two\n * vaults can never clobber each other's index and a moved/re-pointed vault\n * gets a fresh one.\n */\nexport function indexRootDir(): string {\n const home = process.env.KMD_HOME ?? join(homedir(), '.kmd');\n return join(home, 'db');\n}\n\n/**\n * Resolved (symlink-free, absolute) vault root \u2014 the canonical identity a\n * vault is keyed by. Falls back to plain resolution when the path does not\n * exist yet.\n */\nexport function canonicalVaultRoot(vaultRoot: string): string {\n try {\n return realpathSync(vaultRoot);\n } catch {\n return resolve(vaultRoot);\n }\n}\n\n/** `{basename}-{8-hex}` \u2014 human-scannable, collision-safe per resolved path. */\nexport function vaultKey(vaultRoot: string): string {\n const canonical = canonicalVaultRoot(vaultRoot);\n const hash = createHash('sha256').update(canonical).digest('hex').slice(0, 8);\n return `${basename(canonical)}-${hash}`;\n}\n\n/** Absolute path of the vault's index database file. */\nexport function resolveIndexPath(vaultRoot: string): string {\n return join(indexRootDir(), vaultKey(vaultRoot), 'index.db');\n}\n\nexport function getMeta(db: DatabaseSync, key: string): string | null {\n const row = db.prepare('SELECT value FROM meta WHERE key = ?').get(key) as\n | { value: string }\n | undefined;\n return row?.value ?? null;\n}\n\nexport function setMeta(db: DatabaseSync, key: string, value: string): void {\n db.prepare(\n 'INSERT INTO meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value'\n ).run(key, value);\n}\n", "import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parse } from 'yaml';\nimport { z } from 'zod';\n\nconst ScopeSchema = z.object({\n repo: z.string().optional(),\n methodology: z.string().optional(),\n status: z.string()\n});\n\nconst KindEntrySchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n signal: z.string(),\n where: z.string()\n })\n]);\n\nconst VaultConfigSchema = z\n .object({\n scopes: z.record(z.string(), ScopeSchema),\n kinds: z.array(KindEntrySchema),\n statuses: z.array(z.string()),\n methodologies: z.array(z.string()),\n tags: z.object({\n canonical: z.array(z.string()),\n aliases: z.record(z.string(), z.string())\n }),\n authoring_rules: z.string().optional(),\n authoring_rules_extra: z.string().optional(),\n sync_protocol: z.string().optional(),\n sync_protocol_extra: z.string().optional()\n })\n .superRefine((config, ctx) => {\n for (const [name, scope] of Object.entries(config.scopes)) {\n if (scope.methodology !== undefined && !config.methodologies.includes(scope.methodology)) {\n ctx.addIssue({\n code: 'custom',\n path: ['scopes', name, 'methodology'],\n message: `\"${scope.methodology}\" is not in the methodologies list`\n });\n }\n }\n });\n\nexport type KindEntry = z.infer<typeof KindEntrySchema>;\nexport type VaultConfig = z.infer<typeof VaultConfigSchema>;\n\n/** Kind name of a `kinds` entry \u2014 plain string, or the object form's `name`. */\nexport function kindName(entry: KindEntry): string {\n return typeof entry === 'string' ? entry : entry.name;\n}\n\n/**\n * Kinds with built-in engine pedagogy (kind-selector rows; most also carry a\n * served template). An object-form entry with one of these names rewords its\n * selector row only \u2014 it never creates custom-template expectations.\n */\nexport const BUILT_IN_KINDS: ReadonlySet<string> = new Set([\n 'project',\n 'spec',\n 'adr',\n 'plan',\n 'story',\n 'ops',\n 'topic',\n 'article',\n 'src',\n 'note',\n 'artifact',\n 'prompt'\n]);\n\n/**\n * Load and validate `$vaultRoot/vault.yaml` \u2014 the single source of truth for\n * the controlled vocabulary. Throws (fail-loud) when the file is missing or\n * the contents don't satisfy the schema; sync must not run on partial\n * vocabulary.\n */\nexport async function loadVaultConfig(vaultRoot: string): Promise<VaultConfig> {\n const path = join(vaultRoot, 'vault.yaml');\n let raw: string;\n try {\n raw = await readFile(path, 'utf8');\n } catch (err) {\n throw new Error(`vault.yaml not found at ${path}`, { cause: err });\n }\n const parsed = VaultConfigSchema.safeParse(parse(raw));\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` - ${i.path.join('.') || '(root)'}: ${i.message}`)\n .join('\\n');\n throw new Error(`Invalid vault.yaml at ${path}:\\n${issues}`);\n }\n return parsed.data;\n}\n", "import { parse as parseYaml } from 'yaml';\n\nexport interface ParsedFrontmatter {\n data: Record<string, unknown>;\n content: string;\n}\n\n// Leading `---` block, YAML, closing `---`, then one consumed newline. Matches\n// gray-matter's delimiter handling; the closing `---` must be on its own line so\n// `---` rules inside the body are left intact.\nconst FRONTMATTER_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n?---\\r?\\n?/;\n\n/**\n * Split a page's frontmatter from its body using the `yaml` parser. Throws\n * (deterministically, no cache) when the frontmatter is not valid YAML \u2014 this is\n * the failure mode `wiki validate` exists to catch. A page with no leading\n * delimiter parses to empty data and the whole input as body.\n */\nexport function parseFrontmatter(raw: string): ParsedFrontmatter {\n const match = FRONTMATTER_RE.exec(raw);\n if (!match) {\n return { data: {}, content: raw };\n }\n const yamlText = match[1] ?? '';\n const content = raw.slice(match[0].length);\n if (yamlText.trim() === '') {\n return { data: {}, content };\n }\n const parsed = parseYaml(yamlText);\n const data =\n parsed !== null && typeof parsed === 'object' ? (parsed as Record<string, unknown>) : {};\n return { data, content };\n}\n", "import { createHash } from 'node:crypto';\nimport { mkdirSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport { dirname, join, relative, sep } from 'node:path';\nimport type { DatabaseSync } from 'node:sqlite';\nimport { canonicalVaultRoot, openDatabase, resolveIndexPath, setMeta } from '@llm-wiki/db/database';\nimport { z } from 'zod';\nimport { loadVaultConfig } from './config.js';\nimport { type ParsedFrontmatter, parseFrontmatter } from './frontmatter.js';\n\nconst EnvSchema = z.object({\n WIKI_VAULT: z.string().min(1)\n});\n\n// Scan only the three content domains. raw/, templates/, .obsidian/, .git/\n// are intentionally excluded by the design.\nexport const SCAN_DOMAINS = ['projects', 'research', 'notes'] as const;\n\n// [[target]], [[target|display]], [[target#heading]], [[target^block]]\nconst WIKILINK_RE = /\\[\\[([^\\]|#^]+)(?:[#^][^\\]|]*)?(?:\\|([^\\]]+))?\\]\\]/g;\n\ninterface Frontmatter {\n title?: string;\n kind?: string;\n status?: string;\n summary?: string;\n tags?: string[];\n updated?: string | Date;\n}\n\n// Frontmatter keys that already map to first-class indexed columns. Anything\n// outside this set flows into the `meta` JSONB column verbatim, so future\n// vocabulary extensions (e.g. story.triage_state, story.category) become\n// queryable without further schema changes.\nconst INDEXED_FRONTMATTER_KEYS = new Set<string>([\n 'title',\n 'kind',\n 'status',\n 'summary',\n 'tags',\n 'updated',\n 'scope',\n 'topic'\n]);\n\ninterface WikiLink {\n target: string;\n text: string | null;\n}\n\ninterface PageFields {\n path: string;\n title: string;\n kind: string;\n scope: string | null;\n topic: string | null;\n status: string;\n summary: string | null;\n tags: string[] | null;\n updated: string | null;\n body: string;\n hash: string;\n meta: Record<string, unknown> | null;\n}\n\ntype SyncResult = 'changed' | 'unchanged' | 'skipped';\n\nfunction loadEnv(): { WIKI_VAULT: string } {\n const parsed = EnvSchema.safeParse({\n WIKI_VAULT: process.env.WIKI_VAULT\n });\n if (!parsed.success) {\n console.error('invalid env:');\n console.error(parsed.error.format());\n process.exit(1);\n }\n return parsed.data;\n}\n\nexport async function walkMarkdown(root: string, domain: string): Promise<string[]> {\n const out: string[] = [];\n async function recurse(dir: string): Promise<void> {\n // null when the domain dir doesn't exist yet \u2014 fine, nothing to walk.\n const entries = await readdir(dir, { withFileTypes: true }).catch(() => null);\n if (!entries) return;\n for (const entry of entries) {\n if (entry.name.startsWith('.')) continue;\n if (entry.isDirectory()) {\n await recurse(join(dir, entry.name));\n } else if (entry.isFile() && entry.name.endsWith('.md')) {\n out.push(join(dir, entry.name));\n }\n }\n }\n await recurse(join(root, domain));\n return out;\n}\n\nexport function toRelativePath(root: string, absolute: string): string {\n return relative(root, absolute).split(sep).join('/');\n}\n\nfunction sha256(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nexport function extractWikilinks(body: string): WikiLink[] {\n const links: WikiLink[] = [];\n const seen = new Set<string>();\n for (const match of body.matchAll(WIKILINK_RE)) {\n const rawTarget = match[1]?.trim() ?? '';\n if (!rawTarget) continue;\n // Treat any existing extension as authoritative (handles embeds of\n // `.base`, `.png`, `.pdf`, etc.); only append `.md` when the target\n // is bare.\n const hasExt = /\\.[a-zA-Z0-9]+$/.test(rawTarget);\n const target = hasExt ? rawTarget : `${rawTarget}.md`;\n const text = match[2]?.trim() ?? null;\n const key = `${target}|${text ?? ''}`;\n if (seen.has(key)) continue;\n seen.add(key);\n links.push({ target, text });\n }\n return links;\n}\n\n/**\n * Path is authoritative for scope/topic. Frontmatter may also carry these\n * (for human readability) but sync trusts the filesystem.\n *\n * projects/{scope}/... \u2192 scope = first segment\n * research/{topic}/... \u2192 topic = first segment\n * notes/... \u2192 both null\n */\nexport function deriveLocation(relPath: string): { scope: string | null; topic: string | null } {\n const segments = relPath.split('/');\n const domain = segments[0];\n if (domain === 'projects' && segments.length >= 2 && segments[1]) {\n return { scope: segments[1], topic: null };\n }\n if (domain === 'research' && segments.length >= 2 && segments[1]) {\n return { scope: null, topic: segments[1] };\n }\n return { scope: null, topic: null };\n}\n\n/**\n * Build the page row from frontmatter + path. Returns `null` to signal\n * \"skip this file\" (intentionally not indexed).\n *\n * Skip rules:\n * - No `title` in frontmatter \u2192 narrative-only page (e.g., primer.md).\n * - No `kind` AND not under notes/ \u2192 authoring incomplete; warn.\n *\n * Notes are the one place where `kind` is implied by location.\n */\nexport function buildPageFields(\n relPath: string,\n raw: string,\n parsed: ParsedFrontmatter,\n knownScopes: ReadonlySet<string>\n): PageFields | null {\n const fm = parsed.data as Frontmatter;\n if (!fm.title) {\n return null;\n }\n\n let kind = fm.kind;\n if (!kind) {\n if (relPath.startsWith('notes/')) {\n kind = 'note';\n } else {\n console.warn(` skip: ${relPath} \u2014 has title but missing kind`);\n return null;\n }\n }\n\n const { scope, topic } = deriveLocation(relPath);\n if (scope !== null && !knownScopes.has(scope)) {\n throw new Error(\n `unknown scope \"${scope}\" for ${relPath} \u2014 add it to vault.yaml or remove the page`\n );\n }\n const updated =\n fm.updated instanceof Date\n ? fm.updated.toISOString().slice(0, 10)\n : typeof fm.updated === 'string'\n ? fm.updated.slice(0, 10)\n : null;\n\n const metaEntries = Object.entries(parsed.data as Record<string, unknown>).filter(\n ([k]) => !INDEXED_FRONTMATTER_KEYS.has(k)\n );\n const meta = metaEntries.length > 0 ? Object.fromEntries(metaEntries) : null;\n\n return {\n path: relPath,\n title: fm.title,\n kind,\n scope,\n topic,\n status: fm.status ?? (kind === 'note' ? 'active' : 'draft'),\n summary: fm.summary ?? null,\n tags: Array.isArray(fm.tags) ? fm.tags : null,\n updated,\n body: parsed.content,\n hash: sha256(raw),\n meta\n };\n}\n\nexport function syncPage(db: DatabaseSync, fields: PageFields): SyncResult {\n const existing = db.prepare('SELECT content_hash FROM pages WHERE path = ?').get(fields.path) as\n | { content_hash: string | null }\n | undefined;\n if (existing?.content_hash === fields.hash) {\n return 'unchanged';\n }\n\n const upsert = db.prepare(\n `INSERT INTO pages (path, title, kind, scope, topic, status, summary, tags, updated, body, content_hash, meta)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (path) DO UPDATE SET\n title = EXCLUDED.title,\n kind = EXCLUDED.kind,\n scope = EXCLUDED.scope,\n topic = EXCLUDED.topic,\n status = EXCLUDED.status,\n summary = EXCLUDED.summary,\n tags = EXCLUDED.tags,\n updated = EXCLUDED.updated,\n body = EXCLUDED.body,\n content_hash = EXCLUDED.content_hash,\n meta = EXCLUDED.meta`\n );\n\n upsert.run(\n fields.path,\n fields.title,\n fields.kind,\n fields.scope,\n fields.topic,\n fields.status,\n fields.summary,\n fields.tags ? JSON.stringify(fields.tags) : null,\n fields.updated,\n fields.body,\n fields.hash,\n fields.meta ? JSON.stringify(fields.meta) : null\n );\n\n db.prepare('DELETE FROM links WHERE source_path = ?').run(fields.path);\n const insertLink = db.prepare(\n `INSERT INTO links (source_path, target_path, link_text)\n VALUES (?, ?, ?)\n ON CONFLICT (source_path, target_path) DO NOTHING`\n );\n for (const link of extractWikilinks(fields.body)) {\n insertLink.run(fields.path, link.target, link.text);\n }\n\n return 'changed';\n}\n\nexport async function runSync(): Promise<void> {\n const env = loadEnv();\n const dbPath = resolveIndexPath(env.WIKI_VAULT);\n console.log(`sync: ${env.WIKI_VAULT} \u2192 ${dbPath}`);\n\n const vaultConfig = await loadVaultConfig(env.WIKI_VAULT);\n const scopes = new Set(Object.keys(vaultConfig.scopes));\n\n mkdirSync(dirname(dbPath), { recursive: true });\n const db = openDatabase(dbPath);\n\n try {\n const files: string[] = [];\n for (const domain of SCAN_DOMAINS) {\n files.push(...(await walkMarkdown(env.WIKI_VAULT, domain)));\n }\n\n const indexedPaths: string[] = [];\n let changed = 0;\n let unchanged = 0;\n let skipped = 0;\n\n for (const file of files) {\n const path = toRelativePath(env.WIKI_VAULT, file);\n const raw = await readFile(file, 'utf8');\n const parsed = parseFrontmatter(raw);\n const fields = buildPageFields(path, raw, parsed, scopes);\n if (!fields) {\n skipped++;\n continue;\n }\n\n const result = syncPage(db, fields);\n if (result === 'changed') {\n changed++;\n } else {\n unchanged++;\n }\n indexedPaths.push(path);\n }\n\n let pagesDeleted = 0;\n let linksDeleted = 0;\n if (indexedPaths.length > 0) {\n const placeholders = indexedPaths.map(() => '?').join(', ');\n const pageResult = db\n .prepare(`DELETE FROM pages WHERE path NOT IN (${placeholders})`)\n .run(...indexedPaths);\n pagesDeleted = Number(pageResult.changes);\n const linkResult = db\n .prepare('DELETE FROM links WHERE source_path NOT IN (SELECT path FROM pages)')\n .run();\n linksDeleted = Number(linkResult.changes);\n } else {\n console.warn('no indexable pages found; skipping orphan deletion (safety)');\n }\n\n db.exec(\"INSERT INTO pages_fts(pages_fts) VALUES('rebuild')\");\n\n setMeta(db, 'vault_root', canonicalVaultRoot(env.WIKI_VAULT));\n setMeta(db, 'last_synced', new Date().toISOString());\n\n console.log(\n `done: ${changed} changed, ${unchanged} unchanged, ${skipped} skipped, ${pagesDeleted} pages deleted, ${linksDeleted} link orphans cleared`\n );\n } finally {\n db.close();\n }\n}\n", "import { readFile, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { BUILT_IN_KINDS, kindName, loadVaultConfig, type VaultConfig } from './config.js';\nimport { parseFrontmatter } from './frontmatter.js';\nimport {\n deriveLocation,\n extractWikilinks,\n SCAN_DOMAINS,\n toRelativePath,\n walkMarkdown\n} from './sync.js';\n\nexport type Severity = 'error' | 'warning';\n\nexport interface Finding {\n path: string;\n rule: string;\n severity: Severity;\n message: string;\n}\n\n/** Mirrors sync's indexability marker: `buildPageFields` skips any page whose\n * `title` is not a non-empty string. */\nfunction hasIndexableTitle(data: Record<string, unknown>): boolean {\n return typeof data.title === 'string' && data.title.trim() !== '';\n}\n\n/**\n * A page sync would index: it has a `title` and either a `kind` or lives under\n * notes/ (notes imply kind=note). Title-less narrative/reserved pages (primers,\n * the title-less ontology/alayacare pages) are skipped by sync, so the\n * sync-mirror checks are gated on this \u2014 validate governs what sync governs.\n * The kind-floor contract checks gate on kind intent instead: a missing or\n * empty title is itself a floor violation, and must not gate itself out.\n */\nfunction isIndexed(relPath: string, data: Record<string, unknown>): boolean {\n if (!hasIndexableTitle(data)) return false;\n if (typeof data.kind === 'string' && data.kind !== '') return true;\n return relPath.startsWith('notes/');\n}\n\n/**\n * A reserved `primer.md` (at any level). Title-less, so it is skipped by the\n * indexed-page checks \u2014 but it is the agent's first-read surface, so a stale\n * `[[link]]` there must not silently pass the gate. Its body links are checked.\n */\nfunction isPrimer(relPath: string): boolean {\n return relPath === 'primer.md' || relPath.endsWith('/primer.md');\n}\n\n// Required-field floor per kind \u2014 the set of keys present on 100% of existing\n// pages of that kind (corpus-scanned; spec-wiki-validate \u00A7 Required fields per\n// kind). Key-presence, not non-emptiness. Kinds absent here (artifact, prompt,\n// glossary-entry, pso-roster) carry no required-field contract. `tags` is\n// governed separately by the `tags-required` rule (non-empty), not this floor.\nconst REQUIRED_FIELDS: Record<string, readonly string[]> = {\n project: [\n 'title',\n 'kind',\n 'scope',\n 'status',\n 'summary',\n 'updated',\n 'methodology',\n 'phase',\n 'repo'\n ],\n spec: ['title', 'kind', 'scope', 'status', 'summary', 'updated', 'sources'],\n adr: ['title', 'kind', 'scope', 'status', 'updated'],\n plan: ['title', 'kind', 'scope', 'status', 'summary', 'updated'],\n ops: ['title', 'kind', 'scope', 'status', 'summary', 'updated'],\n story: [\n 'title',\n 'kind',\n 'scope',\n 'status',\n 'updated',\n 'parent',\n 'triage_state',\n 'category',\n 'blocked_by',\n 'sources'\n ],\n topic: ['title', 'kind', 'status', 'summary', 'updated', 'confidence'],\n article: ['title', 'kind', 'status', 'updated'],\n src: ['title', 'kind', 'topic', 'status', 'summary', 'updated'],\n note: ['title', 'updated']\n};\n\n// Kinds exempt from the tags-required floor: deliverable/package internals\n// (artifact, prompt) and registry stubs (glossary-entry, pso-roster), not\n// discoverable content pages. Mirrors the required-fields floor exemption.\nconst TAG_OPTIONAL_KINDS = new Set(['artifact', 'prompt', 'glossary-entry', 'pso-roster']);\n\n// Per-kind path patterns (spec-wiki-validate \u00A7 Folder and slug patterns). Kinds\n// absent here have no documented pattern and are exempt (article free naming,\n// notes, and the registered-but-undocumented ontology/alayacare kinds).\nconst FOLDER_PATTERNS: Record<string, RegExp> = {\n spec: /^projects\\/[^/]+\\/spec\\/spec-[^/]+\\.md$/,\n adr: /^projects\\/[^/]+\\/adr\\/adr-[^/]+\\.md$/,\n ops: /^projects\\/[^/]+\\/ops\\/ops-[^/]+\\.md$/,\n plan: /^projects\\/[^/]+\\/plan\\/plan-[^/]+\\.md$/,\n story: /^projects\\/[^/]+\\/plan\\/[^/]+\\/story-[^/]+\\.md$/,\n project: /^projects\\/[^/]+\\/index\\.md$/,\n topic: /^research\\/[^/]+\\/index\\.md$/,\n src: /^research\\/[^/]+\\/src-[^/]+\\.md$/\n};\n\nfunction checkRequiredFields(relPath: string, data: Record<string, unknown>): Finding[] {\n // Notes carry no `kind` key \u2014 sync infers `note` from location; mirror that so\n // the note floor is reachable rather than dead.\n const kind =\n typeof data.kind === 'string' && data.kind !== ''\n ? data.kind\n : relPath.startsWith('notes/')\n ? 'note'\n : undefined;\n const required = kind ? REQUIRED_FIELDS[kind] : undefined;\n if (!required) return [];\n const findings: Finding[] = [];\n for (const field of required) {\n if (!Object.hasOwn(data, field)) {\n findings.push({\n path: relPath,\n rule: 'required-fields',\n severity: 'error',\n message: `missing required field \"${field}\" for kind \"${kind}\"`\n });\n }\n }\n // Title carve-out from key-presence: the one floor field where emptiness is\n // a violation \u2014 sync skips any page without a non-empty title, silently\n // dropping it from the index.\n if (Object.hasOwn(data, 'title') && !hasIndexableTitle(data)) {\n findings.push({\n path: relPath,\n rule: 'required-fields',\n severity: 'error',\n message: `\"title\" must be a non-empty string for kind \"${kind}\" \u2014 sync skips the page otherwise`\n });\n }\n return findings;\n}\n\n// Universal floor for custom kinds: the fields the index serves. Warnings,\n// never errors \u2014 custom kinds keep their freedom; the nudge keeps pages\n// retrievable (title/summary feed FTS, updated feeds prime ordering).\nconst UNIVERSAL_FLOOR = ['title', 'summary', 'updated'] as const;\n\n/** Names of object-form kinds outside the built-in set \u2014 the explicit opt-in\n * to custom pedagogy. Plain-string unknown kinds stay floor-free. */\nfunction customKindNames(cfg: VaultConfig): Set<string> {\n const names = new Set<string>();\n for (const entry of cfg.kinds) {\n if (typeof entry !== 'string' && !BUILT_IN_KINDS.has(entry.name)) names.add(entry.name);\n }\n return names;\n}\n\nfunction checkCustomKindFloor(\n relPath: string,\n data: Record<string, unknown>,\n cfg: VaultConfig\n): Finding[] {\n const kind = data.kind;\n if (typeof kind !== 'string' || !customKindNames(cfg).has(kind)) return [];\n const findings: Finding[] = [];\n for (const field of UNIVERSAL_FLOOR) {\n if (!Object.hasOwn(data, field)) {\n findings.push({\n path: relPath,\n rule: 'custom-kind-floor',\n severity: 'warning',\n message: `custom kind \"${kind}\": missing \"${field}\" \u2014 the universal floor (title, summary, updated) keeps the page retrievable`\n });\n }\n }\n if (Object.hasOwn(data, 'title') && !hasIndexableTitle(data)) {\n findings.push({\n path: relPath,\n rule: 'custom-kind-floor',\n severity: 'warning',\n message: `custom kind \"${kind}\": \"title\" is empty \u2014 sync skips title-less pages; this page will not be indexed`\n });\n }\n return findings;\n}\n\n/**\n * Tags are an open dimension \u2014 any value, no controlled vocabulary \u2014 but every\n * content page must carry at least one. Indexed pages whose kind is not\n * tag-optional require a non-empty `tags` list.\n */\nfunction checkTagsRequired(relPath: string, data: Record<string, unknown>): Finding[] {\n const kind =\n typeof data.kind === 'string' && data.kind !== ''\n ? data.kind\n : relPath.startsWith('notes/')\n ? 'note'\n : undefined;\n if (kind && TAG_OPTIONAL_KINDS.has(kind)) return [];\n if (Array.isArray(data.tags) && data.tags.length > 0) return [];\n return [\n {\n path: relPath,\n rule: 'tags-required',\n severity: 'error',\n message:\n 'tags must be present and non-empty (tags are open \u2014 any values, every content page tagged)'\n }\n ];\n}\n\nfunction checkFolderSlug(relPath: string, data: Record<string, unknown>): Finding[] {\n const kind = data.kind;\n const pattern = typeof kind === 'string' ? FOLDER_PATTERNS[kind] : undefined;\n if (!pattern || pattern.test(relPath)) return [];\n return [\n {\n path: relPath,\n rule: 'folder-slug',\n severity: 'error',\n message: `path does not match the \"${kind}\" slug pattern ${pattern.source}`\n }\n ];\n}\n\nfunction checkVocabulary(\n relPath: string,\n data: Record<string, unknown>,\n cfg: VaultConfig\n): Finding[] {\n const findings: Finding[] = [];\n const kind = data.kind;\n if (typeof kind === 'string' && !cfg.kinds.some((k) => kindName(k) === kind)) {\n findings.push({\n path: relPath,\n rule: 'kind-vocabulary',\n severity: 'error',\n message: `kind \"${kind}\" is not in vault.yaml`\n });\n }\n const status = data.status;\n if (typeof status === 'string' && !cfg.statuses.includes(status)) {\n findings.push({\n path: relPath,\n rule: 'status-vocabulary',\n severity: 'error',\n message: `status \"${status}\" is not in vault.yaml`\n });\n }\n const { scope } = deriveLocation(relPath);\n if (scope !== null && !Object.hasOwn(cfg.scopes, scope)) {\n findings.push({\n path: relPath,\n rule: 'scope-vocabulary',\n severity: 'error',\n message: `scope \"${scope}\" is not in vault.yaml`\n });\n }\n const methodology = data.methodology;\n if (typeof methodology === 'string' && !cfg.methodologies.includes(methodology)) {\n findings.push({\n path: relPath,\n rule: 'methodology-vocabulary',\n severity: 'error',\n message: `methodology \"${methodology}\" is not in vault.yaml`\n });\n }\n return findings;\n}\n\n/**\n * Path is authoritative for `scope`/`topic`: sync derives them from the path and\n * ignores frontmatter. A frontmatter copy is allowed for readability but must not\n * lie \u2014 a mismatch means the label disagrees with where the file actually lives.\n * Fires only where the path defines the value (projects \u2192 scope, research \u2192 topic)\n * and the frontmatter carries it.\n */\nfunction checkScopePath(relPath: string, data: Record<string, unknown>): Finding[] {\n const { scope, topic } = deriveLocation(relPath);\n const findings: Finding[] = [];\n if (\n scope !== null &&\n typeof data.scope === 'string' &&\n data.scope !== '' &&\n data.scope !== scope\n ) {\n findings.push({\n path: relPath,\n rule: 'path-authority',\n severity: 'error',\n message: `frontmatter scope \"${data.scope}\" disagrees with path scope \"${scope}\"`\n });\n }\n if (\n topic !== null &&\n typeof data.topic === 'string' &&\n data.topic !== '' &&\n data.topic !== topic\n ) {\n findings.push({\n path: relPath,\n rule: 'path-authority',\n severity: 'error',\n message: `frontmatter topic \"${data.topic}\" disagrees with path topic \"${topic}\"`\n });\n }\n return findings;\n}\n\n/** A reference's basename target, or null if absent/empty/non-string. */\nfunction refTarget(value: unknown): string | null {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim();\n return trimmed === '' ? null : basename(trimmed);\n}\n\n/**\n * Basename targets of a reference field that may be scalar or array. `supersedes`\n * and `superseded_by` are list-valued in the wild (one ADR can supersede several),\n * so a scalar-only read would miss them and falsely fail reciprocity.\n */\nfunction refTargets(value: unknown): string[] {\n if (Array.isArray(value)) {\n return value.map(refTarget).filter((t): t is string => t !== null);\n }\n const single = refTarget(value);\n return single === null ? [] : [single];\n}\n\n/**\n * Strip code regions so `[[...]]`-shaped syntax inside them is not mistaken for a\n * wikilink: fenced ``` blocks (e.g. a bash `if [[ x == y ]]` test) and inline\n * `code` spans (e.g. a `[[wikilink]]` documentation example). Sync's own link\n * extraction is unaffected \u2014 its pseudo-links are a separate, pre-existing concern.\n */\nfunction stripCode(body: string): string {\n return body.replace(/```[\\s\\S]*?```/g, '').replace(/`[^`]*`/g, '');\n}\n\n/**\n * Body `[[wikilink]]` dangling check against the basename `refIndex`. Code\n * regions are stripped first (see `stripCode`) so `[[...]]`-shaped syntax inside\n * fences/inline-code is not mistaken for a link. Shared by the indexed-page\n * reference checks and the title-less primer carve-in.\n */\nfunction checkBodyLinks(relPath: string, body: string, refIndex: ReadonlySet<string>): Finding[] {\n const findings: Finding[] = [];\n for (const link of extractWikilinks(stripCode(body))) {\n if (!link.target.endsWith('.md')) continue;\n if (!refIndex.has(basename(link.target))) {\n findings.push({\n path: relPath,\n rule: 'dangling-link',\n severity: 'error',\n message: `wikilink target \"${link.target}\" does not resolve`\n });\n }\n }\n return findings;\n}\n\n/**\n * Reference resolution against the basename index: body `[[wikilinks]]` to `.md`\n * targets, plus the frontmatter reference fields. Empty values never fire (the\n * empty `supersedes:`/`superseded_by:` template keys are the 52/57). Non-`.md`\n * wikilink targets (images, `.base`, external) are not policed.\n */\nfunction checkReferences(\n relPath: string,\n data: Record<string, unknown>,\n body: string,\n refIndex: ReadonlySet<string>\n): Finding[] {\n const findings: Finding[] = checkBodyLinks(relPath, body, refIndex);\n const fieldRefs: string[] = [];\n const parent = refTarget(data.parent);\n if (parent !== null) fieldRefs.push(parent);\n for (const field of ['supersedes', 'superseded_by', 'blocked_by'] as const) {\n fieldRefs.push(...refTargets(data[field]));\n }\n for (const target of fieldRefs) {\n if (!refIndex.has(target)) {\n findings.push({\n path: relPath,\n rule: 'ref-resolves',\n severity: 'error',\n message: `frontmatter reference \"${target}\" does not resolve`\n });\n }\n }\n return findings;\n}\n\n/**\n * Tag policy: only the alias case is enforced, as a non-fatal warning. A full\n * canonical-membership check is deferred \u2014 the corpus carries ~211 distinct tags\n * against an 11-entry canonical list, so flagging non-canonical tags would fire\n * on nearly every page (spec-wiki-validate \u00A7 Tag policy).\n */\nfunction checkTags(relPath: string, data: Record<string, unknown>, cfg: VaultConfig): Finding[] {\n if (!Array.isArray(data.tags)) return [];\n const findings: Finding[] = [];\n for (const tag of data.tags) {\n if (typeof tag === 'string' && Object.hasOwn(cfg.tags.aliases, tag)) {\n findings.push({\n path: relPath,\n rule: 'tag-alias',\n severity: 'warning',\n message: `tag \"${tag}\" is an alias; use canonical \"${cfg.tags.aliases[tag]}\"`\n });\n }\n }\n return findings;\n}\n\n/** `status: superseded` requires a non-empty `superseded_by` (README \u00A76). */\nfunction checkSupersededLink(relPath: string, data: Record<string, unknown>): Finding[] {\n if (data.status === 'superseded' && refTargets(data.superseded_by).length === 0) {\n return [\n {\n path: relPath,\n rule: 'superseded-needs-link',\n severity: 'error',\n message: 'status is \"superseded\" but superseded_by is empty'\n }\n ];\n }\n return [];\n}\n\n/** Sync-mirror checks on already-parsed frontmatter \u2014 gated on indexability,\n * governing exactly what sync indexes. Pure. */\nfunction checkIndexedPage(\n relPath: string,\n data: Record<string, unknown>,\n body: string,\n cfg: VaultConfig,\n refIndex: ReadonlySet<string>\n): Finding[] {\n if (!isIndexed(relPath, data)) return [];\n return [\n ...checkTagsRequired(relPath, data),\n ...checkFolderSlug(relPath, data),\n ...checkVocabulary(relPath, data, cfg),\n ...checkScopePath(relPath, data),\n ...checkReferences(relPath, data, body, refIndex),\n ...checkSupersededLink(relPath, data),\n ...checkTags(relPath, data, cfg)\n ];\n}\n\n/**\n * Deterministic checks on a single page's raw content. Pure \u2014 no IO. Parses the\n * frontmatter first: a parse failure is the live bug that silently halts sync\n * mid-walk, reported regardless of the page's other fields. Well-formed pages\n * are then subjected to the indexed-page checks (vocabulary, \u2026) against the\n * controlled vocabulary `cfg` and the basename `refIndex` of valid link targets.\n */\nexport function validatePage(\n relPath: string,\n raw: string,\n cfg: VaultConfig,\n refIndex: ReadonlySet<string>\n): Finding[] {\n let parsed: ReturnType<typeof parseFrontmatter>;\n try {\n parsed = parseFrontmatter(raw);\n } catch (err) {\n return [\n {\n path: relPath,\n rule: 'frontmatter-parse',\n severity: 'error',\n message: err instanceof Error ? err.message : String(err)\n }\n ];\n }\n if (isPrimer(relPath)) {\n return checkBodyLinks(relPath, parsed.content, refIndex);\n }\n // Two-stage pipeline. Contract checks (the kind floors) gate on kind intent:\n // a floor violation must surface even when the violation is the very field\n // (title) that decides indexability \u2014 otherwise the page silently drops from\n // the index with zero findings. Sync-mirror checks gate on isIndexed.\n return [\n ...checkRequiredFields(relPath, parsed.data),\n ...checkCustomKindFloor(relPath, parsed.data, cfg),\n ...checkIndexedPage(relPath, parsed.data, parsed.content, cfg, refIndex)\n ];\n}\n\n/** Exit-code decision: any error-severity finding fails the run. */\nexport function hasErrors(findings: Finding[]): boolean {\n return findings.some((f) => f.severity === 'error');\n}\n\n/** Basename (no extension) of a vault-relative path. */\nfunction basename(relPath: string): string {\n const last = relPath.split('/').pop() ?? relPath;\n return last.replace(/\\.md$/, '');\n}\n\nexport interface PageData {\n path: string;\n data: Record<string, unknown>;\n}\n\n/**\n * Cross-page ADR supersession reciprocity: a non-empty `superseded_by: B` on\n * ADR A requires `supersedes: A` on B, and vice-versa. Fires only on non-empty\n * values; a value pointing at a non-existent ADR is a `ref-resolves` error\n * (checked per-page), not a reciprocity error, so unresolved targets are skipped\n * here. (spec-wiki-validate \u00A7 Supersession.)\n */\nexport function validateSupersession(pages: PageData[]): Finding[] {\n const adrs = new Map<string, { path: string; supersedes: string[]; supersededBy: string[] }>();\n for (const { path, data } of pages) {\n if (data.kind !== 'adr') continue;\n adrs.set(basename(path), {\n path,\n supersedes: refTargets(data.supersedes),\n supersededBy: refTargets(data.superseded_by)\n });\n }\n const findings: Finding[] = [];\n for (const [name, adr] of adrs) {\n for (const target of adr.supersededBy) {\n const other = adrs.get(target);\n if (other && !other.supersedes.includes(name)) {\n findings.push({\n path: adr.path,\n rule: 'supersession-reciprocal',\n severity: 'error',\n message: `superseded_by \"${target}\" which does not declare supersedes \"${name}\"`\n });\n }\n }\n for (const target of adr.supersedes) {\n const other = adrs.get(target);\n if (other && !other.supersededBy.includes(name)) {\n findings.push({\n path: adr.path,\n rule: 'supersession-reciprocal',\n severity: 'error',\n message: `supersedes \"${target}\" which does not declare superseded_by \"${name}\"`\n });\n }\n }\n }\n return findings;\n}\n\n/** Top-level scope/topic key of a path (`projects/{scope}` or `research/{topic}`), or\n * null for notes/root pages. Two pages \"share a scope\" iff their keys are equal. */\nfunction locationKey(relPath: string): string | null {\n const seg = relPath.split('/');\n if ((seg[0] === 'projects' || seg[0] === 'research') && seg[1]) {\n return `${seg[0]}/${seg[1]}`;\n }\n return null;\n}\n\nexport interface LinkPage {\n path: string;\n body: string;\n}\n\n/**\n * Cross-page ambiguity warning. A **bare** `[[wikilink]]` whose basename is owned by\n * more than one file is ambiguous only when none of those owners shares the linking\n * page's scope: a same-scope copy resolves it locally (the per-scope `spec-context`/\n * `primer`/`index` pattern), and a path-qualified link (`[[a/b/c]]`) is already\n * disambiguated. Warning, not error \u2014 the link resolves, just not uniquely.\n */\nexport function validateAmbiguousLinks(\n pages: LinkPage[],\n basenameToPaths: ReadonlyMap<string, string[]>\n): Finding[] {\n const findings: Finding[] = [];\n for (const { path, body } of pages) {\n const here = locationKey(path);\n for (const link of extractWikilinks(stripCode(body))) {\n if (!link.target.endsWith('.md') || link.target.includes('/')) continue;\n const base = basename(link.target);\n const owners = basenameToPaths.get(base);\n if (!owners || owners.length < 2) continue;\n if (here !== null && owners.some((p) => locationKey(p) === here)) continue;\n findings.push({\n path,\n rule: 'ambiguous-link',\n severity: 'warning',\n message: `bare link \"[[${base}]]\" is ambiguous \u2014 basename owned by ${owners.length} files, none in this scope`\n });\n }\n }\n return findings;\n}\n\n/**\n * Walk the vault's content domains (reusing the sync walker), build the basename\n * index of valid reference targets (all on-disk pages, including title-less ones),\n * then aggregate findings across all pages. No database \u2014 validation is a\n * pre-sync, read-only pass over the filesystem.\n */\nexport async function validateVault(root: string): Promise<Finding[]> {\n const cfg = await loadVaultConfig(root);\n\n // Reference target universe = every on-disk page, including title-less ones and\n // pages outside the scanned domains (raw/, templates/) that are legitimate link\n // targets. Walking from '.' covers the whole vault; dotdirs (.git, .obsidian)\n // are skipped by the walker.\n const all = (await walkMarkdown(root, '.')).map((abs) => ({\n relPath: toRelativePath(root, abs),\n abs\n }));\n // basename \u2192 [paths] (the spec's reference-resolution model). `refIndex` (dangling\n // checks: does the basename exist) is its key set; the multimap also backs the\n // cross-page ambiguity warning (does a basename have more than one owner).\n const basenameToPaths = new Map<string, string[]>();\n for (const f of all) {\n const b = basename(f.relPath);\n const owners = basenameToPaths.get(b);\n if (owners) owners.push(f.relPath);\n else basenameToPaths.set(b, [f.relPath]);\n }\n const refIndex = new Set<string>(basenameToPaths.keys());\n\n // Applicability = only the indexed content domains.\n const files = all.filter((f) => SCAN_DOMAINS.some((d) => f.relPath.startsWith(`${d}/`)));\n\n const findings: Finding[] = [];\n const pages: PageData[] = [];\n const linkPages: LinkPage[] = [];\n for (const { relPath, abs } of files) {\n const raw = await readFile(abs, 'utf8');\n findings.push(...validatePage(relPath, raw, cfg, refIndex));\n try {\n const parsed = parseFrontmatter(raw);\n pages.push({ path: relPath, data: parsed.data });\n linkPages.push({ path: relPath, body: parsed.content });\n } catch {\n // Parse failure already reported by validatePage; skip in the graph pass.\n }\n }\n findings.push(...validateSupersession(pages));\n findings.push(...validateAmbiguousLinks(linkPages, basenameToPaths));\n\n // A declared custom kind without its template file leaves the served\n // \"use the matching template\" rule unsatisfiable \u2014 warn, don't block.\n for (const name of customKindNames(cfg)) {\n const file = `templates/${name}.md`;\n try {\n await stat(join(root, file));\n } catch {\n findings.push({\n path: file,\n rule: 'custom-kind-template',\n severity: 'warning',\n message: `custom kind \"${name}\" declared in vault.yaml has no template file`\n });\n }\n }\n return findings;\n}\n", "import { existsSync, readdirSync, rmSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { parseArgs } from 'node:util';\nimport {\n canonicalVaultRoot,\n getMeta,\n indexRootDir,\n openDatabase,\n resolveIndexPath\n} from '@llm-wiki/db/database';\nimport { runSync } from './sync.js';\nimport { type Finding, hasErrors, validateVault } from './validate.js';\n\nexport type Command = 'sync' | 'validate';\n\nexport type CliResolution = { kind: 'run'; command: Command } | { kind: 'error'; message: string };\n\n/**\n * Resolve a `wiki <command>` invocation to the command to run, or a usage\n * error. Pure \u2014 no side effects \u2014 so the routing is testable without executing\n * the (index-touching) command. `argv` is `process.argv.slice(2)`.\n */\nexport function resolveCli(argv: string[]): CliResolution {\n const { positionals } = parseArgs({ args: argv, allowPositionals: true, strict: false });\n const command = positionals[0];\n if (command === 'sync') {\n return { kind: 'run', command: 'sync' };\n }\n if (command === 'validate') {\n return { kind: 'run', command: 'validate' };\n }\n if (command === undefined) {\n return { kind: 'error', message: 'usage: wiki <sync|validate>' };\n }\n return { kind: 'error', message: `unknown command: ${command}` };\n}\n\nexport function vaultRoot(): string {\n const root = process.env.WIKI_VAULT;\n if (!root) {\n console.error('WIKI_VAULT is not set');\n process.exit(1);\n }\n return root;\n}\n\nfunction reportFindings(findings: Finding[]): void {\n for (const f of findings) {\n console.error(`${f.severity}: ${f.path} [${f.rule}] ${f.message}`);\n }\n}\n\nexport async function runValidate(): Promise<void> {\n const findings = await validateVault(vaultRoot());\n reportFindings(findings);\n console.log(`validate: ${findings.length} finding(s)`);\n process.exit(hasErrors(findings) ? 1 : 0);\n}\n\nexport async function runSyncCommand(): Promise<void> {\n const findings = await validateVault(vaultRoot());\n reportFindings(findings);\n if (hasErrors(findings)) {\n const errors = findings.filter((f) => f.severity === 'error').length;\n console.error(`sync aborted: ${errors} validation error(s); no database writes`);\n process.exit(1);\n }\n await runSync();\n}\n\ninterface VaultDescription {\n vault: string;\n index: string;\n synced: string;\n}\n\n// Read-only: never creates the index file or its directory \u2014 `config` must\n// not leave state behind for vaults that were merely asked about.\nfunction describeVault(root: string): VaultDescription {\n const vault = canonicalVaultRoot(root);\n const index = resolveIndexPath(vault);\n let synced = 'never';\n if (existsSync(index)) {\n const db = openDatabase(index);\n try {\n synced = getMeta(db, 'last_synced') ?? 'never';\n } finally {\n db.close();\n }\n }\n return { vault, index, synced };\n}\n\nfunction printVault(d: VaultDescription): void {\n console.log(`vault: ${d.vault}`);\n console.log(`index: ${d.index}`);\n console.log(`synced: ${d.synced}`);\n}\n\n/** Every per-vault index under `~/.kmd/db/` that records its vault root. */\nfunction knownVaults(): VaultDescription[] {\n const root = indexRootDir();\n if (!existsSync(root)) return [];\n const known: VaultDescription[] = [];\n for (const entry of readdirSync(root, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const index = join(root, entry.name, 'index.db');\n if (!existsSync(index)) continue;\n const db = openDatabase(index);\n try {\n const vault = getMeta(db, 'vault_root');\n if (vault === null) continue;\n known.push({ vault, index, synced: getMeta(db, 'last_synced') ?? 'never' });\n } finally {\n db.close();\n }\n }\n return known;\n}\n\nexport async function runConfig(): Promise<void> {\n const root = process.env.WIKI_VAULT;\n if (root) {\n printVault(describeVault(root));\n return;\n }\n const known = knownVaults();\n if (known.length === 0) {\n console.error(\n 'no vault specified and none known \u2014 pass a vault root, set WIKI_VAULT, or run `kmd sync <vault-root>` once'\n );\n process.exit(1);\n }\n known.forEach((d, i) => {\n if (i > 0) console.log('');\n printVault(d);\n });\n}\n\nexport async function runDbReset(): Promise<void> {\n const root = process.env.WIKI_VAULT;\n if (!root) {\n console.error('usage: kmd db reset [<vault-root>] (or set WIKI_VAULT)');\n process.exit(2);\n }\n const dir = dirname(resolveIndexPath(root));\n if (!existsSync(dir)) {\n console.log(`${dir} does not exist \u2014 nothing to reset`);\n return;\n }\n rmSync(dir, { recursive: true, force: true });\n console.log(`deleted ${dir}`);\n}\n\nexport async function main(): Promise<void> {\n const resolution = resolveCli(process.argv.slice(2));\n if (resolution.kind === 'error') {\n console.error(resolution.message);\n process.exit(1);\n }\n if (resolution.command === 'sync') {\n await runSyncCommand();\n } else {\n await runValidate();\n }\n}\n", "import { z } from 'zod';\n\nconst EnvSchema = z.object({\n WIKI_VAULT: z.string().min(1).describe('Absolute path to the Obsidian vault root'),\n LOG_LEVEL: z\n .enum(['trace', 'debug', 'info', 'warn', 'error', 'fatal', 'silent'])\n .default('info')\n .describe('Pino log level. Logs go to stderr to keep the stdio JSON-RPC stream clean.'),\n SERVER_NAME: z.string().default('wiki-mcp'),\n SERVER_VERSION: z.string().default('0.0.0')\n});\n\nexport interface Config {\n readonly wikiVault: string;\n readonly logLevel: z.infer<typeof EnvSchema>['LOG_LEVEL'];\n readonly serverName: string;\n readonly serverVersion: string;\n}\n\nexport function loadConfig(env: NodeJS.ProcessEnv = process.env): Config {\n const parsed = EnvSchema.safeParse(env);\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` - ${i.path.join('.') || '(root)'}: ${i.message}`)\n .join('\\n');\n throw new Error(`Invalid environment configuration:\\n${issues}`);\n }\n return {\n wikiVault: parsed.data.WIKI_VAULT,\n logLevel: parsed.data.LOG_LEVEL,\n serverName: parsed.data.SERVER_NAME,\n serverVersion: parsed.data.SERVER_VERSION\n };\n}\n", "import { mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { DatabaseSync } from 'node:sqlite';\nimport { canonicalVaultRoot, openDatabase, resolveIndexPath, setMeta } from '@llm-wiki/db/database';\n\n/**\n * Open the per-vault index for this server's vault root, recording the root\n * in the index meta so `kmd config` can discover it from any shell \u2014 even for\n * a vault that has never been synced.\n */\nexport function createDatabase(vaultRoot: string): DatabaseSync {\n const dbPath = resolveIndexPath(vaultRoot);\n mkdirSync(dirname(dbPath), { recursive: true });\n const db = openDatabase(dbPath);\n setMeta(db, 'vault_root', canonicalVaultRoot(vaultRoot));\n return db;\n}\n", "import { appendFileSync, mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nconst DIAG_DIR = join(homedir(), '.local', 'state', 'wiki-mcp');\nexport const DIAG_LOG_PATH = join(DIAG_DIR, 'server.log');\n\ntry {\n mkdirSync(DIAG_DIR, { recursive: true });\n} catch {\n // best-effort; do not block startup on log dir creation\n}\n\n/**\n * Synchronous file logger that survives even when pino, the MCP SDK, or any\n * import down the chain fails to load. Writes to ~/.local/state/wiki-mcp/server.log\n * regardless of stdio/stderr capture by the parent process. Use to trace\n * spawn-time failures that never reach pino.\n */\nexport function diag(msg: string, data?: Record<string, unknown>): void {\n try {\n const line = data\n ? `${new Date().toISOString()} pid=${process.pid} ${msg} ${JSON.stringify(data)}\\n`\n : `${new Date().toISOString()} pid=${process.pid} ${msg}\\n`;\n appendFileSync(DIAG_LOG_PATH, line);\n } catch {\n // best-effort; never crash the server on log write failure\n }\n}\n", "import pino from 'pino';\nimport { DIAG_LOG_PATH } from './diag.js';\n\n/**\n * Pino logger that fans out to BOTH stderr (fd 2, captured by Claude Code)\n * AND ~/.local/state/wiki-mcp/server.log (so logs survive when stderr capture\n * doesn't make it into the JSONL connection log). The file destination shares\n * the path with diag.ts so a single `tail -f` follows the entire startup +\n * runtime stream.\n */\nexport function createLogger(level: string, name: string): pino.Logger {\n const streams: pino.StreamEntry[] = [\n { level: level as pino.Level, stream: pino.destination(2) },\n {\n level: level as pino.Level,\n stream: pino.destination({ dest: DIAG_LOG_PATH, sync: false, mkdir: true })\n }\n ];\n return pino({ name, level, base: { pid: process.pid } }, pino.multistream(streams));\n}\n\nexport type Logger = pino.Logger;\n", "import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parse } from 'yaml';\nimport { z } from 'zod';\n\n// Verbatim mirror of @llm-wiki/cli's src/config.ts \u2014 the single definition of a\n// valid vault.yaml. Kept byte-identical (schema + error strings) so mcp and\n// sync/validate never disagree on what is valid. Collapse both into a shared\n// package only when a third separate consumer appears (CLAUDE.md YAGNI rule).\n\nconst ScopeSchema = z.object({\n repo: z.string().optional(),\n methodology: z.string().optional(),\n status: z.string()\n});\n\nconst KindEntrySchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n signal: z.string(),\n where: z.string()\n })\n]);\n\nconst VaultConfigSchema = z\n .object({\n scopes: z.record(z.string(), ScopeSchema),\n kinds: z.array(KindEntrySchema),\n statuses: z.array(z.string()),\n methodologies: z.array(z.string()),\n tags: z.object({\n canonical: z.array(z.string()),\n aliases: z.record(z.string(), z.string())\n }),\n authoring_rules: z.string().optional(),\n authoring_rules_extra: z.string().optional(),\n sync_protocol: z.string().optional(),\n sync_protocol_extra: z.string().optional()\n })\n .superRefine((config, ctx) => {\n for (const [name, scope] of Object.entries(config.scopes)) {\n if (scope.methodology !== undefined && !config.methodologies.includes(scope.methodology)) {\n ctx.addIssue({\n code: 'custom',\n path: ['scopes', name, 'methodology'],\n message: `\"${scope.methodology}\" is not in the methodologies list`\n });\n }\n }\n });\n\nexport type KindEntry = z.infer<typeof KindEntrySchema>;\nexport type VaultConfig = z.infer<typeof VaultConfigSchema>;\n\n/** Kind name of a `kinds` entry \u2014 plain string, or the object form's `name`. */\nexport function kindName(entry: KindEntry): string {\n return typeof entry === 'string' ? entry : entry.name;\n}\n\n/**\n * Kinds with built-in engine pedagogy (kind-selector rows; most also carry a\n * served template). An object-form entry with one of these names rewords its\n * selector row only \u2014 it never creates custom-template expectations.\n */\nexport const BUILT_IN_KINDS: ReadonlySet<string> = new Set([\n 'project',\n 'spec',\n 'adr',\n 'plan',\n 'story',\n 'ops',\n 'topic',\n 'article',\n 'src',\n 'note',\n 'artifact',\n 'prompt'\n]);\n\n/**\n * Load and validate `$vaultRoot/vault.yaml` \u2014 the single source of truth for\n * the controlled vocabulary. Throws (fail-loud) when the file is missing or\n * the contents don't satisfy the schema; the server must not start on partial\n * vocabulary.\n */\nexport async function loadVaultConfig(vaultRoot: string): Promise<VaultConfig> {\n const path = join(vaultRoot, 'vault.yaml');\n let raw: string;\n try {\n raw = await readFile(path, 'utf8');\n } catch (err) {\n throw new Error(`vault.yaml not found at ${path}`, { cause: err });\n }\n const parsed = VaultConfigSchema.safeParse(parse(raw));\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` - ${i.path.join('.') || '(root)'}: ${i.message}`)\n .join('\\n');\n throw new Error(`Invalid vault.yaml at ${path}:\\n${issues}`);\n }\n return parsed.data;\n}\n", "import { canonicalVaultRoot } from '@llm-wiki/db/database';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { type KindEntry, kindName, type VaultConfig } from '../vault-config.js';\n\ninterface KindPedagogy {\n readonly signal: string;\n readonly where: string;\n}\n\nconst KIND_PEDAGOGY: ReadonlyMap<string, KindPedagogy> = new Map([\n [\n 'project',\n {\n signal: 'Identity card for a project scope',\n where: '`projects/{scope}/index.md`'\n }\n ],\n [\n 'spec',\n {\n signal: 'How a system works (state of world, not decision)',\n where: '`projects/{scope}/spec/spec-{slug}.md`'\n }\n ],\n [\n 'adr',\n {\n signal: 'Decision between alternatives, commits direction',\n where: '`projects/{scope}/adr/adr-{slug}.md`'\n }\n ],\n [\n 'plan',\n {\n signal: 'Phase/initiative with milestones and stories',\n where: '`projects/{scope}/plan/plan-{slug}.md`'\n }\n ],\n [\n 'story',\n {\n signal: 'User story with Gherkin + slices (child of plan)',\n where: '`projects/{scope}/plan/{plan}/story-N-{slug}.md`'\n }\n ],\n [\n 'ops',\n {\n signal: 'Operational runbook, how to run/deploy',\n where: '`projects/{scope}/ops/ops-{slug}.md`'\n }\n ],\n [\n 'topic',\n {\n signal: 'Identity card for a research area',\n where: '`research/{topic}/index.md`'\n }\n ],\n [\n 'article',\n {\n signal: 'Original synthesis about a concept/entity',\n where: '`research/{topic}/{slug}.md`'\n }\n ],\n [\n 'src',\n {\n signal: 'Summary of external source with citation',\n where: '`research/{topic}/src-{slug}.md`'\n }\n ],\n ['note', { signal: 'Low-ceremony capture, sort later', where: '`notes/{slug}.md`' }],\n [\n 'artifact',\n {\n signal: 'Deployable configuration (scope-specific, versioned)',\n where: '`projects/{scope}/ops/{deployment}/{slug}.md`'\n }\n ],\n [\n 'prompt',\n {\n signal: 'LLM prompt template (scope-specific, versioned)',\n where: '`projects/{scope}/ops/{deployment}/prompts/{role}/{slug}.md`'\n }\n ]\n]);\n\nconst DEFAULT_AUTHORING_RULES = [\n '**Where things go**',\n '',\n \"- **Use the matching template** via `wiki://template/{domain}/{kind}` (MCP) or from `templates/` (filesystem). Don't hand-roll frontmatter.\",\n '- **Folder name = slug prefix in `projects/`.** `spec/spec-x.md`, `adr/adr-y.md`, `plan/plan-z.md`, `ops/ops-w.md`. Stories use `story-` prefix under `plan/{plan-name}/`.',\n '- **Research is flat.** Articles are `{subject}.md`; sources are `src-{slug}.md`. The topic folder names a *frame*, the article slug names a *subject*. Avoid generic slugs (`architecture.md`, `notes.md`) and slugs that collide with project scopes.',\n '- **Extend before you split.** Prefer sharpening the existing spec, ADR, or article over creating a near-duplicate page. A new page needs a new subject, not a new session.',\n '',\n '**Frontmatter**',\n '',\n '- **`summary` is the retrieval contract.** One sentence stating the page\\'s decision or claim, not its topic. Search and `prime` rank by it \u2014 \"Chose X over Y because Z\" surfaces; \"About the sync pipeline\" sinks.',\n '- **Quote prose-bearing scalars.** `summary: \"...\"` \u2014 unquoted `Word: phrase` patterns break the YAML parser.',\n '- **On any edit, update `updated`.** Never change `created` \u2014 it is write-once.',\n '- **Notes have no `kind` field** \u2014 implied by location. Sync sets `kind: note`.',\n '- **Reuse existing tags** (visible in `prime` response `top_tags`). No synonyms.',\n '',\n '**Content**',\n '',\n '- **ADR and ops pages are predicate-only.** No definitional preambles for established vocabulary, no narrative, no marketing. The audience is the project team \u2014 assume fluency.',\n \"- **Spec / ADR edits land inline with the change that surfaces them.** Don't queue corrections in plans \u2014 the spec reflects current code at every commit.\",\n '',\n '**Linking**',\n '',\n \"- **Cross-reference with `[[wikilinks]]`, and link every mention of another vault page** \u2014 backlinks are the navigation graph for humans and agents alike. Don't link pages that don't exist yet: dangling links fail validation.\",\n '- **ADR supersession is bidirectional**: `superseded_by` on the old ADR + `supersedes` on the new one.',\n \"- **Sources convention**: external paths/URLs go inline in body text. Vault-internal `raw/` paths go in frontmatter `sources:` array. Don't mix the two surfaces.\"\n].join('\\n');\n\nfunction buildAuthoringRules(config: VaultConfig): string {\n const parts = [(config.authoring_rules ?? DEFAULT_AUTHORING_RULES).trim()];\n if (config.authoring_rules_extra) parts.push(config.authoring_rules_extra.trim());\n return ['## Authoring rules', '', parts.join('\\n\\n')].join('\\n');\n}\n\nconst DEFAULT_SYNC_PROTOCOL = [\n 'Edit the smallest set of files that reflects the change. ' +\n \"A milestone tick is plan-only; don't cascade to index.md unless phase or status changed. \" +\n 'Controlled-vocabulary edits (`vault.yaml`) need explicit user approval.',\n 'After editing wiki pages, run `kmd validate` and fix findings before `kmd sync` \u2014 ' +\n 'it checks frontmatter shape, vocabulary membership, and link integrity.'\n].join('\\n');\n\nfunction buildSyncProtocol(config: VaultConfig): string {\n const parts = [(config.sync_protocol ?? DEFAULT_SYNC_PROTOCOL).trim()];\n if (config.sync_protocol_extra) parts.push(config.sync_protocol_extra.trim());\n return ['## Resync protocol', '', parts.join('\\n\\n')].join('\\n');\n}\n\nfunction buildKindSelector(kinds: ReadonlyArray<KindEntry>): string {\n const lines: string[] = ['## Kind selector', '', '| Signal | Kind | Where |', '|---|---|---|'];\n for (const entry of kinds) {\n const name = kindName(entry);\n const pedagogy = typeof entry === 'string' ? KIND_PEDAGOGY.get(entry) : entry;\n const signal = pedagogy?.signal ?? '\u2014';\n const where = pedagogy?.where ?? '\u2014';\n lines.push(`| ${signal} | **${name}** | ${where} |`);\n }\n const names = kinds.map(kindName);\n const hasNote = names.includes('note');\n const hasAdrAndSpec = names.includes('adr') && names.includes('spec');\n if (hasNote || hasAdrAndSpec) {\n const hints: string[] = [];\n if (hasNote) hints.push('If none fits \u2192 note.');\n if (hasAdrAndSpec) {\n hints.push(\n 'If torn between adr and spec \u2192 does it record a choice? adr. Does it describe how things work? spec.'\n );\n }\n lines.push('', hints.join(' '));\n }\n return lines.join('\\n');\n}\n\n// The arrow-and-annotation rendering asserts the default lifecycle; a custom\n// status list gets a plain enumeration rather than an invented ordering.\nconst CANONICAL_STATUS_FLOW = ['draft', 'active', 'superseded', 'archived'] as const;\n\nfunction buildStatusLine(statuses: ReadonlyArray<string>): string {\n const isCanonical =\n statuses.length === CANONICAL_STATUS_FLOW.length &&\n statuses.every((s, i) => s === CANONICAL_STATUS_FLOW[i]);\n return isCanonical\n ? `**Statuses:** ${statuses.join(' \u2192 ')} (one-directional; superseded requires superseded_by link)`\n : `**Statuses:** ${statuses.join(', ')}`;\n}\n\nfunction buildVocabulary(config: VaultConfig): string {\n const lines: string[] = [\n '## Controlled vocabulary',\n '',\n `**Kinds:** ${config.kinds.map(kindName).join(', ')}`,\n buildStatusLine(config.statuses),\n `**Methodologies:** ${config.methodologies.join(', ')}`,\n `**Canonical tags:** ${config.tags.canonical.join(', ')}`\n ];\n const aliases = Object.entries(config.tags.aliases);\n if (aliases.length > 0) {\n lines.push(`**Tag aliases:** ${aliases.map(([a, c]) => `${a} \u2192 ${c}`).join(', ')}`);\n }\n return lines.join('\\n');\n}\n\nexport function registerAuthoringResource(\n mcp: McpServer,\n vaultRoot: string,\n vaultConfig: VaultConfig\n): void {\n mcp.registerResource(\n 'Authoring guide',\n 'wiki://authoring',\n {\n description:\n 'Wiki authoring pedagogy: kind selector, controlled vocabulary, authoring rules, resync protocol, and template URIs. Read before creating or editing wiki pages.',\n mimeType: 'text/markdown'\n },\n async (uri) => {\n const sections = [\n '# Wiki authoring guide',\n '',\n `Vault root: \\`${canonicalVaultRoot(vaultRoot)}\\` \u2014 every page path below is relative to it; write files and run \\`kmd validate\\` / \\`kmd sync\\` against it.`,\n '',\n buildKindSelector(vaultConfig.kinds),\n '',\n buildVocabulary(vaultConfig),\n '',\n '## Templates',\n '',\n 'Full index with URIs and descriptions: `wiki://templates`',\n '',\n buildAuthoringRules(vaultConfig),\n '',\n buildSyncProtocol(vaultConfig)\n ];\n return {\n contents: [\n {\n uri: uri.toString(),\n mimeType: 'text/markdown' as const,\n text: sections.join('\\n')\n }\n ]\n };\n }\n );\n}\n", "import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { BUILT_IN_KINDS, type VaultConfig } from '../vault-config.js';\n\ninterface TemplateSpec {\n /** wiki://template/{domain}/{kind} \u2014 `note` collapses to single segment. */\n readonly uri: string;\n /** Human-readable name shown in resources/list. */\n readonly name: string;\n /** Filename in vault/templates/. */\n readonly file: string;\n /** Description shown in resources/list. */\n readonly description: string;\n}\n\n/**\n * The vault has 11 fixed templates, mirroring the v2 frontmatter schemas\n * (extended with `story` per adr-story-vocabulary-and-triage-fields).\n * URI scheme: `wiki://template/{domain}/{kind}` \u2014 the agent thinks\n * \"I'm authoring a {kind} in the {domain} domain\" and the URI matches\n * that mental model. `note` collapses to a single segment because the\n * notes domain has only one kind.\n */\nexport const TEMPLATES: ReadonlyArray<TemplateSpec> = [\n {\n uri: 'wiki://template/project/index',\n name: 'Project index',\n file: 'project-index.md',\n description:\n 'Identity card for a project. Frontmatter-heavy: methodology, phase, repo, scope, summary, tags. Short body.'\n },\n {\n uri: 'wiki://template/project/primer',\n name: 'Project primer',\n file: 'project-primer.md',\n description:\n 'Human-authored narrative context for a project. Free-form body. Inlined into the prime tool response.'\n },\n {\n uri: 'wiki://template/project/spec',\n name: 'Project spec',\n file: 'project-spec.md',\n description:\n 'Specification page \u2014 how a system or feature works (state of the world, not decision).'\n },\n {\n uri: 'wiki://template/project/adr',\n name: 'Project ADR',\n file: 'project-adr.md',\n description:\n 'Architecture Decision Record \u2014 pinned moment of choice. Sections: Status, Context, Decision, Rationale, Consequences.'\n },\n {\n uri: 'wiki://template/project/plan',\n name: 'Project plan',\n file: 'project-plan.md',\n description:\n 'Plan for a phase or initiative. Sections: Goal, Scope, Milestones, Dependencies, Status Log.'\n },\n {\n uri: 'wiki://template/project/ops',\n name: 'Project ops',\n file: 'project-ops.md',\n description: 'Operational runbook \u2014 how to run or operate a system. Procedural.'\n },\n {\n uri: 'wiki://template/project/story',\n name: 'Project story',\n file: 'project-story.md',\n description:\n 'User story with Gherkin scenarios and inline implementation slices. Lives at plan/{plan-name}/story-N-{slug}.md. Frontmatter carries triage_state, category, blocked_by, parent.'\n },\n {\n uri: 'wiki://template/research/index',\n name: 'Research index',\n file: 'research-index.md',\n description:\n 'Topic identity card for a research area. Frontmatter: confidence, source_count, summary, tags.'\n },\n {\n uri: 'wiki://template/research/article',\n name: 'Research article',\n file: 'research-article.md',\n description:\n 'Wikipedia-style article about a concept, entity, or system. Original synthesis with sources.'\n },\n {\n uri: 'wiki://template/research/src',\n name: 'Research source',\n file: 'research-src.md',\n description:\n 'Summary of an external source (paper, talk, doc) with citation. The only `src-` prefix in research.'\n },\n {\n uri: 'wiki://template/note',\n name: 'Note',\n file: 'note.md',\n description: 'Low-ceremony everyday note. Capture fast, sort later.'\n }\n];\n\n/**\n * Registry entries for custom kinds \u2014 object-form `kinds` entries outside the\n * built-in set. Single-segment URI (the `note` precedent: no domain to encode),\n * file by convention at `templates/{name}.md`, the kind's `signal` doubles as\n * the description.\n */\nfunction customTemplates(config: VaultConfig): TemplateSpec[] {\n const specs: TemplateSpec[] = [];\n for (const entry of config.kinds) {\n if (typeof entry === 'string' || BUILT_IN_KINDS.has(entry.name)) continue;\n specs.push({\n uri: `wiki://template/${entry.name}`,\n name: entry.name.charAt(0).toUpperCase() + entry.name.slice(1),\n file: `${entry.name}.md`,\n description: entry.signal\n });\n }\n return specs;\n}\n\n/**\n * Register all template resources with the MCP server. Each template is a\n * fixed URI; `resources/read` re-reads the file on every call, so edits to\n * vault/templates/*.md are picked up without restarting the server.\n */\nexport function registerTemplateResources(\n mcp: McpServer,\n vaultRoot: string,\n vaultConfig: VaultConfig\n): void {\n const dir = join(vaultRoot, 'templates');\n const templates = [...TEMPLATES, ...customTemplates(vaultConfig)];\n for (const tmpl of templates) {\n mcp.registerResource(\n tmpl.name,\n tmpl.uri,\n { description: tmpl.description, mimeType: 'text/markdown' },\n async (uri) => {\n let text: string;\n try {\n text = await readFile(join(dir, tmpl.file), 'utf8');\n } catch (err) {\n throw new Error(`template file missing: templates/${tmpl.file} (${tmpl.uri})`, {\n cause: err\n });\n }\n return {\n contents: [\n {\n uri: uri.toString(),\n mimeType: 'text/markdown' as const,\n text\n }\n ]\n };\n }\n );\n }\n\n const indexLines = ['# Wiki Templates', ''];\n for (const tmpl of templates) {\n indexLines.push(`- **${tmpl.name}** \u2014 \\`${tmpl.uri}\\` `);\n indexLines.push(` ${tmpl.description}`);\n }\n const indexText = indexLines.join('\\n');\n\n mcp.registerResource(\n 'Template index',\n 'wiki://templates',\n {\n description:\n 'Index of all wiki templates with URIs and descriptions. Read a specific template via its URI.',\n mimeType: 'text/markdown'\n },\n async (uri) => ({\n contents: [{ uri: uri.toString(), mimeType: 'text/markdown' as const, text: indexText }]\n })\n );\n}\n", "import { parse as parseYaml } from 'yaml';\n\n// Verbatim mirror of @llm-wiki/cli's src/frontmatter.ts. Kept byte-identical so\n// mcp parses frontmatter the same way sync/validate do. Collapse into a shared\n// package only when a third separate consumer appears (CLAUDE.md YAGNI rule).\n\nexport interface ParsedFrontmatter {\n data: Record<string, unknown>;\n content: string;\n}\n\n// Leading `---` block, YAML, closing `---`, then one consumed newline. Matches\n// gray-matter's delimiter handling; the closing `---` must be on its own line so\n// `---` rules inside the body are left intact.\nconst FRONTMATTER_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n?---\\r?\\n?/;\n\n/**\n * Split a page's frontmatter from its body using the `yaml` parser. Throws\n * (deterministically, no cache) when the frontmatter is not valid YAML. A page\n * with no leading delimiter parses to empty data and the whole input as body.\n */\nexport function parseFrontmatter(raw: string): ParsedFrontmatter {\n const match = FRONTMATTER_RE.exec(raw);\n if (!match) {\n return { data: {}, content: raw };\n }\n const yamlText = match[1] ?? '';\n const content = raw.slice(match[0].length);\n if (yamlText.trim() === '') {\n return { data: {}, content };\n }\n const parsed = parseYaml(yamlText);\n const data =\n parsed !== null && typeof parsed === 'object' ? (parsed as Record<string, unknown>) : {};\n return { data, content };\n}\n", "const FTS5_KEYWORDS = new Set(['AND', 'OR', 'NOT', 'NEAR']);\n\nexport function sanitizeFtsQuery(raw: string): string {\n return raw\n .replace(/[^\\p{L}\\p{N}\\s]/gu, ' ')\n .split(/\\s+/)\n .filter((t) => t.length > 0 && !FTS5_KEYWORDS.has(t))\n .join(' ');\n}\n", "/**\n * MCP CallToolResult helpers. `content[0].text` carries pretty-printed JSON\n * for LLM-facing clients; `structuredContent` carries the same payload as\n * raw JSON for clients that parse directly. Both fields kept in sync so\n * callers never choose one over the other.\n */\n\nexport function textJson(data: object) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }],\n structuredContent: data as Record<string, unknown>\n };\n}\n\n/**\n * Variant for tools whose model-facing surface is denser as markdown than as\n * pretty-printed JSON (~20% token savings on prose-heavy payloads). The\n * markdown goes to `content[0].text`; `structuredContent` keeps the machine\n * fields so a non-LLM client still gets a parseable shape.\n */\nexport function textWithStruct(markdown: string, data: object) {\n return {\n content: [{ type: 'text' as const, text: markdown }],\n structuredContent: data as Record<string, unknown>\n };\n}\n\nexport interface ToolErrorPayload {\n readonly code: string;\n readonly message: string;\n readonly details?: Record<string, unknown>;\n}\n\nexport function textError(error: ToolErrorPayload) {\n const payload = {\n code: error.code,\n message: error.message,\n details: error.details ?? {}\n };\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: JSON.stringify(payload) }],\n structuredContent: payload as Record<string, unknown>\n };\n}\n", "import { readFile } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\nimport type { DatabaseSync } from 'node:sqlite';\nimport { canonicalVaultRoot } from '@llm-wiki/db/database';\nimport { z } from 'zod';\nimport { parseFrontmatter } from '../frontmatter.js';\nimport { sanitizeFtsQuery } from '../lib/fts.js';\nimport { textError, textWithStruct } from '../lib/toolResponse.js';\nimport { kindName, type VaultConfig } from '../vault-config.js';\n\nexport const PrimeInputSchema = z.object({\n scope: z\n .string()\n .min(1)\n .describe('Project scope to prime (matches projects/{scope}/ in the vault).'),\n task: z\n .string()\n .optional()\n .describe('Optional task description; surfaces top-3 tsvector-ranked relevant pages.')\n});\n\nexport type PrimeInput = z.infer<typeof PrimeInputSchema>;\n\ninterface ProjectIndexFm {\n title?: string;\n methodology?: string;\n phase?: number;\n summary?: string;\n}\n\nexport interface PrimeData {\n scope: string;\n vault_root: string;\n title: string | null;\n methodology: string | null;\n phase: number | null;\n summary: string;\n primer: string;\n counts: Record<string, number>;\n active_adrs: Array<{ path: string; slug: string; title: string; summary: string | null }>;\n current_plan: { path: string; slug: string; title: string } | null;\n top_tags: string[];\n hub_pages: Array<{ path: string; title: string; inbound: number }>;\n recent: Array<{ path: string; operation: string; date: string }>;\n relevant: Array<{ path: string; title: string; score: number }>;\n cross_scope: Array<{ from_scope: string; from_path: string; to_path: string }>;\n}\n\nexport interface PrimeDeps {\n readonly db: DatabaseSync;\n readonly vaultRoot: string;\n readonly vaultConfig: VaultConfig;\n}\n\nfunction pathSlug(p: string): string {\n return basename(p).replace(/\\.md$/, '');\n}\n\nasync function readIndexFm(vaultRoot: string, scope: string): Promise<ProjectIndexFm> {\n try {\n const raw = await readFile(join(vaultRoot, 'projects', scope, 'index.md'), 'utf8');\n return parseFrontmatter(raw).data as ProjectIndexFm;\n } catch {\n return {};\n }\n}\n\nasync function readPrimer(vaultRoot: string, scope: string): Promise<string> {\n try {\n const raw = await readFile(join(vaultRoot, 'projects', scope, 'primer.md'), 'utf8');\n return parseFrontmatter(raw)\n .content.trim()\n .replace(/^#\\s+[^\\n]+\\n+/, '');\n } catch {\n return '';\n }\n}\n\nexport async function prime(\n deps: PrimeDeps,\n input: PrimeInput\n): Promise<{ markdown: string; data: PrimeData }> {\n const { db, vaultRoot, vaultConfig } = deps;\n const { scope, task } = input;\n\n const [fm, primer] = await Promise.all([\n readIndexFm(vaultRoot, scope),\n readPrimer(vaultRoot, scope)\n ]);\n\n const counts = db\n .prepare('SELECT kind, count(*) AS count FROM pages WHERE scope = ? GROUP BY kind')\n .all(scope) as Array<{ kind: string; count: number | bigint }>;\n\n const adrs = db\n .prepare(\n \"SELECT path, title, summary FROM pages WHERE scope = ? AND kind = 'adr' AND status = 'active' ORDER BY updated DESC\"\n )\n .all(scope) as Array<{ path: string; title: string; summary: string | null }>;\n\n const planRow = db\n .prepare(\n \"SELECT path, title FROM pages WHERE scope = ? AND kind = 'plan' AND status = 'active' ORDER BY updated DESC LIMIT 1\"\n )\n .get(scope) as { path: string; title: string } | undefined;\n\n const tags = db\n .prepare(\n `SELECT j.value AS tag, count(*) AS cnt\n FROM pages, json_each(pages.tags) AS j\n WHERE scope = ?\n GROUP BY j.value\n ORDER BY cnt DESC\n LIMIT 10`\n )\n .all(scope) as Array<{ tag: string }>;\n\n const hubs = db\n .prepare(\n `SELECT p.path, p.title, count(*) AS inbound\n FROM links l JOIN pages p ON p.path = l.target_path\n WHERE p.scope = ?\n GROUP BY p.path, p.title\n ORDER BY inbound DESC LIMIT 5`\n )\n .all(scope) as Array<{ path: string; title: string; inbound: number | bigint }>;\n\n const events = db\n .prepare('SELECT path, operation, ts FROM events WHERE scope = ? ORDER BY ts DESC LIMIT 5')\n .all(scope) as Array<{ path: string; operation: string; ts: string }>;\n\n const crossScope = db\n .prepare(\n `SELECT pf.scope AS from_scope, l.source_path AS from_path, l.target_path AS to_path\n FROM links l\n JOIN pages pt ON pt.path = l.target_path\n JOIN pages pf ON pf.path = l.source_path\n WHERE pt.scope = ? AND pf.scope IS NOT NULL AND pf.scope != ?\n LIMIT 10`\n )\n .all(scope, scope) as Array<{ from_scope: string; from_path: string; to_path: string }>;\n\n let relevant: Array<{ path: string; title: string; score: number }> = [];\n if (task) {\n const ftsQuery = sanitizeFtsQuery(task);\n if (ftsQuery) {\n relevant = (\n db\n .prepare(\n `SELECT p.path, p.title, bm25(pages_fts) AS score\n FROM pages_fts\n JOIN pages p ON p.id = pages_fts.rowid\n WHERE pages_fts MATCH ? AND p.scope = ?\n ORDER BY bm25(pages_fts) LIMIT 3`\n )\n .all(ftsQuery, scope) as Array<{ path: string; title: string; score: number }>\n ).map((row) => ({\n path: row.path,\n title: row.title,\n score: row.score\n }));\n }\n }\n\n const countsRecord: Record<string, number> = {};\n for (const row of counts) countsRecord[row.kind] = Number(row.count);\n\n const data: PrimeData = {\n scope,\n vault_root: canonicalVaultRoot(vaultRoot),\n title: fm.title ?? null,\n methodology: fm.methodology ?? null,\n phase: typeof fm.phase === 'number' ? fm.phase : null,\n summary: fm.summary ?? '',\n primer,\n counts: countsRecord,\n active_adrs: adrs.map((r) => ({\n path: r.path,\n slug: pathSlug(r.path),\n title: r.title,\n summary: r.summary\n })),\n current_plan: planRow\n ? {\n path: planRow.path,\n slug: pathSlug(planRow.path),\n title: planRow.title\n }\n : null,\n top_tags: tags.map((r) => r.tag),\n hub_pages: hubs.map((r) => ({\n path: r.path,\n title: r.title,\n inbound: Number(r.inbound)\n })),\n recent: events.map((r) => ({\n path: r.path,\n operation: r.operation,\n date: r.ts.slice(0, 10)\n })),\n relevant,\n cross_scope: crossScope.map((r) => ({\n from_scope: r.from_scope,\n from_path: r.from_path,\n to_path: r.to_path\n }))\n };\n\n return { markdown: renderMarkdown(data, vaultConfig, task), data };\n}\n\nexport function renderMarkdown(\n d: PrimeData,\n config: VaultConfig,\n task: string | undefined\n): string {\n const lines: string[] = [];\n\n const phaseLabel =\n d.phase !== null\n ? d.methodology\n ? `Phase ${d.phase} (${d.methodology})`\n : `Phase ${d.phase}`\n : '';\n const header = phaseLabel ? `${d.scope} \u2014 ${phaseLabel}` : d.scope;\n lines.push(`# ${header}`);\n if (d.summary) lines.push(d.summary);\n // Search returns vault-relative paths; this is what the agent resolves them against.\n lines.push(`Vault root: \\`${d.vault_root}\\``);\n\n if (d.primer) {\n lines.push('', '## Primer', d.primer);\n }\n\n if (d.active_adrs.length > 0) {\n lines.push('', '## Active Decisions');\n for (const a of d.active_adrs) {\n lines.push(`- ${a.slug}: ${a.summary ?? a.title}`);\n }\n }\n\n if (d.current_plan) {\n lines.push('', '## Current Plan');\n lines.push(`${d.current_plan.slug}: ${d.current_plan.title}`);\n }\n\n const countEntries = Object.entries(d.counts);\n if (countEntries.length > 0) {\n lines.push('', '## Pages');\n lines.push(countEntries.map(([k, n]) => `${k}: ${n}`).join(' | '));\n }\n\n lines.push('', '## Vocabulary');\n lines.push(`kinds: ${config.kinds.map(kindName).join(', ')}`);\n lines.push(`statuses: ${config.statuses.join(', ')}`);\n lines.push(`tags: ${config.tags.canonical.join(', ')}`);\n\n if (d.top_tags.length > 0) {\n lines.push('', '## Tags');\n lines.push(d.top_tags.join(', '));\n }\n\n if (d.hub_pages.length > 0) {\n lines.push('', '## Hubs');\n for (const h of d.hub_pages) {\n lines.push(`- ${pathSlug(h.path)} (${h.inbound} inbound)`);\n }\n }\n\n if (d.recent.length > 0) {\n lines.push('', '## Recent');\n for (const r of d.recent) {\n lines.push(`- [${r.date}] ${pathSlug(r.path)} ${r.operation}`);\n }\n }\n\n if (d.relevant.length > 0) {\n lines.push('', `## Relevant (task: \"${task}\")`);\n for (const r of d.relevant) {\n lines.push(`- ${pathSlug(r.path)} (${r.score.toFixed(2)})`);\n }\n }\n\n if (d.cross_scope.length > 0) {\n lines.push('', '## Cross-scope');\n for (const c of d.cross_scope) {\n lines.push(`- ${c.from_scope}/${pathSlug(c.from_path)} \u2192 ${pathSlug(c.to_path)}`);\n }\n }\n\n lines.push(\n '',\n '---',\n 'Authoring wiki content? Read `wiki://authoring` for kind selector, rules, and templates. After edits: `kmd validate`, then `kmd sync`.'\n );\n\n return lines.join('\\n');\n}\n\nexport async function handlePrime(deps: PrimeDeps, input: PrimeInput) {\n if (!Object.hasOwn(deps.vaultConfig.scopes, input.scope)) {\n const valid = Object.keys(deps.vaultConfig.scopes).sort().join(', ');\n return textError({\n code: 'UNKNOWN_SCOPE',\n message: `unknown scope \"${input.scope}\"; valid scopes: ${valid}`\n });\n }\n try {\n const { markdown, data } = await prime(deps, input);\n return textWithStruct(markdown, data as unknown as Record<string, unknown>);\n } catch (err) {\n return textError({\n code: 'PRIME_FAILED',\n message: err instanceof Error ? err.message : String(err)\n });\n }\n}\n", "import type { DatabaseSync } from 'node:sqlite';\nimport { z } from 'zod';\nimport { sanitizeFtsQuery } from '../lib/fts.js';\nimport { textError, textJson } from '../lib/toolResponse.js';\n\nexport const SearchInputSchema = z.object({\n query: z\n .string()\n .min(1)\n .describe(\n 'Natural-language search query. Matched against title, summary, and body via SQLite FTS5.'\n ),\n scope: z\n .string()\n .optional()\n .describe('Optional: restrict to a project scope (e.g. \"ontology\", \"sotto\").'),\n kind: z\n .string()\n .optional()\n .describe(\n 'Optional: restrict to a kind. Project kinds: spec, adr, plan, ops. Research kinds: article, src. Misc: note.'\n ),\n limit: z\n .number()\n .int()\n .min(1)\n .max(50)\n .default(5)\n .describe('Maximum number of ranked results to return. Default 5.')\n});\n\nexport type SearchInput = z.infer<typeof SearchInputSchema>;\n\nexport interface SearchResult {\n readonly path: string;\n readonly title: string;\n readonly kind: string;\n readonly summary: string | null;\n readonly score: number;\n readonly scope?: string | null;\n}\n\nexport interface SearchDeps {\n readonly db: DatabaseSync;\n}\n\nexport function search(deps: SearchDeps, input: SearchInput): { results: SearchResult[] } {\n const ftsQuery = sanitizeFtsQuery(input.query);\n if (!ftsQuery) return { results: [] };\n\n let sql = `SELECT p.path, p.title, p.kind, p.summary, p.scope, bm25(pages_fts) AS score\n FROM pages_fts\n JOIN pages p ON p.id = pages_fts.rowid\n WHERE pages_fts MATCH ?`;\n const params: Array<string | number> = [ftsQuery];\n\n if (input.scope) {\n sql += ' AND p.scope = ?';\n params.push(input.scope);\n }\n if (input.kind) {\n sql += ' AND p.kind = ?';\n params.push(input.kind);\n }\n sql += ' ORDER BY bm25(pages_fts) LIMIT ?';\n params.push(input.limit);\n\n const rows = deps.db.prepare(sql).all(...params) as Array<{\n path: string;\n title: string;\n kind: string;\n summary: string | null;\n scope: string | null;\n score: number;\n }>;\n\n return {\n results: rows.map((r) => ({\n path: r.path,\n title: r.title,\n kind: r.kind,\n summary: r.summary,\n scope: r.scope,\n score: r.score\n }))\n };\n}\n\nexport function handleSearch(deps: SearchDeps, input: SearchInput) {\n try {\n return textJson(search(deps, input));\n } catch (err) {\n return textError({\n code: 'SEARCH_FAILED',\n message: err instanceof Error ? err.message : String(err)\n });\n }\n}\n", "import type { DatabaseSync } from 'node:sqlite';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { Logger } from './lib/logger.js';\nimport { registerAuthoringResource } from './resources/authoring.js';\nimport { registerTemplateResources } from './resources/templates.js';\nimport { handlePrime, PrimeInputSchema } from './tools/prime.js';\nimport { handleSearch, SearchInputSchema } from './tools/search.js';\nimport type { VaultConfig } from './vault-config.js';\n\nexport interface BuildServerArgs {\n readonly name: string;\n readonly version: string;\n readonly vaultRoot: string;\n readonly db: DatabaseSync;\n readonly logger: Logger;\n readonly vaultConfig: VaultConfig;\n}\n\nexport function buildServer(args: BuildServerArgs): McpServer {\n const { name, version, vaultRoot, db, logger, vaultConfig } = args;\n\n const mcp = new McpServer({ name, version }, { capabilities: { tools: {}, resources: {} } });\n\n mcp.tool(\n 'prime',\n 'Orient on a project. Returns a markdown briefing with: identity (scope, phase, methodology, summary), the human-authored primer.md inlined, active ADRs, current plan, page counts, top tags, hub pages (most-linked-to), recent events, cross-scope references, and \u2014 when `task` is provided \u2014 the top 3 tsvector-ranked relevant pages. Call once at session start. Empty sections are omitted to keep the surface lean.',\n PrimeInputSchema.shape,\n async (input) => {\n logger.debug({ tool: 'prime', input }, 'tool call');\n return handlePrime({ db, vaultRoot, vaultConfig }, input);\n }\n );\n\n mcp.tool(\n 'search',\n 'Full-text search across wiki pages via SQLite FTS5. Returns ranked candidates {path, title, kind, summary, score} \u2014 never page bodies. The agent reads the returned paths directly from the filesystem.',\n SearchInputSchema.shape,\n async (input) => {\n logger.debug({ tool: 'search', input }, 'tool call');\n return handleSearch({ db }, input);\n }\n );\n\n registerTemplateResources(mcp, vaultRoot, vaultConfig);\n registerAuthoringResource(mcp, vaultRoot, vaultConfig);\n\n return mcp;\n}\n", "import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { loadConfig } from './config.js';\nimport { createDatabase } from './db.js';\nimport { diag } from './lib/diag.js';\nimport { createLogger } from './lib/logger.js';\nimport { buildServer } from './server.js';\nimport { loadVaultConfig } from './vault-config.js';\n\nexport async function startMcpServer(): Promise<void> {\n diag('main entered');\n\n const config = loadConfig();\n diag('config loaded', { vault: config.wikiVault, level: config.logLevel });\n\n const vaultConfig = await loadVaultConfig(config.wikiVault);\n diag('vault config loaded', {\n scopes: Object.keys(vaultConfig.scopes).length,\n kinds: vaultConfig.kinds.length,\n statuses: vaultConfig.statuses.length\n });\n\n const logger = createLogger(config.logLevel, config.serverName);\n logger.info(\n { vault: config.wikiVault, serverName: config.serverName, serverVersion: config.serverVersion },\n 'starting wiki-mcp on stdio'\n );\n\n const db = createDatabase(config.wikiVault);\n diag('database opened');\n\n const mcp = buildServer({\n name: config.serverName,\n version: config.serverVersion,\n vaultRoot: config.wikiVault,\n db,\n logger,\n vaultConfig\n });\n diag('server built');\n\n const shutdown = async (signal: NodeJS.Signals) => {\n logger.info({ signal }, 'shutting down');\n diag('shutting down', { signal });\n try {\n await mcp.close();\n db.close();\n } catch (err) {\n logger.error({ err }, 'error during shutdown');\n }\n process.exit(0);\n };\n process.once('SIGINT', (s) => void shutdown(s));\n process.once('SIGTERM', (s) => void shutdown(s));\n\n const transport = new StdioServerTransport();\n await mcp.connect(transport);\n logger.info('wiki-mcp ready');\n diag('ready and connected to transport');\n}\n", "#!/usr/bin/env node\nimport { parseArgs } from 'node:util';\n\nconst USAGE = `usage: kmd <command> [options]\n\ncommands:\n sync vault \u2192 index sync (runs validate first)\n validate [<path>] deterministic vault checker (default: $WIKI_VAULT)\n mcp [<vault-root>] start the stdio MCP server (default: $WIKI_VAULT)\n config [<vault-root>] print vault + index resolution; with no vault, list known vaults\n db reset [<vault-root>] delete the vault's index (default: $WIKI_VAULT)\n\noptions:\n --version print version\n --help show this help`;\n\nconst { positionals, values } = parseArgs({\n args: process.argv.slice(2),\n allowPositionals: true,\n strict: false,\n options: {\n version: { type: 'boolean', short: 'v' },\n help: { type: 'boolean', short: 'h' }\n }\n});\n\nconst command = values.version ? '--version' : values.help ? '--help' : positionals[0];\n\nfunction applyVaultRoot(positionalIndex: number): void {\n const arg = positionals[positionalIndex];\n if (arg) {\n process.env.WIKI_VAULT = arg;\n }\n}\n\nasync function run(): Promise<void> {\n switch (command) {\n case 'sync': {\n const { runSyncCommand } = await import('@llm-wiki/cli/cli');\n await runSyncCommand();\n break;\n }\n case 'validate': {\n applyVaultRoot(1);\n const { runValidate } = await import('@llm-wiki/cli/cli');\n await runValidate();\n break;\n }\n case 'mcp': {\n applyVaultRoot(1);\n const { startMcpServer } = await import('@llm-wiki/mcp/start');\n await startMcpServer();\n break;\n }\n case 'config': {\n applyVaultRoot(1);\n const { runConfig } = await import('@llm-wiki/cli/cli');\n await runConfig();\n break;\n }\n case 'db': {\n const sub = positionals[1];\n if (sub === 'reset') {\n applyVaultRoot(2);\n const { runDbReset } = await import('@llm-wiki/cli/cli');\n await runDbReset();\n } else {\n console.error(sub ? `unknown db subcommand: ${sub}` : 'usage: kmd db reset [<vault-root>]');\n process.exit(2);\n }\n break;\n }\n case '--version':\n case '-v': {\n const { readFileSync } = await import('node:fs');\n const { join, dirname } = await import('node:path');\n const { fileURLToPath } = await import('node:url');\n const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));\n const pkg = JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf8')) as {\n version: string;\n };\n console.log(pkg.version);\n break;\n }\n case '--help':\n case '-h':\n case undefined: {\n console.log(USAGE);\n if (command === undefined) process.exit(2);\n break;\n }\n default: {\n console.error(`unknown command: ${command}\\n\\n${USAGE}`);\n process.exit(2);\n }\n }\n}\n\nrun().catch((err) => {\n console.error('kmd failed:', err instanceof Error ? (err.stack ?? err.message) : err);\n process.exit(1);\n});\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAC7B,SAAS,eAAe;AACxB,SAAS,UAAU,MAAM,eAAe;AACxC,SAAS,oBAAoB;AAuDtB,SAAS,aAAa,QAA8B;AACzD,QAAM,KAAK,IAAI,aAAa,MAAM;AAClC,KAAG,KAAK,2BAA2B;AACnC,KAAG,KAAK,0BAA0B;AAClC,KAAG,KAAK,MAAM;AACd,SAAO;AACT;AAQO,SAAS,eAAuB;AACrC,QAAM,OAAO,QAAQ,IAAI,YAAY,KAAK,QAAQ,GAAG,MAAM;AAC3D,SAAO,KAAK,MAAM,IAAI;AACxB;AAOO,SAAS,mBAAmBA,YAA2B;AAC5D,MAAI;AACF,WAAO,aAAaA,UAAS;AAAA,EAC/B,QAAQ;AACN,WAAO,QAAQA,UAAS;AAAA,EAC1B;AACF;AAGO,SAAS,SAASA,YAA2B;AAClD,QAAM,YAAY,mBAAmBA,UAAS;AAC9C,QAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,SAAS,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,CAAC;AAC5E,SAAO,GAAG,SAAS,SAAS,CAAC,IAAI,IAAI;AACvC;AAGO,SAAS,iBAAiBA,YAA2B;AAC1D,SAAO,KAAK,aAAa,GAAG,SAASA,UAAS,GAAG,UAAU;AAC7D;AAEO,SAAS,QAAQ,IAAkB,KAA4B;AACpE,QAAM,MAAM,GAAG,QAAQ,sCAAsC,EAAE,IAAI,GAAG;AAGtE,SAAO,KAAK,SAAS;AACvB;AAEO,SAAS,QAAQ,IAAkB,KAAa,OAAqB;AAC1E,KAAG;AAAA,IACD;AAAA,EACF,EAAE,IAAI,KAAK,KAAK;AAClB;AAlHA,IAMM;AANN;AAAA;AAAA;AAMA,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACNf,SAAS,gBAAgB;AACzB,SAAS,QAAAC,aAAY;AACrB,SAAS,aAAa;AACtB,SAAS,SAAS;AAgDX,SAAS,SAAS,OAA0B;AACjD,SAAO,OAAO,UAAU,WAAW,QAAQ,MAAM;AACnD;AA4BA,eAAsB,gBAAgBC,YAAyC;AAC7E,QAAM,OAAOD,MAAKC,YAAW,YAAY;AACzC,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,SAAS,MAAM,MAAM;AAAA,EACnC,SAAS,KAAK;AACZ,UAAM,IAAI,MAAM,2BAA2B,IAAI,IAAI,EAAE,OAAO,IAAI,CAAC;AAAA,EACnE;AACA,QAAM,SAAS,kBAAkB,UAAU,MAAM,GAAG,CAAC;AACrD,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,SAAS,OAAO,MAAM,OACzB,IAAI,CAAC,MAAM,OAAO,EAAE,KAAK,KAAK,GAAG,KAAK,QAAQ,KAAK,EAAE,OAAO,EAAE,EAC9D,KAAK,IAAI;AACZ,UAAM,IAAI,MAAM,yBAAyB,IAAI;AAAA,EAAM,MAAM,EAAE;AAAA,EAC7D;AACA,SAAO,OAAO;AAChB;AAjGA,IAKM,aAMA,iBASA,mBAwCO;AA5Db;AAAA;AAAA;AAKA,IAAM,cAAc,EAAE,OAAO;AAAA,MAC3B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,MAC1B,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,MACjC,QAAQ,EAAE,OAAO;AAAA,IACnB,CAAC;AAED,IAAM,kBAAkB,EAAE,MAAM;AAAA,MAC9B,EAAE,OAAO;AAAA,MACT,EAAE,OAAO;AAAA,QACP,MAAM,EAAE,OAAO;AAAA,QACf,QAAQ,EAAE,OAAO;AAAA,QACjB,OAAO,EAAE,OAAO;AAAA,MAClB,CAAC;AAAA,IACH,CAAC;AAED,IAAM,oBAAoB,EACvB,OAAO;AAAA,MACN,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,WAAW;AAAA,MACxC,OAAO,EAAE,MAAM,eAAe;AAAA,MAC9B,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,MAC5B,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,MACjC,MAAM,EAAE,OAAO;AAAA,QACb,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,QAC7B,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC;AAAA,MAC1C,CAAC;AAAA,MACD,iBAAiB,EAAE,OAAO,EAAE,SAAS;AAAA,MACrC,uBAAuB,EAAE,OAAO,EAAE,SAAS;AAAA,MAC3C,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,MACnC,qBAAqB,EAAE,OAAO,EAAE,SAAS;AAAA,IAC3C,CAAC,EACA,YAAY,CAAC,QAAQ,QAAQ;AAC5B,iBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,MAAM,GAAG;AACzD,YAAI,MAAM,gBAAgB,UAAa,CAAC,OAAO,cAAc,SAAS,MAAM,WAAW,GAAG;AACxF,cAAI,SAAS;AAAA,YACX,MAAM;AAAA,YACN,MAAM,CAAC,UAAU,MAAM,aAAa;AAAA,YACpC,SAAS,IAAI,MAAM,WAAW;AAAA,UAChC,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAeI,IAAM,iBAAsC,oBAAI,IAAI;AAAA,MACzD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA;AAAA;;;ACzED,SAAS,SAAS,iBAAiB;AAkB5B,SAAS,iBAAiB,KAAgC;AAC/D,QAAM,QAAQ,eAAe,KAAK,GAAG;AACrC,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,MAAM,CAAC,GAAG,SAAS,IAAI;AAAA,EAClC;AACA,QAAM,WAAW,MAAM,CAAC,KAAK;AAC7B,QAAM,UAAU,IAAI,MAAM,MAAM,CAAC,EAAE,MAAM;AACzC,MAAI,SAAS,KAAK,MAAM,IAAI;AAC1B,WAAO,EAAE,MAAM,CAAC,GAAG,QAAQ;AAAA,EAC7B;AACA,QAAM,SAAS,UAAU,QAAQ;AACjC,QAAM,OACJ,WAAW,QAAQ,OAAO,WAAW,WAAY,SAAqC,CAAC;AACzF,SAAO,EAAE,MAAM,QAAQ;AACzB;AAhCA,IAUM;AAVN;AAAA;AAAA;AAUA,IAAM,iBAAiB;AAAA;AAAA;;;ACVvB,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,SAAS,YAAAC,iBAAgB;AAClC,SAAS,SAAS,QAAAC,OAAM,UAAU,WAAW;AAG7C,SAAS,KAAAC,UAAS;AA6DlB,SAAS,UAAkC;AACzC,QAAM,SAAS,UAAU,UAAU;AAAA,IACjC,YAAY,QAAQ,IAAI;AAAA,EAC1B,CAAC;AACD,MAAI,CAAC,OAAO,SAAS;AACnB,YAAQ,MAAM,cAAc;AAC5B,YAAQ,MAAM,OAAO,MAAM,OAAO,CAAC;AACnC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO,OAAO;AAChB;AAEA,eAAsB,aAAa,MAAc,QAAmC;AAClF,QAAM,MAAgB,CAAC;AACvB,iBAAe,QAAQ,KAA4B;AAEjD,UAAM,UAAU,MAAM,QAAQ,KAAK,EAAE,eAAe,KAAK,CAAC,EAAE,MAAM,MAAM,IAAI;AAC5E,QAAI,CAAC,QAAS;AACd,eAAW,SAAS,SAAS;AAC3B,UAAI,MAAM,KAAK,WAAW,GAAG,EAAG;AAChC,UAAI,MAAM,YAAY,GAAG;AACvB,cAAM,QAAQD,MAAK,KAAK,MAAM,IAAI,CAAC;AAAA,MACrC,WAAW,MAAM,OAAO,KAAK,MAAM,KAAK,SAAS,KAAK,GAAG;AACvD,YAAI,KAAKA,MAAK,KAAK,MAAM,IAAI,CAAC;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AACA,QAAM,QAAQA,MAAK,MAAM,MAAM,CAAC;AAChC,SAAO;AACT;AAEO,SAAS,eAAe,MAAc,UAA0B;AACrE,SAAO,SAAS,MAAM,QAAQ,EAAE,MAAM,GAAG,EAAE,KAAK,GAAG;AACrD;AAEA,SAAS,OAAO,SAAyB;AACvC,SAAOF,YAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AAC1D;AAEO,SAAS,iBAAiB,MAA0B;AACzD,QAAM,QAAoB,CAAC;AAC3B,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,SAAS,KAAK,SAAS,WAAW,GAAG;AAC9C,UAAM,YAAY,MAAM,CAAC,GAAG,KAAK,KAAK;AACtC,QAAI,CAAC,UAAW;AAIhB,UAAM,SAAS,kBAAkB,KAAK,SAAS;AAC/C,UAAM,SAAS,SAAS,YAAY,GAAG,SAAS;AAChD,UAAM,OAAO,MAAM,CAAC,GAAG,KAAK,KAAK;AACjC,UAAM,MAAM,GAAG,MAAM,IAAI,QAAQ,EAAE;AACnC,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AACZ,UAAM,KAAK,EAAE,QAAQ,KAAK,CAAC;AAAA,EAC7B;AACA,SAAO;AACT;AAUO,SAAS,eAAe,SAAiE;AAC9F,QAAM,WAAW,QAAQ,MAAM,GAAG;AAClC,QAAM,SAAS,SAAS,CAAC;AACzB,MAAI,WAAW,cAAc,SAAS,UAAU,KAAK,SAAS,CAAC,GAAG;AAChE,WAAO,EAAE,OAAO,SAAS,CAAC,GAAG,OAAO,KAAK;AAAA,EAC3C;AACA,MAAI,WAAW,cAAc,SAAS,UAAU,KAAK,SAAS,CAAC,GAAG;AAChE,WAAO,EAAE,OAAO,MAAM,OAAO,SAAS,CAAC,EAAE;AAAA,EAC3C;AACA,SAAO,EAAE,OAAO,MAAM,OAAO,KAAK;AACpC;AAYO,SAAS,gBACd,SACA,KACA,QACA,aACmB;AACnB,QAAM,KAAK,OAAO;AAClB,MAAI,CAAC,GAAG,OAAO;AACb,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,GAAG;AACd,MAAI,CAAC,MAAM;AACT,QAAI,QAAQ,WAAW,QAAQ,GAAG;AAChC,aAAO;AAAA,IACT,OAAO;AACL,cAAQ,KAAK,WAAW,OAAO,oCAA+B;AAC9D,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,EAAE,OAAO,MAAM,IAAI,eAAe,OAAO;AAC/C,MAAI,UAAU,QAAQ,CAAC,YAAY,IAAI,KAAK,GAAG;AAC7C,UAAM,IAAI;AAAA,MACR,kBAAkB,KAAK,SAAS,OAAO;AAAA,IACzC;AAAA,EACF;AACA,QAAM,UACJ,GAAG,mBAAmB,OAClB,GAAG,QAAQ,YAAY,EAAE,MAAM,GAAG,EAAE,IACpC,OAAO,GAAG,YAAY,WACpB,GAAG,QAAQ,MAAM,GAAG,EAAE,IACtB;AAER,QAAM,cAAc,OAAO,QAAQ,OAAO,IAA+B,EAAE;AAAA,IACzE,CAAC,CAAC,CAAC,MAAM,CAAC,yBAAyB,IAAI,CAAC;AAAA,EAC1C;AACA,QAAM,OAAO,YAAY,SAAS,IAAI,OAAO,YAAY,WAAW,IAAI;AAExE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO,GAAG;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,GAAG,WAAW,SAAS,SAAS,WAAW;AAAA,IACnD,SAAS,GAAG,WAAW;AAAA,IACvB,MAAM,MAAM,QAAQ,GAAG,IAAI,IAAI,GAAG,OAAO;AAAA,IACzC;AAAA,IACA,MAAM,OAAO;AAAA,IACb,MAAM,OAAO,GAAG;AAAA,IAChB;AAAA,EACF;AACF;AAEO,SAAS,SAAS,IAAkB,QAAgC;AACzE,QAAM,WAAW,GAAG,QAAQ,+CAA+C,EAAE,IAAI,OAAO,IAAI;AAG5F,MAAI,UAAU,iBAAiB,OAAO,MAAM;AAC1C,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,GAAG;AAAA,IAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcF;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO,OAAO,KAAK,UAAU,OAAO,IAAI,IAAI;AAAA,IAC5C,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO,OAAO,KAAK,UAAU,OAAO,IAAI,IAAI;AAAA,EAC9C;AAEA,KAAG,QAAQ,yCAAyC,EAAE,IAAI,OAAO,IAAI;AACrE,QAAM,aAAa,GAAG;AAAA,IACpB;AAAA;AAAA;AAAA,EAGF;AACA,aAAW,QAAQ,iBAAiB,OAAO,IAAI,GAAG;AAChD,eAAW,IAAI,OAAO,MAAM,KAAK,QAAQ,KAAK,IAAI;AAAA,EACpD;AAEA,SAAO;AACT;AAEA,eAAsB,UAAyB;AAC7C,QAAM,MAAM,QAAQ;AACpB,QAAM,SAAS,iBAAiB,IAAI,UAAU;AAC9C,UAAQ,IAAI,SAAS,IAAI,UAAU,WAAM,MAAM,EAAE;AAEjD,QAAM,cAAc,MAAM,gBAAgB,IAAI,UAAU;AACxD,QAAM,SAAS,IAAI,IAAI,OAAO,KAAK,YAAY,MAAM,CAAC;AAEtD,YAAU,QAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,QAAM,KAAK,aAAa,MAAM;AAE9B,MAAI;AACF,UAAM,QAAkB,CAAC;AACzB,eAAW,UAAU,cAAc;AACjC,YAAM,KAAK,GAAI,MAAM,aAAa,IAAI,YAAY,MAAM,CAAE;AAAA,IAC5D;AAEA,UAAM,eAAyB,CAAC;AAChC,QAAI,UAAU;AACd,QAAI,YAAY;AAChB,QAAI,UAAU;AAEd,eAAW,QAAQ,OAAO;AACxB,YAAM,OAAO,eAAe,IAAI,YAAY,IAAI;AAChD,YAAM,MAAM,MAAMC,UAAS,MAAM,MAAM;AACvC,YAAM,SAAS,iBAAiB,GAAG;AACnC,YAAM,SAAS,gBAAgB,MAAM,KAAK,QAAQ,MAAM;AACxD,UAAI,CAAC,QAAQ;AACX;AACA;AAAA,MACF;AAEA,YAAM,SAAS,SAAS,IAAI,MAAM;AAClC,UAAI,WAAW,WAAW;AACxB;AAAA,MACF,OAAO;AACL;AAAA,MACF;AACA,mBAAa,KAAK,IAAI;AAAA,IACxB;AAEA,QAAI,eAAe;AACnB,QAAI,eAAe;AACnB,QAAI,aAAa,SAAS,GAAG;AAC3B,YAAM,eAAe,aAAa,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI;AAC1D,YAAM,aAAa,GAChB,QAAQ,wCAAwC,YAAY,GAAG,EAC/D,IAAI,GAAG,YAAY;AACtB,qBAAe,OAAO,WAAW,OAAO;AACxC,YAAM,aAAa,GAChB,QAAQ,qEAAqE,EAC7E,IAAI;AACP,qBAAe,OAAO,WAAW,OAAO;AAAA,IAC1C,OAAO;AACL,cAAQ,KAAK,6DAA6D;AAAA,IAC5E;AAEA,OAAG,KAAK,oDAAoD;AAE5D,YAAQ,IAAI,cAAc,mBAAmB,IAAI,UAAU,CAAC;AAC5D,YAAQ,IAAI,gBAAe,oBAAI,KAAK,GAAE,YAAY,CAAC;AAEnD,YAAQ;AAAA,MACN,SAAS,OAAO,aAAa,SAAS,eAAe,OAAO,aAAa,YAAY,mBAAmB,YAAY;AAAA,IACtH;AAAA,EACF,UAAE;AACA,OAAG,MAAM;AAAA,EACX;AACF;AA5UA,IAUM,WAMO,cAGP,aAeA;AAlCN;AAAA;AAAA;AAKA;AAEA;AACA;AAEA,IAAM,YAAYE,GAAE,OAAO;AAAA,MACzB,YAAYA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IAC9B,CAAC;AAIM,IAAM,eAAe,CAAC,YAAY,YAAY,OAAO;AAG5D,IAAM,cAAc;AAepB,IAAM,2BAA2B,oBAAI,IAAY;AAAA,MAC/C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA;AAAA;;;AC3CD,SAAS,YAAAC,WAAU,YAAY;AAC/B,SAAS,QAAAC,aAAY;AAsBrB,SAAS,kBAAkB,MAAwC;AACjE,SAAO,OAAO,KAAK,UAAU,YAAY,KAAK,MAAM,KAAK,MAAM;AACjE;AAUA,SAAS,UAAU,SAAiB,MAAwC;AAC1E,MAAI,CAAC,kBAAkB,IAAI,EAAG,QAAO;AACrC,MAAI,OAAO,KAAK,SAAS,YAAY,KAAK,SAAS,GAAI,QAAO;AAC9D,SAAO,QAAQ,WAAW,QAAQ;AACpC;AAOA,SAAS,SAAS,SAA0B;AAC1C,SAAO,YAAY,eAAe,QAAQ,SAAS,YAAY;AACjE;AA4DA,SAAS,oBAAoB,SAAiB,MAA0C;AAGtF,QAAM,OACJ,OAAO,KAAK,SAAS,YAAY,KAAK,SAAS,KAC3C,KAAK,OACL,QAAQ,WAAW,QAAQ,IACzB,SACA;AACR,QAAM,WAAW,OAAO,gBAAgB,IAAI,IAAI;AAChD,MAAI,CAAC,SAAU,QAAO,CAAC;AACvB,QAAM,WAAsB,CAAC;AAC7B,aAAW,SAAS,UAAU;AAC5B,QAAI,CAAC,OAAO,OAAO,MAAM,KAAK,GAAG;AAC/B,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,2BAA2B,KAAK,eAAe,IAAI;AAAA,MAC9D,CAAC;AAAA,IACH;AAAA,EACF;AAIA,MAAI,OAAO,OAAO,MAAM,OAAO,KAAK,CAAC,kBAAkB,IAAI,GAAG;AAC5D,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,gDAAgD,IAAI;AAAA,IAC/D,CAAC;AAAA,EACH;AACA,SAAO;AACT;AASA,SAAS,gBAAgB,KAA+B;AACtD,QAAM,QAAQ,oBAAI,IAAY;AAC9B,aAAW,SAAS,IAAI,OAAO;AAC7B,QAAI,OAAO,UAAU,YAAY,CAAC,eAAe,IAAI,MAAM,IAAI,EAAG,OAAM,IAAI,MAAM,IAAI;AAAA,EACxF;AACA,SAAO;AACT;AAEA,SAAS,qBACP,SACA,MACA,KACW;AACX,QAAM,OAAO,KAAK;AAClB,MAAI,OAAO,SAAS,YAAY,CAAC,gBAAgB,GAAG,EAAE,IAAI,IAAI,EAAG,QAAO,CAAC;AACzE,QAAM,WAAsB,CAAC;AAC7B,aAAW,SAAS,iBAAiB;AACnC,QAAI,CAAC,OAAO,OAAO,MAAM,KAAK,GAAG;AAC/B,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,gBAAgB,IAAI,eAAe,KAAK;AAAA,MACnD,CAAC;AAAA,IACH;AAAA,EACF;AACA,MAAI,OAAO,OAAO,MAAM,OAAO,KAAK,CAAC,kBAAkB,IAAI,GAAG;AAC5D,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,gBAAgB,IAAI;AAAA,IAC/B,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAOA,SAAS,kBAAkB,SAAiB,MAA0C;AACpF,QAAM,OACJ,OAAO,KAAK,SAAS,YAAY,KAAK,SAAS,KAC3C,KAAK,OACL,QAAQ,WAAW,QAAQ,IACzB,SACA;AACR,MAAI,QAAQ,mBAAmB,IAAI,IAAI,EAAG,QAAO,CAAC;AAClD,MAAI,MAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS,EAAG,QAAO,CAAC;AAC9D,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SACE;AAAA,IACJ;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,SAAiB,MAA0C;AAClF,QAAM,OAAO,KAAK;AAClB,QAAM,UAAU,OAAO,SAAS,WAAW,gBAAgB,IAAI,IAAI;AACnE,MAAI,CAAC,WAAW,QAAQ,KAAK,OAAO,EAAG,QAAO,CAAC;AAC/C,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,4BAA4B,IAAI,kBAAkB,QAAQ,MAAM;AAAA,IAC3E;AAAA,EACF;AACF;AAEA,SAAS,gBACP,SACA,MACA,KACW;AACX,QAAM,WAAsB,CAAC;AAC7B,QAAM,OAAO,KAAK;AAClB,MAAI,OAAO,SAAS,YAAY,CAAC,IAAI,MAAM,KAAK,CAAC,MAAM,SAAS,CAAC,MAAM,IAAI,GAAG;AAC5E,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,SAAS,IAAI;AAAA,IACxB,CAAC;AAAA,EACH;AACA,QAAM,SAAS,KAAK;AACpB,MAAI,OAAO,WAAW,YAAY,CAAC,IAAI,SAAS,SAAS,MAAM,GAAG;AAChE,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,WAAW,MAAM;AAAA,IAC5B,CAAC;AAAA,EACH;AACA,QAAM,EAAE,MAAM,IAAI,eAAe,OAAO;AACxC,MAAI,UAAU,QAAQ,CAAC,OAAO,OAAO,IAAI,QAAQ,KAAK,GAAG;AACvD,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,UAAU,KAAK;AAAA,IAC1B,CAAC;AAAA,EACH;AACA,QAAM,cAAc,KAAK;AACzB,MAAI,OAAO,gBAAgB,YAAY,CAAC,IAAI,cAAc,SAAS,WAAW,GAAG;AAC/E,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,gBAAgB,WAAW;AAAA,IACtC,CAAC;AAAA,EACH;AACA,SAAO;AACT;AASA,SAAS,eAAe,SAAiB,MAA0C;AACjF,QAAM,EAAE,OAAO,MAAM,IAAI,eAAe,OAAO;AAC/C,QAAM,WAAsB,CAAC;AAC7B,MACE,UAAU,QACV,OAAO,KAAK,UAAU,YACtB,KAAK,UAAU,MACf,KAAK,UAAU,OACf;AACA,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,sBAAsB,KAAK,KAAK,gCAAgC,KAAK;AAAA,IAChF,CAAC;AAAA,EACH;AACA,MACE,UAAU,QACV,OAAO,KAAK,UAAU,YACtB,KAAK,UAAU,MACf,KAAK,UAAU,OACf;AACA,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,sBAAsB,KAAK,KAAK,gCAAgC,KAAK;AAAA,IAChF,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAGA,SAAS,UAAU,OAA+B;AAChD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,YAAY,KAAK,OAAOC,UAAS,OAAO;AACjD;AAOA,SAAS,WAAW,OAA0B;AAC5C,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,SAAS,EAAE,OAAO,CAAC,MAAmB,MAAM,IAAI;AAAA,EACnE;AACA,QAAM,SAAS,UAAU,KAAK;AAC9B,SAAO,WAAW,OAAO,CAAC,IAAI,CAAC,MAAM;AACvC;AAQA,SAAS,UAAU,MAAsB;AACvC,SAAO,KAAK,QAAQ,mBAAmB,EAAE,EAAE,QAAQ,YAAY,EAAE;AACnE;AAQA,SAAS,eAAe,SAAiB,MAAc,UAA0C;AAC/F,QAAM,WAAsB,CAAC;AAC7B,aAAW,QAAQ,iBAAiB,UAAU,IAAI,CAAC,GAAG;AACpD,QAAI,CAAC,KAAK,OAAO,SAAS,KAAK,EAAG;AAClC,QAAI,CAAC,SAAS,IAAIA,UAAS,KAAK,MAAM,CAAC,GAAG;AACxC,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,oBAAoB,KAAK,MAAM;AAAA,MAC1C,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAQA,SAAS,gBACP,SACA,MACA,MACA,UACW;AACX,QAAM,WAAsB,eAAe,SAAS,MAAM,QAAQ;AAClE,QAAM,YAAsB,CAAC;AAC7B,QAAM,SAAS,UAAU,KAAK,MAAM;AACpC,MAAI,WAAW,KAAM,WAAU,KAAK,MAAM;AAC1C,aAAW,SAAS,CAAC,cAAc,iBAAiB,YAAY,GAAY;AAC1E,cAAU,KAAK,GAAG,WAAW,KAAK,KAAK,CAAC,CAAC;AAAA,EAC3C;AACA,aAAW,UAAU,WAAW;AAC9B,QAAI,CAAC,SAAS,IAAI,MAAM,GAAG;AACzB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,0BAA0B,MAAM;AAAA,MAC3C,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAQA,SAAS,UAAU,SAAiB,MAA+B,KAA6B;AAC9F,MAAI,CAAC,MAAM,QAAQ,KAAK,IAAI,EAAG,QAAO,CAAC;AACvC,QAAM,WAAsB,CAAC;AAC7B,aAAW,OAAO,KAAK,MAAM;AAC3B,QAAI,OAAO,QAAQ,YAAY,OAAO,OAAO,IAAI,KAAK,SAAS,GAAG,GAAG;AACnE,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,QAAQ,GAAG,iCAAiC,IAAI,KAAK,QAAQ,GAAG,CAAC;AAAA,MAC5E,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,oBAAoB,SAAiB,MAA0C;AACtF,MAAI,KAAK,WAAW,gBAAgB,WAAW,KAAK,aAAa,EAAE,WAAW,GAAG;AAC/E,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACA,SAAO,CAAC;AACV;AAIA,SAAS,iBACP,SACA,MACA,MACA,KACA,UACW;AACX,MAAI,CAAC,UAAU,SAAS,IAAI,EAAG,QAAO,CAAC;AACvC,SAAO;AAAA,IACL,GAAG,kBAAkB,SAAS,IAAI;AAAA,IAClC,GAAG,gBAAgB,SAAS,IAAI;AAAA,IAChC,GAAG,gBAAgB,SAAS,MAAM,GAAG;AAAA,IACrC,GAAG,eAAe,SAAS,IAAI;AAAA,IAC/B,GAAG,gBAAgB,SAAS,MAAM,MAAM,QAAQ;AAAA,IAChD,GAAG,oBAAoB,SAAS,IAAI;AAAA,IACpC,GAAG,UAAU,SAAS,MAAM,GAAG;AAAA,EACjC;AACF;AASO,SAAS,aACd,SACA,KACA,KACA,UACW;AACX,MAAI;AACJ,MAAI;AACF,aAAS,iBAAiB,GAAG;AAAA,EAC/B,SAAS,KAAK;AACZ,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AACA,MAAI,SAAS,OAAO,GAAG;AACrB,WAAO,eAAe,SAAS,OAAO,SAAS,QAAQ;AAAA,EACzD;AAKA,SAAO;AAAA,IACL,GAAG,oBAAoB,SAAS,OAAO,IAAI;AAAA,IAC3C,GAAG,qBAAqB,SAAS,OAAO,MAAM,GAAG;AAAA,IACjD,GAAG,iBAAiB,SAAS,OAAO,MAAM,OAAO,SAAS,KAAK,QAAQ;AAAA,EACzE;AACF;AAGO,SAAS,UAAU,UAA8B;AACtD,SAAO,SAAS,KAAK,CAAC,MAAM,EAAE,aAAa,OAAO;AACpD;AAGA,SAASA,UAAS,SAAyB;AACzC,QAAM,OAAO,QAAQ,MAAM,GAAG,EAAE,IAAI,KAAK;AACzC,SAAO,KAAK,QAAQ,SAAS,EAAE;AACjC;AAcO,SAAS,qBAAqB,OAA8B;AACjE,QAAM,OAAO,oBAAI,IAA4E;AAC7F,aAAW,EAAE,MAAM,KAAK,KAAK,OAAO;AAClC,QAAI,KAAK,SAAS,MAAO;AACzB,SAAK,IAAIA,UAAS,IAAI,GAAG;AAAA,MACvB;AAAA,MACA,YAAY,WAAW,KAAK,UAAU;AAAA,MACtC,cAAc,WAAW,KAAK,aAAa;AAAA,IAC7C,CAAC;AAAA,EACH;AACA,QAAM,WAAsB,CAAC;AAC7B,aAAW,CAAC,MAAM,GAAG,KAAK,MAAM;AAC9B,eAAW,UAAU,IAAI,cAAc;AACrC,YAAM,QAAQ,KAAK,IAAI,MAAM;AAC7B,UAAI,SAAS,CAAC,MAAM,WAAW,SAAS,IAAI,GAAG;AAC7C,iBAAS,KAAK;AAAA,UACZ,MAAM,IAAI;AAAA,UACV,MAAM;AAAA,UACN,UAAU;AAAA,UACV,SAAS,kBAAkB,MAAM,wCAAwC,IAAI;AAAA,QAC/E,CAAC;AAAA,MACH;AAAA,IACF;AACA,eAAW,UAAU,IAAI,YAAY;AACnC,YAAM,QAAQ,KAAK,IAAI,MAAM;AAC7B,UAAI,SAAS,CAAC,MAAM,aAAa,SAAS,IAAI,GAAG;AAC/C,iBAAS,KAAK;AAAA,UACZ,MAAM,IAAI;AAAA,UACV,MAAM;AAAA,UACN,UAAU;AAAA,UACV,SAAS,eAAe,MAAM,2CAA2C,IAAI;AAAA,QAC/E,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAIA,SAAS,YAAY,SAAgC;AACnD,QAAM,MAAM,QAAQ,MAAM,GAAG;AAC7B,OAAK,IAAI,CAAC,MAAM,cAAc,IAAI,CAAC,MAAM,eAAe,IAAI,CAAC,GAAG;AAC9D,WAAO,GAAG,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;AAAA,EAC5B;AACA,SAAO;AACT;AAcO,SAAS,uBACd,OACA,iBACW;AACX,QAAM,WAAsB,CAAC;AAC7B,aAAW,EAAE,MAAM,KAAK,KAAK,OAAO;AAClC,UAAM,OAAO,YAAY,IAAI;AAC7B,eAAW,QAAQ,iBAAiB,UAAU,IAAI,CAAC,GAAG;AACpD,UAAI,CAAC,KAAK,OAAO,SAAS,KAAK,KAAK,KAAK,OAAO,SAAS,GAAG,EAAG;AAC/D,YAAM,OAAOA,UAAS,KAAK,MAAM;AACjC,YAAM,SAAS,gBAAgB,IAAI,IAAI;AACvC,UAAI,CAAC,UAAU,OAAO,SAAS,EAAG;AAClC,UAAI,SAAS,QAAQ,OAAO,KAAK,CAAC,MAAM,YAAY,CAAC,MAAM,IAAI,EAAG;AAClE,eAAS,KAAK;AAAA,QACZ;AAAA,QACA,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,gBAAgB,IAAI,6CAAwC,OAAO,MAAM;AAAA,MACpF,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAQA,eAAsB,cAAc,MAAkC;AACpE,QAAM,MAAM,MAAM,gBAAgB,IAAI;AAMtC,QAAM,OAAO,MAAM,aAAa,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS;AAAA,IACxD,SAAS,eAAe,MAAM,GAAG;AAAA,IACjC;AAAA,EACF,EAAE;AAIF,QAAM,kBAAkB,oBAAI,IAAsB;AAClD,aAAW,KAAK,KAAK;AACnB,UAAM,IAAIA,UAAS,EAAE,OAAO;AAC5B,UAAM,SAAS,gBAAgB,IAAI,CAAC;AACpC,QAAI,OAAQ,QAAO,KAAK,EAAE,OAAO;AAAA,QAC5B,iBAAgB,IAAI,GAAG,CAAC,EAAE,OAAO,CAAC;AAAA,EACzC;AACA,QAAM,WAAW,IAAI,IAAY,gBAAgB,KAAK,CAAC;AAGvD,QAAM,QAAQ,IAAI,OAAO,CAAC,MAAM,aAAa,KAAK,CAAC,MAAM,EAAE,QAAQ,WAAW,GAAG,CAAC,GAAG,CAAC,CAAC;AAEvF,QAAM,WAAsB,CAAC;AAC7B,QAAM,QAAoB,CAAC;AAC3B,QAAM,YAAwB,CAAC;AAC/B,aAAW,EAAE,SAAS,IAAI,KAAK,OAAO;AACpC,UAAM,MAAM,MAAMF,UAAS,KAAK,MAAM;AACtC,aAAS,KAAK,GAAG,aAAa,SAAS,KAAK,KAAK,QAAQ,CAAC;AAC1D,QAAI;AACF,YAAM,SAAS,iBAAiB,GAAG;AACnC,YAAM,KAAK,EAAE,MAAM,SAAS,MAAM,OAAO,KAAK,CAAC;AAC/C,gBAAU,KAAK,EAAE,MAAM,SAAS,MAAM,OAAO,QAAQ,CAAC;AAAA,IACxD,QAAQ;AAAA,IAER;AAAA,EACF;AACA,WAAS,KAAK,GAAG,qBAAqB,KAAK,CAAC;AAC5C,WAAS,KAAK,GAAG,uBAAuB,WAAW,eAAe,CAAC;AAInE,aAAW,QAAQ,gBAAgB,GAAG,GAAG;AACvC,UAAM,OAAO,aAAa,IAAI;AAC9B,QAAI;AACF,YAAM,KAAKC,MAAK,MAAM,IAAI,CAAC;AAAA,IAC7B,QAAQ;AACN,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,gBAAgB,IAAI;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAzpBA,IAuDM,iBAqCA,oBAKA,iBAkDA;AAnJN;AAAA;AAAA;AAEA;AACA;AACA;AAmDA,IAAM,kBAAqD;AAAA,MACzD,SAAS;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,MAAM,CAAC,SAAS,QAAQ,SAAS,UAAU,WAAW,WAAW,SAAS;AAAA,MAC1E,KAAK,CAAC,SAAS,QAAQ,SAAS,UAAU,SAAS;AAAA,MACnD,MAAM,CAAC,SAAS,QAAQ,SAAS,UAAU,WAAW,SAAS;AAAA,MAC/D,KAAK,CAAC,SAAS,QAAQ,SAAS,UAAU,WAAW,SAAS;AAAA,MAC9D,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO,CAAC,SAAS,QAAQ,UAAU,WAAW,WAAW,YAAY;AAAA,MACrE,SAAS,CAAC,SAAS,QAAQ,UAAU,SAAS;AAAA,MAC9C,KAAK,CAAC,SAAS,QAAQ,SAAS,UAAU,WAAW,SAAS;AAAA,MAC9D,MAAM,CAAC,SAAS,SAAS;AAAA,IAC3B;AAKA,IAAM,qBAAqB,oBAAI,IAAI,CAAC,YAAY,UAAU,kBAAkB,YAAY,CAAC;AAKzF,IAAM,kBAA0C;AAAA,MAC9C,MAAM;AAAA,MACN,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAyCA,IAAM,kBAAkB,CAAC,SAAS,WAAW,SAAS;AAAA;AAAA;;;ACnJtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,YAAY,aAAa,cAAc;AAChD,SAAS,WAAAE,UAAS,QAAAC,aAAY;AAC9B,SAAS,iBAAiB;AAoBnB,SAAS,WAAW,MAA+B;AACxD,QAAM,EAAE,aAAAC,aAAY,IAAI,UAAU,EAAE,MAAM,MAAM,kBAAkB,MAAM,QAAQ,MAAM,CAAC;AACvF,QAAMC,WAAUD,aAAY,CAAC;AAC7B,MAAIC,aAAY,QAAQ;AACtB,WAAO,EAAE,MAAM,OAAO,SAAS,OAAO;AAAA,EACxC;AACA,MAAIA,aAAY,YAAY;AAC1B,WAAO,EAAE,MAAM,OAAO,SAAS,WAAW;AAAA,EAC5C;AACA,MAAIA,aAAY,QAAW;AACzB,WAAO,EAAE,MAAM,SAAS,SAAS,8BAA8B;AAAA,EACjE;AACA,SAAO,EAAE,MAAM,SAAS,SAAS,oBAAoBA,QAAO,GAAG;AACjE;AAEO,SAAS,YAAoB;AAClC,QAAM,OAAO,QAAQ,IAAI;AACzB,MAAI,CAAC,MAAM;AACT,YAAQ,MAAM,uBAAuB;AACrC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAEA,SAAS,eAAe,UAA2B;AACjD,aAAW,KAAK,UAAU;AACxB,YAAQ,MAAM,GAAG,EAAE,QAAQ,KAAK,EAAE,IAAI,KAAK,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE;AAAA,EACnE;AACF;AAEA,eAAsB,cAA6B;AACjD,QAAM,WAAW,MAAM,cAAc,UAAU,CAAC;AAChD,iBAAe,QAAQ;AACvB,UAAQ,IAAI,aAAa,SAAS,MAAM,aAAa;AACrD,UAAQ,KAAK,UAAU,QAAQ,IAAI,IAAI,CAAC;AAC1C;AAEA,eAAsB,iBAAgC;AACpD,QAAM,WAAW,MAAM,cAAc,UAAU,CAAC;AAChD,iBAAe,QAAQ;AACvB,MAAI,UAAU,QAAQ,GAAG;AACvB,UAAM,SAAS,SAAS,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO,EAAE;AAC9D,YAAQ,MAAM,iBAAiB,MAAM,0CAA0C;AAC/E,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,QAAQ;AAChB;AAUA,SAAS,cAAc,MAAgC;AACrD,QAAM,QAAQ,mBAAmB,IAAI;AACrC,QAAM,QAAQ,iBAAiB,KAAK;AACpC,MAAI,SAAS;AACb,MAAI,WAAW,KAAK,GAAG;AACrB,UAAM,KAAK,aAAa,KAAK;AAC7B,QAAI;AACF,eAAS,QAAQ,IAAI,aAAa,KAAK;AAAA,IACzC,UAAE;AACA,SAAG,MAAM;AAAA,IACX;AAAA,EACF;AACA,SAAO,EAAE,OAAO,OAAO,OAAO;AAChC;AAEA,SAAS,WAAW,GAA2B;AAC7C,UAAQ,IAAI,UAAU,EAAE,KAAK,EAAE;AAC/B,UAAQ,IAAI,UAAU,EAAE,KAAK,EAAE;AAC/B,UAAQ,IAAI,WAAW,EAAE,MAAM,EAAE;AACnC;AAGA,SAAS,cAAkC;AACzC,QAAM,OAAO,aAAa;AAC1B,MAAI,CAAC,WAAW,IAAI,EAAG,QAAO,CAAC;AAC/B,QAAM,QAA4B,CAAC;AACnC,aAAW,SAAS,YAAY,MAAM,EAAE,eAAe,KAAK,CAAC,GAAG;AAC9D,QAAI,CAAC,MAAM,YAAY,EAAG;AAC1B,UAAM,QAAQF,MAAK,MAAM,MAAM,MAAM,UAAU;AAC/C,QAAI,CAAC,WAAW,KAAK,EAAG;AACxB,UAAM,KAAK,aAAa,KAAK;AAC7B,QAAI;AACF,YAAM,QAAQ,QAAQ,IAAI,YAAY;AACtC,UAAI,UAAU,KAAM;AACpB,YAAM,KAAK,EAAE,OAAO,OAAO,QAAQ,QAAQ,IAAI,aAAa,KAAK,QAAQ,CAAC;AAAA,IAC5E,UAAE;AACA,SAAG,MAAM;AAAA,IACX;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,YAA2B;AAC/C,QAAM,OAAO,QAAQ,IAAI;AACzB,MAAI,MAAM;AACR,eAAW,cAAc,IAAI,CAAC;AAC9B;AAAA,EACF;AACA,QAAM,QAAQ,YAAY;AAC1B,MAAI,MAAM,WAAW,GAAG;AACtB,YAAQ;AAAA,MACN;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,QAAQ,CAAC,GAAG,MAAM;AACtB,QAAI,IAAI,EAAG,SAAQ,IAAI,EAAE;AACzB,eAAW,CAAC;AAAA,EACd,CAAC;AACH;AAEA,eAAsB,aAA4B;AAChD,QAAM,OAAO,QAAQ,IAAI;AACzB,MAAI,CAAC,MAAM;AACT,YAAQ,MAAM,wDAAwD;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,MAAMD,SAAQ,iBAAiB,IAAI,CAAC;AAC1C,MAAI,CAAC,WAAW,GAAG,GAAG;AACpB,YAAQ,IAAI,GAAG,GAAG,yCAAoC;AACtD;AAAA,EACF;AACA,SAAO,KAAK,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAC5C,UAAQ,IAAI,WAAW,GAAG,EAAE;AAC9B;AAEA,eAAsB,OAAsB;AAC1C,QAAM,aAAa,WAAW,QAAQ,KAAK,MAAM,CAAC,CAAC;AACnD,MAAI,WAAW,SAAS,SAAS;AAC/B,YAAQ,MAAM,WAAW,OAAO;AAChC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,WAAW,YAAY,QAAQ;AACjC,UAAM,eAAe;AAAA,EACvB,OAAO;AACL,UAAM,YAAY;AAAA,EACpB;AACF;AArKA;AAAA;AAAA;AAGA;AAOA;AACA;AAAA;AAAA;;;ACXA,SAAS,KAAAI,UAAS;AAmBX,SAAS,WAAW,MAAyB,QAAQ,KAAa;AACvE,QAAM,SAASC,WAAU,UAAU,GAAG;AACtC,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,SAAS,OAAO,MAAM,OACzB,IAAI,CAAC,MAAM,OAAO,EAAE,KAAK,KAAK,GAAG,KAAK,QAAQ,KAAK,EAAE,OAAO,EAAE,EAC9D,KAAK,IAAI;AACZ,UAAM,IAAI,MAAM;AAAA,EAAuC,MAAM,EAAE;AAAA,EACjE;AACA,SAAO;AAAA,IACL,WAAW,OAAO,KAAK;AAAA,IACvB,UAAU,OAAO,KAAK;AAAA,IACtB,YAAY,OAAO,KAAK;AAAA,IACxB,eAAe,OAAO,KAAK;AAAA,EAC7B;AACF;AAjCA,IAEMA;AAFN,IAAAC,eAAA;AAAA;AAAA;AAEA,IAAMD,aAAYD,GAAE,OAAO;AAAA,MACzB,YAAYA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,MACjF,WAAWA,GACR,KAAK,CAAC,SAAS,SAAS,QAAQ,QAAQ,SAAS,SAAS,QAAQ,CAAC,EACnE,QAAQ,MAAM,EACd,SAAS,4EAA4E;AAAA,MACxF,aAAaA,GAAE,OAAO,EAAE,QAAQ,UAAU;AAAA,MAC1C,gBAAgBA,GAAE,OAAO,EAAE,QAAQ,OAAO;AAAA,IAC5C,CAAC;AAAA;AAAA;;;ACVD,SAAS,aAAAG,kBAAiB;AAC1B,SAAS,WAAAC,gBAAe;AASjB,SAAS,eAAeC,YAAiC;AAC9D,QAAM,SAAS,iBAAiBA,UAAS;AACzC,EAAAF,WAAUC,SAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,QAAM,KAAK,aAAa,MAAM;AAC9B,UAAQ,IAAI,cAAc,mBAAmBC,UAAS,CAAC;AACvD,SAAO;AACT;AAhBA;AAAA;AAAA;AAGA;AAAA;AAAA;;;ACHA,SAAS,gBAAgB,aAAAC,kBAAiB;AAC1C,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,aAAY;AAiBd,SAAS,KAAK,KAAa,MAAsC;AACtE,MAAI;AACF,UAAM,OAAO,OACT,IAAG,oBAAI,KAAK,GAAE,YAAY,CAAC,QAAQ,QAAQ,GAAG,IAAI,GAAG,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,IAC7E,IAAG,oBAAI,KAAK,GAAE,YAAY,CAAC,QAAQ,QAAQ,GAAG,IAAI,GAAG;AAAA;AACzD,mBAAe,eAAe,IAAI;AAAA,EACpC,QAAQ;AAAA,EAER;AACF;AA5BA,IAIM,UACO;AALb;AAAA;AAAA;AAIA,IAAM,WAAWA,MAAKD,SAAQ,GAAG,UAAU,SAAS,UAAU;AACvD,IAAM,gBAAgBC,MAAK,UAAU,YAAY;AAExD,QAAI;AACF,MAAAF,WAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAAA,IACzC,QAAQ;AAAA,IAER;AAAA;AAAA;;;ACXA,OAAO,UAAU;AAUV,SAAS,aAAa,OAAe,MAA2B;AACrE,QAAM,UAA8B;AAAA,IAClC,EAAE,OAA4B,QAAQ,KAAK,YAAY,CAAC,EAAE;AAAA,IAC1D;AAAA,MACE;AAAA,MACA,QAAQ,KAAK,YAAY,EAAE,MAAM,eAAe,MAAM,OAAO,OAAO,KAAK,CAAC;AAAA,IAC5E;AAAA,EACF;AACA,SAAO,KAAK,EAAE,MAAM,OAAO,MAAM,EAAE,KAAK,QAAQ,IAAI,EAAE,GAAG,KAAK,YAAY,OAAO,CAAC;AACpF;AAnBA;AAAA;AAAA;AACA;AAAA;AAAA;;;ACDA,SAAS,YAAAG,iBAAgB;AACzB,SAAS,QAAAC,aAAY;AACrB,SAAS,SAAAC,cAAa;AACtB,SAAS,KAAAC,UAAS;AAqDX,SAASC,UAAS,OAA0B;AACjD,SAAO,OAAO,UAAU,WAAW,QAAQ,MAAM;AACnD;AA4BA,eAAsBC,iBAAgBC,YAAyC;AAC7E,QAAM,OAAOL,MAAKK,YAAW,YAAY;AACzC,MAAI;AACJ,MAAI;AACF,UAAM,MAAMN,UAAS,MAAM,MAAM;AAAA,EACnC,SAAS,KAAK;AACZ,UAAM,IAAI,MAAM,2BAA2B,IAAI,IAAI,EAAE,OAAO,IAAI,CAAC;AAAA,EACnE;AACA,QAAM,SAASO,mBAAkB,UAAUL,OAAM,GAAG,CAAC;AACrD,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,SAAS,OAAO,MAAM,OACzB,IAAI,CAAC,MAAM,OAAO,EAAE,KAAK,KAAK,GAAG,KAAK,QAAQ,KAAK,EAAE,OAAO,EAAE,EAC9D,KAAK,IAAI;AACZ,UAAM,IAAI,MAAM,yBAAyB,IAAI;AAAA,EAAM,MAAM,EAAE;AAAA,EAC7D;AACA,SAAO,OAAO;AAChB;AAtGA,IAUMM,cAMAC,kBASAF,oBAwCOG;AAjEb;AAAA;AAAA;AAUA,IAAMF,eAAcL,GAAE,OAAO;AAAA,MAC3B,MAAMA,GAAE,OAAO,EAAE,SAAS;AAAA,MAC1B,aAAaA,GAAE,OAAO,EAAE,SAAS;AAAA,MACjC,QAAQA,GAAE,OAAO;AAAA,IACnB,CAAC;AAED,IAAMM,mBAAkBN,GAAE,MAAM;AAAA,MAC9BA,GAAE,OAAO;AAAA,MACTA,GAAE,OAAO;AAAA,QACP,MAAMA,GAAE,OAAO;AAAA,QACf,QAAQA,GAAE,OAAO;AAAA,QACjB,OAAOA,GAAE,OAAO;AAAA,MAClB,CAAC;AAAA,IACH,CAAC;AAED,IAAMI,qBAAoBJ,GACvB,OAAO;AAAA,MACN,QAAQA,GAAE,OAAOA,GAAE,OAAO,GAAGK,YAAW;AAAA,MACxC,OAAOL,GAAE,MAAMM,gBAAe;AAAA,MAC9B,UAAUN,GAAE,MAAMA,GAAE,OAAO,CAAC;AAAA,MAC5B,eAAeA,GAAE,MAAMA,GAAE,OAAO,CAAC;AAAA,MACjC,MAAMA,GAAE,OAAO;AAAA,QACb,WAAWA,GAAE,MAAMA,GAAE,OAAO,CAAC;AAAA,QAC7B,SAASA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAO,CAAC;AAAA,MAC1C,CAAC;AAAA,MACD,iBAAiBA,GAAE,OAAO,EAAE,SAAS;AAAA,MACrC,uBAAuBA,GAAE,OAAO,EAAE,SAAS;AAAA,MAC3C,eAAeA,GAAE,OAAO,EAAE,SAAS;AAAA,MACnC,qBAAqBA,GAAE,OAAO,EAAE,SAAS;AAAA,IAC3C,CAAC,EACA,YAAY,CAAC,QAAQ,QAAQ;AAC5B,iBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,MAAM,GAAG;AACzD,YAAI,MAAM,gBAAgB,UAAa,CAAC,OAAO,cAAc,SAAS,MAAM,WAAW,GAAG;AACxF,cAAI,SAAS;AAAA,YACX,MAAM;AAAA,YACN,MAAM,CAAC,UAAU,MAAM,aAAa;AAAA,YACpC,SAAS,IAAI,MAAM,WAAW;AAAA,UAChC,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAeI,IAAMO,kBAAsC,oBAAI,IAAI;AAAA,MACzD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA;AAAA;;;ACwCD,SAAS,oBAAoB,QAA6B;AACxD,QAAM,QAAQ,EAAE,OAAO,mBAAmB,yBAAyB,KAAK,CAAC;AACzE,MAAI,OAAO,sBAAuB,OAAM,KAAK,OAAO,sBAAsB,KAAK,CAAC;AAChF,SAAO,CAAC,sBAAsB,IAAI,MAAM,KAAK,MAAM,CAAC,EAAE,KAAK,IAAI;AACjE;AAUA,SAAS,kBAAkB,QAA6B;AACtD,QAAM,QAAQ,EAAE,OAAO,iBAAiB,uBAAuB,KAAK,CAAC;AACrE,MAAI,OAAO,oBAAqB,OAAM,KAAK,OAAO,oBAAoB,KAAK,CAAC;AAC5E,SAAO,CAAC,sBAAsB,IAAI,MAAM,KAAK,MAAM,CAAC,EAAE,KAAK,IAAI;AACjE;AAEA,SAAS,kBAAkB,OAAyC;AAClE,QAAM,QAAkB,CAAC,oBAAoB,IAAI,6BAA6B,eAAe;AAC7F,aAAW,SAAS,OAAO;AACzB,UAAM,OAAOC,UAAS,KAAK;AAC3B,UAAM,WAAW,OAAO,UAAU,WAAW,cAAc,IAAI,KAAK,IAAI;AACxE,UAAM,SAAS,UAAU,UAAU;AACnC,UAAM,QAAQ,UAAU,SAAS;AACjC,UAAM,KAAK,KAAK,MAAM,QAAQ,IAAI,QAAQ,KAAK,IAAI;AAAA,EACrD;AACA,QAAM,QAAQ,MAAM,IAAIA,SAAQ;AAChC,QAAM,UAAU,MAAM,SAAS,MAAM;AACrC,QAAM,gBAAgB,MAAM,SAAS,KAAK,KAAK,MAAM,SAAS,MAAM;AACpE,MAAI,WAAW,eAAe;AAC5B,UAAM,QAAkB,CAAC;AACzB,QAAI,QAAS,OAAM,KAAK,2BAAsB;AAC9C,QAAI,eAAe;AACjB,YAAM;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AACA,UAAM,KAAK,IAAI,MAAM,KAAK,GAAG,CAAC;AAAA,EAChC;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAMA,SAAS,gBAAgB,UAAyC;AAChE,QAAM,cACJ,SAAS,WAAW,sBAAsB,UAC1C,SAAS,MAAM,CAAC,GAAG,MAAM,MAAM,sBAAsB,CAAC,CAAC;AACzD,SAAO,cACH,iBAAiB,SAAS,KAAK,UAAK,CAAC,+DACrC,iBAAiB,SAAS,KAAK,IAAI,CAAC;AAC1C;AAEA,SAAS,gBAAgB,QAA6B;AACpD,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA,cAAc,OAAO,MAAM,IAAIA,SAAQ,EAAE,KAAK,IAAI,CAAC;AAAA,IACnD,gBAAgB,OAAO,QAAQ;AAAA,IAC/B,sBAAsB,OAAO,cAAc,KAAK,IAAI,CAAC;AAAA,IACrD,uBAAuB,OAAO,KAAK,UAAU,KAAK,IAAI,CAAC;AAAA,EACzD;AACA,QAAM,UAAU,OAAO,QAAQ,OAAO,KAAK,OAAO;AAClD,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,KAAK,oBAAoB,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,WAAM,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EACpF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEO,SAAS,0BACd,KACAC,YACA,aACM;AACN,MAAI;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,UAAU;AAAA,IACZ;AAAA,IACA,OAAO,QAAQ;AACb,YAAM,WAAW;AAAA,QACf;AAAA,QACA;AAAA,QACA,iBAAiB,mBAAmBA,UAAS,CAAC;AAAA,QAC9C;AAAA,QACA,kBAAkB,YAAY,KAAK;AAAA,QACnC;AAAA,QACA,gBAAgB,WAAW;AAAA,QAC3B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,oBAAoB,WAAW;AAAA,QAC/B;AAAA,QACA,kBAAkB,WAAW;AAAA,MAC/B;AACA,aAAO;AAAA,QACL,UAAU;AAAA,UACR;AAAA,YACE,KAAK,IAAI,SAAS;AAAA,YAClB,UAAU;AAAA,YACV,MAAM,SAAS,KAAK,IAAI;AAAA,UAC1B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AA1OA,IASM,eAiFA,yBAkCA,uBAyCA;AArKN;AAAA;AAAA;AAAA;AAEA;AAOA,IAAM,gBAAmD,oBAAI,IAAI;AAAA,MAC/D;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,CAAC,QAAQ,EAAE,QAAQ,oCAAoC,OAAO,oBAAoB,CAAC;AAAA,MACnF;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAED,IAAM,0BAA0B;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAQX,IAAM,wBAAwB;AAAA,MAC5B;AAAA,MAGA;AAAA,IAEF,EAAE,KAAK,IAAI;AAmCX,IAAM,wBAAwB,CAAC,SAAS,UAAU,cAAc,UAAU;AAAA;AAAA;;;ACrK1E,SAAS,YAAAC,iBAAgB;AACzB,SAAS,QAAAC,aAAY;AA2GrB,SAAS,gBAAgB,QAAqC;AAC5D,QAAM,QAAwB,CAAC;AAC/B,aAAW,SAAS,OAAO,OAAO;AAChC,QAAI,OAAO,UAAU,YAAYC,gBAAe,IAAI,MAAM,IAAI,EAAG;AACjE,UAAM,KAAK;AAAA,MACT,KAAK,mBAAmB,MAAM,IAAI;AAAA,MAClC,MAAM,MAAM,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,MAAM,KAAK,MAAM,CAAC;AAAA,MAC7D,MAAM,GAAG,MAAM,IAAI;AAAA,MACnB,aAAa,MAAM;AAAA,IACrB,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAOO,SAAS,0BACd,KACAC,YACA,aACM;AACN,QAAM,MAAMF,MAAKE,YAAW,WAAW;AACvC,QAAM,YAAY,CAAC,GAAG,WAAW,GAAG,gBAAgB,WAAW,CAAC;AAChE,aAAW,QAAQ,WAAW;AAC5B,QAAI;AAAA,MACF,KAAK;AAAA,MACL,KAAK;AAAA,MACL,EAAE,aAAa,KAAK,aAAa,UAAU,gBAAgB;AAAA,MAC3D,OAAO,QAAQ;AACb,YAAI;AACJ,YAAI;AACF,iBAAO,MAAMH,UAASC,MAAK,KAAK,KAAK,IAAI,GAAG,MAAM;AAAA,QACpD,SAAS,KAAK;AACZ,gBAAM,IAAI,MAAM,oCAAoC,KAAK,IAAI,KAAK,KAAK,GAAG,KAAK;AAAA,YAC7E,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AACA,eAAO;AAAA,UACL,UAAU;AAAA,YACR;AAAA,cACE,KAAK,IAAI,SAAS;AAAA,cAClB,UAAU;AAAA,cACV;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,CAAC,oBAAoB,EAAE;AAC1C,aAAW,QAAQ,WAAW;AAC5B,eAAW,KAAK,OAAO,KAAK,IAAI,eAAU,KAAK,GAAG,MAAM;AACxD,eAAW,KAAK,KAAK,KAAK,WAAW,EAAE;AAAA,EACzC;AACA,QAAM,YAAY,WAAW,KAAK,IAAI;AAEtC,MAAI;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,UAAU;AAAA,IACZ;AAAA,IACA,OAAO,SAAS;AAAA,MACd,UAAU,CAAC,EAAE,KAAK,IAAI,SAAS,GAAG,UAAU,iBAA0B,MAAM,UAAU,CAAC;AAAA,IACzF;AAAA,EACF;AACF;AApLA,IAwBa;AAxBb;AAAA;AAAA;AAGA;AAqBO,IAAM,YAAyC;AAAA,MACpD;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,IACF;AAAA;AAAA;;;ACpGA,SAAS,SAASG,kBAAiB;AAqB5B,SAASC,kBAAiB,KAAgC;AAC/D,QAAM,QAAQC,gBAAe,KAAK,GAAG;AACrC,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,MAAM,CAAC,GAAG,SAAS,IAAI;AAAA,EAClC;AACA,QAAM,WAAW,MAAM,CAAC,KAAK;AAC7B,QAAM,UAAU,IAAI,MAAM,MAAM,CAAC,EAAE,MAAM;AACzC,MAAI,SAAS,KAAK,MAAM,IAAI;AAC1B,WAAO,EAAE,MAAM,CAAC,GAAG,QAAQ;AAAA,EAC7B;AACA,QAAM,SAASF,WAAU,QAAQ;AACjC,QAAM,OACJ,WAAW,QAAQ,OAAO,WAAW,WAAY,SAAqC,CAAC;AACzF,SAAO,EAAE,MAAM,QAAQ;AACzB;AAnCA,IAcME;AAdN,IAAAC,oBAAA;AAAA;AAAA;AAcA,IAAMD,kBAAiB;AAAA;AAAA;;;ACZhB,SAAS,iBAAiB,KAAqB;AACpD,SAAO,IACJ,QAAQ,qBAAqB,GAAG,EAChC,MAAM,KAAK,EACX,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,cAAc,IAAI,CAAC,CAAC,EACnD,KAAK,GAAG;AACb;AARA,IAAM;AAAN;AAAA;AAAA;AAAA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,OAAO,MAAM,OAAO,MAAM,CAAC;AAAA;AAAA;;;ACOnD,SAAS,SAAS,MAAc;AACrC,SAAO;AAAA,IACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC,EAAE,CAAC;AAAA,IACxE,mBAAmB;AAAA,EACrB;AACF;AAQO,SAAS,eAAe,UAAkB,MAAc;AAC7D,SAAO;AAAA,IACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,SAAS,CAAC;AAAA,IACnD,mBAAmB;AAAA,EACrB;AACF;AAQO,SAAS,UAAU,OAAyB;AACjD,QAAM,UAAU;AAAA,IACd,MAAM,MAAM;AAAA,IACZ,SAAS,MAAM;AAAA,IACf,SAAS,MAAM,WAAW,CAAC;AAAA,EAC7B;AACA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,OAAO,EAAE,CAAC;AAAA,IAClE,mBAAmB;AAAA,EACrB;AACF;AA5CA;AAAA;AAAA;AAAA;AAAA;;;ACAA,SAAS,YAAAE,iBAAgB;AACzB,SAAS,YAAAC,WAAU,QAAAC,aAAY;AAG/B,SAAS,KAAAC,UAAS;AAkDlB,SAAS,SAAS,GAAmB;AACnC,SAAOF,UAAS,CAAC,EAAE,QAAQ,SAAS,EAAE;AACxC;AAEA,eAAe,YAAYG,YAAmB,OAAwC;AACpF,MAAI;AACF,UAAM,MAAM,MAAMJ,UAASE,MAAKE,YAAW,YAAY,OAAO,UAAU,GAAG,MAAM;AACjF,WAAOC,kBAAiB,GAAG,EAAE;AAAA,EAC/B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,eAAe,WAAWD,YAAmB,OAAgC;AAC3E,MAAI;AACF,UAAM,MAAM,MAAMJ,UAASE,MAAKE,YAAW,YAAY,OAAO,WAAW,GAAG,MAAM;AAClF,WAAOC,kBAAiB,GAAG,EACxB,QAAQ,KAAK,EACb,QAAQ,kBAAkB,EAAE;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,MACpB,MACA,OACgD;AAChD,QAAM,EAAE,IAAI,WAAAD,YAAW,YAAY,IAAI;AACvC,QAAM,EAAE,OAAO,KAAK,IAAI;AAExB,QAAM,CAAC,IAAI,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,IACrC,YAAYA,YAAW,KAAK;AAAA,IAC5B,WAAWA,YAAW,KAAK;AAAA,EAC7B,CAAC;AAED,QAAM,SAAS,GACZ,QAAQ,yEAAyE,EACjF,IAAI,KAAK;AAEZ,QAAM,OAAO,GACV;AAAA,IACC;AAAA,EACF,EACC,IAAI,KAAK;AAEZ,QAAM,UAAU,GACb;AAAA,IACC;AAAA,EACF,EACC,IAAI,KAAK;AAEZ,QAAM,OAAO,GACV;AAAA,IACC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMF,EACC,IAAI,KAAK;AAEZ,QAAM,OAAO,GACV;AAAA,IACC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKF,EACC,IAAI,KAAK;AAEZ,QAAM,SAAS,GACZ,QAAQ,iFAAiF,EACzF,IAAI,KAAK;AAEZ,QAAM,aAAa,GAChB;AAAA,IACC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMF,EACC,IAAI,OAAO,KAAK;AAEnB,MAAI,WAAkE,CAAC;AACvE,MAAI,MAAM;AACR,UAAM,WAAW,iBAAiB,IAAI;AACtC,QAAI,UAAU;AACZ,iBACE,GACG;AAAA,QACC;AAAA;AAAA;AAAA;AAAA;AAAA,MAKF,EACC,IAAI,UAAU,KAAK,EACtB,IAAI,CAAC,SAAS;AAAA,QACd,MAAM,IAAI;AAAA,QACV,OAAO,IAAI;AAAA,QACX,OAAO,IAAI;AAAA,MACb,EAAE;AAAA,IACJ;AAAA,EACF;AAEA,QAAM,eAAuC,CAAC;AAC9C,aAAW,OAAO,OAAQ,cAAa,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK;AAEnE,QAAM,OAAkB;AAAA,IACtB;AAAA,IACA,YAAY,mBAAmBA,UAAS;AAAA,IACxC,OAAO,GAAG,SAAS;AAAA,IACnB,aAAa,GAAG,eAAe;AAAA,IAC/B,OAAO,OAAO,GAAG,UAAU,WAAW,GAAG,QAAQ;AAAA,IACjD,SAAS,GAAG,WAAW;AAAA,IACvB;AAAA,IACA,QAAQ;AAAA,IACR,aAAa,KAAK,IAAI,CAAC,OAAO;AAAA,MAC5B,MAAM,EAAE;AAAA,MACR,MAAM,SAAS,EAAE,IAAI;AAAA,MACrB,OAAO,EAAE;AAAA,MACT,SAAS,EAAE;AAAA,IACb,EAAE;AAAA,IACF,cAAc,UACV;AAAA,MACE,MAAM,QAAQ;AAAA,MACd,MAAM,SAAS,QAAQ,IAAI;AAAA,MAC3B,OAAO,QAAQ;AAAA,IACjB,IACA;AAAA,IACJ,UAAU,KAAK,IAAI,CAAC,MAAM,EAAE,GAAG;AAAA,IAC/B,WAAW,KAAK,IAAI,CAAC,OAAO;AAAA,MAC1B,MAAM,EAAE;AAAA,MACR,OAAO,EAAE;AAAA,MACT,SAAS,OAAO,EAAE,OAAO;AAAA,IAC3B,EAAE;AAAA,IACF,QAAQ,OAAO,IAAI,CAAC,OAAO;AAAA,MACzB,MAAM,EAAE;AAAA,MACR,WAAW,EAAE;AAAA,MACb,MAAM,EAAE,GAAG,MAAM,GAAG,EAAE;AAAA,IACxB,EAAE;AAAA,IACF;AAAA,IACA,aAAa,WAAW,IAAI,CAAC,OAAO;AAAA,MAClC,YAAY,EAAE;AAAA,MACd,WAAW,EAAE;AAAA,MACb,SAAS,EAAE;AAAA,IACb,EAAE;AAAA,EACJ;AAEA,SAAO,EAAE,UAAU,eAAe,MAAM,aAAa,IAAI,GAAG,KAAK;AACnE;AAEO,SAAS,eACd,GACA,QACA,MACQ;AACR,QAAM,QAAkB,CAAC;AAEzB,QAAM,aACJ,EAAE,UAAU,OACR,EAAE,cACA,SAAS,EAAE,KAAK,KAAK,EAAE,WAAW,MAClC,SAAS,EAAE,KAAK,KAClB;AACN,QAAM,SAAS,aAAa,GAAG,EAAE,KAAK,WAAM,UAAU,KAAK,EAAE;AAC7D,QAAM,KAAK,KAAK,MAAM,EAAE;AACxB,MAAI,EAAE,QAAS,OAAM,KAAK,EAAE,OAAO;AAEnC,QAAM,KAAK,iBAAiB,EAAE,UAAU,IAAI;AAE5C,MAAI,EAAE,QAAQ;AACZ,UAAM,KAAK,IAAI,aAAa,EAAE,MAAM;AAAA,EACtC;AAEA,MAAI,EAAE,YAAY,SAAS,GAAG;AAC5B,UAAM,KAAK,IAAI,qBAAqB;AACpC,eAAW,KAAK,EAAE,aAAa;AAC7B,YAAM,KAAK,KAAK,EAAE,IAAI,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE;AAAA,IACnD;AAAA,EACF;AAEA,MAAI,EAAE,cAAc;AAClB,UAAM,KAAK,IAAI,iBAAiB;AAChC,UAAM,KAAK,GAAG,EAAE,aAAa,IAAI,KAAK,EAAE,aAAa,KAAK,EAAE;AAAA,EAC9D;AAEA,QAAM,eAAe,OAAO,QAAQ,EAAE,MAAM;AAC5C,MAAI,aAAa,SAAS,GAAG;AAC3B,UAAM,KAAK,IAAI,UAAU;AACzB,UAAM,KAAK,aAAa,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,KAAK,CAAC;AAAA,EACnE;AAEA,QAAM,KAAK,IAAI,eAAe;AAC9B,QAAM,KAAK,UAAU,OAAO,MAAM,IAAIE,SAAQ,EAAE,KAAK,IAAI,CAAC,EAAE;AAC5D,QAAM,KAAK,aAAa,OAAO,SAAS,KAAK,IAAI,CAAC,EAAE;AACpD,QAAM,KAAK,SAAS,OAAO,KAAK,UAAU,KAAK,IAAI,CAAC,EAAE;AAEtD,MAAI,EAAE,SAAS,SAAS,GAAG;AACzB,UAAM,KAAK,IAAI,SAAS;AACxB,UAAM,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;AAAA,EAClC;AAEA,MAAI,EAAE,UAAU,SAAS,GAAG;AAC1B,UAAM,KAAK,IAAI,SAAS;AACxB,eAAW,KAAK,EAAE,WAAW;AAC3B,YAAM,KAAK,KAAK,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,WAAW;AAAA,IAC3D;AAAA,EACF;AAEA,MAAI,EAAE,OAAO,SAAS,GAAG;AACvB,UAAM,KAAK,IAAI,WAAW;AAC1B,eAAW,KAAK,EAAE,QAAQ;AACxB,YAAM,KAAK,MAAM,EAAE,IAAI,KAAK,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE;AAAA,IAC/D;AAAA,EACF;AAEA,MAAI,EAAE,SAAS,SAAS,GAAG;AACzB,UAAM,KAAK,IAAI,uBAAuB,IAAI,IAAI;AAC9C,eAAW,KAAK,EAAE,UAAU;AAC1B,YAAM,KAAK,KAAK,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,QAAQ,CAAC,CAAC,GAAG;AAAA,IAC5D;AAAA,EACF;AAEA,MAAI,EAAE,YAAY,SAAS,GAAG;AAC5B,UAAM,KAAK,IAAI,gBAAgB;AAC/B,eAAW,KAAK,EAAE,aAAa;AAC7B,YAAM,KAAK,KAAK,EAAE,UAAU,IAAI,SAAS,EAAE,SAAS,CAAC,WAAM,SAAS,EAAE,OAAO,CAAC,EAAE;AAAA,IAClF;AAAA,EACF;AAEA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,eAAsB,YAAY,MAAiB,OAAmB;AACpE,MAAI,CAAC,OAAO,OAAO,KAAK,YAAY,QAAQ,MAAM,KAAK,GAAG;AACxD,UAAM,QAAQ,OAAO,KAAK,KAAK,YAAY,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI;AACnE,WAAO,UAAU;AAAA,MACf,MAAM;AAAA,MACN,SAAS,kBAAkB,MAAM,KAAK,oBAAoB,KAAK;AAAA,IACjE,CAAC;AAAA,EACH;AACA,MAAI;AACF,UAAM,EAAE,UAAU,KAAK,IAAI,MAAM,MAAM,MAAM,KAAK;AAClD,WAAO,eAAe,UAAU,IAA0C;AAAA,EAC5E,SAAS,KAAK;AACZ,WAAO,UAAU;AAAA,MACf,MAAM;AAAA,MACN,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IAC1D,CAAC;AAAA,EACH;AACF;AA5TA,IAUa;AAVb;AAAA;AAAA;AAGA;AAEA,IAAAC;AACA;AACA;AACA;AAEO,IAAM,mBAAmBJ,GAAE,OAAO;AAAA,MACvC,OAAOA,GACJ,OAAO,EACP,IAAI,CAAC,EACL,SAAS,kEAAkE;AAAA,MAC9E,MAAMA,GACH,OAAO,EACP,SAAS,EACT,SAAS,2EAA2E;AAAA,IACzF,CAAC;AAAA;AAAA;;;AClBD,SAAS,KAAAK,UAAS;AA6CX,SAAS,OAAO,MAAkB,OAAiD;AACxF,QAAM,WAAW,iBAAiB,MAAM,KAAK;AAC7C,MAAI,CAAC,SAAU,QAAO,EAAE,SAAS,CAAC,EAAE;AAEpC,MAAI,MAAM;AAAA;AAAA;AAAA;AAIV,QAAM,SAAiC,CAAC,QAAQ;AAEhD,MAAI,MAAM,OAAO;AACf,WAAO;AACP,WAAO,KAAK,MAAM,KAAK;AAAA,EACzB;AACA,MAAI,MAAM,MAAM;AACd,WAAO;AACP,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB;AACA,SAAO;AACP,SAAO,KAAK,MAAM,KAAK;AAEvB,QAAM,OAAO,KAAK,GAAG,QAAQ,GAAG,EAAE,IAAI,GAAG,MAAM;AAS/C,SAAO;AAAA,IACL,SAAS,KAAK,IAAI,CAAC,OAAO;AAAA,MACxB,MAAM,EAAE;AAAA,MACR,OAAO,EAAE;AAAA,MACT,MAAM,EAAE;AAAA,MACR,SAAS,EAAE;AAAA,MACX,OAAO,EAAE;AAAA,MACT,OAAO,EAAE;AAAA,IACX,EAAE;AAAA,EACJ;AACF;AAEO,SAAS,aAAa,MAAkB,OAAoB;AACjE,MAAI;AACF,WAAO,SAAS,OAAO,MAAM,KAAK,CAAC;AAAA,EACrC,SAAS,KAAK;AACZ,WAAO,UAAU;AAAA,MACf,MAAM;AAAA,MACN,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IAC1D,CAAC;AAAA,EACH;AACF;AAjGA,IAKa;AALb;AAAA;AAAA;AAEA;AACA;AAEO,IAAM,oBAAoBA,GAAE,OAAO;AAAA,MACxC,OAAOA,GACJ,OAAO,EACP,IAAI,CAAC,EACL;AAAA,QACC;AAAA,MACF;AAAA,MACF,OAAOA,GACJ,OAAO,EACP,SAAS,EACT,SAAS,mEAAmE;AAAA,MAC/E,MAAMA,GACH,OAAO,EACP,SAAS,EACT;AAAA,QACC;AAAA,MACF;AAAA,MACF,OAAOA,GACJ,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,EAAE,EACN,QAAQ,CAAC,EACT,SAAS,wDAAwD;AAAA,IACtE,CAAC;AAAA;AAAA;;;AC5BD,SAAS,iBAAiB;AAiBnB,SAAS,YAAY,MAAkC;AAC5D,QAAM,EAAE,MAAM,SAAS,WAAAC,YAAW,IAAI,QAAQ,YAAY,IAAI;AAE9D,QAAM,MAAM,IAAI,UAAU,EAAE,MAAM,QAAQ,GAAG,EAAE,cAAc,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC,EAAE,EAAE,CAAC;AAE3F,MAAI;AAAA,IACF;AAAA,IACA;AAAA,IACA,iBAAiB;AAAA,IACjB,OAAO,UAAU;AACf,aAAO,MAAM,EAAE,MAAM,SAAS,MAAM,GAAG,WAAW;AAClD,aAAO,YAAY,EAAE,IAAI,WAAAA,YAAW,YAAY,GAAG,KAAK;AAAA,IAC1D;AAAA,EACF;AAEA,MAAI;AAAA,IACF;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,IAClB,OAAO,UAAU;AACf,aAAO,MAAM,EAAE,MAAM,UAAU,MAAM,GAAG,WAAW;AACnD,aAAO,aAAa,EAAE,GAAG,GAAG,KAAK;AAAA,IACnC;AAAA,EACF;AAEA,4BAA0B,KAAKA,YAAW,WAAW;AACrD,4BAA0B,KAAKA,YAAW,WAAW;AAErD,SAAO;AACT;AA/CA;AAAA;AAAA;AAGA;AACA;AACA;AACA;AAAA;AAAA;;;ACNA;AAAA;AAAA;AAAA;AAAA,SAAS,4BAA4B;AAQrC,eAAsB,iBAAgC;AACpD,OAAK,cAAc;AAEnB,QAAM,SAAS,WAAW;AAC1B,OAAK,iBAAiB,EAAE,OAAO,OAAO,WAAW,OAAO,OAAO,SAAS,CAAC;AAEzE,QAAM,cAAc,MAAMC,iBAAgB,OAAO,SAAS;AAC1D,OAAK,uBAAuB;AAAA,IAC1B,QAAQ,OAAO,KAAK,YAAY,MAAM,EAAE;AAAA,IACxC,OAAO,YAAY,MAAM;AAAA,IACzB,UAAU,YAAY,SAAS;AAAA,EACjC,CAAC;AAED,QAAM,SAAS,aAAa,OAAO,UAAU,OAAO,UAAU;AAC9D,SAAO;AAAA,IACL,EAAE,OAAO,OAAO,WAAW,YAAY,OAAO,YAAY,eAAe,OAAO,cAAc;AAAA,IAC9F;AAAA,EACF;AAEA,QAAM,KAAK,eAAe,OAAO,SAAS;AAC1C,OAAK,iBAAiB;AAEtB,QAAM,MAAM,YAAY;AAAA,IACtB,MAAM,OAAO;AAAA,IACb,SAAS,OAAO;AAAA,IAChB,WAAW,OAAO;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,OAAK,cAAc;AAEnB,QAAM,WAAW,OAAO,WAA2B;AACjD,WAAO,KAAK,EAAE,OAAO,GAAG,eAAe;AACvC,SAAK,iBAAiB,EAAE,OAAO,CAAC;AAChC,QAAI;AACF,YAAM,IAAI,MAAM;AAChB,SAAG,MAAM;AAAA,IACX,SAAS,KAAK;AACZ,aAAO,MAAM,EAAE,IAAI,GAAG,uBAAuB;AAAA,IAC/C;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,UAAQ,KAAK,UAAU,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;AAC9C,UAAQ,KAAK,WAAW,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;AAE/C,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,IAAI,QAAQ,SAAS;AAC3B,SAAO,KAAK,gBAAgB;AAC5B,OAAK,kCAAkC;AACzC;AA1DA;AAAA;AAAA;AACA,IAAAC;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;;;ACLA,SAAS,aAAAC,kBAAiB;AAE1B,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAad,IAAM,EAAE,aAAa,OAAO,IAAIA,WAAU;AAAA,EACxC,MAAM,QAAQ,KAAK,MAAM,CAAC;AAAA,EAC1B,kBAAkB;AAAA,EAClB,QAAQ;AAAA,EACR,SAAS;AAAA,IACP,SAAS,EAAE,MAAM,WAAW,OAAO,IAAI;AAAA,IACvC,MAAM,EAAE,MAAM,WAAW,OAAO,IAAI;AAAA,EACtC;AACF,CAAC;AAED,IAAM,UAAU,OAAO,UAAU,cAAc,OAAO,OAAO,WAAW,YAAY,CAAC;AAErF,SAAS,eAAe,iBAA+B;AACrD,QAAM,MAAM,YAAY,eAAe;AACvC,MAAI,KAAK;AACP,YAAQ,IAAI,aAAa;AAAA,EAC3B;AACF;AAEA,eAAe,MAAqB;AAClC,UAAQ,SAAS;AAAA,IACf,KAAK,QAAQ;AACX,YAAM,EAAE,gBAAAC,gBAAe,IAAI,MAAM;AACjC,YAAMA,gBAAe;AACrB;AAAA,IACF;AAAA,IACA,KAAK,YAAY;AACf,qBAAe,CAAC;AAChB,YAAM,EAAE,aAAAC,aAAY,IAAI,MAAM;AAC9B,YAAMA,aAAY;AAClB;AAAA,IACF;AAAA,IACA,KAAK,OAAO;AACV,qBAAe,CAAC;AAChB,YAAM,EAAE,gBAAAC,gBAAe,IAAI,MAAM;AACjC,YAAMA,gBAAe;AACrB;AAAA,IACF;AAAA,IACA,KAAK,UAAU;AACb,qBAAe,CAAC;AAChB,YAAM,EAAE,WAAAC,WAAU,IAAI,MAAM;AAC5B,YAAMA,WAAU;AAChB;AAAA,IACF;AAAA,IACA,KAAK,MAAM;AACT,YAAM,MAAM,YAAY,CAAC;AACzB,UAAI,QAAQ,SAAS;AACnB,uBAAe,CAAC;AAChB,cAAM,EAAE,YAAAC,YAAW,IAAI,MAAM;AAC7B,cAAMA,YAAW;AAAA,MACnB,OAAO;AACL,gBAAQ,MAAM,MAAM,0BAA0B,GAAG,KAAK,oCAAoC;AAC1F,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,KAAK,MAAM;AACT,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,SAAS;AAC/C,YAAM,EAAE,MAAAC,QAAM,SAAAC,SAAQ,IAAI,MAAM,OAAO,WAAW;AAClD,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,UAAU;AACjD,YAAM,SAASA,SAAQA,SAAQ,cAAc,YAAY,GAAG,CAAC,CAAC;AAC9D,YAAM,MAAM,KAAK,MAAM,aAAaD,OAAK,QAAQ,cAAc,GAAG,MAAM,CAAC;AAGzE,cAAQ,IAAI,IAAI,OAAO;AACvB;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,QAAW;AACd,cAAQ,IAAI,KAAK;AACjB,UAAI,YAAY,OAAW,SAAQ,KAAK,CAAC;AACzC;AAAA,IACF;AAAA,IACA,SAAS;AACP,cAAQ,MAAM,oBAAoB,OAAO;AAAA;AAAA,EAAO,KAAK,EAAE;AACvD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF;AAEA,IAAI,EAAE,MAAM,CAAC,QAAQ;AACnB,UAAQ,MAAM,eAAe,eAAe,QAAS,IAAI,SAAS,IAAI,UAAW,GAAG;AACpF,UAAQ,KAAK,CAAC;AAChB,CAAC;",
6
+ "names": ["vaultRoot", "join", "vaultRoot", "createHash", "readFile", "join", "z", "readFile", "join", "basename", "dirname", "join", "positionals", "command", "z", "EnvSchema", "init_config", "mkdirSync", "dirname", "vaultRoot", "mkdirSync", "homedir", "join", "readFile", "join", "parse", "z", "kindName", "loadVaultConfig", "vaultRoot", "VaultConfigSchema", "ScopeSchema", "KindEntrySchema", "BUILT_IN_KINDS", "kindName", "vaultRoot", "readFile", "join", "BUILT_IN_KINDS", "vaultRoot", "parseYaml", "parseFrontmatter", "FRONTMATTER_RE", "init_frontmatter", "readFile", "basename", "join", "z", "vaultRoot", "parseFrontmatter", "kindName", "init_frontmatter", "z", "vaultRoot", "loadVaultConfig", "init_config", "parseArgs", "runSyncCommand", "runValidate", "startMcpServer", "runConfig", "runDbReset", "join", "dirname"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bartolli/kmd",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Knowledge-markdown CLI + MCP server. One binary for vault sync, validate, and the wiki-mcp agent tools.",
5
5
  "license": "MIT",
6
6
  "author": "Angel Bartolli <bartolli@gmail.com>",