@indigoai-us/hq-cloud 6.15.79 → 6.15.81

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 (100) hide show
  1. package/dist/bin/area-ledger-migration.d.ts +13 -0
  2. package/dist/bin/area-ledger-migration.d.ts.map +1 -0
  3. package/dist/bin/area-ledger-migration.js +64 -0
  4. package/dist/bin/area-ledger-migration.js.map +1 -0
  5. package/dist/bin/area-ledger-migration.test.d.ts +2 -0
  6. package/dist/bin/area-ledger-migration.test.d.ts.map +1 -0
  7. package/dist/bin/area-ledger-migration.test.js +55 -0
  8. package/dist/bin/area-ledger-migration.test.js.map +1 -0
  9. package/dist/bin/sync-runner-company.d.ts +6 -0
  10. package/dist/bin/sync-runner-company.d.ts.map +1 -1
  11. package/dist/bin/sync-runner-company.js +21 -0
  12. package/dist/bin/sync-runner-company.js.map +1 -1
  13. package/dist/bin/sync-runner-company.test.js +112 -0
  14. package/dist/bin/sync-runner-company.test.js.map +1 -1
  15. package/dist/bin/sync-runner-events.test.js +20 -0
  16. package/dist/bin/sync-runner-events.test.js.map +1 -1
  17. package/dist/bin/sync-runner-watch-loop.d.ts +7 -0
  18. package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
  19. package/dist/bin/sync-runner-watch-loop.js +308 -20
  20. package/dist/bin/sync-runner-watch-loop.js.map +1 -1
  21. package/dist/bin/sync-runner.d.ts +5 -0
  22. package/dist/bin/sync-runner.d.ts.map +1 -1
  23. package/dist/bin/sync-runner.js.map +1 -1
  24. package/dist/bin/sync-runner.test.js +144 -1
  25. package/dist/bin/sync-runner.test.js.map +1 -1
  26. package/dist/cli/share.d.ts +8 -0
  27. package/dist/cli/share.d.ts.map +1 -1
  28. package/dist/cli/share.js +213 -15
  29. package/dist/cli/share.js.map +1 -1
  30. package/dist/cli/share.test.js +461 -31
  31. package/dist/cli/share.test.js.map +1 -1
  32. package/dist/cli/sync.d.ts +30 -0
  33. package/dist/cli/sync.d.ts.map +1 -1
  34. package/dist/cli/sync.js +83 -8
  35. package/dist/cli/sync.js.map +1 -1
  36. package/dist/cli/sync.test.js +224 -0
  37. package/dist/cli/sync.test.js.map +1 -1
  38. package/dist/cli/watch-event-push-conflict.test.js +22 -11
  39. package/dist/cli/watch-event-push-conflict.test.js.map +1 -1
  40. package/dist/journal-store.test.js +42 -1
  41. package/dist/journal-store.test.js.map +1 -1
  42. package/dist/journal.d.ts +12 -1
  43. package/dist/journal.d.ts.map +1 -1
  44. package/dist/journal.js +103 -6
  45. package/dist/journal.js.map +1 -1
  46. package/dist/s3.d.ts +62 -0
  47. package/dist/s3.d.ts.map +1 -1
  48. package/dist/s3.js +91 -1
  49. package/dist/s3.js.map +1 -1
  50. package/dist/s3.rename-retry.test.d.ts +2 -0
  51. package/dist/s3.rename-retry.test.d.ts.map +1 -0
  52. package/dist/s3.rename-retry.test.js +153 -0
  53. package/dist/s3.rename-retry.test.js.map +1 -0
  54. package/dist/sync/area-ledger-migration.d.ts +116 -0
  55. package/dist/sync/area-ledger-migration.d.ts.map +1 -0
  56. package/dist/sync/area-ledger-migration.js +505 -0
  57. package/dist/sync/area-ledger-migration.js.map +1 -0
  58. package/dist/sync/area-ledger-migration.test.d.ts +2 -0
  59. package/dist/sync/area-ledger-migration.test.d.ts.map +1 -0
  60. package/dist/sync/area-ledger-migration.test.js +274 -0
  61. package/dist/sync/area-ledger-migration.test.js.map +1 -0
  62. package/dist/sync/feature-flags.d.ts +9 -0
  63. package/dist/sync/feature-flags.d.ts.map +1 -1
  64. package/dist/sync/feature-flags.js +19 -0
  65. package/dist/sync/feature-flags.js.map +1 -1
  66. package/dist/sync/feature-flags.test.js +11 -1
  67. package/dist/sync/feature-flags.test.js.map +1 -1
  68. package/dist/sync/index.d.ts +2 -0
  69. package/dist/sync/index.d.ts.map +1 -1
  70. package/dist/sync/index.js +1 -0
  71. package/dist/sync/index.js.map +1 -1
  72. package/dist/sync/parallel-sync-coordinator.d.ts.map +1 -1
  73. package/dist/sync/parallel-sync-coordinator.js +19 -4
  74. package/dist/sync/parallel-sync-coordinator.js.map +1 -1
  75. package/dist/sync/parallel-sync-coordinator.test.js +59 -0
  76. package/dist/sync/parallel-sync-coordinator.test.js.map +1 -1
  77. package/dist/sync/reconcile-cursor.d.ts +97 -0
  78. package/dist/sync/reconcile-cursor.d.ts.map +1 -0
  79. package/dist/sync/reconcile-cursor.js +215 -0
  80. package/dist/sync/reconcile-cursor.js.map +1 -0
  81. package/dist/sync/reconcile-cursor.test.d.ts +2 -0
  82. package/dist/sync/reconcile-cursor.test.d.ts.map +1 -0
  83. package/dist/sync/reconcile-cursor.test.js +139 -0
  84. package/dist/sync/reconcile-cursor.test.js.map +1 -0
  85. package/dist/sync/state-store.d.ts +37 -0
  86. package/dist/sync/state-store.d.ts.map +1 -1
  87. package/dist/sync/state-store.js +109 -1
  88. package/dist/sync/state-store.js.map +1 -1
  89. package/dist/sync/sync-work.d.ts +2 -1
  90. package/dist/sync/sync-work.d.ts.map +1 -1
  91. package/dist/sync/sync-work.js.map +1 -1
  92. package/dist/types.d.ts +6 -0
  93. package/dist/types.d.ts.map +1 -1
  94. package/dist/vault-client.d.ts +9 -2
  95. package/dist/vault-client.d.ts.map +1 -1
  96. package/dist/vault-client.js +3 -2
  97. package/dist/vault-client.js.map +1 -1
  98. package/dist/vault-client.test.js +26 -0
  99. package/dist/vault-client.test.js.map +1 -1
  100. package/package.json +3 -2
@@ -0,0 +1,139 @@
1
+ import * as fs from "node:fs";
2
+ import * as os from "node:os";
3
+ import * as path from "node:path";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import { ReconcileCursorStore, checkpointReconcileApply, takeBoundedReconcileSlice, } from "./reconcile-cursor.js";
6
+ const roots = [];
7
+ afterEach(() => {
8
+ for (const root of roots.splice(0))
9
+ fs.rmSync(root, { recursive: true, force: true });
10
+ });
11
+ function root() {
12
+ const value = fs.mkdtempSync(path.join(os.tmpdir(), "hq-reconcile-cursor-test-"));
13
+ roots.push(value);
14
+ return value;
15
+ }
16
+ function cursor(phase, overrides = {}) {
17
+ return { routerVersion: 1, epoch: "epoch-1", areaId: "root:notes", phase, ...overrides };
18
+ }
19
+ function open(dir) {
20
+ return ReconcileCursorStore.open({ rootDir: dir, journalSlug: "personal", layoutEpoch: 1, areaId: "root:notes" });
21
+ }
22
+ describe("ReconcileCursorStore", () => {
23
+ it("resumes each discovery phase and does not revisit a completed area", () => {
24
+ const dir = root();
25
+ const first = open(dir);
26
+ first.checkpointDiscovery(cursor("local-discovery", { localDirectoryStack: ["notes"], localAfterPath: "notes/a.md" }));
27
+ expect(open(dir).read().cursor).toMatchObject({ phase: "local-discovery", localAfterPath: "notes/a.md" });
28
+ open(dir).checkpointDiscovery(cursor("remote-list", { remotePrefix: "notes/", remoteContinuation: "page-2" }));
29
+ expect(open(dir).read().cursor).toMatchObject({ phase: "remote-list", remoteContinuation: "page-2" });
30
+ open(dir).checkpointDiscovery(cursor("diff", { journalAfterKey: "notes/a.md", remoteHighWater: "etag-9" }));
31
+ expect(open(dir).read().cursor).toMatchObject({ phase: "diff", journalAfterKey: "notes/a.md" });
32
+ open(dir).complete("epoch-1");
33
+ expect(open(dir).read()).toEqual({ format: 1, completedEpoch: "epoch-1" });
34
+ });
35
+ it("only advances apply after each delete/tombstone outcome is durable", () => {
36
+ const dir = root();
37
+ const store = open(dir);
38
+ expect(() => store.checkpointApply(cursor("apply", { journalAfterKey: "notes/deleted.md" }), [
39
+ { path: "notes/deleted.md", durable: false },
40
+ ])).toThrow("before every path outcome is durable");
41
+ expect(store.read().cursor).toBeUndefined();
42
+ store.checkpointApply(cursor("apply", { journalAfterKey: "notes/deleted.md" }), [
43
+ { path: "notes/deleted.md", durable: true },
44
+ { path: "notes/tombstone.md", durable: true },
45
+ ]);
46
+ expect(open(dir).read().cursor).toMatchObject({ phase: "apply", journalAfterKey: "notes/deleted.md" });
47
+ });
48
+ it("advances an entrypoint apply cursor only after the caller reports durable paths", () => {
49
+ const dir = root();
50
+ const store = open(dir);
51
+ checkpointReconcileApply({ store, cursor: cursor("apply", { journalAfterKey: "notes/tombstone.md" }) }, ["notes/upload.md", "notes/tombstone.md"]);
52
+ expect(open(dir).read().cursor).toMatchObject({ phase: "apply", journalAfterKey: "notes/tombstone.md" });
53
+ });
54
+ it("invalidates a remote continuation when a later inventory epoch supersedes it", () => {
55
+ const dir = root();
56
+ const store = open(dir);
57
+ store.checkpointDiscovery(cursor("remote-list", { remotePrefix: "notes/", remoteContinuation: "page-8", remoteHighWater: "old" }));
58
+ expect(store.invalidateRemoteContinuation("epoch-1", "new")).toMatchObject({
59
+ phase: "remote-list",
60
+ remoteHighWater: "new",
61
+ });
62
+ const resumed = open(dir).read().cursor;
63
+ expect(resumed).not.toHaveProperty("remoteContinuation");
64
+ expect(resumed.remoteHighWater).toBe("new");
65
+ });
66
+ it("keeps cursor state isolated per area", () => {
67
+ const dir = root();
68
+ const alpha = ReconcileCursorStore.open({ rootDir: dir, journalSlug: "personal", layoutEpoch: 1, areaId: "root:alpha" });
69
+ const beta = ReconcileCursorStore.open({ rootDir: dir, journalSlug: "personal", layoutEpoch: 1, areaId: "root:beta" });
70
+ alpha.checkpointDiscovery({ routerVersion: 1, epoch: "one", areaId: "root:alpha", phase: "diff" });
71
+ expect(beta.read().cursor).toBeUndefined();
72
+ });
73
+ it("ignores stale checkpoints and completion records from an older epoch", () => {
74
+ const dir = root();
75
+ const current = open(dir);
76
+ const stale = open(dir);
77
+ current.checkpointDiscovery(cursor("diff"));
78
+ current.complete("epoch-1");
79
+ current.checkpointDiscovery({ ...cursor("diff"), epoch: "epoch-2" });
80
+ stale.checkpointDiscovery(cursor("remote-list", { remoteContinuation: "late" }));
81
+ stale.complete("epoch-1");
82
+ expect(open(dir).read()).toMatchObject({
83
+ cursor: { epoch: "epoch-2", phase: "diff" },
84
+ });
85
+ current.complete("epoch-2");
86
+ expect(open(dir).read()).toEqual({ format: 1, completedEpoch: "epoch-2" });
87
+ });
88
+ });
89
+ describe("takeBoundedReconcileSlice", () => {
90
+ it("yields by count, bytes, and wall-clock without materializing the inventory", () => {
91
+ function* inventory() {
92
+ for (let index = 0; index < 562_000; index += 1)
93
+ yield { path: `notes/${index}.md`, bytes: 1 };
94
+ }
95
+ const largeInventoryResult = takeBoundedReconcileSlice(inventory(), { maxEntries: 512 });
96
+ expect(largeInventoryResult.entries).toHaveLength(512);
97
+ expect(largeInventoryResult).toMatchObject({ bytes: 512, yielded: true });
98
+ expect(takeBoundedReconcileSlice([{ path: "one", bytes: 8 }, { path: "two", bytes: 8 }], { maxBytes: 10 })).toMatchObject({ entries: [{ path: "one", bytes: 8 }], bytes: 8, yielded: true });
99
+ let time = 0;
100
+ const result = takeBoundedReconcileSlice([{ path: "one", bytes: 1 }, { path: "two", bytes: 1 }], {
101
+ maxWallClockMs: 50,
102
+ now: () => (time += 50),
103
+ });
104
+ expect(result).toMatchObject({ entries: [{ path: "one", bytes: 1 }], yielded: true });
105
+ });
106
+ it("checks cancellation between every file and returns the completed prefix", () => {
107
+ let checks = 0;
108
+ const result = takeBoundedReconcileSlice([
109
+ { path: "notes/one", bytes: 1 },
110
+ { path: "notes/two", bytes: 1 },
111
+ ], { isCancelled: () => ++checks === 2 });
112
+ expect(result).toEqual({
113
+ entries: [{ path: "notes/one", bytes: 1 }],
114
+ bytes: 1,
115
+ yielded: true,
116
+ cancelled: true,
117
+ deferred: { path: "notes/two", bytes: 1 },
118
+ });
119
+ });
120
+ it("retains a generator remainder after yielding a bounded slice", () => {
121
+ function* inventory() {
122
+ yield { path: "notes/one", bytes: 1 };
123
+ yield { path: "notes/two", bytes: 1 };
124
+ yield { path: "notes/three", bytes: 1 };
125
+ }
126
+ const source = inventory();
127
+ const first = takeBoundedReconcileSlice(source, { maxEntries: 1 });
128
+ expect(first.deferred).toEqual({ path: "notes/two", bytes: 1 });
129
+ function* resumed() {
130
+ yield first.deferred;
131
+ yield* source;
132
+ }
133
+ expect(takeBoundedReconcileSlice(resumed(), { maxEntries: 10 }).entries).toEqual([
134
+ { path: "notes/two", bytes: 1 },
135
+ { path: "notes/three", bytes: 1 },
136
+ ]);
137
+ });
138
+ });
139
+ //# sourceMappingURL=reconcile-cursor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile-cursor.test.js","sourceRoot":"","sources":["../../src/sync/reconcile-cursor.test.ts"],"names":[],"mappings":"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"}
@@ -80,6 +80,30 @@ export interface StateStoreRecoveryStats {
80
80
  /** Largest single snapshot payload or WAL frame buffered during recovery. */
81
81
  maxReadBytes: number;
82
82
  }
83
+ /** A stable identity for one complete snapshot/WAL generation. */
84
+ export interface StateStoreGenerationIdentity {
85
+ generation: number;
86
+ lastRecordSequence: number;
87
+ walBytes: number;
88
+ }
89
+ /**
90
+ * A durable lease on an immutable source generation.
91
+ *
92
+ * Rotation normally keeps only a short rollback history. Migration uses this
93
+ * lease to make an older source generation part of that history until the
94
+ * copy/catch-up transaction has finished (or has explicitly been abandoned).
95
+ */
96
+ export interface StateStoreGenerationPin {
97
+ readonly identity: StateStoreGenerationIdentity;
98
+ /** Durable pin file, persisted by long-running migration control state. */
99
+ readonly path: string;
100
+ release(): void;
101
+ }
102
+ /** One bounded value yielded from a keyed state projection. */
103
+ export interface StateStoreStateEntry {
104
+ key: string;
105
+ value: unknown;
106
+ }
83
107
  export interface StateStoreRepairResult {
84
108
  recoveredGeneration: number;
85
109
  recoveredWalBytes: number;
@@ -153,6 +177,19 @@ export declare class StateStore<T> {
153
177
  getGeneration(): number;
154
178
  getLastRecordSequence(): number;
155
179
  getRecoveryStats(): StateStoreRecoveryStats;
180
+ getGenerationIdentity(): StateStoreGenerationIdentity;
181
+ /**
182
+ * Persist a generation pin while holding append.lock. The pin is a tiny
183
+ * checksummed file in the store directory, so a concurrent compactor sees it
184
+ * before deciding which immutable generations may be pruned.
185
+ */
186
+ pinCurrentGeneration(): StateStoreGenerationPin;
187
+ /**
188
+ * Iterate a keyed projection without exposing its mutable backing object.
189
+ * Each yielded row is cloned independently, allowing migration clients to
190
+ * keep projected WAL records bounded even when the source journal is huge.
191
+ */
192
+ iterateStateEntries(path: readonly string[]): IterableIterator<StateStoreStateEntry>;
156
193
  append(type: number, payload: unknown, flags?: number): StateStoreAppendResult;
157
194
  /**
158
195
  * Async lock acquisition for callback-originated work. The write itself
@@ -1 +1 @@
1
- {"version":3,"file":"state-store.d.ts","sourceRoot":"","sources":["../../src/sync/state-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"state-store.d.ts","sourceRoot":"","sources":["../../src/sync/state-store.ts"],"names":[],"mappings":"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"}
@@ -434,6 +434,70 @@ export class StateStore {
434
434
  getRecoveryStats() {
435
435
  return { walBytes: this.walBytes, maxReadBytes: this.maxRecoveryReadBytes };
436
436
  }
437
+ getGenerationIdentity() {
438
+ return {
439
+ generation: this.generation,
440
+ lastRecordSequence: this.lastRecordSequence,
441
+ walBytes: this.walBytes,
442
+ };
443
+ }
444
+ /**
445
+ * Persist a generation pin while holding append.lock. The pin is a tiny
446
+ * checksummed file in the store directory, so a concurrent compactor sees it
447
+ * before deciding which immutable generations may be pruned.
448
+ */
449
+ pinCurrentGeneration() {
450
+ while (true) {
451
+ const pin = withScopeLock(this.stateDir, () => {
452
+ const refresh = this.refreshFromDisk();
453
+ if (!refresh)
454
+ return undefined;
455
+ const identity = this.getGenerationIdentity();
456
+ const pinPath = writeGenerationPin(this.stateDir, this.scopeDigest, identity);
457
+ let released = false;
458
+ return {
459
+ identity,
460
+ path: pinPath,
461
+ release: () => {
462
+ if (released)
463
+ return;
464
+ released = true;
465
+ try {
466
+ fs.unlinkSync(pinPath);
467
+ fsyncDirectory(this.stateDir);
468
+ }
469
+ catch (error) {
470
+ if (!isMissing(error))
471
+ throw new Error(`state-store: cannot release generation pin ${pinPath}`, { cause: error });
472
+ }
473
+ },
474
+ };
475
+ });
476
+ if (pin)
477
+ return pin;
478
+ this.recoverNewestGenerationOutsideLock();
479
+ }
480
+ }
481
+ /**
482
+ * Iterate a keyed projection without exposing its mutable backing object.
483
+ * Each yielded row is cloned independently, allowing migration clients to
484
+ * keep projected WAL records bounded even when the source journal is huge.
485
+ */
486
+ *iterateStateEntries(path) {
487
+ let current = this.state;
488
+ for (const segment of path) {
489
+ if (typeof current !== "object" || current === null || Array.isArray(current) || !Object.hasOwn(current, segment)) {
490
+ throw new Error(`state-store: state path ${JSON.stringify(path)} is not an object map`);
491
+ }
492
+ current = current[segment];
493
+ }
494
+ if (typeof current !== "object" || current === null || Array.isArray(current)) {
495
+ throw new Error(`state-store: state path ${JSON.stringify(path)} is not an object map`);
496
+ }
497
+ for (const [key, value] of Object.entries(current)) {
498
+ yield { key, value: structuredClone(value) };
499
+ }
500
+ }
437
501
  append(type, payload, flags = 0) {
438
502
  assertUint16(type, "record type");
439
503
  assertUint16(flags, "record flags");
@@ -2172,7 +2236,7 @@ function retainedGenerationHistoryNeedsRepair(dir, newestGeneration, currentGene
2172
2236
  return false;
2173
2237
  }
2174
2238
  function pruneGenerations(dir, retain) {
2175
- const retained = new Set(retain);
2239
+ const retained = new Set([...retain, ...pinnedGenerations(dir)]);
2176
2240
  for (const name of fs.readdirSync(dir)) {
2177
2241
  const match = /^(?:snapshot|wal)-(\d+)\.bin$/.exec(name);
2178
2242
  if (!match)
@@ -2189,6 +2253,50 @@ function pruneGenerations(dir, retain) {
2189
2253
  }
2190
2254
  fsyncDirectory(dir);
2191
2255
  }
2256
+ function writeGenerationPin(dir, scopeDigest, identity) {
2257
+ const body = {
2258
+ generation: identity.generation,
2259
+ lastRecordSequence: identity.lastRecordSequence,
2260
+ walBytes: identity.walBytes,
2261
+ scopeDigest: scopeDigest.toString("hex"),
2262
+ };
2263
+ const checksum = sha256(Buffer.from(canonicalJson(body), "utf8")).toString("hex");
2264
+ const pinPath = path.join(dir, `generation-pin-${process.pid}-${crypto.randomBytes(8).toString("hex")}.json`);
2265
+ writeNewDurably(pinPath, Buffer.from(`${canonicalJson({ ...body, checksum })}\n`, "utf8"));
2266
+ fsyncDirectory(dir);
2267
+ return pinPath;
2268
+ }
2269
+ /** Invalid pins are retained conservatively: pruning is never allowed to win a crash race. */
2270
+ function pinnedGenerations(dir) {
2271
+ const pins = new Set();
2272
+ for (const name of fs.readdirSync(dir)) {
2273
+ if (!/^generation-pin-[A-Za-z0-9-]+\.json$/.test(name))
2274
+ continue;
2275
+ try {
2276
+ const raw = JSON.parse(fs.readFileSync(path.join(dir, name), "utf8"));
2277
+ const { checksum, ...body } = raw;
2278
+ if (typeof checksum !== "string" ||
2279
+ checksum !== sha256(Buffer.from(canonicalJson(body), "utf8")).toString("hex") ||
2280
+ !Number.isSafeInteger(body.generation) ||
2281
+ body.generation < 1) {
2282
+ // A torn pin represents an in-flight migration; retain every local
2283
+ // generation rather than guessing which source it meant to protect.
2284
+ return fs.readdirSync(dir)
2285
+ .map((candidate) => /^(?:snapshot|wal)-(\d+)\.bin$/.exec(candidate)?.[1])
2286
+ .filter((value) => value !== undefined)
2287
+ .map(Number);
2288
+ }
2289
+ pins.add(body.generation);
2290
+ }
2291
+ catch {
2292
+ return fs.readdirSync(dir)
2293
+ .map((candidate) => /^(?:snapshot|wal)-(\d+)\.bin$/.exec(candidate)?.[1])
2294
+ .filter((value) => value !== undefined)
2295
+ .map(Number);
2296
+ }
2297
+ }
2298
+ return [...pins];
2299
+ }
2192
2300
  function cleanupUnpublishedInitialGeneration(dir) {
2193
2301
  if (fs.existsSync(path.join(dir, "current")))
2194
2302
  return;