@indigoai-us/hq-cli 5.269.0 → 5.271.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,34 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.271.0] — 2026-09-28
6
+
7
+ ### Fixed
8
+
9
+ - `hq lanes create --outpost` reads `lanes.outpost-load-balancing` for the
10
+ resolved company, so enabled personal worker profiles can run on an Outpost.
11
+ - Resolve host-suffixed lanes created on a registered Outpost for grant,
12
+ message, and resume commands while keeping senior authorization on the primary.
13
+ - `hq lanes move-target` keeps the company placement gate, and unfiltered
14
+ `hq lanes list` resolves the active company for host capacity.
15
+
16
+ ## [5.270.0] — 2026-09-28
17
+
18
+ ### Fixed
19
+
20
+ - Company billing links in CLI plan-limit notices no longer depend on the
21
+ rollout flag.
22
+
23
+ ### Removed
24
+
25
+ - Removed stale gate language from hire-grant command help. Enforcement remains
26
+ unconditional; backfill remains dry-run only.
27
+
28
+ ### Fixed
29
+
30
+ - `hq files unshare --with` now accepts the same person UID principals as direct grants.
31
+ - The update gate no longer retries failed Windows installs through `sudo -n`.
32
+
5
33
  ## [5.269.0] — 2026-09-28
6
34
 
7
35
  ### Fixed
@@ -334,6 +362,10 @@
334
362
  - Removed the unused `cli.network.force-ipv4` hq-flags lookup and forced IPv4
335
363
  startup path. The existing Node family-attempt timeout remains unchanged.
336
364
  - `hq auth login` continues when it cannot read or save the remembered provider. It prints a dim warning with the state path and error code; a save failure does not turn a successful sign-in into a login failure.
365
+ - `hq doctor`, client health metadata, and feedback attachments now use the
366
+ newest sync-log source from the desktop app or configured daemon directory.
367
+ Daemon `HQ_DAEMON_DIR` overrides and log rotations are supported, and
368
+ numeric runner error levels count in health metadata.
337
369
 
338
370
  ## [5.242.0] — 2026-09-27
339
371
 
@@ -1701,7 +1701,7 @@ export declare const COMMAND_CATALOG: readonly [{
1701
1701
  }];
1702
1702
  readonly options: readonly [{
1703
1703
  readonly flags: "--with <principal>";
1704
- readonly description: "Email address, group id, or '@all' to remove the company-wide grant";
1704
+ readonly description: "Person uid, email address, group id, or '@all' to remove the grant";
1705
1705
  }];
1706
1706
  readonly subcommands: readonly [];
1707
1707
  }, {
@@ -7755,7 +7755,7 @@ export declare const COMMAND_CATALOG: readonly [{
7755
7755
  readonly description: "Non-negative safe integer hire grant";
7756
7756
  }, {
7757
7757
  readonly flags: "--grant-context <base64url>";
7758
- readonly description: "Primary-authorized hire hierarchy and gate decision";
7758
+ readonly description: "Primary-authorized hire hierarchy context";
7759
7759
  }, {
7760
7760
  readonly flags: "--json";
7761
7761
  readonly description: "JSON on stdout (always)";
@@ -7800,6 +7800,9 @@ export declare const COMMAND_CATALOG: readonly [{
7800
7800
  readonly options: readonly [{
7801
7801
  readonly flags: "--hire <n>";
7802
7802
  readonly description: "Non-negative safe integer hire grant";
7803
+ }, {
7804
+ readonly flags: "--outpost <id>";
7805
+ readonly description: "Confirm the registered Outpost hosting a native lane";
7803
7806
  }, {
7804
7807
  readonly flags: "--json";
7805
7808
  readonly description: "JSON on stdout (always)";
@@ -7807,7 +7810,7 @@ export declare const COMMAND_CATALOG: readonly [{
7807
7810
  readonly subcommands: readonly [];
7808
7811
  }, {
7809
7812
  readonly name: "backfill-grants";
7810
- readonly description: "Preview or apply missing hire grants for alive manager lanes";
7813
+ readonly description: "Preview missing hire grants for alive manager lanes; writes are disabled";
7811
7814
  readonly aliases: readonly [];
7812
7815
  readonly hidden: false;
7813
7816
  readonly usage: "[options]";
@@ -7817,7 +7820,7 @@ export declare const COMMAND_CATALOG: readonly [{
7817
7820
  readonly description: "Print proposed values without writing (default)";
7818
7821
  }, {
7819
7822
  readonly flags: "--apply";
7820
- readonly description: "Write missing hire grants; only run before enforcement is enabled";
7823
+ readonly description: "Retained for compatibility; writes are disabled";
7821
7824
  }, {
7822
7825
  readonly flags: "--json";
7823
7826
  readonly description: "JSON on stdout (always)";
@@ -2170,7 +2170,7 @@ export const COMMAND_CATALOG = [
2170
2170
  "options": [
2171
2171
  {
2172
2172
  "flags": "--with <principal>",
2173
- "description": "Email address, group id, or '@all' to remove the company-wide grant"
2173
+ "description": "Person uid, email address, group id, or '@all' to remove the grant"
2174
2174
  }
2175
2175
  ],
2176
2176
  "subcommands": []
@@ -10026,7 +10026,7 @@ export const COMMAND_CATALOG = [
10026
10026
  },
10027
10027
  {
10028
10028
  "flags": "--grant-context <base64url>",
10029
- "description": "Primary-authorized hire hierarchy and gate decision"
10029
+ "description": "Primary-authorized hire hierarchy context"
10030
10030
  },
10031
10031
  {
10032
10032
  "flags": "--json",
@@ -10086,6 +10086,10 @@ export const COMMAND_CATALOG = [
10086
10086
  "flags": "--hire <n>",
10087
10087
  "description": "Non-negative safe integer hire grant"
10088
10088
  },
10089
+ {
10090
+ "flags": "--outpost <id>",
10091
+ "description": "Confirm the registered Outpost hosting a native lane"
10092
+ },
10089
10093
  {
10090
10094
  "flags": "--json",
10091
10095
  "description": "JSON on stdout (always)"
@@ -10095,7 +10099,7 @@ export const COMMAND_CATALOG = [
10095
10099
  },
10096
10100
  {
10097
10101
  "name": "backfill-grants",
10098
- "description": "Preview or apply missing hire grants for alive manager lanes",
10102
+ "description": "Preview missing hire grants for alive manager lanes; writes are disabled",
10099
10103
  "aliases": [],
10100
10104
  "hidden": false,
10101
10105
  "usage": "[options]",
@@ -10107,7 +10111,7 @@ export const COMMAND_CATALOG = [
10107
10111
  },
10108
10112
  {
10109
10113
  "flags": "--apply",
10110
- "description": "Write missing hire grants; only run before enforcement is enabled"
10114
+ "description": "Retained for compatibility; writes are disabled"
10111
10115
  },
10112
10116
  {
10113
10117
  "flags": "--json",
@@ -262,7 +262,7 @@ export function registerFilesCommand(program) {
262
262
  files
263
263
  .command("unshare <prefix>")
264
264
  .description("Remove a file access grant. A trailing slash targets the private-folder row exactly.")
265
- .requiredOption("--with <principal>", "Email address, group id, or '@all' to remove the company-wide grant")
265
+ .requiredOption("--with <principal>", "Person uid, email address, group id, or '@all' to remove the grant")
266
266
  .action(async (prefix, opts) => {
267
267
  try {
268
268
  // Unshare MUTATES access with no preview, and it resolves the target
@@ -278,7 +278,8 @@ export function registerFilesCommand(program) {
278
278
  const isAll = principal === "@all";
279
279
  const isEmail = !isAll && EMAIL_PATTERN.test(principal);
280
280
  const isGroup = !isAll && GROUP_ID_PATTERN.test(principal);
281
- if (!isAll && !isEmail && !isGroup) {
281
+ const isPerson = !isAll && !isEmail && !isGroup && PERSON_UID_PATTERN.test(principal);
282
+ if (!isAll && !isEmail && !isGroup && !isPerson) {
282
283
  console.error(chalk.red(`Invalid principal '${principal}': must be '@all', an email address, or a group id matching grp_<alphanumeric>`));
283
284
  process.exit(1);
284
285
  }
@@ -286,7 +287,9 @@ export function registerFilesCommand(program) {
286
287
  ? "company-wide"
287
288
  : isEmail
288
289
  ? "email"
289
- : "group";
290
+ : isGroup
291
+ ? "group"
292
+ : "person";
290
293
  const granteeId = isAll
291
294
  ? ""
292
295
  : isEmail
@@ -65,9 +65,12 @@ export function createLaneMessageHandlers(deps) {
65
65
  if (!text) {
66
66
  throw new LanesError("missing_text", "--text is required", {});
67
67
  }
68
- let lane = readLane(hqRoot, laneId);
69
- if (lane.host.kind === "outpost" && !laneIsHostedHere(ctx, lane)) {
70
- await dispatchOutpostLaneCommand(ctx, lane, "message", opts);
68
+ const resolution = await deps.resolveCommandLane(ctx, laneId);
69
+ let lane = resolution.lane;
70
+ if (resolution.remoteOnly || (lane.host.kind === "outpost" && !laneIsHostedHere(ctx, lane))) {
71
+ await dispatchOutpostLaneCommand(ctx, lane, "message", opts, resolution.remoteOnly
72
+ ? { syncPrimary: false, expectedOwnerHost: resolution.ownerHost }
73
+ : undefined);
71
74
  return;
72
75
  }
73
76
  assertLaneRunsHereForOperatorMutation(ctx, lane, "message");
@@ -86,7 +86,8 @@ export function createLaneResumeHandlers(deps) {
86
86
  */
87
87
  async function runResume(ctx, laneId, opts) {
88
88
  const hqRoot = ctx.hqRoot();
89
- let lane = readLane(hqRoot, laneId);
89
+ const resolution = await deps.resolveCommandLane(ctx, laneId);
90
+ let lane = resolution.lane;
90
91
  const failedResumeReason = opts.reason?.trim();
91
92
  if (opts.reason !== undefined && opts.fromFailed !== true) {
92
93
  throw new LanesError("failed_resume_reason_requires_flag", "--reason on hq lanes resume requires --from-failed", { lane_id: laneId });
@@ -122,9 +123,11 @@ export function createLaneResumeHandlers(deps) {
122
123
  if (opts.profileRepinContext !== undefined && !ctx.isSsmOwnerDispatch()) {
123
124
  throw new LanesError("worker_profile_hash_mismatch", "Profile re-pin context is only valid on an Outpost owner dispatch", { lane_id: laneId });
124
125
  }
125
- if (lane.host.kind === "outpost" && !laneIsHostedHere(ctx, lane)) {
126
+ if (resolution.remoteOnly || (lane.host.kind === "outpost" && !laneIsHostedHere(ctx, lane))) {
126
127
  await withResumeHireAdmission(ctx, lane, () => undefined);
127
- await dispatchOutpostLaneCommand(ctx, lane, "resume", opts);
128
+ await dispatchOutpostLaneCommand(ctx, lane, "resume", opts, resolution.remoteOnly
129
+ ? { syncPrimary: false, expectedOwnerHost: resolution.ownerHost }
130
+ : undefined);
128
131
  return;
129
132
  }
130
133
  // Fail before provider/session work if a terminal child would consume a
@@ -115,6 +115,21 @@ export declare function resolveResumeEffort(ctx: Ctx, lane: LaneRecord, input: {
115
115
  model?: string;
116
116
  }): ResolvedEffort | undefined;
117
117
  export declare function recordedResumeEffort(lane: LaneRecord): ResolvedEffort;
118
+ export type CommandLaneResolution = {
119
+ lane: LaneRecord;
120
+ remoteOnly: false;
121
+ } | {
122
+ lane: LaneRecord;
123
+ remoteOnly: true;
124
+ outpostId: string;
125
+ ownerHost: LaneRecord["host"];
126
+ };
127
+ export interface OutpostLaneDispatchBehavior {
128
+ /** Keep remote-only lanes out of the primary lane store. */
129
+ syncPrimary?: boolean;
130
+ /** Host identity returned by the remote record lookup for a remote-only lane. */
131
+ expectedOwnerHost?: LaneRecord["host"];
132
+ }
118
133
  export interface LaneMessageHandlerDeps {
119
134
  archiveResumeMessage(hqRoot: string, laneId: string, message: {
120
135
  message_id: string;
@@ -128,7 +143,7 @@ export interface LaneMessageHandlerDeps {
128
143
  alreadyQueued?: boolean;
129
144
  }): Promise<AdmissionResult>;
130
145
  casUpdateLane(hqRoot: string, laneId: string, updater: (current: LaneRecord) => LaneRecord): LaneRecord;
131
- dispatchOutpostLaneCommand(ctx: Ctx, lane: LaneRecord, action: "message" | "resume", options: LaneMessageOptions | LaneResumeOptions): Promise<void>;
146
+ dispatchOutpostLaneCommand(ctx: Ctx, lane: LaneRecord, action: "message" | "resume", options: LaneMessageOptions | LaneResumeOptions, behavior?: OutpostLaneDispatchBehavior): Promise<void>;
132
147
  drainHookStatusFor(ctx: Ctx, lane: LaneRecord): {
133
148
  registered: boolean;
134
149
  kind: string;
@@ -142,6 +157,7 @@ export interface LaneMessageHandlerDeps {
142
157
  persistClaudeAccountSelection(hqRoot: string, lane: LaneRecord, selection: LaneAccountSelection): LaneRecord;
143
158
  printJson(value: unknown): void;
144
159
  recordResumeSetup(ctx: Ctx, lane: LaneRecord, input: RecordResumeSetupInput): LaneRecord;
160
+ resolveCommandLane(ctx: Ctx, laneId: string): Promise<CommandLaneResolution>;
145
161
  resolveActiveQuestionCompany(ctx: Ctx, message?: string): Promise<LaneCompanyRef>;
146
162
  resolveResumeProfile(ctx: Ctx, lane: LaneRecord, workerId: string): ResolvedResumeProfile;
147
163
  selectAutomaticClaudeResumeAccount(ctx: Ctx, lane: LaneRecord, workerProfile?: ResolvedResumeProfile, options?: {
@@ -154,8 +170,8 @@ export interface LaneMessageHandlerDeps {
154
170
  validateResumeProfileModel(ctx: Ctx, lane: LaneRecord, profile: WorkerProfile): void;
155
171
  withResumeHireAdmission<T>(ctx: Ctx, lane: LaneRecord, fn: () => T, grantContext?: OutpostHireGrantContext): Promise<T>;
156
172
  }
157
- export interface LaneResumeHandlerDeps extends Pick<LaneMessageHandlerDeps, "archiveResumeMessage" | "assertLaneRunsHereForAdmission" | "assertLaneRunsHereForOperatorMutation" | "assessLaneAdmission" | "casUpdateLane" | "laneIsHostedHere" | "laneWithRecoveredProviderSession" | "mintMessageId" | "prepareAccountMove" | "persistClaudeAccountSelection" | "printJson" | "recordResumeSetup" | "resolveResumeProfile" | "selectAutomaticClaudeResumeAccount" | "validateResumeProfileModel" | "withResumeHireAdmission"> {
158
- dispatchOutpostLaneCommand(ctx: Ctx, lane: LaneRecord, action: "resume", options: LaneResumeOptions): Promise<void>;
173
+ export interface LaneResumeHandlerDeps extends Pick<LaneMessageHandlerDeps, "archiveResumeMessage" | "assertLaneRunsHereForAdmission" | "assertLaneRunsHereForOperatorMutation" | "assessLaneAdmission" | "casUpdateLane" | "laneIsHostedHere" | "laneWithRecoveredProviderSession" | "mintMessageId" | "prepareAccountMove" | "persistClaudeAccountSelection" | "printJson" | "recordResumeSetup" | "resolveCommandLane" | "resolveResumeProfile" | "selectAutomaticClaudeResumeAccount" | "validateResumeProfileModel" | "withResumeHireAdmission"> {
174
+ dispatchOutpostLaneCommand(ctx: Ctx, lane: LaneRecord, action: "resume", options: LaneResumeOptions, behavior?: OutpostLaneDispatchBehavior): Promise<void>;
159
175
  authorizeFailedResume(ctx: Ctx, lane: LaneRecord, encodedContext?: string): string;
160
176
  authorizeResumeProfileRepin(ctx: Ctx, lane: LaneRecord, profile: ResolvedResumeProfile | undefined, encodedContext: string | undefined): ResumeProfileRepinAuthorization | undefined;
161
177
  automaticBalanceMoveHistoryReason(ctx: Ctx, lane: LaneRecord): AccountHistoryEntry["reason"];
@@ -217,7 +233,7 @@ export interface Ctx {
217
233
  }) => Promise<OutpostDispatchResult>;
218
234
  backfillOutpostIdentity: (expectedId: string) => "created" | "unchanged";
219
235
  fetchText: (url: string) => Promise<string>;
220
- lanePlacementEnabled: () => boolean;
236
+ lanePlacementEnabled: (company: LaneCompanyRef | undefined) => Promise<boolean>;
221
237
  storyLedgerEnabled: () => boolean;
222
238
  isSsmOwnerDispatch: () => boolean;
223
239
  withGrantHireLocks: typeof withLaneHireLocks;
@@ -83,7 +83,7 @@ export interface LanesCommandDeps {
83
83
  locateTranscript?: (home: string, sessionId: string) => string | null;
84
84
  monitorEvidence?: MonitorEvidenceReader;
85
85
  /** Test seam for the default-off outpost placement rollout flag. */
86
- lanePlacementEnabled?: () => boolean;
86
+ lanePlacementEnabled?: (company: LaneCompanyRef | undefined) => Promise<boolean>;
87
87
  /** Test seam for the default-off story ledger flag. */
88
88
  storyLedgerEnabled?: () => boolean;
89
89
  /** Test seam for the SSM-only Outpost owner grant path. */