renor-engine 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/LICENSE +661 -0
  2. package/NOTICE +73 -0
  3. package/README.md +105 -2
  4. package/dist/BUILD.json +6 -0
  5. package/dist/api/apiAuth.js +43 -0
  6. package/dist/api/server.js +172 -0
  7. package/dist/buildIdentity.js +132 -0
  8. package/dist/cli-extractors.js +46 -0
  9. package/dist/cli.js +491 -0
  10. package/dist/config.js +65 -0
  11. package/dist/context/composer.js +320 -0
  12. package/dist/context/readHonesty.js +478 -0
  13. package/dist/context/rowStore.js +238 -0
  14. package/dist/conversation/formatter.js +81 -0
  15. package/dist/conversation/parser.js +189 -0
  16. package/dist/conversation/types.js +2 -0
  17. package/dist/conversation/writer.js +42 -0
  18. package/dist/db/client.js +147 -0
  19. package/dist/db/indexSalvage.js +81 -0
  20. package/dist/db/migrations.js +642 -0
  21. package/dist/db/readCache.js +109 -0
  22. package/dist/db/schema.js +5 -0
  23. package/dist/db/statements.js +89 -0
  24. package/dist/digests/digestCache.js +142 -0
  25. package/dist/digests/digests.js +597 -0
  26. package/dist/digests/worker.js +348 -0
  27. package/dist/embeddings/caching.js +337 -0
  28. package/dist/embeddings/coalescing.js +177 -0
  29. package/dist/embeddings/interactive.js +103 -0
  30. package/dist/embeddings/local.js +68 -0
  31. package/dist/embeddings/openai.js +105 -0
  32. package/dist/embeddings/rebuild.js +166 -0
  33. package/dist/embeddings/simdScan.js +258 -0
  34. package/dist/embeddings/space.js +21 -0
  35. package/dist/embeddings/types.js +14 -0
  36. package/dist/embeddings/vectorIndex.js +675 -0
  37. package/dist/embeddings/vertex.js +224 -0
  38. package/dist/eval/artifacts.js +42 -0
  39. package/dist/eval/cacheReport.js +139 -0
  40. package/dist/eval/comparison.js +182 -0
  41. package/dist/eval/context700-candidate.js +145 -0
  42. package/dist/eval/evalCache.js +525 -0
  43. package/dist/eval/hashEmbedding.js +35 -0
  44. package/dist/eval/longmemeval.js +56 -0
  45. package/dist/eval/metrics.js +181 -0
  46. package/dist/eval/renorbenchBaseline.js +486 -0
  47. package/dist/eval/renorbenchDocuments.js +134 -0
  48. package/dist/eval/renorbenchProduct.js +182 -0
  49. package/dist/eval/runLedger.js +279 -0
  50. package/dist/eval/runManifest.js +479 -0
  51. package/dist/eval/scoring.js +197 -0
  52. package/dist/evidence/attach.js +267 -0
  53. package/dist/evidence/background.js +147 -0
  54. package/dist/evidence/evidenceCache.js +182 -0
  55. package/dist/evidence/gate.js +37 -0
  56. package/dist/evidence/keyPool.js +85 -0
  57. package/dist/evidence/ollamaChat.js +84 -0
  58. package/dist/evidence/optin.js +165 -0
  59. package/dist/evidence/options.js +130 -0
  60. package/dist/evidence/secondPass.js +456 -0
  61. package/dist/extraction/classifyCapture.js +34 -0
  62. package/dist/extraction/decision-model.js +174 -0
  63. package/dist/extraction/eventExtractor.js +113 -0
  64. package/dist/extraction/extractionClient.js +122 -0
  65. package/dist/extraction/factExtractor.js +46 -0
  66. package/dist/extraction/factsWritePath.js +179 -0
  67. package/dist/extraction/preferenceExtractor.js +153 -0
  68. package/dist/extraction/secretGuard.js +176 -0
  69. package/dist/extraction/secretScanner.js +665 -0
  70. package/dist/extraction/typedFacts.js +224 -0
  71. package/dist/extraction/writePathAdjudication.js +110 -0
  72. package/dist/importing/apply.js +644 -0
  73. package/dist/importing/bundle-write.js +80 -0
  74. package/dist/importing/cli.js +407 -0
  75. package/dist/importing/existing.js +49 -0
  76. package/dist/importing/facts.js +123 -0
  77. package/dist/importing/forgetImported.js +79 -0
  78. package/dist/importing/hosted.js +467 -0
  79. package/dist/importing/index.js +29 -0
  80. package/dist/importing/journalLog.js +96 -0
  81. package/dist/importing/markdown.js +98 -0
  82. package/dist/importing/plan.js +206 -0
  83. package/dist/importing/secretScreen.js +113 -0
  84. package/dist/importing/serialize.js +188 -0
  85. package/dist/importing/source.js +463 -0
  86. package/dist/importing/types.js +6 -0
  87. package/dist/indexer/chunker.js +319 -0
  88. package/dist/indexer/dailyEntries.js +63 -0
  89. package/dist/indexer/hasher.js +10 -0
  90. package/dist/indexer/laneRuns.js +48 -0
  91. package/dist/indexer/o200k.js +481 -0
  92. package/dist/indexer/o200k.json +8 -0
  93. package/dist/indexer/outsideRoot.js +77 -0
  94. package/dist/indexer/parser.js +167 -0
  95. package/dist/indexer/pipeline.js +1168 -0
  96. package/dist/indexer/staleness.js +201 -0
  97. package/dist/indexer/tokenizer.js +77 -0
  98. package/dist/indexer/walker.js +184 -0
  99. package/dist/mcp/hive.js +88 -0
  100. package/dist/mcp/requestErrors.js +47 -0
  101. package/dist/mcp/server.js +396 -0
  102. package/dist/memory/agentLease.js +43 -0
  103. package/dist/memory/confinedWrite.js +315 -0
  104. package/dist/memory/controls.js +73 -0
  105. package/dist/memory/dailyNote.js +265 -0
  106. package/dist/memory/durableAppend.js +57 -0
  107. package/dist/memory/factConflicts.js +203 -0
  108. package/dist/memory/factTerms.js +321 -0
  109. package/dist/memory/hiveNameHeader.cjs +10 -0
  110. package/dist/memory/inventory.js +55 -0
  111. package/dist/memory/invisibleText.js +20 -0
  112. package/dist/memory/lifecycle.js +1756 -0
  113. package/dist/memory/limits.js +13 -0
  114. package/dist/memory/requests.js +183 -0
  115. package/dist/memory/sourceName.js +200 -0
  116. package/dist/memory/whatsNew.js +158 -0
  117. package/dist/memory/writer.js +175 -0
  118. package/dist/memory/writerConflicts.js +85 -0
  119. package/dist/memorymap/memoryMap.js +1568 -0
  120. package/dist/memorymap/replacedJournal.js +58 -0
  121. package/dist/memorymap/replacements.js +405 -0
  122. package/dist/mvp/activity.js +86 -0
  123. package/dist/mvp/agentMemory.js +1744 -0
  124. package/dist/mvp/auth.js +531 -0
  125. package/dist/mvp/cli.js +73 -0
  126. package/dist/mvp/client-store.js +462 -0
  127. package/dist/mvp/compileCache.js +249 -0
  128. package/dist/mvp/compileSeed.js +27 -0
  129. package/dist/mvp/config.js +288 -0
  130. package/dist/mvp/connectionStatus.js +80 -0
  131. package/dist/mvp/contextRelevance.js +413 -0
  132. package/dist/mvp/engine.js +1065 -0
  133. package/dist/mvp/exportAll.js +359 -0
  134. package/dist/mvp/factLanePack.js +77 -0
  135. package/dist/mvp/factMarkers.js +49 -0
  136. package/dist/mvp/factsLane.js +203 -0
  137. package/dist/mvp/hiddenSpans.js +585 -0
  138. package/dist/mvp/history.js +413 -0
  139. package/dist/mvp/hitDates.js +31 -0
  140. package/dist/mvp/hitFloor.js +36 -0
  141. package/dist/mvp/identity.js +18 -0
  142. package/dist/mvp/idle.js +113 -0
  143. package/dist/mvp/memoryDir.js +98 -0
  144. package/dist/mvp/posthogMcp.js +210 -0
  145. package/dist/mvp/readScope.js +104 -0
  146. package/dist/mvp/readUsefulness.js +222 -0
  147. package/dist/mvp/sanitize.js +48 -0
  148. package/dist/mvp/schemaRejections.js +91 -0
  149. package/dist/mvp/scope.js +127 -0
  150. package/dist/mvp/server.js +2089 -0
  151. package/dist/mvp/serverCard.js +29 -0
  152. package/dist/mvp/storedSize.js +139 -0
  153. package/dist/mvp/telemetry.js +441 -0
  154. package/dist/retrieval/adviceLines.js +195 -0
  155. package/dist/retrieval/adviceQuestion.js +44 -0
  156. package/dist/retrieval/conversationShape.js +44 -0
  157. package/dist/retrieval/dailyEntryTime.js +55 -0
  158. package/dist/retrieval/entityLookup.js +113 -0
  159. package/dist/retrieval/factsFirst.js +188 -0
  160. package/dist/retrieval/keyword.js +84 -0
  161. package/dist/retrieval/ledgerEventTime.js +51 -0
  162. package/dist/retrieval/ledgerLiveness.js +83 -0
  163. package/dist/retrieval/ledgerPresentation.js +161 -0
  164. package/dist/retrieval/noteIdentity.js +57 -0
  165. package/dist/retrieval/orchestrator.js +1086 -0
  166. package/dist/retrieval/queryHelpers.js +142 -0
  167. package/dist/retrieval/questionSpan.js +475 -0
  168. package/dist/retrieval/readerEvents.js +690 -0
  169. package/dist/retrieval/readerLayout.js +503 -0
  170. package/dist/retrieval/relativeTimeHints.js +113 -0
  171. package/dist/retrieval/semantic.js +67 -0
  172. package/dist/router/routerCache.js +106 -0
  173. package/dist/router/sessionRouter.js +726 -0
  174. package/dist/toolRefusal.js +120 -0
  175. package/dist/watcher/watcher.js +75 -0
  176. package/package.json +120 -4
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.openDb = openDb;
7
+ exports.openIndexDb = openIndexDb;
8
+ exports.openReadOnlyDb = openReadOnlyDb;
9
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const migrations_1 = require("./migrations");
13
+ const indexSalvage_1 = require("./indexSalvage");
14
+ /**
15
+ * Map up to this much of the database file into memory for reads (`PRAGMA mmap_size`). SQLite maps only
16
+ * what exists, so a small database is untouched; the ceiling is address space, not memory.
17
+ *
18
+ * Why: a sqlite-vec nearest-neighbour query reads every vector chunk, each a multi-megabyte BLOB, and
19
+ * SQLite reads a BLOB's overflow pages straight from the file, one pread() per 4 KB page, bypassing its
20
+ * page cache (so a bigger cache_size does not help). On a 10,000-note workspace that was ~60% kernel time
21
+ * per query. Reading through the mapping turns those syscalls into copies and cut the scan's CPU by about
22
+ * a third (scripts/bench/mcp-latency.ts). Only reads change: writes still go through write(), and answers
23
+ * are identical.
24
+ *
25
+ * The one thing a mapped read cannot survive is the file shrinking under it. The engine never VACUUMs or
26
+ * truncates its database, and the data-deletion runbook stops the service before touching the files.
27
+ * Not applied to `openReadOnlyDb`, which inspects or imports from files this process does not own.
28
+ */
29
+ const MMAP_SIZE_BYTES = 1024 * 1024 * 1024;
30
+ function openDb(dbPath) {
31
+ const onDisk = dbPath !== ':memory:' && dbPath !== '';
32
+ if (onDisk) {
33
+ // The index holds every remembered statement in plain text. A new one is created owner-only whatever the
34
+ // umask; SQLite gives its -wal and -shm files the main file's mode. An existing file keeps its mode.
35
+ fs_1.default.mkdirSync(path_1.default.dirname(dbPath), { recursive: true, mode: 0o700 });
36
+ fs_1.default.closeSync(fs_1.default.openSync(dbPath, fs_1.default.constants.O_CREAT | fs_1.default.constants.O_WRONLY, 0o600));
37
+ }
38
+ const db = new better_sqlite3_1.default(dbPath);
39
+ try {
40
+ db.pragma('journal_mode = WAL');
41
+ db.pragma('foreign_keys = ON');
42
+ db.pragma(`mmap_size = ${MMAP_SIZE_BYTES}`);
43
+ }
44
+ catch (err) {
45
+ // A file that is not a database fails on its first pragma; do not leave its handle open for the caller that never gets it.
46
+ db.close();
47
+ throw err;
48
+ }
49
+ return db;
50
+ }
51
+ /**
52
+ * Opens the derived index, and rebuilds it when it is damaged. The index is rebuilt from the ledger and the Markdown
53
+ * (the CLI banner says so), so a damaged `index.db` is not a reason to refuse to start: it is moved aside, with its
54
+ * `-wal` and `-shm`, to `index.db.corrupt-<timestamp>` (kept for forensics) and the caller gets a fresh index, exactly
55
+ * as for a missing one. Only corruption is moved aside: an open that fails for another reason (permissions, I/O) throws.
56
+ * The move needs the ledger to rebuild from, so with no ledger a damaged index throws rather than being set aside.
57
+ * The ledger itself is never touched here.
58
+ */
59
+ function openIndexDb(dbPath, ledgerPath) {
60
+ let damage;
61
+ try {
62
+ const db = openDb(dbPath);
63
+ let verdict;
64
+ try {
65
+ verdict = db.pragma('quick_check', { simple: true });
66
+ }
67
+ catch (err) {
68
+ db.close();
69
+ throw err;
70
+ }
71
+ if (verdict === 'ok')
72
+ return db;
73
+ db.close();
74
+ damage = String(verdict);
75
+ }
76
+ catch (err) {
77
+ if (!isCorruptionError(err))
78
+ throw err;
79
+ damage = err.message;
80
+ }
81
+ if (!fs_1.default.existsSync(ledgerPath)) {
82
+ throw new Error(`index ${dbPath} is damaged (${damage}) and there is no ledger to rebuild it from; it was not moved aside. Restore the ledger, or move the index aside by hand.`);
83
+ }
84
+ // Read what the damaged file still gives before it is moved: the pending requests and cursors are not in the ledger.
85
+ const salvage = readDamagedIndex(dbPath);
86
+ const aside = setIndexAside(dbPath);
87
+ const db = openDb(dbPath);
88
+ (0, migrations_1.runMigrations)(db);
89
+ const { restored, rejected } = (0, indexSalvage_1.restoreIndexTables)(db, salvage);
90
+ console.error(`[index] ${dbPath} is damaged (${damage}); moved it and its -wal and -shm files to ${aside} and rebuilt it from the ledger. ${(0, indexSalvage_1.describeSalvage)(salvage, restored, rejected)}`);
91
+ return db;
92
+ }
93
+ /** The rows the ledger does not hold, read from the damaged file, read-only (openReadOnlyDb: the file is not written). */
94
+ function readDamagedIndex(dbPath) {
95
+ let db;
96
+ try {
97
+ db = openReadOnlyDb(dbPath);
98
+ }
99
+ catch (err) {
100
+ return (0, indexSalvage_1.unreadableSalvage)(err instanceof Error ? err.message : String(err));
101
+ }
102
+ try {
103
+ return (0, indexSalvage_1.salvageIndexTables)(db);
104
+ }
105
+ finally {
106
+ db.close();
107
+ }
108
+ }
109
+ /** A SQLite error that says the file is damaged, as opposed to unreadable for some other reason. */
110
+ function isCorruptionError(err) {
111
+ const code = err.code;
112
+ return typeof code === 'string' && (code === 'SQLITE_NOTADB' || code === 'SQLITE_CORRUPT' || code.startsWith('SQLITE_CORRUPT_'));
113
+ }
114
+ /**
115
+ * Renames the index's side files first and the main file last: if this is interrupted, the damaged main file is still
116
+ * there to be found again on the next start, and no WAL is ever left beside a fresh database it does not belong to.
117
+ */
118
+ function setIndexAside(dbPath) {
119
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-');
120
+ let aside = `${dbPath}.corrupt-${stamp}`;
121
+ for (let n = 2; ['', '-wal', '-shm'].some(side => fs_1.default.existsSync(aside + side)); n++)
122
+ aside = `${dbPath}.corrupt-${stamp}-${n}`;
123
+ for (const side of ['-wal', '-shm', '']) {
124
+ if (fs_1.default.existsSync(dbPath + side))
125
+ fs_1.default.renameSync(dbPath + side, aside + side);
126
+ }
127
+ return aside;
128
+ }
129
+ /**
130
+ * Read-only open of a SQLite database by path — a product index being inspected, or a
131
+ * source index an import reads from.
132
+ *
133
+ * Read-only is enforced by SQLite itself rather than by convention, so a read can never
134
+ * write to the store it is reading. That matters for the WAL side files too: a
135
+ * write-capable open of a WAL database can create `-wal`/`-shm` and checkpoint back into
136
+ * the main file. `journal_mode` is deliberately NOT set here, because setting it is a
137
+ * write. Product code must reach product SQLite through this module
138
+ * (`tests/eval/product-path-contract.test.ts` guards the `openDb` boundary).
139
+ */
140
+ function openReadOnlyDb(dbPath) {
141
+ if (!fs_1.default.existsSync(dbPath)) {
142
+ throw new Error(`database not found: ${dbPath}`);
143
+ }
144
+ const db = new better_sqlite3_1.default(dbPath, { readonly: true, fileMustExist: true });
145
+ db.pragma('foreign_keys = ON');
146
+ return db;
147
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.INDEX_ONLY_TABLES = void 0;
4
+ exports.unreadableSalvage = unreadableSalvage;
5
+ exports.salvageIndexTables = salvageIndexTables;
6
+ exports.restoreIndexTables = restoreIndexTables;
7
+ exports.describeSalvage = describeSalvage;
8
+ /**
9
+ * The index is rebuilt from the ledger, but a few of its tables hold state that no ledger event rebuilds: the pending
10
+ * agent requests, the what's-new cursors, and the connection names the workspace has seen (known_agents). When the
11
+ * index is damaged, those rows are read out of the damaged file, read-only, and written into the rebuilt one.
12
+ */
13
+ exports.INDEX_ONLY_TABLES = ['agent_requests', 'agent_cursors', 'known_agents'];
14
+ /** What a damaged index gives when it cannot be opened at all: every table is unreadable, for the same reason. */
15
+ function unreadableSalvage(reason) {
16
+ const salvage = { rows: {}, unreadable: {} };
17
+ for (const table of exports.INDEX_ONLY_TABLES) {
18
+ salvage.rows[table] = [];
19
+ salvage.unreadable[table] = reason;
20
+ }
21
+ return salvage;
22
+ }
23
+ /** Reads what an open (read-only) damaged index still gives. Never throws: a table that does not read says why. */
24
+ function salvageIndexTables(db) {
25
+ const salvage = { rows: {}, unreadable: {} };
26
+ for (const table of exports.INDEX_ONLY_TABLES) {
27
+ const rows = [];
28
+ salvage.rows[table] = rows;
29
+ try {
30
+ for (const row of db.prepare(`SELECT rowid AS __rowid, * FROM "${table}"`).iterate()) {
31
+ rows.push(row);
32
+ }
33
+ }
34
+ catch (err) {
35
+ // An index from before this table existed has nothing to salvage here; that is not a loss.
36
+ if (!/no such table/.test(errorText(err)))
37
+ salvage.unreadable[table] = errorText(err);
38
+ }
39
+ }
40
+ return salvage;
41
+ }
42
+ /** Writes the salvaged rows into a freshly migrated index. A row that will not go in is counted, never skipped silently. */
43
+ function restoreIndexTables(db, salvage) {
44
+ const restored = {};
45
+ const rejected = {};
46
+ for (const table of exports.INDEX_ONLY_TABLES) {
47
+ restored[table] = 0;
48
+ rejected[table] = 0;
49
+ for (const row of salvage.rows[table] ?? []) {
50
+ const { __rowid, ...values } = row;
51
+ const cols = ['rowid', ...Object.keys(values)];
52
+ const sql = `INSERT OR IGNORE INTO "${table}" (${cols.map(c => `"${c}"`).join(', ')}) VALUES (${cols.map(() => '?').join(', ')})`;
53
+ try {
54
+ const info = db.prepare(sql).run(__rowid, ...Object.keys(values).map(c => values[c]));
55
+ restored[table] += info.changes;
56
+ }
57
+ catch {
58
+ rejected[table] += 1;
59
+ }
60
+ }
61
+ }
62
+ return { restored, rejected };
63
+ }
64
+ /** One sentence for the log: what came back from the damaged index, and what did not. */
65
+ function describeSalvage(salvage, restored, rejected) {
66
+ const kept = exports.INDEX_ONLY_TABLES.map(t => `${t} ${restored[t] ?? 0}`).join(', ');
67
+ const lost = exports.INDEX_ONLY_TABLES
68
+ .map(t => {
69
+ const parts = [];
70
+ if (rejected[t])
71
+ parts.push(`${rejected[t]} row(s) could not be written`);
72
+ if (salvage.unreadable[t])
73
+ parts.push(`the damaged file could not be read (${salvage.unreadable[t]}), so rows past the damage are gone and not counted`);
74
+ return parts.length ? `${t}: ${parts.join('; ')}` : '';
75
+ })
76
+ .filter(Boolean);
77
+ return `Kept from the damaged index: ${kept}.${lost.length ? ` NOT RECOVERED: ${lost.join('. ')}.` : ''}`;
78
+ }
79
+ function errorText(err) {
80
+ return err instanceof Error ? err.message : String(err);
81
+ }