@izagood/avcs 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.
Files changed (111) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +221 -0
  3. package/dist/api/repo.d.ts +616 -0
  4. package/dist/api/repo.d.ts.map +1 -0
  5. package/dist/api/repo.js +1772 -0
  6. package/dist/api/repo.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +660 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/concurrency/lease.d.ts +27 -0
  12. package/dist/concurrency/lease.d.ts.map +1 -0
  13. package/dist/concurrency/lease.js +63 -0
  14. package/dist/concurrency/lease.js.map +1 -0
  15. package/dist/core/canonical.d.ts +16 -0
  16. package/dist/core/canonical.d.ts.map +1 -0
  17. package/dist/core/canonical.js +66 -0
  18. package/dist/core/canonical.js.map +1 -0
  19. package/dist/core/cbor.d.ts +9 -0
  20. package/dist/core/cbor.d.ts.map +1 -0
  21. package/dist/core/cbor.js +213 -0
  22. package/dist/core/cbor.js.map +1 -0
  23. package/dist/core/clock.d.ts +18 -0
  24. package/dist/core/clock.d.ts.map +1 -0
  25. package/dist/core/clock.js +32 -0
  26. package/dist/core/clock.js.map +1 -0
  27. package/dist/core/identity.d.ts +34 -0
  28. package/dist/core/identity.d.ts.map +1 -0
  29. package/dist/core/identity.js +62 -0
  30. package/dist/core/identity.js.map +1 -0
  31. package/dist/hub/hubClient.d.ts +38 -0
  32. package/dist/hub/hubClient.d.ts.map +1 -0
  33. package/dist/hub/hubClient.js +157 -0
  34. package/dist/hub/hubClient.js.map +1 -0
  35. package/dist/hub/hubServer.d.ts +28 -0
  36. package/dist/hub/hubServer.d.ts.map +1 -0
  37. package/dist/hub/hubServer.js +365 -0
  38. package/dist/hub/hubServer.js.map +1 -0
  39. package/dist/index.d.ts +13 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +19 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/objects/types.d.ts +352 -0
  44. package/dist/objects/types.d.ts.map +1 -0
  45. package/dist/objects/types.js +17 -0
  46. package/dist/objects/types.js.map +1 -0
  47. package/dist/observe/logger.d.ts +27 -0
  48. package/dist/observe/logger.d.ts.map +1 -0
  49. package/dist/observe/logger.js +37 -0
  50. package/dist/observe/logger.js.map +1 -0
  51. package/dist/observe/metrics.d.ts +20 -0
  52. package/dist/observe/metrics.d.ts.map +1 -0
  53. package/dist/observe/metrics.js +42 -0
  54. package/dist/observe/metrics.js.map +1 -0
  55. package/dist/policy/owners.d.ts +5 -0
  56. package/dist/policy/owners.d.ts.map +1 -0
  57. package/dist/policy/owners.js +38 -0
  58. package/dist/policy/owners.js.map +1 -0
  59. package/dist/policy/reliability.d.ts +7 -0
  60. package/dist/policy/reliability.d.ts.map +1 -0
  61. package/dist/policy/reliability.js +41 -0
  62. package/dist/policy/reliability.js.map +1 -0
  63. package/dist/query/diff.d.ts +16 -0
  64. package/dist/query/diff.d.ts.map +1 -0
  65. package/dist/query/diff.js +32 -0
  66. package/dist/query/diff.js.map +1 -0
  67. package/dist/reducer/incremental.d.ts +2 -0
  68. package/dist/reducer/incremental.d.ts.map +1 -0
  69. package/dist/reducer/incremental.js +14 -0
  70. package/dist/reducer/incremental.js.map +1 -0
  71. package/dist/reducer/policy.d.ts +17 -0
  72. package/dist/reducer/policy.d.ts.map +1 -0
  73. package/dist/reducer/policy.js +143 -0
  74. package/dist/reducer/policy.js.map +1 -0
  75. package/dist/reducer/reducer.d.ts +155 -0
  76. package/dist/reducer/reducer.d.ts.map +1 -0
  77. package/dist/reducer/reducer.js +849 -0
  78. package/dist/reducer/reducer.js.map +1 -0
  79. package/dist/release/sbom.d.ts +7 -0
  80. package/dist/release/sbom.d.ts.map +1 -0
  81. package/dist/release/sbom.js +26 -0
  82. package/dist/release/sbom.js.map +1 -0
  83. package/dist/semantic/contract.d.ts +32 -0
  84. package/dist/semantic/contract.d.ts.map +1 -0
  85. package/dist/semantic/contract.js +150 -0
  86. package/dist/semantic/contract.js.map +1 -0
  87. package/dist/semantic/symbols.d.ts +45 -0
  88. package/dist/semantic/symbols.d.ts.map +1 -0
  89. package/dist/semantic/symbols.js +323 -0
  90. package/dist/semantic/symbols.js.map +1 -0
  91. package/dist/store/applyRedactions.d.ts +16 -0
  92. package/dist/store/applyRedactions.d.ts.map +1 -0
  93. package/dist/store/applyRedactions.js +60 -0
  94. package/dist/store/applyRedactions.js.map +1 -0
  95. package/dist/store/lock.d.ts +12 -0
  96. package/dist/store/lock.d.ts.map +1 -0
  97. package/dist/store/lock.js +63 -0
  98. package/dist/store/lock.js.map +1 -0
  99. package/dist/store/objectStore.d.ts +127 -0
  100. package/dist/store/objectStore.d.ts.map +1 -0
  101. package/dist/store/objectStore.js +549 -0
  102. package/dist/store/objectStore.js.map +1 -0
  103. package/dist/validation/repair.d.ts +31 -0
  104. package/dist/validation/repair.d.ts.map +1 -0
  105. package/dist/validation/repair.js +37 -0
  106. package/dist/validation/repair.js.map +1 -0
  107. package/dist/validation/runner.d.ts +20 -0
  108. package/dist/validation/runner.d.ts.map +1 -0
  109. package/dist/validation/runner.js +90 -0
  110. package/dist/validation/runner.js.map +1 -0
  111. package/package.json +83 -0
@@ -0,0 +1,549 @@
1
+ // Append-only, content-addressed object store.
2
+ //
3
+ // Physical layout (under <repo>/.avcs):
4
+ // objects/<aa>/<oid>.json immutable objects, sharded by oid prefix
5
+ // refs/<name> named pointers (e.g. the default view), mutable
6
+ // HEAD the active view name
7
+ //
8
+ // Objects are never modified or deleted. "Changing" the world means appending a new
9
+ // object (a new operation, a decision, a superseding op). This is what makes AVCS
10
+ // fully auditable: the entire causal history of how code reached its current state
11
+ // is replayable.
12
+ import { mkdir, readFile, readdir, stat, open, rename, appendFile, rm } from "node:fs/promises";
13
+ import { existsSync } from "node:fs";
14
+ import { join, dirname } from "node:path";
15
+ import { Buffer } from "node:buffer";
16
+ import { computeOid, sha256hex } from "../core/canonical.js";
17
+ import { encodeCbor, decodeCbor, looksLikeCbor } from "../core/cbor.js";
18
+ import { withLock } from "./lock.js";
19
+ /**
20
+ * A stored object's bytes could not be decoded — bit-rot, truncation, or a torn write
21
+ * that slipped past the atomic-write guarantee (D1). Typed (not an opaque `SyntaxError`)
22
+ * and carries the offending `oid` so a decode failure deep in `materialize`/`pull` is
23
+ * actionable: the caller knows exactly which object to `fsck`/repair. F1 (docs/13).
24
+ */
25
+ export class CorruptObjectError extends Error {
26
+ oid;
27
+ constructor(message, opts) {
28
+ super(message, opts?.cause !== undefined ? { cause: opts.cause } : undefined);
29
+ this.name = "CorruptObjectError";
30
+ this.oid = opts?.oid;
31
+ }
32
+ }
33
+ /** Deserialize a stored object: CBOR (new format) or legacy canonical-JSON, sniffed by
34
+ * the first byte. oids are JSON-derived so both formats address identically (B1). Any
35
+ * malformed input (truncated CBOR, broken JSON, empty file) is normalized to a typed
36
+ * {@link CorruptObjectError} carrying `oid` — never an opaque parser throw (F1). */
37
+ function decodeObject(raw, oid) {
38
+ try {
39
+ return (looksLikeCbor(raw) ? decodeCbor(raw) : JSON.parse(raw.toString("utf8")));
40
+ }
41
+ catch (e) {
42
+ const where = oid ? ` ${oid}` : "";
43
+ throw new CorruptObjectError(`undecodable object${where}: ${e.message}`, { oid, cause: e });
44
+ }
45
+ }
46
+ /** Opt-out of fsync for throughput-bound bulk loads (D1). Durability traded for speed. */
47
+ const NO_FSYNC = process.env.AVCS_NO_FSYNC === "1";
48
+ export class ObjectStore {
49
+ root; // the .avcs directory
50
+ #wc = 0; // temp-file counter for atomic writes
51
+ #packLoc = null; // lazy oid → pack location index (B2)
52
+ constructor(repoDir) {
53
+ this.root = join(repoDir, ".avcs");
54
+ }
55
+ async init() {
56
+ await mkdir(join(this.root, "objects"), { recursive: true });
57
+ await mkdir(join(this.root, "refs"), { recursive: true });
58
+ await mkdir(join(this.root, "locks"), { recursive: true });
59
+ await mkdir(join(this.root, "indexes", "entity"), { recursive: true });
60
+ if (!existsSync(join(this.root, "HEAD"))) {
61
+ await this.#writeAtomic(join(this.root, "HEAD"), "main");
62
+ }
63
+ }
64
+ /**
65
+ * Crash- and concurrency-safe write: write a unique temp file in the same dir,
66
+ * fsync it, then atomically rename over the target. A reader therefore sees either
67
+ * the old file or the complete new one — never a torn/partial read. (H-5)
68
+ *
69
+ * After the rename we fsync the *containing directory* (D1): a fsync of the file
70
+ * persists its bytes but not necessarily the directory entry created by the rename,
71
+ * so a power loss could otherwise lose a just-written object/ref/HEAD even after
72
+ * this call returned. Set AVCS_NO_FSYNC=1 to skip all fsyncs for throughput-bound
73
+ * bulk loads (durability traded for speed).
74
+ */
75
+ async #writeAtomic(path, data) {
76
+ const tmp = `${path}.tmp-${process.pid}-${++this.#wc}`;
77
+ const fh = await open(tmp, "w");
78
+ try {
79
+ await fh.writeFile(data);
80
+ if (!NO_FSYNC)
81
+ await fh.sync();
82
+ }
83
+ finally {
84
+ await fh.close();
85
+ }
86
+ await rename(tmp, path); // atomic on the same filesystem
87
+ await this.#fsyncDir(dirname(path)); // persist the new directory entry
88
+ }
89
+ /**
90
+ * fsync a directory so a just-created/renamed/appended entry survives power loss.
91
+ * Best-effort: some platforms reject opening a directory for fsync (EISDIR/EPERM/
92
+ * EINVAL) — there the rename's own ordering is the durability guarantee, so we
93
+ * swallow those rather than fail the write. No-op under AVCS_NO_FSYNC.
94
+ */
95
+ async #fsyncDir(dir) {
96
+ if (NO_FSYNC)
97
+ return;
98
+ let dh;
99
+ try {
100
+ dh = await open(dir, "r");
101
+ await dh.sync();
102
+ }
103
+ catch (e) {
104
+ const code = e.code;
105
+ if (code && !["EISDIR", "EPERM", "EINVAL", "ENOENT", "EACCES"].includes(code))
106
+ throw e;
107
+ }
108
+ finally {
109
+ await dh?.close();
110
+ }
111
+ }
112
+ /**
113
+ * Durable append: append `line` to a file, fsync the file's data, and fsync its
114
+ * directory (the first append also creates the directory entry). This is what keeps
115
+ * the op-log and entity index from losing their last record(s) on a hard crash. (D1)
116
+ */
117
+ async #appendDurable(path, line) {
118
+ await appendFile(path, line, "utf8");
119
+ if (NO_FSYNC)
120
+ return;
121
+ let fh;
122
+ try {
123
+ fh = await open(path, "r+");
124
+ await fh.sync();
125
+ }
126
+ finally {
127
+ await fh?.close();
128
+ }
129
+ await this.#fsyncDir(dirname(path));
130
+ }
131
+ /**
132
+ * Atomically write a derived auxiliary file under the repo's `.avcs` root, reusing the
133
+ * crash-safe temp→fsync→rename→fsync-dir path (D1/D2). For repo-managed caches the
134
+ * store doesn't model as objects — e.g. the compaction snapshot. `relPath` is resolved
135
+ * under root; parent dirs are created. Crash-safe: a reader sees old-or-complete, and
136
+ * the file survives a hard crash once this returns.
137
+ */
138
+ async writeAux(relPath, data) {
139
+ const p = join(this.root, relPath);
140
+ await mkdir(dirname(p), { recursive: true });
141
+ await this.#writeAtomic(p, data);
142
+ }
143
+ /** Durably append a line to an auxiliary log under the repo's `.avcs` root (e.g. the
144
+ * hub audit log, E7). Reuses the fsync-file + fsync-dir append path. */
145
+ async appendAux(relPath, line) {
146
+ const p = join(this.root, relPath);
147
+ await mkdir(dirname(p), { recursive: true });
148
+ await this.#appendDurable(p, line);
149
+ }
150
+ /** Run a critical section under a named cross-process lock (see lock.ts). */
151
+ async withLock(name, fn, opts) {
152
+ return withLock(join(this.root, "locks"), name, fn, opts);
153
+ }
154
+ // ── entity index (Phase 9) ──────────────────────────────────────────────
155
+ // An append-only secondary index: entity key → op oids, sharded by key hash, so
156
+ // "history of this symbol" is O(ops-on-that-entity) instead of a full-store scan.
157
+ // It is a rebuildable cache (O_APPEND keeps small records atomic across processes).
158
+ #indexPathFor(key) {
159
+ const h = sha256hex(key);
160
+ return join(this.root, "indexes", "entity", h.slice(0, 2), `${h.slice(0, 32)}.idx`);
161
+ }
162
+ async appendEntityIndex(key, oid) {
163
+ const p = this.#indexPathFor(key);
164
+ await mkdir(dirname(p), { recursive: true });
165
+ await this.#appendDurable(p, `${oid}\n`);
166
+ }
167
+ async readEntityIndex(key) {
168
+ const p = this.#indexPathFor(key);
169
+ if (!existsSync(p))
170
+ return [];
171
+ const seen = new Set();
172
+ for (const line of (await readFile(p, "utf8")).split("\n"))
173
+ if (line)
174
+ seen.add(line);
175
+ return [...seen];
176
+ }
177
+ static isRepo(repoDir) {
178
+ return existsSync(join(repoDir, ".avcs", "objects"));
179
+ }
180
+ #pathFor(oid) {
181
+ // shard by the first 2 hex chars after the type prefix
182
+ const hexStart = oid.indexOf("_") + 1;
183
+ const shard = oid.slice(hexStart, hexStart + 2) || "00";
184
+ return join(this.root, "objects", shard, `${oid}.json`);
185
+ }
186
+ /**
187
+ * Write an object. Returns its oid. Idempotent: writing identical content yields
188
+ * the same oid and is a no-op if already present (append-only honored).
189
+ */
190
+ async put(obj) {
191
+ const { oid: _ignore, ...payload } = obj;
192
+ void _ignore;
193
+ const oid = computeOid(obj.type, payload);
194
+ const p = this.#pathFor(oid);
195
+ if (!existsSync(p)) {
196
+ await mkdir(dirname(p), { recursive: true });
197
+ // Atomic: concurrent writers of the same oid write distinct temp files and the
198
+ // rename is a no-op overwrite with identical content; never a torn object.
199
+ // Stored as canonical CBOR (B1) — oid stays JSON-derived, so this is oid-neutral.
200
+ await this.#writeAtomic(p, encodeCbor({ ...payload, oid }));
201
+ // Op-log (docs/11 A5): append the oid of every NEWLY-written operation to a single
202
+ // append-only log, AFTER the object is durable. This is the choke point through
203
+ // which every op enters the store — authoring, pull, importBundle, hub push — so
204
+ // the log is automatically consistent with the op set regardless of ingress path.
205
+ // It lets a reader tail only the ops added since its last read (incremental reduce)
206
+ // instead of scanning every shard. O_APPEND keeps small records atomic across
207
+ // processes (same pattern as the entity index).
208
+ if (obj.type === "operation")
209
+ await this.#appendDurable(join(this.root, "oplog"), `${oid}\n`);
210
+ // Object-log (E5 / docs/13): append EVERY newly-written object's oid (all types)
211
+ // to a single append-only log in arrival order. A hub serves `GET /sync?since=N`
212
+ // from it so a client fetches only objects added since its last sync, instead of
213
+ // diffing the whole oid set each time. Append-only (never reordered in normal
214
+ // operation), so a numeric cursor is stable. Rebuildable cache; backfilled lazily.
215
+ await this.#appendDurable(join(this.root, "objlog"), `${oid}\n`);
216
+ }
217
+ return oid;
218
+ }
219
+ /**
220
+ * Op-log in authoring/arrival order (docs/11 A5). Returns oids of every operation ever
221
+ * written, deduped, FIRST-WRITE order preserved. May include oids of operations later
222
+ * removed by GC (the store is the source of truth — callers tolerate a missing object).
223
+ * Empty for a store created before the op-log existed; `rebuildOpLog` backfills it.
224
+ */
225
+ async readOpLog() {
226
+ const p = join(this.root, "oplog");
227
+ if (!existsSync(p))
228
+ return [];
229
+ const seen = new Set();
230
+ const out = [];
231
+ for (const line of (await readFile(p, "utf8")).split("\n"))
232
+ if (line && !seen.has(line)) {
233
+ seen.add(line);
234
+ out.push(line);
235
+ }
236
+ return out;
237
+ }
238
+ /**
239
+ * Object-log in arrival order (E5): oids of EVERY object ever written, deduped,
240
+ * first-write order preserved. A store predating the log (or one that just upgraded)
241
+ * is backfilled once from a full scan — that scan order becomes this hub's stable
242
+ * append base. Append-only afterward, so an index into it is a valid sync cursor.
243
+ */
244
+ async readObjLog() {
245
+ const p = join(this.root, "objlog");
246
+ if (!existsSync(p))
247
+ await this.#backfillObjLog();
248
+ if (!existsSync(p))
249
+ return [];
250
+ const seen = new Set();
251
+ const out = [];
252
+ for (const line of (await readFile(p, "utf8")).split("\n"))
253
+ if (line && !seen.has(line)) {
254
+ seen.add(line);
255
+ out.push(line);
256
+ }
257
+ return out;
258
+ }
259
+ /** One-time backfill of the object-log for a store that predates it. */
260
+ async #backfillObjLog() {
261
+ const oids = [];
262
+ for await (const o of this.list())
263
+ oids.push(o.oid);
264
+ if (oids.length)
265
+ await this.#writeAtomic(join(this.root, "objlog"), oids.map((o) => `${o}\n`).join(""));
266
+ }
267
+ /** Backfill the op-log from a full scan (for stores predating it, or after corruption).
268
+ * Rewrites it atomically to the current operation set in canonical oid order. */
269
+ async rebuildOpLog() {
270
+ const oids = [];
271
+ for await (const o of this.list("operation"))
272
+ oids.push(o.oid);
273
+ oids.sort();
274
+ await this.#writeAtomic(join(this.root, "oplog"), oids.map((o) => `${o}\n`).join(""));
275
+ return oids.length;
276
+ }
277
+ /**
278
+ * Redaction exception (Phase 12): overwrite the object stored AT `oid` with new
279
+ * content that no longer hashes to it. This is the ONE place append-only/content-
280
+ * addressing yields — used only by an admin-signed Redaction to evict leaked bytes
281
+ * while keeping the oid (and every reference to it) valid.
282
+ */
283
+ async overwriteAt(oid, obj) {
284
+ const { oid: _drop, ...payload } = obj;
285
+ void _drop;
286
+ const p = this.#pathFor(oid);
287
+ await mkdir(dirname(p), { recursive: true }); // shard dir may not exist yet on a fresh clone
288
+ await this.#writeAtomic(p, encodeCbor({ ...payload, oid }));
289
+ }
290
+ /**
291
+ * GC exception: delete an object file. Used only by `repo.gc` to reclaim objects
292
+ * that are unreachable from the authoritative graph (orphan blobs, expired
293
+ * quarantined ops). The append-only audit history of accepted ops is never removed.
294
+ */
295
+ async deleteObject(oid) {
296
+ const p = this.#pathFor(oid);
297
+ if (existsSync(p))
298
+ await rm(p, { force: true });
299
+ }
300
+ async get(oid) {
301
+ const p = this.#pathFor(oid);
302
+ if (existsSync(p))
303
+ return decodeObject(await readFile(p), oid); // loose shadows packs
304
+ const loc = (await this.#packLocations()).get(oid);
305
+ if (loc)
306
+ return decodeObject(await this.#readPackSlice(loc), oid);
307
+ return decodeObject(await readFile(p), oid); // absent → throws ENOENT (prior behavior)
308
+ }
309
+ async has(oid) {
310
+ return existsSync(this.#pathFor(oid)) || (await this.#packLocations()).has(oid);
311
+ }
312
+ /** Stream every object of a given type — loose objects first, then packed ones (B2). */
313
+ async *list(type) {
314
+ const seen = new Set();
315
+ const objectsDir = join(this.root, "objects");
316
+ if (existsSync(objectsDir)) {
317
+ for (const shard of await readdir(objectsDir)) {
318
+ const shardDir = join(objectsDir, shard);
319
+ if (!(await stat(shardDir)).isDirectory())
320
+ continue;
321
+ for (const file of await readdir(shardDir)) {
322
+ if (!file.endsWith(".json"))
323
+ continue;
324
+ if (type && !file.startsWith(`${type}_`))
325
+ continue;
326
+ seen.add(file.slice(0, -".json".length));
327
+ yield decodeObject(await readFile(join(shardDir, file)), file.slice(0, -".json".length));
328
+ }
329
+ }
330
+ }
331
+ for (const [oid, loc] of await this.#packLocations()) {
332
+ if (seen.has(oid))
333
+ continue; // a re-added loose copy already yielded
334
+ if (type && !oid.startsWith(`${type}_`))
335
+ continue;
336
+ yield decodeObject(await this.#readPackSlice(loc), oid);
337
+ }
338
+ }
339
+ // ── packing (docs/11 B2) ──────────────────────────────────────────────────
340
+ // Many tiny loose object files are inode-heavy and slow to scan. `pack` folds them
341
+ // into a single append-only packfile + index (oid → offset,length). Reads check loose
342
+ // first, then packs, so packing is a transparent read optimization. BLOBS are never
343
+ // packed: redaction overwrites a blob's bytes in place (overwriteAt), and rewriting a
344
+ // packfile to evict bytes is costly — keeping blobs loose makes redaction always able
345
+ // to scrub plaintext. (Operations/evidence/decisions/etc. are append-only & immutable.)
346
+ async #packLocations() {
347
+ if (this.#packLoc)
348
+ return this.#packLoc;
349
+ const m = new Map();
350
+ const dir = join(this.root, "packs");
351
+ if (existsSync(dir)) {
352
+ for (const f of await readdir(dir)) {
353
+ if (!f.endsWith(".idx"))
354
+ continue;
355
+ const packFile = join(dir, `${f.slice(0, -".idx".length)}.pack`);
356
+ for (const line of (await readFile(join(dir, f), "utf8")).split("\n")) {
357
+ if (!line)
358
+ continue;
359
+ const [oid, off, len] = line.split(" "); // oids contain no spaces
360
+ if (oid)
361
+ m.set(oid, { file: packFile, offset: Number(off), length: Number(len) });
362
+ }
363
+ }
364
+ }
365
+ this.#packLoc = m;
366
+ return m;
367
+ }
368
+ async #readPackSlice(loc) {
369
+ const fh = await open(loc.file, "r");
370
+ try {
371
+ const buf = Buffer.alloc(loc.length);
372
+ await fh.read(buf, 0, loc.length, loc.offset);
373
+ return buf;
374
+ }
375
+ finally {
376
+ await fh.close();
377
+ }
378
+ }
379
+ /**
380
+ * Fold all loose NON-blob objects into a new packfile (+ index), then delete the loose
381
+ * copies. Idempotent in effect (already-packed objects have no loose file). Reads stay
382
+ * correct throughout (loose-first, then packs). Returns how many objects were packed.
383
+ */
384
+ async pack() {
385
+ return this.withLock("pack", async () => {
386
+ const objectsDir = join(this.root, "objects");
387
+ if (!existsSync(objectsDir))
388
+ return { packed: 0 };
389
+ const entries = [];
390
+ for (const shard of await readdir(objectsDir)) {
391
+ const shardDir = join(objectsDir, shard);
392
+ if (!(await stat(shardDir)).isDirectory())
393
+ continue;
394
+ for (const file of await readdir(shardDir)) {
395
+ if (!file.endsWith(".json") || file.startsWith("blob_"))
396
+ continue; // blobs stay loose
397
+ entries.push({ oid: file.slice(0, -".json".length), bytes: await readFile(join(shardDir, file)) });
398
+ }
399
+ }
400
+ if (entries.length === 0)
401
+ return { packed: 0 };
402
+ entries.sort((a, b) => (a.oid < b.oid ? -1 : a.oid > b.oid ? 1 : 0)); // deterministic layout
403
+ const packDir = join(this.root, "packs");
404
+ await mkdir(packDir, { recursive: true });
405
+ const n = (await readdir(packDir)).filter((f) => f.endsWith(".pack")).length;
406
+ const base = `pack-${n}`;
407
+ const idxLines = [];
408
+ let offset = 0;
409
+ for (const e of entries) {
410
+ idxLines.push(`${e.oid} ${offset} ${e.bytes.length}`);
411
+ offset += e.bytes.length;
412
+ }
413
+ // Write the packfile + index BEFORE removing loose copies (crash-safe: a crash
414
+ // leaves both, and reads prefer loose — never a lost object).
415
+ await this.#writeAtomic(join(packDir, `${base}.pack`), Buffer.concat(entries.map((e) => e.bytes)));
416
+ await this.#writeAtomic(join(packDir, `${base}.idx`), `${idxLines.join("\n")}\n`);
417
+ for (const e of entries)
418
+ await rm(this.#pathFor(e.oid), { force: true });
419
+ this.#packLoc = null; // invalidate the index cache
420
+ return { packed: entries.length };
421
+ });
422
+ }
423
+ async collect(type) {
424
+ const out = [];
425
+ for await (const o of this.list(type))
426
+ out.push(o);
427
+ return out;
428
+ }
429
+ // ── refs ────────────────────────────────────────────────────────────────
430
+ async setRef(name, oid) {
431
+ await this.#writeAtomic(join(this.root, "refs", name), oid);
432
+ }
433
+ async getRef(name) {
434
+ const p = join(this.root, "refs", name);
435
+ if (!existsSync(p))
436
+ return null;
437
+ return (await readFile(p, "utf8")).trim();
438
+ }
439
+ /** All named refs as name → oid (for hub governance distribution). */
440
+ async listRefs() {
441
+ const dir = join(this.root, "refs");
442
+ if (!existsSync(dir))
443
+ return new Map();
444
+ const out = new Map();
445
+ for (const name of await readdir(dir)) {
446
+ out.set(name, (await readFile(join(dir, name), "utf8")).trim());
447
+ }
448
+ return out;
449
+ }
450
+ async setHead(viewName) {
451
+ await this.#writeAtomic(join(this.root, "HEAD"), viewName);
452
+ }
453
+ async getHead() {
454
+ return (await readFile(join(this.root, "HEAD"), "utf8")).trim();
455
+ }
456
+ // ── integrity check (D3 / docs/12) ────────────────────────────────────────
457
+ /**
458
+ * Re-derive every stored object's content address and compare it to the address it
459
+ * lives at — catching bit-rot, truncation, and a torn write that slipped past the
460
+ * atomic-write guarantee. A redacted blob is exempt: its bytes were deliberately
461
+ * overwritten by an admin Redaction and no longer hash to their oid (that's the one
462
+ * sanctioned exception to content-addressing). Also reconciles the op-log against the
463
+ * actual operation set: operation objects missing from the log are real drift (the
464
+ * fast-path could skip them); log entries with no object are GC'd/lost (informational).
465
+ * Read-only unless `rebuild` is set, which rewrites the op-log to match the object set.
466
+ */
467
+ async fsck(opts = {}) {
468
+ const corrupt = [];
469
+ let objectsChecked = 0;
470
+ const verify = (oid, raw) => {
471
+ objectsChecked++;
472
+ let obj;
473
+ try {
474
+ obj = decodeObject(raw, oid);
475
+ }
476
+ catch (e) {
477
+ corrupt.push({ oid, reason: `undecodable: ${e.message}` });
478
+ return;
479
+ }
480
+ if (obj.type === "blob" && obj.redacted === true)
481
+ return; // sanctioned overwrite
482
+ const { oid: _drop, ...payload } = obj;
483
+ void _drop;
484
+ let recomputed;
485
+ try {
486
+ recomputed = computeOid(obj.type, payload);
487
+ }
488
+ catch (e) {
489
+ corrupt.push({ oid, reason: `unhashable content: ${e.message}` });
490
+ return;
491
+ }
492
+ if (recomputed !== oid)
493
+ corrupt.push({ oid, reason: `content hashes to ${recomputed}` });
494
+ };
495
+ // loose objects
496
+ const objectsDir = join(this.root, "objects");
497
+ if (existsSync(objectsDir)) {
498
+ for (const shard of await readdir(objectsDir)) {
499
+ const shardDir = join(objectsDir, shard);
500
+ if (!(await stat(shardDir)).isDirectory())
501
+ continue;
502
+ for (const file of await readdir(shardDir)) {
503
+ if (!file.endsWith(".json"))
504
+ continue;
505
+ verify(file.slice(0, -".json".length), await readFile(join(shardDir, file)));
506
+ }
507
+ }
508
+ }
509
+ // packed objects (loose copies, if any, already covered above and shadow these)
510
+ const looseChecked = new Set(); // avoid double-count of a re-added loose copy
511
+ for (const [oid, loc] of await this.#packLocations()) {
512
+ if (looseChecked.has(oid) || existsSync(this.#pathFor(oid)))
513
+ continue;
514
+ verify(oid, await this.#readPackSlice(loc));
515
+ }
516
+ // op-log reconciliation — collect operation oids by ADDRESS (filename / pack index),
517
+ // never by decoding, so a corrupt object (caught above) doesn't crash the log check.
518
+ const logged = new Set(await this.readOpLog());
519
+ const actualOps = new Set();
520
+ if (existsSync(objectsDir)) {
521
+ for (const shard of await readdir(objectsDir)) {
522
+ const shardDir = join(objectsDir, shard);
523
+ if (!(await stat(shardDir)).isDirectory())
524
+ continue;
525
+ for (const file of await readdir(shardDir))
526
+ if (file.startsWith("operation_") && file.endsWith(".json"))
527
+ actualOps.add(file.slice(0, -".json".length));
528
+ }
529
+ }
530
+ for (const oid of (await this.#packLocations()).keys())
531
+ if (oid.startsWith("operation_"))
532
+ actualOps.add(oid);
533
+ const opsMissingFromLog = [...actualOps].filter((o) => !logged.has(o)).sort();
534
+ const logEntriesMissingObject = [...logged].filter((o) => !actualOps.has(o)).sort();
535
+ let repaired;
536
+ if (opts.rebuild && opsMissingFromLog.length) {
537
+ const n = await this.rebuildOpLog();
538
+ repaired = { oplogRebuilt: true, oplogEntries: n };
539
+ }
540
+ return {
541
+ objectsChecked,
542
+ ok: corrupt.length === 0 && opsMissingFromLog.length === 0,
543
+ corrupt,
544
+ oplogDrift: { opsMissingFromLog, logEntriesMissingObject },
545
+ repaired,
546
+ };
547
+ }
548
+ }
549
+ //# sourceMappingURL=objectStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"objectStore.js","sourceRoot":"","sources":["../../src/store/objectStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { Decision, Evidence, Operation } from "../objects/types.ts";
2
+ export interface RepairContext {
3
+ /** The operations that failed and must be repaired. */
4
+ failedOps: {
5
+ oid: string;
6
+ purpose: string;
7
+ target: string;
8
+ path?: string;
9
+ }[];
10
+ /** The failing evidence, with its (truncated) output. */
11
+ failures: {
12
+ kind: string;
13
+ result: string;
14
+ command?: string;
15
+ detail?: string;
16
+ }[];
17
+ /** Decisions that touch these ops — prior rulings the repair must respect. */
18
+ relatedDecisions: {
19
+ oid: string;
20
+ reason: string;
21
+ futurePolicy?: string;
22
+ }[];
23
+ /** A short, imperative instruction for the agent. */
24
+ suggestion: string;
25
+ }
26
+ /**
27
+ * Build a repair packet from a set of ops and the evidence/decisions about them.
28
+ * Pure; the caller supplies the already-loaded objects.
29
+ */
30
+ export declare function buildRepairContext(ops: Operation[], evidence: Evidence[], decisions: Decision[]): RepairContext;
31
+ //# sourceMappingURL=repair.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repair.d.ts","sourceRoot":"","sources":["../../src/validation/repair.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEzE,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,SAAS,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7E,yDAAyD;IACzD,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChF,8EAA8E;IAC9E,gBAAgB,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3E,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,SAAS,EAAE,EAChB,QAAQ,EAAE,QAAQ,EAAE,EACpB,SAAS,EAAE,QAAQ,EAAE,GACpB,aAAa,CA2Bf"}
@@ -0,0 +1,37 @@
1
+ // Phase 3: RepairContext — when validation fails, hand the agent the *minimum* it
2
+ // needs to fix the problem, not the whole repo. Re-reading everything is how agents
3
+ // burn context and lose the plot; a focused repair packet keeps the loop tight.
4
+ /**
5
+ * Build a repair packet from a set of ops and the evidence/decisions about them.
6
+ * Pure; the caller supplies the already-loaded objects.
7
+ */
8
+ export function buildRepairContext(ops, evidence, decisions) {
9
+ const opIds = new Set(ops.map((o) => o.oid));
10
+ const failures = evidence
11
+ .filter((e) => e.result === "fail" && e.forOps.some((o) => opIds.has(o)))
12
+ .map((e) => ({ kind: e.kind, result: e.result, command: e.command, detail: truncate(e.detail, 1500) }));
13
+ const relatedDecisions = decisions
14
+ .filter((d) => [...d.chosenOps, ...d.rejectedOps].some((o) => opIds.has(o)))
15
+ .map((d) => ({ oid: d.oid, reason: d.reason, futurePolicy: d.futurePolicy }));
16
+ const kinds = [...new Set(failures.map((f) => f.kind))];
17
+ const suggestion = failures.length
18
+ ? `Fix the ${kinds.join(", ")} failure(s) by appending a new operation; do not hide or rewrite the failing op. Re-run the same checks. ${relatedDecisions.length ? "Respect the related prior decision(s)." : ""}`.trim()
19
+ : "No failing evidence found for these ops.";
20
+ return {
21
+ failedOps: ops.map((o) => ({
22
+ oid: o.oid,
23
+ purpose: o.declaredPurpose,
24
+ target: `${o.target.entityKind}:${o.target.entityId}`,
25
+ path: o.body.path,
26
+ })),
27
+ failures,
28
+ relatedDecisions,
29
+ suggestion,
30
+ };
31
+ }
32
+ function truncate(s, n) {
33
+ if (s === undefined)
34
+ return undefined;
35
+ return s.length > n ? s.slice(0, n) + `… (+${s.length - n} chars)` : s;
36
+ }
37
+ //# sourceMappingURL=repair.js.map