@indigoai-us/hq-cli 5.345.17 → 5.345.18

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,8 +2,9 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
- ## [5.345.17] — 2026-10-06
5
+ ## [5.345.18] — 2026-10-06
6
6
  - Git Bash forwarders now keep slash commands intact and convert file path arguments that hq needs on Windows.
7
+ - Lane placement and Claude account-balance refusals now show the requested placement, actual host, balance host when different, and the model values and sources used for an unavailable-account decision.
7
8
 
8
9
  ## [5.345.16] — 2026-10-06
9
10
  - Claude account model settings are defaults, so explicit lane models remain eligible; explicit account selections on create, resume, and message are recorded as CLI choices.
@@ -197,6 +197,7 @@ export function createLaneAccountsHandlers(deps) {
197
197
  target_host: host.capacity.host,
198
198
  error: isLanesError(err) ? err.error : "claude_account_balance_selection_failed",
199
199
  message: dispatchErrorMessage(err),
200
+ ...(isLanesError(err) ? { details: err.details } : {}),
200
201
  };
201
202
  }
202
203
  });
@@ -3472,14 +3472,20 @@ async function runCreate(ctx, opts) {
3472
3472
  const targetHost = placementBalanceHostOverride ?? placementHostOverride ?? (outpostId !== undefined
3473
3473
  ? { kind: "outpost", id: outpostId }
3474
3474
  : laneHostFromCtx(ctx));
3475
+ const actualTargetHost = placementHostOverride ?? (outpostId !== undefined
3476
+ ? { kind: "outpost", id: outpostId }
3477
+ : { kind: "local", id: ctx.hostname() });
3475
3478
  balanceTargetHost = targetHost;
3476
3479
  balanceHostLoad = await loadClaudeBalanceHostSnapshots(ctx, hqRoot, config);
3477
3480
  const selected = selectClaudeAccount({
3478
3481
  hosts: balanceHostLoad.snapshots,
3479
3482
  targetHost,
3483
+ actualTargetHost,
3484
+ requestedPlacement: placementToApply ?? null,
3480
3485
  config,
3481
3486
  quotaState: loadQuotaState(hqRoot),
3482
3487
  ...(modelToValidate !== undefined ? { model: modelToValidate } : {}),
3488
+ requestedModelSource: cliModel !== undefined ? "flag" : profileModel !== undefined ? "profile" : "default",
3483
3489
  recentUsageEnabled: await readClaudeAccountBalanceSignalsEnabled(ctx, company ?? undefined),
3484
3490
  now: ctx.now(),
3485
3491
  ...(allowedAccounts !== undefined ? { allowedAccounts } : {}),
@@ -3523,12 +3529,18 @@ async function runCreate(ctx, opts) {
3523
3529
  const hosts = balanceHostLoad.snapshots.map((host) => host.capacity.host.kind === localHost.kind && host.capacity.host.id === localHost.id
3524
3530
  ? refreshedLocal
3525
3531
  : host);
3532
+ const actualTargetHostForPersist = placementHostOverride ?? (outpostId !== undefined
3533
+ ? { kind: "outpost", id: outpostId }
3534
+ : { kind: "local", id: ctx.hostname() });
3526
3535
  const selected = selectClaudeAccount({
3527
3536
  hosts,
3528
3537
  targetHost: balanceTargetHost,
3538
+ actualTargetHost: actualTargetHostForPersist,
3539
+ requestedPlacement: placementToApply ?? null,
3529
3540
  config,
3530
3541
  quotaState: loadQuotaState(hqRoot),
3531
3542
  ...(modelToValidate !== undefined ? { model: modelToValidate } : {}),
3543
+ requestedModelSource: cliModel !== undefined ? "flag" : profileModel !== undefined ? "profile" : "default",
3532
3544
  recentUsageEnabled: await readClaudeAccountBalanceSignalsEnabled(ctx, company ?? undefined),
3533
3545
  now: ctx.now(),
3534
3546
  ...(allowedAccounts !== undefined ? { allowedAccounts } : {}),
@@ -6802,6 +6814,11 @@ async function selectAutomaticClaudeResumeAccount(ctx, lane, workerProfile, opti
6802
6814
  // Repair keeps an account-derived model pinned through the move; plain
6803
6815
  // automatic rebalancing resolves each candidate's account default itself.
6804
6816
  const selectionModel = preservedModel ?? pinnedModel ?? profileModel;
6817
+ const selectionModelSource = preservedModel !== undefined || pinnedModel !== undefined
6818
+ ? "lane"
6819
+ : profileModel !== undefined
6820
+ ? "profile"
6821
+ : "default";
6805
6822
  const model = resolveLaneModel({
6806
6823
  cliModel: pinnedModel,
6807
6824
  profileModel,
@@ -6829,11 +6846,14 @@ async function selectAutomaticClaudeResumeAccount(ctx, lane, workerProfile, opti
6829
6846
  const selectionInput = {
6830
6847
  hosts: balanceHosts.snapshots,
6831
6848
  targetHost: lane.host,
6849
+ actualTargetHost: lane.host,
6850
+ requestedPlacement: null,
6832
6851
  config,
6833
6852
  quotaState: loadQuotaState(hqRoot),
6834
6853
  recentUsageEnabled: await readClaudeAccountBalanceSignalsEnabled(ctx, lane.company ?? undefined),
6835
6854
  now: ctx.now(),
6836
6855
  ...(selectionModel !== undefined ? { model: selectionModel } : {}),
6856
+ requestedModelSource: selectionModelSource,
6837
6857
  unavailableHosts: balanceHosts.unavailableHosts,
6838
6858
  };
6839
6859
  let selected;
@@ -1,6 +1,6 @@
1
1
  import type { AuthState } from "./accounts.js";
2
2
  import type { HostCapacityAccount, HostCapacitySnapshot } from "./host-capacity.js";
3
- import type { LaneHost, LaneRecord, LanesConfig } from "./types.js";
3
+ import type { LaneHost, LanePlacementPolicy, LaneRecord, LanesConfig } from "./types.js";
4
4
  import { type QuotaState } from "./quota.js";
5
5
  export declare const BALANCE_LIVE_STATES: readonly ["running", "queued", "awaiting_input"];
6
6
  export declare const BALANCE_MOVABLE_STATES: readonly ["interrupted", "done", "awaiting_input"];
@@ -81,6 +81,10 @@ export declare function selectClaudeAccount(input: {
81
81
  recentUsageEnabled?: boolean;
82
82
  now?: Date;
83
83
  explicitAccount?: string;
84
+ requestedModelSource?: "flag" | "profile" | "lane" | "default";
85
+ requestedPlacement?: LanePlacementPolicy | null;
86
+ /** Actual host where the lane would run; targetHost may be a distinct balance host. */
87
+ actualTargetHost?: LaneHost;
84
88
  unavailableHosts?: readonly BalanceHostGap[];
85
89
  }): ClaudeAccountSelection;
86
90
  export declare function accountLoadsForReport(input: {
@@ -119,6 +119,9 @@ function targetIneligibilityReason(accountId, globalEnabled, allowedAccounts, ta
119
119
  return "login_status_unknown";
120
120
  return undefined;
121
121
  }
122
+ function configModelForAccount(config, accountId) {
123
+ return config.providers.claude.accounts[accountId]?.model;
124
+ }
122
125
  function buildLoads(input) {
123
126
  const configAccounts = input.config.providers.claude.accounts;
124
127
  const targetHost = input.target.capacity.host;
@@ -156,10 +159,16 @@ function buildLoads(input) {
156
159
  return { loads, skipped };
157
160
  }
158
161
  export function selectClaudeAccount(input) {
162
+ const actualTargetHost = input.actualTargetHost ?? input.targetHost;
163
+ const placementDetails = {
164
+ requested_placement: input.requestedPlacement ?? null,
165
+ target_host: actualTargetHost,
166
+ ...(sameHost(actualTargetHost, input.targetHost) ? {} : { balance_host: input.targetHost }),
167
+ };
159
168
  const target = input.hosts.find((host) => sameHost(host.capacity.host, input.targetHost));
160
169
  if (!target) {
161
170
  throw new LanesError("claude_account_balance_target_host_unavailable", `Cannot verify Claude accounts on target host ${input.targetHost.kind}:${input.targetHost.id}`, {
162
- target_host: input.targetHost,
171
+ ...placementDetails,
163
172
  unavailable_hosts: input.unavailableHosts ?? [],
164
173
  });
165
174
  }
@@ -170,8 +179,16 @@ export function selectClaudeAccount(input) {
170
179
  if (!selected || !selected.eligible) {
171
180
  throw new LanesError("claude_account_balance_account_unavailable", `Explicit Claude account ${JSON.stringify(input.explicitAccount)} is unavailable on ${input.targetHost.kind}:${input.targetHost.id}`, {
172
181
  account: input.explicitAccount,
173
- target_host: input.targetHost,
174
182
  reason: selected?.ineligible_reason ?? "unknown_account",
183
+ ...placementDetails,
184
+ compared: {
185
+ requested_model: input.model ?? configModelForAccount(input.config, input.explicitAccount) ?? input.config.providers.claude.model ?? null,
186
+ requested_model_source: input.requestedModelSource ?? "default",
187
+ account_model: configModelForAccount(input.config, input.explicitAccount) ?? null,
188
+ account_model_source: `personal/lanes/config.json#providers.claude.accounts.${input.explicitAccount}.model`,
189
+ host: input.targetHost,
190
+ reason: selected?.ineligible_reason ?? "unknown_account",
191
+ },
175
192
  account_reasons: skipped,
176
193
  unavailable_hosts: input.unavailableHosts ?? [],
177
194
  });
@@ -196,7 +213,7 @@ export function selectClaudeAccount(input) {
196
213
  : "";
197
214
  throw new LanesError("claude_account_balance_no_eligible_account", `No enabled, logged-in Claude account is available on ${input.targetHost.kind}:${input.targetHost.id}${unknownLoginDetail}`, {
198
215
  provider: "claude",
199
- target_host: input.targetHost,
216
+ ...placementDetails,
200
217
  account_reasons: loads.map((load) => ({
201
218
  account: load.account,
202
219
  reason: load.ineligible_reason ?? "unavailable",
@@ -334,11 +334,18 @@ function selectSpawnAccount(input) {
334
334
  const selection = selectClaudeAccount({
335
335
  hosts: [{ capacity, lanes, laneListAvailable: true }],
336
336
  targetHost: lane.host,
337
+ actualTargetHost: lane.host,
338
+ requestedPlacement: null,
337
339
  config,
338
340
  quotaState: loadQuotaState(hqRoot),
339
341
  ...((recordedModel ?? pinnedModel ?? profileModel) !== undefined
340
342
  ? { model: recordedModel ?? pinnedModel ?? profileModel }
341
343
  : {}),
344
+ requestedModelSource: recordedModel !== undefined || pinnedModel !== undefined
345
+ ? "lane"
346
+ : profileModel !== undefined
347
+ ? "profile"
348
+ : "default",
342
349
  });
343
350
  return {
344
351
  account: resolveAccount(lane.provider, selection.account, config, context),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.345.17",
3
+ "version": "5.345.18",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {