@indigoai-us/hq-cloud 6.15.42 → 6.15.44

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 (62) hide show
  1. package/dist/bin/sync-runner-company.d.ts +3 -0
  2. package/dist/bin/sync-runner-company.d.ts.map +1 -1
  3. package/dist/bin/sync-runner-company.js +50 -14
  4. package/dist/bin/sync-runner-company.js.map +1 -1
  5. package/dist/bin/sync-runner-company.test.js +135 -0
  6. package/dist/bin/sync-runner-company.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 +33 -1
  9. package/dist/bin/sync-runner-watch-loop.js.map +1 -1
  10. package/dist/bin/sync-runner.d.ts +5 -5
  11. package/dist/bin/sync-runner.d.ts.map +1 -1
  12. package/dist/bin/sync-runner.js +3 -0
  13. package/dist/bin/sync-runner.js.map +1 -1
  14. package/dist/bin/sync-runner.test.js +96 -2
  15. package/dist/bin/sync-runner.test.js.map +1 -1
  16. package/dist/cli/share.d.ts +5 -17
  17. package/dist/cli/share.d.ts.map +1 -1
  18. package/dist/cli/share.js +16 -77
  19. package/dist/cli/share.js.map +1 -1
  20. package/dist/cli/share.test.js +48 -99
  21. package/dist/cli/share.test.js.map +1 -1
  22. package/dist/cli/sync.d.ts +16 -18
  23. package/dist/cli/sync.d.ts.map +1 -1
  24. package/dist/cli/sync.js +16 -72
  25. package/dist/cli/sync.js.map +1 -1
  26. package/dist/cli/sync.test.js +40 -59
  27. package/dist/cli/sync.test.js.map +1 -1
  28. package/dist/cli/tombstones.d.ts +23 -8
  29. package/dist/cli/tombstones.d.ts.map +1 -1
  30. package/dist/cli/tombstones.js +63 -33
  31. package/dist/cli/tombstones.js.map +1 -1
  32. package/dist/cli/tombstones.test.d.ts +2 -0
  33. package/dist/cli/tombstones.test.d.ts.map +1 -0
  34. package/dist/cli/tombstones.test.js +27 -0
  35. package/dist/cli/tombstones.test.js.map +1 -0
  36. package/dist/cli/watch-event-push-conflict.test.js +7 -0
  37. package/dist/cli/watch-event-push-conflict.test.js.map +1 -1
  38. package/dist/local-path-codec.test.js +20 -0
  39. package/dist/local-path-codec.test.js.map +1 -1
  40. package/dist/s3.d.ts +1 -1
  41. package/dist/s3.d.ts.map +1 -1
  42. package/dist/s3.js +7 -23
  43. package/dist/s3.js.map +1 -1
  44. package/dist/s3.test.js +13 -20
  45. package/dist/s3.test.js.map +1 -1
  46. package/dist/sync-core.d.ts +16 -0
  47. package/dist/sync-core.d.ts.map +1 -1
  48. package/dist/sync-core.js +38 -0
  49. package/dist/sync-core.js.map +1 -1
  50. package/dist/sync-progress.d.ts +18 -1
  51. package/dist/sync-progress.d.ts.map +1 -1
  52. package/dist/sync-progress.js +113 -7
  53. package/dist/sync-progress.js.map +1 -1
  54. package/dist/sync-progress.test.js +32 -2
  55. package/dist/sync-progress.test.js.map +1 -1
  56. package/dist/watcher.d.ts +37 -8
  57. package/dist/watcher.d.ts.map +1 -1
  58. package/dist/watcher.js +137 -23
  59. package/dist/watcher.js.map +1 -1
  60. package/dist/watcher.test.js +116 -9
  61. package/dist/watcher.test.js.map +1 -1
  62. package/package.json +1 -1
@@ -149,6 +149,7 @@ function makeDeps(overrides = {}) {
149
149
  // and adds ambient diagnostic events to otherwise-hermetic assertions.
150
150
  getIdTokenClaims: vi.fn().mockReturnValue(null),
151
151
  createVaultClient: vi.fn().mockImplementation(() => makeVaultStub()),
152
+ fetchFileTombstones: vi.fn().mockResolvedValue(new Map()),
152
153
  sync: vi.fn().mockResolvedValue(defaultSyncResult()),
153
154
  reindex: vi.fn(() => ({ status: 0 })),
154
155
  qmdReindex: vi.fn(() => ({
@@ -1172,7 +1173,9 @@ describe("fanout-plan", () => {
1172
1173
  }),
1173
1174
  });
1174
1175
  expect(await runRunner(["--companies"], deps)).toBe(0);
1175
- expect(order).toEqual(["company", "personal", "reconcile"]);
1176
+ expect(order).toHaveLength(3);
1177
+ expect(order.slice(0, 2).sort()).toEqual(["company", "personal"]);
1178
+ expect(order[2]).toBe("reconcile");
1176
1179
  });
1177
1180
  it("includes entity.name on plan entries when available", async () => {
1178
1181
  const deps = makeDeps({
@@ -1323,7 +1326,10 @@ describe("automatic journal maintenance", () => {
1323
1326
  `repair:${PERSONAL_VAULT_JOURNAL_SLUG}`,
1324
1327
  "repair:personal",
1325
1328
  ]);
1326
- expect(order[3]).toBe("sync:indigo");
1329
+ expect(order.slice(3).sort()).toEqual([
1330
+ `sync:${PERSONAL_VAULT_JOURNAL_SLUG}`,
1331
+ "sync:indigo",
1332
+ ]);
1327
1333
  expect(deps.stdout.events().filter((event) => event.type === "maintenance-progress")).toEqual([
1328
1334
  {
1329
1335
  type: "maintenance-progress",
@@ -1504,6 +1510,27 @@ describe("per-company fanout", () => {
1504
1510
  expect(all).toBeDefined();
1505
1511
  expect(all?.partial).toBe(true);
1506
1512
  });
1513
+ it("fails the affected pass loudly when deletion authority cannot be fetched", async () => {
1514
+ const deps = makeDeps({
1515
+ createVaultClient: () => makeVaultStub({
1516
+ memberships: [{ companyUid: "cmp_a" }],
1517
+ entityGet: (uid) => Promise.resolve({ uid, slug: "acme" }),
1518
+ }),
1519
+ fetchFileTombstones: vi
1520
+ .fn()
1521
+ .mockRejectedValue(new Error("FILE_TOMBSTONE fetch failed after retries; refusing to sync without delete suppression")),
1522
+ });
1523
+ expect(await runRunner(["--companies", "--direction", "both"], deps)).toBe(PARTIAL_SYNC_EXIT);
1524
+ expect(deps.stderr.events()).toContainEqual(expect.objectContaining({
1525
+ type: "error",
1526
+ company: "acme",
1527
+ path: "(company)",
1528
+ message: expect.stringContaining("refusing to sync without delete suppression"),
1529
+ }));
1530
+ const complete = deps.stdout.events().find((event) => event.type === "all-complete");
1531
+ expect(complete).toMatchObject({ partial: true });
1532
+ expect(complete?.companies).toContainEqual(expect.objectContaining({ company: "acme", status: "errored" }));
1533
+ });
1507
1534
  it("emits complete event per company with the SyncResult spread", async () => {
1508
1535
  const result = defaultSyncResult({
1509
1536
  filesDownloaded: 3,
@@ -3944,6 +3971,73 @@ describe("runRunnerWithLoop — event-push wiring", () => {
3944
3971
  stderrWrite.mockRestore();
3945
3972
  }
3946
3973
  });
3974
+ it("emits a WARN with the reason code when the watcher stands down", async () => {
3975
+ const watcher = makeWatcherStub();
3976
+ const stderrWrite = vi
3977
+ .spyOn(process.stderr, "write")
3978
+ .mockImplementation(() => true);
3979
+ let triggerShutdown = () => { };
3980
+ const loop = runRunnerWithLoop(["--companies", "--watch", "--event-push", "--hq-root", "/tmp/hq"], {
3981
+ runPass: vi.fn().mockResolvedValue(completedPassOutcome()),
3982
+ createWatcher: (options) => {
3983
+ watcher.start = () => {
3984
+ watcher.started = true;
3985
+ options.onDegraded?.({
3986
+ reason: "inotify_enospc",
3987
+ watchedPaths: 17349,
3988
+ maxWatchedPaths: 500000,
3989
+ action: "stopped",
3990
+ });
3991
+ };
3992
+ return watcher;
3993
+ },
3994
+ sleep: () => new Promise(() => { }),
3995
+ onShutdownSignal: (handler) => {
3996
+ triggerShutdown = handler;
3997
+ return () => { };
3998
+ },
3999
+ });
4000
+ try {
4001
+ await flushLoopMicrotasks();
4002
+ expect(stderrWrite.mock.calls.map(([chunk]) => String(chunk)).join("")).toContain("event-push watcher degraded; stopped; continuing cadence-only: inotify_enospc (watched-paths=17349/500000)");
4003
+ }
4004
+ finally {
4005
+ triggerShutdown();
4006
+ await loop;
4007
+ stderrWrite.mockRestore();
4008
+ }
4009
+ });
4010
+ it("reports current watcher liveness after startup", async () => {
4011
+ vi.useFakeTimers();
4012
+ const watcher = makeWatcherStub();
4013
+ watcher.isWatching = () => true;
4014
+ watcher.watchedPathCount = () => 17349;
4015
+ watcher.watchMode = () => "chokidar";
4016
+ const stderrWrite = vi
4017
+ .spyOn(process.stderr, "write")
4018
+ .mockImplementation(() => true);
4019
+ let triggerShutdown = () => { };
4020
+ const loop = runRunnerWithLoop(["--companies", "--watch", "--event-push", "--hq-root", "/tmp/hq"], {
4021
+ runPass: vi.fn().mockResolvedValue(completedPassOutcome()),
4022
+ createWatcher: () => watcher,
4023
+ sleep: () => new Promise(() => { }),
4024
+ onShutdownSignal: (handler) => {
4025
+ triggerShutdown = handler;
4026
+ return () => { };
4027
+ },
4028
+ });
4029
+ try {
4030
+ await flushLoopMicrotasks();
4031
+ await vi.advanceTimersByTimeAsync(30_000);
4032
+ expect(stderrWrite.mock.calls.map(([chunk]) => String(chunk)).join("")).toContain("event-push watcher liveness (state=active, mode=chokidar, watched-paths=17349)");
4033
+ }
4034
+ finally {
4035
+ triggerShutdown();
4036
+ await loop;
4037
+ stderrWrite.mockRestore();
4038
+ vi.useRealTimers();
4039
+ }
4040
+ });
3947
4041
  it("warns once and continues poll-only when watcher startup fails", async () => {
3948
4042
  const stderrWrite = vi
3949
4043
  .spyOn(process.stderr, "write")