@indigoai-us/hq-cli 5.188.1 → 5.189.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,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.189.0] — 2026-09-25
6
+
7
+ ### Added
8
+
9
+ - `hq lanes resume` and `hq lanes message` accept `--effort <level>` for the next resumed provider turn. Attaching a worker profile applies its configured effort when the command has no effort flag. With neither option, the lane keeps its recorded effort. Outpost commands forward the flag and report `outpost_effort_unsupported` when the remote CLI rejects it.
10
+
5
11
  ## [5.188.1] — 2026-09-25
6
12
 
7
13
  ### Fixed
@@ -7345,6 +7345,9 @@ export declare const COMMAND_CATALOG: readonly [{
7345
7345
  }, {
7346
7346
  readonly flags: "--model <id>";
7347
7347
  readonly description: "Model for the moved lane (with --account only)";
7348
+ }, {
7349
+ readonly flags: "--effort <level>";
7350
+ readonly description: "Reasoning effort for the resumed provider turn";
7348
7351
  }, {
7349
7352
  readonly flags: "--worker <profile>";
7350
7353
  readonly description: "Attach a personal worker profile when this message resumes the lane";
@@ -7382,6 +7385,9 @@ export declare const COMMAND_CATALOG: readonly [{
7382
7385
  }, {
7383
7386
  readonly flags: "--model <id>";
7384
7387
  readonly description: "Model for the moved lane (with --account only)";
7388
+ }, {
7389
+ readonly flags: "--effort <level>";
7390
+ readonly description: "Reasoning effort for the resumed provider turn";
7385
7391
  }, {
7386
7392
  readonly flags: "--worker <profile>";
7387
7393
  readonly description: "Attach a personal worker profile for the resumed turn";
@@ -9496,6 +9496,10 @@ export const COMMAND_CATALOG = [
9496
9496
  "flags": "--model <id>",
9497
9497
  "description": "Model for the moved lane (with --account only)"
9498
9498
  },
9499
+ {
9500
+ "flags": "--effort <level>",
9501
+ "description": "Reasoning effort for the resumed provider turn"
9502
+ },
9499
9503
  {
9500
9504
  "flags": "--worker <profile>",
9501
9505
  "description": "Attach a personal worker profile when this message resumes the lane"
@@ -9545,6 +9549,10 @@ export const COMMAND_CATALOG = [
9545
9549
  "flags": "--model <id>",
9546
9550
  "description": "Model for the moved lane (with --account only)"
9547
9551
  },
9552
+ {
9553
+ "flags": "--effort <level>",
9554
+ "description": "Reasoning effort for the resumed provider turn"
9555
+ },
9548
9556
  {
9549
9557
  "flags": "--worker <profile>",
9550
9558
  "description": "Attach a personal worker profile for the resumed turn"
@@ -20,7 +20,7 @@ import { createOutpostHireGrantContext, parseOutpostHireGrantContext, sameHireGr
20
20
  import { OUTPOST_DIR, OUTPOST_ID_PATH, readOutpostIdentity, resolveAdmissionHost, } from "../lib/lanes/admission-host.js";
21
21
  export { OUTPOST_DIR, OUTPOST_ID_PATH, readOutpostIdentity } from "../lib/lanes/admission-host.js";
22
22
  export { LANE_HIRE_GRANTS_FLAG };
23
- import { buildOutpostCapacityCommand, buildOutpostBalanceMoveCommand, buildOutpostIdentityBackfillCommand, buildOutpostLaneCommand, buildOutpostMoveTargetCommand, buildOutpostPickupCommand, createOutpostsClient, dispatchErrorMessage, dispatchOutpostPickup, buildOutpostLaneListCommand, parseOutpostPickupPayload, stageOutpostPayload, } from "../lib/lanes/outpost-dispatch.js";
23
+ import { buildOutpostCapacityCommand, buildOutpostBalanceMoveCommand, buildOutpostIdentityBackfillCommand, buildOutpostLaneCommand, buildOutpostMoveTargetCommand, buildOutpostPickupCommand, createOutpostsClient, dispatchErrorMessage, dispatchOutpostPickup, buildOutpostLaneListCommand, outpostRejectedEffortOption, parseOutpostPickupPayload, stageOutpostPayload, } from "../lib/lanes/outpost-dispatch.js";
24
24
  import { buildHostCapacitySnapshot, chooseHostForLane, parseHostCapacitySnapshot, } from "../lib/lanes/host-capacity.js";
25
25
  import { BALANCE_MOVABLE_STATES, CLAUDE_ACCOUNT_BALANCE_FLAG, accountLoadsForReport, assertBalanceApplyEnabled, planClaudeBalanceMoves, selectClaudeAccount, } from "../lib/lanes/claude-account-balance.js";
26
26
  import { parseUserYaml } from "../utils/user-yaml-error.js";
@@ -34,7 +34,7 @@ import { activeLaneStories, laneStories, laneStory, storyWarning, } from "../lib
34
34
  import { questionBodyAbsPath } from "../lib/lanes/questions.js";
35
35
  import { compactionAfterUsage, } from "../lib/lanes/compaction.js";
36
36
  import { providerCompactAfterMs } from "../lib/lanes/config.js";
37
- import { parseCliEffort, resolveLaneEffort } from "../lib/lanes/effort.js";
37
+ import { parseCliEffort, resolveLaneEffort, } from "../lib/lanes/effort.js";
38
38
  import { LanesError } from "../lib/lanes/errors.js";
39
39
  import { accountQuotaView, loadQuotaState, quotaBlockFor } from "../lib/lanes/quota.js";
40
40
  import { SESSION_MOVE_REASON } from "../lib/lanes/move-account.js";
@@ -3100,6 +3100,8 @@ async function dispatchOutpostLaneCommand(ctx, lane, action, options) {
3100
3100
  story: options.story,
3101
3101
  account: options.account,
3102
3102
  model: options.model,
3103
+ effort: options.effort,
3104
+ worker: options.worker,
3103
3105
  hire: options.hire,
3104
3106
  grantContext,
3105
3107
  compact: options.compact,
@@ -3110,6 +3112,18 @@ async function dispatchOutpostLaneCommand(ctx, lane, action, options) {
3110
3112
  throw new LanesError("outpost_dispatch_failed", `Could not dispatch ${action} for lane ${lane.lane_id} to Outpost ${outpostId}: ${dispatchErrorMessage(err)}`, { lane_id: lane.lane_id, outpost_id: outpostId });
3111
3113
  }
3112
3114
  const ownerError = ownerErrorFromOutput(dispatched.stdout);
3115
+ if (options.effort !== undefined && outpostRejectedEffortOption(dispatched)) {
3116
+ throw new LanesError("outpost_effort_unsupported", `Outpost ${outpostId} rejected --effort; update hq-cli on that Outpost before changing a lane's effort remotely`, {
3117
+ lane_id: lane.lane_id,
3118
+ outpost_id: outpostId,
3119
+ command_id: dispatched.commandId,
3120
+ effort: options.effort,
3121
+ status: dispatched.status,
3122
+ done: dispatched.done ?? false,
3123
+ exit_code: dispatched.exitCode,
3124
+ owner_error: ownerError,
3125
+ });
3126
+ }
3113
3127
  if (ownerError) {
3114
3128
  throw new LanesError("outpost_dispatch_failed", `Outpost ${outpostId} rejected the ${action} command: ${ownerError.message}`, {
3115
3129
  lane_id: lane.lane_id,
@@ -4336,34 +4350,43 @@ function validateResumeProfileModel(ctx, lane, profile) {
4336
4350
  env: ctx.env,
4337
4351
  });
4338
4352
  }
4353
+ function applyResumeProfileAndEffort(current, next, input) {
4354
+ if (input.profile !== undefined) {
4355
+ const profile = input.profile.profile;
4356
+ next.worker = input.profile.id;
4357
+ next.worker_path = input.profile.path;
4358
+ next.worker_pack = input.profile.pack;
4359
+ next.worker_profile = profile.id;
4360
+ next.worker_profile_hash = profile.contentHash;
4361
+ next.worker_profile_ignored = ignoredWorkerProfileFields(current.provider);
4362
+ next.worker_policy_delivery = undefined;
4363
+ if (next.model_source !== "cli") {
4364
+ if (profile.meta.provider === current.provider && profile.meta.model !== undefined) {
4365
+ next.model = profile.meta.model;
4366
+ next.model_source = "profile";
4367
+ }
4368
+ else if (profile.meta.provider === current.provider) {
4369
+ next.model = undefined;
4370
+ next.model_source = "none";
4371
+ }
4372
+ }
4373
+ }
4374
+ if (input.effort !== undefined) {
4375
+ next.effort = input.effort.effort;
4376
+ next.effort_source = input.effort.source;
4377
+ }
4378
+ }
4339
4379
  function recordResumeSetup(ctx, lane, input) {
4340
- if (input.profile === undefined && input.meshCompany === undefined)
4380
+ if (input.profile === undefined &&
4381
+ input.effort === undefined &&
4382
+ input.meshCompany === undefined)
4341
4383
  return lane;
4342
4384
  return casUpdateLane(ctx.hqRoot(), lane.lane_id, (current) => {
4343
4385
  if (current.version !== lane.version) {
4344
4386
  throw new LanesError("lane_resume_setup_conflict", `Lane ${lane.lane_id} changed while resume settings were prepared; run the resume again`, { lane_id: lane.lane_id, prepared_version: lane.version, version: current.version });
4345
4387
  }
4346
4388
  const next = { ...current };
4347
- if (input.profile !== undefined) {
4348
- const profile = input.profile.profile;
4349
- next.worker = input.profile.id;
4350
- next.worker_path = input.profile.path;
4351
- next.worker_pack = input.profile.pack;
4352
- next.worker_profile = profile.id;
4353
- next.worker_profile_hash = profile.contentHash;
4354
- next.worker_profile_ignored = ignoredWorkerProfileFields(current.provider);
4355
- next.worker_policy_delivery = undefined;
4356
- if (current.model_source !== "cli") {
4357
- if (profile.meta.provider === current.provider && profile.meta.model !== undefined) {
4358
- next.model = profile.meta.model;
4359
- next.model_source = "profile";
4360
- }
4361
- else if (profile.meta.provider === current.provider) {
4362
- next.model = undefined;
4363
- next.model_source = "none";
4364
- }
4365
- }
4366
- }
4389
+ applyResumeProfileAndEffort(current, next, input);
4367
4390
  if (input.meshCompany !== undefined) {
4368
4391
  if (current.company === null)
4369
4392
  next.mesh_company = input.meshCompany;
@@ -4373,6 +4396,40 @@ function recordResumeSetup(ctx, lane, input) {
4373
4396
  return next;
4374
4397
  });
4375
4398
  }
4399
+ /** Resolve an explicit resume override or newly attached profile like create does. */
4400
+ function resolveResumeEffort(ctx, lane, input) {
4401
+ if (input.cliEffort === undefined && input.profile === undefined)
4402
+ return undefined;
4403
+ const config = loadLanesConfig(ctx.hqRoot());
4404
+ const providerConfig = config.providers[lane.provider];
4405
+ const accountId = input.account?.trim() || lane.account;
4406
+ const accountConfig = accountId === undefined
4407
+ ? undefined
4408
+ : providerConfig.accounts[accountId];
4409
+ const profileDefaultsApply = input.profile?.profile.meta.provider === lane.provider;
4410
+ const pinnedModel = lane.model_source === undefined || lane.model_source === "cli"
4411
+ ? lane.model
4412
+ : undefined;
4413
+ const model = resolveLaneModel({
4414
+ cliModel: input.model?.trim() || pinnedModel,
4415
+ profileModel: profileDefaultsApply ? input.profile?.profile.meta.model : undefined,
4416
+ accountModel: accountConfig?.model,
4417
+ providerModel: providerConfig.model,
4418
+ });
4419
+ return resolveLaneEffort({
4420
+ cliEffort: input.cliEffort,
4421
+ profileEffort: profileDefaultsApply ? input.profile?.profile.meta.effort : undefined,
4422
+ accountEffort: accountConfig?.effort,
4423
+ providerEffort: providerConfig.effort,
4424
+ model,
4425
+ });
4426
+ }
4427
+ function recordedResumeEffort(lane) {
4428
+ return {
4429
+ ...(lane.effort !== undefined ? { effort: lane.effort } : {}),
4430
+ source: lane.effort_source ?? "none",
4431
+ };
4432
+ }
4376
4433
  /**
4377
4434
  * US-023: move the lane's provider session to `--account` (same provider)
4378
4435
  * before a resume or a message resume. Every check runs before anything is
@@ -4440,7 +4497,7 @@ async function prepareAccountMove(ctx, lane, input) {
4440
4497
  }).logged_in !== true) {
4441
4498
  throw new LanesError("account_not_logged_in", `Account ${target} for ${lane.provider} is not logged in (no credential file)`, { provider: lane.provider, account: target, lane_id: laneId });
4442
4499
  }
4443
- const profile = input.workerProfile ?? (lane.worker_profile !== undefined
4500
+ const profile = input.workerProfile?.profile ?? (lane.worker_profile !== undefined
4444
4501
  ? loadWorkerProfile(hqRoot, lane.worker_profile)
4445
4502
  : undefined);
4446
4503
  const profileDefaultsApply = profile !== undefined && profile.meta.provider === lane.provider;
@@ -4542,6 +4599,10 @@ async function prepareAccountMove(ctx, lane, input) {
4542
4599
  ? undefined
4543
4600
  : { session_id: sessionId, at, ...input.pending },
4544
4601
  };
4602
+ applyResumeProfileAndEffort(current, next, {
4603
+ ...(input.workerProfile !== undefined ? { profile: input.workerProfile } : {}),
4604
+ ...(input.effort !== undefined ? { effort: input.effort } : {}),
4605
+ });
4545
4606
  if (input.deferTurnStart) {
4546
4607
  next.state = current.state;
4547
4608
  }
@@ -4618,6 +4679,10 @@ async function runMessage(ctx, laneId, opts) {
4618
4679
  return;
4619
4680
  }
4620
4681
  assertLaneRunsHereForOperatorMutation(ctx, lane, "message");
4682
+ const cliEffort = parseCliEffort(lane.provider, opts.effort);
4683
+ if (cliEffort !== undefined && !providerSupportsSessionResume(lane.provider)) {
4684
+ throw new LanesError("effort_resume_unsupported", `Provider ${lane.provider} cannot change effort on a resumed session`, { lane_id: laneId, provider: lane.provider });
4685
+ }
4621
4686
  // Check before transcript recovery, account probing, or message writes.
4622
4687
  // The final state transition repeats this check under the senior lock.
4623
4688
  await withResumeHireAdmission(ctx, lane, () => undefined);
@@ -4649,12 +4714,24 @@ async function runMessage(ctx, laneId, opts) {
4649
4714
  if (opts.worker !== undefined && mechanism === "dropbox") {
4650
4715
  throw new LanesError("worker_profile_requires_resume", `Lane ${laneId} is still running; --worker can only be applied when message starts a resumed provider turn`, { lane_id: laneId, state: lane.state });
4651
4716
  }
4717
+ if (cliEffort !== undefined && mechanism === "dropbox") {
4718
+ throw new LanesError("lane_effort_requires_resume", `Lane ${laneId} is still running; --effort can only be applied when message starts a resumed provider turn`, { lane_id: laneId, state: lane.state });
4719
+ }
4652
4720
  const resumeProfile = opts.worker !== undefined
4653
4721
  ? resolveResumeProfile(ctx, lane, opts.worker)
4654
4722
  : undefined;
4655
4723
  if (opts.model !== undefined && opts.account === undefined) {
4656
4724
  throw new LanesError("model_requires_account", "--model on hq lanes message is only accepted together with --account", {});
4657
4725
  }
4726
+ const automaticAccountSelection = opts.account === undefined && mechanism === "resume"
4727
+ ? await selectAutomaticClaudeResumeAccount(ctx, lane)
4728
+ : undefined;
4729
+ const resumeEffort = resolveResumeEffort(ctx, lane, {
4730
+ cliEffort,
4731
+ profile: resumeProfile,
4732
+ account: opts.account ?? automaticAccountSelection?.account,
4733
+ model: opts.model,
4734
+ });
4658
4735
  const messageId = mintMessageId();
4659
4736
  const at = ctx.now().toISOString();
4660
4737
  const projectId = opts.project?.trim() || lane.project_id;
@@ -4675,7 +4752,8 @@ async function runMessage(ctx, laneId, opts) {
4675
4752
  move = await prepareAccountMove(ctx, lane, {
4676
4753
  account: opts.account,
4677
4754
  cliModel: opts.model?.trim() || undefined,
4678
- ...(resumeProfile !== undefined ? { workerProfile: resumeProfile.profile } : {}),
4755
+ ...(resumeProfile !== undefined ? { workerProfile: resumeProfile } : {}),
4756
+ ...(resumeEffort !== undefined ? { effort: resumeEffort } : {}),
4679
4757
  pending: { trigger: "message", text, message_id: messageId, compact: opts.compact !== false },
4680
4758
  });
4681
4759
  lane = move.lane;
@@ -4684,13 +4762,14 @@ async function runMessage(ctx, laneId, opts) {
4684
4762
  }
4685
4763
  }
4686
4764
  else if (mechanism === "resume") {
4687
- const selection = await selectAutomaticClaudeResumeAccount(ctx, lane);
4765
+ const selection = automaticAccountSelection;
4688
4766
  if (selection !== undefined) {
4689
4767
  if (selection.account !== lane.account) {
4690
4768
  move = await prepareAccountMove(ctx, lane, {
4691
4769
  account: selection.account,
4692
4770
  cliModel: undefined,
4693
- ...(resumeProfile !== undefined ? { workerProfile: resumeProfile.profile } : {}),
4771
+ ...(resumeProfile !== undefined ? { workerProfile: resumeProfile } : {}),
4772
+ ...(resumeEffort !== undefined ? { effort: resumeEffort } : {}),
4694
4773
  pending: {
4695
4774
  trigger: "message",
4696
4775
  text,
@@ -4708,10 +4787,14 @@ async function runMessage(ctx, laneId, opts) {
4708
4787
  }
4709
4788
  }
4710
4789
  }
4711
- if (resumeProfile !== undefined) {
4712
- if (opts.account === undefined)
4713
- validateResumeProfileModel(ctx, lane, resumeProfile.profile);
4714
- lane = recordResumeSetup(ctx, lane, { profile: resumeProfile });
4790
+ if (resumeProfile !== undefined && opts.account === undefined) {
4791
+ validateResumeProfileModel(ctx, lane, resumeProfile.profile);
4792
+ }
4793
+ if (move === null && (resumeProfile !== undefined || resumeEffort !== undefined)) {
4794
+ lane = recordResumeSetup(ctx, lane, {
4795
+ ...(resumeProfile !== undefined ? { profile: resumeProfile } : {}),
4796
+ ...(resumeEffort !== undefined ? { effort: resumeEffort } : {}),
4797
+ });
4715
4798
  }
4716
4799
  if (move?.queued) {
4717
4800
  // Parked at the target's cap: reconcile resumes the session there.
@@ -4785,6 +4868,7 @@ async function runMessage(ctx, laneId, opts) {
4785
4868
  }, {
4786
4869
  trigger: { kind: "message", text, message_id: messageId },
4787
4870
  compact: opts.compact !== false,
4871
+ effort: resumeEffort ?? recordedResumeEffort(lane),
4788
4872
  });
4789
4873
  archiveResumeMessage(hqRoot, laneId, dropboxMessage);
4790
4874
  return started;
@@ -5071,6 +5155,10 @@ async function runResume(ctx, laneId, opts) {
5071
5155
  // slot that its senior has already assigned elsewhere.
5072
5156
  await withResumeHireAdmission(ctx, lane, () => undefined);
5073
5157
  assertLaneRunsHereForOperatorMutation(ctx, lane, "resume");
5158
+ const cliEffort = parseCliEffort(lane.provider, opts.effort);
5159
+ if (cliEffort !== undefined && !providerSupportsSessionResume(lane.provider)) {
5160
+ throw new LanesError("effort_resume_unsupported", `Provider ${lane.provider} cannot change effort on a resumed session`, { lane_id: laneId, provider: lane.provider });
5161
+ }
5074
5162
  lane = laneWithRecoveredProviderSession(hqRoot, lane);
5075
5163
  if (opts.model !== undefined && opts.account === undefined) {
5076
5164
  throw new LanesError("model_requires_account", "--model on hq lanes resume is only accepted together with --account", {});
@@ -5127,12 +5215,19 @@ async function runResume(ctx, laneId, opts) {
5127
5215
  const automaticAccountSelection = opts.account === undefined
5128
5216
  ? await selectAutomaticClaudeResumeAccount(ctx, lane)
5129
5217
  : undefined;
5218
+ const resumeEffort = resolveResumeEffort(ctx, lane, {
5219
+ cliEffort,
5220
+ profile: resumeProfile,
5221
+ account: opts.account ?? automaticAccountSelection?.account,
5222
+ model: opts.model,
5223
+ });
5130
5224
  let move = null;
5131
5225
  if (opts.account !== undefined) {
5132
5226
  move = await prepareAccountMove(ctx, lane, {
5133
5227
  account: opts.account,
5134
5228
  cliModel: opts.model?.trim() || undefined,
5135
- ...(resumeProfile !== undefined ? { workerProfile: resumeProfile.profile } : {}),
5229
+ ...(resumeProfile !== undefined ? { workerProfile: resumeProfile } : {}),
5230
+ ...(resumeEffort !== undefined ? { effort: resumeEffort } : {}),
5136
5231
  pending: {
5137
5232
  trigger: "resume",
5138
5233
  resumed_from: resumedFrom,
@@ -5148,7 +5243,8 @@ async function runResume(ctx, laneId, opts) {
5148
5243
  move = await prepareAccountMove(ctx, lane, {
5149
5244
  account: automaticAccountSelection.account,
5150
5245
  cliModel: undefined,
5151
- ...(resumeProfile !== undefined ? { workerProfile: resumeProfile.profile } : {}),
5246
+ ...(resumeProfile !== undefined ? { workerProfile: resumeProfile } : {}),
5247
+ ...(resumeEffort !== undefined ? { effort: resumeEffort } : {}),
5152
5248
  pending: {
5153
5249
  trigger: "resume",
5154
5250
  resumed_from: resumedFrom,
@@ -5165,7 +5261,8 @@ async function runResume(ctx, laneId, opts) {
5165
5261
  }
5166
5262
  }
5167
5263
  lane = recordResumeSetup(ctx, lane, {
5168
- ...(resumeProfile !== undefined ? { profile: resumeProfile } : {}),
5264
+ ...(move === null && resumeProfile !== undefined ? { profile: resumeProfile } : {}),
5265
+ ...(move === null && resumeEffort !== undefined ? { effort: resumeEffort } : {}),
5169
5266
  ...(requestedMeshCompany !== undefined
5170
5267
  ? { meshCompany: requestedMeshCompany, threadId: meshThreadId }
5171
5268
  : {}),
@@ -5239,6 +5336,7 @@ async function runResume(ctx, laneId, opts) {
5239
5336
  ...(messageId !== undefined ? { message_id: messageId } : {}),
5240
5337
  },
5241
5338
  compact: opts.compact !== false,
5339
+ effort: resumeEffort ?? recordedResumeEffort(lane),
5242
5340
  });
5243
5341
  });
5244
5342
  }, ctx.sleep);
@@ -7049,6 +7147,7 @@ export function registerLanesCommand(parent, deps = {}) {
7049
7147
  .option("--story <id>", "Re-point story attribution from this message")
7050
7148
  .option("--account <id>", "Move the lane's session to this account of its provider before the message resumes it")
7051
7149
  .option("--model <id>", "Model for the moved lane (with --account only)")
7150
+ .option("--effort <level>", "Reasoning effort for the resumed provider turn")
7052
7151
  .option("--worker <profile>", "Attach a personal worker profile when this message resumes the lane")
7053
7152
  .option("--no-compact", "Skip the resume-time compaction check for this message")
7054
7153
  .action(wrap(async (laneId, opts) => {
@@ -7063,6 +7162,7 @@ export function registerLanesCommand(parent, deps = {}) {
7063
7162
  .option("--story <id>", "Re-point story attribution from this resume")
7064
7163
  .option("--account <id>", "Move the lane's session to this account of its provider before resuming")
7065
7164
  .option("--model <id>", "Model for the moved lane (with --account only)")
7165
+ .option("--effort <level>", "Reasoning effort for the resumed provider turn")
7066
7166
  .option("--worker <profile>", "Attach a personal worker profile for the resumed turn")
7067
7167
  .option("--mesh-company <slug>", "Attach Work Mesh attribution after verifying company membership")
7068
7168
  .option("--no-compact", "Skip the resume-time compaction check for this resume")
@@ -35,6 +35,8 @@ export interface OutpostLaneCommand {
35
35
  story?: string;
36
36
  account?: string;
37
37
  model?: string;
38
+ effort?: string;
39
+ worker?: string;
38
40
  hire?: string;
39
41
  grantContext?: string;
40
42
  compact?: boolean;
@@ -81,6 +83,8 @@ export declare function buildOutpostBalanceMoveCommand(input: {
81
83
  export declare function buildOutpostIdentityBackfillCommand(expectedId: string): string;
82
84
  /** Build the same `hq outposts exec` remote command used by lane pickup. */
83
85
  export declare function buildOutpostLaneCommand(input: OutpostLaneCommand): string;
86
+ /** True when a remote CLI exited after rejecting the forwarded effort flag. */
87
+ export declare function outpostRejectedEffortOption(result: Pick<OutpostDispatchResult, "exitCode" | "stdout" | "stderr">): boolean;
84
88
  export declare function stageOutpostPayload(port: Pick<OutpostExecPort, "stageExecInput">, outpostId: string, bytes: Uint8Array, put?: typeof fetch): Promise<{
85
89
  getUrl: string;
86
90
  }>;
@@ -104,6 +104,8 @@ export function buildOutpostLaneCommand(input) {
104
104
  ["--story", input.story],
105
105
  ["--account", input.account],
106
106
  ["--model", input.model],
107
+ ["--effort", input.effort],
108
+ ["--worker", input.worker],
107
109
  ["--hire", input.hire],
108
110
  ["--grant-context", input.grantContext],
109
111
  ]) {
@@ -114,6 +116,12 @@ export function buildOutpostLaneCommand(input) {
114
116
  args.push("--no-compact");
115
117
  return withRemoteHqDir(joinCommandParts(args));
116
118
  }
119
+ /** True when a remote CLI exited after rejecting the forwarded effort flag. */
120
+ export function outpostRejectedEffortOption(result) {
121
+ if (result.exitCode === 0)
122
+ return false;
123
+ return /(?:unknown|unrecognized) option[^\n]{0,120}--effort/i.test(`${result.stderr}\n${result.stdout}`);
124
+ }
117
125
  export async function stageOutpostPayload(port, outpostId, bytes, put = fetch) {
118
126
  const staged = await port.stageExecInput(outpostId);
119
127
  const upload = await put(staged.putUrl, {
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import { PROVIDER_HOME_ENV } from "./accounts.js";
11
11
  import { type RunCompactionFn } from "./compaction.js";
12
+ import { type ResolvedEffort } from "./effort.js";
12
13
  import { type KnownModelsDeps } from "./models.js";
13
14
  import { type LaunchTrigger } from "./delivery.js";
14
15
  import { type MachineIdentity } from "./machine-identity.js";
@@ -283,6 +284,8 @@ export interface SpawnLaunchOptions {
283
284
  * (`hq lanes message --no-compact`). Default true.
284
285
  */
285
286
  compact?: boolean;
287
+ /** Effort resolved by an explicit resume/message request, or pinned from its record. */
288
+ effort?: ResolvedEffort;
286
289
  }
287
290
  /**
288
291
  * Bind the account, spawn the worker and its watcher outside the caller's
@@ -15,7 +15,7 @@ import { PROVIDER_HOME_ENV, accountStatus, isLoggedOut, resolveAccount, selectBa
15
15
  import { COMPACTION_PROMPT, compactionAfterUsage, compactionDue, compactLaneSession, } from "./compaction.js";
16
16
  import { installDrainHook } from "./hooks-install.js";
17
17
  import { loadLanesConfig, providerAutoCompactTokens, providerCompactAfterMs, } from "./config.js";
18
- import { appendEffortFlag, resolveLaneEffort } from "./effort.js";
18
+ import { appendEffortFlag, resolveLaneEffort, } from "./effort.js";
19
19
  import { defaultProbe, validateLaneModel, validateProfileLaneModel, } from "./models.js";
20
20
  import { claimableStatesFor, planLaneLaunch, providerSupportsSessionResume, } from "./delivery.js";
21
21
  import { AccountResolutionError, LanesError } from "./errors.js";
@@ -1719,7 +1719,13 @@ export function spawnLaneWorker(hqRoot, lane, deps = {}, launch = {}) {
1719
1719
  accountModel: accountCfg?.model,
1720
1720
  providerModel: config.providers[lane.provider].model,
1721
1721
  });
1722
- const effort = resolveLaneEffort({
1722
+ const pendingResumeEffort = pendingResume !== undefined
1723
+ ? {
1724
+ ...(existing.effort !== undefined ? { effort: existing.effort } : {}),
1725
+ source: existing.effort_source ?? "none",
1726
+ }
1727
+ : undefined;
1728
+ const effort = launch.effort ?? pendingResumeEffort ?? resolveLaneEffort({
1723
1729
  cliEffort: existing.effort_source === "cli" ? existing.effort : undefined,
1724
1730
  profileEffort,
1725
1731
  accountEffort: accountCfg?.effort,
@@ -226,7 +226,7 @@ export const LANE_FIELD_WRITERS = {
226
226
  priority: ["command"], worker: ["creator", "command"], worker_path: ["creator", "command"], worker_pack: ["creator", "command"], worker_profile: ["creator", "command"], worker_profile_hash: ["creator", "command", "spawn"], worker_profile_ignored: ["creator", "command", "spawn"], worker_policy_delivery: ["command", "spawn"],
227
227
  provider: ["creator"], account: ["creator", "spawn", "command", "watcher", "reconcile"], account_selection: ["creator", "command"], admission_accounts: ["creator", "command"], account_history: ["command", "spawn", "watcher", "reconcile"], pending_resume: ["command", "spawn", "watcher", "reconcile"], placement_default: ["creator"], host: ["creator", "command"], origin_host: ["creator"], origin_host_source: ["creator"],
228
228
  version: ["creator"], created_at: ["creator"], updated_at: ["creator"], attribution_history: ["command"],
229
- last_envelope: ["watcher", "reconcile"], model: ["creator", "spawn", "command"], model_source: ["creator", "spawn", "command"], effort: ["creator", "spawn"], effort_source: ["creator", "spawn"], fast_mode: ["spawn"],
229
+ last_envelope: ["watcher", "reconcile"], model: ["creator", "spawn", "command"], model_source: ["creator", "spawn", "command"], effort: ["creator", "spawn", "command"], effort_source: ["creator", "spawn", "command"], fast_mode: ["spawn"],
230
230
  last_message_at: ["command"], last_compaction: ["spawn"], story_complete: ["watcher", "reconcile"], story_complete_reason: ["watcher", "reconcile"], story_status: ["watcher", "reconcile"],
231
231
  overdue: ["reconcile"], overdue_at: ["reconcile"], last_host_report_at: ["watcher", "spawn", "reconcile"], stalled: ["watcher"], stalled_at: ["watcher"], stalled_reason: ["watcher"],
232
232
  admitted_reason: ["command", "reconcile"], terminal_reason: ["command", "watcher", "spawn", "reconcile"], terminal_details: ["command", "spawn", "watcher", "reconcile"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.188.1",
3
+ "version": "5.189.0",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {