crbro-memory 2.10.0 → 2.11.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 (205) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +256 -465
  3. package/SECURITY.md +114 -12
  4. package/bin/crbro.mjs +539 -300
  5. package/dist/build-id.json +10 -0
  6. package/dist/cli/common.js +211 -0
  7. package/dist/cli/export.js +522 -0
  8. package/dist/cli/import.js +683 -0
  9. package/dist/cli/markdown.js +313 -0
  10. package/dist/cli/mcpclient.js +107 -0
  11. package/dist/cli/serve.js +453 -0
  12. package/dist/cli/view.js +358 -0
  13. package/dist/cli/viewer-page.js +378 -0
  14. package/dist/daemon/daemon.js +119 -11
  15. package/dist/daemon/endpoint.js +222 -21
  16. package/dist/daemon/lines.js +102 -13
  17. package/dist/daemon/proxy.js +480 -125
  18. package/dist/daemon/surface.js +116 -0
  19. package/dist/daemon/trace.js +73 -0
  20. package/dist/engine/atrest.js +132 -0
  21. package/dist/engine/backup.js +139 -19
  22. package/dist/engine/brain.js +22 -6
  23. package/dist/engine/codexconfig.js +476 -0
  24. package/dist/engine/cortex.js +667 -232
  25. package/dist/engine/doctor.js +312 -14
  26. package/dist/engine/heat.js +81 -37
  27. package/dist/engine/hippocampus.js +18 -7
  28. package/dist/engine/hookrefresh.js +296 -0
  29. package/dist/engine/hookverify.js +15 -3
  30. package/dist/engine/installer.js +1022 -0
  31. package/dist/engine/installio.js +279 -0
  32. package/dist/engine/keychain.js +721 -162
  33. package/dist/engine/maintenance.js +355 -87
  34. package/dist/engine/modinstall.js +98 -45
  35. package/dist/engine/prefrontal.js +29 -6
  36. package/dist/engine/quarantine.js +204 -0
  37. package/dist/engine/secrets.js +41 -5
  38. package/dist/engine/shelf.js +25 -3
  39. package/dist/engine/synapses.js +183 -80
  40. package/dist/engine/triggers.js +141 -11
  41. package/dist/index.js +37 -3
  42. package/dist/mcp-surface.json +1 -0
  43. package/dist/miner/extractor.js +64 -17
  44. package/dist/miner/scheduler.js +144 -68
  45. package/dist/search/index.js +797 -176
  46. package/dist/search/semantic.js +208 -18
  47. package/dist/search/tokenize.js +44 -0
  48. package/dist/server.js +583 -373
  49. package/dist/sync/git.js +203 -72
  50. package/dist/sync/space.js +100 -25
  51. package/dist/sync/validate.js +204 -0
  52. package/dist/utils/budget.js +15 -2
  53. package/dist/utils/fs.js +40 -6
  54. package/dist/utils/ids.js +128 -14
  55. package/dist/utils/lock.js +94 -7
  56. package/hooks/crbro-codex.mjs +284 -0
  57. package/hooks/crbro-guard.mjs +281 -173
  58. package/hooks/crbro-hooks.shipped.json +20 -0
  59. package/hooks/crbro-lifecycle.mjs +16 -4
  60. package/hooks/crbro-subagent.mjs +180 -180
  61. package/package.json +9 -5
  62. package/dist/daemon/daemon.d.ts +0 -25
  63. package/dist/daemon/daemon.d.ts.map +0 -1
  64. package/dist/daemon/daemon.js.map +0 -1
  65. package/dist/daemon/endpoint.d.ts +0 -66
  66. package/dist/daemon/endpoint.d.ts.map +0 -1
  67. package/dist/daemon/endpoint.js.map +0 -1
  68. package/dist/daemon/lines.d.ts +0 -55
  69. package/dist/daemon/lines.d.ts.map +0 -1
  70. package/dist/daemon/lines.js.map +0 -1
  71. package/dist/daemon/proxy.d.ts +0 -55
  72. package/dist/daemon/proxy.d.ts.map +0 -1
  73. package/dist/daemon/proxy.js.map +0 -1
  74. package/dist/engine/backup.d.ts +0 -68
  75. package/dist/engine/backup.d.ts.map +0 -1
  76. package/dist/engine/backup.js.map +0 -1
  77. package/dist/engine/brain.d.ts +0 -79
  78. package/dist/engine/brain.d.ts.map +0 -1
  79. package/dist/engine/brain.js.map +0 -1
  80. package/dist/engine/cortex.d.ts +0 -682
  81. package/dist/engine/cortex.d.ts.map +0 -1
  82. package/dist/engine/cortex.js.map +0 -1
  83. package/dist/engine/dates.d.ts +0 -28
  84. package/dist/engine/dates.d.ts.map +0 -1
  85. package/dist/engine/dates.js.map +0 -1
  86. package/dist/engine/doctor.d.ts +0 -93
  87. package/dist/engine/doctor.d.ts.map +0 -1
  88. package/dist/engine/doctor.js.map +0 -1
  89. package/dist/engine/evidence.d.ts +0 -26
  90. package/dist/engine/evidence.d.ts.map +0 -1
  91. package/dist/engine/evidence.js.map +0 -1
  92. package/dist/engine/heat.d.ts +0 -28
  93. package/dist/engine/heat.d.ts.map +0 -1
  94. package/dist/engine/heat.js.map +0 -1
  95. package/dist/engine/hippocampus.d.ts +0 -60
  96. package/dist/engine/hippocampus.d.ts.map +0 -1
  97. package/dist/engine/hippocampus.js.map +0 -1
  98. package/dist/engine/hookverify.d.ts +0 -42
  99. package/dist/engine/hookverify.d.ts.map +0 -1
  100. package/dist/engine/hookverify.js.map +0 -1
  101. package/dist/engine/keychain.d.ts +0 -32
  102. package/dist/engine/keychain.d.ts.map +0 -1
  103. package/dist/engine/keychain.js.map +0 -1
  104. package/dist/engine/maintenance.d.ts +0 -218
  105. package/dist/engine/maintenance.d.ts.map +0 -1
  106. package/dist/engine/maintenance.js.map +0 -1
  107. package/dist/engine/modinstall.d.ts +0 -215
  108. package/dist/engine/modinstall.d.ts.map +0 -1
  109. package/dist/engine/modinstall.js.map +0 -1
  110. package/dist/engine/postmortem.d.ts +0 -81
  111. package/dist/engine/postmortem.d.ts.map +0 -1
  112. package/dist/engine/postmortem.js.map +0 -1
  113. package/dist/engine/prefrontal.d.ts +0 -64
  114. package/dist/engine/prefrontal.d.ts.map +0 -1
  115. package/dist/engine/prefrontal.js.map +0 -1
  116. package/dist/engine/projects.d.ts +0 -20
  117. package/dist/engine/projects.d.ts.map +0 -1
  118. package/dist/engine/projects.js.map +0 -1
  119. package/dist/engine/secrets.d.ts +0 -30
  120. package/dist/engine/secrets.d.ts.map +0 -1
  121. package/dist/engine/secrets.js.map +0 -1
  122. package/dist/engine/shelf.d.ts +0 -155
  123. package/dist/engine/shelf.d.ts.map +0 -1
  124. package/dist/engine/shelf.js.map +0 -1
  125. package/dist/engine/source.d.ts +0 -6
  126. package/dist/engine/source.d.ts.map +0 -1
  127. package/dist/engine/source.js.map +0 -1
  128. package/dist/engine/synapses.d.ts +0 -82
  129. package/dist/engine/synapses.d.ts.map +0 -1
  130. package/dist/engine/synapses.js.map +0 -1
  131. package/dist/engine/triggers.d.ts +0 -53
  132. package/dist/engine/triggers.d.ts.map +0 -1
  133. package/dist/engine/triggers.js.map +0 -1
  134. package/dist/engine/usage.d.ts +0 -61
  135. package/dist/engine/usage.d.ts.map +0 -1
  136. package/dist/engine/usage.js.map +0 -1
  137. package/dist/index.d.ts +0 -2
  138. package/dist/index.d.ts.map +0 -1
  139. package/dist/index.js.map +0 -1
  140. package/dist/miner/extractor.d.ts +0 -12
  141. package/dist/miner/extractor.d.ts.map +0 -1
  142. package/dist/miner/extractor.js.map +0 -1
  143. package/dist/miner/index.d.ts +0 -61
  144. package/dist/miner/index.d.ts.map +0 -1
  145. package/dist/miner/index.js.map +0 -1
  146. package/dist/miner/scheduler.d.ts +0 -30
  147. package/dist/miner/scheduler.d.ts.map +0 -1
  148. package/dist/miner/scheduler.js.map +0 -1
  149. package/dist/miner/types.d.ts +0 -11
  150. package/dist/miner/types.d.ts.map +0 -1
  151. package/dist/miner/types.js.map +0 -1
  152. package/dist/search/index.d.ts +0 -328
  153. package/dist/search/index.d.ts.map +0 -1
  154. package/dist/search/index.js.map +0 -1
  155. package/dist/search/quality.d.ts +0 -18
  156. package/dist/search/quality.d.ts.map +0 -1
  157. package/dist/search/quality.js.map +0 -1
  158. package/dist/search/semantic.d.ts +0 -80
  159. package/dist/search/semantic.d.ts.map +0 -1
  160. package/dist/search/semantic.js.map +0 -1
  161. package/dist/search/synonyms.d.ts +0 -2
  162. package/dist/search/synonyms.d.ts.map +0 -1
  163. package/dist/search/synonyms.js.map +0 -1
  164. package/dist/search/tokenize.d.ts +0 -39
  165. package/dist/search/tokenize.d.ts.map +0 -1
  166. package/dist/search/tokenize.js.map +0 -1
  167. package/dist/server.d.ts +0 -41
  168. package/dist/server.d.ts.map +0 -1
  169. package/dist/server.js.map +0 -1
  170. package/dist/sync/git.d.ts +0 -36
  171. package/dist/sync/git.d.ts.map +0 -1
  172. package/dist/sync/git.js.map +0 -1
  173. package/dist/sync/materialize.d.ts +0 -36
  174. package/dist/sync/materialize.d.ts.map +0 -1
  175. package/dist/sync/materialize.js.map +0 -1
  176. package/dist/sync/ops.d.ts +0 -147
  177. package/dist/sync/ops.d.ts.map +0 -1
  178. package/dist/sync/ops.js.map +0 -1
  179. package/dist/sync/space.d.ts +0 -118
  180. package/dist/sync/space.d.ts.map +0 -1
  181. package/dist/sync/space.js.map +0 -1
  182. package/dist/types/index.d.ts +0 -369
  183. package/dist/types/index.d.ts.map +0 -1
  184. package/dist/types/index.js.map +0 -1
  185. package/dist/utils/budget.d.ts +0 -44
  186. package/dist/utils/budget.d.ts.map +0 -1
  187. package/dist/utils/budget.js.map +0 -1
  188. package/dist/utils/fs.d.ts +0 -59
  189. package/dist/utils/fs.d.ts.map +0 -1
  190. package/dist/utils/fs.js.map +0 -1
  191. package/dist/utils/hash.d.ts +0 -20
  192. package/dist/utils/hash.d.ts.map +0 -1
  193. package/dist/utils/hash.js.map +0 -1
  194. package/dist/utils/ids.d.ts +0 -47
  195. package/dist/utils/ids.d.ts.map +0 -1
  196. package/dist/utils/ids.js.map +0 -1
  197. package/dist/utils/lock.d.ts +0 -13
  198. package/dist/utils/lock.d.ts.map +0 -1
  199. package/dist/utils/lock.js.map +0 -1
  200. package/dist/utils/transcripts.d.ts +0 -63
  201. package/dist/utils/transcripts.d.ts.map +0 -1
  202. package/dist/utils/transcripts.js.map +0 -1
  203. package/dist/version.d.ts +0 -26
  204. package/dist/version.d.ts.map +0 -1
  205. package/dist/version.js.map +0 -1
@@ -1,682 +0,0 @@
1
- import { AsyncLocalStorage } from 'node:async_hooks';
2
- import { type Op } from '../sync/ops.js';
3
- import { type MergeReport } from '../sync/materialize.js';
4
- import { type ShelfReason } from './shelf.js';
5
- import { type VerificationInput } from './evidence.js';
6
- import type { Brain } from './brain.js';
7
- import type { Neuron, NeuronType, Fact, FactStatus, ShelfLife, SourceReference, Verification } from '../types/index.js';
8
- /**
9
- * `witnessed`: "<neuron>|<fact id>" of every fact this session stored or
10
- * confirmed. A session is one witness: storing the same line again in the
11
- * same session (a retry, the post-compaction re-save) does not count twice.
12
- * Not cleared by consolidate, which ends a chapter, not the conversation.
13
- */
14
- export interface SessionTally {
15
- facts: number;
16
- decisions: number;
17
- topics: Set<string>;
18
- witnessed?: Set<string>;
19
- verifiedEmitted?: Set<string>;
20
- }
21
- export declare const newTally: () => SessionTally;
22
- /**
23
- * The connection a request belongs to, carried through every await. Empty
24
- * outside the daemon. `resumed`: this backend took over a conversation that
25
- * was already running (its daemon died), so the tally starts at zero although
26
- * the conversation did not — consolidate must not present that zero as the truth.
27
- */
28
- export declare const sessionScope: AsyncLocalStorage<{
29
- tally: SessionTally;
30
- resumed?: boolean;
31
- }>;
32
- /**
33
- * Near-duplicates of `content` among `candidates`, best first: Dice ≥ 0.8 on
34
- * lower-cased text, both sides at least NEAR_DUP_MIN_LENGTH characters. The
35
- * one rule behind learn's near_duplicates warning (inside one neuron) and
36
- * consolidate's promotion_candidates (across project neurons), so the two
37
- * cannot disagree on what "almost the same line" means.
38
- */
39
- export declare function nearDuplicatesAmong(content: string, candidates: Array<{
40
- id: string;
41
- text: string;
42
- }>): Array<{
43
- id: string;
44
- similarity: number;
45
- text: string;
46
- }>;
47
- /** Lesson kinds that can be promoted: what was learned, not what was decided or preferred. */
48
- export type LessonKind = 'fact' | 'pattern' | 'error';
49
- export interface PromotionCandidate {
50
- kind: LessonKind;
51
- /** The telling to promote: the most confirmed copy, then the longest. */
52
- text: string;
53
- /** Project neurons that hold it, the one written this session first. */
54
- neurons: string[];
55
- /** The entry id of the copy in each of `neurons`, same order. */
56
- entry_ids: string[];
57
- /** Lowest similarity in the group: 1 when every copy is the same text. */
58
- similarity: number;
59
- /** Sum of the copies' confirmations (each copy counts at least 1). */
60
- confirmations: number;
61
- }
62
- /** Most promotion candidates consolidate reports. More is a backlog, not a nudge. */
63
- export declare const MAX_PROMOTION_CANDIDATES = 5;
64
- /**
65
- * The same lesson living in two or more project neurons: the mark of
66
- * something that is not about one project at all and belongs in a tech_ or
67
- * process_ neuron where every project finds it.
68
- *
69
- * Generalises findNearDuplicates (one neuron) to many without making it
70
- * quadratic: only the lessons of `seedIds` — the project neurons this session
71
- * touched — are compared, and each only against the lessons that hold the
72
- * same numbers and most of its distinctive words (inverted indexes built
73
- * once). The bigram test then decides, as in learn. Exact copies (same
74
- * normalised text) count at any length.
75
- *
76
- * Only the user's own lessons take part. A line that arrived from a shared
77
- * space, the miner or anything that is not this machine's session is left
78
- * out: promoting it would rewrite a third party's text as the user's own
79
- * lesson, valid for every project, and drop the origin recall shows for it.
80
- *
81
- * Read-only and pure: it suggests, it never moves anything.
82
- */
83
- export declare function findPromotionCandidates(neurons: Neuron[], seedIds: Iterable<string>, max?: number): PromotionCandidate[];
84
- export type Indexer = (neuron: Neuron) => Promise<void> | void;
85
- /**
86
- * Called after a write so shared neurons can append a note to the team log.
87
- * A hook rather than a direct call, because the sync layer needs the Cortex
88
- * and the Cortex would then need the sync layer.
89
- */
90
- export type Emitter = (neuronId: string, change: {
91
- kind: 'fact';
92
- text: string;
93
- fid: string;
94
- conf: number;
95
- at: string;
96
- src?: string;
97
- keys?: string[];
98
- shelf?: ShelfLife;
99
- reference?: SourceReference;
100
- temporal?: Fact['temporal'];
101
- verification_invalidated_at?: string;
102
- } | {
103
- kind: 'status';
104
- fid: string;
105
- to: 'superseded' | 'retracted';
106
- at: string;
107
- why?: string;
108
- } | {
109
- kind: 'decision';
110
- text: string;
111
- why?: string;
112
- at: string;
113
- } | {
114
- kind: 'pattern';
115
- text: string;
116
- at: string;
117
- } | {
118
- kind: 'error';
119
- text: string;
120
- at: string;
121
- } | {
122
- kind: 'debt';
123
- text: string;
124
- at: string;
125
- } | {
126
- kind: 'map';
127
- text: string;
128
- at: string;
129
- } | {
130
- kind: 'error_purge';
131
- key: string;
132
- at: string;
133
- } | {
134
- kind: 'debt_purge';
135
- key: string;
136
- at: string;
137
- } | {
138
- kind: 'decision_purge';
139
- key: string;
140
- at: string;
141
- } | {
142
- kind: 'pattern_purge';
143
- key: string;
144
- at: string;
145
- }
146
- /** A line was checked against its source and still holds (shelf life). `at` is the check. */
147
- | {
148
- kind: 'verify';
149
- eid: string;
150
- ekind: 'fact' | 'entry';
151
- at: string;
152
- verification?: Verification;
153
- }) => Promise<void> | void;
154
- /**
155
- * Called after a neuron file is deleted, so the search index drops its
156
- * chunks. The mirror of Indexer: without it a forgotten neuron kept
157
- * answering recall until the next full rebuild.
158
- */
159
- export type Remover = (neuronId: string) => Promise<void> | void;
160
- /**
161
- * Everything of `source` folded into `target`, as a new object.
162
- *
163
- * Shared by restoreNeuron (a quarantine copy back over a neuron that was
164
- * re-created since) and mergeNeurons (two neurons that turned out to be one
165
- * topic). Pure on purpose: neither input is touched, so the caller can diff
166
- * the result against what it had and emit only what actually moved.
167
- *
168
- * Facts line up by id (the content hash), falling back to normalised text;
169
- * on a collision the target's telling stays but takes the furthest-along
170
- * status (active < superseded < retracted) and the earliest `added`, and the
171
- * keys are unioned. Everything else is a set union keyed by normalised text
172
- * with the target's order first. Local observations (heat, access_count)
173
- * combine as max and sum; identity (id, name, domain, type) is the target's.
174
- */
175
- export declare function unionNeuron(target: Neuron, source: Neuron): {
176
- neuron: Neuron;
177
- moved: {
178
- facts: number;
179
- decisions: number;
180
- patterns: number;
181
- preferences: number;
182
- errors: number;
183
- debts: number;
184
- tags: number;
185
- map: 0 | 1;
186
- };
187
- };
188
- /**
189
- * Aliases a future question may use, as stored: trimmed, lower-cased, at
190
- * most 40 characters each, unique, at most eight. Order is kept.
191
- */
192
- export declare function normalizeKeys(keys?: string[]): string[];
193
- export declare class Cortex {
194
- private brain;
195
- /**
196
- * Optional hook invoked after every write. Wiring it here — rather than
197
- * calling the search engine from each caller — is what guarantees the miner
198
- * path gets indexed too. Before this, the miner wrote straight to disk and
199
- * 91% of the brain never reached the index.
200
- */
201
- private indexer;
202
- private emitter;
203
- private remover;
204
- /**
205
- * What this session has actually written, for an honest consolidate().
206
- * One per Cortex when a process serves one conversation; in the daemon one
207
- * Cortex serves every client, so the tally in force is the one the
208
- * connection carries (sessionScope) — otherwise whoever consolidated first
209
- * would log, and link with synapses, what the other conversations wrote.
210
- */
211
- private ownTally;
212
- private get tally();
213
- constructor(brain: Brain);
214
- /** Facts, decisions and neurons touched since the last consolidation. */
215
- sessionTally(): {
216
- facts: number;
217
- decisions: number;
218
- topics: string[];
219
- };
220
- resetSessionTally(): void;
221
- setIndexer(indexer: Indexer | null): void;
222
- setEmitter(emitter: Emitter | null): void;
223
- setRemover(remover: Remover | null): void;
224
- private unindex;
225
- /**
226
- * Copy a whole neuron to .quarantine/ with a timestamp, before anything
227
- * destructive. Same stamp format everywhere, so restoreNeuron can pick the
228
- * newest copy by name alone.
229
- */
230
- private quarantine;
231
- /** Remove the neuron file, drop its chunks, and keep the manifest honest. */
232
- private deleteNeuronFile;
233
- private emit;
234
- /**
235
- * Fusionar contra la versión leída dentro del mismo bloqueo de escritura.
236
- * Un snapshot calculado antes del bloqueo puede borrar un learn o retiro.
237
- */
238
- mergeFromSync(nid: string, ops: Op[]): Promise<{
239
- report: MergeReport;
240
- created: boolean;
241
- }>;
242
- private reindex;
243
- /**
244
- * Get a neuron by ID.
245
- */
246
- get(id: string): Promise<Neuron | null>;
247
- /**
248
- * Get a neuron by ID without updating access stats.
249
- */
250
- peek(id: string): Promise<Neuron | null>;
251
- /**
252
- * Find a neuron by name.
253
- *
254
- * Returns null rather than guessing. That is the point: the previous
255
- * implementation fell back to substring containment in either direction, so
256
- * a two-word topic landed inside any long id that happened to contain it —
257
- * a short name like "SEO" was swallowed by a sixty-character neuron whose
258
- * title merely mentioned it.
259
- * Knowledge written into the wrong neuron is recalled attributed to the
260
- * wrong neuron, and no amount of index tuning repairs that. A wrong guess
261
- * is worse than a new neuron.
262
- */
263
- findByName(name: string): Promise<Neuron | null>;
264
- /**
265
- * Create a new neuron.
266
- * Refuses to clobber: two different names can slugify to the same id, and
267
- * the old code wrote straight over the existing file, losing every fact in it.
268
- */
269
- create(name: string, type: NeuronType, domain: string, summary?: string): Promise<Neuron>;
270
- /**
271
- * Learn — add a fact, decision, pattern or preference to a neuron.
272
- * Creates the neuron if it does not exist.
273
- */
274
- learn(topic: string, type: 'fact' | 'decision' | 'pattern' | 'preference' | 'error' | 'debt', content: string, options?: {
275
- confidence?: number;
276
- domain?: string;
277
- rationale?: string;
278
- neuronType?: NeuronType;
279
- /** Facts only: words a future question may use that the text does not contain. Indexed, never displayed. */
280
- keys?: string[];
281
- /**
282
- * On an exact-duplicate fact, replace its stored keys with `keys`
283
- * instead of merging them. Local only: materialize unions keys across
284
- * teammates, so a removed alias does not propagate to their brains.
285
- */
286
- keysReplace?: boolean;
287
- /** Write to this exact neuron and skip name resolution entirely. */
288
- neuronId?: string;
289
- /** Who is writing: 'session' (default), 'miner', 'manual'. */
290
- source?: string;
291
- reference?: SourceReference;
292
- temporal?: Fact['temporal'];
293
- /** Ids or verbatim texts of facts this one replaces. */
294
- supersedes?: string[];
295
- /**
296
- * Facts only: how fast this value goes stale, when the caller says so.
297
- * Stored only when given; absent, the class is inferred from the text at
298
- * read time. On an exact duplicate a different value replaces the stored one.
299
- */
300
- shelfLife?: ShelfLife;
301
- /**
302
- * Create the neuron when the topic is unknown. Default true.
303
- * The miner passes false: an automated pass guessing at topic names is
304
- * how a brain ends up with a thousand neurons called things like
305
- * `lang_pool_8_ball`, each of them shorter -- and therefore
306
- * easier to retrieve -- than the knowledge that matters.
307
- */
308
- createIfMissing?: boolean;
309
- }): Promise<{
310
- neuron: Neuron | null;
311
- /**
312
- * `skipped` — no neuron and createIfMissing was false.
313
- * `skipped_retired` — the text matches a fact or entry that was retired
314
- * (superseded or retracted); nothing was written. Re-learning a retired
315
- * line silently would undo a deliberate revision; the caller decides,
316
- * with `skipped_retired` in hand, whether to reactivate it instead.
317
- */
318
- action: 'created' | 'updated' | 'skipped' | 'skipped_retired';
319
- superseded: number;
320
- /** Supersedes targets that matched no active fact — a silent miss no more. */
321
- supersedes_unmatched: string[];
322
- /**
323
- * Active facts this one closely resembles (Dice ≥ 0.8). The fact is
324
- * stored anyway — the brain never refuses knowledge — but the caller is
325
- * told, so it can retire the older telling with supersedes/revise
326
- * instead of leaving two versions competing on recall.
327
- */
328
- near_duplicates: Array<{
329
- id: string;
330
- similarity: number;
331
- preview: string;
332
- }>;
333
- redacted: string[];
334
- /** The exact text (case-insensitive) was already an active fact of the neuron. */
335
- duplicate: boolean;
336
- /** An exact-duplicate fact had its confidence or keys changed by this call. */
337
- updated_in_place: boolean;
338
- /** Set when the text matches a retired fact/entry; nothing was written. */
339
- skipped_retired: {
340
- id: string;
341
- status: 'superseded' | 'retracted';
342
- revised?: string;
343
- note?: string;
344
- } | null;
345
- /** Exact-duplicate fact only: how many times the line has now been learned (2.7). */
346
- confirmations?: number;
347
- /** Facts only: the shelf-life class that applies, and whether it was inferred from the text (and by which rule). */
348
- shelf?: {
349
- shelf_life: ShelfLife;
350
- inferred: boolean;
351
- reason?: ShelfReason;
352
- };
353
- /** Compatibilidad de lectura: learn ya no produce esta marca. */
354
- reconfirmed?: boolean;
355
- /** An explicit shelf_life was replaced by a less volatile one (team merge restores the more volatile value). */
356
- shelf_lengthened?: boolean;
357
- }>;
358
- /**
359
- * Mark facts as no longer current.
360
- *
361
- * `superseded` — a newer fact replaces it.
362
- * `retracted` — it was never true.
363
- *
364
- * Facts are matched by id, and failing that by verbatim text, because the
365
- * caller usually has the text in front of it and not the hash.
366
- */
367
- revise(neuronRef: string, targets: string[], options?: {
368
- status?: FactStatus;
369
- note?: string;
370
- replacedBy?: string;
371
- }): Promise<{
372
- neuron: Neuron | null;
373
- revised: number;
374
- unmatched: string[];
375
- }>;
376
- /**
377
- * Reconfirm: the caller checked these lines against their source and they
378
- * still hold, so their shelf-life clock restarts now.
379
- *
380
- * `facts` match ACTIVE facts by id or exact text (trimmed, case-insensitive);
381
- * `entries` match live decisions and patterns by entry id or exact text —
382
- * the two kinds whose class is durable. A retired fact or entry is not
383
- * verifiable: it comes back in `retired` with its status (reactivate it with
384
- * status active first, if it holds again), and in `unmatched` like any miss.
385
- * Preferences, errors and debts never go stale, so there is nothing to
386
- * reconfirm on them; they are unmatched.
387
- *
388
- * Each stamp is emitted as a verify op, so on a shared neuron a teammate's
389
- * clock restarts too: the fact is shared, and so is the world it describes.
390
- */
391
- verify(neuronRef: string, targets: {
392
- facts?: string[];
393
- entries?: string[];
394
- evidence?: VerificationInput;
395
- }): Promise<{
396
- neuron: Neuron | null;
397
- verified: string[];
398
- unmatched: string[];
399
- retired: Array<{
400
- target: string;
401
- id: string;
402
- status: 'superseded' | 'retracted';
403
- }>;
404
- }>;
405
- /**
406
- * Which active facts does this text closely resemble?
407
- *
408
- * Warn-only by design. Measured on the reference brain: the heaviest
409
- * neuron held 293 facts with 1,407 near-duplicate pairs — session
410
- * summaries retelling the same thing with variations, each version as
411
- * loud as the others on recall. The fix is the writer retiring the old
412
- * telling, never the engine merging on its own.
413
- */
414
- private findNearDuplicates;
415
- /**
416
- * Flip matching facts to a non-active status.
417
- *
418
- * Also reports which targets matched nothing. Callers pass free text, and
419
- * a miss used to be indistinguishable from a hit: `supersedes` returned 0
420
- * without a word, the writer walked away believing the old version was
421
- * retired, and both versions kept surfacing on recall as equals.
422
- */
423
- private retire;
424
- /**
425
- * Bring retired facts back. The inverse of retire: only superseded or
426
- * retracted facts match, by id or by trimmed lower-cased text. Clears
427
- * superseded_by (the replacement no longer replaces it) and stamps the
428
- * revision date; the note, if given, records why it came back.
429
- */
430
- private reactivate;
431
- /**
432
- * Retire — or reactivate — decisions, patterns, errors and debts by exact
433
- * text (trimmed, case-insensitive). These are plain strings, so their
434
- * status lives in the entry_status sidecar keyed by entryId(text), the
435
- * same way their dates do. A retired entry stays in the file and leaves
436
- * recall exactly like a superseded fact; status 'active' deletes the key.
437
- *
438
- * Never emitted: the sidecar travels only through the local file and
439
- * survives a sync because applyOps copies and prunes it.
440
- */
441
- retireEntries(neuronRef: string, targets: string[], options?: {
442
- status?: FactStatus;
443
- note?: string;
444
- }): Promise<{
445
- neuron: Neuron | null;
446
- revised: number;
447
- unmatched: string[];
448
- }>;
449
- /**
450
- * Edit a neuron's metadata: summary, domain, tags, name.
451
- *
452
- * Only fields that actually differ are written and reported; a call that
453
- * changes nothing writes nothing. `tags` replaces the whole list — protocol
454
- * neurons keep their 'priority:'/'source:' tags only if the caller re-sends
455
- * them. `name` changes the display name only: the id, and with it the file,
456
- * the synapses, the shared map and the connections, never move. `domain`
457
- * replaces unconditionally, unlike learn, which only fills in 'general'.
458
- *
459
- * Not emitted: NeuronOp is only an announcement, and metadata is local.
460
- */
461
- setMeta(neuronRef: string, meta: {
462
- summary?: string;
463
- domain?: string;
464
- tags?: string[];
465
- name?: string;
466
- }): Promise<{
467
- neuron: Neuron | null;
468
- changed: Array<'summary' | 'domain' | 'tags' | 'name'>;
469
- redacted: string[];
470
- }>;
471
- /**
472
- * Replace the neuron's system map.
473
- *
474
- * Whole-document semantics on purpose: a map that can only be appended to
475
- * rots the same way facts did — old directions never die. The writer reads
476
- * the current map, rewrites it, and stores the new truth. Credentials are
477
- * redacted exactly as in learn.
478
- */
479
- setMap(neuronRef: string, content: string, options?: {
480
- domain?: string;
481
- neuronType?: NeuronType;
482
- }): Promise<{
483
- neuron: Neuron | null;
484
- action: 'created' | 'updated';
485
- redacted: string[];
486
- }>;
487
- /**
488
- * List all neurons with optional filters, and how many matched before paging.
489
- *
490
- * `list` returns only the page, which made every caller report the page size
491
- * as the total — so a client paging through 1,145 neurons was told there were
492
- * 50, and stopped. The count here is taken after the filters and before the
493
- * slice, which is the only number a pager can trust.
494
- */
495
- listWithTotal(options?: {
496
- domain?: string;
497
- type?: NeuronType;
498
- min_heat?: number;
499
- limit?: number;
500
- offset?: number;
501
- }): Promise<{
502
- total: number;
503
- rows: Awaited<ReturnType<Cortex['list']>>;
504
- }>;
505
- /**
506
- * List all neurons with optional filters.
507
- */
508
- list(options?: {
509
- domain?: string;
510
- type?: NeuronType;
511
- min_heat?: number;
512
- limit?: number;
513
- /** Rows to skip after the heat sort, for paging. Default 0. */
514
- offset?: number;
515
- }): Promise<Array<{
516
- id: string;
517
- name: string;
518
- domain: string;
519
- type: NeuronType;
520
- heat: number;
521
- last_accessed: string;
522
- facts_count: number;
523
- }>>;
524
- /**
525
- * Update a neuron's summary.
526
- */
527
- updateSummary(id: string, summary: string): Promise<Neuron | null>;
528
- /**
529
- * Add tags to a neuron.
530
- */
531
- addTags(id: string, tags: string[]): Promise<Neuron | null>;
532
- /**
533
- * Remove facts for good.
534
- *
535
- * The only destructive operation in CRBRO, so it never edits in place: the
536
- * whole neuron is copied to .quarantine/ first, with a timestamp, and can be
537
- * put back by hand. Superseding hides a fact; this is for the ones that must
538
- * not exist at all — a credential, someone's personal data.
539
- */
540
- forget(neuronRef: string, targets: string[]): Promise<{
541
- neuron_id: string | null;
542
- removed: number;
543
- backup: string | null;
544
- }>;
545
- /**
546
- * Delete a whole neuron. Quarantine copy first, then the file goes, the
547
- * index drops its chunks and the manifest is decremented.
548
- *
549
- * Synapses are not touched here (the Cortex has no Synapses): the server
550
- * calls synapses.removeAllFor(id) right after. Nor is shared state checked
551
- * — the server refuses beforehand when the neuron is shared, because the
552
- * next sync would simply re-create it from the team log. Nothing is
553
- * emitted: there is no neuron-delete op.
554
- */
555
- forgetNeuron(neuronRef: string): Promise<{
556
- neuron_id: string | null;
557
- backup: string | null;
558
- counts: {
559
- facts: number;
560
- decisions: number;
561
- patterns: number;
562
- preferences: number;
563
- errors: number;
564
- debts: number;
565
- connections: number;
566
- };
567
- }>;
568
- /**
569
- * Quarantine copies of one neuron, newest first. Stamps sort lexically, so
570
- * the file name alone orders them.
571
- */
572
- private quarantineCopies;
573
- /**
574
- * Bring a neuron back from quarantine.
575
- *
576
- * The newest copy is used unless `file` names an exact basename. If the
577
- * neuron no longer exists the copy is written back as it was; if it does
578
- * (a forget of facts, or the topic was re-created since) the copy is
579
- * unioned into it. The quarantine file stays where it is, so a restore is
580
- * repeatable. Nothing is emitted.
581
- */
582
- restoreNeuron(neuronId: string, options?: {
583
- file?: string;
584
- }): Promise<{
585
- neuron: Neuron | null;
586
- restored_from: string | null;
587
- merged_into_existing: boolean;
588
- moved: ReturnType<typeof unionNeuron>['moved'] | null;
589
- }>;
590
- /**
591
- * Fold one neuron into another and delete the first.
592
- *
593
- * `from` is quarantined, unioned into `into`, and then removed exactly like
594
- * forgetNeuron. Each element that actually moved is emitted for `into`, so
595
- * a shared target receives the knowledge (the emitter no-ops when `into`
596
- * is unshared). Synapses are not touched — the server calls
597
- * synapses.rewire(from, into) right after — and the server refuses
598
- * beforehand when `from` is shared (unshare first, or the next sync
599
- * re-creates it).
600
- */
601
- mergeNeurons(fromRef: string, intoRef: string): Promise<{
602
- from: string | null;
603
- into: string | null;
604
- backup: string | null;
605
- moved: ReturnType<typeof unionNeuron>['moved'] | null;
606
- }>;
607
- /**
608
- * Emit what a union added, by diffing the result against what the target
609
- * had. The union is pure, so this is exact: nothing the target already held
610
- * is re-announced. The emitter no-ops when the target is not shared.
611
- */
612
- private emitAdded;
613
- /**
614
- * Move entries from one neuron to another, whole: text, date, keys,
615
- * confidence, retirement. The way to split a neuron that grew past what one
616
- * read can carry — learn + forget would do it too, but every entry would be
617
- * reborn today and lose the one thing recall uses to tell old from new.
618
- *
619
- * `targets` are entry ids (factId for facts, entryId for the rest) or exact
620
- * texts, any kind. The target neuron is created when missing, with the
621
- * source's type and domain. Order is union first, removal second: a crash
622
- * in between leaves an entry in both places, never in neither. The source
623
- * is quarantined by forget() before anything leaves it. The map never
624
- * moves: it describes the system, not an entry.
625
- */
626
- moveEntries(fromRef: string, targets: string[], intoRef: string, options?: {
627
- domain?: string;
628
- }): Promise<{
629
- from: string | null;
630
- into: string | null;
631
- created: boolean;
632
- moved: number;
633
- unmatched: string[];
634
- backup: string | null;
635
- }>;
636
- /**
637
- * Fold many small neurons into one digest neuron, in a single pass.
638
- *
639
- * mergeNeurons would do it one at a time, reindexing a growing target on
640
- * every call — quadratic, and minutes on the 766 leftovers this was written
641
- * for. Here every source is quarantined, the union is built in memory,
642
- * written once and indexed once; only then do the sources go. A source's
643
- * NAME is the only context a one-line neuron had ("Phase 1 homepage audit
644
- * francortes…"), so its words travel as the fact's keys: searchable, never
645
- * shown. The caller picks the sources; nothing here judges them. Unshared
646
- * and unconnected sources only — there is no rewiring in this path.
647
- */
648
- compact(sourceIds: string[], digestName: string, options: {
649
- type: NeuronType;
650
- domain: string;
651
- }): Promise<{
652
- into: string | null;
653
- folded: string[];
654
- skipped: string[];
655
- entries: number;
656
- }>;
657
- /**
658
- * Which neurons hold something that looks like a credential.
659
- * Reports the kind and where it is, never the value.
660
- */
661
- auditSecrets(): Promise<Array<{
662
- neuron_id: string;
663
- name: string;
664
- kinds: string[];
665
- facts: number;
666
- decisions: number;
667
- patterns: number;
668
- preferences: number;
669
- errors: number;
670
- debts: number;
671
- map: number;
672
- }>>;
673
- /**
674
- * Get all neuron IDs.
675
- */
676
- allIds(): Promise<string[]>;
677
- /**
678
- * Count total neurons.
679
- */
680
- count(): Promise<number>;
681
- }
682
- //# sourceMappingURL=cortex.d.ts.map