@wiki0/core 0.0.3 → 0.0.4

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/README.md CHANGED
@@ -8,9 +8,14 @@ Core wiki0 primitives for local-first Markdown wiki memory.
8
8
  - Obsidian-style `[[WikiLinks]]` parsing.
9
9
  - Page create/read/append/frontmatter operations.
10
10
  - SQLite indexing and FTS search.
11
- - Context snippets with `wiki/...` citations.
11
+ - Chunk-level context snippets with `wiki/path.md:line-line`
12
+ citations.
13
+ - Direct indexed chunk lookup for known `path:line` targets.
12
14
  - Backlinks, graph data, lint results, review queues, and structured
13
- facts.
15
+ facts with optional source-line provenance.
16
+ - Stale-index warnings in context responses.
17
+ - Lightweight topic threads and operation logs for agent workflows.
18
+ - Frontmatter-aware chunk ranking using priority, status, and tags.
14
19
  - Wiki-building workflow planning for agents that need a deterministic
15
20
  source-to-wiki recipe.
16
21
 
@@ -18,31 +23,41 @@ Core wiki0 primitives for local-first Markdown wiki memory.
18
23
 
19
24
  ```ts
20
25
  import {
21
- bootstrap_wiki,
22
- create_page,
23
- index_status,
24
- index_wiki,
25
- search_wiki,
26
- get_wiki_context,
27
- lint_wiki,
28
- plan_wiki,
29
- } from "@wiki0/core";
30
-
31
- create_page("projects/wiki0", "Local-first [[topics/memory]].", {
32
- root: ".",
26
+ bootstrap_wiki,
27
+ create_page,
28
+ index_status,
29
+ index_wiki,
30
+ search_wiki,
31
+ get_wiki_context,
32
+ lint_wiki,
33
+ plan_wiki,
34
+ } from '@wiki0/core';
35
+
36
+ create_page('projects/wiki0', 'Local-first [[topics/memory]].', {
37
+ root: '.',
33
38
  });
34
- index_wiki(".");
35
- console.log(index_status("."));
36
- console.log(search_wiki("memory", ".", 10));
37
- console.log(get_wiki_context("what is wiki0?", ".", 5).markdown);
38
- console.log(lint_wiki("."));
39
- console.log(plan_wiki({ sourceType: "codebase", scope: "current repo" }));
40
- console.log(bootstrap_wiki({ root: ".", sourceType: "docs" }));
39
+ index_wiki('.');
40
+ console.log(index_status('.'));
41
+ console.log(search_wiki('memory', '.', 10));
42
+ console.log(get_wiki_context('what is wiki0?', '.', 5).markdown);
43
+ console.log(lint_wiki('.'));
44
+ console.log(
45
+ plan_wiki({ source_type: 'codebase', scope: 'current repo' }),
46
+ );
47
+ console.log(
48
+ bootstrap_wiki({
49
+ root: '.',
50
+ source_type: 'docs',
51
+ sources: ['docs/guide.md'],
52
+ ingest_sources: true,
53
+ }),
54
+ );
41
55
  ```
42
56
 
43
57
  ## Storage model
44
58
 
45
59
  Markdown files under `wiki/` are canonical. The `.wiki0/wiki0.sqlite`
46
60
  database is a rebuildable cache for search, backlinks, graph data, and
47
- facts. `index_status` reports indexed-at time, schema version, and
48
- stale reasons when Markdown has changed since the last rebuild.
61
+ facts. `index_status` reports indexed-at time, schema/package
62
+ versions, and stale reasons when Markdown or index metadata has
63
+ changed since the last rebuild.
@@ -0,0 +1,9 @@
1
+ import type { WikiEvent } from './types.js';
2
+ export declare function log_wiki_event(options: {
3
+ root?: string;
4
+ operation: string;
5
+ summary: string;
6
+ target?: string;
7
+ details?: unknown;
8
+ }): WikiEvent;
9
+ export declare function list_wiki_events(root?: string, limit?: number): WikiEvent[];
package/dist/events.js ADDED
@@ -0,0 +1,56 @@
1
+ import { open_wiki_database } from './database.js';
2
+ import { resolve_wiki_root } from './paths.js';
3
+ export function log_wiki_event(options) {
4
+ const wiki_root = resolve_wiki_root(options.root);
5
+ const db = open_wiki_database(wiki_root);
6
+ ensure_events_table(db);
7
+ const result = db
8
+ .prepare(`INSERT INTO wiki_events (operation, summary, target, details)
9
+ VALUES (?, ?, ?, ?)`)
10
+ .run(options.operation, options.summary, options.target ?? null, options.details === undefined
11
+ ? null
12
+ : JSON.stringify(options.details));
13
+ const event = select_event_by_id(db, Number(result.lastInsertRowid));
14
+ db.close();
15
+ return event;
16
+ }
17
+ export function list_wiki_events(root = '.', limit = 50) {
18
+ const db = open_wiki_database(root);
19
+ ensure_events_table(db);
20
+ const rows = db
21
+ .prepare(`SELECT id, operation, summary, target, details, created_at
22
+ FROM wiki_events
23
+ ORDER BY id DESC
24
+ LIMIT ?`)
25
+ .all(limit);
26
+ db.close();
27
+ return rows.map(event_from_row);
28
+ }
29
+ function select_event_by_id(db, id) {
30
+ const row = db
31
+ .prepare(`SELECT id, operation, summary, target, details, created_at
32
+ FROM wiki_events WHERE id = ?`)
33
+ .get(id);
34
+ return event_from_row(row);
35
+ }
36
+ function event_from_row(row) {
37
+ return {
38
+ id: Number(row.id),
39
+ operation: String(row.operation),
40
+ summary: String(row.summary),
41
+ target: row.target === null ? null : String(row.target),
42
+ details: row.details === null ? null : String(row.details),
43
+ created_at: String(row.created_at),
44
+ };
45
+ }
46
+ function ensure_events_table(db) {
47
+ db.exec(`CREATE TABLE IF NOT EXISTS wiki_events (
48
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
49
+ operation TEXT NOT NULL,
50
+ summary TEXT NOT NULL,
51
+ target TEXT,
52
+ details TEXT,
53
+ created_at TEXT DEFAULT (datetime('now'))
54
+ )`);
55
+ }
56
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAqB,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAG/C,MAAM,UAAU,cAAc,CAAC,OAM9B;IACA,MAAM,SAAS,GAAG,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACzC,mBAAmB,CAAC,EAAE,CAAC,CAAC;IACxB,MAAM,MAAM,GAAG,EAAE;SACf,OAAO,CACP;uBACoB,CACpB;SACA,GAAG,CACH,OAAO,CAAC,SAAS,EACjB,OAAO,CAAC,OAAO,EACf,OAAO,CAAC,MAAM,IAAI,IAAI,EACtB,OAAO,CAAC,OAAO,KAAK,SAAS;QAC5B,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAClC,CAAC;IACH,MAAM,KAAK,GAAG,kBAAkB,CAC/B,EAAE,EACF,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAC9B,CAAC;IACF,EAAE,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC/B,IAAI,GAAG,GAAG,EACV,KAAK,GAAG,EAAE;IAEV,MAAM,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACpC,mBAAmB,CAAC,EAAE,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,EAAE;SACb,OAAO,CACP;;;WAGQ,CACR;SACA,GAAG,CAAC,KAAK,CAAqC,CAAC;IACjD,EAAE,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,kBAAkB,CAAC,EAAgB,EAAE,EAAU;IACvD,MAAM,GAAG,GAAG,EAAE;SACZ,OAAO,CACP;iCAC8B,CAC9B;SACA,GAAG,CAAC,EAAE,CAAmC,CAAC;IAC5C,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,cAAc,CACtB,GAAmC;IAEnC,OAAO;QACN,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;QAChC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAC5B,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;QACvD,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAC1D,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;KAClC,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,EAAgB;IAC5C,EAAE,CAAC,IAAI,CAAC;;;;;;;GAON,CAAC,CAAC;AACL,CAAC"}
package/dist/facts.js CHANGED
@@ -1,43 +1,105 @@
1
1
  import { open_wiki_database } from './database.js';
2
+ import { log_wiki_event } from './events.js';
2
3
  import { resolve_page_path } from './pages.js';
3
4
  import { resolve_wiki_root } from './paths.js';
5
+ import { show_wiki_chunk } from './search.js';
4
6
  export function add_fact(fact) {
5
7
  const wiki_root = resolve_wiki_root(fact.root);
6
8
  const db = open_wiki_database(wiki_root);
9
+ ensure_fact_provenance_columns(db);
10
+ const source_chunk = fact.source
11
+ ? show_wiki_chunk(fact.source, wiki_root)
12
+ : null;
7
13
  const page_path = fact.page
8
14
  ? resolve_page_path(fact.page, wiki_root)
9
- : null;
15
+ : (source_chunk?.path ?? null);
10
16
  const page = page_path
11
17
  ? db
12
18
  .prepare('SELECT id FROM pages WHERE path = ?')
13
19
  .get(page_path)
14
20
  : undefined;
15
21
  const result = db
16
- .prepare(`INSERT INTO facts (page_id, category, summary, body, confidence)
17
- VALUES (?, ?, ?, ?, ?)`)
18
- .run(page?.id ?? null, fact.category, fact.summary, fact.body ?? null, fact.confidence ?? 'unknown');
19
- const inserted = db
20
- .prepare(`SELECT facts.id, pages.path AS pagePath, facts.category,
21
- facts.summary, facts.body, facts.confidence, facts.created_at AS createdAt
22
- FROM facts
23
- LEFT JOIN pages ON pages.id = facts.page_id
24
- WHERE facts.id = ?`)
25
- .get(result.lastInsertRowid);
22
+ .prepare(`INSERT INTO facts (
23
+ page_id, category, summary, body, confidence,
24
+ source_path, source_heading, source_start_line, source_end_line, source_quote
25
+ )
26
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
27
+ .run(page?.id ?? null, fact.category, fact.summary, fact.body ?? null, fact.confidence ?? 'unknown', source_chunk?.path ?? null, source_chunk?.heading ?? null, source_chunk?.start_line ?? null, source_chunk?.end_line ?? null, fact.source_quote ?? source_quote(source_chunk));
28
+ const inserted = select_fact_by_id(db, Number(result.lastInsertRowid));
26
29
  db.close();
30
+ log_wiki_event({
31
+ root: wiki_root,
32
+ operation: 'add_fact',
33
+ summary: fact.summary,
34
+ target: page_path ?? source_chunk?.path ?? undefined,
35
+ details: {
36
+ category: fact.category,
37
+ confidence: inserted.confidence,
38
+ },
39
+ });
27
40
  return inserted;
28
41
  }
29
42
  export function list_facts(root = '.', category) {
30
43
  const db = open_wiki_database(root);
31
- const sql = `SELECT facts.id, pages.path AS pagePath, facts.category,
32
- facts.summary, facts.body, facts.confidence, facts.created_at AS createdAt
33
- FROM facts
34
- LEFT JOIN pages ON pages.id = facts.page_id
44
+ ensure_fact_provenance_columns(db);
45
+ const sql = `${fact_select_sql}
35
46
  ${category ? 'WHERE facts.category = ?' : ''}
36
47
  ORDER BY facts.created_at DESC, facts.id DESC`;
37
48
  const rows = category
38
49
  ? db.prepare(sql).all(category)
39
50
  : db.prepare(sql).all();
40
51
  db.close();
41
- return rows;
52
+ return rows.map(fact_from_row);
53
+ }
54
+ const fact_select_sql = `SELECT facts.id, pages.path AS page_path, facts.category,
55
+ facts.summary, facts.body, facts.confidence,
56
+ facts.source_path, facts.source_heading, facts.source_start_line,
57
+ facts.source_end_line, facts.source_quote, facts.created_at AS created_at
58
+ FROM facts
59
+ LEFT JOIN pages ON pages.id = facts.page_id`;
60
+ function select_fact_by_id(db, id) {
61
+ const row = db
62
+ .prepare(`${fact_select_sql} WHERE facts.id = ?`)
63
+ .get(id);
64
+ return fact_from_row(row);
65
+ }
66
+ function fact_from_row(row) {
67
+ return {
68
+ id: Number(row.id),
69
+ page_path: row.page_path === null ? null : String(row.page_path),
70
+ category: String(row.category),
71
+ summary: String(row.summary),
72
+ body: row.body === null ? null : String(row.body),
73
+ confidence: String(row.confidence),
74
+ source_path: row.source_path === null ? null : String(row.source_path),
75
+ source_heading: row.source_heading === null ? null : String(row.source_heading),
76
+ source_start_line: row.source_start_line === null
77
+ ? null
78
+ : Number(row.source_start_line),
79
+ source_end_line: row.source_end_line === null
80
+ ? null
81
+ : Number(row.source_end_line),
82
+ source_quote: row.source_quote === null ? null : String(row.source_quote),
83
+ created_at: String(row.created_at),
84
+ };
85
+ }
86
+ function source_quote(source_chunk) {
87
+ if (!source_chunk)
88
+ return null;
89
+ return source_chunk.body.slice(0, 1000);
90
+ }
91
+ function ensure_fact_provenance_columns(db) {
92
+ const columns = new Set(db.prepare('PRAGMA table_info(facts)').all().map((column) => column.name));
93
+ const migrations = {
94
+ source_path: 'ALTER TABLE facts ADD COLUMN source_path TEXT',
95
+ source_heading: 'ALTER TABLE facts ADD COLUMN source_heading TEXT',
96
+ source_start_line: 'ALTER TABLE facts ADD COLUMN source_start_line INTEGER',
97
+ source_end_line: 'ALTER TABLE facts ADD COLUMN source_end_line INTEGER',
98
+ source_quote: 'ALTER TABLE facts ADD COLUMN source_quote TEXT',
99
+ };
100
+ for (const [column_name, sql] of Object.entries(migrations)) {
101
+ if (!columns.has(column_name))
102
+ db.exec(sql);
103
+ }
42
104
  }
43
105
  //# sourceMappingURL=facts.js.map
package/dist/facts.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"facts.js","sourceRoot":"","sources":["../src/facts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAG/C,MAAM,UAAU,QAAQ,CAAC,IAAsB;IAC9C,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI;QAC1B,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QACzC,CAAC,CAAC,IAAI,CAAC;IACR,MAAM,IAAI,GAAG,SAAS;QACrB,CAAC,CAAE,EAAE;aACF,OAAO,CAAC,qCAAqC,CAAC;aAC9C,GAAG,CAAC,SAAS,CAAgC;QAChD,CAAC,CAAC,SAAS,CAAC;IAEb,MAAM,MAAM,GAAG,EAAE;SACf,OAAO,CACP;0BACuB,CACvB;SACA,GAAG,CACH,IAAI,EAAE,EAAE,IAAI,IAAI,EAChB,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,IAAI,IAAI,IAAI,EACjB,IAAI,CAAC,UAAU,IAAI,SAAS,CAC5B,CAAC;IACH,MAAM,QAAQ,GAAG,EAAE;SACjB,OAAO,CACP;;;;sBAImB,CACnB;SACA,GAAG,CAAC,MAAM,CAAC,eAAe,CAAS,CAAC;IACtC,EAAE,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAI,GAAG,GAAG,EAAE,QAAiB;IACvD,MAAM,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG;;;;IAIT,QAAQ,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,EAAE;gDACE,CAAC;IAChD,MAAM,IAAI,GAAG,QAAQ;QACpB,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC/B,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACzB,EAAE,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,IAAc,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"facts.js","sourceRoot":"","sources":["../src/facts.ts"],"names":[],"mappings":"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"}
package/dist/graph.js CHANGED
@@ -6,11 +6,11 @@ export function graph_wiki(root = '.') {
6
6
  const nodes = db
7
7
  .prepare('SELECT path, title FROM pages ORDER BY path')
8
8
  .all();
9
- const edges = db
9
+ const edge_rows = db
10
10
  .prepare(`SELECT pages.path AS "from",
11
11
  COALESCE(page_links.to_path, page_links.target) AS "to",
12
12
  page_links.target,
13
- page_links.raw_text AS rawText,
13
+ page_links.raw_text AS raw_text,
14
14
  page_links.alias,
15
15
  page_links.embed,
16
16
  page_links.status
@@ -19,6 +19,7 @@ export function graph_wiki(root = '.') {
19
19
  ORDER BY pages.path, page_links.target`)
20
20
  .all();
21
21
  db.close();
22
+ const edges = edge_rows.map(graph_edge_from_row);
22
23
  return {
23
24
  root: wiki_root,
24
25
  nodes,
@@ -31,4 +32,15 @@ export function graph_wiki(root = '.') {
31
32
  })),
32
33
  };
33
34
  }
35
+ function graph_edge_from_row(row) {
36
+ return {
37
+ from: String(row.from),
38
+ to: String(row.to),
39
+ target: String(row.target),
40
+ raw_text: String(row.raw_text),
41
+ alias: row.alias === null ? null : String(row.alias),
42
+ embed: Boolean(row.embed),
43
+ status: row.status === 'resolved' ? 'resolved' : 'unresolved',
44
+ };
45
+ }
34
46
  //# sourceMappingURL=graph.js.map
package/dist/graph.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGrE,MAAM,UAAU,UAAU,CAAC,IAAI,GAAG,GAAG;IACpC,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,EAAE;SACd,OAAO,CAAC,6CAA6C,CAAC;SACtD,GAAG,EAAiB,CAAC;IACvB,MAAM,KAAK,GAAG,EAAE;SACd,OAAO,CACP;;;;;;;;;0CASuC,CACvC;SACA,GAAG,EAA4B,CAAC;IAClC,EAAE,CAAC,KAAK,EAAE,CAAC;IAEX,OAAO;QACN,IAAI,EAAE,SAAS;QACf,KAAK;QACL,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC3B,GAAG,IAAI;YACP,EAAE,EACD,IAAI,CAAC,MAAM,KAAK,UAAU;gBACzB,CAAC,CAAC,IAAI,CAAC,EAAE;gBACT,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC;YACrC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;SAC1B,CAAC,CAAC;KACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGrE,MAAM,UAAU,UAAU,CAAC,IAAI,GAAG,GAAG;IACpC,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,EAAE;SACd,OAAO,CAAC,6CAA6C,CAAC;SACtD,GAAG,EAAiB,CAAC;IACvB,MAAM,SAAS,GAAG,EAAE;SAClB,OAAO,CACP;;;;;;;;;0CASuC,CACvC;SACA,GAAG,EAAsC,CAAC;IAC5C,EAAE,CAAC,KAAK,EAAE,CAAC;IAEX,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACjD,OAAO;QACN,IAAI,EAAE,SAAS;QACf,KAAK;QACL,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC3B,GAAG,IAAI;YACP,EAAE,EACD,IAAI,CAAC,MAAM,KAAK,UAAU;gBACzB,CAAC,CAAC,IAAI,CAAC,EAAE;gBACT,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC;YACrC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;SAC1B,CAAC,CAAC;KACH,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAC3B,GAAmC;IAEnC,OAAO;QACN,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;QACtB,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;QAC1B,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC9B,KAAK,EAAE,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;QACpD,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QACzB,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY;KAC7D,CAAC;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,13 +1,15 @@
1
1
  export { open_wiki_database, wiki_db_path } from './database.js';
2
+ export { list_wiki_events, log_wiki_event } from './events.js';
2
3
  export { add_fact, list_facts } from './facts.js';
3
4
  export { graph_wiki } from './graph.js';
4
- export { current_index_schema_version, index_status, index_wiki, } from './indexer.js';
5
+ export { current_index_package_version, current_index_schema_version, index_status, index_wiki, } from './indexer.js';
5
6
  export { lint_wiki } from './lint.js';
6
7
  export { page_title_from_markdown, parse_frontmatter, parse_markdown, parse_wikilinks, serialize_frontmatter, strip_fenced_code_blocks, strip_inline_code, } from './markdown.js';
7
8
  export { append_page, create_page, list_markdown_page_paths, read_page, resolve_page_path, set_page_frontmatter, } from './pages.js';
8
9
  export { display_page_title, page_file_path, page_relative_path, resolve_wiki_root, slugify_title, wikilink_target_path, } from './paths.js';
9
10
  export { review_wiki } from './review.js';
10
11
  export { schema_sql } from './schema.js';
11
- export { backlinks_for_page, format_context_markdown, get_wiki_context, search_wiki, } from './search.js';
12
+ export { backlinks_for_page, format_context_markdown, get_wiki_context, search_wiki, search_wiki_chunks, show_wiki_chunk, } from './search.js';
13
+ export { list_topic_threads } from './topics.js';
12
14
  export type * from './types.js';
13
15
  export { bootstrap_wiki, plan_wiki, wiki_building_workflow_markdown, } from './workflow.js';
package/dist/index.js CHANGED
@@ -1,13 +1,15 @@
1
1
  export { open_wiki_database, wiki_db_path } from './database.js';
2
+ export { list_wiki_events, log_wiki_event } from './events.js';
2
3
  export { add_fact, list_facts } from './facts.js';
3
4
  export { graph_wiki } from './graph.js';
4
- export { current_index_schema_version, index_status, index_wiki, } from './indexer.js';
5
+ export { current_index_package_version, current_index_schema_version, index_status, index_wiki, } from './indexer.js';
5
6
  export { lint_wiki } from './lint.js';
6
7
  export { page_title_from_markdown, parse_frontmatter, parse_markdown, parse_wikilinks, serialize_frontmatter, strip_fenced_code_blocks, strip_inline_code, } from './markdown.js';
7
8
  export { append_page, create_page, list_markdown_page_paths, read_page, resolve_page_path, set_page_frontmatter, } from './pages.js';
8
9
  export { display_page_title, page_file_path, page_relative_path, resolve_wiki_root, slugify_title, wikilink_target_path, } from './paths.js';
9
10
  export { review_wiki } from './review.js';
10
11
  export { schema_sql } from './schema.js';
11
- export { backlinks_for_page, format_context_markdown, get_wiki_context, search_wiki, } from './search.js';
12
+ export { backlinks_for_page, format_context_markdown, get_wiki_context, search_wiki, search_wiki_chunks, show_wiki_chunk, } from './search.js';
13
+ export { list_topic_threads } from './topics.js';
12
14
  export { bootstrap_wiki, plan_wiki, wiki_building_workflow_markdown, } from './workflow.js';
13
15
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EACN,4BAA4B,EAC5B,YAAY,EACZ,UAAU,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACN,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,WAAW,EACX,WAAW,EACX,wBAAwB,EACxB,SAAS,EACT,iBAAiB,EACjB,oBAAoB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,oBAAoB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,gBAAgB,EAChB,WAAW,GACX,MAAM,aAAa,CAAC;AAErB,OAAO,EACN,cAAc,EACd,SAAS,EACT,+BAA+B,GAC/B,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EACN,6BAA6B,EAC7B,4BAA4B,EAC5B,YAAY,EACZ,UAAU,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACN,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,WAAW,EACX,WAAW,EACX,wBAAwB,EACxB,SAAS,EACT,iBAAiB,EACjB,oBAAoB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,oBAAoB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,eAAe,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EACN,cAAc,EACd,SAAS,EACT,+BAA+B,GAC/B,MAAM,eAAe,CAAC"}
package/dist/indexer.d.ts CHANGED
@@ -1,4 +1,14 @@
1
1
  import type { IndexResult, IndexStatus } from './types.js';
2
- export declare const current_index_schema_version = 1;
2
+ export declare const current_index_schema_version = 4;
3
+ export declare const current_index_package_version: string;
3
4
  export declare function index_wiki(root?: string): IndexResult;
5
+ type PageChunk = {
6
+ heading: string | null;
7
+ body: string;
8
+ start_line: number;
9
+ end_line: number;
10
+ sequence: number;
11
+ };
12
+ export declare function chunk_page_body(body: string): PageChunk[];
4
13
  export declare function index_status(root?: string): IndexStatus;
14
+ export {};
package/dist/indexer.js CHANGED
@@ -1,14 +1,17 @@
1
1
  import { createHash } from 'node:crypto';
2
- import { existsSync, statSync } from 'node:fs';
2
+ import { existsSync, readFileSync, statSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
4
  import { open_wiki_database, wiki_db_path } from './database.js';
5
+ import { log_wiki_event } from './events.js';
5
6
  import { list_markdown_page_paths, read_page_by_path, } from './pages.js';
6
7
  import { resolve_wiki_root, wikilink_target_path } from './paths.js';
7
- export const current_index_schema_version = 1;
8
+ export const current_index_schema_version = 4;
9
+ export const current_index_package_version = read_package_version();
8
10
  export function index_wiki(root = '.') {
9
11
  const wiki_root = resolve_wiki_root(root);
10
12
  const db_path = wiki_db_path(wiki_root);
11
13
  const db = open_wiki_database(wiki_root);
14
+ ensure_index_schema(db);
12
15
  let page_count = 0;
13
16
  let link_count = 0;
14
17
  const upsert_page = db.prepare(`
@@ -28,7 +31,17 @@ export function index_wiki(root = '.') {
28
31
  VALUES (?, ?, ?, ?, ?, ?, ?)
29
32
  `);
30
33
  const clear_fts = db.prepare('DELETE FROM fts_pages');
34
+ const clear_chunks = db.prepare('DELETE FROM page_chunks');
35
+ const clear_chunk_fts = db.prepare('DELETE FROM fts_page_chunks');
31
36
  const insert_fts = db.prepare('INSERT INTO fts_pages (path, title, body) VALUES (?, ?, ?)');
37
+ const insert_chunk = db.prepare(`
38
+ INSERT INTO page_chunks (
39
+ page_id, path, title, heading, body, start_line, end_line,
40
+ sequence, page_priority, page_status, page_tags
41
+ )
42
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
43
+ `);
44
+ const insert_chunk_fts = db.prepare('INSERT INTO fts_page_chunks (chunk_id, path, title, heading, body) VALUES (?, ?, ?, ?, ?)');
32
45
  const set_meta = db.prepare(`
33
46
  INSERT INTO wiki_meta (key, value, updated_at)
34
47
  VALUES (?, ?, datetime('now'))
@@ -58,6 +71,8 @@ export function index_wiki(root = '.') {
58
71
  try {
59
72
  indexed_at = new Date().toISOString();
60
73
  clear_fts.run();
74
+ clear_chunks.run();
75
+ clear_chunk_fts.run();
61
76
  for (const page of pages) {
62
77
  const file_path = join(wiki_root, 'wiki', page.path);
63
78
  const modified_at = statSync(file_path).mtime.toISOString();
@@ -84,6 +99,13 @@ export function index_wiki(root = '.') {
84
99
  link_count += 1;
85
100
  }
86
101
  insert_fts.run(page.path, page.title, page.content);
102
+ const page_priority = frontmatter_number(page.frontmatter.priority);
103
+ const page_status = frontmatter_string(page.frontmatter.status);
104
+ const page_tags = frontmatter_string_array(page.frontmatter.tags);
105
+ for (const chunk of chunk_page_body(page.body)) {
106
+ const chunk_result = insert_chunk.run(row.id, page.path, page.title, chunk.heading, chunk.body, chunk.start_line, chunk.end_line, chunk.sequence, page_priority, page_status, JSON.stringify(page_tags));
107
+ insert_chunk_fts.run(chunk_result.lastInsertRowid, page.path, page.title, chunk.heading, chunk.body);
108
+ }
87
109
  page_count += 1;
88
110
  }
89
111
  const placeholders = [...known_paths].map(() => '?').join(', ');
@@ -95,6 +117,7 @@ export function index_wiki(root = '.') {
95
117
  }
96
118
  set_meta.run('indexed_at', indexed_at);
97
119
  set_meta.run('schema_version', String(current_index_schema_version));
120
+ set_meta.run('package_version', current_index_package_version);
98
121
  db.exec('COMMIT');
99
122
  }
100
123
  catch (error) {
@@ -102,14 +125,85 @@ export function index_wiki(root = '.') {
102
125
  throw error;
103
126
  }
104
127
  db.close();
128
+ log_wiki_event({
129
+ root: wiki_root,
130
+ operation: 'index_wiki',
131
+ summary: `Indexed ${page_count} pages and ${link_count} links`,
132
+ target: wiki_root,
133
+ details: {
134
+ page_count,
135
+ link_count,
136
+ schema_version: current_index_schema_version,
137
+ },
138
+ });
105
139
  return {
106
140
  root: wiki_root,
107
- dbPath: db_path,
108
- pageCount: page_count,
109
- linkCount: link_count,
110
- indexedAt: indexed_at,
111
- schemaVersion: current_index_schema_version,
141
+ db_path: db_path,
142
+ page_count: page_count,
143
+ link_count: link_count,
144
+ indexed_at: indexed_at,
145
+ schema_version: current_index_schema_version,
146
+ package_version: current_index_package_version,
147
+ };
148
+ }
149
+ function ensure_index_schema(db) {
150
+ const chunk_columns = new Set(db.prepare('PRAGMA table_info(page_chunks)').all().map((column) => column.name));
151
+ const migrations = {
152
+ page_priority: 'ALTER TABLE page_chunks ADD COLUMN page_priority INTEGER NOT NULL DEFAULT 0',
153
+ page_status: 'ALTER TABLE page_chunks ADD COLUMN page_status TEXT',
154
+ page_tags: 'ALTER TABLE page_chunks ADD COLUMN page_tags TEXT',
112
155
  };
156
+ for (const [column_name, sql] of Object.entries(migrations)) {
157
+ if (!chunk_columns.has(column_name))
158
+ db.exec(sql);
159
+ }
160
+ }
161
+ export function chunk_page_body(body) {
162
+ const lines = body.split(/\r?\n/u);
163
+ const heading_lines = lines
164
+ .map((line, index) => ({ line, index }))
165
+ .filter(({ line }) => /^#{1,6}\s+\S/u.test(line));
166
+ if (heading_lines.length === 0) {
167
+ return [
168
+ {
169
+ heading: null,
170
+ body: body.trim(),
171
+ start_line: 1,
172
+ end_line: Math.max(lines.length, 1),
173
+ sequence: 0,
174
+ },
175
+ ];
176
+ }
177
+ return heading_lines.map((heading, sequence) => {
178
+ const next_heading = heading_lines[sequence + 1];
179
+ const end_index = next_heading
180
+ ? next_heading.index - 1
181
+ : lines.length - 1;
182
+ return {
183
+ heading: heading.line.replace(/^#{1,6}\s+/u, '').trim(),
184
+ body: lines
185
+ .slice(heading.index, end_index + 1)
186
+ .join('\n')
187
+ .trim(),
188
+ start_line: heading.index + 1,
189
+ end_line: end_index + 1,
190
+ sequence,
191
+ };
192
+ });
193
+ }
194
+ function frontmatter_string(value) {
195
+ return typeof value === 'string' ? value : null;
196
+ }
197
+ function frontmatter_number(value) {
198
+ return typeof value === 'number' && Number.isFinite(value)
199
+ ? value
200
+ : 0;
201
+ }
202
+ function frontmatter_string_array(value) {
203
+ if (Array.isArray(value)) {
204
+ return value.filter((item) => typeof item === 'string');
205
+ }
206
+ return typeof value === 'string' ? [value] : [];
113
207
  }
114
208
  export function index_status(root = '.') {
115
209
  const wiki_root = resolve_wiki_root(root);
@@ -119,13 +213,15 @@ export function index_status(root = '.') {
119
213
  if (!existsSync(db_path)) {
120
214
  return {
121
215
  root: wiki_root,
122
- dbPath: db_path,
216
+ db_path: db_path,
123
217
  exists: false,
124
- indexedAt: null,
125
- schemaVersion: null,
126
- currentSchemaVersion: current_index_schema_version,
127
- pageCount: page_paths.length,
128
- indexedPageCount: 0,
218
+ indexed_at: null,
219
+ schema_version: null,
220
+ current_schema_version: current_index_schema_version,
221
+ package_version: null,
222
+ current_package_version: current_index_package_version,
223
+ page_count: page_paths.length,
224
+ indexed_page_count: 0,
129
225
  stale: true,
130
226
  reasons: ['missing-index'],
131
227
  };
@@ -137,9 +233,10 @@ export function index_status(root = '.') {
137
233
  const meta = new Map(meta_rows.map((row) => [row.key, row.value]));
138
234
  const indexed_at = meta.get('indexed_at') ?? null;
139
235
  const schema_version = Number(meta.get('schema_version') ?? NaN);
236
+ const package_version = meta.get('package_version') ?? null;
140
237
  const indexed_page_count = db.prepare('SELECT COUNT(*) AS count FROM pages').get().count;
141
238
  const indexed_pages = db
142
- .prepare('SELECT path, content_hash AS contentHash FROM pages')
239
+ .prepare('SELECT path, content_hash AS content_hash FROM pages')
143
240
  .all();
144
241
  db.close();
145
242
  if (!indexed_at)
@@ -147,11 +244,14 @@ export function index_status(root = '.') {
147
244
  if (schema_version !== current_index_schema_version) {
148
245
  reasons.push('schema-version-mismatch');
149
246
  }
247
+ if (package_version !== current_index_package_version) {
248
+ reasons.push('package-version-mismatch');
249
+ }
150
250
  if (indexed_page_count !== page_paths.length) {
151
251
  reasons.push('page-count-changed');
152
252
  }
153
253
  const current_paths = new Set(page_paths);
154
- const indexed_hashes = new Map(indexed_pages.map((page) => [page.path, page.contentHash]));
254
+ const indexed_hashes = new Map(indexed_pages.map((page) => [page.path, page.content_hash]));
155
255
  for (const page of indexed_pages) {
156
256
  if (!current_paths.has(page.path))
157
257
  reasons.push('deleted-pages');
@@ -169,17 +269,28 @@ export function index_status(root = '.') {
169
269
  }
170
270
  return {
171
271
  root: wiki_root,
172
- dbPath: db_path,
272
+ db_path: db_path,
173
273
  exists: true,
174
- indexedAt: indexed_at,
175
- schemaVersion: Number.isNaN(schema_version)
274
+ indexed_at: indexed_at,
275
+ schema_version: Number.isNaN(schema_version)
176
276
  ? null
177
277
  : schema_version,
178
- currentSchemaVersion: current_index_schema_version,
179
- pageCount: page_paths.length,
180
- indexedPageCount: indexed_page_count,
278
+ current_schema_version: current_index_schema_version,
279
+ package_version: package_version,
280
+ current_package_version: current_index_package_version,
281
+ page_count: page_paths.length,
282
+ indexed_page_count: indexed_page_count,
181
283
  stale: reasons.length > 0,
182
284
  reasons: [...new Set(reasons)],
183
285
  };
184
286
  }
287
+ function read_package_version() {
288
+ try {
289
+ const package_json = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
290
+ return package_json.version ?? '0.0.0';
291
+ }
292
+ catch {
293
+ return '0.0.0';
294
+ }
295
+ }
185
296
  //# sourceMappingURL=indexer.js.map