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,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SecretRefusedError = exports.SecretGuardDecisionModel = void 0;
4
+ exports.secretGuardEnabled = secretGuardEnabled;
5
+ exports.refuseUnchecked = refuseUnchecked;
6
+ exports.assertStorable = assertStorable;
7
+ exports.findSensitive = findSensitive;
8
+ exports.logSkip = logSkip;
9
+ /**
10
+ * The write-path secret guard: tier 0 of the sensitivity guardrail
11
+ * (docs/evals/results/SECRET-GUARD-TIER0-20261003.md).
12
+ *
13
+ * Behind RENOR_SECRET_GUARD, default ON (secretGuardEnabled). Every path that writes text into memory screens
14
+ * it with the deterministic scanner first, before anything is written:
15
+ *
16
+ * save `remember` (both modes), `save_memory`, the daily-note writer, the conversation logger:
17
+ * the whole save is refused. Nothing is stored, redacted or altered, so a save that
18
+ * succeeds is still a save that stored every character it was given.
19
+ * import a note or fact in an import plan is left out with its reason, and a plan that still holds
20
+ * one is refused whole (src/importing/secretScreen.ts).
21
+ * retire a memory whose text is flagged is not retired, because retiring copies its text into the
22
+ * retired-memory journal; restore is refused the same way, because it puts the text back
23
+ * into live memory (src/memorymap/memoryMap.ts).
24
+ *
25
+ * With it off (RENOR_SECRET_GUARD=0, false, no or off), nothing here runs on any of those paths.
26
+ *
27
+ * The guard is a DecisionModel, so the write path asks the same `capture_gate` question the indexer
28
+ * asks and refuses on `sensitive`. A model's second opinion, if one is ever approved, composes behind
29
+ * the scanner here, and a scanner `sensitive` stays final.
30
+ *
31
+ * It decides whether text may be STORED. It cannot stop text from reaching the server, and it does not
32
+ * look at what is already stored.
33
+ */
34
+ const decision_model_1 = require("./decision-model");
35
+ const secretScanner_1 = require("./secretScanner");
36
+ /**
37
+ * RENOR_SECRET_GUARD (default ON, decided 2026-10-12). Off only when set to 0, false, no or off (any case). Unset, empty
38
+ * and any other value keep it on: a value the guard does not recognise must not switch the screen off.
39
+ */
40
+ function secretGuardEnabled(env = process.env) {
41
+ const raw = (env.RENOR_SECRET_GUARD ?? '').trim().toLowerCase();
42
+ return !(raw === '0' || raw === 'false' || raw === 'no' || raw === 'off');
43
+ }
44
+ /**
45
+ * Answers the capture gate from the scanner alone: text it flags is `sensitive`, and everything else
46
+ * (all other text, and every dedupe question) is the inner model's, so the guard changes no other decision.
47
+ */
48
+ class SecretGuardDecisionModel {
49
+ inner;
50
+ constructor(inner = (0, decision_model_1.defaultDecisionModel)()) {
51
+ this.inner = inner;
52
+ }
53
+ async decide(request) {
54
+ if (request.task !== 'capture_gate')
55
+ return this.inner.decide(request);
56
+ const started = Date.now();
57
+ const finding = (0, secretScanner_1.scanSecrets)(request.text);
58
+ if (finding === null)
59
+ return this.inner.decide(request);
60
+ const verdict = {
61
+ task: 'capture_gate',
62
+ decision: 'sensitive',
63
+ confidence: 1,
64
+ latencyMs: Date.now() - started,
65
+ costUSDCents: 0,
66
+ finding,
67
+ };
68
+ return verdict;
69
+ }
70
+ }
71
+ exports.SecretGuardDecisionModel = SecretGuardDecisionModel;
72
+ const APPEARS_TO_CONTAIN = {
73
+ credential: 'a credential (an API key, token, password, PIN or private key)',
74
+ identifier: 'a personal identifier (a payment card, government ID or phone number)',
75
+ sensitive: 'a credential or personal identifier',
76
+ };
77
+ /**
78
+ * What the caller is told. It names the field and the kind of thing found from fixed text, never the
79
+ * text itself, and says what to do next. Kept under the 400 characters the MCP error reply keeps.
80
+ */
81
+ function refusalMessage(field, reason, action) {
82
+ const lead = action === 'save' ? 'Nothing was saved' : 'Nothing was changed';
83
+ if (reason === 'unavailable') {
84
+ return `${lead}: the secret guard (RENOR_SECRET_GUARD) is on but could not check the ${field}, so it refuses by default. `
85
+ + 'Try again, and tell the user if it keeps happening.';
86
+ }
87
+ if (action === 'retire') {
88
+ return `${lead}: the ${field} appears to contain ${APPEARS_TO_CONTAIN[reason]}, and the secret guard (RENOR_SECRET_GUARD) is on, `
89
+ + 'so this memory was not retired: retiring copies its text into the retired-memory journal. It stays as it is. '
90
+ + 'Remove it with the data-deletion procedure, or ask the owner to switch the guard off first.';
91
+ }
92
+ if (action === 'restore') {
93
+ return `${lead}: the ${field} appears to contain ${APPEARS_TO_CONTAIN[reason]}, and the secret guard (RENOR_SECRET_GUARD) is on, `
94
+ + 'so this memory was not restored: restoring would put its text back into live memory. It stays retired.';
95
+ }
96
+ return `${lead}: the ${field} appears to contain ${APPEARS_TO_CONTAIN[reason]}, and the secret guard (RENOR_SECRET_GUARD) is on, `
97
+ + 'so Renor does not store it. Save what it is for instead (for example "the staging API key is in 1Password"), '
98
+ + 'or reword the text without the value, then save again.';
99
+ }
100
+ /** The operation was refused: nothing was written or moved. `reason` is what was found, or `unavailable` when the guard could not decide. */
101
+ class SecretRefusedError extends Error {
102
+ field;
103
+ reason;
104
+ action;
105
+ constructor(field, reason, action = 'save') {
106
+ super(refusalMessage(field, reason, action));
107
+ this.name = 'SecretRefusedError';
108
+ this.field = field;
109
+ this.reason = reason;
110
+ this.action = action;
111
+ }
112
+ }
113
+ exports.SecretRefusedError = SecretRefusedError;
114
+ /**
115
+ * One line for whoever runs the service, in the same JSON shape as its access log: what was refused and why,
116
+ * never what it said. It is how an operator sees what the guard is refusing.
117
+ */
118
+ function logRefusal(field, reason, action, cause) {
119
+ console.warn(JSON.stringify({
120
+ ts: new Date().toISOString(), event: 'secret_guard_refusal', action, field, reason,
121
+ ...(cause instanceof Error ? { error: cause.name } : {}),
122
+ }));
123
+ }
124
+ function refuse(field, reason, action, cause) {
125
+ logRefusal(field, reason, action, cause);
126
+ throw new SecretRefusedError(field, reason, action);
127
+ }
128
+ /** For a text the guard cannot read in full (too large to hold): refuse, as it does when its own check fails. */
129
+ function refuseUnchecked(field, action) {
130
+ return refuse(field, 'unavailable', action);
131
+ }
132
+ /**
133
+ * Throws SecretRefusedError when the guard is on and any of `texts` is sensitive; resolves otherwise.
134
+ * It fails closed: if the check itself throws, the save is refused. Call it before the first write.
135
+ * With the guard off it returns at once, so callers that must not add a step to the unguarded path
136
+ * check `secretGuardEnabled()` first and skip the call.
137
+ */
138
+ async function assertStorable(texts, action = 'save') {
139
+ if (!secretGuardEnabled())
140
+ return;
141
+ const model = new SecretGuardDecisionModel();
142
+ for (const { field, text } of texts) {
143
+ if (text === undefined || text === '')
144
+ continue;
145
+ let verdict;
146
+ try {
147
+ verdict = await model.decide({ task: 'capture_gate', text });
148
+ }
149
+ catch (cause) {
150
+ refuse(field, 'unavailable', action, cause);
151
+ }
152
+ if (verdict.decision === 'sensitive') {
153
+ refuse(field, verdict.finding?.class ?? 'sensitive', action);
154
+ }
155
+ }
156
+ }
157
+ /**
158
+ * The first of `texts` that looks like a secret, or null: the same scanner as `assertStorable`, answered at
159
+ * once and without the DecisionModel, for the bulk paths that screen thousands of texts in synchronous code
160
+ * (an import plan) and decide per item. Independent of the switch: callers check `secretGuardEnabled()`.
161
+ * If the scan throws, the exception propagates, so a plan that cannot be screened is not built or applied.
162
+ */
163
+ function findSensitive(texts) {
164
+ for (const { field, text } of texts) {
165
+ if (text === undefined || text === '')
166
+ continue;
167
+ const finding = (0, secretScanner_1.scanSecrets)(text);
168
+ if (finding !== null)
169
+ return { field, reason: finding.class };
170
+ }
171
+ return null;
172
+ }
173
+ /** One log line for a text a bulk path left out (same shape as a refusal), so an operator sees what the guard skipped. */
174
+ function logSkip(field, reason) {
175
+ logRefusal(field, reason, 'import');
176
+ }