@indigoai-us/hq-cli 5.345.135 → 5.345.137
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/assets/scaffold/core/scripts/worktree-gc.sh +98 -8
- package/dist/command-catalog.generated.d.ts +17 -6
- package/dist/command-catalog.generated.js +23 -7
- package/dist/commands/core-checkpoint-native.d.ts +10 -0
- package/dist/commands/core-checkpoint-native.js +60 -15
- package/dist/commands/daemon.js +3 -1
- package/dist/commands/integrations-core.d.ts +22 -0
- package/dist/commands/integrations-core.js +25 -0
- package/dist/commands/integrations-manage.d.ts +24 -1
- package/dist/commands/integrations-manage.js +92 -17
- package/dist/commands/integrations.d.ts +11 -0
- package/dist/commands/integrations.js +100 -19
- package/dist/commands/lanes-loop.d.ts +9 -0
- package/dist/commands/lanes-loop.js +9 -1
- package/dist/commands/lanes.js +69 -54
- package/dist/commands/meetings.d.ts +2 -0
- package/dist/commands/meetings.js +57 -14
- package/dist/commands/mesh.d.ts +19 -1
- package/dist/commands/mesh.js +158 -70
- package/dist/commands/reindex.js +80 -5
- package/dist/commands/storage-offload.d.ts +93 -28
- package/dist/commands/storage-offload.js +290 -34
- package/dist/commands/storage.js +60 -7
- package/dist/hq-cloud-sync-runner/bin/sync-runner.js +2550 -1748
- package/dist/hq-cloud-sync-runner/package.json +1 -1
- package/dist/index.js +4 -0
- package/dist/lib/capacity/route.js +24 -0
- package/dist/lib/core-utils/session-company.d.ts +11 -0
- package/dist/lib/core-utils/session-company.js +34 -0
- package/dist/lib/core-utils/worktree-resume.js +44 -4
- package/dist/lib/core-utils/worktree-session-owner.d.ts +27 -0
- package/dist/lib/core-utils/worktree-session-owner.js +157 -0
- package/dist/lib/daemon/catalog.d.ts +2 -0
- package/dist/lib/daemon/catalog.js +3 -3
- package/dist/lib/daemon/hq-child-bootstrap-stage.d.ts +5 -0
- package/dist/lib/daemon/hq-child-bootstrap-stage.js +3 -11
- package/dist/lib/daemon/server.js +10 -1
- package/dist/lib/daemon/supervisor.js +6 -0
- package/dist/lib/daemon/sync-runner-bundle.d.ts +5 -0
- package/dist/lib/daemon/sync-runner-bundle.js +4 -12
- package/dist/lib/doctor/checks/claude-wiring.js +2 -1
- package/dist/lib/doctor/fix/apply.d.ts +20 -0
- package/dist/lib/doctor/fix/apply.js +63 -3
- package/dist/lib/doctor/fix/remediation.d.ts +1 -1
- package/dist/lib/doctor/fix/remediation.js +16 -0
- package/dist/lib/doctor/shared.d.ts +11 -1
- package/dist/lib/doctor/shared.js +16 -2
- package/dist/lib/flag-registry-worker-source.generated.d.ts +1 -1
- package/dist/lib/flag-registry-worker-source.generated.js +1 -1
- package/dist/lib/lanes/monitor.js +14 -2
- package/dist/lib/mesh/live/daemon/install.d.ts +12 -0
- package/dist/lib/mesh/live/daemon/install.js +22 -0
- package/dist/lib/mesh/live/flush.js +106 -3
- package/dist/lib/mesh/live/session-events-client.d.ts +9 -0
- package/dist/lib/mesh/live/session-events-client.js +15 -0
- package/dist/lib/work-context/state.d.ts +10 -0
- package/dist/lib/work-context/state.js +5 -0
- package/dist/utils/fsync-directory.d.ts +17 -0
- package/dist/utils/fsync-directory.js +27 -0
- package/dist/utils/windows-hide-default.d.ts +42 -0
- package/dist/utils/windows-hide-default.js +98 -0
- package/package.json +2 -2
|
@@ -46,7 +46,7 @@ import { removeStrayGateEntries } from "../stray-gate-entries.js";
|
|
|
46
46
|
import { deriveRemediation } from "./remediation.js";
|
|
47
47
|
import { botDir } from "../../bot/paths.js";
|
|
48
48
|
import { readBotConfig } from "../../bot/config.js";
|
|
49
|
-
import { buildBotDaemonPaths, rewriteBotDaemonNodePath } from "../../bot/daemon.js";
|
|
49
|
+
import { buildBotDaemonPaths, installedDaemonHqBinary, repairBotDaemonIfStale, rewriteBotDaemonNodePath, } from "../../bot/daemon.js";
|
|
50
50
|
import { classifyRefreshSyncOutcome, } from "./refresh-sync-outcome.js";
|
|
51
51
|
import { readRefreshSyncProgress, writeRefreshSyncCursor, writeRefreshSyncLastRun, } from "./refresh-sync-progress.js";
|
|
52
52
|
import { clientHealthShowManualOnlyEnabled } from "../client-health-reason-codes-flag.js";
|
|
@@ -130,6 +130,7 @@ export async function applyFixes(options) {
|
|
|
130
130
|
const collect = options.runChecks ?? defaultRunChecks;
|
|
131
131
|
const refreshSync = options.refreshSync ?? defaultRefreshSync;
|
|
132
132
|
const rewriteBotNodePath = options.rewriteBotNodePath ?? defaultRewriteBotNodePath;
|
|
133
|
+
const repairBotHqBinary = options.repairBotHqBinary ?? defaultRepairBotHqBinary;
|
|
133
134
|
// 2. Collect findings, then plan each newly unlocked allowlisted repair.
|
|
134
135
|
// Identity is deliberately the check id + target pair: an unsuccessful
|
|
135
136
|
// repair must not be applied repeatedly in one invocation.
|
|
@@ -154,7 +155,7 @@ export async function applyFixes(options) {
|
|
|
154
155
|
const rem = deriveRemediation(result);
|
|
155
156
|
if (!rem?.autoFixable)
|
|
156
157
|
continue;
|
|
157
|
-
const plan = planFix(hqRoot, result, rem, refreshSync, rewriteBotNodePath);
|
|
158
|
+
const plan = planFix(hqRoot, result, rem, refreshSync, rewriteBotNodePath, repairBotHqBinary);
|
|
158
159
|
if (!plan)
|
|
159
160
|
continue;
|
|
160
161
|
const key = JSON.stringify([plan.checkId, plan.target]);
|
|
@@ -421,10 +422,12 @@ export function uncommittedHookConfigChanges(hqRoot) {
|
|
|
421
422
|
}
|
|
422
423
|
// --- Fix planning --------------------------------------------------------------
|
|
423
424
|
/** Build the concrete plan for one auto-fixable finding, or null if unplannable. */
|
|
424
|
-
function planFix(hqRoot, result, rem, refreshSync, rewriteBotNodePath = defaultRewriteBotNodePath) {
|
|
425
|
+
function planFix(hqRoot, result, rem, refreshSync, rewriteBotNodePath = defaultRewriteBotNodePath, repairBotHqBinary = defaultRepairBotHqBinary) {
|
|
425
426
|
switch (rem.fixClass) {
|
|
426
427
|
case "bot-node-path":
|
|
427
428
|
return planBotNodePath(result, rem, rewriteBotNodePath);
|
|
429
|
+
case "bot-hq-binary":
|
|
430
|
+
return planBotHqBinary(result, rem, repairBotHqBinary);
|
|
428
431
|
case "executable-bit":
|
|
429
432
|
return planExecutableBit(hqRoot, result, rem);
|
|
430
433
|
case "gate-profile":
|
|
@@ -467,6 +470,63 @@ export function defaultRewriteBotNodePath(name) {
|
|
|
467
470
|
return null;
|
|
468
471
|
return rewriteBotDaemonNodePath(buildBotDaemonPaths({ name, botDir: dir, hqRoot: config.hqRoot, hqBinary: "hq" }), { platform: "darwin" });
|
|
469
472
|
}
|
|
473
|
+
/** Reinstall one bot LaunchAgent whose hq binary is missing. */
|
|
474
|
+
function planBotHqBinary(result, rem, repair) {
|
|
475
|
+
const name = rem.fixTarget;
|
|
476
|
+
if (!name)
|
|
477
|
+
return null;
|
|
478
|
+
return {
|
|
479
|
+
checkId: result.checkId,
|
|
480
|
+
fixClass: "bot-hq-binary",
|
|
481
|
+
target: name,
|
|
482
|
+
relpath: "",
|
|
483
|
+
preview: ` ~/Library/LaunchAgents/ai.getindigo.hq-bot.${name}.plist\n` +
|
|
484
|
+
` ~ hq path -> the installed hq (same as hq bot daemon install ${name})\n` +
|
|
485
|
+
` the agent is reloaded; its old hq path is missing, so it was not running`,
|
|
486
|
+
summary: `reinstall ${name} startup agent against the installed hq`,
|
|
487
|
+
apply: () => {
|
|
488
|
+
repair(name);
|
|
489
|
+
},
|
|
490
|
+
postStatus: (results) => results.find((entry) => entry.checkId === result.checkId)?.status ?? null,
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
/** Real launchctl for the `bot-hq-binary` reload; a failure is a non-ok result. */
|
|
494
|
+
const doctorLaunchctl = (args) => {
|
|
495
|
+
const r = spawnSync("launchctl", args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
496
|
+
return { ok: r.status === 0, stdout: String(r.stdout ?? ""), stderr: String(r.stderr ?? r.error?.message ?? "") };
|
|
497
|
+
};
|
|
498
|
+
/**
|
|
499
|
+
* An hq path a bot may be pointed at unattended: an installed package entry
|
|
500
|
+
* or its stable shim, never a worktree or one-off build that happens to be
|
|
501
|
+
* running `hq doctor --fix`.
|
|
502
|
+
*/
|
|
503
|
+
export function isInstalledHqBinary(hqBinary) {
|
|
504
|
+
const normalized = hqBinary.replace(/\\/g, "/");
|
|
505
|
+
if (/\/node_modules\/@indigoai-us\/hq-cli\//i.test(normalized))
|
|
506
|
+
return true;
|
|
507
|
+
return /\/bin\/hq(\.cmd)?$/i.test(normalized);
|
|
508
|
+
}
|
|
509
|
+
/** Default `bot-hq-binary` repair against the real bot state and LaunchAgents. */
|
|
510
|
+
export function defaultRepairBotHqBinary(name) {
|
|
511
|
+
if (process.platform !== "darwin")
|
|
512
|
+
return null;
|
|
513
|
+
const dir = botDir(name);
|
|
514
|
+
const config = readBotConfig(dir);
|
|
515
|
+
if (!config)
|
|
516
|
+
return null;
|
|
517
|
+
const paths = buildBotDaemonPaths({ name, botDir: dir, hqRoot: config.hqRoot });
|
|
518
|
+
if (!isInstalledHqBinary(paths.hqBinary) || !fs.existsSync(paths.hqBinary))
|
|
519
|
+
return null;
|
|
520
|
+
let from;
|
|
521
|
+
try {
|
|
522
|
+
from = installedDaemonHqBinary(paths);
|
|
523
|
+
}
|
|
524
|
+
catch {
|
|
525
|
+
from = null;
|
|
526
|
+
}
|
|
527
|
+
const repaired = repairBotDaemonIfStale(paths, { launchctl: doctorLaunchctl });
|
|
528
|
+
return repaired ? { from, to: paths.hqBinary } : null;
|
|
529
|
+
}
|
|
470
530
|
/** Pull one company or the personal vault to refresh a stale journal. */
|
|
471
531
|
function planRefreshSync(hqRoot, result, rem, refreshSync) {
|
|
472
532
|
const slug = rem.fixTarget;
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
*/
|
|
41
41
|
import type { CheckResult } from "../types.js";
|
|
42
42
|
/** The allowlisted safe repair classes `--fix` is permitted to apply. */
|
|
43
|
-
export type FixClass = "executable-bit" | "gate-profile" | "remove-stray-gate-entries" | "refresh-sync" | "bot-node-path";
|
|
43
|
+
export type FixClass = "executable-bit" | "gate-profile" | "remove-stray-gate-entries" | "refresh-sync" | "bot-node-path" | "bot-hq-binary";
|
|
44
44
|
/**
|
|
45
45
|
* A finding's structured remediation. `autoFixable`, `action`, and `command`
|
|
46
46
|
* are the `--json` surface (AC1); `fixTarget`/`fixClass` are the internal handle
|
|
@@ -119,6 +119,22 @@ export function deriveRemediation(result) {
|
|
|
119
119
|
command: remediation ?? `hq bot start ${target}`,
|
|
120
120
|
};
|
|
121
121
|
}
|
|
122
|
+
// bot-hq-binary — a bot LaunchAgent whose hq path no longer exists (an
|
|
123
|
+
// update moved or removed it), so launchd cannot start the bot. The repair
|
|
124
|
+
// is what `hq bot daemon install <name>` does: rewrite the agent against
|
|
125
|
+
// the installed hq and reload it. A job whose hq is missing is not running a
|
|
126
|
+
// turn, so the reload cuts nothing short (feedback_c441dd9a).
|
|
127
|
+
const botBinary = /^bots\.(.+)\.daemon-binary$/.exec(checkId);
|
|
128
|
+
if (botBinary && result.status === "FAIL") {
|
|
129
|
+
const name = botBinary[1];
|
|
130
|
+
return {
|
|
131
|
+
autoFixable: true,
|
|
132
|
+
fixClass: "bot-hq-binary",
|
|
133
|
+
fixTarget: name,
|
|
134
|
+
action: `Reinstall the ${name} startup agent against the installed hq binary and reload it.`,
|
|
135
|
+
command: remediation ?? `hq bot daemon install ${name}`,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
122
138
|
// Available hq-core upgrade. WARN is intentional in `hq doctor` and is
|
|
123
139
|
// not a broken sync; --fix has no mechanical repair for it.
|
|
124
140
|
if (checkId === "sync.update.core") {
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
/** Collect every `command` string from a `{hooks:{Event:[{hooks:[…]}]}}` doc. */
|
|
2
2
|
export declare function collectCommands(parsed: unknown): string[];
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Whether a file mode counts as executable for a hook check.
|
|
5
|
+
*
|
|
6
|
+
* Windows has no POSIX execute bit: Node reports 0o666 for every regular file
|
|
7
|
+
* that is not a .exe/.cmd/.bat/.com, and the hook runtimes start HQ's shell
|
|
8
|
+
* hooks through bash, which never consults it. A mode check there can only
|
|
9
|
+
* produce false FAILs (feedback_a60339e8, 27 of them on one install), so
|
|
10
|
+
* win32 treats every present file as executable.
|
|
11
|
+
*/
|
|
12
|
+
export declare function modeIsExecutable(mode: number, platform?: NodeJS.Platform): boolean;
|
|
13
|
+
export declare function fileState(target: string, platform?: NodeJS.Platform): {
|
|
4
14
|
present: boolean;
|
|
5
15
|
executable: boolean;
|
|
6
16
|
};
|
|
@@ -23,10 +23,24 @@ export function collectCommands(parsed) {
|
|
|
23
23
|
}
|
|
24
24
|
return commands;
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Whether a file mode counts as executable for a hook check.
|
|
28
|
+
*
|
|
29
|
+
* Windows has no POSIX execute bit: Node reports 0o666 for every regular file
|
|
30
|
+
* that is not a .exe/.cmd/.bat/.com, and the hook runtimes start HQ's shell
|
|
31
|
+
* hooks through bash, which never consults it. A mode check there can only
|
|
32
|
+
* produce false FAILs (feedback_a60339e8, 27 of them on one install), so
|
|
33
|
+
* win32 treats every present file as executable.
|
|
34
|
+
*/
|
|
35
|
+
export function modeIsExecutable(mode, platform = process.platform) {
|
|
36
|
+
if (platform === "win32")
|
|
37
|
+
return true;
|
|
38
|
+
return (mode & 0o111) !== 0;
|
|
39
|
+
}
|
|
40
|
+
export function fileState(target, platform = process.platform) {
|
|
27
41
|
try {
|
|
28
42
|
const stat = fs.statSync(target);
|
|
29
|
-
return { present: stat.isFile(), executable: (stat.mode
|
|
43
|
+
return { present: stat.isFile(), executable: modeIsExecutable(stat.mode, platform) };
|
|
30
44
|
}
|
|
31
45
|
catch {
|
|
32
46
|
return { present: false, executable: false };
|