@indigoai-us/hq-cli 5.342.7 → 5.342.8

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.342.8] — 2026-10-04
6
+ - Keep blocker escalation failures visible on the lane and stop retrying the same failed fallback every watcher turn.
7
+ - Release the daemon's hq-cli package-use lease after all reachable lazy runtime modules preload successfully, allowing CLI updates while preserving the existing restart-on-update path.
8
+
5
9
  ## [5.342.7] — 2026-10-04
6
10
  - Batch policy frontmatter reads into one `hq core policy frontmatter` invocation while preserving single-file output.
7
11
 
@@ -19,8 +19,8 @@ import type { HostApp } from "../lib/daemon/supervisor.js";
19
19
  import { type SyncModeVaultClient } from "./sync-mode.js";
20
20
  import type { RunCommand } from "../lib/service-manager/launchd.js";
21
21
  type DaemonRunnerModule = typeof import("../lib/daemon/run.js");
22
- /** Load the daemon runtime without releasing its lease: it reads package files while resident. */
23
- export declare function loadDaemonRunner(_release?: () => void, load?: () => Promise<DaemonRunnerModule>): Promise<DaemonRunnerModule["runDaemon"]>;
22
+ /** Load every lazy daemon runtime module before releasing its package-use lease. */
23
+ export declare function loadDaemonRunner(release?: () => void, load?: () => Promise<DaemonRunnerModule>, preload?: () => Promise<void>, reportPreloadFailure?: (error: unknown) => void): Promise<DaemonRunnerModule["runDaemon"]>;
24
24
  export interface DaemonCommandDeps {
25
25
  env: NodeJS.ProcessEnv;
26
26
  home: string;
@@ -35,10 +35,23 @@ import { requireAnywhereRuntime } from "./anywhere-runtime-flag.js";
35
35
  import { hqdRequest, hqdSocketPath, HqdClientError } from "../lib/daemon/protocol.js";
36
36
  import { parseStdinMachineCredentials } from "../lib/daemon/machine-login.js";
37
37
  import { resolveDefaultHqRoot } from "../utils/cognito-session.js";
38
- /** Load the daemon runtime without releasing its lease: it reads package files while resident. */
39
- export async function loadDaemonRunner(_release = () => undefined, load = () => import("../lib/daemon/run.js")) {
38
+ import { releaseCurrentPackageUseLease, releasePackageUseLeaseAfterResidentPreload } from "../utils/package-use-lease.js";
39
+ import { preloadResidentPackageModules, reportResidentPackagePreloadFailure } from "../utils/resident-package-preload.js";
40
+ /** Load every lazy daemon runtime module before releasing its package-use lease. */
41
+ export async function loadDaemonRunner(release = releaseCurrentPackageUseLease, load = () => import("../lib/daemon/run.js"), preload = () => preloadResidentPackageModules("daemon"), reportPreloadFailure = reportResidentPackagePreloadFailure) {
40
42
  const { runDaemon } = await load();
41
- return runDaemon;
43
+ let preloadComplete = false;
44
+ await releasePackageUseLeaseAfterResidentPreload(preload, reportPreloadFailure, () => {
45
+ preloadComplete = true;
46
+ });
47
+ return (options) => runDaemon({
48
+ ...options,
49
+ onStartupReadsComplete: () => {
50
+ options.onStartupReadsComplete?.();
51
+ if (preloadComplete)
52
+ release();
53
+ },
54
+ });
42
55
  }
43
56
  class DaemonCommandError extends Error {
44
57
  }
@@ -34,6 +34,8 @@ export interface RunDaemonOptions {
34
34
  env?: NodeJS.ProcessEnv;
35
35
  nodeBinary: string;
36
36
  hqBinary: string;
37
+ /** Called after the initial supervisor plan has finished package-backed startup reads. */
38
+ onStartupReadsComplete?: () => void;
37
39
  }
38
40
  export declare function resolveSyncRunnerPath(): string | null;
39
41
  /** The hosted desktop app uses this env value when planning daemon services. */
@@ -830,6 +830,9 @@ export async function runDaemon(opts) {
830
830
  releaseDaemonLock(paths.lockPath);
831
831
  resolve(1);
832
832
  }
833
+ finally {
834
+ opts.onStartupReadsComplete?.();
835
+ }
833
836
  });
834
837
  }
835
838
  /** Report an hqd op crash to the CLI's existing Sentry integration, tagged with the failing op. */
@@ -863,11 +863,6 @@ 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
- deliverFallback = true;
868
- undeliverableReason = failedFallback.reason ?? prior?.undeliverable_reason ?? "The session senior inbox is unavailable";
869
- escalationText = `Blocker freshness escalation for ${current.lane_id}: these blockers remain stale after consecutive turns: ${staleLabels.join(", ")}. Status file: ${resolution.statusPath}.`;
870
- }
871
866
  else if (prior !== undefined && blockerFreshnessFingerprint(prior.stale_keys.map((key, index) => ({ key, label: prior.stale_labels[index] ?? "" }))) !== fingerprint) {
872
867
  escalatedFingerprint = undefined;
873
868
  }
@@ -923,16 +918,18 @@ async function settleBlockerFreshness(hqRoot, lane, manifestTurnId, at, deps, me
923
918
  logDecision({ event: "blocker_stale_escalation_fallback_failed", at, turn_id: turnId, fingerprint, error: message });
924
919
  updated = retryUpdateLane(hqRoot, lane.lane_id, "watcher", (current) => {
925
920
  const state = current.blocker_freshness_state;
926
- const retryableState = state === undefined ? undefined : { ...state };
927
- if (retryableState !== undefined) {
928
- delete retryableState.undeliverable_fingerprint;
929
- delete retryableState.undeliverable_reason;
930
- }
921
+ const failureReason = `${undeliverableReason ?? `Session ${lane.senior.id ?? "unknown"} has no monitor-session inbox`}; lane inbox fallback failed: ${message}`;
931
922
  return {
932
923
  ...current,
933
- ...(retryableState !== undefined ? { blocker_freshness_state: retryableState } : {}),
924
+ ...(state !== undefined ? {
925
+ blocker_freshness_state: {
926
+ ...state,
927
+ undeliverable_fingerprint: fingerprint,
928
+ undeliverable_reason: failureReason,
929
+ },
930
+ } : {}),
934
931
  status_gate_history: (current.status_gate_history ?? []).map((entry) => entry.event === "blocker_stale_escalation_undeliverable" && entry.fingerprint === fingerprint
935
- ? { ...entry, delivery_failed: true }
932
+ ? { ...entry, delivery_failed: true, reason: failureReason }
936
933
  : entry),
937
934
  };
938
935
  });
@@ -1083,12 +1080,12 @@ function findBlockerFreshnessSessionInbox(hqRoot, sessionId) {
1083
1080
  .filter((sessionDir) => fs.existsSync(sessionDir));
1084
1081
  }
1085
1082
  catch (error) {
1086
- return { reason: `Could not resolve the monitor inbox for session senior: ${error instanceof Error ? error.message : String(error)}` };
1083
+ return { reason: `Could not resolve the monitor inbox for session ${sessionId}: ${error instanceof Error ? error.message : String(error)}` };
1087
1084
  }
1088
1085
  if (candidates.length !== 1) {
1089
1086
  return { reason: candidates.length === 0
1090
- ? "No monitor-session inbox is registered for the session senior"
1091
- : "The session senior matches more than one monitor-session inbox" };
1087
+ ? `No monitor-session inbox is registered for session ${sessionId}`
1088
+ : `Session ${sessionId} matches more than one monitor-session inbox` };
1092
1089
  }
1093
1090
  return { inbox: path.join(candidates[0], "dropbox") };
1094
1091
  }
package/dist/sentry.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import type { ErrorEvent, EventHint, NodeOptions } from "@sentry/node";
2
2
  type SentryModule = typeof import("@sentry/node");
3
+ /** Load the SDK through the same resolver used by the lazy Sentry facade. */
4
+ export declare function preloadSentrySdk(): void;
3
5
  /**
4
6
  * The command graph touches the Sentry facade on normal startup for a
5
7
  * breadcrumb and a final flush. Keep those operations inert until the SDK
package/dist/sentry.js CHANGED
@@ -24,6 +24,10 @@ function loadSentryModule() {
24
24
  sentryModule ??= requireSentry("@sentry/node");
25
25
  return sentryModule;
26
26
  }
27
+ /** Load the SDK through the same resolver used by the lazy Sentry facade. */
28
+ export function preloadSentrySdk() {
29
+ loadSentryModule();
30
+ }
27
31
  /**
28
32
  * The command graph touches the Sentry facade on normal startup for a
29
33
  * breadcrumb and a final flush. Keep those operations inert until the SDK
@@ -1,4 +1,4 @@
1
- export type ResidentPackagePath = "bot" | "mcp";
1
+ export type ResidentPackagePath = "bot" | "mcp" | "daemon";
2
2
  /** Package imports reachable lazily from each resident command's runtime graph. */
3
3
  export declare const RESIDENT_PACKAGE_MODULES: Record<ResidentPackagePath, readonly string[]>;
4
4
  export declare class ResidentPackagePreloadError extends Error {
@@ -2,18 +2,42 @@
2
2
  export const RESIDENT_PACKAGE_MODULES = {
3
3
  bot: ["../lib/flag-registry.js", "../commands/access.js", "../sentry.js", "open"],
4
4
  mcp: ["../lib/mcp/tools.js", "../lib/mcp/prompts.js"],
5
+ daemon: [
6
+ "../sentry.js",
7
+ "../utils/cognito-session.js",
8
+ "../lib/daemon/mcp-oauth.js",
9
+ "@modelcontextprotocol/sdk/client/index.js",
10
+ "@modelcontextprotocol/sdk/client/streamableHttp.js",
11
+ "../utils/staged-npm-install.js",
12
+ "open",
13
+ ],
5
14
  };
6
15
  const LOADERS = {
7
16
  bot: [
8
17
  () => import("../lib/flag-registry.js"),
9
18
  () => import("../commands/access.js"),
10
- () => import("../sentry.js"),
19
+ async () => {
20
+ const { preloadSentrySdk } = await import("../sentry.js");
21
+ preloadSentrySdk();
22
+ },
11
23
  () => import("open"),
12
24
  ],
13
25
  mcp: [
14
26
  () => import("../lib/mcp/tools.js"),
15
27
  () => import("../lib/mcp/prompts.js"),
16
28
  ],
29
+ daemon: [
30
+ async () => {
31
+ const { preloadSentrySdk } = await import("../sentry.js");
32
+ preloadSentrySdk();
33
+ },
34
+ () => import("../utils/cognito-session.js"),
35
+ () => import("../lib/daemon/mcp-oauth.js"),
36
+ () => import("@modelcontextprotocol/sdk/client/index.js"),
37
+ () => import("@modelcontextprotocol/sdk/client/streamableHttp.js"),
38
+ () => import("../utils/staged-npm-install.js"),
39
+ () => import("open"),
40
+ ],
17
41
  };
18
42
  export class ResidentPackagePreloadError extends Error {
19
43
  moduleSpecifier;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.342.7",
3
+ "version": "5.342.8",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {