@indigoai-us/hq-cli 5.345.202 → 5.345.203

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 (49) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/command-catalog.generated.d.ts +24 -0
  3. package/dist/command-catalog.generated.js +26 -0
  4. package/dist/commands/capacity.js +10 -2
  5. package/dist/commands/daemon.d.ts +2 -1
  6. package/dist/commands/daemon.js +225 -4
  7. package/dist/commands/integrations-core.d.ts +3 -0
  8. package/dist/commands/integrations-core.js +11 -0
  9. package/dist/commands/integrations-manage.js +2 -2
  10. package/dist/commands/integrations.js +5 -5
  11. package/dist/commands/sync-core.js +2 -1
  12. package/dist/lib/bot/executive-settings.d.ts +1 -1
  13. package/dist/lib/bot/executive-settings.js +8 -6
  14. package/dist/lib/bot/jobs/meeting-detect.js +2 -2
  15. package/dist/lib/bot/jobs/meeting-rider.js +2 -2
  16. package/dist/lib/bot/run.js +3 -3
  17. package/dist/lib/capacity/codex-availability.d.ts +6 -0
  18. package/dist/lib/capacity/codex-availability.js +33 -0
  19. package/dist/lib/capacity/ledger.d.ts +0 -11
  20. package/dist/lib/capacity/ledger.js +30 -3
  21. package/dist/lib/capacity/route.js +11 -5
  22. package/dist/lib/daemon/catalog.d.ts +3 -0
  23. package/dist/lib/daemon/catalog.js +15 -2
  24. package/dist/lib/daemon/handoff.d.ts +2 -0
  25. package/dist/lib/daemon/handoff.js +9 -2
  26. package/dist/lib/daemon/install.d.ts +99 -0
  27. package/dist/lib/daemon/install.js +316 -7
  28. package/dist/lib/daemon/migrate.d.ts +3 -1
  29. package/dist/lib/daemon/migrate.js +14 -2
  30. package/dist/lib/daemon/plist-refresh.d.ts +34 -0
  31. package/dist/lib/daemon/plist-refresh.js +62 -0
  32. package/dist/lib/daemon/run.js +25 -0
  33. package/dist/lib/daemon/selfcheck.d.ts +71 -0
  34. package/dist/lib/daemon/selfcheck.js +150 -0
  35. package/dist/lib/daemon/supervisor.d.ts +31 -0
  36. package/dist/lib/daemon/supervisor.js +130 -6
  37. package/dist/lib/daemon/unit-holds.js +2 -1
  38. package/dist/lib/service-manager/launchd.d.ts +25 -0
  39. package/dist/lib/service-manager/launchd.js +51 -3
  40. package/dist/lib/service-manager/migration.d.ts +14 -0
  41. package/dist/lib/service-manager/migration.js +34 -0
  42. package/dist/lib/service-manager/systemd.d.ts +13 -0
  43. package/dist/lib/service-manager/systemd.js +19 -0
  44. package/dist/lib/service-manager/types.d.ts +8 -0
  45. package/dist/lib/sync-core/reconcile.d.ts +4 -1
  46. package/dist/lib/sync-core/reconcile.js +12 -2
  47. package/dist/lib/sync-core/release.d.ts +23 -0
  48. package/dist/lib/sync-core/release.js +39 -0
  49. package/package.json +7 -7
@@ -21,6 +21,14 @@ export interface ServiceSpec {
21
21
  restartSec: number;
22
22
  /** systemd unit file name; defaults to `hq-agent-<name>.service`. */
23
23
  unitName?: string;
24
+ /**
25
+ * macOS: run the job directly under node, without the HQ.app launcher and
26
+ * without AssociatedBundleIdentifiers, so launchd loads it at login whether
27
+ * or not the app is installed, enabled or allowed. The daemon sets this:
28
+ * on 2026-11-03 launchd skipped both app-associated agents at login and the
29
+ * daemon stayed down for 16 hours.
30
+ */
31
+ independentOfApp?: boolean;
24
32
  }
25
33
  export interface ServiceHostPaths {
26
34
  home: string;
@@ -1,5 +1,5 @@
1
1
  import { type SyncCoreVault } from "./engine-home.js";
2
- import { type SyncCoreBinaryInstall } from "./release.js";
2
+ import { type SyncCoreBinaryInstall, type SyncCorePin } from "./release.js";
3
3
  import { type SyncCoreRolloutState } from "./rollout-state.js";
4
4
  export interface SyncCoreMembership {
5
5
  companyUid: string;
@@ -14,7 +14,10 @@ export interface SyncCoreReconcileDeps {
14
14
  resolvePersonUid: () => Promise<string | null>;
15
15
  readRolloutFlag: (companyUid: string) => Promise<boolean>;
16
16
  ensureBinary: (release: string) => Promise<SyncCoreBinaryInstall>;
17
+ /** A fixed release (tests). Otherwise readPin decides, then SYNC_CORE_RELEASE. */
17
18
  release?: string;
19
+ /** Reads the server-side engine pin; never throws (see readSyncCorePin). */
20
+ readPin?: () => Promise<SyncCorePin>;
18
21
  now?: () => Date;
19
22
  log?: (line: string) => void;
20
23
  }
@@ -3,7 +3,7 @@ import * as path from "node:path";
3
3
  import { readCompaniesManifestMap } from "../work-context/repo-remote.js";
4
4
  import { readVaultSyncSwitches, writeVaultSyncSwitches } from "../vault-sync-switches.js";
5
5
  import { clearEngineStatus, engineFirstCycle, isSyncCoreVaultUid, removeEngineOwnership, syncCoreEngineHome, writeEngineHome, } from "./engine-home.js";
6
- import { SYNC_CORE_FULL_RELEASE, SYNC_CORE_RELEASE, fullModeAllowed, installedSyncCoreRelease, syncCoreBinaryPath, } from "./release.js";
6
+ import { SYNC_CORE_FULL_RELEASE, SYNC_CORE_RELEASE, compareSyncCoreReleases, fullModeAllowed, installedSyncCoreRelease, syncCoreBinaryPath, } from "./release.js";
7
7
  import { readSyncCoreSkips } from "./skip.js";
8
8
  import { SYNC_RUST_ENGINE_ROLLOUT_FLAG } from "./flag.js";
9
9
  import { readSyncCoreRolloutState, syncCoreRolloutStatePath, writeSyncCoreRolloutState, } from "./rollout-state.js";
@@ -65,8 +65,8 @@ function ownedVaultsWithoutState(home, hqRoot) {
65
65
  export async function reconcileSyncCore(deps) {
66
66
  const now = deps.now ?? (() => new Date());
67
67
  const log = deps.log ?? (() => { });
68
- const release = deps.release ?? SYNC_CORE_RELEASE;
69
68
  const warnings = [];
69
+ let release = deps.release ?? SYNC_CORE_RELEASE;
70
70
  const previous = readSyncCoreRolloutState(deps.home);
71
71
  const previousVaults = previous?.vaults ?? ownedVaultsWithoutState(deps.home, deps.hqRoot);
72
72
  const previousByUid = new Map(previousVaults.map((vault) => [vault.uid, vault]));
@@ -117,6 +117,16 @@ export async function reconcileSyncCore(deps) {
117
117
  let binaryPath = syncCoreBinaryPath(deps.home);
118
118
  let installedRelease = installedSyncCoreRelease(deps.home);
119
119
  if (desired.length > 0) {
120
+ if (deps.release === undefined && deps.readPin) {
121
+ const pin = await deps.readPin();
122
+ release = pin.release;
123
+ if (pin.warning)
124
+ warnings.push(pin.warning);
125
+ if (pin.source === "server" && installedRelease && compareSyncCoreReleases(pin.release, installedRelease) < 0) {
126
+ // The no-downgrade guard in ensureSyncCoreBinary keeps the newer engine.
127
+ log(`the server pins hq-syncd ${pin.release}, older than the installed ${installedRelease}; keeping ${installedRelease}`);
128
+ }
129
+ }
120
130
  try {
121
131
  const install = await deps.ensureBinary(release);
122
132
  binaryPath = install.binaryPath;
@@ -4,6 +4,29 @@ export declare function compareSyncCoreReleases(a: string, b: string): number;
4
4
  export declare function fullModeAllowed(release: string): boolean;
5
5
  export declare const SYNC_CORE_DOWNLOAD_BASE = "https://indigoai-public.s3.amazonaws.com/hq-sync-core";
6
6
  export declare const SYNC_CORE_DOWNLOAD_BASE_ENV = "HQ_SYNC_CORE_DOWNLOAD_BASE";
7
+ /** The server-side engine pin, published next to the release folders on the download base. */
8
+ export declare const SYNC_CORE_PIN_FILE = "pin.json";
9
+ export interface SyncCorePin {
10
+ /** The engine release machines should run. */
11
+ release: string;
12
+ /** "server": read from pin.json; "built-in": SYNC_CORE_RELEASE, because no server pin could be used. */
13
+ source: "server" | "built-in";
14
+ /** Why the server pin was not used, when it exists but could not be read. A missing pin.json sets none. */
15
+ warning?: string;
16
+ }
17
+ /**
18
+ * The engine release to install, read from `<download base>/pin.json`
19
+ * (`{"release":"v0.1.24"}`), so an engine release reaches machines without an
20
+ * hq-cli release. Falls back to SYNC_CORE_RELEASE when the file is missing,
21
+ * unreadable or malformed. Never throws. Windows stays unsupported: the pin
22
+ * only picks a version, and syncCoreAssetName has no Windows build.
23
+ */
24
+ export declare function readSyncCorePin(opts?: {
25
+ env?: NodeJS.ProcessEnv;
26
+ baseUrl?: string;
27
+ fetch?: typeof fetch;
28
+ timeoutMs?: number;
29
+ }): Promise<SyncCorePin>;
7
30
  export declare function syncCoreBinaryPath(home?: string): string;
8
31
  export declare function syncCoreReleaseMarkerPath(home?: string): string;
9
32
  export declare function syncCoreAssetName(release: string, platform: NodeJS.Platform, arch: string): string | null;
@@ -21,6 +21,45 @@ export function fullModeAllowed(release) {
21
21
  export const SYNC_CORE_DOWNLOAD_BASE = "https://indigoai-public.s3.amazonaws.com/hq-sync-core";
22
22
  export const SYNC_CORE_DOWNLOAD_BASE_ENV = "HQ_SYNC_CORE_DOWNLOAD_BASE";
23
23
  const DOWNLOAD_TIMEOUT_MS = 600_000;
24
+ /** The server-side engine pin, published next to the release folders on the download base. */
25
+ export const SYNC_CORE_PIN_FILE = "pin.json";
26
+ const PIN_TIMEOUT_MS = 10_000;
27
+ const RELEASE_PATTERN = /^v\d+\.\d+\.\d+$/;
28
+ /**
29
+ * The engine release to install, read from `<download base>/pin.json`
30
+ * (`{"release":"v0.1.24"}`), so an engine release reaches machines without an
31
+ * hq-cli release. Falls back to SYNC_CORE_RELEASE when the file is missing,
32
+ * unreadable or malformed. Never throws. Windows stays unsupported: the pin
33
+ * only picks a version, and syncCoreAssetName has no Windows build.
34
+ */
35
+ export async function readSyncCorePin(opts = {}) {
36
+ const builtIn = (warning) => ({ release: SYNC_CORE_RELEASE, source: "built-in", ...(warning ? { warning } : {}) });
37
+ const url = `${opts.baseUrl?.replace(/\/+$/, "") ?? syncCoreDownloadBase(opts.env)}/${SYNC_CORE_PIN_FILE}`;
38
+ let response;
39
+ try {
40
+ response = await (opts.fetch ?? fetch)(url, { signal: AbortSignal.timeout(opts.timeoutMs ?? PIN_TIMEOUT_MS) });
41
+ }
42
+ catch (error) {
43
+ return builtIn(`could not read the engine pin ${url}: ${error instanceof Error ? error.message : String(error)}; using built-in ${SYNC_CORE_RELEASE}`);
44
+ }
45
+ // S3 answers 403 for a missing key on a bucket without public listing.
46
+ if (response.status === 404 || response.status === 403)
47
+ return builtIn();
48
+ if (!response.ok)
49
+ return builtIn(`could not read the engine pin ${url}: HTTP ${response.status}; using built-in ${SYNC_CORE_RELEASE}`);
50
+ let parsed;
51
+ try {
52
+ parsed = JSON.parse(await response.text());
53
+ }
54
+ catch {
55
+ return builtIn(`the engine pin ${url} is not JSON; using built-in ${SYNC_CORE_RELEASE}`);
56
+ }
57
+ const release = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed.release : undefined;
58
+ if (typeof release !== "string" || !RELEASE_PATTERN.test(release)) {
59
+ return builtIn(`the engine pin ${url} has no valid "release" (want vX.Y.Z); using built-in ${SYNC_CORE_RELEASE}`);
60
+ }
61
+ return { release, source: "server" };
62
+ }
24
63
  export function syncCoreBinaryPath(home = os.homedir()) {
25
64
  return path.join(home, ".hq", "bin", "hq-syncd");
26
65
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.345.202",
3
+ "version": "5.345.203",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -117,11 +117,11 @@
117
117
  "*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}": "eslint --cache --no-error-on-unmatched-pattern"
118
118
  },
119
119
  "optionalDependencies": {
120
- "@indigoai-us/hq-hook-win32-x64": "5.345.202",
121
- "@indigoai-us/hq-hook-win32-arm64": "5.345.202",
122
- "@indigoai-us/hq-hook-darwin-x64": "5.345.202",
123
- "@indigoai-us/hq-hook-darwin-arm64": "5.345.202",
124
- "@indigoai-us/hq-hook-linux-x64": "5.345.202",
125
- "@indigoai-us/hq-hook-linux-arm64": "5.345.202"
120
+ "@indigoai-us/hq-hook-win32-x64": "5.345.203",
121
+ "@indigoai-us/hq-hook-win32-arm64": "5.345.203",
122
+ "@indigoai-us/hq-hook-darwin-x64": "5.345.203",
123
+ "@indigoai-us/hq-hook-darwin-arm64": "5.345.203",
124
+ "@indigoai-us/hq-hook-linux-x64": "5.345.203",
125
+ "@indigoai-us/hq-hook-linux-arm64": "5.345.203"
126
126
  }
127
127
  }