@indigoai-us/hq-cli 5.309.0 → 5.309.1

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 (75) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/command-catalog.generated.d.ts +4 -1
  3. package/dist/command-catalog.generated.js +5 -1
  4. package/dist/commands/agents.js +6 -0
  5. package/dist/commands/core-checkpoint-gate-setting.d.ts +0 -10
  6. package/dist/commands/core-checkpoint-gate-setting.js +3 -3
  7. package/dist/commands/core-ontology.d.ts +1 -9
  8. package/dist/commands/core-ontology.js +4 -4
  9. package/dist/commands/core-policy.d.ts +0 -3
  10. package/dist/commands/core-policy.js +3 -3
  11. package/dist/commands/files.js +1 -1
  12. package/dist/commands/index-cmd.js +1 -1
  13. package/dist/commands/integrations-api.d.ts +9 -4
  14. package/dist/commands/integrations-api.js +9 -6
  15. package/dist/commands/integrations-manage.js +11 -3
  16. package/dist/commands/integrations.d.ts +8 -0
  17. package/dist/commands/integrations.js +83 -0
  18. package/dist/commands/lanes-checks.d.ts +0 -2
  19. package/dist/commands/lanes-checks.js +2 -2
  20. package/dist/commands/lanes.d.ts +0 -11
  21. package/dist/commands/lanes.js +6 -6
  22. package/dist/commands/mcp-registration.d.ts +5 -11
  23. package/dist/commands/mcp-registration.js +2 -6
  24. package/dist/lib/core-utils/sentry-report.d.ts +5 -11
  25. package/dist/lib/core-utils/sentry-report.js +2 -2
  26. package/dist/lib/db/local.d.ts +0 -5
  27. package/dist/lib/db/local.js +1 -1
  28. package/dist/lib/db/migrate.d.ts +0 -12
  29. package/dist/lib/db/migrate.js +5 -5
  30. package/dist/lib/db/sql.d.ts +0 -10
  31. package/dist/lib/db/sql.js +4 -8
  32. package/dist/lib/doctor/checks/codex-wiring.js +1 -33
  33. package/dist/lib/doctor/checks/grok-wiring.js +1 -34
  34. package/dist/lib/doctor/deep/effects.js +1 -3
  35. package/dist/lib/doctor/deep/sandbox.js +1 -3
  36. package/dist/lib/doctor/fixtures/schema.js +1 -3
  37. package/dist/lib/doctor/shared.d.ts +8 -0
  38. package/dist/lib/doctor/shared.js +38 -0
  39. package/dist/lib/lanes/autopilot.js +6 -4
  40. package/dist/lib/monitor.d.ts +2 -6
  41. package/dist/lib/monitor.js +5 -5
  42. package/dist/lib/report-publish.d.ts +1 -10
  43. package/dist/lib/report-publish.js +3 -9
  44. package/dist/lib/search-index/index.d.ts +7 -0
  45. package/dist/lib/search-index/index.js +21 -2
  46. package/dist/lib/search-index/qmd-exit-diagnostics.d.ts +5 -0
  47. package/dist/lib/search-index/qmd-exit-diagnostics.js +40 -0
  48. package/dist/lib/service-manager/launchd.d.ts +0 -7
  49. package/dist/lib/service-manager/launchd.js +2 -2
  50. package/dist/main.js +7 -2
  51. package/dist/startup-registration.js +9 -1
  52. package/dist/utils/client-health.d.ts +0 -4
  53. package/dist/utils/client-health.js +2 -2
  54. package/dist/utils/feedback-diagnostics.d.ts +2 -1
  55. package/dist/utils/feedback-log-bundle.d.ts +0 -25
  56. package/dist/utils/feedback-log-bundle.js +5 -5
  57. package/dist/utils/feedback-logs.d.ts +4 -38
  58. package/dist/utils/feedback-logs.js +7 -7
  59. package/dist/utils/feedback-screenshots.d.ts +0 -1
  60. package/dist/utils/feedback-screenshots.js +1 -1
  61. package/dist/utils/install-tree-torn.d.ts +19 -13
  62. package/dist/utils/install-tree-torn.js +77 -2
  63. package/dist/utils/local-files-overview.d.ts +0 -6
  64. package/dist/utils/local-files-overview.js +1 -1
  65. package/dist/utils/qmd-model-download-error.d.ts +0 -8
  66. package/dist/utils/qmd-model-download-error.js +1 -1
  67. package/dist/utils/qmd-query-document-error.d.ts +0 -6
  68. package/dist/utils/qmd-query-document-error.js +1 -1
  69. package/dist/utils/scaffold-fast-import-guard.d.ts +0 -1
  70. package/dist/utils/scaffold-fast-import-guard.js +1 -1
  71. package/dist/utils/scaffold-sibling-references.d.ts +3 -2
  72. package/dist/utils/sentry-fingerprint.js +17 -0
  73. package/dist/utils/version-gate.d.ts +4 -0
  74. package/dist/utils/version-gate.js +13 -0
  75. package/package.json +1 -1
@@ -76,6 +76,10 @@ export class QmdExitError extends Error {
76
76
  stdout;
77
77
  stderr;
78
78
  name = 'QmdExitError';
79
+ /** Safe route labels for telemetry; raw qmd streams remain local to the error. */
80
+ entryPath;
81
+ /** Present only when the invoked executable is the bundled qmd. */
82
+ qmdVersion;
79
83
  constructor(message, args, status, stdout, stderr) {
80
84
  super(message);
81
85
  this.args = args;
@@ -1239,6 +1243,21 @@ function finishRunQmd(result, bin, args, attribution) {
1239
1243
  }
1240
1244
  throw exitError;
1241
1245
  }
1246
+ function finishRunQmdWithDiagnostics(result, bin, args, options, attribution) {
1247
+ try {
1248
+ return finishRunQmd(result, bin, args, attribution);
1249
+ }
1250
+ catch (error) {
1251
+ if (error instanceof QmdExitError) {
1252
+ if (args[0] === 'update' && options.entryPath)
1253
+ error.entryPath = options.entryPath;
1254
+ const bundledBins = [packageLocalBin(), packageLocalNodeEntry()].filter((candidate) => Boolean(candidate));
1255
+ if (bundledBins.includes(bin))
1256
+ error.qmdVersion = resolveQmdVersion();
1257
+ }
1258
+ throw error;
1259
+ }
1260
+ }
1242
1261
  /** Run qmd with captured output and typed failures. */
1243
1262
  export function runQmd(args, options = {}) {
1244
1263
  // Legacy string-bin runner seam (tests and callers that inject a fake process):
@@ -1246,7 +1265,7 @@ export function runQmd(args, options = {}) {
1246
1265
  if (options.runner) {
1247
1266
  const bin = options.bin ?? resolveQmdBin({ env: options.env });
1248
1267
  const result = options.runner(bin, args, { cwd: options.cwd, env: options.env });
1249
- return finishRunQmd(result, bin, args);
1268
+ return finishRunQmdWithDiagnostics(result, bin, args, options);
1250
1269
  }
1251
1270
  // Default path: resolve the full invocation (shell-free Node launcher preferred)
1252
1271
  // and spawn it through the shared Windows-aware plan. An explicit string bin is
@@ -1279,7 +1298,7 @@ export function runQmd(args, options = {}) {
1279
1298
  // genuinely missing qmd — instead of blaming the launcher for all three
1280
1299
  // (HQ-CLI-1A). `command` is the process actually spawned; `launcher` is qmd's
1281
1300
  // file identity.
1282
- return finishRunQmd(result, launcher, args, {
1301
+ return finishRunQmdWithDiagnostics(result, launcher, args, options, {
1283
1302
  command: invocation.command,
1284
1303
  launcher,
1285
1304
  cwd: options.cwd,
@@ -0,0 +1,5 @@
1
+ /** Bounded Sentry tags for qmd exits; never return captured streams or full argv. */
2
+ export declare function qmdExitCaptureContext(err: unknown): {
3
+ tags: Record<string, string>;
4
+ } | undefined;
5
+ //# sourceMappingURL=qmd-exit-diagnostics.d.ts.map
@@ -0,0 +1,40 @@
1
+ import { QmdExitError } from "./index.js";
2
+ const QMD_ERROR_CODE_TOKENS = [
3
+ "SQLITE_BUSY",
4
+ "SQLITE_CORRUPT",
5
+ "SQLITE_FULL",
6
+ "ENOSPC",
7
+ "EACCES",
8
+ "EPERM",
9
+ "ENOENT",
10
+ "ECONNRESET",
11
+ "ETIMEDOUT",
12
+ ];
13
+ const QMD_UPDATE_ENTRY_PATHS = new Set(["index-sync"]);
14
+ /** Bounded Sentry tags for qmd exits; never return captured streams or full argv. */
15
+ export function qmdExitCaptureContext(err) {
16
+ if (!(err instanceof QmdExitError))
17
+ return undefined;
18
+ const output = err.stderr + "\n" + err.stdout;
19
+ const errorCode = QMD_ERROR_CODE_TOKENS.find((token) => new RegExp("(^|[^A-Za-z0-9_])" + token + "(?=$|[^A-Za-z0-9_])").test(output)) ?? "none";
20
+ const firstArg = err.args[0];
21
+ const subcommand = typeof firstArg === "string" && /^[a-z][a-z0-9_-]{0,31}$/.test(firstArg)
22
+ ? firstArg
23
+ : "unknown";
24
+ const exitStatus = typeof err.status === "number" && Number.isSafeInteger(err.status)
25
+ ? String(err.status)
26
+ : "unknown";
27
+ const tags = {
28
+ qmd_error_code: errorCode,
29
+ qmd_subcommand: subcommand,
30
+ qmd_exit_status: exitStatus,
31
+ };
32
+ if (typeof err.qmdVersion === "string" && /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(err.qmdVersion)) {
33
+ tags.qmd_version = err.qmdVersion;
34
+ }
35
+ if (typeof err.entryPath === "string" && QMD_UPDATE_ENTRY_PATHS.has(err.entryPath)) {
36
+ tags.qmd_entry_path = err.entryPath;
37
+ }
38
+ return { tags };
39
+ }
40
+ //# sourceMappingURL=qmd-exit-diagnostics.js.map
@@ -7,7 +7,6 @@
7
7
  * touch launchctl.
8
8
  */
9
9
  import { type ServiceHostPaths, type ServiceSpec } from "./types.js";
10
- export declare const LAUNCHD_PATH_ENV = "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin";
11
10
  export declare function launchAgentsDir(home: string): string;
12
11
  export declare function launchdPlistPath(home: string, spec: Pick<ServiceSpec, "label">): string;
13
12
  export declare function renderLaunchdPlist(spec: ServiceSpec, host: ServiceHostPaths): string;
@@ -27,12 +26,6 @@ export declare const LAUNCHD_BOOTSTRAP_BACKOFF_MS: readonly number[];
27
26
  export declare const LAUNCHD_BOOTSTRAP_ATTEMPTS: number;
28
27
  export declare const defaultRunCommand: RunCommand;
29
28
  export declare function launchdServiceTarget(plistPath: string, uid?: number): string;
30
- /** launchd returns EIO (5) when bootstrap races the previous job's exit. */
31
- export declare function isRetryableLaunchdBootstrap(r: {
32
- status: number | null;
33
- stdout: string;
34
- stderr: string;
35
- }): boolean;
36
29
  /** ProgramArguments from a LaunchAgent plist. */
37
30
  export declare function launchdPlistProgramArguments(plist: string): string[];
38
31
  /**
@@ -10,7 +10,7 @@ import { spawnSync } from "node:child_process";
10
10
  import * as os from "node:os";
11
11
  import * as path from "node:path";
12
12
  import { escapeXml, } from "./types.js";
13
- export const LAUNCHD_PATH_ENV = "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin";
13
+ const LAUNCHD_PATH_ENV = "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin";
14
14
  export function launchAgentsDir(home) {
15
15
  return path.join(home, "Library", "LaunchAgents");
16
16
  }
@@ -89,7 +89,7 @@ function bootstrapErrorText(r) {
89
89
  return `${r.stderr} ${r.stdout} exit ${r.status ?? ""}`;
90
90
  }
91
91
  /** launchd returns EIO (5) when bootstrap races the previous job's exit. */
92
- export function isRetryableLaunchdBootstrap(r) {
92
+ function isRetryableLaunchdBootstrap(r) {
93
93
  if (r.status === 0)
94
94
  return false;
95
95
  return /Input\/output error|\bEIO\b|Bootstrap failed: 5|Boot-strap failed: 5/i.test(bootstrapErrorText(r));
package/dist/main.js CHANGED
@@ -24,6 +24,7 @@ import { qmdStoreUnopenableMessage } from "./utils/qmd-store-unopenable-error.js
24
24
  import { qmdQueryDocumentMessage } from "./utils/qmd-query-document-error.js";
25
25
  import { qmdModelDownloadMessage } from "./utils/qmd-model-download-error.js";
26
26
  import { qmdWorkdirMissingMessage } from "./utils/qmd-workdir-missing-error.js";
27
+ import { qmdExitCaptureContext } from "./lib/search-index/qmd-exit-diagnostics.js";
27
28
  import { hqStateWriteErrorMessage } from "./utils/hq-state-write-error.js";
28
29
  import { checkpointStampWriteCaptureContext, checkpointStampWriteMessage, } from "./utils/checkpoint-stamp-write-error.js";
29
30
  import { incompleteInstallMessage, incompleteInstallCaptureContext, } from "./utils/incomplete-install-error.js";
@@ -872,9 +873,13 @@ export async function handleTopLevelError(err, deps = defaultTopLevelErrorDepend
872
873
  // Every other error captures bare, exactly as before.
873
874
  const spawnContext = qmdSpawnFailureCaptureContext(err);
874
875
  const installContext = incompleteInstallCaptureContext(err);
875
- if (spawnContext || installContext) {
876
+ const qmdContext = qmdExitCaptureContext(err);
877
+ if (spawnContext || installContext || qmdContext) {
876
878
  deps.sentry.captureException(err, {
877
- contexts: { ...spawnContext?.contexts, ...installContext },
879
+ ...qmdContext,
880
+ ...((spawnContext || installContext)
881
+ ? { contexts: { ...spawnContext?.contexts, ...installContext } }
882
+ : {}),
878
883
  });
879
884
  }
880
885
  else {
@@ -17,7 +17,7 @@
17
17
  * spawns, waits, or a real install tree.
18
18
  */
19
19
  import { spawnSync } from "node:child_process";
20
- import { resolveRunningInstall } from "./utils/version-gate.js";
20
+ import { getVersionGatePhase, resolveRunningInstall } from "./utils/version-gate.js";
21
21
  import { stringDerivedPackageRoot } from "./utils/hq-roots.js";
22
22
  import { updateLockPath, UPDATE_LOCK_STALE_MS } from "./utils/update-lock.js";
23
23
  import { classifyEvalThrow, classifyModuleNotFound, installRewriteInProgress, InstallTreeTornError, waitForInstallTreeSettled, } from "./utils/install-tree-torn.js";
@@ -122,6 +122,7 @@ export async function registerCommandsWithRecovery(args) {
122
122
  cause: err,
123
123
  classified,
124
124
  packageRoot,
125
+ versionGatePhase: getVersionGatePhase(),
125
126
  outcome: "guarded",
126
127
  treeState: env[INSTALL_TREE_RECOVERY_TREE_STATE_ENV] === "stale" ? "stale" : "in_flight",
127
128
  attempt: 2,
@@ -165,6 +166,9 @@ export async function registerCommandsWithRecovery(args) {
165
166
  sawLock: result.sawLock,
166
167
  sawRetired: result.sawRetired,
167
168
  retiredSiblingPresent: result.retiredSiblingPresent,
169
+ retiredSiblingKind: result.retiredSiblingKind,
170
+ installTargetState: result.installTargetState,
171
+ updaterPidAlive: result.updaterPidAlive,
168
172
  sawTreeChange: result.sawTreeChange,
169
173
  lockHeldAtEnd: result.lockHeldAtEnd,
170
174
  lockedMs: result.lockedMs,
@@ -189,6 +193,7 @@ export async function registerCommandsWithRecovery(args) {
189
193
  cause: err,
190
194
  classified,
191
195
  packageRoot,
196
+ versionGatePhase: getVersionGatePhase(),
192
197
  outcome: "reexec-failed",
193
198
  treeState,
194
199
  attempt: 1,
@@ -196,6 +201,9 @@ export async function registerCommandsWithRecovery(args) {
196
201
  sawLock: result.sawLock,
197
202
  sawRetired: result.sawRetired,
198
203
  retiredSiblingPresent: result.retiredSiblingPresent,
204
+ retiredSiblingKind: result.retiredSiblingKind,
205
+ installTargetState: result.installTargetState,
206
+ updaterPidAlive: result.updaterPidAlive,
199
207
  sawTreeChange: result.sawTreeChange,
200
208
  lockTool: result.lockTool,
201
209
  });
@@ -33,8 +33,6 @@
33
33
  import { isExpiring, loadCachedTokens } from "./cognito-session.js";
34
34
  import { type VersionInfo } from "./feedback-versions.js";
35
35
  import { type ClientHealthArch, type ClientHealthHeartbeat, type ClientHealthLocalFilesOverview, type ClientHealthPlatform } from "./client-health-contract.js";
36
- /** Same bound as CLI telemetry: a heartbeat may never stall a command. */
37
- export declare const CLIENT_HEALTH_TIMEOUT_MS = 1200;
38
36
  export declare const CLIENT_HEALTH_STATE_FILE = "cli-client-health.json";
39
37
  /**
40
38
  * Single-flight marker for the journal observation below. Held only for the
@@ -66,8 +64,6 @@ export declare const CLIENT_HEALTH_OBSERVATION_FILE = "cli-client-health.observa
66
64
  * always re-observe — they have opened the store anyway, so it costs nothing.
67
65
  */
68
66
  export declare const JOURNAL_OBSERVATION_TTL_MS: number;
69
- /** An observation lock older than this is treated as abandoned. */
70
- export declare const JOURNAL_OBSERVATION_LOCK_STALE_MS: number;
71
67
  export interface CliClientHealthState {
72
68
  /** Stable random installation identity — regenerated only if invalid. */
73
69
  installationId: string;
@@ -40,7 +40,7 @@ import { collectVersions } from "./feedback-versions.js";
40
40
  import { CLIENT_HEALTH_CONTRACT_VERSION, parseClientHealthHeartbeat, } from "./client-health-contract.js";
41
41
  import { collectLocalFilesOverview } from "./local-files-overview.js";
42
42
  /** Same bound as CLI telemetry: a heartbeat may never stall a command. */
43
- export const CLIENT_HEALTH_TIMEOUT_MS = 1_200;
43
+ const CLIENT_HEALTH_TIMEOUT_MS = 1_200;
44
44
  export const CLIENT_HEALTH_STATE_FILE = "cli-client-health.json";
45
45
  /**
46
46
  * Single-flight marker for the journal observation below. Held only for the
@@ -73,7 +73,7 @@ export const CLIENT_HEALTH_OBSERVATION_FILE = "cli-client-health.observation.jso
73
73
  */
74
74
  export const JOURNAL_OBSERVATION_TTL_MS = 15 * 60_000;
75
75
  /** An observation lock older than this is treated as abandoned. */
76
- export const JOURNAL_OBSERVATION_LOCK_STALE_MS = 5 * 60_000;
76
+ const JOURNAL_OBSERVATION_LOCK_STALE_MS = 5 * 60_000;
77
77
  /**
78
78
  * Pre-filter mirror of the contract's SemVer shape (the contract keeps its
79
79
  * validators private). A version failing this is DROPPED individually so one
@@ -1,6 +1,6 @@
1
1
  import { type VersionInfo } from "./feedback-versions.js";
2
2
  import type { FeedbackLogsBlob } from "./feedback-logs.js";
3
- export interface GitContext {
3
+ interface GitContext {
4
4
  branch: string | null;
5
5
  head: string | null;
6
6
  dirty: boolean;
@@ -37,4 +37,5 @@ export interface DiagnosticsBlob {
37
37
  }
38
38
  export declare function sanitizeArgv(argv: string[]): string[];
39
39
  export declare function collectDiagnostics(): DiagnosticsBlob;
40
+ export {};
40
41
  //# sourceMappingURL=feedback-diagnostics.d.ts.map
@@ -61,29 +61,6 @@ import { vaultApiFetch } from "./vault-api.js";
61
61
  * stay in step or the CLI will build bundles the server will not accept.
62
62
  */
63
63
  export declare const LOG_BUNDLE_MAX_BYTES: number;
64
- /**
65
- * What the presign request declares, and what the server must answer with.
66
- * Mirrors `LOG_BUNDLE_FORMAT_ZIP` / `LOG_BUNDLE_ZIP_CONTENT_TYPE` in the hq-pro
67
- * handler `feedback-log-bundles.ts`.
68
- */
69
- export declare const LOG_BUNDLE_FORMAT = "zip";
70
- export declare const LOG_BUNDLE_CONTENT_TYPE = "application/zip";
71
- /**
72
- * Headroom between the size we stop feeding at and the hard cap.
73
- *
74
- * deflate reports compressed bytes only as its internal buffer flushes, so the
75
- * running total lags the bytes actually consumed. The lag is bounded by that
76
- * buffer (tens of KiB); a 1 MiB margin covers it with three orders of magnitude
77
- * to spare, and the final size is asserted against the real cap regardless.
78
- */
79
- export declare const LOG_BUNDLE_SAFETY_MARGIN_BYTES: number;
80
- /**
81
- * Per-file raw ceiling. The desktop logger rotates at 32 MiB (hq-desktop-core
82
- * `logfile.rs`), so this admits a full generation with headroom while stopping
83
- * one pathological file from consuming the whole bundle. Files above it are
84
- * read from the TAIL — the end of a log is what explains a failure.
85
- */
86
- export declare const LOG_BUNDLE_MAX_FILE_RAW_BYTES: number;
87
64
  export interface LogBundleResult {
88
65
  /** The zipped NDJSON bytes, ready to PUT. */
89
66
  bytes: Buffer;
@@ -150,8 +127,6 @@ export declare const ZIP32_UNCOMPRESSED_STOP_BYTES: number;
150
127
  */
151
128
  export declare function entryCeiling(requested?: number): number;
152
129
  export declare function crc32Fallback(buf: Buffer, seed?: number): number;
153
- /** Exported for the test that proves the fallback agrees with the native one. */
154
- export declare function crc32(buf: Buffer, seed?: number): number;
155
130
  /**
156
131
  * Bytes of ZIP framing around one entry: local header, central directory
157
132
  * header, end-of-central-directory. The name is stored twice.
@@ -71,8 +71,8 @@ export const LOG_BUNDLE_MAX_BYTES = 50 * 1024 * 1024;
71
71
  * Mirrors `LOG_BUNDLE_FORMAT_ZIP` / `LOG_BUNDLE_ZIP_CONTENT_TYPE` in the hq-pro
72
72
  * handler `feedback-log-bundles.ts`.
73
73
  */
74
- export const LOG_BUNDLE_FORMAT = "zip";
75
- export const LOG_BUNDLE_CONTENT_TYPE = "application/zip";
74
+ const LOG_BUNDLE_FORMAT = "zip";
75
+ const LOG_BUNDLE_CONTENT_TYPE = "application/zip";
76
76
  /**
77
77
  * Headroom between the size we stop feeding at and the hard cap.
78
78
  *
@@ -81,14 +81,14 @@ export const LOG_BUNDLE_CONTENT_TYPE = "application/zip";
81
81
  * buffer (tens of KiB); a 1 MiB margin covers it with three orders of magnitude
82
82
  * to spare, and the final size is asserted against the real cap regardless.
83
83
  */
84
- export const LOG_BUNDLE_SAFETY_MARGIN_BYTES = 1024 * 1024;
84
+ const LOG_BUNDLE_SAFETY_MARGIN_BYTES = 1024 * 1024;
85
85
  /**
86
86
  * Per-file raw ceiling. The desktop logger rotates at 32 MiB (hq-desktop-core
87
87
  * `logfile.rs`), so this admits a full generation with headroom while stopping
88
88
  * one pathological file from consuming the whole bundle. Files above it are
89
89
  * read from the TAIL — the end of a log is what explains a failure.
90
90
  */
91
- export const LOG_BUNDLE_MAX_FILE_RAW_BYTES = 64 * 1024 * 1024;
91
+ const LOG_BUNDLE_MAX_FILE_RAW_BYTES = 64 * 1024 * 1024;
92
92
  /** Read slice size. Bounds peak memory; unrelated to the output chunking. */
93
93
  const READ_SLICE_BYTES = 4 * 1024 * 1024;
94
94
  /** Target raw text per emitted chunk record. Keeps NDJSON lines manageable. */
@@ -217,7 +217,7 @@ export function crc32Fallback(buf, seed = 0) {
217
217
  return (~crc >>> 0) >>> 0;
218
218
  }
219
219
  /** Exported for the test that proves the fallback agrees with the native one. */
220
- export function crc32(buf, seed = 0) {
220
+ function crc32(buf, seed = 0) {
221
221
  const native = zlib.crc32;
222
222
  return typeof native === "function" ? native(buf, seed) : crc32Fallback(buf, seed);
223
223
  }
@@ -84,13 +84,6 @@ export declare const FEEDBACK_LOGS_MIN_USEFUL_BYTES = 1024;
84
84
  * evidence. The overflow count preserves the signal without the bytes.
85
85
  */
86
86
  export declare const FEEDBACK_MAX_SKIPPED_ENTRIES = 25;
87
- /** Subdirectory of `~/.hq` whose log files are eligible. Not recursive. */
88
- export declare const FEEDBACK_LOGS_DIRNAME = "logs";
89
- /**
90
- * Eligible extensions inside `~/.hq/logs/`. `.jsonl` is included because the
91
- * CLI's MCP registry audit trail is JSON-lines, not plain text.
92
- */
93
- export declare const FEEDBACK_LOG_EXTENSIONS: readonly string[];
94
87
  /**
95
88
  * True for a log filename, including a ROTATED generation.
96
89
  *
@@ -103,26 +96,6 @@ export declare const FEEDBACK_LOG_EXTENSIONS: readonly string[];
103
96
  export declare function isEligibleLogName(name: string): boolean;
104
97
  /** Per-state-file ceiling. These are status documents, not streams. */
105
98
  export declare const FEEDBACK_STATE_MAX_FILE_BYTES: number;
106
- /**
107
- * Ceiling on all state snapshots combined. Deliberately a small slice of the
108
- * overall budget: state is dense but finite, and the rest belongs to logs.
109
- */
110
- export declare const FEEDBACK_STATE_MAX_TOTAL_BYTES: number;
111
- /**
112
- * State files at the `~/.hq` ROOT that are eligible, by EXACT name.
113
- *
114
- * The root is where `cognito-tokens.json`, `deploy-passwords.json`, and
115
- * `secrets-cache/` live, so it is never globbed. Adding a name here is a
116
- * deliberate act: confirm the file carries no credential before listing it.
117
- */
118
- export declare const FEEDBACK_STATE_FILENAMES: readonly string[];
119
- /**
120
- * Per-company sync journal LOCATORS (`sync-journal.<slug>.json`) are also
121
- * eligible. Matched by an exact prefix AND a `.json` suffix, which is what
122
- * excludes the multi-hundred-megabyte `…json.last-good` snapshots sitting
123
- * beside them. No credential file at the root carries this prefix.
124
- */
125
- export declare const FEEDBACK_STATE_JOURNAL_PREFIX = "sync-journal.";
126
99
  /**
127
100
  * `~/.hq/locks/` — held operation locks and background-work claims.
128
101
  *
@@ -141,8 +114,6 @@ export declare const FEEDBACK_LOCKS_DIRNAME = "locks";
141
114
  * bounds that walk carries.
142
115
  */
143
116
  export declare const FEEDBACK_JOBS_DIRNAME = "jobs";
144
- /** Per-entry ceiling for a lock file. Their value is the name plus a little context. */
145
- export declare const FEEDBACK_LOCK_MAX_FILE_BYTES = 512;
146
117
  /**
147
118
  * Bounds on the `jobs/` walk. Depth 3 reaches
148
119
  * `jobs/probes/<job>/last-attempt.json`; the file cap stops a pathological
@@ -152,15 +123,9 @@ export declare const FEEDBACK_JOBS_MAX_DEPTH = 3;
152
123
  export declare const FEEDBACK_JOBS_MAX_FILES = 20;
153
124
  /** Ceiling on how many lock entries are collected. */
154
125
  export declare const FEEDBACK_LOCKS_MAX_FILES = 20;
155
- /**
156
- * Log files that live at the root of `~/.hq` rather than under `logs/`.
157
- * Listed explicitly — the root directory holds credentials and must never be
158
- * enumerated by pattern.
159
- */
160
- export declare const FEEDBACK_ROOT_LOG_FILENAMES: readonly string[];
161
126
  /** Why a discovered log file contributed nothing to the submission. */
162
- export type SkipReason = "budget" | "empty" | "unreadable";
163
- export interface LogTail {
127
+ type SkipReason = "budget" | "empty" | "unreadable";
128
+ interface LogTail {
164
129
  /** Path relative to `~/.hq`, e.g. `logs/hq-sync.log`. Never absolute. */
165
130
  name: string;
166
131
  /** Full on-disk size, even when only a tail was included. */
@@ -177,7 +142,7 @@ export interface LogTail {
177
142
  tail: string;
178
143
  }
179
144
  /** A small JSON status document included whole (or head-truncated). */
180
- export interface StateSnapshot {
145
+ interface StateSnapshot {
181
146
  /** Path relative to `~/.hq`, e.g. `sync-progress.json`. Never absolute. */
182
147
  name: string;
183
148
  sizeBytes: number;
@@ -331,4 +296,5 @@ export interface CollectFeedbackLogsOptions {
331
296
  * omit the field entirely rather than attach an empty object. Never throws.
332
297
  */
333
298
  export declare function collectFeedbackLogs(opts?: CollectFeedbackLogsOptions): FeedbackLogsBlob | undefined;
299
+ export {};
334
300
  //# sourceMappingURL=feedback-logs.d.ts.map
@@ -89,12 +89,12 @@ export const FEEDBACK_LOGS_MIN_USEFUL_BYTES = 1024;
89
89
  */
90
90
  export const FEEDBACK_MAX_SKIPPED_ENTRIES = 25;
91
91
  /** Subdirectory of `~/.hq` whose log files are eligible. Not recursive. */
92
- export const FEEDBACK_LOGS_DIRNAME = "logs";
92
+ const FEEDBACK_LOGS_DIRNAME = "logs";
93
93
  /**
94
94
  * Eligible extensions inside `~/.hq/logs/`. `.jsonl` is included because the
95
95
  * CLI's MCP registry audit trail is JSON-lines, not plain text.
96
96
  */
97
- export const FEEDBACK_LOG_EXTENSIONS = [".log", ".jsonl"];
97
+ const FEEDBACK_LOG_EXTENSIONS = [".log", ".jsonl"];
98
98
  /**
99
99
  * True for a log filename, including a ROTATED generation.
100
100
  *
@@ -120,7 +120,7 @@ export const FEEDBACK_STATE_MAX_FILE_BYTES = 4 * 1024;
120
120
  * Ceiling on all state snapshots combined. Deliberately a small slice of the
121
121
  * overall budget: state is dense but finite, and the rest belongs to logs.
122
122
  */
123
- export const FEEDBACK_STATE_MAX_TOTAL_BYTES = 12 * 1024;
123
+ const FEEDBACK_STATE_MAX_TOTAL_BYTES = 12 * 1024;
124
124
  /**
125
125
  * State files at the `~/.hq` ROOT that are eligible, by EXACT name.
126
126
  *
@@ -128,7 +128,7 @@ export const FEEDBACK_STATE_MAX_TOTAL_BYTES = 12 * 1024;
128
128
  * `secrets-cache/` live, so it is never globbed. Adding a name here is a
129
129
  * deliberate act: confirm the file carries no credential before listing it.
130
130
  */
131
- export const FEEDBACK_STATE_FILENAMES = [
131
+ const FEEDBACK_STATE_FILENAMES = [
132
132
  // In-flight sync: phase, file counts, conflict count, current file.
133
133
  "sync-progress.json",
134
134
  // Sync contract version the installation last wrote.
@@ -150,7 +150,7 @@ export const FEEDBACK_STATE_FILENAMES = [
150
150
  * excludes the multi-hundred-megabyte `…json.last-good` snapshots sitting
151
151
  * beside them. No credential file at the root carries this prefix.
152
152
  */
153
- export const FEEDBACK_STATE_JOURNAL_PREFIX = "sync-journal.";
153
+ const FEEDBACK_STATE_JOURNAL_PREFIX = "sync-journal.";
154
154
  /**
155
155
  * `~/.hq/locks/` — held operation locks and background-work claims.
156
156
  *
@@ -170,7 +170,7 @@ export const FEEDBACK_LOCKS_DIRNAME = "locks";
170
170
  */
171
171
  export const FEEDBACK_JOBS_DIRNAME = "jobs";
172
172
  /** Per-entry ceiling for a lock file. Their value is the name plus a little context. */
173
- export const FEEDBACK_LOCK_MAX_FILE_BYTES = 512;
173
+ const FEEDBACK_LOCK_MAX_FILE_BYTES = 512;
174
174
  /**
175
175
  * Bounds on the `jobs/` walk. Depth 3 reaches
176
176
  * `jobs/probes/<job>/last-attempt.json`; the file cap stops a pathological
@@ -185,7 +185,7 @@ export const FEEDBACK_LOCKS_MAX_FILES = 20;
185
185
  * Listed explicitly — the root directory holds credentials and must never be
186
186
  * enumerated by pattern.
187
187
  */
188
- export const FEEDBACK_ROOT_LOG_FILENAMES = [
188
+ const FEEDBACK_ROOT_LOG_FILENAMES = [
189
189
  "boot-sync.log",
190
190
  "boot-capture.log",
191
191
  ];
@@ -1,5 +1,4 @@
1
1
  export declare const MAX_SCREENSHOTS = 5;
2
- export declare const MAX_SCREENSHOT_BYTES: number;
3
2
  export declare function contentTypeForPath(filePath: string): string;
4
3
  export interface ScreenshotInput {
5
4
  path: string;
@@ -3,7 +3,7 @@ import * as path from "node:path";
3
3
  import { vaultApiFetch } from "./vault-api.js";
4
4
  export const MAX_SCREENSHOTS = 5;
5
5
  // Per-image ceiling. Screenshots are PNG/JPEG captures; 10 MB is generous.
6
- export const MAX_SCREENSHOT_BYTES = 10 * 1024 * 1024;
6
+ const MAX_SCREENSHOT_BYTES = 10 * 1024 * 1024;
7
7
  // Extension → content type. Must stay in sync with the server's allowed set
8
8
  // (hq-pro feedback-screenshots.ts ALLOWED_CONTENT_TYPES).
9
9
  const EXT_CONTENT_TYPE = {
@@ -37,7 +37,7 @@
37
37
  * for a module-EVALUATION throw that carries NO real `code` (HQ-CLI-1T) — see
38
38
  * {@link ModuleErrorDialect}.
39
39
  */
40
- export type ModuleNotFoundCode = "ERR_MODULE_NOT_FOUND" | "MODULE_NOT_FOUND" | "ENOENT" | "EVAL_THROW";
40
+ type ModuleNotFoundCode = "ERR_MODULE_NOT_FOUND" | "MODULE_NOT_FOUND" | "ENOENT" | "EVAL_THROW";
41
41
  /**
42
42
  * The closed set of resolution-failure dialects, verified on Node v22.23.1 and
43
43
  * the observed Node 24 synchronous ESM loader shape (the @sentry/node
@@ -78,7 +78,7 @@ export type ModuleNotFoundCode = "ERR_MODULE_NOT_FOUND" | "MODULE_NOT_FOUND" | "
78
78
  * - `unknown`: a module-not-found whose message did not parse; recovery
79
79
  * still waits on the lock / retired-dir / quiet signals.
80
80
  */
81
- export type ModuleErrorDialect = "esm-path" | "esm-package" | "cjs-path" | "cjs-package" | "cjs-relative" | "esm-enoent" | "cjs-enoent" | "resolve-enoent" | "eval-throw" | "unknown";
81
+ type ModuleErrorDialect = "esm-path" | "esm-package" | "cjs-path" | "cjs-package" | "cjs-relative" | "esm-enoent" | "cjs-enoent" | "resolve-enoent" | "eval-throw" | "unknown";
82
82
  /**
83
83
  * The missing thing, re-resolvable by the readiness probe:
84
84
  * - `path`: an absolute filesystem path (a `.js` file, or a package dir).
@@ -214,15 +214,6 @@ export interface InstallTreeFs {
214
214
  * Any filesystem error reads as "not present" rather than throwing.
215
215
  */
216
216
  export declare function installTargetPresent(target: ModuleErrorTarget, fs?: InstallTreeFs): boolean;
217
- /**
218
- * Default ceiling on the CUMULATIVE time the wait may spend observing a FRESH
219
- * foreign lock held by a live pid. Equal to the shared update-lock contract's own
220
- * staleness window ({@link UPDATE_LOCK_STALE_MS} — "no healthy npm install -g of
221
- * this package runs 10 minutes"), so the wait trusts a live cooperating writer for
222
- * exactly as long as the contract legitimises holding the lock, and never longer.
223
- * Overridable by the seam (env HQ_INSTALL_SETTLE_LOCK_TIMEOUT_MS).
224
- */
225
- export declare const DEFAULT_INSTALL_SETTLE_LOCK_WAIT_MS: number;
226
217
  export interface WaitForInstallTreeSettledArgs {
227
218
  target: ModuleErrorTarget;
228
219
  /** The running install's package dir (from resolveRunningInstall), or null. */
@@ -276,8 +267,14 @@ export interface WaitForInstallTreeSettledResult {
276
267
  retiredSiblingPresent?: boolean | null;
277
268
  /** A stable partial retired-sibling scan ended the wait without claiming the tree is stale. */
278
269
  retiredSiblingUnverified?: boolean;
270
+ retiredSiblingKind?: RetiredSiblingKind;
271
+ installTargetState?: InstallTargetState;
272
+ updaterPidAlive?: UpdaterPidAlive;
279
273
  }
280
- export declare const DEFAULT_INSTALL_TREE_STALE_PROBE_MS = 1500;
274
+ type RetiredSiblingKind = "npm_hash_retired" | "hq_staging" | "hq_backup" | "other" | "unknown";
275
+ type InstallTargetState = "missing" | "manifest_valid" | "manifest_invalid" | "unreadable" | "unknown";
276
+ type UpdaterPidAlive = "true" | "false" | "unknown";
277
+ type VersionGatePhase = "preflight" | "lock_acquired" | "installer_running" | "verifying" | "rollback" | "complete" | "failed" | "unknown";
281
278
  /**
282
279
  * Poll until the install tree has been continuously READY for `quietMs`, or the
283
280
  * wait exhausts its bounds. READY means: (i) no FRESH update lock held by another
@@ -337,7 +334,7 @@ export interface InstallRewriteSignalArgs {
337
334
  export declare function installRewriteInProgress(args: InstallRewriteSignalArgs): boolean;
338
335
  /** The recovery OUTCOME, which — not the dialect — decides capture. */
339
336
  export type InstallTreeTornOutcome = "guarded" | "unsettled" | "reexec-failed" | "lock-held" | "stale_tree" | "retired_unverified";
340
- export type InstallTreeState = "in_flight" | "stale";
337
+ type InstallTreeState = "in_flight" | "stale";
341
338
  export type InstallTreeTornDiagnostics = {
342
339
  dialect: ModuleErrorDialect;
343
340
  code: ModuleNotFoundCode;
@@ -362,6 +359,10 @@ export type InstallTreeTornDiagnostics = {
362
359
  retiredSiblingPresent?: boolean;
363
360
  /** The thrown error's `name` for the eval-throw dialect (HQ-CLI-1T), else "". */
364
361
  errorName: string;
362
+ retiredSiblingKind: RetiredSiblingKind;
363
+ installTargetState: InstallTargetState;
364
+ versionGatePhase: VersionGatePhase;
365
+ updaterPidAlive: UpdaterPidAlive;
365
366
  };
366
367
  export interface InstallTreeTornInit {
367
368
  /** The original loader error, carried unchanged as `cause`. */
@@ -383,6 +384,10 @@ export interface InstallTreeTornInit {
383
384
  lockTool?: string;
384
385
  /** Final retired sibling presence, or null when the scope directory was unreadable. */
385
386
  retiredSiblingPresent?: boolean | null;
387
+ retiredSiblingKind?: RetiredSiblingKind;
388
+ installTargetState?: InstallTargetState;
389
+ versionGatePhase?: VersionGatePhase;
390
+ updaterPidAlive?: UpdaterPidAlive;
386
391
  }
387
392
  /**
388
393
  * A torn-install failure that stays VISIBLE in Sentry with bounded, hq-derived
@@ -431,4 +436,5 @@ export declare const INSTALL_TREE_LOCK_HELD_REMEDY: string;
431
436
  * {@link INSTALL_TREE_TORN_REMEDY} byte-for-byte.
432
437
  */
433
438
  export declare function installTreeTornStderrLine(err: InstallTreeTornError): string;
439
+ export {};
434
440
  //# sourceMappingURL=install-tree-torn.d.ts.map