@indigoai-us/hq-cloud 6.18.53 → 6.18.54

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 (110) hide show
  1. package/dist/bin/sync-runner-audit.d.ts +26 -0
  2. package/dist/bin/sync-runner-audit.d.ts.map +1 -0
  3. package/dist/bin/sync-runner-audit.js +51 -0
  4. package/dist/bin/sync-runner-audit.js.map +1 -0
  5. package/dist/bin/sync-runner-company.d.ts +18 -0
  6. package/dist/bin/sync-runner-company.d.ts.map +1 -1
  7. package/dist/bin/sync-runner-company.js +186 -9
  8. package/dist/bin/sync-runner-company.js.map +1 -1
  9. package/dist/bin/sync-runner-watch-loop.d.ts +107 -5
  10. package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
  11. package/dist/bin/sync-runner-watch-loop.js +1382 -183
  12. package/dist/bin/sync-runner-watch-loop.js.map +1 -1
  13. package/dist/bin/sync-runner.d.ts +63 -11
  14. package/dist/bin/sync-runner.d.ts.map +1 -1
  15. package/dist/bin/sync-runner.js +350 -95
  16. package/dist/bin/sync-runner.js.map +1 -1
  17. package/dist/bin/watcher-catchup-skip-store.d.ts +60 -0
  18. package/dist/bin/watcher-catchup-skip-store.d.ts.map +1 -0
  19. package/dist/bin/watcher-catchup-skip-store.js +282 -0
  20. package/dist/bin/watcher-catchup-skip-store.js.map +1 -0
  21. package/dist/cli/conflict.d.ts +6 -0
  22. package/dist/cli/conflict.d.ts.map +1 -1
  23. package/dist/cli/conflict.js +3 -1
  24. package/dist/cli/conflict.js.map +1 -1
  25. package/dist/cli/reindex.d.ts.map +1 -1
  26. package/dist/cli/reindex.js +95 -5
  27. package/dist/cli/reindex.js.map +1 -1
  28. package/dist/cli/rescue-core.d.ts +25 -1
  29. package/dist/cli/rescue-core.d.ts.map +1 -1
  30. package/dist/cli/rescue-core.js +69 -4
  31. package/dist/cli/rescue-core.js.map +1 -1
  32. package/dist/cli/share.d.ts +27 -0
  33. package/dist/cli/share.d.ts.map +1 -1
  34. package/dist/cli/share.js +140 -23
  35. package/dist/cli/share.js.map +1 -1
  36. package/dist/cli/sync.d.ts +18 -2
  37. package/dist/cli/sync.d.ts.map +1 -1
  38. package/dist/cli/sync.js +90 -25
  39. package/dist/cli/sync.js.map +1 -1
  40. package/dist/ignore.d.ts +1 -1
  41. package/dist/ignore.d.ts.map +1 -1
  42. package/dist/ignore.js +2 -2
  43. package/dist/ignore.js.map +1 -1
  44. package/dist/journal-row-store.d.ts.map +1 -1
  45. package/dist/journal-row-store.js +6 -0
  46. package/dist/journal-row-store.js.map +1 -1
  47. package/dist/journal-snapshot-v4.d.ts +8 -0
  48. package/dist/journal-snapshot-v4.d.ts.map +1 -1
  49. package/dist/journal-snapshot-v4.js +208 -17
  50. package/dist/journal-snapshot-v4.js.map +1 -1
  51. package/dist/journal.d.ts +18 -2
  52. package/dist/journal.d.ts.map +1 -1
  53. package/dist/journal.js +248 -17
  54. package/dist/journal.js.map +1 -1
  55. package/dist/lib/cloud-authoritative.d.ts +9 -2
  56. package/dist/lib/cloud-authoritative.d.ts.map +1 -1
  57. package/dist/lib/cloud-authoritative.js +34 -2
  58. package/dist/lib/cloud-authoritative.js.map +1 -1
  59. package/dist/lib/exit-codes.d.ts +2 -0
  60. package/dist/lib/exit-codes.d.ts.map +1 -1
  61. package/dist/lib/exit-codes.js +2 -0
  62. package/dist/lib/exit-codes.js.map +1 -1
  63. package/dist/personal-vault-exclusions.d.ts +2 -2
  64. package/dist/personal-vault-exclusions.d.ts.map +1 -1
  65. package/dist/personal-vault-exclusions.js +5 -3
  66. package/dist/personal-vault-exclusions.js.map +1 -1
  67. package/dist/personal-vault.d.ts +7 -0
  68. package/dist/personal-vault.d.ts.map +1 -1
  69. package/dist/personal-vault.js +10 -0
  70. package/dist/personal-vault.js.map +1 -1
  71. package/dist/qmd-runner-admission.d.ts +22 -0
  72. package/dist/qmd-runner-admission.d.ts.map +1 -0
  73. package/dist/qmd-runner-admission.js +107 -0
  74. package/dist/qmd-runner-admission.js.map +1 -0
  75. package/dist/symlink-target-policy.d.ts +11 -0
  76. package/dist/symlink-target-policy.d.ts.map +1 -1
  77. package/dist/symlink-target-policy.js +110 -0
  78. package/dist/symlink-target-policy.js.map +1 -1
  79. package/dist/sync/area-ledger-migration.d.ts +3 -1
  80. package/dist/sync/area-ledger-migration.d.ts.map +1 -1
  81. package/dist/sync/area-ledger-migration.js +3 -0
  82. package/dist/sync/area-ledger-migration.js.map +1 -1
  83. package/dist/sync/area-ledger.d.ts +3 -0
  84. package/dist/sync/area-ledger.d.ts.map +1 -1
  85. package/dist/sync/area-ledger.js +29 -6
  86. package/dist/sync/area-ledger.js.map +1 -1
  87. package/dist/sync/mutation-session.d.ts.map +1 -1
  88. package/dist/sync/mutation-session.js +4 -0
  89. package/dist/sync/mutation-session.js.map +1 -1
  90. package/dist/sync/parallel-sync-coordinator.d.ts +29 -0
  91. package/dist/sync/parallel-sync-coordinator.d.ts.map +1 -1
  92. package/dist/sync/parallel-sync-coordinator.js +229 -16
  93. package/dist/sync/parallel-sync-coordinator.js.map +1 -1
  94. package/dist/sync/push-receiver.d.ts +5 -0
  95. package/dist/sync/push-receiver.d.ts.map +1 -1
  96. package/dist/sync/push-receiver.js +32 -10
  97. package/dist/sync/push-receiver.js.map +1 -1
  98. package/dist/sync/state-store.d.ts +7 -0
  99. package/dist/sync/state-store.d.ts.map +1 -1
  100. package/dist/sync/state-store.js +113 -6
  101. package/dist/sync/state-store.js.map +1 -1
  102. package/dist/watch-owner-lease.d.ts +4 -0
  103. package/dist/watch-owner-lease.d.ts.map +1 -1
  104. package/dist/watch-owner-lease.js +40 -6
  105. package/dist/watch-owner-lease.js.map +1 -1
  106. package/dist/watcher.d.ts +16 -3
  107. package/dist/watcher.d.ts.map +1 -1
  108. package/dist/watcher.js +114 -21
  109. package/dist/watcher.js.map +1 -1
  110. package/package.json +4 -3
@@ -70,6 +70,8 @@ const COMPACTION_RETRY_BACKOFF_MAX_MS = 250;
70
70
  const COMPACTION_RETRY_MIN_ATTEMPTS = 3;
71
71
  /** Safety cap so a frozen test clock cannot spin forever. */
72
72
  const COMPACTION_RETRY_MAX_ATTEMPTS = 10_000;
73
+ /** Keep a live synchronous writer from invalidating async snapshots forever. */
74
+ const ASYNC_COMPACTION_MAX_STALE_ATTEMPTS = 3;
73
75
  // Test instrumentation for materialisation regressions. Kept at the storage
74
76
  // seam so a fixture counts actual snapshot JSON decodes, not API invocations.
75
77
  let snapshotRecoveryCount = 0;
@@ -309,6 +311,7 @@ export class StateStore {
309
311
  walBytes;
310
312
  maxRecoveryReadBytes;
311
313
  observedHighestSnapshotGeneration;
314
+ deferredCompactionScheduled = false;
312
315
  constructor(options, recovered, wasCreated) {
313
316
  this.options = options;
314
317
  this.scopeDigest = digestScope(options.scopeId);
@@ -345,8 +348,16 @@ export class StateStore {
345
348
  // A process can die after its durable append but before append() gets
346
349
  // to its post-lock compaction. Repair that crash window before handing
347
350
  // an already-over-budget WAL to the caller, otherwise restart loops
348
- // can grow a WAL without bound.
349
- store.compactIfNeeded();
351
+ // can grow a WAL without bound. Large domain encoders defer that
352
+ // repair so opening a journal on a watcher pass does not serialize its
353
+ // full snapshot on the runner's event loop.
354
+ if (normalized.snapshotEncoderAsync) {
355
+ if (store.needsCompaction())
356
+ store.scheduleAsyncCompaction();
357
+ }
358
+ else {
359
+ store.compactIfNeeded();
360
+ }
350
361
  return store;
351
362
  }
352
363
  const created = withScopeLock(dir, () => {
@@ -619,12 +630,29 @@ export class StateStore {
619
630
  return this.needsCompaction();
620
631
  }
621
632
  /** Async counterpart used by callback-originated recovery paths. */
633
+ scheduleAsyncCompaction() {
634
+ if (this.deferredCompactionScheduled)
635
+ return;
636
+ this.deferredCompactionScheduled = true;
637
+ setImmediate(() => {
638
+ void this.compactIfNeededAsync().catch((error) => {
639
+ process.stderr.write(`${JSON.stringify({
640
+ type: "state-store-async-compaction-failed",
641
+ stateDir: this.stateDir,
642
+ error: error instanceof Error ? error.message : String(error),
643
+ })}\n`);
644
+ }).finally(() => {
645
+ this.deferredCompactionScheduled = false;
646
+ });
647
+ });
648
+ }
649
+ /** Async counterpart used by callback-originated recovery paths. */
622
650
  async compactIfNeededAsync() {
623
651
  const compacted = await withRotationClaimAsync(this.stateDir, async () => {
624
652
  const startedAt = currentTimeMs();
625
653
  const budget = this.generationPublishRetryBudgetMs();
626
654
  let attempts = 0;
627
- while (attempts < COMPACTION_RETRY_MAX_ATTEMPTS) {
655
+ while (attempts < ASYNC_COMPACTION_MAX_STALE_ATTEMPTS) {
628
656
  let resolveStaged;
629
657
  let rejectStaged;
630
658
  const stagedReady = new Promise((resolve, reject) => {
@@ -680,7 +708,7 @@ export class StateStore {
680
708
  return false;
681
709
  attempts += 1;
682
710
  try {
683
- const staged = stageGeneration(this.stateDir, this.scopeDigest, plan.next, this.options.snapshotEncoder);
711
+ const staged = await stageGenerationAsync(this.stateDir, this.scopeDigest, plan.next, this.options.snapshotEncoder, this.options.snapshotEncoderAsync);
684
712
  try {
685
713
  afterGenerationStageHookForTest?.();
686
714
  }
@@ -705,6 +733,12 @@ export class StateStore {
705
733
  }
706
734
  return false;
707
735
  });
736
+ if (compacted === false && this.needsCompaction()) {
737
+ // A synchronous append can keep advancing the WAL while an async
738
+ // snapshot yields. After three rejected captures, finish one bounded
739
+ // rotation synchronously instead of letting the WAL grow indefinitely.
740
+ return this.compactIfNeeded();
741
+ }
708
742
  return compacted ?? false;
709
743
  }
710
744
  getGenerationIdentity() {
@@ -810,8 +844,12 @@ export class StateStore {
810
844
  recovered = true;
811
845
  continue;
812
846
  }
813
- if (compact)
814
- this.compact();
847
+ if (compact) {
848
+ if (this.options.snapshotEncoderAsync)
849
+ this.scheduleAsyncCompaction();
850
+ else
851
+ this.compact();
852
+ }
815
853
  return result;
816
854
  }
817
855
  }
@@ -1394,6 +1432,75 @@ function stageGeneration(dir, scopeDigest, generation, snapshotEncoder) {
1394
1432
  throw error;
1395
1433
  }
1396
1434
  }
1435
+ async function stageGenerationAsync(dir, scopeDigest, generation, snapshotEncoder, snapshotEncoderAsync) {
1436
+ snapshotMaterializationCount++;
1437
+ const payload = {
1438
+ lastRecordSequence: generation.lastRecordSequence,
1439
+ state: generation.state,
1440
+ };
1441
+ const snapshot = snapshotEncoderAsync
1442
+ ? await snapshotEncoderAsync(generation.generation, scopeDigest, payload)
1443
+ : encodeGenerationSnapshot(generation, scopeDigest, snapshotEncoder);
1444
+ let snapshotTemporary;
1445
+ let walTemporary;
1446
+ try {
1447
+ snapshotTemporary = await writeDurableTemporaryAsync(dir, `snapshot-${generation.generation}`, snapshot.chunks);
1448
+ walTemporary = await writeDurableTemporaryAsync(dir, `wal-${generation.generation}`, encodeWalHeader(generation.generation, scopeDigest));
1449
+ return { generation, snapshotTemporary, walTemporary };
1450
+ }
1451
+ catch (error) {
1452
+ if (snapshotTemporary !== undefined) {
1453
+ try {
1454
+ await fs.promises.rm(snapshotTemporary, { force: true });
1455
+ }
1456
+ catch { /* preserve primary staging error */ }
1457
+ }
1458
+ if (walTemporary !== undefined) {
1459
+ try {
1460
+ await fs.promises.rm(walTemporary, { force: true });
1461
+ }
1462
+ catch { /* preserve primary staging error */ }
1463
+ }
1464
+ throw error;
1465
+ }
1466
+ }
1467
+ async function writeDurableTemporaryAsync(dir, label, bytes) {
1468
+ const temporary = temporaryPath(dir, label);
1469
+ let handle;
1470
+ try {
1471
+ handle = await fs.promises.open(temporary, "wx");
1472
+ if (label.startsWith("snapshot-"))
1473
+ snapshotWriteHookForTest?.();
1474
+ const chunks = Buffer.isBuffer(bytes) ? [bytes] : bytes;
1475
+ for (const chunk of chunks) {
1476
+ let offset = 0;
1477
+ while (offset < chunk.length) {
1478
+ const { bytesWritten } = await handle.write(chunk, offset, chunk.length - offset, null);
1479
+ if (bytesWritten <= 0)
1480
+ throw new Error("state-store: async durable write made no progress");
1481
+ offset += bytesWritten;
1482
+ }
1483
+ await new Promise((resolve) => setImmediate(resolve));
1484
+ }
1485
+ await handle.datasync();
1486
+ await handle.close();
1487
+ handle = undefined;
1488
+ return temporary;
1489
+ }
1490
+ catch (error) {
1491
+ if (handle !== undefined) {
1492
+ try {
1493
+ await handle.close();
1494
+ }
1495
+ catch { /* preserve primary durable-write error */ }
1496
+ }
1497
+ try {
1498
+ await fs.promises.rm(temporary, { force: true });
1499
+ }
1500
+ catch { /* preserve primary durable-write error */ }
1501
+ throw new Error(`state-store: async staged write failed for ${label}`, { cause: error });
1502
+ }
1503
+ }
1397
1504
  function encodeGenerationSnapshot(generation, scopeDigest, snapshotEncoder) {
1398
1505
  const payload = {
1399
1506
  lastRecordSequence: generation.lastRecordSequence,