@indigoai-us/hq-cli 5.134.0 → 5.135.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,28 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.135.0] — 2026-09-23
6
+
7
+ ### Added
8
+
9
+ - Claude lanes now set Claude Code's `CLAUDE_CODE_AUTO_COMPACT_WINDOW=200000`
10
+ control on fresh launches and session resumes.
11
+ `providers.claude.auto_compact_tokens` sets a positive-integer override, and
12
+ Codex and Grok launch environments are unchanged.
13
+
14
+ - Added `hq lanes watch` for bounded state and question polling, plus
15
+ `hq lanes monitor-check` for Claude Monitor coverage with distinct exit codes
16
+ for uncovered lanes and unreadable evidence. The reminder text is available
17
+ from `hq lanes monitor-check --reminder`.
18
+ - Corrected watch JSONL output and question status transitions, bounded Monitor
19
+ recommendations to the watch limit, and made stale or unreadable Monitor
20
+ evidence fail closed.
21
+
22
+ - Lanes can opt selected Codex model ids into fast mode with
23
+ `providers.codex.fast_mode_models`. Matching fresh and resumed runs pass
24
+ Codex's `service_tier="fast"` and `fast_mode` settings and record the
25
+ decision in the lane record and `spawn.json`.
26
+
5
27
  ## [5.134.0] — 2026-09-22
6
28
 
7
29
  ### Fixed
@@ -6744,6 +6744,46 @@ export declare const COMMAND_CATALOG: readonly [{
6744
6744
  readonly description: "JSON on stdout (always)";
6745
6745
  }];
6746
6746
  readonly subcommands: readonly [];
6747
+ }, {
6748
+ readonly name: "watch";
6749
+ readonly description: "Watch lane state and question changes until all lanes are terminal";
6750
+ readonly aliases: readonly [];
6751
+ readonly hidden: false;
6752
+ readonly usage: "[options] <lane-id...>";
6753
+ readonly arguments: readonly [{
6754
+ readonly name: "lane-id";
6755
+ readonly required: true;
6756
+ readonly variadic: true;
6757
+ }];
6758
+ readonly options: readonly [{
6759
+ readonly flags: "--interval-ms <ms>";
6760
+ readonly description: "Polling interval, bounded to 100ms–30s";
6761
+ }, {
6762
+ readonly flags: "--json";
6763
+ readonly description: "JSON on stdout (always)";
6764
+ }];
6765
+ readonly subcommands: readonly [];
6766
+ }, {
6767
+ readonly name: "monitor-check";
6768
+ readonly description: "Check that active Claude senior lanes have live Monitor watch tasks";
6769
+ readonly aliases: readonly [];
6770
+ readonly hidden: false;
6771
+ readonly usage: "[options]";
6772
+ readonly arguments: readonly [];
6773
+ readonly options: readonly [{
6774
+ readonly flags: "--session <id>";
6775
+ readonly description: "Senior session id";
6776
+ }, {
6777
+ readonly flags: "--engine <engine>";
6778
+ readonly description: "claude | codex | grok; defaults to HQ_CONDUCT_ENGINE or claude";
6779
+ }, {
6780
+ readonly flags: "--reminder";
6781
+ readonly description: "Print the senior Monitor reminder text";
6782
+ }, {
6783
+ readonly flags: "--json";
6784
+ readonly description: "JSON on stdout";
6785
+ }];
6786
+ readonly subcommands: readonly [];
6747
6787
  }, {
6748
6788
  readonly name: "show";
6749
6789
  readonly description: "Show one lane";
@@ -8716,6 +8716,58 @@ export const COMMAND_CATALOG = [
8716
8716
  ],
8717
8717
  "subcommands": []
8718
8718
  },
8719
+ {
8720
+ "name": "watch",
8721
+ "description": "Watch lane state and question changes until all lanes are terminal",
8722
+ "aliases": [],
8723
+ "hidden": false,
8724
+ "usage": "[options] <lane-id...>",
8725
+ "arguments": [
8726
+ {
8727
+ "name": "lane-id",
8728
+ "required": true,
8729
+ "variadic": true
8730
+ }
8731
+ ],
8732
+ "options": [
8733
+ {
8734
+ "flags": "--interval-ms <ms>",
8735
+ "description": "Polling interval, bounded to 100ms–30s"
8736
+ },
8737
+ {
8738
+ "flags": "--json",
8739
+ "description": "JSON on stdout (always)"
8740
+ }
8741
+ ],
8742
+ "subcommands": []
8743
+ },
8744
+ {
8745
+ "name": "monitor-check",
8746
+ "description": "Check that active Claude senior lanes have live Monitor watch tasks",
8747
+ "aliases": [],
8748
+ "hidden": false,
8749
+ "usage": "[options]",
8750
+ "arguments": [],
8751
+ "options": [
8752
+ {
8753
+ "flags": "--session <id>",
8754
+ "description": "Senior session id"
8755
+ },
8756
+ {
8757
+ "flags": "--engine <engine>",
8758
+ "description": "claude | codex | grok; defaults to HQ_CONDUCT_ENGINE or claude"
8759
+ },
8760
+ {
8761
+ "flags": "--reminder",
8762
+ "description": "Print the senior Monitor reminder text"
8763
+ },
8764
+ {
8765
+ "flags": "--json",
8766
+ "description": "JSON on stdout"
8767
+ }
8768
+ ],
8769
+ "subcommands": []
8770
+ },
8719
8771
  {
8720
8772
  "name": "show",
8721
8773
  "description": "Show one lane",
@@ -1,13 +1,14 @@
1
1
  /**
2
2
  * `hq lanes` — worker lane management and decision queue (spec §5–§7, §10–§11).
3
3
  *
4
- * Every command prints JSON on stdout and takes no interactive input, except
4
+ * Existing commands print JSON on stdout and take no interactive input, except
5
5
  * `accounts login`, which hands the terminal to the vendor's own sign-in.
6
+ * `watch` and the monitor reminder are the line-oriented text surfaces.
6
7
  */
7
8
  import { Command } from "commander";
8
9
  import { type OutpostDispatchResult } from "../lib/lanes/outpost-dispatch.js";
9
10
  import { emitLaneDecisionEvents, type LaneMesh } from "../lib/lanes/mesh-events.js";
10
- import { MAX_LANE_DEPTH, type LaneCompanyRef, type LaneRecord, type QuestionRecord, type ResolvedLaneWorker, type SeniorRef, type LivenessDeps, type MachineIdentity, type RunCommand, type ThrottleDeps } from "../lib/lanes/index.js";
11
+ import { MAX_LANE_DEPTH, type LaneCompanyRef, type LaneRecord, type QuestionRecord, type ResolvedLaneWorker, type SeniorRef, type LivenessDeps, type MachineIdentity, type MonitorEvidenceReader, type RunCommand, type ThrottleDeps } from "../lib/lanes/index.js";
11
12
  import { questionBodyAbsPath } from "../lib/lanes/questions.js";
12
13
  import { type RunCompactionFn } from "../lib/lanes/compaction.js";
13
14
  import { type KnownModelsDeps, type ProbeCommand } from "../lib/lanes/models.js";
@@ -76,6 +77,7 @@ export interface LanesCommandDeps {
76
77
  fetchText?: (url: string) => Promise<string>;
77
78
  runCompaction?: RunCompactionFn;
78
79
  locateTranscript?: (home: string, sessionId: string) => string | null;
80
+ monitorEvidence?: MonitorEvidenceReader;
79
81
  }
80
82
  export declare function readOutpostIdentity(existsSync?: (p: string) => boolean, readFileSync?: (p: string) => string): OutpostIdentity;
81
83
  export declare function parseSeniorRef(raw: string): SeniorRef;
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * `hq lanes` — worker lane management and decision queue (spec §5–§7, §10–§11).
3
3
  *
4
- * Every command prints JSON on stdout and takes no interactive input, except
4
+ * Existing commands print JSON on stdout and take no interactive input, except
5
5
  * `accounts login`, which hands the terminal to the vendor's own sign-in.
6
+ * `watch` and the monitor reminder are the line-oriented text surfaces.
6
7
  */
7
8
  import { spawn, spawnSync } from "node:child_process";
8
9
  import { randomBytes } from "node:crypto";
@@ -17,7 +18,7 @@ import { vaultApiFetch } from "../utils/vault-api.js";
17
18
  import { openMeshTransport } from "../lib/mesh/client.js";
18
19
  import { createLaneMesh, emitLaneDecisionEvents, } from "../lib/lanes/mesh-events.js";
19
20
  import { sessionIdFromEnv } from "../lib/mesh/live/session-identity.js";
20
- import { AccountResolutionError, DEFAULT_ACCOUNT_HOMES, LANE_PROVIDERS, LANE_STATES, PROVIDER_HOME_ENV, QUESTION_STATUSES, SENIOR_KINDS, accountMaxRunning, accountStatus, appendCappedHistory, canonicalizeHome, createLane, decideAdmission, defaultLivenessDeps, defaultSystemdUserDir, defaultThrottleDeps, installDrainHook, installReconcileTimer, providerPathEnv, probeDrainHookRegistration, isLanesError, isLaneVersionConflict, isTerminalLaneState, listAccountStatuses, listLaneIds, listQuestionIds, listSessionLiveness, loadLanesConfig, MAX_LANE_DEPTH, resolveMachineIdentity as lookupMachineIdentity, loadLivenessIndex, parseLaneProvider, parseLaneState, parseLivenessState, parseQuestionStatus, parseSeniorKind, readDaemonPresenceConnected, readLane, retryUpdateLane, readQuestion, resolveAccount, resolveLaneWorker, isLoggedOut, runReconcilePass, sessionLiveness, tryReadLane, uninstallReconcileTimer, updateLane, updateQuestion, writeLanesConfig, appendDropboxMessage, answerDropboxMessage, deliveryRefusalReason, resumeCommandRefusal, dropboxDir, dropboxInboxPath, laneAcceptsDropboxDelivery, laneAcceptsOperatorMessage, laneDeliveryMechanism, hasRecordedSessionId, providerSupportsSessionResume, laneIdForAnswerDelivery, operatorMessageRefusalReason, raiseLaneQuestion, sha256Text, writeQuestionBody, } from "../lib/lanes/index.js";
21
+ import { AccountResolutionError, coveredLaneIds, DEFAULT_ACCOUNT_HOMES, LANE_PROVIDERS, LANE_STATES, PROVIDER_HOME_ENV, QUESTION_STATUSES, SENIOR_KINDS, accountMaxRunning, accountStatus, appendCappedHistory, canonicalizeHome, createLane, decideAdmission, defaultLivenessDeps, defaultSystemdUserDir, defaultThrottleDeps, installDrainHook, installReconcileTimer, providerPathEnv, probeDrainHookRegistration, isLanesError, isLaneVersionConflict, isTerminalLaneState, listAccountStatuses, listLaneIds, listQuestionIds, listSessionLiveness, loadLanesConfig, MAX_LANE_DEPTH, MONITOR_ERROR_EXIT_CODE, MONITOR_ENGINES, MONITOR_MAX_TIMEOUT_MS, MONITOR_UNCOVERED_EXIT_CODE, MAX_WATCHED_LANES, monitorReminderText, readLiveMonitorEvidence, resolveMachineIdentity as lookupMachineIdentity, loadLivenessIndex, parseLaneProvider, parseLaneState, parseLivenessState, parseQuestionStatus, parseSeniorKind, readDaemonPresenceConnected, readLane, retryUpdateLane, readQuestion, resolveAccount, resolveLaneWorker, isLoggedOut, runReconcilePass, runLaneWatch, sessionLiveness, tryReadLane, uninstallReconcileTimer, updateLane, updateQuestion, writeLanesConfig, appendDropboxMessage, answerDropboxMessage, deliveryRefusalReason, resumeCommandRefusal, dropboxDir, dropboxInboxPath, laneAcceptsDropboxDelivery, laneAcceptsOperatorMessage, laneDeliveryMechanism, hasRecordedSessionId, providerSupportsSessionResume, laneIdForAnswerDelivery, operatorMessageRefusalReason, raiseLaneQuestion, sha256Text, writeQuestionBody, } from "../lib/lanes/index.js";
21
22
  import { questionBodyAbsPath } from "../lib/lanes/questions.js";
22
23
  import { compactionAfterUsage, } from "../lib/lanes/compaction.js";
23
24
  import { providerCompactAfterMs } from "../lib/lanes/config.js";
@@ -62,6 +63,24 @@ function wrap(action) {
62
63
  }
63
64
  };
64
65
  }
66
+ function failText(err) {
67
+ const message = err instanceof Error ? err.message : String(err);
68
+ process.stderr.write(`hq lanes: ${message}\n`);
69
+ process.exit(MONITOR_ERROR_EXIT_CODE);
70
+ }
71
+ function wrapText(action) {
72
+ return async (...args) => {
73
+ let code;
74
+ try {
75
+ code = await action(...args);
76
+ }
77
+ catch (err) {
78
+ failText(err);
79
+ }
80
+ if (code !== 0)
81
+ process.exit(code);
82
+ };
83
+ }
65
84
  function collectRepeatable(value, previous = []) {
66
85
  return previous.concat(value);
67
86
  }
@@ -206,6 +225,12 @@ function resolveDeps(deps = {}) {
206
225
  probeProvider: deps.probeProvider ?? defaultProbe,
207
226
  runCompaction: deps.runCompaction,
208
227
  locateTranscript: deps.locateTranscript,
228
+ monitorEvidence: deps.monitorEvidence ??
229
+ ((sessionId) => readLiveMonitorEvidence(sessionId, {
230
+ homedir: () => deps.homedir?.() ?? os.homedir(),
231
+ env,
232
+ now: deps.now ?? (() => new Date()),
233
+ })),
209
234
  stageOutpostPayload: deps.stageOutpostPayload ?? defaultStageOutpostPayload,
210
235
  dispatchOutpostExec: deps.dispatchOutpostExec ?? defaultDispatchOutpostExec,
211
236
  fetchText: deps.fetchText ?? defaultFetchText,
@@ -387,6 +412,115 @@ function loadAllLanes(hqRoot) {
387
412
  function loadAllQuestions(hqRoot) {
388
413
  return listQuestionIds(hqRoot).map((id) => readQuestion(hqRoot, id));
389
414
  }
415
+ const MONITOR_ACTIVE_LANE_STATES = new Set([
416
+ "running",
417
+ "queued",
418
+ "awaiting_input",
419
+ "blocked",
420
+ ]);
421
+ function resolveMonitorEngine(requested, env) {
422
+ const value = requested?.trim().toLowerCase() ||
423
+ env.HQ_CONDUCT_ENGINE?.trim().toLowerCase() ||
424
+ "claude";
425
+ if (!MONITOR_ENGINES.includes(value)) {
426
+ throw new LanesError("monitor_invalid_engine", `Unknown monitor-check engine ${JSON.stringify(value)}. Accepted: ${MONITOR_ENGINES.join(", ")}`, { accepted: [...MONITOR_ENGINES], value });
427
+ }
428
+ return value;
429
+ }
430
+ async function runWatch(ctx, laneIds, opts) {
431
+ const rawInterval = opts.intervalMs === undefined ? undefined : Number(opts.intervalMs);
432
+ await runLaneWatch(ctx.hqRoot(), laneIds, {
433
+ intervalMs: rawInterval,
434
+ sleep: ctx.sleep,
435
+ writeLine: (line) => console.log(opts.json ? JSON.stringify({ event: line }) : line),
436
+ writeError: (line) => process.stderr.write(`${line}\n`),
437
+ });
438
+ return 0;
439
+ }
440
+ function monitorCallsForLaneIds(laneIds) {
441
+ const calls = [];
442
+ for (let offset = 0; offset < laneIds.length; offset += MAX_WATCHED_LANES) {
443
+ const chunk = laneIds.slice(offset, offset + MAX_WATCHED_LANES);
444
+ calls.push({
445
+ command: `hq lanes watch ${chunk.join(" ")}`,
446
+ timeout_ms: MONITOR_MAX_TIMEOUT_MS,
447
+ persistent: true,
448
+ });
449
+ }
450
+ return calls;
451
+ }
452
+ async function runMonitorCheck(ctx, opts) {
453
+ if (opts.reminder) {
454
+ console.log(monitorReminderText());
455
+ return 0;
456
+ }
457
+ const sessionId = opts.session?.trim();
458
+ if (!sessionId) {
459
+ throw new LanesError("monitor_session_required", "hq lanes monitor-check requires --session <id> unless --reminder is used");
460
+ }
461
+ const engine = resolveMonitorEngine(opts.engine, ctx.env);
462
+ const activeLanes = loadAllLanes(ctx.hqRoot()).filter((lane) => lane.senior.kind === "session" &&
463
+ lane.senior.id === sessionId &&
464
+ MONITOR_ACTIVE_LANE_STATES.has(lane.state));
465
+ if (engine !== "claude") {
466
+ if (opts.json) {
467
+ printJson({
468
+ ok: true,
469
+ action: "monitor-check",
470
+ session_id: sessionId,
471
+ engine,
472
+ active_lane_ids: activeLanes.map((lane) => lane.lane_id),
473
+ covered_lane_ids: [],
474
+ uncovered_lane_ids: [],
475
+ skipped: "engine_has_no_claude_monitor",
476
+ });
477
+ }
478
+ return 0;
479
+ }
480
+ if (activeLanes.length === 0) {
481
+ if (opts.json) {
482
+ printJson({
483
+ ok: true,
484
+ action: "monitor-check",
485
+ session_id: sessionId,
486
+ engine,
487
+ active_lane_ids: [],
488
+ covered_lane_ids: [],
489
+ uncovered_lane_ids: [],
490
+ });
491
+ }
492
+ return 0;
493
+ }
494
+ const evidence = await ctx.monitorEvidence(sessionId);
495
+ if (evidence.sessionId !== sessionId) {
496
+ throw new LanesError("monitor_evidence_session_mismatch", `Monitor evidence was for ${JSON.stringify(evidence.sessionId)}, expected ${JSON.stringify(sessionId)}`);
497
+ }
498
+ const covered = coveredLaneIds(evidence, ctx.now());
499
+ const activeIds = activeLanes.map((lane) => lane.lane_id);
500
+ const uncovered = activeIds.filter((laneId) => !covered.has(laneId));
501
+ const monitorCalls = monitorCallsForLaneIds(uncovered);
502
+ if (opts.json) {
503
+ printJson({
504
+ ok: uncovered.length === 0,
505
+ action: "monitor-check",
506
+ session_id: sessionId,
507
+ engine,
508
+ active_lane_ids: activeIds,
509
+ covered_lane_ids: activeIds.filter((laneId) => covered.has(laneId)),
510
+ uncovered_lane_ids: uncovered,
511
+ monitor_call: monitorCalls.length === 1 ? monitorCalls[0] : null,
512
+ monitor_calls: monitorCalls,
513
+ });
514
+ }
515
+ else if (uncovered.length > 0) {
516
+ for (const laneId of uncovered)
517
+ console.log(`uncovered lane: ${laneId}`);
518
+ for (const monitorCall of monitorCalls) {
519
+ console.log(`Monitor(command=${JSON.stringify(monitorCall.command)}, timeout_ms=${monitorCall.timeout_ms}, persistent=true)`);
520
+ }
521
+ }
522
+ return uncovered.length > 0 ? MONITOR_UNCOVERED_EXIT_CODE : 0;
523
+ }
390
524
  function sessionMetaPath(hqRoot, sessionId) {
391
525
  return path.join(hqRoot, "workspace", "sessions", sessionId, "meta.yaml");
392
526
  }
@@ -3193,6 +3327,20 @@ export function registerLanesCommand(parent, deps = {}) {
3193
3327
  .action(wrap(async (opts) => {
3194
3328
  await runList(ctx, opts);
3195
3329
  }));
3330
+ lanes
3331
+ .command("watch")
3332
+ .description("Watch lane state and question changes until all lanes are terminal")
3333
+ .argument("<lane-id...>", "Lane ids to watch")
3334
+ .option("--interval-ms <ms>", "Polling interval, bounded to 100ms–30s", "5000")
3335
+ .action(wrapText(async (laneIds, opts) => runWatch(ctx, laneIds, opts)));
3336
+ lanes
3337
+ .command("monitor-check")
3338
+ .description("Check that active Claude senior lanes have live Monitor watch tasks")
3339
+ .option("--session <id>", "Senior session id")
3340
+ .option("--engine <engine>", "claude | codex | grok; defaults to HQ_CONDUCT_ENGINE or claude")
3341
+ .option("--reminder", "Print the senior Monitor reminder text")
3342
+ .option("--json", "JSON on stdout")
3343
+ .action(wrapText(async (opts) => runMonitorCheck(ctx, opts)));
3196
3344
  lanes
3197
3345
  .command("show")
3198
3346
  .description("Show one lane")
@@ -18,6 +18,11 @@ export declare const DEFAULT_MIN_AVAILABLE_MEM_MB = 1024;
18
18
  * run compact". Override per provider with `compact_after_ms`.
19
19
  */
20
20
  export declare const DEFAULT_COMPACT_AFTER_MS: number;
21
+ /**
22
+ * Claude Code's auto-compaction window, in tokens. Override with
23
+ * `providers.claude.auto_compact_tokens`.
24
+ */
25
+ export declare const DEFAULT_AUTO_COMPACT_TOKENS = 200000;
21
26
  /**
22
27
  * Watcher `lane_progress` throttle: at most one thread event per five minutes
23
28
  * per lane, and only when the tick saw new activity. Override per provider
@@ -66,6 +71,8 @@ export interface ConfigWriteDeps {
66
71
  export declare function writeLanesConfig(hqRoot: string, config: LanesConfig, deps?: ConfigWriteDeps): void;
67
72
  /** Resume-time compaction threshold for a provider, defaulting to one hour. */
68
73
  export declare function providerCompactAfterMs(provider: ProviderConfig): number;
74
+ /** Claude Code auto-compaction threshold, defaulting to 200,000 tokens. */
75
+ export declare function providerAutoCompactTokens(provider: ProviderConfig): number;
69
76
  /** Minimum gap between two `lane_progress` events, defaulting to five minutes. */
70
77
  export declare function providerProgressEventMinIntervalMs(provider: ProviderConfig): number;
71
78
  /** Hold for a reset-less 429 on this provider's accounts. */
@@ -22,6 +22,11 @@ export const DEFAULT_MIN_AVAILABLE_MEM_MB = 1024;
22
22
  * run compact". Override per provider with `compact_after_ms`.
23
23
  */
24
24
  export const DEFAULT_COMPACT_AFTER_MS = 60 * 60 * 1000;
25
+ /**
26
+ * Claude Code's auto-compaction window, in tokens. Override with
27
+ * `providers.claude.auto_compact_tokens`.
28
+ */
29
+ export const DEFAULT_AUTO_COMPACT_TOKENS = 200_000;
25
30
  /**
26
31
  * Watcher `lane_progress` throttle: at most one thread event per five minutes
27
32
  * per lane, and only when the tick saw new activity. Override per provider
@@ -159,6 +164,15 @@ function nonEmptyModel(value, field) {
159
164
  }
160
165
  return value.trim();
161
166
  }
167
+ function parseFastModeModels(value, field) {
168
+ if (value === undefined)
169
+ return [];
170
+ if (!Array.isArray(value) ||
171
+ value.some((model) => typeof model !== "string" || model.trim().length === 0)) {
172
+ throw new LanesConfigError("invalid_fast_mode_models", `${field} must be an array of non-empty strings`, { field, value });
173
+ }
174
+ return value.map((model) => model.trim());
175
+ }
162
176
  function rejectDuplicateHomes(provider, accounts) {
163
177
  const seen = new Map();
164
178
  for (const [id, account] of Object.entries(accounts)) {
@@ -219,6 +233,9 @@ function parseProvider(provider, raw, deps) {
219
233
  max_queued: positiveInt(raw.max_queued, `providers.${provider}.max_queued`, DEFAULT_MAX_QUEUED),
220
234
  accounts,
221
235
  };
236
+ if (provider === "codex") {
237
+ parsed.fast_mode_models = parseFastModeModels(raw.fast_mode_models, `providers.${provider}.fast_mode_models`);
238
+ }
222
239
  if (defaultAccount !== undefined)
223
240
  parsed.default_account = defaultAccount;
224
241
  if (raw.model !== undefined) {
@@ -230,6 +247,9 @@ function parseProvider(provider, raw, deps) {
230
247
  if (raw.compact_after_ms !== undefined) {
231
248
  parsed.compact_after_ms = positiveInt(raw.compact_after_ms, `providers.${provider}.compact_after_ms`);
232
249
  }
250
+ if (raw.auto_compact_tokens !== undefined) {
251
+ parsed.auto_compact_tokens = positiveInt(raw.auto_compact_tokens, `providers.${provider}.auto_compact_tokens`);
252
+ }
233
253
  if (raw.progress_event_min_interval_ms !== undefined) {
234
254
  parsed.progress_event_min_interval_ms = positiveInt(raw.progress_event_min_interval_ms, `providers.${provider}.progress_event_min_interval_ms`);
235
255
  }
@@ -277,11 +297,14 @@ function parseLiveness(raw) {
277
297
  export function documentedDefaultConfig(deps = defaultDeps()) {
278
298
  const providers = {};
279
299
  for (const provider of LANE_PROVIDERS) {
280
- providers[provider] = {
300
+ const providerConfig = {
281
301
  max_running: DEFAULT_PROVIDER_MAX_RUNNING[provider],
282
302
  max_queued: DEFAULT_MAX_QUEUED,
283
303
  accounts: defaultAccountMap(provider, deps),
284
304
  };
305
+ if (provider === "codex")
306
+ providerConfig.fast_mode_models = [];
307
+ providers[provider] = providerConfig;
285
308
  }
286
309
  return {
287
310
  schema_version: CONFIG_SCHEMA_VERSION,
@@ -399,6 +422,10 @@ export function writeLanesConfig(hqRoot, config, deps = defaultWriteDeps()) {
399
422
  export function providerCompactAfterMs(provider) {
400
423
  return provider.compact_after_ms ?? DEFAULT_COMPACT_AFTER_MS;
401
424
  }
425
+ /** Claude Code auto-compaction threshold, defaulting to 200,000 tokens. */
426
+ export function providerAutoCompactTokens(provider) {
427
+ return provider.auto_compact_tokens ?? DEFAULT_AUTO_COMPACT_TOKENS;
428
+ }
402
429
  /** Minimum gap between two `lane_progress` events, defaulting to five minutes. */
403
430
  export function providerProgressEventMinIntervalMs(provider) {
404
431
  return provider.progress_event_min_interval_ms ?? DEFAULT_PROGRESS_EVENT_MIN_INTERVAL_MS;
@@ -5,7 +5,7 @@ export { AccountResolutionError, LaneNotFoundError, LaneSchemaError, LaneVersion
5
5
  export { MAX_LANE_DEPTH } from "./constants.js";
6
6
  export { CONFIG_SCHEMA_VERSION, ENVELOPE_DECISIONS, ENVELOPE_SCHEMA_VERSION, HISTORY_CAP, HOST_KINDS, LANE_PROVIDERS, LANE_SCHEMA_VERSION, LANE_STATES, LIVENESS_STATES, QUESTION_BODY_STORES, QUESTION_SCHEMA_VERSION, QUESTION_STATUSES, QUEUED_REASONS, RAISED_VIA, ROUTING_REASONS, SENIOR_KINDS, STORY_STATUSES, TERMINAL_LANE_STATES, isEnvelopeDecision, isHostKind, isLaneProvider, isLaneState, isLivenessState, isQuestionStatus, isSeniorKind, isTerminalLaneState, parseLaneEnvelope, parseLaneProvider, parseLaneState, parseLivenessState, parseMajorSchema, parseQuestionStatus, parseSeniorKind, } from "./types.js";
7
7
  export type { AccountConfig, AttributionHistoryEntry, EnvelopeDecision, EnvelopeQuestion, HostKind, LaneCompanyRef, LaneEnvelope, LaneHost, LaneProvider, LaneRecord, PendingResume, AccountHistoryEntry, LaneState, LanesConfig, LastEnvelopeRef, LivenessState, LivenessWindows, ProviderConfig, QuestionAnswer, QuestionBodyRef, QuestionRecord, QuestionStatus, QueuedReason, RaisedVia, RoutingHistoryEntry, RoutingReason, SeniorHistoryEntry, SeniorKind, SeniorRef, StoryStatus, TerminalLaneState, ThrottleConfig, } from "./types.js";
8
- export { DEFAULT_ACCOUNT_HOMES, DEFAULT_COMPACT_AFTER_MS, DEFAULT_CPU_BUSY_PAUSE, DEFAULT_CPU_BUSY_RESUME, DEFAULT_LIVE_WITHIN_MS, DEFAULT_LIVENESS_WINDOWS, DEFAULT_MAX_QUEUED, DEFAULT_MIN_AVAILABLE_MEM_MB, DEFAULT_PROVIDER_MAX_RUNNING, DEFAULT_SILENT_LOST_MS, DEFAULT_TURN_START_LOST_MS, LANES_CONFIG_REL, accountMaxRunning, canonicalizeHome, documentedDefaultConfig, expandHome, lanesConfigPath, loadLanesConfig, parseLanesConfig, providerCompactAfterMs, providerQuotaDefaultHoldMs, DEFAULT_QUOTA_HOLD_MS, writeLanesConfig, } from "./config.js";
8
+ export { DEFAULT_ACCOUNT_HOMES, DEFAULT_AUTO_COMPACT_TOKENS, DEFAULT_COMPACT_AFTER_MS, DEFAULT_CPU_BUSY_PAUSE, DEFAULT_CPU_BUSY_RESUME, DEFAULT_LIVE_WITHIN_MS, DEFAULT_LIVENESS_WINDOWS, DEFAULT_MAX_QUEUED, DEFAULT_MIN_AVAILABLE_MEM_MB, DEFAULT_PROVIDER_MAX_RUNNING, DEFAULT_SILENT_LOST_MS, DEFAULT_TURN_START_LOST_MS, LANES_CONFIG_REL, accountMaxRunning, canonicalizeHome, documentedDefaultConfig, expandHome, lanesConfigPath, loadLanesConfig, parseLanesConfig, providerCompactAfterMs, providerAutoCompactTokens, providerQuotaDefaultHoldMs, DEFAULT_QUOTA_HOLD_MS, writeLanesConfig, } from "./config.js";
9
9
  export type { ConfigLoadDeps, ConfigWriteDeps } from "./config.js";
10
10
  export { resolveLanesHqRoot } from "./hq-root.js";
11
11
  export type { LanesHqRootOpts } from "./hq-root.js";
@@ -13,6 +13,10 @@ export { buildOutpostPickupCommand, parseOutpostPickupPayload, } from "./outpost
13
13
  export type { OutpostDispatchResult, OutpostPickupPayload, } from "./outpost-dispatch.js";
14
14
  export { LANES_STORE_REL, LANE_RECORDS_DIR, PENDING_INDEX_DIR, QUESTION_RECORDS_DIR, appendCappedHistory, appendLaneAttribution, appendLaneSeniorHistory, appendQuestionRouting, createLane, createQuestion, isConflictSidecarName, laneRecordPath, lanesStoreRoot, listLaneIds, listQuestionIds, mergeLaneRecords, mergeQuestionRecords, mintLaneId, mintQuestionId, parseLaneRecord, parseQuestionRecord, pendingMarkerPath, questionRecordPath, readLane, readQuestion, resolveStoreHqRoot, sanitizeHostComponent, tryReadLane, tryReadQuestion, retryUpdateLane, retryUpdateQuestion, updateLane, updateQuestion, } from "./store.js";
15
15
  export type { StoreDeps } from "./store.js";
16
+ export { DEFAULT_LANE_WATCH_INTERVAL_MS, MAX_LANE_WATCH_INTERVAL_MS, MAX_WATCHED_LANES, MAX_WATCH_OUTPUT_LINES, runLaneWatch, } from "./watch.js";
17
+ export type { LaneWatchDeps, LaneWatchResult } from "./watch.js";
18
+ export { MONITOR_ERROR_EXIT_CODE, MONITOR_ENGINES, MONITOR_MAX_TIMEOUT_MS, MONITOR_TASK_OUTPUT_MAX_BYTES, MONITOR_TRANSCRIPT_MAX_BYTES, MONITOR_UNCOVERED_EXIT_CODE, coveredLaneIds, isMonitorTaskLive, monitorReminderText, parseCanonicalWatchCommand, parseMonitorTranscript, readLiveMonitorEvidence, } from "./monitor.js";
19
+ export type { LiveMonitorEvidenceOptions, MonitorEngine, MonitorEvidence, MonitorEvidenceReader, MonitorTaskEvidence, } from "./monitor.js";
16
20
  export { IMDS_HOST, IMDS_INSTANCE_ID_URL, IMDS_TIMEOUT_MS, IMDS_TOKEN_URL, defaultReadImdsInstanceId, resolveMachineIdentity, } from "./machine-identity.js";
17
21
  export type { MachineIdentity, MachineIdentityDeps } from "./machine-identity.js";
18
22
  export { LANES_RUNS_REL as SPAWN_LANES_RUNS_REL, PID_LIVENESS_DECISIONS, PROVIDER_COMMAND, PROVIDER_MODEL_FLAG, SPAWN_TERMINAL_REASONS, ANSWERED_QUESTIONS_FILE, appendModelFlag, armLaneWatcher, buildProviderCommand, parseCliModel, resolveLaneModel, defaultProveDetached, isPidRecordAlive, laneRunDir, missingPidProbe, nextEnvelopePath, markSpawnFailure, parsePidRecord, parseProcStat, parseSpawnTerminalReason, probePidRecord, readPidRecord, readProcStarttime, readProcStarttimeDetailed, readSpawnManifest, resumePrompt, envelopeInstruction, spawnLaneWorker, stopLaneProcesses, watcherMainPath, workerEnv, } from "./spawn.js";
@@ -4,10 +4,12 @@
4
4
  export { AccountResolutionError, LaneNotFoundError, LaneSchemaError, LaneVersionConflict, LanesConfigError, LanesError, WorkerResolutionError, isLaneVersionConflict, isLanesError, } from "./errors.js";
5
5
  export { MAX_LANE_DEPTH } from "./constants.js";
6
6
  export { CONFIG_SCHEMA_VERSION, ENVELOPE_DECISIONS, ENVELOPE_SCHEMA_VERSION, HISTORY_CAP, HOST_KINDS, LANE_PROVIDERS, LANE_SCHEMA_VERSION, LANE_STATES, LIVENESS_STATES, QUESTION_BODY_STORES, QUESTION_SCHEMA_VERSION, QUESTION_STATUSES, QUEUED_REASONS, RAISED_VIA, ROUTING_REASONS, SENIOR_KINDS, STORY_STATUSES, TERMINAL_LANE_STATES, isEnvelopeDecision, isHostKind, isLaneProvider, isLaneState, isLivenessState, isQuestionStatus, isSeniorKind, isTerminalLaneState, parseLaneEnvelope, parseLaneProvider, parseLaneState, parseLivenessState, parseMajorSchema, parseQuestionStatus, parseSeniorKind, } from "./types.js";
7
- export { DEFAULT_ACCOUNT_HOMES, DEFAULT_COMPACT_AFTER_MS, DEFAULT_CPU_BUSY_PAUSE, DEFAULT_CPU_BUSY_RESUME, DEFAULT_LIVE_WITHIN_MS, DEFAULT_LIVENESS_WINDOWS, DEFAULT_MAX_QUEUED, DEFAULT_MIN_AVAILABLE_MEM_MB, DEFAULT_PROVIDER_MAX_RUNNING, DEFAULT_SILENT_LOST_MS, DEFAULT_TURN_START_LOST_MS, LANES_CONFIG_REL, accountMaxRunning, canonicalizeHome, documentedDefaultConfig, expandHome, lanesConfigPath, loadLanesConfig, parseLanesConfig, providerCompactAfterMs, providerQuotaDefaultHoldMs, DEFAULT_QUOTA_HOLD_MS, writeLanesConfig, } from "./config.js";
7
+ export { DEFAULT_ACCOUNT_HOMES, DEFAULT_AUTO_COMPACT_TOKENS, DEFAULT_COMPACT_AFTER_MS, DEFAULT_CPU_BUSY_PAUSE, DEFAULT_CPU_BUSY_RESUME, DEFAULT_LIVE_WITHIN_MS, DEFAULT_LIVENESS_WINDOWS, DEFAULT_MAX_QUEUED, DEFAULT_MIN_AVAILABLE_MEM_MB, DEFAULT_PROVIDER_MAX_RUNNING, DEFAULT_SILENT_LOST_MS, DEFAULT_TURN_START_LOST_MS, LANES_CONFIG_REL, accountMaxRunning, canonicalizeHome, documentedDefaultConfig, expandHome, lanesConfigPath, loadLanesConfig, parseLanesConfig, providerCompactAfterMs, providerAutoCompactTokens, providerQuotaDefaultHoldMs, DEFAULT_QUOTA_HOLD_MS, writeLanesConfig, } from "./config.js";
8
8
  export { resolveLanesHqRoot } from "./hq-root.js";
9
9
  export { buildOutpostPickupCommand, parseOutpostPickupPayload, } from "./outpost-dispatch.js";
10
10
  export { LANES_STORE_REL, LANE_RECORDS_DIR, PENDING_INDEX_DIR, QUESTION_RECORDS_DIR, appendCappedHistory, appendLaneAttribution, appendLaneSeniorHistory, appendQuestionRouting, createLane, createQuestion, isConflictSidecarName, laneRecordPath, lanesStoreRoot, listLaneIds, listQuestionIds, mergeLaneRecords, mergeQuestionRecords, mintLaneId, mintQuestionId, parseLaneRecord, parseQuestionRecord, pendingMarkerPath, questionRecordPath, readLane, readQuestion, resolveStoreHqRoot, sanitizeHostComponent, tryReadLane, tryReadQuestion, retryUpdateLane, retryUpdateQuestion, updateLane, updateQuestion, } from "./store.js";
11
+ export { DEFAULT_LANE_WATCH_INTERVAL_MS, MAX_LANE_WATCH_INTERVAL_MS, MAX_WATCHED_LANES, MAX_WATCH_OUTPUT_LINES, runLaneWatch, } from "./watch.js";
12
+ export { MONITOR_ERROR_EXIT_CODE, MONITOR_ENGINES, MONITOR_MAX_TIMEOUT_MS, MONITOR_TASK_OUTPUT_MAX_BYTES, MONITOR_TRANSCRIPT_MAX_BYTES, MONITOR_UNCOVERED_EXIT_CODE, coveredLaneIds, isMonitorTaskLive, monitorReminderText, parseCanonicalWatchCommand, parseMonitorTranscript, readLiveMonitorEvidence, } from "./monitor.js";
11
13
  export { IMDS_HOST, IMDS_INSTANCE_ID_URL, IMDS_TIMEOUT_MS, IMDS_TOKEN_URL, defaultReadImdsInstanceId, resolveMachineIdentity, } from "./machine-identity.js";
12
14
  export { LANES_RUNS_REL as SPAWN_LANES_RUNS_REL, PID_LIVENESS_DECISIONS, PROVIDER_COMMAND, PROVIDER_MODEL_FLAG, SPAWN_TERMINAL_REASONS, ANSWERED_QUESTIONS_FILE, appendModelFlag, armLaneWatcher, buildProviderCommand, parseCliModel, resolveLaneModel, defaultProveDetached, isPidRecordAlive, laneRunDir, missingPidProbe, nextEnvelopePath, markSpawnFailure, parsePidRecord, parseProcStat, parseSpawnTerminalReason, probePidRecord, readPidRecord, readProcStarttime, readProcStarttimeDetailed, readSpawnManifest, resumePrompt, envelopeInstruction, spawnLaneWorker, stopLaneProcesses, watcherMainPath, workerEnv, } from "./spawn.js";
13
15
  export { SILENCE_MS, WATCHER_DECISION_EVENTS, WATCHER_OUT_MAX_BYTES, WATCHER_POLL_MS, WATCHER_SIGNAL_KINDS, appendCappedLog, appendWatcherSignal, applyTerminalToLane, classifyLaneExit, clearLaneStalled, isPidAlive, laneIdentityFromRecord, markLaneStalled, notifySlotFreed, parseWatcherSignalKind, readLatestEnvelope, runWatcherLoop, stalledReason, tickWatcher, watcherEventsPath, watcherLastSignalPath, watcherOutLogPath, writeWatcherDecision, } from "./watcher.js";
@@ -0,0 +1,48 @@
1
+ export declare const MONITOR_MAX_TIMEOUT_MS = 1800000;
2
+ export declare const MONITOR_UNCOVERED_EXIT_CODE = 2;
3
+ export declare const MONITOR_ERROR_EXIT_CODE = 3;
4
+ export declare const MONITOR_TRANSCRIPT_MAX_BYTES: number;
5
+ export declare const MONITOR_TASK_OUTPUT_MAX_BYTES: number;
6
+ export type MonitorEngine = "claude" | "codex" | "grok";
7
+ export declare const MONITOR_ENGINES: readonly MonitorEngine[];
8
+ export interface MonitorTaskEvidence {
9
+ taskId: string;
10
+ command: string;
11
+ startedAt: string;
12
+ timeoutMs: number;
13
+ persistent?: boolean;
14
+ stopped?: boolean;
15
+ outputPresent: boolean;
16
+ outputText?: string;
17
+ processAlive?: boolean;
18
+ outputPath?: string;
19
+ }
20
+ export interface MonitorEvidence {
21
+ sessionId: string;
22
+ tasks: readonly MonitorTaskEvidence[];
23
+ transcriptPaths?: readonly string[];
24
+ taskOutputPaths?: readonly string[];
25
+ processCommands?: readonly string[];
26
+ }
27
+ export interface LiveMonitorEvidenceOptions {
28
+ homedir?: () => string;
29
+ env?: NodeJS.ProcessEnv;
30
+ now?: () => Date;
31
+ transcriptMaxBytes?: number;
32
+ taskOutputMaxBytes?: number;
33
+ readProcessCommands?: () => readonly string[];
34
+ }
35
+ /**
36
+ * Parse only the JSONL shape emitted by Claude Code's Monitor tool. The
37
+ * caller supplies a bounded tail; malformed or partial lines are ignored so a
38
+ * torn final write cannot turn into positive liveness evidence.
39
+ */
40
+ export declare function parseMonitorTranscript(text: string): MonitorTaskEvidence[];
41
+ /** Return argv only for the exact command form the gate arms. */
42
+ export declare function parseCanonicalWatchCommand(command: string): string[] | null;
43
+ export declare function isMonitorTaskLive(task: MonitorTaskEvidence, now: Date): boolean;
44
+ export declare function coveredLaneIds(evidence: MonitorEvidence, now: Date): Set<string>;
45
+ export declare function readLiveMonitorEvidence(sessionId: string, options?: LiveMonitorEvidenceOptions): MonitorEvidence;
46
+ export type MonitorEvidenceReader = (sessionId: string) => MonitorEvidence | Promise<MonitorEvidence>;
47
+ export declare function monitorReminderText(): string;
48
+ //# sourceMappingURL=monitor.d.ts.map