@cmnwlth/core 0.1.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.
@@ -0,0 +1,955 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * The four note kinds that make up a brain. See docs/02-data-model.md.
5
+ * One concept per file; kind determines the folder it lives in.
6
+ */
7
+ declare const NOTE_KINDS: readonly ["memory", "decision", "work-state", "person"];
8
+ type NoteKind = (typeof NOTE_KINDS)[number];
9
+ /** Folder each kind is stored in, relative to the brain root. */
10
+ declare const KIND_DIR: Record<NoteKind, string>;
11
+ /**
12
+ * Dates are stored as `YYYY-MM-DD` strings. YAML parsers coerce unquoted dates to
13
+ * JS `Date`; this preprocessor normalizes both back to the canonical string form.
14
+ */
15
+ declare const IsoDate: z.ZodEffects<z.ZodString, string, unknown>;
16
+ declare const MemoryFrontmatter: z.ZodObject<{
17
+ kind: z.ZodLiteral<"memory">;
18
+ status: z.ZodDefault<z.ZodEnum<["active", "superseded", "stale"]>>;
19
+ /** Last time this fact was checked against reality (Kage-style verification). */
20
+ verified: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
21
+ sources: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
22
+ superseded_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
23
+ id: z.ZodEffects<z.ZodString, string, string>;
24
+ title: z.ZodString;
25
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
26
+ created: z.ZodEffects<z.ZodString, string, unknown>;
27
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
28
+ author: z.ZodOptional<z.ZodString>;
29
+ /**
30
+ * Originating project the note was captured from — a stable repo identity (git `origin`
31
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
32
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
33
+ */
34
+ source: z.ZodOptional<z.ZodString>;
35
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
36
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
37
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
38
+ kind: z.ZodLiteral<"memory">;
39
+ status: z.ZodDefault<z.ZodEnum<["active", "superseded", "stale"]>>;
40
+ /** Last time this fact was checked against reality (Kage-style verification). */
41
+ verified: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
42
+ sources: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
43
+ superseded_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
44
+ id: z.ZodEffects<z.ZodString, string, string>;
45
+ title: z.ZodString;
46
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
47
+ created: z.ZodEffects<z.ZodString, string, unknown>;
48
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
49
+ author: z.ZodOptional<z.ZodString>;
50
+ /**
51
+ * Originating project the note was captured from — a stable repo identity (git `origin`
52
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
53
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
54
+ */
55
+ source: z.ZodOptional<z.ZodString>;
56
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
57
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
58
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
59
+ kind: z.ZodLiteral<"memory">;
60
+ status: z.ZodDefault<z.ZodEnum<["active", "superseded", "stale"]>>;
61
+ /** Last time this fact was checked against reality (Kage-style verification). */
62
+ verified: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
63
+ sources: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
64
+ superseded_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
65
+ id: z.ZodEffects<z.ZodString, string, string>;
66
+ title: z.ZodString;
67
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
68
+ created: z.ZodEffects<z.ZodString, string, unknown>;
69
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
70
+ author: z.ZodOptional<z.ZodString>;
71
+ /**
72
+ * Originating project the note was captured from — a stable repo identity (git `origin`
73
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
74
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
75
+ */
76
+ source: z.ZodOptional<z.ZodString>;
77
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
78
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
79
+ }, z.ZodTypeAny, "passthrough">>;
80
+ type MemoryFrontmatter = z.infer<typeof MemoryFrontmatter>;
81
+ declare const DecisionFrontmatter: z.ZodObject<{
82
+ kind: z.ZodLiteral<"decision">;
83
+ status: z.ZodDefault<z.ZodEnum<["proposed", "accepted", "superseded"]>>;
84
+ supersedes: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
85
+ superseded_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
86
+ deciders: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
87
+ id: z.ZodEffects<z.ZodString, string, string>;
88
+ title: z.ZodString;
89
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
90
+ created: z.ZodEffects<z.ZodString, string, unknown>;
91
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
92
+ author: z.ZodOptional<z.ZodString>;
93
+ /**
94
+ * Originating project the note was captured from — a stable repo identity (git `origin`
95
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
96
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
97
+ */
98
+ source: z.ZodOptional<z.ZodString>;
99
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
100
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
101
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
102
+ kind: z.ZodLiteral<"decision">;
103
+ status: z.ZodDefault<z.ZodEnum<["proposed", "accepted", "superseded"]>>;
104
+ supersedes: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
105
+ superseded_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
106
+ deciders: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
107
+ id: z.ZodEffects<z.ZodString, string, string>;
108
+ title: z.ZodString;
109
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
110
+ created: z.ZodEffects<z.ZodString, string, unknown>;
111
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
112
+ author: z.ZodOptional<z.ZodString>;
113
+ /**
114
+ * Originating project the note was captured from — a stable repo identity (git `origin`
115
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
116
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
117
+ */
118
+ source: z.ZodOptional<z.ZodString>;
119
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
120
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
121
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
122
+ kind: z.ZodLiteral<"decision">;
123
+ status: z.ZodDefault<z.ZodEnum<["proposed", "accepted", "superseded"]>>;
124
+ supersedes: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
125
+ superseded_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
126
+ deciders: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
127
+ id: z.ZodEffects<z.ZodString, string, string>;
128
+ title: z.ZodString;
129
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
130
+ created: z.ZodEffects<z.ZodString, string, unknown>;
131
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
132
+ author: z.ZodOptional<z.ZodString>;
133
+ /**
134
+ * Originating project the note was captured from — a stable repo identity (git `origin`
135
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
136
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
137
+ */
138
+ source: z.ZodOptional<z.ZodString>;
139
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
140
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
141
+ }, z.ZodTypeAny, "passthrough">>;
142
+ type DecisionFrontmatter = z.infer<typeof DecisionFrontmatter>;
143
+ declare const WorkStateFrontmatter: z.ZodObject<{
144
+ kind: z.ZodLiteral<"work-state">;
145
+ owner: z.ZodOptional<z.ZodString>;
146
+ status: z.ZodDefault<z.ZodEnum<["planned", "in-progress", "blocked", "done"]>>;
147
+ id: z.ZodEffects<z.ZodString, string, string>;
148
+ title: z.ZodString;
149
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
150
+ created: z.ZodEffects<z.ZodString, string, unknown>;
151
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
152
+ author: z.ZodOptional<z.ZodString>;
153
+ /**
154
+ * Originating project the note was captured from — a stable repo identity (git `origin`
155
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
156
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
157
+ */
158
+ source: z.ZodOptional<z.ZodString>;
159
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
160
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
161
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
162
+ kind: z.ZodLiteral<"work-state">;
163
+ owner: z.ZodOptional<z.ZodString>;
164
+ status: z.ZodDefault<z.ZodEnum<["planned", "in-progress", "blocked", "done"]>>;
165
+ id: z.ZodEffects<z.ZodString, string, string>;
166
+ title: z.ZodString;
167
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
168
+ created: z.ZodEffects<z.ZodString, string, unknown>;
169
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
170
+ author: z.ZodOptional<z.ZodString>;
171
+ /**
172
+ * Originating project the note was captured from — a stable repo identity (git `origin`
173
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
174
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
175
+ */
176
+ source: z.ZodOptional<z.ZodString>;
177
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
178
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
179
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
180
+ kind: z.ZodLiteral<"work-state">;
181
+ owner: z.ZodOptional<z.ZodString>;
182
+ status: z.ZodDefault<z.ZodEnum<["planned", "in-progress", "blocked", "done"]>>;
183
+ id: z.ZodEffects<z.ZodString, string, string>;
184
+ title: z.ZodString;
185
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
186
+ created: z.ZodEffects<z.ZodString, string, unknown>;
187
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
188
+ author: z.ZodOptional<z.ZodString>;
189
+ /**
190
+ * Originating project the note was captured from — a stable repo identity (git `origin`
191
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
192
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
193
+ */
194
+ source: z.ZodOptional<z.ZodString>;
195
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
196
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
197
+ }, z.ZodTypeAny, "passthrough">>;
198
+ type WorkStateFrontmatter = z.infer<typeof WorkStateFrontmatter>;
199
+ declare const PersonFrontmatter: z.ZodObject<{
200
+ kind: z.ZodLiteral<"person">;
201
+ name: z.ZodString;
202
+ org: z.ZodOptional<z.ZodString>;
203
+ role: z.ZodOptional<z.ZodString>;
204
+ id: z.ZodEffects<z.ZodString, string, string>;
205
+ title: z.ZodString;
206
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
207
+ created: z.ZodEffects<z.ZodString, string, unknown>;
208
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
209
+ author: z.ZodOptional<z.ZodString>;
210
+ /**
211
+ * Originating project the note was captured from — a stable repo identity (git `origin`
212
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
213
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
214
+ */
215
+ source: z.ZodOptional<z.ZodString>;
216
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
217
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
218
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
219
+ kind: z.ZodLiteral<"person">;
220
+ name: z.ZodString;
221
+ org: z.ZodOptional<z.ZodString>;
222
+ role: z.ZodOptional<z.ZodString>;
223
+ id: z.ZodEffects<z.ZodString, string, string>;
224
+ title: z.ZodString;
225
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
226
+ created: z.ZodEffects<z.ZodString, string, unknown>;
227
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
228
+ author: z.ZodOptional<z.ZodString>;
229
+ /**
230
+ * Originating project the note was captured from — a stable repo identity (git `origin`
231
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
232
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
233
+ */
234
+ source: z.ZodOptional<z.ZodString>;
235
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
236
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
237
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
238
+ kind: z.ZodLiteral<"person">;
239
+ name: z.ZodString;
240
+ org: z.ZodOptional<z.ZodString>;
241
+ role: z.ZodOptional<z.ZodString>;
242
+ id: z.ZodEffects<z.ZodString, string, string>;
243
+ title: z.ZodString;
244
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
245
+ created: z.ZodEffects<z.ZodString, string, unknown>;
246
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
247
+ author: z.ZodOptional<z.ZodString>;
248
+ /**
249
+ * Originating project the note was captured from — a stable repo identity (git `origin`
250
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
251
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
252
+ */
253
+ source: z.ZodOptional<z.ZodString>;
254
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
255
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
256
+ }, z.ZodTypeAny, "passthrough">>;
257
+ type PersonFrontmatter = z.infer<typeof PersonFrontmatter>;
258
+ /**
259
+ * Discriminated union over `kind` — the validated frontmatter of any note. Each member is
260
+ * `.passthrough()` so unknown keys survive parse→serialize (#81): a field this build's schema
261
+ * doesn't know (a user's custom key, or one a newer schema added) is preserved rather than
262
+ * silently dropped when a note is re-serialized (e.g. sync's conflict sibling rewrite).
263
+ */
264
+ declare const Frontmatter: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
265
+ kind: z.ZodLiteral<"memory">;
266
+ status: z.ZodDefault<z.ZodEnum<["active", "superseded", "stale"]>>;
267
+ /** Last time this fact was checked against reality (Kage-style verification). */
268
+ verified: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
269
+ sources: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
270
+ superseded_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
271
+ id: z.ZodEffects<z.ZodString, string, string>;
272
+ title: z.ZodString;
273
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
274
+ created: z.ZodEffects<z.ZodString, string, unknown>;
275
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
276
+ author: z.ZodOptional<z.ZodString>;
277
+ /**
278
+ * Originating project the note was captured from — a stable repo identity (git `origin`
279
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
280
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
281
+ */
282
+ source: z.ZodOptional<z.ZodString>;
283
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
284
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
285
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
286
+ kind: z.ZodLiteral<"memory">;
287
+ status: z.ZodDefault<z.ZodEnum<["active", "superseded", "stale"]>>;
288
+ /** Last time this fact was checked against reality (Kage-style verification). */
289
+ verified: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
290
+ sources: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
291
+ superseded_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
292
+ id: z.ZodEffects<z.ZodString, string, string>;
293
+ title: z.ZodString;
294
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
295
+ created: z.ZodEffects<z.ZodString, string, unknown>;
296
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
297
+ author: z.ZodOptional<z.ZodString>;
298
+ /**
299
+ * Originating project the note was captured from — a stable repo identity (git `origin`
300
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
301
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
302
+ */
303
+ source: z.ZodOptional<z.ZodString>;
304
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
305
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
306
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
307
+ kind: z.ZodLiteral<"memory">;
308
+ status: z.ZodDefault<z.ZodEnum<["active", "superseded", "stale"]>>;
309
+ /** Last time this fact was checked against reality (Kage-style verification). */
310
+ verified: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
311
+ sources: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
312
+ superseded_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
313
+ id: z.ZodEffects<z.ZodString, string, string>;
314
+ title: z.ZodString;
315
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
316
+ created: z.ZodEffects<z.ZodString, string, unknown>;
317
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
318
+ author: z.ZodOptional<z.ZodString>;
319
+ /**
320
+ * Originating project the note was captured from — a stable repo identity (git `origin`
321
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
322
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
323
+ */
324
+ source: z.ZodOptional<z.ZodString>;
325
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
326
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
327
+ }, z.ZodTypeAny, "passthrough">>, z.ZodObject<{
328
+ kind: z.ZodLiteral<"decision">;
329
+ status: z.ZodDefault<z.ZodEnum<["proposed", "accepted", "superseded"]>>;
330
+ supersedes: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
331
+ superseded_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
332
+ deciders: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
333
+ id: z.ZodEffects<z.ZodString, string, string>;
334
+ title: z.ZodString;
335
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
336
+ created: z.ZodEffects<z.ZodString, string, unknown>;
337
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
338
+ author: z.ZodOptional<z.ZodString>;
339
+ /**
340
+ * Originating project the note was captured from — a stable repo identity (git `origin`
341
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
342
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
343
+ */
344
+ source: z.ZodOptional<z.ZodString>;
345
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
346
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
347
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
348
+ kind: z.ZodLiteral<"decision">;
349
+ status: z.ZodDefault<z.ZodEnum<["proposed", "accepted", "superseded"]>>;
350
+ supersedes: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
351
+ superseded_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
352
+ deciders: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
353
+ id: z.ZodEffects<z.ZodString, string, string>;
354
+ title: z.ZodString;
355
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
356
+ created: z.ZodEffects<z.ZodString, string, unknown>;
357
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
358
+ author: z.ZodOptional<z.ZodString>;
359
+ /**
360
+ * Originating project the note was captured from — a stable repo identity (git `origin`
361
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
362
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
363
+ */
364
+ source: z.ZodOptional<z.ZodString>;
365
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
366
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
367
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
368
+ kind: z.ZodLiteral<"decision">;
369
+ status: z.ZodDefault<z.ZodEnum<["proposed", "accepted", "superseded"]>>;
370
+ supersedes: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
371
+ superseded_by: z.ZodOptional<z.ZodNullable<z.ZodString>>;
372
+ deciders: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
373
+ id: z.ZodEffects<z.ZodString, string, string>;
374
+ title: z.ZodString;
375
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
376
+ created: z.ZodEffects<z.ZodString, string, unknown>;
377
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
378
+ author: z.ZodOptional<z.ZodString>;
379
+ /**
380
+ * Originating project the note was captured from — a stable repo identity (git `origin`
381
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
382
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
383
+ */
384
+ source: z.ZodOptional<z.ZodString>;
385
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
386
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
387
+ }, z.ZodTypeAny, "passthrough">>, z.ZodObject<{
388
+ kind: z.ZodLiteral<"work-state">;
389
+ owner: z.ZodOptional<z.ZodString>;
390
+ status: z.ZodDefault<z.ZodEnum<["planned", "in-progress", "blocked", "done"]>>;
391
+ id: z.ZodEffects<z.ZodString, string, string>;
392
+ title: z.ZodString;
393
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
394
+ created: z.ZodEffects<z.ZodString, string, unknown>;
395
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
396
+ author: z.ZodOptional<z.ZodString>;
397
+ /**
398
+ * Originating project the note was captured from — a stable repo identity (git `origin`
399
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
400
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
401
+ */
402
+ source: z.ZodOptional<z.ZodString>;
403
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
404
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
405
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
406
+ kind: z.ZodLiteral<"work-state">;
407
+ owner: z.ZodOptional<z.ZodString>;
408
+ status: z.ZodDefault<z.ZodEnum<["planned", "in-progress", "blocked", "done"]>>;
409
+ id: z.ZodEffects<z.ZodString, string, string>;
410
+ title: z.ZodString;
411
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
412
+ created: z.ZodEffects<z.ZodString, string, unknown>;
413
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
414
+ author: z.ZodOptional<z.ZodString>;
415
+ /**
416
+ * Originating project the note was captured from — a stable repo identity (git `origin`
417
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
418
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
419
+ */
420
+ source: z.ZodOptional<z.ZodString>;
421
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
422
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
423
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
424
+ kind: z.ZodLiteral<"work-state">;
425
+ owner: z.ZodOptional<z.ZodString>;
426
+ status: z.ZodDefault<z.ZodEnum<["planned", "in-progress", "blocked", "done"]>>;
427
+ id: z.ZodEffects<z.ZodString, string, string>;
428
+ title: z.ZodString;
429
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
430
+ created: z.ZodEffects<z.ZodString, string, unknown>;
431
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
432
+ author: z.ZodOptional<z.ZodString>;
433
+ /**
434
+ * Originating project the note was captured from — a stable repo identity (git `origin`
435
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
436
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
437
+ */
438
+ source: z.ZodOptional<z.ZodString>;
439
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
440
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
441
+ }, z.ZodTypeAny, "passthrough">>, z.ZodObject<{
442
+ kind: z.ZodLiteral<"person">;
443
+ name: z.ZodString;
444
+ org: z.ZodOptional<z.ZodString>;
445
+ role: z.ZodOptional<z.ZodString>;
446
+ id: z.ZodEffects<z.ZodString, string, string>;
447
+ title: z.ZodString;
448
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
449
+ created: z.ZodEffects<z.ZodString, string, unknown>;
450
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
451
+ author: z.ZodOptional<z.ZodString>;
452
+ /**
453
+ * Originating project the note was captured from — a stable repo identity (git `origin`
454
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
455
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
456
+ */
457
+ source: z.ZodOptional<z.ZodString>;
458
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
459
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
460
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
461
+ kind: z.ZodLiteral<"person">;
462
+ name: z.ZodString;
463
+ org: z.ZodOptional<z.ZodString>;
464
+ role: z.ZodOptional<z.ZodString>;
465
+ id: z.ZodEffects<z.ZodString, string, string>;
466
+ title: z.ZodString;
467
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
468
+ created: z.ZodEffects<z.ZodString, string, unknown>;
469
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
470
+ author: z.ZodOptional<z.ZodString>;
471
+ /**
472
+ * Originating project the note was captured from — a stable repo identity (git `origin`
473
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
474
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
475
+ */
476
+ source: z.ZodOptional<z.ZodString>;
477
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
478
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
479
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
480
+ kind: z.ZodLiteral<"person">;
481
+ name: z.ZodString;
482
+ org: z.ZodOptional<z.ZodString>;
483
+ role: z.ZodOptional<z.ZodString>;
484
+ id: z.ZodEffects<z.ZodString, string, string>;
485
+ title: z.ZodString;
486
+ tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
487
+ created: z.ZodEffects<z.ZodString, string, unknown>;
488
+ updated: z.ZodOptional<z.ZodEffects<z.ZodString, string, unknown>>;
489
+ author: z.ZodOptional<z.ZodString>;
490
+ /**
491
+ * Originating project the note was captured from — a stable repo identity (git `origin`
492
+ * slug, else the repo-root basename). Lets a shared brain group/filter notes by project
493
+ * (ADR-0015). Optional: pre-existing and non-project notes are "unattributed".
494
+ */
495
+ source: z.ZodOptional<z.ZodString>;
496
+ /** Wikilink targets (`[[id]]` or bare id) to related notes. */
497
+ relates: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
498
+ }, z.ZodTypeAny, "passthrough">>]>;
499
+ type Frontmatter = z.infer<typeof Frontmatter>;
500
+ /** A parsed note: validated frontmatter + markdown body + repo-relative path. */
501
+ interface Note {
502
+ frontmatter: Frontmatter;
503
+ /** Markdown content after the frontmatter block. */
504
+ body: string;
505
+ /** Path relative to the brain root, e.g. `memory/2026-07-01-foo-a1b2.md`. */
506
+ path: string;
507
+ }
508
+ /** Current on-disk schema version, pinned in `.commonwealth/schema-version`. */
509
+ declare const SCHEMA_VERSION = 1;
510
+
511
+ /**
512
+ * Secret scanner (issue #16). A shared, synced brain must never carry credentials, so
513
+ * we detect and redact common, low-false-positive secrets. Used to block secrets at
514
+ * capture (curate) and to scrub hand-edited notes at pre-commit (sync) as defense in
515
+ * depth. Detection is intentionally conservative: patterns are tuned to real credential
516
+ * shapes so ordinary prose (e.g. "the password is rotated monthly") does not match.
517
+ */
518
+ /** A single detected secret. Never carries the raw value — only a masked preview. */
519
+ interface SecretMatch {
520
+ /** Which pattern matched (e.g. "aws-access-key-id", "github-token"). */
521
+ kind: string;
522
+ /** Zero-based index of the match start within the scanned text. */
523
+ index: number;
524
+ /** Length in characters of the matched substring. */
525
+ length: number;
526
+ /** The match with its middle masked (first4 + "..." + last2); never the full secret. */
527
+ preview: string;
528
+ }
529
+ /**
530
+ * Credential patterns, ordered most-specific first so a value that could match both a
531
+ * specific provider and the generic assignment is attributed to the specific provider.
532
+ * Each `re` MUST be global (`g`) so {@link findSecrets} can iterate all matches.
533
+ */
534
+ declare const SECRET_PATTERNS: ReadonlyArray<{
535
+ kind: string;
536
+ re: RegExp;
537
+ }>;
538
+ /**
539
+ * Shannon entropy of `s` in BITS PER CHARACTER (0 for empty). A uniform random base64 string
540
+ * approaches ~6, hex ~4, English prose ~1–1.5. Used by the opt-in entropy detector to flag
541
+ * high-randomness tokens that match no named pattern (novel/custom secrets, #46).
542
+ */
543
+ declare function shannonEntropy(s: string): number;
544
+ /** Options for the scanners: opt-in entropy detection and a false-positive allowlist (#46). */
545
+ interface ScanOptions {
546
+ /**
547
+ * Also flag high-entropy base64/hex tokens that match no named pattern. Default OFF: it needs
548
+ * the {@link ScanOptions.allowlist} to stay usable (git SHAs, UUIDs, base64 data can trip it),
549
+ * so a brain opts in via config rather than it changing the zero-FP default everywhere.
550
+ */
551
+ detectEntropy?: boolean;
552
+ /** Exact token values to never flag (accepted values / known false positives). Per-brain. */
553
+ allowlist?: readonly string[];
554
+ }
555
+ /**
556
+ * Scan `text` with every pattern in {@link ALL_PATTERNS} (our hand-tuned
557
+ * {@link SECRET_PATTERNS} first, then {@link GITLEAKS_PATTERNS}) and return the matches,
558
+ * deduplicated by start index and sorted by position. When two patterns hit the same
559
+ * index, the earlier (more specific) pattern wins. Previews are masked — the raw secret
560
+ * is never returned.
561
+ */
562
+ declare function findSecrets(text: string, opts?: ScanOptions): SecretMatch[];
563
+ /** True if `text` contains at least one detected secret. */
564
+ declare function hasSecrets(text: string, opts?: ScanOptions): boolean;
565
+ /**
566
+ * Replace every detected secret in `text` with a `[REDACTED:<kind>]` placeholder,
567
+ * preserving all surrounding content. Overlapping/duplicate matches are handled by
568
+ * {@link findSecrets}; replacement runs right-to-left so earlier indices stay valid.
569
+ */
570
+ declare function redactSecrets(text: string, opts?: ScanOptions): string;
571
+
572
+ /**
573
+ * Brain-level (shared, synced) configuration, stored at `<brain>/.commonwealth/config.json`
574
+ * (ADR-0009). Distinct from the per-user, unsynced scope config at `~/.commonwealth/config.json`
575
+ * (ADR-0008). Because it lives in the repo, `features` apply to the whole team.
576
+ */
577
+ interface BrainConfig {
578
+ /** Human-readable brain name (defaults to the brain directory's basename). */
579
+ name: string;
580
+ /** On-disk schema version this brain is pinned to. */
581
+ schemaVersion: number;
582
+ /** Configured git remotes for sync (names or URLs). */
583
+ remotes: string[];
584
+ /** Free-form curation settings, reserved for the curator seam (ADR-0007). */
585
+ curation: Record<string, unknown>;
586
+ /** Team-wide feature toggles; see {@link FEATURE_FLAGS}. */
587
+ features: Record<string, boolean>;
588
+ /**
589
+ * Secret-scanner tuning (#46), committed so it applies team-wide. `entropy` opts into
590
+ * high-entropy detection beyond the named patterns; `allowlist` holds accepted values /
591
+ * known false positives to suppress. Off + empty by default (preserves the zero-FP default).
592
+ */
593
+ secretScan: {
594
+ entropy: boolean;
595
+ allowlist: string[];
596
+ };
597
+ }
598
+ /** Build the {@link ScanOptions} for the secret scanner from a brain's config (#46). */
599
+ declare function scanOptions(config: BrainConfig): ScanOptions;
600
+ /**
601
+ * Registry of the known feature flags: their name, a human-readable description, and the
602
+ * default (off unless a team opts in). New flags are added here; scaffold and
603
+ * {@link defaultBrainConfig} build the `features` block from this list.
604
+ */
605
+ declare const FEATURE_FLAGS: ReadonlyArray<{
606
+ name: string;
607
+ description: string;
608
+ default: boolean;
609
+ }>;
610
+ /**
611
+ * A fresh {@link BrainConfig} for a brain named `name`: no remotes, empty curation, and the
612
+ * `features` block filled from {@link FEATURE_FLAGS} defaults. Pinned to `SCHEMA_VERSION`.
613
+ */
614
+ declare function defaultBrainConfig(name: string): BrainConfig;
615
+ /** Absolute path to a brain's shared config file (`<brainDir>/.commonwealth/config.json`). */
616
+ declare function brainConfigPath(brainDir: string): string;
617
+ /**
618
+ * Load a brain's shared config, merged over {@link defaultBrainConfig} so any missing
619
+ * top-level field AND any missing feature key is filled in (file values win; unknown
620
+ * feature keys present in the file are preserved). Never throws on a missing or unparseable
621
+ * file — returns the defaults in that case.
622
+ */
623
+ declare function loadBrainConfig(brainDir: string): Promise<BrainConfig>;
624
+ /**
625
+ * Persist a brain's shared config as pretty (2-space) JSON with a trailing newline at
626
+ * {@link brainConfigPath}, creating the `.commonwealth/` parent directory if needed.
627
+ */
628
+ declare function saveBrainConfig(brainDir: string, config: BrainConfig): Promise<void>;
629
+ /**
630
+ * True when `feature` is enabled in the brain's shared config. Unknown or unset flags are
631
+ * treated as disabled (`false`). Never throws on a missing config file.
632
+ */
633
+ declare function isFeatureEnabled(brainDir: string, feature: string): Promise<boolean>;
634
+ /**
635
+ * Set `feature` to `on` in the brain's shared config and persist it (load-modify-save).
636
+ * Missing top-level fields and feature keys are filled from defaults on the way through.
637
+ */
638
+ declare function setFeature(brainDir: string, feature: string, on: boolean): Promise<void>;
639
+
640
+ /** A fresh collision-avoidance suffix. */
641
+ declare function shortId(): string;
642
+ /** URL/filename-safe slug of a title, capped so filenames stay reasonable. */
643
+ declare function slugify(title: string): string;
644
+ /**
645
+ * Build a note id of the form `<created>-<slug>-<shortid>`, e.g.
646
+ * `2026-07-01-auth-choice-a1b2`. The id equals the filename stem and is stable.
647
+ */
648
+ declare function makeNoteId(title: string, created: string, suffix?: string): string;
649
+ /**
650
+ * A filesystem-safe single path segment for a project `source` (ADR-0015). The source may be
651
+ * an `owner/repo` slug; we flatten separators so a project is exactly one folder level
652
+ * (`<project>/<kind>/<id>.md`), keeping the tree a fixed depth. The full source stays in
653
+ * frontmatter. Empty/invalid input yields "" (→ unattributed, note lives at the kind root).
654
+ */
655
+ declare function sourceSegment(source: string | undefined): string;
656
+ /**
657
+ * Repo-relative path for a note. With a project `source` the note lives under a per-project
658
+ * subtree (`<project>/<kind>/<id>.md`, ADR-0015); without one it stays at the kind root
659
+ * (`<kind>/<id>.md`) — which is also the back-compat location for pre-provenance notes.
660
+ */
661
+ declare function pathForNote(kind: NoteKind, id: string, source?: string): string;
662
+ /** `YYYY-MM-DD` for a given date (defaults to now). */
663
+ declare function today(date?: Date): string;
664
+
665
+ /**
666
+ * Input to create a new note. `id`, `created` (defaults to today), and the file path are
667
+ * derived; kind-specific fields (e.g. a decision's `deciders`) go in `fields` and are
668
+ * validated against the schema.
669
+ */
670
+ interface NewNoteInput {
671
+ kind: NoteKind;
672
+ title: string;
673
+ body: string;
674
+ tags?: string[];
675
+ author?: string;
676
+ /** Originating project (git repo identity); recorded as frontmatter `source` (ADR-0015). */
677
+ source?: string;
678
+ /** `YYYY-MM-DD`; defaults to today. */
679
+ created?: string;
680
+ /** Extra kind-specific frontmatter fields, validated against the schema. */
681
+ fields?: Record<string, unknown>;
682
+ }
683
+ /**
684
+ * Parse a raw markdown-with-frontmatter string into a validated {@link Note}.
685
+ * Throws (zod) if the frontmatter does not satisfy the schema for its `kind`.
686
+ */
687
+ declare function parseNote(raw: string, notePath: string): Note;
688
+ /**
689
+ * Resolve `relPath` under `brainDir` and assert it stays inside the brain (path containment).
690
+ * A `relPath` containing `../` — from a malicious MCP `read` arg or an attacker-controlled note
691
+ * id — would otherwise escape the brain and read/write arbitrary files (#76, #77). Boundary-safe:
692
+ * `/brain` does not contain `/brainiac`. Returns the resolved absolute path.
693
+ */
694
+ declare function resolveWithinBrain(brainDir: string, relPath: string): string;
695
+ /** Serialize a {@link Note} back to canonical `---`-fenced frontmatter + body. */
696
+ declare function serializeNote(note: Note): string;
697
+ /**
698
+ * Create a new note atomically under `brainDir`. The id embeds a random suffix
699
+ * (`makeNoteId`), so two concurrent writers of the same title+date produce distinct
700
+ * files that git unions rather than conflicts (ADR-0003). Writes to a temp file then
701
+ * renames, so readers never observe a partial file.
702
+ */
703
+ declare function writeNote(brainDir: string, input: NewNoteInput): Promise<Note>;
704
+ /**
705
+ * Overwrite an existing note's file with `note` (its `path`), atomically (tmp + rename). Unlike
706
+ * {@link writeNote} this INTENDS to replace an existing file — used to supersede a note in place
707
+ * (#29), never to create. Throws if the resolved path escapes the brain (#76).
708
+ */
709
+ declare function overwriteNote(brainDir: string, note: Note): Promise<void>;
710
+ /**
711
+ * Mark a memory/decision note superseded IN PLACE (supersede-not-delete, ADR-0008/#29): set
712
+ * `status: "superseded"` and `superseded_by: <survivorId>`, additive so it union-merges. Only
713
+ * memory and decision carry these fields; other kinds are returned unchanged (no-op). Returns
714
+ * the updated note, or the original when it isn't a supersede-able kind / is already superseded
715
+ * by the same survivor.
716
+ */
717
+ declare function supersedeNote(brainDir: string, relPath: string, survivorId: string): Promise<Note>;
718
+ /** Read and parse a single note by its repo-relative path. */
719
+ declare function readNote(brainDir: string, relPath: string): Promise<Note>;
720
+ /**
721
+ * List all notes, optionally filtered to one kind. Layout-agnostic (ADR-0015): notes may live
722
+ * at the kind root (`<kind>/<id>.md`, unattributed) or under a per-project subtree
723
+ * (`<project>/<kind>/<id>.md`). A file is a note when its PARENT folder is a kind folder and it
724
+ * is not the generated `INDEX.md`; the authoritative kind comes from frontmatter. Skips derived
725
+ * (`index/`), local (`staging/`), and vcs dirs so canon never includes staged/derived files.
726
+ */
727
+ declare function listNotes(brainDir: string, kind?: NoteKind): Promise<Note[]>;
728
+
729
+ interface InitBrainOptions {
730
+ /** Human-readable brain name, written into COMMONWEALTH.md / .commonwealth/config. */
731
+ name?: string;
732
+ /** Proceed even if the directory already contains files. */
733
+ force?: boolean;
734
+ }
735
+ /**
736
+ * Initialize a brain repository skeleton at `dir` (see docs/01-architecture.md §1,
737
+ * docs/02-data-model.md). Creates:
738
+ * - the four kind folders: memory/ decisions/ work-state/ people/ (each with `.gitkeep`)
739
+ * - `.commonwealth/` with `schema-version` and a `config.json` (name, schemaVersion, remotes, curation)
740
+ * - `.gitattributes` with `merge=union` for derived/append-only files (ADR-0003)
741
+ * - `.gitignore` ignoring the derived `index/` and `*.db`
742
+ * - a generated `COMMONWEALTH.md` router and per-folder `INDEX.md` placeholders
743
+ * - a git repository with an initial commit (a brain *is* a git repo; ADR-0003, ADR-0013)
744
+ *
745
+ * Idempotent: safe to call again; missing files are (re)created and an existing `.git` is left
746
+ * untouched. Throws if `dir` already contains non-Commonwealth files and `force` is not set.
747
+ */
748
+ declare function initBrain(dir: string, opts?: InitBrainOptions): Promise<void>;
749
+ declare const BRAIN_KIND_DIRS: readonly string[];
750
+
751
+ interface SearchOptions {
752
+ kind?: NoteKind;
753
+ /** Restrict to notes from one originating project (frontmatter `source`; ADR-0015). */
754
+ source?: string;
755
+ /** Max results (default 20). */
756
+ limit?: number;
757
+ }
758
+ interface SearchResult {
759
+ id: string;
760
+ kind: NoteKind;
761
+ title: string;
762
+ path: string;
763
+ /** Originating project, when the note carries one. */
764
+ source?: string;
765
+ /** Highlighted excerpt around the match. */
766
+ snippet: string;
767
+ /** Relevance score (higher = better). */
768
+ score: number;
769
+ }
770
+ /**
771
+ * (Re)build the derived SQLite FTS5 index from the markdown notes under `brainDir`.
772
+ * The index lives at `index/commonwealth.db`, is gitignored, and is fully disposable —
773
+ * it can always be rebuilt from the files. See ADR-0005.
774
+ *
775
+ * Performs a FULL rebuild each call (DROP + CREATE) so the result is a pure function
776
+ * of the note set and running it twice is idempotent. Returns the count indexed.
777
+ */
778
+ declare function buildIndex(brainDir: string): Promise<{
779
+ indexed: number;
780
+ }>;
781
+ /**
782
+ * Lexical (FTS5) search over title, body, and tags. Builds the index on first use if it
783
+ * is missing, but does NOT detect subsequent note additions/edits/removals — the index
784
+ * refreshes only when {@link buildIndex} is called. Callers that need fresh results after
785
+ * writes should rebuild first.
786
+ */
787
+ declare function search(brainDir: string, query: string, opts?: SearchOptions): Promise<SearchResult[]>;
788
+ /**
789
+ * Regenerate derived, never-hand-merged artifacts from the note set: the `COMMONWEALTH.md`
790
+ * router (grouped by project, ADR-0015) and an `INDEX.md` in every directory that holds notes
791
+ * (`<kind>/` and `<project>/<kind>/`). Idempotent — output is a pure function of the files
792
+ * (ADR-0003), so running twice yields byte-identical files.
793
+ */
794
+ declare function regenerateDerived(brainDir: string): Promise<void>;
795
+
796
+ /** One prefix → brain mapping entry in the user registry file. */
797
+ interface RegistryMapping {
798
+ /** A path prefix (tilde-allowed); a `cwd` under it maps to {@link brain}. */
799
+ prefix: string;
800
+ /** The brain directory (tilde-allowed) to use for cwds under {@link prefix}. */
801
+ brain: string;
802
+ }
803
+ /** Shape of the user registry JSON file (`~/.commonwealth/registry.json`). */
804
+ interface Registry {
805
+ mappings: RegistryMapping[];
806
+ }
807
+ /** Options for {@link resolveBrainDir}; all optional (env + registry path overrides). */
808
+ interface ResolveBrainOptions {
809
+ /** Explicit value to use instead of `process.env.COMMONWEALTH_BRAIN_DIR` (step 4). */
810
+ env?: string;
811
+ /** Explicit registry file path, overriding the default resolution (step 3). */
812
+ registryPath?: string;
813
+ }
814
+ /**
815
+ * Resolve the brain directory for `startDir`. First hit wins:
816
+ *
817
+ * 1. Walk up from `startDir`: a `.commonwealth/brain` marker file (a path, `~`-expanded and
818
+ * resolved relative to the dir holding it) pins the brain explicitly — but only when that
819
+ * target directory exists. A marker pointing at a missing brain is skipped so a stale/
820
+ * dangling marker falls through to the registry instead of hijacking resolution (#68).
821
+ * 2. Walk up: a directory that is itself a brain (`.commonwealth/schema-version`) resolves to
822
+ * itself.
823
+ * 3. The user registry file (`opts.registryPath` ?? `$COMMONWEALTH_REGISTRY` ?? sibling of
824
+ * `$COMMONWEALTH_CONFIG` ?? `~/.commonwealth/registry.json`): the first `prefix` (tilde-expanded,
825
+ * resolved) that `startDir` is under → its `brain` (tilde-expanded).
826
+ * 4. `opts.env` ?? `process.env.COMMONWEALTH_BRAIN_DIR`, if set.
827
+ * 5. `null`.
828
+ *
829
+ * Never throws on missing/unreadable files.
830
+ */
831
+ declare function resolveBrainDir(startDir: string, opts?: ResolveBrainOptions): Promise<string | null>;
832
+ /**
833
+ * Write the `.commonwealth/brain` marker in `projectDir` naming `brainPath`, creating the
834
+ * `.commonwealth/` directory if needed. Used to pin a project to its brain (registry step 1).
835
+ */
836
+ declare function setBrainMarker(projectDir: string, brainPath: string): Promise<void>;
837
+ /**
838
+ * The default user registry path (public wrapper over the internal resolver): honors
839
+ * `$COMMONWEALTH_REGISTRY`, then a `registry.json` sibling of `$COMMONWEALTH_CONFIG`, then
840
+ * `~/.commonwealth/registry.json`. This is where onboarding writes the project→brain map
841
+ * (resolution layer 3, the default source of truth).
842
+ */
843
+ declare function defaultRegistryPath(): string;
844
+ /**
845
+ * The default convenience-symlink directory (`brains/` next to the registry file), where
846
+ * `~/.commonwealth/brains/<name>` symlinks let a human `ls`/`cd` their brains.
847
+ */
848
+ declare function defaultBrainsDir(): string;
849
+ /**
850
+ * Add (or update) a `prefix → brain` mapping in the user registry, the default brain-wiring
851
+ * source of truth (resolution layer 3). Both `prefix` and `brain` are `~`-expanded and
852
+ * resolved to absolute paths; dedupe is by expanded prefix:
853
+ *
854
+ * - no mapping with this prefix → push `{ prefix, brain }` (`added: true`);
855
+ * - a mapping with this prefix but a DIFFERENT brain → update it (`updated: true`);
856
+ * - an identical mapping → no-op (`{ added: false, updated: false }`).
857
+ *
858
+ * Idempotent. Creates the registry's directory if missing and persists pretty (2-space) JSON
859
+ * atomically (tmp file + rename) so a crash mid-write cannot corrupt it. A present-but-corrupt
860
+ * registry is NOT clobbered: it is backed up to `registry.json.corrupt-<ts>` and a clear error is
861
+ * thrown, so a transient/partial-write corruption never silently wipes every other project's
862
+ * brain wiring (#78). A missing file is treated as an empty registry (the normal first-run case).
863
+ */
864
+ declare function addRegistryMapping(prefix: string, brain: string, registryPath?: string): Promise<{
865
+ added: boolean;
866
+ updated: boolean;
867
+ }>;
868
+ /**
869
+ * Drop a convenience symlink `<brainsDir>/<name> → <brainDir>` so a human can `ls`/`cd` their
870
+ * brains. `name` is sanitized via `path.basename`; an empty/`.`/`..` name is rejected. If a
871
+ * symlink already resolves to the target it is a no-op; a symlink pointing elsewhere is
872
+ * replaced; a real (non-symlink) file/dir at the path is left intact and reported as skipped.
873
+ * Never throws for unsupported/permission cases (Windows/EPERM/EACCES/ENOSYS/EEXIST) — those
874
+ * are reported via `skipped`.
875
+ */
876
+ declare function linkBrain(name: string, brainDir: string, brainsDir?: string): Promise<{
877
+ path: string;
878
+ linked: boolean;
879
+ skipped?: string;
880
+ }>;
881
+
882
+ /**
883
+ * Resolve a stable project identity for `cwd` — the value stamped as a note's frontmatter
884
+ * `source` so a shared brain can group/filter notes by originating project (ADR-0015).
885
+ *
886
+ * Order: the nearest ancestor git repo's `origin` remote, slugified to `owner/repo` → else
887
+ * that repo root's basename → else the basename of `cwd`. Best-effort and never throws: git
888
+ * being absent/erroring degrades to the basename. Returns `null` only for an empty input.
889
+ */
890
+ declare function resolveProjectSource(cwd: string): Promise<string | null>;
891
+ /**
892
+ * Reduce a git remote URL to a stable `owner/repo` identity (or bare `repo` when there is no
893
+ * owner segment). Handles `git@host:owner/repo.git`, `https://host/owner/repo(.git)`, and
894
+ * `ssh://host/owner/repo`. Returns null when nothing usable can be extracted.
895
+ */
896
+ declare function slugFromRemote(remote: string): string | null;
897
+
898
+ /**
899
+ * Brain-health / trust rollup (#109). A shared brain rots if it can't tell fresh from stale, so
900
+ * this surfaces decay: stale, never-verified, contradiction-flagged, and orphaned notes, plus a
901
+ * single headline freshness/trust score. Pure and read-only — computed from the note set (the
902
+ * source of truth), never written back (ADR-0003).
903
+ */
904
+ /** Default age (days) past which an active memory note counts as stale. Overridable per call. */
905
+ declare const DEFAULT_STALE_AFTER_DAYS = 90;
906
+ /** One bucket of the rollup: how many notes, and which (by id, for drill-down). */
907
+ interface HealthBucket {
908
+ count: number;
909
+ ids: string[];
910
+ }
911
+ /** The brain-health rollup for a note set. */
912
+ interface HealthReport {
913
+ /** Notes considered. */
914
+ total: number;
915
+ /** Explicitly `status: stale`, or an active memory note older than the stale threshold. */
916
+ stale: HealthBucket;
917
+ /** Active memory notes never checked against reality (no `verified` date). */
918
+ unverified: HealthBucket;
919
+ /** Notes flagged as contradicted (a `contradicted` tag; the future embeddings signal, #107). */
920
+ contradicted: HealthBucket;
921
+ /** Notes nothing else links to (no inbound `relates`/`supersedes`/`superseded_by`/`sources`). */
922
+ orphaned: HealthBucket;
923
+ /** Composite freshness/trust score, 0–100 (100 = nothing decayed; empty brain = 100). */
924
+ score: number;
925
+ }
926
+ /** Options for {@link brainHealth}. */
927
+ interface HealthOptions {
928
+ /** Age in days past which an active memory note is stale (default {@link DEFAULT_STALE_AFTER_DAYS}). */
929
+ staleAfterDays?: number;
930
+ /** "Today" as `YYYY-MM-DD`; defaults to the real date. Injectable for deterministic tests. */
931
+ now?: string;
932
+ }
933
+ /**
934
+ * Compute the {@link HealthReport} for `notes`. Definitions:
935
+ * - **stale**: `status: stale` (memory), OR an `active` memory note whose last touch
936
+ * (`verified` ?? `updated` ?? `created`) is older than `staleAfterDays`.
937
+ * - **unverified**: `active` memory notes with no `verified` date.
938
+ * - **contradicted**: any note carrying a `contradicted` tag.
939
+ * - **orphaned**: notes whose id is referenced by NO other note (no inbound links).
940
+ * - **score**: `100 * (1 - (serious + 0.5·soft)/total)`, where serious = stale ∪ contradicted and
941
+ * soft = (unverified ∪ orphaned) minus serious. Clamped to [0,100]; empty brain scores 100.
942
+ */
943
+ declare function brainHealth(notes: Note[], opts?: HealthOptions): HealthReport;
944
+ /** Load a brain's notes and compute its {@link HealthReport}. Read-only; never writes canon. */
945
+ declare function computeBrainHealth(brainDir: string, opts?: HealthOptions): Promise<HealthReport>;
946
+
947
+ /**
948
+ * Try to acquire the sync lock for `brainDir`. Returns a `release` function on success, or
949
+ * `null` when another LIVE process currently holds it (the caller should skip this pass). A
950
+ * stale lock (dead owner, or unreadable) is reclaimed and acquisition retried once. Never throws
951
+ * for the contended case; genuine IO errors propagate.
952
+ */
953
+ declare function acquireSyncLock(brainDir: string): Promise<(() => Promise<void>) | null>;
954
+
955
+ export { BRAIN_KIND_DIRS, type BrainConfig, DEFAULT_STALE_AFTER_DAYS, DecisionFrontmatter, FEATURE_FLAGS, Frontmatter, type HealthBucket, type HealthOptions, type HealthReport, type InitBrainOptions, IsoDate, KIND_DIR, MemoryFrontmatter, NOTE_KINDS, type NewNoteInput, type Note, type NoteKind, PersonFrontmatter, type Registry, type RegistryMapping, type ResolveBrainOptions, SCHEMA_VERSION, SECRET_PATTERNS, type ScanOptions, type SearchOptions, type SearchResult, type SecretMatch, WorkStateFrontmatter, acquireSyncLock, addRegistryMapping, brainConfigPath, brainHealth, buildIndex, computeBrainHealth, defaultBrainConfig, defaultBrainsDir, defaultRegistryPath, findSecrets, hasSecrets, initBrain, isFeatureEnabled, linkBrain, listNotes, loadBrainConfig, makeNoteId, overwriteNote, parseNote, pathForNote, readNote, redactSecrets, regenerateDerived, resolveBrainDir, resolveProjectSource, resolveWithinBrain, saveBrainConfig, scanOptions, search, serializeNote, setBrainMarker, setFeature, shannonEntropy, shortId, slugFromRemote, slugify, sourceSegment, supersedeNote, today, writeNote };