@indigoai-us/hq-cli 5.303.0 → 5.305.0

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 (42) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/command-catalog.generated.d.ts +1 -1
  3. package/dist/command-catalog.generated.js +3 -1
  4. package/dist/command-registration-plan.js +8 -0
  5. package/dist/commands/lanes.d.ts +2 -0
  6. package/dist/commands/lanes.js +34 -6
  7. package/dist/commands/mcp-status.js +1 -0
  8. package/dist/commands/members.js +0 -1
  9. package/dist/commands/people.d.ts +3 -0
  10. package/dist/commands/people.js +27 -3
  11. package/dist/index.js +6 -1
  12. package/dist/lazy-commands.js +5 -2
  13. package/dist/lib/aws-sdk-node-warning-output.d.ts +12 -0
  14. package/dist/lib/aws-sdk-node-warning-output.js +22 -0
  15. package/dist/lib/company-errors-sdk-warning-flag.d.ts +5 -0
  16. package/dist/lib/company-errors-sdk-warning-flag.js +8 -0
  17. package/dist/lib/doctor/checks/work-context.js +2 -2
  18. package/dist/lib/doctor/deep/executor.d.ts +4 -10
  19. package/dist/lib/doctor/deep/executor.js +1 -1
  20. package/dist/lib/doctor/deep/parity.d.ts +2 -29
  21. package/dist/lib/doctor/deep/parity.js +7 -7
  22. package/dist/lib/doctor/deep/sandbox.d.ts +7 -25
  23. package/dist/lib/doctor/deep/sandbox.js +4 -4
  24. package/dist/lib/lanes/keep-alive.js +13 -2
  25. package/dist/lib/mesh/live/daemon/doctor.js +2 -2
  26. package/dist/lib/mesh/live/flush.d.ts +2 -2
  27. package/dist/lib/mesh/live/flush.js +49 -29
  28. package/dist/lib/mesh/live/spool.d.ts +6 -0
  29. package/dist/lib/mesh/live/spool.js +203 -4
  30. package/dist/lib/work-context/bind-best.js +13 -1
  31. package/dist/main.js +16 -3
  32. package/dist/utils/self-update.d.ts +4 -0
  33. package/dist/utils/self-update.js +46 -9
  34. package/dist/utils/version-check.d.ts +7 -0
  35. package/dist/utils/version-check.js +30 -1
  36. package/dist/utils/version-gate.d.ts +28 -10
  37. package/dist/utils/version-gate.js +159 -29
  38. package/dist/utils/version-report.d.ts +2 -1
  39. package/dist/utils/version-report.js +8 -1
  40. package/package.json +1 -1
  41. package/dist/lib/work-context/index.d.ts +0 -26
  42. package/dist/lib/work-context/index.js +0 -22
package/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.305.0] — 2026-10-01
6
+
7
+ - Work Mesh project discovery skips projects whose matching local lifecycle state is archived or retired.
8
+
9
+ - `hq lanes show` now treats a newer terminal primary mirror as authoritative when an Outpost owner snapshot is behind, avoiding a misleading refresh warning while preserving warnings for nonterminal conflicts.
10
+ - Self-updates detect an unwritable npm global prefix before install, show the command to repair that install, and report the handled permission state as a rate-limited warning.
11
+ - Keep Work Mesh held events unique by event ID across retries, including interrupted overflow recovery.
12
+ - Added `hq mcp list` as an alias for the existing MCP status command. `hq version` can show cached CLI update guidance on stderr when the default-off `cli.version-update-nudge` flag is enabled. Bare `hq --version` prints only the installed CLI semver and starts no flag or network work.
13
+ - Keep-alive no longer lets a newer terminal lane or a same-profile lane under a distinct lane senior supersede a running lane.
14
+ - With `cli.company-errors-sdk-warning` enabled, `hq people` uses shared active-company guidance when local metadata is missing, and files commands show the AWS SDK Node-version notice only with verbose diagnostics.
15
+ - Remove the unrelated secret-sharing hint from active member listings.
16
+
17
+ ## [5.304.0] — 2026-10-01
18
+ - `hq lanes show` skips owner refresh only when a failed Outpost dispatch explicitly recorded `pickup_persisted: false` and no owner heartbeat; it reports `remote_refresh: "skipped_undispatched"` in that case.
19
+
5
20
  ## [5.303.0] — 2026-10-01
6
21
  - Fixed bundled shell scripts failing on Windows when Git Bash is installed but `bash` is not on `PATH`.
7
22
  - The bundled token usage script now reads Claude sessions from `CLAUDE_CONFIG_DIR/projects` and the standard Claude project directories, including nested session folders (subagent transcripts are skipped), when no project directory is given.
@@ -3622,7 +3622,7 @@ export declare const COMMAND_CATALOG: readonly [{
3622
3622
  readonly subcommands: readonly [{
3623
3623
  readonly name: "status";
3624
3624
  readonly description: "Show installed MCP packs/servers and their health in BOTH Claude and Codex (PARTIAL/DRIFT flagged; secrets redacted)";
3625
- readonly aliases: readonly [];
3625
+ readonly aliases: readonly ["list"];
3626
3626
  readonly hidden: false;
3627
3627
  readonly usage: "[options]";
3628
3628
  readonly arguments: readonly [];
@@ -4674,7 +4674,9 @@ export const COMMAND_CATALOG = [
4674
4674
  {
4675
4675
  "name": "status",
4676
4676
  "description": "Show installed MCP packs/servers and their health in BOTH Claude and Codex (PARTIAL/DRIFT flagged; secrets redacted)",
4677
- "aliases": [],
4677
+ "aliases": [
4678
+ "list"
4679
+ ],
4678
4680
  "hidden": false,
4679
4681
  "usage": "[options]",
4680
4682
  "arguments": [],
@@ -85,6 +85,7 @@ export const REGISTRATION_PLAN = [
85
85
  ];
86
86
  async function executePlan(program, steps) {
87
87
  const parents = new Map([["program", program]]);
88
+ let filesRuntimeConfigured = false;
88
89
  for (const step of steps) {
89
90
  if (step.type === "group") {
90
91
  const group = program.command(step.name, step.hidden ? { hidden: true } : {});
@@ -94,6 +95,13 @@ async function executePlan(program, steps) {
94
95
  const parent = parents.get(step.parent);
95
96
  if (!parent)
96
97
  throw new Error(`Missing command parent '${step.parent}' for '${step.exportName}'`);
98
+ if (step.root === "files" && !filesRuntimeConfigured) {
99
+ // The SDK emits its Node support notice during module evaluation. Set
100
+ // its narrow suppression switch before loading any files command module.
101
+ const { configureAwsSdkNodeVersionWarningOutput } = await import("./lib/aws-sdk-node-warning-output.js");
102
+ configureAwsSdkNodeVersionWarningOutput();
103
+ filesRuntimeConfigured = true;
104
+ }
97
105
  const imported = await import(step.module);
98
106
  const register = imported[step.exportName];
99
107
  if (!register)
@@ -132,6 +132,8 @@ export declare function parseMaxRuntimeSeconds(raw: unknown, workerId: string):
132
132
  export declare const PICKUP_TERMINAL_REASONS: readonly ["account_not_logged_in", "unknown_account", "account_disabled", "model_unsupported"];
133
133
  export declare const DISPATCH_TERMINAL_REASON: "outpost_dispatch_failed";
134
134
  export type PickupTerminalReason = (typeof PICKUP_TERMINAL_REASONS)[number];
135
+ /** Only explicit non-persistence evidence can prove a failed dispatch has no owner snapshot. */
136
+ export declare function isUndispatchedOutpostMirror(lane: LaneRecord): boolean;
135
137
  /**
136
138
  * The CAS updater a pickup failure applies. A lane that is already terminal
137
139
  * for any reason (a cancel that landed after the caller's last read, an
@@ -1284,9 +1284,7 @@ async function refreshRemoteLaneMirrors(ctx, hqRoot, records, parentLaneIds, opt
1284
1284
  ((parentLaneIds === undefined || (lane.senior.kind === "lane" &&
1285
1285
  lane.senior.id !== undefined &&
1286
1286
  parentLaneIds.has(lane.senior.id))) || options.laneIds?.has(lane.lane_id) === true) &&
1287
- !(isTerminalLaneState(lane.state) &&
1288
- lane.terminal_reason === DISPATCH_TERMINAL_REASON &&
1289
- lane.last_host_report_at === undefined) &&
1287
+ !isUndispatchedOutpostMirror(lane) &&
1290
1288
  (options.includeTerminalMirrors === true || !isTerminalLaneState(lane.state)))
1291
1289
  .sort((a, b) => {
1292
1290
  const terminalOrder = Number(isTerminalLaneState(a.state)) - Number(isTerminalLaneState(b.state));
@@ -2524,6 +2522,14 @@ export const PICKUP_TERMINAL_REASONS = [
2524
2522
  "model_unsupported",
2525
2523
  ];
2526
2524
  export const DISPATCH_TERMINAL_REASON = "outpost_dispatch_failed";
2525
+ /** Only explicit non-persistence evidence can prove a failed dispatch has no owner snapshot. */
2526
+ export function isUndispatchedOutpostMirror(lane) {
2527
+ return lane.host.kind === "outpost" &&
2528
+ isTerminalLaneState(lane.state) &&
2529
+ lane.terminal_reason === DISPATCH_TERMINAL_REASON &&
2530
+ lane.terminal_details?.pickup_persisted === false &&
2531
+ lane.last_host_report_at == null;
2532
+ }
2527
2533
  function parsePickupTerminalReason(value) {
2528
2534
  if (PICKUP_TERMINAL_REASONS.includes(value)) {
2529
2535
  return value;
@@ -3647,6 +3653,9 @@ async function dispatchCreatedOutpostLane(ctx, input) {
3647
3653
  command_id: dispatched.commandId,
3648
3654
  exit_code: dispatched.exitCode,
3649
3655
  status: dispatched.status,
3656
+ ...(remote?.pickup_persisted === false || ownerError.details.pickup_persisted === false
3657
+ ? { pickup_persisted: false }
3658
+ : {}),
3650
3659
  owner_error: ownerError,
3651
3660
  });
3652
3661
  await emitLaneTerminalStateSoft(ctx, failed);
@@ -5038,13 +5047,17 @@ async function runOutpostIdentityBackfillTarget(ctx, opts) {
5038
5047
  }
5039
5048
  async function refreshOutpostLaneCopiesForShow(ctx, lane, localLanes) {
5040
5049
  if (lane.host.kind !== "outpost" || laneRunsHere(lane, reconcileHostFromCtx(ctx))) {
5041
- return lane;
5050
+ return { lane };
5051
+ }
5052
+ if (isUndispatchedOutpostMirror(lane)) {
5053
+ return { lane, remoteRefresh: "skipped_undispatched" };
5042
5054
  }
5043
5055
  const outpostId = lane.host.id;
5044
5056
  const descendantIds = localLanes
5045
5057
  .filter((candidate) => candidate.lane_id !== lane.lane_id &&
5046
5058
  candidate.host.kind === "outpost" && candidate.host.id === outpostId &&
5047
5059
  walkHitsLane(ctx.hqRoot(), candidate.senior, lane.lane_id, ctx))
5060
+ .filter((candidate) => !isUndispatchedOutpostMirror(candidate))
5048
5061
  .map((candidate) => candidate.lane_id);
5049
5062
  const refresh = async (laneId) => {
5050
5063
  try {
@@ -5052,6 +5065,19 @@ async function refreshOutpostLaneCopiesForShow(ctx, lane, localLanes) {
5052
5065
  return syncLaneRecordFromOwner(ctx.hqRoot(), laneId, outpostId, ownerLane, undefined, { allowNonTerminal: true });
5053
5066
  }
5054
5067
  catch (err) {
5068
+ if (isLanesError(err) && err.error === "outpost_lane_sync_conflict") {
5069
+ const ownerVersion = err.details.owner_version;
5070
+ const primaryVersion = err.details.primary_version;
5071
+ if (typeof ownerVersion === "number" &&
5072
+ typeof primaryVersion === "number" &&
5073
+ ownerVersion < primaryVersion) {
5074
+ const currentPrimary = readLane(ctx.hqRoot(), laneId);
5075
+ if (currentPrimary.version === primaryVersion &&
5076
+ isTerminalLaneState(currentPrimary.state)) {
5077
+ return currentPrimary;
5078
+ }
5079
+ }
5080
+ }
5055
5081
  const detail = isLanesError(err)
5056
5082
  ? `${err.error}: ${err.message}`
5057
5083
  : `outpost_lane_sync_unavailable: ${dispatchErrorMessage(err)}`;
@@ -5061,13 +5087,14 @@ async function refreshOutpostLaneCopiesForShow(ctx, lane, localLanes) {
5061
5087
  };
5062
5088
  const refreshed = await mapWithConcurrency([lane.lane_id, ...descendantIds], OUTPOST_HIRE_SUMMARY_CONCURRENCY, refresh);
5063
5089
  const refreshedLane = refreshed[0] ?? null;
5064
- return refreshedLane ?? lane;
5090
+ return { lane: refreshedLane ?? lane };
5065
5091
  }
5066
5092
  async function runShow(ctx, laneId, hasPendingQuestionForLane) {
5067
5093
  const hqRoot = ctx.hqRoot();
5068
5094
  const initialLane = readLane(hqRoot, laneId);
5069
5095
  const initialLanes = loadAllLanes(hqRoot);
5070
- const storedLane = await refreshOutpostLaneCopiesForShow(ctx, initialLane, initialLanes);
5096
+ const showRefresh = await refreshOutpostLaneCopiesForShow(ctx, initialLane, initialLanes);
5097
+ const storedLane = showRefresh.lane;
5071
5098
  const allLanes = loadAllLanes(hqRoot);
5072
5099
  const hire = await laneHirePresentation(ctx, storedLane, allLanes);
5073
5100
  const remoteQueued = storedLane.state === "queued" &&
@@ -5152,6 +5179,7 @@ async function runShow(ctx, laneId, hasPendingQuestionForLane) {
5152
5179
  stalled_reason: lane.stalled_reason ?? null,
5153
5180
  ask_delivery_failed: askDeliveryFailed,
5154
5181
  delivery,
5182
+ ...(showRefresh.remoteRefresh === undefined ? {} : { remote_refresh: showRefresh.remoteRefresh }),
5155
5183
  provider_session_id: lane.provider_session_id ?? null,
5156
5184
  provider_session_id_absent: lane.provider_session_id_absent ?? null,
5157
5185
  envelope_repair_mode: lane.envelope_repair?.mode ?? null,
@@ -374,6 +374,7 @@ export function registerMcpCommand(program) {
374
374
  .description('MCP pack observability (read-only) across Claude + Codex');
375
375
  mcp
376
376
  .command('status')
377
+ .alias('list')
377
378
  .description('Show installed MCP packs/servers and their health in BOTH Claude and Codex (PARTIAL/DRIFT flagged; secrets redacted)')
378
379
  .option('--json', 'Emit the structured report as JSON (for CI / scripting)')
379
380
  .action((opts) => {
@@ -672,7 +672,6 @@ export function registerMembersCommand(program) {
672
672
  const name = m.personName ?? m.personSlug ?? "";
673
673
  console.log([email.padEnd(emailW), m.role.padEnd(roleW), name].join(" "));
674
674
  }
675
- console.log(chalk.gray("Share a secret with a member: hq secrets share <path> --with <email>"));
676
675
  }
677
676
  catch (err) {
678
677
  if (err instanceof InviteHttpError) {
@@ -17,6 +17,9 @@ import { resolveNameToEmail, type PersonRecord } from "../utils/people.js";
17
17
  export type FetchPeopleRoster = (hqRoot: string, companySlug: string) => Promise<PersonRecord[]>;
18
18
  interface PeopleCommandDeps {
19
19
  fetchRoster?: FetchPeopleRoster;
20
+ /** Test seam for the shared active-membership ambiguity resolver. */
21
+ resolveMissingManifestMemberships?: () => Promise<void>;
22
+ companySelectionGuidanceEnabled?: () => boolean;
20
23
  }
21
24
  interface PeopleLookupOpts {
22
25
  localOnly?: boolean;
@@ -19,6 +19,7 @@ import { findHqRoot } from "../utils/manifest.js";
19
19
  import { manifestPath } from "./cloud-provision.js";
20
20
  import { ensureCognitoToken } from "../utils/cognito-session.js";
21
21
  import { getCompanyUid } from "../utils/vault-api.js";
22
+ import { companyErrorsSdkWarningEnabled } from "../lib/company-errors-sdk-warning-flag.js";
22
23
  import { listActiveMembers } from "./members.js";
23
24
  import { assertSafeCompanySlug, listCompanyPeople, searchPeople, resolveNameToEmail, companyPeopleDir, } from "../utils/people.js";
24
25
  function slugify(value) {
@@ -108,6 +109,29 @@ export function resolveCompanySlug(hqRoot, explicit) {
108
109
  throw new Error("Multiple companies found — re-run with --company <slug> to pick one:\n" +
109
110
  slugs.map((s) => ` --company ${s}`).join("\n"));
110
111
  }
112
+ async function resolvePeopleCompanySlug(hqRoot, explicit, localOnly, deps) {
113
+ try {
114
+ return resolveCompanySlug(hqRoot, explicit);
115
+ }
116
+ catch (error) {
117
+ const message = error instanceof Error ? error.message : String(error);
118
+ const ambiguous = message.includes("companies/manifest.yaml not found") ||
119
+ message.startsWith("Multiple companies found");
120
+ const enabled = (deps.companySelectionGuidanceEnabled ?? companyErrorsSdkWarningEnabled)();
121
+ if (!explicit && !localOnly && enabled && ambiguous) {
122
+ const resolveMemberships = deps.resolveMissingManifestMemberships ??
123
+ (async () => {
124
+ const token = await ensureCognitoToken();
125
+ await getCompanyUid(token, undefined);
126
+ });
127
+ // The shared resolver throws members-style guidance for multiple active
128
+ // companies. A single membership cannot provide a local slug without a
129
+ // manifest, so preserve the existing missing-manifest error in that case.
130
+ await resolveMemberships();
131
+ }
132
+ throw error;
133
+ }
134
+ }
111
135
  /** Resolve the HQ root: explicit override (tests) → cwd walk-up. */
112
136
  function resolveHqRoot(opts) {
113
137
  return opts.hqRoot ?? findHqRoot();
@@ -192,7 +216,7 @@ export function registerPeopleCommand(program, deps = {}) {
192
216
  try {
193
217
  const scope = people.opts();
194
218
  const hqRoot = resolveHqRoot(scope);
195
- const slug = resolveCompanySlug(hqRoot, scope.company);
219
+ const slug = await resolvePeopleCompanySlug(hqRoot, scope.company, opts.localOnly, deps);
196
220
  let records = listCompanyPeople(hqRoot, slug);
197
221
  if (!opts.localOnly) {
198
222
  const roster = await tryFetchRoster(deps.fetchRoster ?? fetchMembershipRoster, hqRoot, slug);
@@ -223,7 +247,7 @@ export function registerPeopleCommand(program, deps = {}) {
223
247
  try {
224
248
  const scope = people.opts();
225
249
  const hqRoot = resolveHqRoot(scope);
226
- const slug = resolveCompanySlug(hqRoot, scope.company);
250
+ const slug = await resolvePeopleCompanySlug(hqRoot, scope.company, opts.localOnly, deps);
227
251
  const matches = await searchPeopleWithRosterFallback({
228
252
  hqRoot,
229
253
  slug,
@@ -255,7 +279,7 @@ export function registerPeopleCommand(program, deps = {}) {
255
279
  try {
256
280
  const scope = people.opts();
257
281
  const hqRoot = resolveHqRoot(scope);
258
- const slug = resolveCompanySlug(hqRoot, scope.company);
282
+ const slug = await resolvePeopleCompanySlug(hqRoot, scope.company, opts.localOnly, deps);
259
283
  const result = await resolvePersonWithRosterFallback({
260
284
  hqRoot,
261
285
  slug,
package/dist/index.js CHANGED
@@ -22,9 +22,14 @@ if (isVersionRequest(process.argv)) {
22
22
  // compare). `hq version` and `--json` print the labelled HQ/CLI report.
23
23
  // Lazy so this path still skips the command graph.
24
24
  if (wantsLabelledVersionReport(process.argv)) {
25
- void import("./utils/version-report.js").then(({ runVersionCommand }) => runVersionCommand(process.argv));
25
+ void import("./lib/flag-registry.js").then(({ kickFlagRegistryReadiness }) => {
26
+ kickFlagRegistryReadiness();
27
+ return import("./utils/version-report.js").then(({ runVersionCommand }) => runVersionCommand(process.argv));
28
+ });
26
29
  }
27
30
  else {
31
+ // Keep the benchmarked updater fast route limited to the installed semver.
32
+ // Registry checks and flag resolution belong to the regular command path.
28
33
  void import("./cli-version.js").then(({ CLI_VERSION }) => {
29
34
  process.stdout.write(`${CLI_VERSION}\n`);
30
35
  });
@@ -55,8 +55,11 @@ function commandForToken(token) {
55
55
  * preserve the complete help and unknown-command recovery surfaces.
56
56
  */
57
57
  export function findLazyCommand(argv) {
58
- const first = argv[2];
59
- const token = first === "help" ? argv[3] : first;
58
+ let commandIndex = 2;
59
+ while (argv[commandIndex] === "--verbose")
60
+ commandIndex += 1;
61
+ const first = argv[commandIndex];
62
+ const token = first === "help" ? argv[commandIndex + 1] : first;
60
63
  if (typeof token !== "string" || token.startsWith("-"))
61
64
  return null;
62
65
  const command = commandForToken(token);
@@ -0,0 +1,12 @@
1
+ export declare const AWS_SDK_NODE_VERSION_WARNING_ENV = "AWS_SDK_JS_NODE_VERSION_SUPPORT_WARNING_DISABLED";
2
+ export interface AwsSdkWarningOutputOptions {
3
+ argv?: readonly string[];
4
+ env?: NodeJS.ProcessEnv;
5
+ enabled?: boolean;
6
+ }
7
+ /**
8
+ * Configure the AWS SDK's documented, warning-specific switch before loading
9
+ * the files command and its SDK clients. No other SDK warnings are affected.
10
+ */
11
+ export declare function configureAwsSdkNodeVersionWarningOutput(options?: AwsSdkWarningOutputOptions): void;
12
+ //# sourceMappingURL=aws-sdk-node-warning-output.d.ts.map
@@ -0,0 +1,22 @@
1
+ import { companyErrorsSdkWarningEnabled } from "./company-errors-sdk-warning-flag.js";
2
+ export const AWS_SDK_NODE_VERSION_WARNING_ENV = "AWS_SDK_JS_NODE_VERSION_SUPPORT_WARNING_DISABLED";
3
+ /**
4
+ * Configure the AWS SDK's documented, warning-specific switch before loading
5
+ * the files command and its SDK clients. No other SDK warnings are affected.
6
+ */
7
+ export function configureAwsSdkNodeVersionWarningOutput(options = {}) {
8
+ const env = options.env ?? process.env;
9
+ const argv = options.argv ?? process.argv;
10
+ const enabled = options.enabled ?? companyErrorsSdkWarningEnabled();
11
+ if (!enabled)
12
+ return;
13
+ const verbose = argv.includes("--verbose");
14
+ const debug = /^(1|true|yes)$/i.test(env.HQ_DEBUG?.trim() ?? "");
15
+ if (verbose || debug) {
16
+ delete env[AWS_SDK_NODE_VERSION_WARNING_ENV];
17
+ }
18
+ else {
19
+ env[AWS_SDK_NODE_VERSION_WARNING_ENV] = "true";
20
+ }
21
+ }
22
+ //# sourceMappingURL=aws-sdk-node-warning-output.js.map
@@ -0,0 +1,5 @@
1
+ export declare const COMPANY_ERRORS_SDK_WARNING_FLAG = "cli.company-errors-sdk-warning";
2
+ export declare const COMPANY_ERRORS_SDK_WARNING_FALLBACK = false;
3
+ /** One default-off rollout gate for the two US-163 CLI compatibility fixes. */
4
+ export declare function companyErrorsSdkWarningEnabled(): boolean;
5
+ //# sourceMappingURL=company-errors-sdk-warning-flag.d.ts.map
@@ -0,0 +1,8 @@
1
+ import { resolveProcessFlagGate } from "./flag-registry.js";
2
+ export const COMPANY_ERRORS_SDK_WARNING_FLAG = "cli.company-errors-sdk-warning";
3
+ export const COMPANY_ERRORS_SDK_WARNING_FALLBACK = false;
4
+ /** One default-off rollout gate for the two US-163 CLI compatibility fixes. */
5
+ export function companyErrorsSdkWarningEnabled() {
6
+ return resolveProcessFlagGate(COMPANY_ERRORS_SDK_WARNING_FLAG, {}, () => COMPANY_ERRORS_SDK_WARNING_FALLBACK);
7
+ }
8
+ //# sourceMappingURL=company-errors-sdk-warning-flag.js.map
@@ -10,7 +10,7 @@ import { readDeviceConfig, } from "../../work-context/config.js";
10
10
  import { outboxStats, listOutboxOperations } from "../../work-context/outbox.js";
11
11
  import { outboxQuarantineStatusEnabled } from "../../work-context/outbox-quarantine-status-flag.js";
12
12
  import { workContextRoot, workContextSessionsDir } from "../../work-context/paths.js";
13
- import { countJsonlLines, deadLetterNonEmpty, } from "../../mesh/live/spool.js";
13
+ import { countDistinctHeldEvents, countJsonlLines, deadLetterNonEmpty, } from "../../mesh/live/spool.js";
14
14
  import { workMeshDeadLetterPath, workMeshHeldPath, workMeshRoot, workMeshSpoolPath, } from "../../mesh/live/paths.js";
15
15
  import { collectDaemonDoctor, formatDaemonDoctor, } from "../../mesh/live/daemon/doctor.js";
16
16
  export const WORK_CONTEXT_FAMILY_ID = "work-context";
@@ -139,7 +139,7 @@ function runChecks(deps) {
139
139
  const heldPath = workMeshHeldPath(meshRoot);
140
140
  const deadLetterPath = workMeshDeadLetterPath(meshRoot);
141
141
  const spoolDepth = countJsonlLines(spoolPath);
142
- const heldDepth = countJsonlLines(heldPath);
142
+ const heldDepth = countDistinctHeldEvents(heldPath);
143
143
  results.push({
144
144
  status: "PASS",
145
145
  checkId: "work-context.spool-depth",
@@ -55,7 +55,7 @@ export declare const DEFAULT_PER_CASE_TIMEOUT_MS = 10000;
55
55
  */
56
56
  export declare const SANDBOX_COPY_RELPATHS: readonly string[];
57
57
  /** One gate execution's inputs. */
58
- export interface GateRunInput {
58
+ interface GateRunInput {
59
59
  /** Absolute path to the sandboxed `hook-gate.sh`. */
60
60
  gatePath: string;
61
61
  /** Absolute path to the sandboxed hook script the gate delegates to. */
@@ -72,7 +72,7 @@ export interface GateRunInput {
72
72
  timeoutMs: number;
73
73
  }
74
74
  /** One gate execution's observed outcome. */
75
- export interface GateRunResult {
75
+ interface GateRunResult {
76
76
  /** True when the execution exceeded {@link GateRunInput.timeoutMs}. */
77
77
  timedOut: boolean;
78
78
  /** Gate exit code, or null when it did not exit normally (timeout/signal). */
@@ -81,14 +81,7 @@ export interface GateRunResult {
81
81
  stderr: string;
82
82
  }
83
83
  /** Executes one gate invocation. Injectable so the aggregation is unit-testable. */
84
- export type GateRunner = (input: GateRunInput) => GateRunResult;
85
- /**
86
- * The real runner: spawn `bash hook-gate.sh <id> <script>` with the payload on
87
- * stdin, `HQ_HOOK_PROFILE` set, and a hard timeout. A timeout is detected by the
88
- * `ETIMEDOUT` error code spawnSync reports; the process is killed with SIGKILL so
89
- * a hook cannot ignore the bound.
90
- */
91
- export declare const defaultGateRunner: GateRunner;
84
+ type GateRunner = (input: GateRunInput) => GateRunResult;
92
85
  /** Options for {@link runDeepGuardTests}. All are injectable for testing. */
93
86
  export interface DeepTestOptions {
94
87
  /** Per-case time bound. Default: {@link DEFAULT_PER_CASE_TIMEOUT_MS}. */
@@ -109,4 +102,5 @@ export declare function cleanupAllDeepSandboxes(): void;
109
102
  * an empty list — creating no sandbox — when there is nothing to run.
110
103
  */
111
104
  export declare function runDeepGuardTests(context: CheckContext, options?: DeepTestOptions): Promise<CheckResult[]>;
105
+ export {};
112
106
  //# sourceMappingURL=executor.d.ts.map
@@ -74,7 +74,7 @@ export const SANDBOX_COPY_RELPATHS = [
74
74
  * `ETIMEDOUT` error code spawnSync reports; the process is killed with SIGKILL so
75
75
  * a hook cannot ignore the bound.
76
76
  */
77
- export const defaultGateRunner = (input) => {
77
+ const defaultGateRunner = (input) => {
78
78
  const result = spawnSync("bash", [input.gatePath, input.hookId, input.hookScriptPath], {
79
79
  input: input.payload,
80
80
  cwd: input.cwd,
@@ -46,14 +46,6 @@ import { type PlatformId } from "../payload-shapes.js";
46
46
  export declare const PARITY_FAMILY_ID = "deep-parity";
47
47
  /** Human title of the parity family. */
48
48
  export declare const PARITY_FAMILY_TITLE = "Cross-platform parity replay";
49
- /** Default per-case, per-platform time bound. */
50
- export declare const DEFAULT_PARITY_TIMEOUT_MS = 10000;
51
- /** The gate profile the replay runs each hook under. Strict is the broadest
52
- * allowlist, so profile gating never suppresses the hook whose LOGIC is being
53
- * compared across platforms — profile-specific behaviour is US-008's concern. */
54
- export declare const PARITY_GATE_PROFILE = "strict";
55
- /** The session id stamped onto every replay payload. */
56
- export declare const PARITY_SESSION_ID = "hq-doctor-parity-replay";
57
49
  /** One platform replay's inputs. */
58
50
  export interface PlatformRunInput {
59
51
  /** Which platform's adapter path to exercise. */
@@ -85,27 +77,7 @@ export interface PlatformRunOutput {
85
77
  /** Executes one platform replay. Injectable so the comparison is unit-testable. */
86
78
  export type PlatformRunner = (input: PlatformRunInput) => PlatformRunOutput;
87
79
  /** The real runner set, keyed by platform. */
88
- export type PlatformRunners = Record<PlatformId, PlatformRunner>;
89
- /** The real Claude runner: the canonical script through the Claude gate. */
90
- export declare const defaultClaudeRunner: PlatformRunner;
91
- /** The real Codex runner: the duplicated mirror through the Codex gate. */
92
- export declare const defaultCodexRunner: PlatformRunner;
93
- /**
94
- * The real Grok runner. Grok shares the canonical `.claude/hooks/` scripts with
95
- * Claude — it has no mirror of its own — and its adapter's whole job is to read
96
- * the camelCase payload, map the tool alias back to canonical, build the Claude
97
- * JSON, and pipe it to the same `hook-gate.sh`. We reproduce that routing here
98
- * (via {@link toGrokPayload} + {@link grokToSnakePayload}) rather than spawn the
99
- * adapter directly, for two reasons: the live adapter runs a whole tool
100
- * *sequence* where the replay needs one isolated hook, and its user-global
101
- * bridge cannot be simulated from a project-local run (US-005 keeps bridge
102
- * presence a wiring check). The Grok block protocol still applies — the gate's
103
- * non-zero exit is what the adapter would translate into a stdout `deny`
104
- * ({@link interpretGrokBlock} in verdictFor recognises both).
105
- */
106
- export declare const defaultGrokRunner: PlatformRunner;
107
- /** The default real runner set wired to each platform's real adapter path. */
108
- export declare const defaultPlatformRunners: PlatformRunners;
80
+ type PlatformRunners = Record<PlatformId, PlatformRunner>;
109
81
  /** Options for {@link runParityReplay}. All injectable for testing. */
110
82
  export interface ParityOptions {
111
83
  /** Per-case, per-platform time bound. Default: {@link DEFAULT_PARITY_TIMEOUT_MS}. */
@@ -126,4 +98,5 @@ export declare function cleanupAllParitySandboxes(): void;
126
98
  * empty list — creating no sandbox — when there is nothing to replay.
127
99
  */
128
100
  export declare function runParityReplay(context: CheckContext, options?: ParityOptions): Promise<CheckResult[]>;
101
+ export {};
129
102
  //# sourceMappingURL=parity.d.ts.map
@@ -52,13 +52,13 @@ export const PARITY_FAMILY_ID = "deep-parity";
52
52
  /** Human title of the parity family. */
53
53
  export const PARITY_FAMILY_TITLE = "Cross-platform parity replay";
54
54
  /** Default per-case, per-platform time bound. */
55
- export const DEFAULT_PARITY_TIMEOUT_MS = 10_000;
55
+ const DEFAULT_PARITY_TIMEOUT_MS = 10_000;
56
56
  /** The gate profile the replay runs each hook under. Strict is the broadest
57
57
  * allowlist, so profile gating never suppresses the hook whose LOGIC is being
58
58
  * compared across platforms — profile-specific behaviour is US-008's concern. */
59
- export const PARITY_GATE_PROFILE = "strict";
59
+ const PARITY_GATE_PROFILE = "strict";
60
60
  /** The session id stamped onto every replay payload. */
61
- export const PARITY_SESSION_ID = "hq-doctor-parity-replay";
61
+ const PARITY_SESSION_ID = "hq-doctor-parity-replay";
62
62
  function spawnWithStdin(command, args, stdin, input) {
63
63
  const result = spawnSync(command, args, {
64
64
  input: stdin,
@@ -96,12 +96,12 @@ function runThroughGate(input, platformDir, payload) {
96
96
  return { ...spawned };
97
97
  }
98
98
  /** The real Claude runner: the canonical script through the Claude gate. */
99
- export const defaultClaudeRunner = (input) => runThroughGate(input, ".claude", JSON.stringify(toClaudePayload(input.testCase, {
99
+ const defaultClaudeRunner = (input) => runThroughGate(input, ".claude", JSON.stringify(toClaudePayload(input.testCase, {
100
100
  cwd: input.sandbox,
101
101
  sessionId: PARITY_SESSION_ID,
102
102
  })));
103
103
  /** The real Codex runner: the duplicated mirror through the Codex gate. */
104
- export const defaultCodexRunner = (input) => runThroughGate(input, ".codex", JSON.stringify(toCodexPayload(input.testCase, {
104
+ const defaultCodexRunner = (input) => runThroughGate(input, ".codex", JSON.stringify(toCodexPayload(input.testCase, {
105
105
  cwd: input.sandbox,
106
106
  sessionId: PARITY_SESSION_ID,
107
107
  })));
@@ -118,7 +118,7 @@ export const defaultCodexRunner = (input) => runThroughGate(input, ".codex", JSO
118
118
  * non-zero exit is what the adapter would translate into a stdout `deny`
119
119
  * ({@link interpretGrokBlock} in verdictFor recognises both).
120
120
  */
121
- export const defaultGrokRunner = (input) => {
121
+ const defaultGrokRunner = (input) => {
122
122
  const grokPayload = toGrokPayload(input.testCase, {
123
123
  cwd: input.sandbox,
124
124
  sessionId: PARITY_SESSION_ID,
@@ -127,7 +127,7 @@ export const defaultGrokRunner = (input) => {
127
127
  return runThroughGate(input, ".claude", JSON.stringify(snake));
128
128
  };
129
129
  /** The default real runner set wired to each platform's real adapter path. */
130
- export const defaultPlatformRunners = {
130
+ const defaultPlatformRunners = {
131
131
  claude: defaultClaudeRunner,
132
132
  codex: defaultCodexRunner,
133
133
  grok: defaultGrokRunner,
@@ -46,21 +46,10 @@ export declare const DEFAULT_PER_CASE_TIMEOUT_MS = 15000;
46
46
  * come under sandboxed execution.
47
47
  */
48
48
  export type Precondition = "git-repo" | "session-metadata" | "company-scaffold";
49
- /** Every precondition the default seeder knows how to provide. */
50
- export declare const KNOWN_PRECONDITIONS: readonly Precondition[];
51
- /**
52
- * Tree entries copied from the live tree into every sandbox — the same curated
53
- * set US-008 uses: the hook scripts and gate, the settings a hook may read, the
54
- * Codex/Grok mirrors, and `core/` (helpers hooks source). Missing entries are
55
- * skipped so a partial tree still sandboxes cleanly.
56
- */
57
- export declare const SANDBOX_SEED_RELPATHS: readonly string[];
58
49
  /** Remove every side-effect sandbox still on disk. Safe to call repeatedly. */
59
50
  export declare function cleanupAllSandboxes(): void;
60
51
  /** The sandbox roots this process is still tracking (for tests). */
61
52
  export declare function trackedSandboxRoots(): string[];
62
- /** Remove one sandbox and stop tracking it. Idempotent. */
63
- export declare function destroySandbox(root: string): void;
64
53
  /** The outcome of seeding one sandbox. */
65
54
  export interface SeedResult {
66
55
  /** Absolute, realpath'd sandbox root under the OS temp dir. */
@@ -91,7 +80,7 @@ export interface SeedOptions {
91
80
  */
92
81
  export declare function seedSandbox(hqRoot: string, opts?: SeedOptions): SeedResult;
93
82
  /** One hook execution's inputs. */
94
- export interface HookRunInput {
83
+ interface HookRunInput {
95
84
  /** Absolute path to the sandboxed hook script. */
96
85
  hookScriptPath: string;
97
86
  /** The JSON payload piped to the hook's stdin. */
@@ -104,7 +93,7 @@ export interface HookRunInput {
104
93
  timeoutMs: number;
105
94
  }
106
95
  /** One hook execution's observed result (exit code is diagnostic only). */
107
- export interface HookRunResult {
96
+ interface HookRunResult {
108
97
  /** True when the execution exceeded {@link HookRunInput.timeoutMs}. */
109
98
  timedOut: boolean;
110
99
  /** Exit code, or null when it did not exit normally (timeout/signal). */
@@ -113,17 +102,9 @@ export interface HookRunResult {
113
102
  stderr: string;
114
103
  }
115
104
  /** Runs one hook. Injectable so the tier's aggregation is unit-testable. */
116
- export type HookRunner = (input: HookRunInput) => HookRunResult;
117
- /**
118
- * The real runner: fire the hook script directly with the payload on stdin, its
119
- * cwd and session env pointed at the sandbox, and a hard timeout. Unlike a pure
120
- * guard (US-008), a side-effecting hook is run directly rather than through the
121
- * gate — its exit code is irrelevant here; what matters is the effect it leaves
122
- * on the sandbox, which effects.ts reads afterwards.
123
- */
124
- export declare const defaultHookRunner: HookRunner;
105
+ type HookRunner = (input: HookRunInput) => HookRunResult;
125
106
  /** One parsed side-effecting fixture case (its own shape, not the US-007 schema). */
126
- export interface SideEffectCase {
107
+ interface SideEffectCase {
127
108
  name: string;
128
109
  event: string;
129
110
  tool: string;
@@ -136,13 +117,13 @@ export interface SideEffectCase {
136
117
  expectedFailure?: ExpectedFailure;
137
118
  }
138
119
  /** A validated side-effecting fixture. */
139
- export interface SideEffectFixture {
120
+ interface SideEffectFixture {
140
121
  hookId: string;
141
122
  relpath: string;
142
123
  cases: SideEffectCase[];
143
124
  }
144
125
  /** A side-effecting fixture that could not be parsed. */
145
- export interface SideEffectFixtureError {
126
+ interface SideEffectFixtureError {
146
127
  hookId: string | null;
147
128
  relpath: string;
148
129
  message: string;
@@ -187,4 +168,5 @@ export interface SideEffectTestOptions {
187
168
  * Returns an empty list when there is nothing side-effecting to run.
188
169
  */
189
170
  export declare function runSideEffectTests(context: CheckContext, options?: SideEffectTestOptions): Promise<CheckResult[]>;
171
+ export {};
190
172
  //# sourceMappingURL=sandbox.d.ts.map
@@ -46,7 +46,7 @@ import { captureEffectBaseline, describeEffect, defaultGitProbe, evaluateEffects
46
46
  /** Default per-case time bound. No latency target, but no case may hang. */
47
47
  export const DEFAULT_PER_CASE_TIMEOUT_MS = 15_000;
48
48
  /** Every precondition the default seeder knows how to provide. */
49
- export const KNOWN_PRECONDITIONS = [
49
+ const KNOWN_PRECONDITIONS = [
50
50
  "git-repo",
51
51
  "session-metadata",
52
52
  "company-scaffold",
@@ -57,7 +57,7 @@ export const KNOWN_PRECONDITIONS = [
57
57
  * Codex/Grok mirrors, and `core/` (helpers hooks source). Missing entries are
58
58
  * skipped so a partial tree still sandboxes cleanly.
59
59
  */
60
- export const SANDBOX_SEED_RELPATHS = [
60
+ const SANDBOX_SEED_RELPATHS = [
61
61
  ".claude/hooks",
62
62
  ".claude/settings.json",
63
63
  ".claude/settings.local.json",
@@ -100,7 +100,7 @@ function removeTree(root) {
100
100
  }
101
101
  }
102
102
  /** Remove one sandbox and stop tracking it. Idempotent. */
103
- export function destroySandbox(root) {
103
+ function destroySandbox(root) {
104
104
  removeTree(root);
105
105
  trackedSandboxes.delete(root);
106
106
  }
@@ -198,7 +198,7 @@ function git(root, args) {
198
198
  * gate — its exit code is irrelevant here; what matters is the effect it leaves
199
199
  * on the sandbox, which effects.ts reads afterwards.
200
200
  */
201
- export const defaultHookRunner = (input) => {
201
+ const defaultHookRunner = (input) => {
202
202
  const result = spawnSync("bash", [input.hookScriptPath], {
203
203
  input: input.payload,
204
204
  cwd: input.cwd,