@indigoai-us/hq-cloud 6.18.29 → 6.18.31

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 (40) hide show
  1. package/dist/bin/area-ledger-migration.d.ts +2 -0
  2. package/dist/bin/area-ledger-migration.d.ts.map +1 -1
  3. package/dist/bin/area-ledger-migration.js +36 -10
  4. package/dist/bin/area-ledger-migration.js.map +1 -1
  5. package/dist/bin/area-ledger-migration.test.js +356 -3
  6. package/dist/bin/area-ledger-migration.test.js.map +1 -1
  7. package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
  8. package/dist/bin/sync-runner-watch-loop.js +52 -7
  9. package/dist/bin/sync-runner-watch-loop.js.map +1 -1
  10. package/dist/bin/sync-runner.d.ts +15 -1
  11. package/dist/bin/sync-runner.d.ts.map +1 -1
  12. package/dist/bin/sync-runner.js +21 -2
  13. package/dist/bin/sync-runner.js.map +1 -1
  14. package/dist/bin/sync-runner.test.js +55 -4
  15. package/dist/bin/sync-runner.test.js.map +1 -1
  16. package/dist/journal.d.ts +13 -0
  17. package/dist/journal.d.ts.map +1 -1
  18. package/dist/journal.js +106 -0
  19. package/dist/journal.js.map +1 -1
  20. package/dist/operation-lock.d.ts +23 -3
  21. package/dist/operation-lock.d.ts.map +1 -1
  22. package/dist/operation-lock.js +108 -24
  23. package/dist/operation-lock.js.map +1 -1
  24. package/dist/operation-lock.test.js +105 -0
  25. package/dist/operation-lock.test.js.map +1 -1
  26. package/dist/sync/area-ledger-migration.d.ts +15 -0
  27. package/dist/sync/area-ledger-migration.d.ts.map +1 -1
  28. package/dist/sync/area-ledger-migration.js +104 -41
  29. package/dist/sync/area-ledger-migration.js.map +1 -1
  30. package/dist/sync/area-ledger-migration.test.js +34 -0
  31. package/dist/sync/area-ledger-migration.test.js.map +1 -1
  32. package/dist/sync/area-ledger-recovery.bench.test.d.ts +2 -0
  33. package/dist/sync/area-ledger-recovery.bench.test.d.ts.map +1 -0
  34. package/dist/sync/area-ledger-recovery.bench.test.js +60 -0
  35. package/dist/sync/area-ledger-recovery.bench.test.js.map +1 -0
  36. package/dist/sync/area-ledger-writer-lock.bench.test.d.ts +2 -0
  37. package/dist/sync/area-ledger-writer-lock.bench.test.d.ts.map +1 -0
  38. package/dist/sync/area-ledger-writer-lock.bench.test.js +57 -0
  39. package/dist/sync/area-ledger-writer-lock.bench.test.js.map +1 -0
  40. package/package.json +1 -1
@@ -17,13 +17,13 @@ import { shouldRecordLocalDeleteIntent } from "../local-replacement.js";
17
17
  import { createIgnoreFilter } from "../ignore.js";
18
18
  import { TreeWatcher, resolveEventDebounceConfig, systemClock, } from "../watcher.js";
19
19
  import { recoverHqRootLocalState } from "../hq-root-recovery.js";
20
- import { clearLocalDeleteIntent, getStateDir, markLocalDeleteIntent, PERSONAL_VAULT_JOURNAL_SLUG, openJournalStoreSession, openJournalStoreSessionAsync, listJournalSlugs, listJournals, maintainAreaJournalSlice, disposeScopedJournalStores, releaseScopedJournalStore, releaseCachedAreaJournalMigrations, journalCacheCensusSizes, emitJournalCacheMetric, journalRows, readJournalScoped, readJournalScopedAsync, applyJournalDeltaAsync, } from "../journal.js";
20
+ import { clearLocalDeleteIntent, getStateDir, markLocalDeleteIntent, PERSONAL_VAULT_JOURNAL_SLUG, openJournalStoreSession, openJournalStoreSessionAsync, listJournalSlugs, listJournals, maintainAreaJournalSlice, disposeScopedJournalStores, releaseScopedJournalStore, releaseCachedAreaJournalMigrations, recoverCachedAreaJournalMirrorIfNeeded, setAreaLedgerRecoveryHqRootForProcess, journalCacheCensusSizes, emitJournalCacheMetric, journalRows, readJournalScoped, readJournalScopedAsync, applyJournalDeltaAsync, } from "../journal.js";
21
21
  import { isPersonalVaultDeletionExcluded } from "../personal-vault.js";
22
22
  import { NoopPushReceiver, ReceiverDispatchError, isReceiverTransportFailure, } from "../sync/push-receiver.js";
23
23
  import { CONTENT_HASH_PATTERN } from "../sync/push-event.js";
24
24
  import { resolveEventSync, startEventSync as defaultStartEventSync, } from "../sync/event-sync.js";
25
25
  import { resolveAreaStorageEnabled, resolveEffectiveParallelSyncRollout, resolveParallelSyncRollout, } from "../sync/feature-flags.js";
26
- import { resolveAreaLayoutAuthority } from "../sync/area-ledger-migration.js";
26
+ import { readAreaLayoutState, resolveAreaLayoutAuthority } from "../sync/area-ledger-migration.js";
27
27
  import { AREA_AUTO_MIGRATION_SOURCE, createAreaAutoMigrationScheduler, openPersonalVaultAreaMigration, readPersonalVaultLayoutPhase, } from "../sync/area-ledger-auto-migration.js";
28
28
  import { emitCloudTelemetry } from "../telemetry-events.js";
29
29
  import { HeapCensus, startRunnerHeapSampling, heapSampleCloudProperties, heapPressureCloudProperties, heapPressureStderrLine, heapRecycleCloudProperties, heapRecycleStderrLine, performHeapHardExit, nodeHeapReaders, nodeMajorGcObserver, resolveDeclaredHeapCeilingBytes, resolveHeapPressureFraction, resolveHeapSampleIntervalMs, resolveHeapRecycleEnabled, resolveHeapRecycleLiveFraction, resolveHeapRecycleSustainWindowMs, resolveHeapRecycleEmergencyFraction, resolveHeapRecycleMinUptimeMs, resolveHeapCheckpointMs, resolveHeapPinnedFraction, resolveHeapPinnedSustainMs, resolveHeapHardExitFraction, resolveHeapRecycleLatchHardExitMs, resolveHeapFootprintRecycleEnabled, resolveHeapFootprintRecycleBytes, resolveHeapFootprintHardExitBytes, HEAP_SAMPLE_INTERVAL_ENV, HEAP_PRESSURE_FRACTION_ENV, HEAP_RECYCLE_ENABLED_ENV, HEAP_RECYCLE_LIVE_FRACTION_ENV, HEAP_RECYCLE_SUSTAIN_WINDOW_MS_ENV, HEAP_RECYCLE_EMERGENCY_FRACTION_ENV, HEAP_RECYCLE_MIN_UPTIME_MS_ENV, HEAP_CHECKPOINT_MS_ENV, HEAP_PINNED_FRACTION_ENV, HEAP_PINNED_SUSTAIN_MS_ENV, HEAP_HARD_EXIT_FRACTION_ENV, HEAP_RECYCLE_LATCH_HARD_EXIT_MS_ENV, HEAP_FOOTPRINT_RECYCLE_ENABLED_ENV, HEAP_FOOTPRINT_RECYCLE_MB_ENV, HEAP_FOOTPRINT_HARD_EXIT_MB_ENV, } from "./sync-runner-heap-telemetry.js";
@@ -1401,6 +1401,19 @@ export async function runWatchLoop(argv, parsed, deps, runtime) {
1401
1401
  };
1402
1402
  const monotonicNow = deps.monotonicNow ?? (() => performance.now());
1403
1403
  const runPass = deps.runPass ?? runtime.runPassWithOperationLockAlreadyHeld;
1404
+ const reportProtocolStatus = deps.reportProtocolStatus;
1405
+ const reportLockWait = (holder) => {
1406
+ const command = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(holder.command)
1407
+ ? holder.command
1408
+ : "unknown";
1409
+ reportProtocolStatus?.({
1410
+ state: "waiting-for-lock",
1411
+ holder: { pid: holder.pid, command },
1412
+ });
1413
+ };
1414
+ const reportRunnerRunning = () => {
1415
+ reportProtocolStatus?.({ state: "running" });
1416
+ };
1404
1417
  const qmdShutdownController = new AbortController();
1405
1418
  const runPassSupportsQmdLifecycle = deps.runPass === undefined || deps.runPassSupportsQmdLifecycle === true;
1406
1419
  const runPassSupportsCooperativeCheckpoint = deps.runPass === undefined || deps.runPassSupportsCooperativeCheckpoint === true;
@@ -1435,6 +1448,7 @@ export async function runWatchLoop(argv, parsed, deps, runtime) {
1435
1448
  skipPersonalEnv === "yes",
1436
1449
  };
1437
1450
  const hqRoot = parsed.hqRoot;
1451
+ setAreaLedgerRecoveryHqRootForProcess(hqRoot);
1438
1452
  const serviceStartedAt = Date.now();
1439
1453
  // Delayed and daily: this must never be attached to the 15s poll cadence.
1440
1454
  // Stage 0 remains dry-run only; the standalone hq-backup-prune command is
@@ -1468,7 +1482,7 @@ export async function runWatchLoop(argv, parsed, deps, runtime) {
1468
1482
  try {
1469
1483
  const handle = acquireOperationLock(hqRoot, "sync", {
1470
1484
  timeoutSec: 0,
1471
- onWaitStart: () => undefined,
1485
+ onWaitStart: (holder) => reportLockWait(holder),
1472
1486
  deferToWaiters: true,
1473
1487
  });
1474
1488
  handle.release();
@@ -1716,6 +1730,7 @@ export async function runWatchLoop(argv, parsed, deps, runtime) {
1716
1730
  onWaitStart: () => undefined,
1717
1731
  deferToWaiters: true,
1718
1732
  });
1733
+ reportRunnerRunning();
1719
1734
  try {
1720
1735
  telemetry?.mark("network");
1721
1736
  if (lane === "slow") {
@@ -1750,7 +1765,8 @@ export async function runWatchLoop(argv, parsed, deps, runtime) {
1750
1765
  }
1751
1766
  }
1752
1767
  try {
1753
- return await withOperationLock(hqRoot, "sync", async () => {
1768
+ const outcome = await withOperationLock(hqRoot, "sync", async () => {
1769
+ reportRunnerRunning();
1754
1770
  telemetry?.mark("network");
1755
1771
  if (lane === "slow") {
1756
1772
  processOwnsOperationLock = true;
@@ -1771,9 +1787,16 @@ export async function runWatchLoop(argv, parsed, deps, runtime) {
1771
1787
  processOwnsOperationLock = false;
1772
1788
  }
1773
1789
  }
1774
- }, { timeoutSec: parsed.lockTimeoutSec, deferToWaiters: true });
1790
+ }, {
1791
+ timeoutSec: parsed.lockTimeoutSec,
1792
+ deferToWaiters: true,
1793
+ onWaitStart: (holder) => reportLockWait(holder),
1794
+ });
1795
+ reportRunnerRunning();
1796
+ return outcome;
1775
1797
  }
1776
1798
  catch (err) {
1799
+ reportRunnerRunning();
1777
1800
  if (err instanceof OperationLockedError) {
1778
1801
  process.stderr.write(err.message + "\n");
1779
1802
  return OPERATION_LOCKED_EXIT;
@@ -1782,6 +1805,7 @@ export async function runWatchLoop(argv, parsed, deps, runtime) {
1782
1805
  }
1783
1806
  };
1784
1807
  const runTaskWithLock = async (task, workClass = "chore") => {
1808
+ reportRunnerRunning();
1785
1809
  if (workClass === "realtime" &&
1786
1810
  passScheduler.handoffActive &&
1787
1811
  processOwnsOperationLock) {
@@ -1796,9 +1820,10 @@ export async function runWatchLoop(argv, parsed, deps, runtime) {
1796
1820
  try {
1797
1821
  const handle = acquireOperationLock(hqRoot, "sync", {
1798
1822
  timeoutSec: 0,
1799
- onWaitStart: () => undefined,
1823
+ onWaitStart: (holder) => reportLockWait(holder),
1800
1824
  deferToWaiters: true,
1801
1825
  });
1826
+ reportRunnerRunning();
1802
1827
  try {
1803
1828
  return await task();
1804
1829
  }
@@ -1815,12 +1840,19 @@ export async function runWatchLoop(argv, parsed, deps, runtime) {
1815
1840
  }
1816
1841
  }
1817
1842
  try {
1818
- return await withOperationLock(hqRoot, "sync", task, {
1843
+ const outcome = await withOperationLock(hqRoot, "sync", async () => {
1844
+ reportRunnerRunning();
1845
+ return task();
1846
+ }, {
1819
1847
  timeoutSec: parsed.lockTimeoutSec,
1820
1848
  deferToWaiters: true,
1849
+ onWaitStart: (holder) => reportLockWait(holder),
1821
1850
  });
1851
+ reportRunnerRunning();
1852
+ return outcome;
1822
1853
  }
1823
1854
  catch (err) {
1855
+ reportRunnerRunning();
1824
1856
  if (err instanceof OperationLockedError) {
1825
1857
  process.stderr.write(err.message + "\n");
1826
1858
  return OPERATION_LOCKED_EXIT;
@@ -3617,6 +3649,19 @@ export async function runWatchLoop(argv, parsed, deps, runtime) {
3617
3649
  catch (err) {
3618
3650
  process.stderr.write(`hq-sync-runner: WARN local HQ recovery failed: ${describeError(err)}\n`);
3619
3651
  }
3652
+ if (personalJournalInScope) {
3653
+ const layout = readAreaLayoutState(getStateDir(), PERSONAL_VAULT_JOURNAL_SLUG);
3654
+ const activeCommit = layout?.activeCommitWatermark ?? 0;
3655
+ if (layout?.phase === "area-authoritative" &&
3656
+ (!layout.rollbackSafe || (layout.legacyMirrorWatermark ?? 0) !== activeCommit)) {
3657
+ const recoveryStartedAt = performance.now();
3658
+ const recovery = withOperationLockSync(hqRoot, "area-ledger-migration", () => recoverCachedAreaJournalMirrorIfNeeded(PERSONAL_VAULT_JOURNAL_SLUG), { mode: "exclusive", timeoutSec: 5, onWaitStart: () => undefined });
3659
+ if (recovery?.recovered) {
3660
+ process.stderr.write(`hq-sync-runner: recovered area-ledger legacy mirror before watch ` +
3661
+ `(rows=${recovery.rowCount}, durationMs=${Math.round(performance.now() - recoveryStartedAt)})\n`);
3662
+ }
3663
+ }
3664
+ }
3620
3665
  watcher.start();
3621
3666
  const reportWatcherReady = () => {
3622
3667
  if (stopped || watcher === null)