@indigoai-us/hq-cli 5.345.50 → 5.345.52

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 (33) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/commands/core-hq-session-native.js +2 -2
  3. package/dist/commands/core-resolve-company-native.js +2 -2
  4. package/dist/commands/lanes.js +52 -11
  5. package/dist/commands/secrets.js +2 -2
  6. package/dist/commands/workers.js +2 -2
  7. package/dist/hq-cloud-sync-runner/bin/sync-runner.js +40293 -13770
  8. package/dist/hq-cloud-sync-runner/package.json +1 -1
  9. package/dist/lib/bot/daemon.d.ts +1 -1
  10. package/dist/lib/bot/daemon.js +35 -29
  11. package/dist/lib/daemon/install.js +34 -3
  12. package/dist/lib/doctor/checks/bots.js +3 -8
  13. package/dist/lib/flag-registry-worker-source.generated.d.ts +1 -1
  14. package/dist/lib/flag-registry-worker-source.generated.js +1 -1
  15. package/dist/lib/lanes/outpost-dispatch.d.ts +1 -0
  16. package/dist/lib/lanes/outpost-dispatch.js +2 -0
  17. package/dist/lib/mesh/live/daemon/install.js +28 -15
  18. package/dist/lib/service-manager/index.d.ts +3 -0
  19. package/dist/lib/service-manager/index.js +22 -6
  20. package/dist/lib/service-manager/launchd.d.ts +40 -3
  21. package/dist/lib/service-manager/launchd.js +106 -5
  22. package/dist/lib/service-manager/migration-state.d.ts +12 -0
  23. package/dist/lib/service-manager/migration-state.js +46 -0
  24. package/dist/lib/service-manager/migration.d.ts +22 -0
  25. package/dist/lib/service-manager/migration.js +85 -0
  26. package/dist/lib/service-manager/startup-migration.d.ts +24 -0
  27. package/dist/lib/service-manager/startup-migration.js +27 -0
  28. package/dist/lib/service-manager/types.d.ts +3 -0
  29. package/dist/main.js +22 -0
  30. package/dist/native-fast-route.d.ts +4 -0
  31. package/dist/native-fast-route.js +20 -0
  32. package/dist/utils/resident-package-preload.js +2 -1
  33. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.345.52] — 2026-10-08
6
+ - Improves recovery from disk-full sync failures by using the updated hq-cloud rescue staging flow.
7
+
8
+ ## [5.345.51] — 2026-10-08
9
+
10
+ - Multi-company session locking now defaults on across native CLI readers; an explicit false flag value remains the kill switch.
11
+
12
+ - The Codex skill bridge regression suite now checks that the repo `.agents/skills` mirror exposes every skill from the Claude listing source once.
13
+ - `hq lanes message`, `resume` and `grant` now reach an Outpost-hosted lane that has no local record even when the owner's lane store is too large for one hierarchy read. The lane, its senior, its siblings and its children are read in bounded parts instead of the command failing with `lane_not_found`.
14
+ - HQ CLI compares LaunchAgent plists before writing or reloading them, attributes jobs to an installed HQ.app, uses its signed launcher when available, and migrates legacy Node-first agents once.
15
+
5
16
  ## [5.345.50] — 2026-10-08
6
17
  - The lane keep-alive audit now admits every `done` stop envelope and splits the unrestarted ones by keep-alive eligibility: a stop keep-alive is specified not to wake is reported as `finished_story` or `idle_no_queued_work` instead of being counted as a liveness failure. `stopped_and_not_restarted_on_their_own` keeps its name and its value on the stops the audit already reported.
7
18
  - A finished standing lane that receives queued work long after it stopped now gets the normal grace period measured from when that work appeared, so a normal exit from `idle_no_queued_work` is no longer reported as a keep-alive liveness failure.
@@ -781,11 +781,11 @@ export async function runHqSessionFast(argv, _stdin, cwd, hqRoot) {
781
781
  || (commandArgs[0] === "get" && commandArgs[1] === "company_slugs");
782
782
  let enabled = false;
783
783
  if (needsMultiCompanyFlag) {
784
- const [{ fastFlagEnabled }, { MULTI_COMPANY_SESSION_LOCK_FLAG }] = await Promise.all([
784
+ const [{ fastFlagEnabledDefaultOn }, { MULTI_COMPANY_SESSION_LOCK_FLAG }] = await Promise.all([
785
785
  import("../native-fast-route.js"),
786
786
  import("../lib/cli-flag-keys.js"),
787
787
  ]);
788
- enabled = await fastFlagEnabled(MULTI_COMPANY_SESSION_LOCK_FLAG);
788
+ enabled = await fastFlagEnabledDefaultOn(MULTI_COMPANY_SESSION_LOCK_FLAG);
789
789
  }
790
790
  const result = executeHqSession(argv, { cwd, hqRoot }, { multiCompanyLockEnabled: enabled });
791
791
  if (result.stdout)
@@ -4,7 +4,7 @@ import * as fs from "node:fs";
4
4
  import * as path from "node:path";
5
5
  import { awkCannotOpenFileDiagnostic } from "../lib/core-utils/awk-diagnostics.js";
6
6
  import { buildCmdExeSpawnPlan, isWindowsBatchFile } from "../utils/windows-spawn.js";
7
- import { fastFlagEnabled } from "../native-fast-route.js";
7
+ import { fastFlagEnabledDefaultOn } from "../native-fast-route.js";
8
8
  export const RESOLVE_COMPANY_ASSET = "core/scripts/resolve-company.sh";
9
9
  export const RESOLVE_COMPANY_HELP = [
10
10
  "hq-core: public",
@@ -603,7 +603,7 @@ export async function runResolveCompanyFast(args, stdin, cwd, hqRoot, _commandNa
603
603
  hqRoot,
604
604
  stdin: actualStdin,
605
605
  stdinIsTty: process.stdin.isTTY === true,
606
- multiCompanyLockEnabled: await fastFlagEnabled("hooks.multi-company-session-lock"),
606
+ multiCompanyLockEnabled: await fastFlagEnabledDefaultOn("hooks.multi-company-session-lock"),
607
607
  });
608
608
  process.stdout.write(result.stdout);
609
609
  if (result.stderr.length)
@@ -947,6 +947,7 @@ function laneListQueryFlags(query) {
947
947
  ...(query.laneUlids?.length ? ["--lane-ulid"] : []),
948
948
  ...(query.active ? ["--active"] : []),
949
949
  ...(query.hierarchy?.length ? ["--hierarchy"] : []),
950
+ ...(query.senior !== undefined ? ["--senior"] : []),
950
951
  ...(query.snapshot ? ["--snapshot"] : []),
951
952
  ];
952
953
  }
@@ -1404,6 +1405,7 @@ function normalizedLaneListQuery(query) {
1404
1405
  ...(laneUlids === undefined ? {} : { laneUlids }),
1405
1406
  ...(query.active ? { active: true } : {}),
1406
1407
  ...(hierarchy === undefined ? {} : { hierarchy }),
1408
+ ...(query.senior === undefined ? {} : { senior: query.senior }),
1407
1409
  ...(query.snapshot ? { snapshot: true } : {}),
1408
1410
  ...(query.strictSnapshot ? { strictSnapshot: true } : {}),
1409
1411
  ...(query.includeForeignHostRows ? { includeForeignHostRows: true } : {}),
@@ -1503,6 +1505,48 @@ async function readOutpostLaneRecords(ctx, outpostId, requestedQuery = {}, dispa
1503
1505
  }
1504
1506
  return invocationMemo.getOrCreate(outpostId, query, () => readOutpostLaneRecordsUncached(ctx, outpostId, query, dispatchOptions));
1505
1507
  }
1508
+ /**
1509
+ * Read the owner rows the hire-grant context for `laneId` is built from.
1510
+ *
1511
+ * The owner's `--hierarchy` selector also returns every lane that shares the
1512
+ * target's company and project, so on a store with hundreds of lanes in one
1513
+ * project the response reaches the Outpost exec output limit and the read
1514
+ * fails before a single row is parsed. When that happens, and the target has a
1515
+ * lane senior, assemble the rows the context builder needs from bounded reads
1516
+ * every owner CLI supports: the target and its senior by id, the senior's
1517
+ * direct children (the target's siblings) and the target's own children by
1518
+ * `--senior`. The owner rejects `--senior` together with `--snapshot`, so the
1519
+ * two `--senior` reads use the plain JSON list; the dispatched command sets
1520
+ * HQ_LANES_REMOTE_READ=1, which keeps that list from refreshing remote
1521
+ * mirrors, and the view-only fields it adds are stripped before parsing. A
1522
+ * session-senior target needs same-company profile rows that no bounded
1523
+ * filter selects, so its oversized read stays an error.
1524
+ */
1525
+ async function readOutpostLaneHierarchy(ctx, outpostId, laneId) {
1526
+ let tooLarge;
1527
+ try {
1528
+ return await readOutpostLaneRecords(ctx, outpostId, { hierarchy: [laneId], snapshot: true });
1529
+ }
1530
+ catch (err) {
1531
+ if (!isLanesError(err) || err.error !== "outpost_lane_list_too_large")
1532
+ throw err;
1533
+ tooLarge = err;
1534
+ }
1535
+ const targets = await readOutpostLaneRecords(ctx, outpostId, { laneIds: [laneId], snapshot: true });
1536
+ const target = targets.find((lane) => lane.lane_id === laneId);
1537
+ if (target === undefined)
1538
+ return targets;
1539
+ if (target.senior.kind !== "lane" || !target.senior.id) {
1540
+ throw new LanesError(tooLarge.error, `${tooLarge.message}; lane ${laneId} has a ${target.senior.kind} senior, whose hierarchy cannot be read in bounded parts`, { ...tooLarge.details, lane_id: laneId, senior: target.senior });
1541
+ }
1542
+ const seniorId = target.senior.id;
1543
+ const [seniorRows, siblings, children] = await Promise.all([
1544
+ readOutpostLaneRecords(ctx, outpostId, { laneIds: [seniorId], snapshot: true }),
1545
+ readOutpostLaneRecords(ctx, outpostId, { senior: `lane:${seniorId}` }),
1546
+ readOutpostLaneRecords(ctx, outpostId, { senior: `lane:${laneId}` }),
1547
+ ]);
1548
+ return mergeOwnerLaneRecords([...targets, ...seniorRows, ...siblings], children);
1549
+ }
1506
1550
  /** Refresh this host's selected Outpost mirrors in one bounded owner query per Outpost. */
1507
1551
  async function refreshRemoteLaneMirrors(ctx, hqRoot, records, parentLaneIds, options = {}) {
1508
1552
  const result = {
@@ -1829,9 +1873,12 @@ async function resolveCommandLaneTarget(ctx, laneId, options = {}) {
1829
1873
  for (const outpostId of lookupOutpostIds) {
1830
1874
  let ownerLanes;
1831
1875
  try {
1832
- ownerLanes = await readOutpostLaneRecords(ctx, outpostId, hostlessUlidLookup
1833
- ? { laneUlids: [requestedUlid], snapshot: true }
1834
- : { hierarchy: [laneId], snapshot: true });
1876
+ // The hierarchy read is shared with the grant context built after
1877
+ // resolution, so one owner round trip serves both whenever the Outpost
1878
+ // exec output limit can carry the owner's response.
1879
+ ownerLanes = hostlessUlidLookup
1880
+ ? await readOutpostLaneRecords(ctx, outpostId, { laneUlids: [requestedUlid], snapshot: true })
1881
+ : await readOutpostLaneHierarchy(ctx, outpostId, laneId);
1835
1882
  probedOutpostIds.push(outpostId);
1836
1883
  }
1837
1884
  catch (err) {
@@ -4665,20 +4712,14 @@ async function dispatchOutpostLaneCommand(ctx, lane, action, options, behavior =
4665
4712
  let grantContext;
4666
4713
  let grantHierarchy;
4667
4714
  if (action === "grant") {
4668
- const ownerHierarchy = mergeOwnerLaneRecords(loadAllLanes(ctx.hqRoot()), await readOutpostLaneRecords(ctx, outpostId, {
4669
- hierarchy: [lane.lane_id],
4670
- snapshot: true,
4671
- }));
4715
+ const ownerHierarchy = mergeOwnerLaneRecords(loadAllLanes(ctx.hqRoot()), await readOutpostLaneHierarchy(ctx, outpostId, lane.lane_id));
4672
4716
  const hierarchy = await hierarchyWithVerifiedRemoteSenior(ctx, ctx.hqRoot(), lane, ownerHierarchy);
4673
4717
  grantHierarchy = hierarchy;
4674
4718
  grantContext = createOutpostHireGrantContext(lane, hierarchy);
4675
4719
  }
4676
4720
  else if ((action === "resume" && lane.senior.kind === "lane") ||
4677
4721
  (action === "message" && (lane.senior.kind === "lane" || lane.senior.kind === "session"))) {
4678
- const ownerHierarchy = mergeOwnerLaneRecords(loadAllLanes(ctx.hqRoot()), await readOutpostLaneRecords(ctx, outpostId, {
4679
- hierarchy: [lane.lane_id],
4680
- snapshot: true,
4681
- }));
4722
+ const ownerHierarchy = mergeOwnerLaneRecords(loadAllLanes(ctx.hqRoot()), await readOutpostLaneHierarchy(ctx, outpostId, lane.lane_id));
4682
4723
  const hierarchy = await hierarchyWithVerifiedRemoteSenior(ctx, ctx.hqRoot(), lane, ownerHierarchy);
4683
4724
  grantContext = createOutpostHireGrantContext(lane, hierarchy, action === "message" ? options.supersededMessageCallerId : undefined, action === "message" ? options.supersededMessageSessionId : undefined);
4684
4725
  }
@@ -145,7 +145,7 @@ import { ensureCognitoToken } from "../utils/cognito-session.js";
145
145
  import { removeCacheEntry, clearAllCache } from "../utils/secrets-cache.js";
146
146
  import { isHqCliChild, releaseChildWrapperPackageUseLeaseAfterStart } from "../utils/child-wrapper-lease.js";
147
147
  import { resolveDefaultHqRoot } from "../utils/hq-root-resolver.js";
148
- import { fastFlagEnabled } from "../native-fast-route.js";
148
+ import { fastFlagEnabledDefaultOn } from "../native-fast-route.js";
149
149
  import { MULTI_COMPANY_SESSION_LOCK_FLAG } from "../lib/cli-flag-keys.js";
150
150
  import { resolveSessionId } from "../lib/core-utils/session-id.js";
151
151
  import { secretsExecChildExitCode } from "../utils/child-wrapper-exit.js";
@@ -1249,7 +1249,7 @@ export function registerSecretsCommand(program) {
1249
1249
  process.exit(1);
1250
1250
  }
1251
1251
  const keys = parseSecretNameList(_opts.only);
1252
- const multiCompanyLockEnabled = await fastFlagEnabled(MULTI_COMPANY_SESSION_LOCK_FLAG);
1252
+ const multiCompanyLockEnabled = await fastFlagEnabledDefaultOn(MULTI_COMPANY_SESSION_LOCK_FLAG);
1253
1253
  const sessionLock = multiCompanyLockEnabled ? readSessionCompanyLock(process.env) : undefined;
1254
1254
  const parentScope = secrets.opts();
1255
1255
  const inheritedCompany = parentScope.company;
@@ -7,7 +7,7 @@ import { ensureCognitoToken } from "../utils/cognito-session.js";
7
7
  import { vaultApiFetch, getCompanyUid } from "./secrets.js";
8
8
  import { GROUP_ID_PATTERN, EMAIL_PATTERN, toSharedFolderGlob } from "./_patterns.js";
9
9
  import { findHqRoot } from "../utils/manifest.js";
10
- import { fastFlagEnabled } from "../native-fast-route.js";
10
+ import { fastFlagEnabledDefaultOn } from "../native-fast-route.js";
11
11
  import { MULTI_COMPANY_SESSION_LOCK_FLAG } from "../lib/cli-flag-keys.js";
12
12
  import { resolveSessionId } from "../lib/core-utils/session-id.js";
13
13
  export { readWorkerRegistry } from "../lib/workers-registry/read.js";
@@ -198,7 +198,7 @@ async function runWorkersShare(workerId, opts) {
198
198
  }
199
199
  async function runWorkersList(opts) {
200
200
  const hqRoot = findHqRoot();
201
- const enabled = await fastFlagEnabled(MULTI_COMPANY_SESSION_LOCK_FLAG);
201
+ const enabled = await fastFlagEnabledDefaultOn(MULTI_COMPANY_SESSION_LOCK_FLAG);
202
202
  const lockedCompanies = resolveActiveCompanies(hqRoot, enabled);
203
203
  if (enabled && opts.company && denyWorkerCompanyOutsideLock(opts.company, lockedCompanies))
204
204
  return;