@indigoai-us/hq-cli 5.345.170 → 5.345.172

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 (142) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/assets/scaffold/core/scripts/hq-delegate-send.sh +1 -1
  3. package/dist/command-catalog.generated.d.ts +206 -7
  4. package/dist/command-catalog.generated.js +252 -8
  5. package/dist/command-registration-plan.d.ts +7 -0
  6. package/dist/command-registration-plan.js +1 -0
  7. package/dist/commands/access.d.ts +32 -1
  8. package/dist/commands/access.js +112 -3
  9. package/dist/commands/agent-kit.d.ts +1 -1
  10. package/dist/commands/agent-kit.js +3 -1
  11. package/dist/commands/agents.js +2 -1
  12. package/dist/commands/bot.d.ts +3 -0
  13. package/dist/commands/bot.js +179 -18
  14. package/dist/commands/cloud.d.ts +58 -1
  15. package/dist/commands/cloud.js +228 -10
  16. package/dist/commands/core-company-index-scope-flag.d.ts +8 -1
  17. package/dist/commands/core-company-index-scope-flag.js +9 -2
  18. package/dist/commands/core-delegate-w1b.js +5 -2
  19. package/dist/commands/core-dm-bind-native.js +19 -4
  20. package/dist/commands/core-rebuild-index-fast.js +24 -6
  21. package/dist/commands/core.js +18 -6
  22. package/dist/commands/daemon.js +16 -1
  23. package/dist/commands/dm.d.ts +17 -3
  24. package/dist/commands/dm.js +121 -26
  25. package/dist/commands/files.d.ts +1 -0
  26. package/dist/commands/files.js +22 -4
  27. package/dist/commands/integrations-api.d.ts +4 -0
  28. package/dist/commands/integrations-api.js +18 -2
  29. package/dist/commands/integrations-connect.d.ts +10 -3
  30. package/dist/commands/integrations-connect.js +70 -6
  31. package/dist/commands/integrations-core.d.ts +23 -0
  32. package/dist/commands/integrations-core.js +100 -0
  33. package/dist/commands/integrations-manage.js +8 -1
  34. package/dist/commands/integrations.js +49 -5
  35. package/dist/commands/lanes-loop.d.ts +20 -0
  36. package/dist/commands/lanes-loop.js +69 -11
  37. package/dist/commands/lanes.js +9 -1
  38. package/dist/commands/rescue.d.ts +9 -0
  39. package/dist/commands/rescue.js +31 -0
  40. package/dist/commands/run.js +115 -40
  41. package/dist/commands/scan.d.ts +5 -1
  42. package/dist/commands/scan.js +16 -4
  43. package/dist/commands/secrets.js +50 -9
  44. package/dist/commands/sync-core.d.ts +22 -0
  45. package/dist/commands/sync-core.js +124 -0
  46. package/dist/hq-cloud-sync-runner/bin/sync-runner.js +2447 -2135
  47. package/dist/hq-cloud-sync-runner/package.json +1 -1
  48. package/dist/lib/agent-kit/inbox-state.d.ts +17 -0
  49. package/dist/lib/agent-kit/inbox-state.js +41 -20
  50. package/dist/lib/agent-kit/kit-config.d.ts +2 -0
  51. package/dist/lib/agent-kit/kit-config.js +6 -0
  52. package/dist/lib/agent-kit/mcp/tools.js +12 -5
  53. package/dist/lib/agent-kit/run/heartbeat.d.ts +6 -3
  54. package/dist/lib/agent-kit/run/heartbeat.js +6 -3
  55. package/dist/lib/agent-kit/run/inbox.d.ts +8 -3
  56. package/dist/lib/agent-kit/run/inbox.js +42 -10
  57. package/dist/lib/agent-kit/run/request-timeout.d.ts +26 -0
  58. package/dist/lib/agent-kit/run/request-timeout.js +51 -0
  59. package/dist/lib/bot/api.d.ts +1 -1
  60. package/dist/lib/bot/config.d.ts +10 -0
  61. package/dist/lib/bot/config.js +17 -1
  62. package/dist/lib/bot/fleet-local.d.ts +142 -0
  63. package/dist/lib/bot/fleet-local.js +689 -0
  64. package/dist/lib/bot/fleet-python.d.ts +47 -0
  65. package/dist/lib/bot/fleet-python.js +218 -0
  66. package/dist/lib/bot/index.d.ts +2 -0
  67. package/dist/lib/bot/index.js +2 -0
  68. package/dist/lib/bot/local-config.d.ts +3 -2
  69. package/dist/lib/bot/local-config.js +5 -2
  70. package/dist/lib/bot/promote.d.ts +10 -0
  71. package/dist/lib/bot/promote.js +3 -2
  72. package/dist/lib/bot/prompt.d.ts +6 -1
  73. package/dist/lib/bot/prompt.js +8 -3
  74. package/dist/lib/bot/runtime/index.js +8 -4
  75. package/dist/lib/bot/runtime/scratch-dir.d.ts +24 -0
  76. package/dist/lib/bot/runtime/scratch-dir.js +41 -0
  77. package/dist/lib/caller-principal.d.ts +4 -0
  78. package/dist/lib/caller-principal.js +40 -0
  79. package/dist/lib/capacity/collectors/grok.js +8 -2
  80. package/dist/lib/cli-flag-keys.d.ts +2 -0
  81. package/dist/lib/cli-flag-keys.js +2 -0
  82. package/dist/lib/daemon/catalog.d.ts +12 -4
  83. package/dist/lib/daemon/catalog.js +70 -24
  84. package/dist/lib/daemon/config.d.ts +0 -7
  85. package/dist/lib/daemon/config.js +0 -32
  86. package/dist/lib/daemon/run.d.ts +5 -1
  87. package/dist/lib/daemon/run.js +48 -11
  88. package/dist/lib/daemon/supervisor.js +3 -1
  89. package/dist/lib/doctor/checks/release-links.d.ts +62 -1
  90. package/dist/lib/doctor/checks/release-links.js +188 -2
  91. package/dist/lib/doctor/fix/apply.js +54 -0
  92. package/dist/lib/doctor/fix/remediation.d.ts +8 -1
  93. package/dist/lib/doctor/fix/remediation.js +22 -0
  94. package/dist/lib/flag-registry-worker-source.generated.d.ts +1 -1
  95. package/dist/lib/flag-registry-worker-source.generated.js +1 -1
  96. package/dist/lib/index-render/index.d.ts +9 -0
  97. package/dist/lib/index-render/index.js +65 -5
  98. package/dist/lib/index-render/session-scope.d.ts +69 -0
  99. package/dist/lib/index-render/session-scope.js +279 -0
  100. package/dist/lib/lanes/admission.js +7 -20
  101. package/dist/lib/lanes/reconcile.js +13 -15
  102. package/dist/lib/lanes/stale-lock.d.ts +50 -0
  103. package/dist/lib/lanes/stale-lock.js +105 -0
  104. package/dist/lib/lanes/store.js +11 -76
  105. package/dist/lib/notify-recipient.d.ts +10 -4
  106. package/dist/lib/notify-recipient.js +16 -4
  107. package/dist/lib/secret-input-link.d.ts +42 -0
  108. package/dist/lib/secret-input-link.js +93 -0
  109. package/dist/lib/secret-scan/range.d.ts +57 -0
  110. package/dist/lib/secret-scan/range.js +266 -0
  111. package/dist/lib/secret-scan/repo-config.d.ts +18 -3
  112. package/dist/lib/secret-scan/repo-config.js +135 -2
  113. package/dist/lib/sync-core/engine-home.d.ts +44 -0
  114. package/dist/lib/sync-core/engine-home.js +193 -0
  115. package/dist/lib/sync-core/flag.d.ts +17 -0
  116. package/dist/lib/sync-core/flag.js +47 -0
  117. package/dist/lib/sync-core/reconcile.d.ts +31 -0
  118. package/dist/lib/sync-core/reconcile.js +196 -0
  119. package/dist/lib/sync-core/release.d.ts +32 -0
  120. package/dist/lib/sync-core/release.js +140 -0
  121. package/dist/lib/sync-core/rollout-state.d.ts +24 -0
  122. package/dist/lib/sync-core/rollout-state.js +94 -0
  123. package/dist/lib/vault-sync-switches.d.ts +5 -0
  124. package/dist/lib/vault-sync-switches.js +43 -0
  125. package/dist/run/script-bound-schema.d.ts +27 -0
  126. package/dist/run/script-bound-schema.js +97 -0
  127. package/dist/secrets-env-action.d.ts +2 -0
  128. package/dist/secrets-env-action.js +7 -2
  129. package/dist/utils/cognito-session.d.ts +3 -30
  130. package/dist/utils/cognito-session.js +2 -100
  131. package/dist/utils/machine-principal-state.d.ts +38 -0
  132. package/dist/utils/machine-principal-state.js +110 -0
  133. package/dist/utils/remote-list-not-converging.d.ts +21 -0
  134. package/dist/utils/remote-list-not-converging.js +40 -0
  135. package/dist/utils/safe-link.js +9 -0
  136. package/dist/utils/script-bound-exec.d.ts +158 -0
  137. package/dist/utils/script-bound-exec.js +568 -0
  138. package/dist/utils/sync-watchdog.d.ts +92 -0
  139. package/dist/utils/sync-watchdog.js +250 -0
  140. package/package.json +8 -8
  141. package/dist/lib/daemon/sync-core-canary.d.ts +0 -9
  142. package/dist/lib/daemon/sync-core-canary.js +0 -56
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Opt-in watchdog for `hq sync now` (feedback_b7c00a62).
3
+ *
4
+ * A scheduled `hq sync now --all --on-conflict keep` held a CPU core for
5
+ * hours and never exited. The cause, a LIST that re-requested the same page
6
+ * forever, is fixed in hq-cloud and hq-pro. This watchdog is a safety net
7
+ * for scheduled or unattended jobs, and it is OFF by default: a healthy sync
8
+ * is never stopped unless the caller asks for a limit.
9
+ *
10
+ * - Idle limit (`--max-idle` / HQ_SYNC_MAX_IDLE, default off): stop the run
11
+ * after this long with no observed progress. Progress is a change in this
12
+ * process's hq-cloud sync-progress snapshot: a leg starting, its plan, or a
13
+ * file transferred, skipped, or in conflict. The snapshot has no counter
14
+ * for LIST pages or planned rows, so the remote LIST and planning phase of
15
+ * a leg counts as no progress; set the idle limit longer than the slowest
16
+ * expected planning phase. One file transfer also counts only when it
17
+ * completes.
18
+ * - Total cap (`--max-runtime` / HQ_SYNC_MAX_RUNTIME, default off).
19
+ *
20
+ * Time is measured on the monotonic clock (`process.hrtime`), which does not
21
+ * advance while a Mac or Linux laptop sleeps, so sleep is not idle time.
22
+ *
23
+ * Two layers enforce the limits:
24
+ *
25
+ * 1. An in-process check. When a limit passes, the run rejects with
26
+ * {@link SyncWatchdogTimeoutError}; the command prints the message,
27
+ * records a failed sync (bounded to {@link SYNC_WATCHDOG_REPORT_GRACE_MS}),
28
+ * and exits {@link SYNC_WATCHDOG_EXIT_CODE} (124).
29
+ * 2. A worker-thread backstop. A timer on the main thread cannot fire while
30
+ * the main thread spins in a loop that never yields. The worker reads the
31
+ * same progress clock through shared memory and, once a limit is exceeded
32
+ * by {@link SYNC_WATCHDOG_BACKSTOP_GRACE_MS}, writes the message to stderr
33
+ * and SIGKILLs the process. The backstop stays armed after an in-process
34
+ * timeout until the process exits, so hung post-timeout work is still
35
+ * ended. A backstop kill exits 137 on POSIX (128 + SIGKILL), not 124; on
36
+ * Windows the process ends with exit code 1.
37
+ */
38
+ import { Worker } from "node:worker_threads";
39
+ /** Default no-progress limit: off. Opt in with --max-idle / HQ_SYNC_MAX_IDLE. */
40
+ export const DEFAULT_SYNC_MAX_IDLE_SECONDS = 0;
41
+ /** Default total cap: off. */
42
+ export const DEFAULT_SYNC_MAX_RUNTIME_SECONDS = 0;
43
+ /** How long the worker backstop waits past a limit before it kills. */
44
+ export const SYNC_WATCHDOG_BACKSTOP_GRACE_MS = 60_000;
45
+ /** Upper bound on the failed-sync report after a timeout, before exit 124. */
46
+ export const SYNC_WATCHDOG_REPORT_GRACE_MS = 10_000;
47
+ /** Exit code for a run the in-process watchdog ended (same as coreutils `timeout`). */
48
+ export const SYNC_WATCHDOG_EXIT_CODE = 124;
49
+ export class SyncWatchdogTimeoutError extends Error {
50
+ code = "SYNC_WATCHDOG_TIMEOUT";
51
+ reason;
52
+ seconds;
53
+ constructor(reason, seconds, label) {
54
+ super(syncWatchdogMessage(reason, seconds, label));
55
+ this.name = "SyncWatchdogTimeoutError";
56
+ this.reason = reason;
57
+ this.seconds = seconds;
58
+ }
59
+ }
60
+ export function syncWatchdogMessage(reason, seconds, label) {
61
+ const what = reason === "idle"
62
+ ? `${label} made no progress for ${seconds}s`
63
+ : `${label} did not finish within ${seconds}s`;
64
+ return (`${what} and was stopped by the sync watchdog. Run it again; if it stops ` +
65
+ "here every time, report it with `hq feedback bug`. Change the limits with " +
66
+ "--max-idle / HQ_SYNC_MAX_IDLE and --max-runtime / HQ_SYNC_MAX_RUNTIME " +
67
+ "(0 turns a limit off).");
68
+ }
69
+ function parseSeconds(value, flag) {
70
+ const seconds = Number(value);
71
+ if (!Number.isInteger(seconds) || seconds < 0) {
72
+ throw new Error(`${flag} must be a non-negative integer number of seconds`);
73
+ }
74
+ return seconds;
75
+ }
76
+ /** Resolve both limits. A flag wins, then the environment, then the default. */
77
+ export function resolveSyncWatchdogLimits(raw, env = process.env) {
78
+ return {
79
+ idleSeconds: parseSeconds(raw.maxIdle ?? env.HQ_SYNC_MAX_IDLE ?? String(DEFAULT_SYNC_MAX_IDLE_SECONDS), "--max-idle"),
80
+ maxRuntimeSeconds: parseSeconds(raw.maxRuntime ?? env.HQ_SYNC_MAX_RUNTIME ?? String(DEFAULT_SYNC_MAX_RUNTIME_SECONDS), "--max-runtime"),
81
+ };
82
+ }
83
+ // ── Progress clock ──────────────────────────────────────────────────────────
84
+ // One per process. Float64 slot holds the last progress time (ms since epoch)
85
+ // in shared memory, so the worker backstop sees updates made on the main
86
+ // thread without any message passing.
87
+ let progressClock = null;
88
+ /** Monotonic milliseconds, shared by every thread in the process. */
89
+ function hrtimeMs() {
90
+ return Number(process.hrtime.bigint() / 1000000n);
91
+ }
92
+ let monotonicNow = hrtimeMs;
93
+ /** Test seam: replace the monotonic clock. `null` restores process.hrtime. */
94
+ export function setSyncWatchdogClockForTesting(clock) {
95
+ monotonicNow = clock ?? hrtimeMs;
96
+ }
97
+ let lastProgressAt = monotonicNow();
98
+ /** Record sync progress. Cheap; safe to call on every row or event. */
99
+ export function noteSyncProgress() {
100
+ const now = monotonicNow();
101
+ lastProgressAt = now;
102
+ if (progressClock)
103
+ progressClock[0] = now;
104
+ }
105
+ /** Last recorded progress time, for tests and the in-process check. */
106
+ export function lastSyncProgressAt() {
107
+ return lastProgressAt;
108
+ }
109
+ /**
110
+ * Build a probe that calls {@link noteSyncProgress} whenever THIS process's
111
+ * sync-progress snapshot changes. hq-cloud rewrites that snapshot when a leg
112
+ * starts, when it plans, and for every file transferred or skipped, for both
113
+ * push and pull, so a moving sync keeps resetting the idle limit without any
114
+ * change to the engine's progress recorders. Snapshots written by another
115
+ * process (the menubar runner) are ignored. A single file transfer is not
116
+ * seen until it completes; the engine's own per-body idle timeouts cover a
117
+ * transfer that stalls.
118
+ */
119
+ export function createSnapshotProgressProbe(read, pid = process.pid) {
120
+ let last = null;
121
+ return () => {
122
+ let snap;
123
+ try {
124
+ snap = read();
125
+ }
126
+ catch {
127
+ return;
128
+ }
129
+ if (!snap || snap.pid !== pid)
130
+ return;
131
+ const key = [snap.startedAt, snap.phase, snap.company, snap.filesTotal, snap.filesDone, snap.conflicts].join("|");
132
+ if (last !== null && key !== last)
133
+ noteSyncProgress();
134
+ last = key;
135
+ };
136
+ }
137
+ // Runs in a worker. Wakes every `checkMs` (or on cancel), reads the shared
138
+ // progress clock, and kills the whole process once a limit plus grace passes.
139
+ const BACKSTOP_SOURCE = `
140
+ const { workerData } = require("node:worker_threads");
141
+ const fs = require("node:fs");
142
+ const flag = new Int32Array(workerData.flag);
143
+ const clock = new Float64Array(workerData.clock);
144
+ const { startedAt, idleMs, maxRuntimeMs, graceMs, idleMessage, runtimeMessage } = workerData;
145
+ const checkMs = Math.max(10, Math.min(5000, Math.floor(graceMs / 4)));
146
+ for (;;) {
147
+ Atomics.wait(flag, 0, 0, checkMs);
148
+ if (Atomics.load(flag, 0) !== 0) break;
149
+ const now = Number(process.hrtime.bigint() / 1000000n);
150
+ let message = null;
151
+ if (idleMs > 0 && now - clock[0] > idleMs + graceMs) message = idleMessage;
152
+ else if (maxRuntimeMs > 0 && now - startedAt > maxRuntimeMs + graceMs) message = runtimeMessage;
153
+ if (message !== null) {
154
+ try { fs.writeSync(2, "\\n\\u2717 " + message + " (forced exit)\\n"); } catch {}
155
+ process.kill(process.pid, "SIGKILL");
156
+ }
157
+ }
158
+ `;
159
+ export const startWorkerBackstop = (options) => {
160
+ const flagBuffer = new SharedArrayBuffer(4);
161
+ const flag = new Int32Array(flagBuffer);
162
+ const worker = new Worker(BACKSTOP_SOURCE, {
163
+ eval: true,
164
+ workerData: {
165
+ flag: flagBuffer,
166
+ clock: options.clock.buffer,
167
+ startedAt: options.startedAt,
168
+ idleMs: options.idleMs,
169
+ maxRuntimeMs: options.maxRuntimeMs,
170
+ graceMs: options.graceMs,
171
+ idleMessage: options.idleMessage,
172
+ runtimeMessage: options.runtimeMessage,
173
+ },
174
+ });
175
+ worker.unref();
176
+ worker.on("error", () => {
177
+ // Best-effort; the in-process check still applies.
178
+ });
179
+ return {
180
+ cancel() {
181
+ Atomics.store(flag, 0, 1);
182
+ Atomics.notify(flag, 0);
183
+ void worker.terminate().catch(() => undefined);
184
+ },
185
+ };
186
+ };
187
+ let backstopStarterForTest = null;
188
+ /** Test seam: replace the worker backstop. `null` restores the real one. */
189
+ export function setSyncBackstopStarterForTesting(start) {
190
+ backstopStarterForTest = start;
191
+ }
192
+ /**
193
+ * Run `run` under the watchdog. Resolves or rejects with `run`'s outcome when
194
+ * it finishes within the limits. Otherwise rejects with
195
+ * {@link SyncWatchdogTimeoutError} and leaves the backstop armed: the caller
196
+ * is expected to exit the process. With both limits 0 it just runs `run`.
197
+ */
198
+ export async function withSyncWatchdog(run, options) {
199
+ const { idleMs, maxRuntimeMs, label } = options;
200
+ if (idleMs <= 0 && maxRuntimeMs <= 0)
201
+ return run();
202
+ const startedAt = monotonicNow();
203
+ if (!progressClock)
204
+ progressClock = new Float64Array(new SharedArrayBuffer(8));
205
+ noteSyncProgress();
206
+ const idleSeconds = Math.round(idleMs / 1000);
207
+ const runtimeSeconds = Math.round(maxRuntimeMs / 1000);
208
+ const backstop = (options.startBackstop ?? backstopStarterForTest ?? startWorkerBackstop)({
209
+ clock: progressClock,
210
+ startedAt,
211
+ idleMs,
212
+ maxRuntimeMs,
213
+ graceMs: options.backstopGraceMs ?? SYNC_WATCHDOG_BACKSTOP_GRACE_MS,
214
+ idleMessage: syncWatchdogMessage("idle", idleSeconds, label),
215
+ runtimeMessage: syncWatchdogMessage("runtime", runtimeSeconds, label),
216
+ });
217
+ const limits = [idleMs, maxRuntimeMs].filter((ms) => ms > 0);
218
+ const checkMs = options.checkIntervalMs ?? Math.max(10, Math.min(30_000, Math.floor(Math.min(...limits) / 4)));
219
+ let interval;
220
+ const deadline = new Promise((_, reject) => {
221
+ interval = setInterval(() => {
222
+ options.probeProgress?.();
223
+ const now = monotonicNow();
224
+ if (maxRuntimeMs > 0 && now - startedAt >= maxRuntimeMs) {
225
+ reject(new SyncWatchdogTimeoutError("runtime", runtimeSeconds, label));
226
+ }
227
+ else if (idleMs > 0 && now - lastProgressAt >= idleMs) {
228
+ reject(new SyncWatchdogTimeoutError("idle", idleSeconds, label));
229
+ }
230
+ }, checkMs);
231
+ });
232
+ let timedOut = false;
233
+ try {
234
+ return await Promise.race([run(), deadline]);
235
+ }
236
+ catch (err) {
237
+ if (err instanceof SyncWatchdogTimeoutError)
238
+ timedOut = true;
239
+ throw err;
240
+ }
241
+ finally {
242
+ if (interval !== undefined)
243
+ clearInterval(interval);
244
+ // After a timeout the backstop stays armed until the process exits, so
245
+ // a report or cleanup step that hangs cannot keep the process alive.
246
+ if (!timedOut)
247
+ backstop.cancel();
248
+ }
249
+ }
250
+ //# sourceMappingURL=sync-watchdog.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.345.170",
3
+ "version": "5.345.172",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -52,7 +52,7 @@
52
52
  "@aws-sdk/client-iot-data-plane": "^3.1096.0",
53
53
  "@aws-sdk/client-s3": "^3.1049.0",
54
54
  "@aws-sdk/dsql-signer": "^3.1146.0",
55
- "@indigoai-us/hq-cloud": "6.18.101",
55
+ "@indigoai-us/hq-cloud": "6.18.103",
56
56
  "@indigoai-us/hq-flags-client": "^0.1.2",
57
57
  "@modelcontextprotocol/sdk": "1.29.0",
58
58
  "@sentry/node": "^10.49.0",
@@ -114,11 +114,11 @@
114
114
  "*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}": "eslint --cache --no-error-on-unmatched-pattern"
115
115
  },
116
116
  "optionalDependencies": {
117
- "@indigoai-us/hq-hook-win32-x64": "5.345.170",
118
- "@indigoai-us/hq-hook-win32-arm64": "5.345.170",
119
- "@indigoai-us/hq-hook-darwin-x64": "5.345.170",
120
- "@indigoai-us/hq-hook-darwin-arm64": "5.345.170",
121
- "@indigoai-us/hq-hook-linux-x64": "5.345.170",
122
- "@indigoai-us/hq-hook-linux-arm64": "5.345.170"
117
+ "@indigoai-us/hq-hook-win32-x64": "5.345.172",
118
+ "@indigoai-us/hq-hook-win32-arm64": "5.345.172",
119
+ "@indigoai-us/hq-hook-darwin-x64": "5.345.172",
120
+ "@indigoai-us/hq-hook-darwin-arm64": "5.345.172",
121
+ "@indigoai-us/hq-hook-linux-x64": "5.345.172",
122
+ "@indigoai-us/hq-hook-linux-arm64": "5.345.172"
123
123
  }
124
124
  }
@@ -1,9 +0,0 @@
1
- import type { SyncCoreCanaryConfig } from "./config.js";
2
- export interface SyncCoreCanaryPlan {
3
- binaryPath?: string;
4
- vaultUid?: string;
5
- canaryPath?: string;
6
- blockedReason?: string;
7
- }
8
- export declare function inspectSyncCoreCanary(home: string, hqRoot: string | undefined, config: SyncCoreCanaryConfig, platform: NodeJS.Platform): SyncCoreCanaryPlan;
9
- //# sourceMappingURL=sync-core-canary.d.ts.map
@@ -1,56 +0,0 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import { parse as parseToml } from "smol-toml";
4
- function blocked(config, blockedReason) {
5
- return { ...config, blockedReason };
6
- }
7
- function record(value) {
8
- return value && typeof value === "object" && !Array.isArray(value)
9
- ? value
10
- : undefined;
11
- }
12
- export function inspectSyncCoreCanary(home, hqRoot, config, platform) {
13
- if (platform !== "darwin" && platform !== "linux") {
14
- return blocked(config, "the sync-core canary requires macOS or Linux");
15
- }
16
- try {
17
- if (!fs.statSync(config.binaryPath).isFile())
18
- return blocked(config, "the sync-core binary is missing");
19
- fs.accessSync(config.binaryPath, fs.constants.X_OK);
20
- }
21
- catch {
22
- return blocked(config, "the sync-core binary is missing or not executable");
23
- }
24
- const configPath = path.join(home, ".hq", "sync-core", "config.toml");
25
- let sync;
26
- try {
27
- sync = record(record(parseToml(fs.readFileSync(configPath, "utf8")))?.sync);
28
- }
29
- catch {
30
- return blocked(config, `the sync-core config at ${configPath} is missing or invalid`);
31
- }
32
- if (sync?.engine !== "rust-test" || sync.mode !== "full") {
33
- return blocked(config, "the sync-core config must select engine rust-test in full mode");
34
- }
35
- const vaults = sync.vaults;
36
- if (!Array.isArray(vaults) || vaults.length !== 1 || vaults[0] !== config.vaultUid) {
37
- return blocked(config, `the sync-core config must name exactly ${config.vaultUid}`);
38
- }
39
- if (!hqRoot || typeof sync.hq_root !== "string" || path.resolve(sync.hq_root) !== path.resolve(hqRoot)) {
40
- return blocked(config, "the sync-core config must use the daemon's HQ folder");
41
- }
42
- const canaryPath = typeof sync.canary_path === "string" ? sync.canary_path.trim() : "";
43
- if (!canaryPath)
44
- return blocked(config, "the sync-core config must name one canary path");
45
- const ownedPath = path.join(home, ".hq", "sync-core", "owned", `${config.vaultUid}.json`);
46
- try {
47
- const owned = record(JSON.parse(fs.readFileSync(ownedPath, "utf8")));
48
- if (owned?.vault !== config.vaultUid)
49
- throw new Error("mismatch");
50
- }
51
- catch {
52
- return blocked(config, `the sync-core ownership record for ${config.vaultUid} is missing or invalid`);
53
- }
54
- return { ...config, canaryPath };
55
- }
56
- //# sourceMappingURL=sync-core-canary.js.map