@indigoai-us/hq-cli 5.345.1 → 5.345.3

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.
@@ -36,7 +36,7 @@ import { MESSAGE_REPLAY_STATE_NAME } from "./message-replay.js";
36
36
  import { markAnsweredQuestionsDelivered } from "./questions.js";
37
37
  import { hasEarlierEligibleQueuedLane, laneAdmissionCapReason, withLaneAdmissionLock, } from "./admission.js";
38
38
  import { resolveAdmissionHost } from "./admission-host.js";
39
- import { checkLaneDiskSpace, lowDiskGuardEnabledForLane } from "./disk-guard.js";
39
+ import { checkLaneDiskSpace, laneDiskAccount } from "./disk-guard.js";
40
40
  import { LANE_ENVELOPE_JSON_SCHEMA, ENVELOPE_INVALID_REASON, parseLaneProvider, } from "./types.js";
41
41
  export const LANES_RUNS_REL = path.join("workspace", "lanes-runs");
42
42
  /** Written by reconcile before a resume spawn; the worker prompt names this path. */
@@ -606,7 +606,6 @@ export async function retryLaneOnAlternateAccount(hqRoot, lane, reason, writer =
606
606
  return moved;
607
607
  return spawnLaneWorker(hqRoot, moved, {
608
608
  ...deps,
609
- lowDiskGuardEnabled: deps.lowDiskGuardEnabled ?? await lowDiskGuardEnabledForLane(hqRoot, moved),
610
609
  });
611
610
  });
612
611
  }
@@ -1840,33 +1839,26 @@ export function spawnLaneWorker(hqRoot, lane, deps = {}, launch = {}) {
1840
1839
  probe: modelDeps.probe ?? defaultProbe,
1841
1840
  env,
1842
1841
  };
1843
- if (deps.lowDiskGuardEnabled === true) {
1844
- const providerConfig = config.providers[existing.provider];
1845
- const diskAccount = (existing.account !== undefined ? providerConfig.accounts[existing.account] : undefined) ??
1846
- (providerConfig.default_account !== undefined
1847
- ? providerConfig.accounts[providerConfig.default_account]
1848
- : undefined) ??
1849
- Object.values(providerConfig.accounts).find((account) => account.enabled);
1850
- if (diskAccount !== undefined) {
1851
- const free = checkLaneDiskSpace(hqRoot, effectiveAccountHome(diskAccount, hostname).home, deps.statfs, config.low_disk_min_free_bytes);
1852
- if (free.low) {
1853
- const measuredAt = (deps.now ?? (() => new Date()))().toISOString();
1854
- return retryUpdateLane(hqRoot, lane.lane_id, "spawn", (current) => ({
1855
- ...current,
1856
- state: "queued",
1857
- queued_reason: "low_disk",
1858
- queued_details: {
1859
- reason: "low_disk",
1860
- hq_free_bytes: free.hq.free_bytes,
1861
- provider_free_bytes: free.provider.free_bytes,
1862
- measured_at: measuredAt,
1863
- },
1864
- queued_at: current.queued_at ?? measuredAt,
1865
- admission_reserved_at: undefined,
1866
- terminal_reason: undefined,
1867
- terminal_details: undefined,
1868
- }));
1869
- }
1842
+ const diskAccount = laneDiskAccount(config, existing.provider, existing.account);
1843
+ if (diskAccount !== undefined) {
1844
+ const free = checkLaneDiskSpace(hqRoot, effectiveAccountHome(diskAccount, hostname).home, deps.statfs, config.low_disk_min_free_bytes);
1845
+ if (free.low) {
1846
+ const measuredAt = (deps.now ?? (() => new Date()))().toISOString();
1847
+ return retryUpdateLane(hqRoot, lane.lane_id, "spawn", (current) => ({
1848
+ ...current,
1849
+ state: "queued",
1850
+ queued_reason: "low_disk",
1851
+ queued_details: {
1852
+ reason: "low_disk",
1853
+ hq_free_bytes: free.hq.free_bytes,
1854
+ provider_free_bytes: free.provider.free_bytes,
1855
+ measured_at: measuredAt,
1856
+ },
1857
+ queued_at: current.queued_at ?? measuredAt,
1858
+ admission_reserved_at: undefined,
1859
+ terminal_reason: undefined,
1860
+ terminal_details: undefined,
1861
+ }));
1870
1862
  }
1871
1863
  }
1872
1864
  let selection;
@@ -863,6 +863,12 @@ async function settleBlockerFreshness(hqRoot, lane, manifestTurnId, at, deps, me
863
863
  retryUndeliverable = true;
864
864
  escalationText = `Blocker freshness escalation for ${current.lane_id}: these blockers remain stale after consecutive turns: ${staleLabels.join(", ")}. Status file: ${resolution.statusPath}.`;
865
865
  }
866
+ else if (failedFallback !== undefined) {
867
+ // If the senior inbox is still unavailable, retry the lane inbox fallback.
868
+ deliverFallback = true;
869
+ undeliverableReason = failedFallback.reason ?? prior?.undeliverable_reason ?? "The session senior inbox is unavailable";
870
+ escalationText = `Blocker freshness escalation for ${current.lane_id}: these blockers remain stale after consecutive turns: ${staleLabels.join(", ")}. Status file: ${resolution.statusPath}.`;
871
+ }
866
872
  else if (prior !== undefined && blockerFreshnessFingerprint(prior.stale_keys.map((key, index) => ({ key, label: prior.stale_labels[index] ?? "" }))) !== fingerprint) {
867
873
  escalatedFingerprint = undefined;
868
874
  }
@@ -34,7 +34,13 @@ export declare function createPackageUseLeaseHandoff(lease: PackageUseLease, tim
34
34
  export declare function createCurrentPackageUseLeaseHandoff(timeoutMs?: number): PackageUseLeaseHandoff | null;
35
35
  /** Publish this process's lease identity to a parent waiting in the same prefix. */
36
36
  export declare function publishPackageUseLeaseHandoff(lease: PackageUseLease, env?: NodeJS.ProcessEnv): boolean;
37
+ export declare function currentPackageUseLeaseInstall(): {
38
+ prefix: string;
39
+ version: string;
40
+ } | null;
37
41
  export declare function acquireCurrentPackageUseLease(argv?: readonly string[]): PackageUseLease | null;
42
+ /** Let a daemon bootstrap drop its temporary lease after this process published its own. */
43
+ export declare function signalPackageUseLeaseBootstrapHandoff(lease?: PackageUseLease | null): void;
38
44
  /** Release this process's package-use lease after a long-running command has loaded its package modules. */
39
45
  export declare function releaseCurrentPackageUseLease(): void;
40
46
  /** The lease remains held through command execution and is released on process exit. */
@@ -50,6 +50,7 @@ export function packageUseLeasePurposeForArgv(argv) {
50
50
  return "command";
51
51
  }
52
52
  let currentPackageUseLease = null;
53
+ const BOOTSTRAP_HANDOFF_ENV = "HQ_CLI_PACKAGE_USE_HANDOFF_TOKEN";
53
54
  function errorLabel(error) {
54
55
  if (error && typeof error === "object") {
55
56
  const value = error;
@@ -308,7 +309,7 @@ function exists(file) {
308
309
  throw error;
309
310
  }
310
311
  }
311
- export function acquireCurrentPackageUseLease(argv = process.argv) {
312
+ export function currentPackageUseLeaseInstall() {
312
313
  const pkg = findCliPackage(path.dirname(fileURLToPath(import.meta.url)));
313
314
  if (!pkg || isPnpmGlobal(pkg.root) || isBunGlobal(pkg.root))
314
315
  return null;
@@ -321,11 +322,33 @@ export function acquireCurrentPackageUseLease(argv = process.argv) {
321
322
  if (nodeModules > 0 && parts[nodeModules - 1] !== "lib")
322
323
  return null;
323
324
  }
324
- const lease = acquirePackageUseLease(prefix, pkg.version, undefined, packageUseLeasePurposeForArgv(argv));
325
+ return { prefix, version: pkg.version };
326
+ }
327
+ export function acquireCurrentPackageUseLease(argv = process.argv) {
328
+ const install = currentPackageUseLeaseInstall();
329
+ if (!install)
330
+ return null;
331
+ const lease = acquirePackageUseLease(install.prefix, install.version, undefined, packageUseLeasePurposeForArgv(argv));
325
332
  currentPackageUseLease = lease;
326
333
  publishPackageUseLeaseHandoff(lease);
327
334
  return lease;
328
335
  }
336
+ /** Let a daemon bootstrap drop its temporary lease after this process published its own. */
337
+ export function signalPackageUseLeaseBootstrapHandoff(lease = currentPackageUseLease) {
338
+ const token = process.env[BOOTSTRAP_HANDOFF_ENV];
339
+ if (token === undefined)
340
+ return;
341
+ delete process.env[BOOTSTRAP_HANDOFF_ENV];
342
+ if (!lease || !/^[a-f0-9]{32}$/.test(token))
343
+ return;
344
+ const markerPath = path.join(path.dirname(lease.leasePath), `handoff-${process.pid}-${token}.handoff`);
345
+ try {
346
+ writeFileSync(markerPath, `${process.pid}\n`, { flag: "wx", mode: 0o600 });
347
+ }
348
+ catch (error) {
349
+ process.stderr.write(`hq-cli package-use lease handoff signal failed (${errorLabel(error)})\n`);
350
+ }
351
+ }
329
352
  /** Release this process's package-use lease after a long-running command has loaded its package modules. */
330
353
  export function releaseCurrentPackageUseLease() {
331
354
  currentPackageUseLease?.release();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.345.1",
3
+ "version": "5.345.3",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -24,7 +24,7 @@
24
24
  "scripts/mesh-daemon-if-stale.mjs"
25
25
  ],
26
26
  "scripts": {
27
- "build": "node scripts/generate-dsn.mjs && node scripts/build-flag-registry-worker.mjs && tsc && node scripts/generate-command-catalog.mjs --check && node scripts/copy-schemas.mjs && node scripts/chmod-bins.mjs",
27
+ "build": "node scripts/generate-dsn.mjs && node scripts/build-flag-registry-worker.mjs && tsc && node scripts/generate-command-catalog.mjs --check && node scripts/copy-schemas.mjs && node scripts/chmod-bins.mjs && node scripts/bundle-sync-runner.mjs",
28
28
  "prepublishOnly": "npm run build",
29
29
  "pretypecheck": "node scripts/generate-dsn.mjs && node scripts/build-flag-registry-worker.mjs",
30
30
  "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.typetest.json",