@rallycry/conveyor-agent 11.0.19 → 11.0.20

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.
@@ -11,14 +11,14 @@ import {
11
11
  readAgentVersion,
12
12
  refreshSkillsAfterCheckout,
13
13
  runPreReadyBinds
14
- } from "./chunk-SR66HQKB.js";
14
+ } from "./chunk-37J5MMQT.js";
15
15
  import "./chunk-W5INK3NE.js";
16
16
  import {
17
17
  GitPrepJob,
18
18
  defaultGit,
19
19
  ensureDir,
20
20
  reportBootMilestone
21
- } from "./chunk-GL2DIQEQ.js";
21
+ } from "./chunk-Q4FQOJ7D.js";
22
22
  import "./chunk-W4LZ7R6Z.js";
23
23
  import "./chunk-372R6E4C.js";
24
24
  import "./chunk-SQM2BQ7H.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  redactToken
3
- } from "./chunk-GL2DIQEQ.js";
3
+ } from "./chunk-Q4FQOJ7D.js";
4
4
 
5
5
  // src/boot/graphify.ts
6
6
  var USER_HOME_MOUNT = "/mnt/conveyor-users";
@@ -3,7 +3,7 @@ import {
3
3
  DEFAULT_RETRY_DELAY_MS,
4
4
  FETCH_TIMEOUT_MS,
5
5
  GIT_PREP_MAX_RETRIES
6
- } from "./chunk-GL2DIQEQ.js";
6
+ } from "./chunk-Q4FQOJ7D.js";
7
7
  import {
8
8
  gitCredentialHelper,
9
9
  sleep,
@@ -2,7 +2,7 @@ import {
2
2
  mapChatHistory,
3
3
  readAgentVersion,
4
4
  refreshSkillsAfterCheckout
5
- } from "./chunk-SR66HQKB.js";
5
+ } from "./chunk-37J5MMQT.js";
6
6
  import {
7
7
  MAX_BETWEEN_TURN_BUFFER,
8
8
  MAX_DIAGNOSTIC_OUTPUT,
@@ -59,11 +59,11 @@ import {
59
59
  statWorkspacePath,
60
60
  updateRemoteToken,
61
61
  verifyGitCredential
62
- } from "./chunk-WS7QRB37.js";
62
+ } from "./chunk-JBGPARLG.js";
63
63
  import {
64
64
  registerBootMilestoneSocketFallback,
65
65
  reportBootMilestone
66
- } from "./chunk-GL2DIQEQ.js";
66
+ } from "./chunk-Q4FQOJ7D.js";
67
67
  import {
68
68
  describeTokenFile,
69
69
  ghHostsExternallyOwned,
@@ -4847,7 +4847,8 @@ var ClaudeTuiAdapter = class {
4847
4847
  structuredEvents: true,
4848
4848
  prefill: true,
4849
4849
  passiveTurns: true,
4850
- rawPromptGate: false
4850
+ rawPromptGate: false,
4851
+ prewarm: true
4851
4852
  };
4852
4853
  resolveBinary(env = process.env) {
4853
4854
  return env.CONVEYOR_CLAUDE_BIN ?? "claude";
@@ -4942,7 +4943,6 @@ var PtySession = class {
4942
4943
  // Raw-TUI input detection (see awaitRawTuiInputLive). `probeWindow`, when
4943
4944
  // non-null, accumulates raw output so a probe can look for its own sentinel
4944
4945
  // coming back.
4945
- spawnedAt = 0;
4946
4946
  // Set once the child writes a DEC private mode — it owns the tty from then on,
4947
4947
  // so the kernel no longer echoes our keystrokes and a sentinel coming back is
4948
4948
  // attributable to the app's own repaint.
@@ -5002,6 +5002,8 @@ var PtySession = class {
5002
5002
  turn;
5003
5003
  codexPromptInArgv = false;
5004
5004
  codexInitialPrompt;
5005
+ /** A fresh CLI intentionally started without input for checkout overlap. */
5006
+ prewarmed = false;
5005
5007
  codexSource = null;
5006
5008
  adapterCleanupPaths = [];
5007
5009
  onIdle(listener) {
@@ -5095,7 +5097,7 @@ var PtySession = class {
5095
5097
  * never set) keeps the Claude semantics byte-identical.
5096
5098
  */
5097
5099
  canReuse(resume, fingerprint) {
5098
- const resumeMatches = resume === void 0 ? this.reportedOpenCodeId !== null : resume === this.sessionUuid;
5100
+ const resumeMatches = resume === void 0 ? this.reportedOpenCodeId !== null || this.prewarmed : resume === this.sessionUuid;
5099
5101
  return !this._toreDown && !this.exited && this.activeQueue === null && // A parked questionnaire owns the terminal — a fed prompt would type
5100
5102
  // into the dialog. Force teardown + respawn instead.
5101
5103
  !this.questionnairePending && resumeMatches && fingerprint === this.spawnFingerprint;
@@ -5125,6 +5127,7 @@ var PtySession = class {
5125
5127
  if (this.betweenTurnBuffer.length > MAX_BETWEEN_TURN_BUFFER) {
5126
5128
  this.betweenTurnBuffer.shift();
5127
5129
  }
5130
+ if (this.prewarmed) return;
5128
5131
  if (!this.passiveSignaled) {
5129
5132
  this.passiveSignaled = true;
5130
5133
  this.passiveListener?.();
@@ -5136,8 +5139,10 @@ var PtySession = class {
5136
5139
  * the prompt into the live pty. The caller must have verified canReuse().
5137
5140
  */
5138
5141
  async beginTurn(prompt, options) {
5142
+ this.prewarmed = false;
5139
5143
  this.turnPrompt = prompt;
5140
5144
  this.turn = turnOptionsFrom(options);
5145
+ this.attachInput();
5141
5146
  this.resetForTurn();
5142
5147
  this.betweenTurnBuffer = [];
5143
5148
  this.activeQueue = new AsyncEventQueue();
@@ -5228,13 +5233,24 @@ var PtySession = class {
5228
5233
  }
5229
5234
  }
5230
5235
  async start() {
5236
+ await this.startInternal(true);
5237
+ }
5238
+ /** Start the CLI and its event plumbing without allocating a model turn. */
5239
+ async startParked() {
5240
+ this.prewarmed = true;
5241
+ await this.startInternal(false);
5242
+ }
5243
+ // oxlint-disable-next-line complexity -- adapter startup and turn gating share one teardown boundary
5244
+ async startInternal(feedPrompt) {
5231
5245
  await this.collectCodexPrompt();
5232
5246
  const sessionId = this.resume ?? this.options.sessionId;
5233
5247
  if (!sessionId) {
5234
5248
  throw new Error("PtySession requires options.sessionId or a resume target");
5235
5249
  }
5236
- this.activeQueue = new AsyncEventQueue();
5237
- this.turnStream = this.activeQueue.drain();
5250
+ if (feedPrompt) {
5251
+ this.activeQueue = new AsyncEventQueue();
5252
+ this.turnStream = this.activeQueue.drain();
5253
+ }
5238
5254
  const signal = this.turn.abortController?.signal;
5239
5255
  if (signal?.aborted) {
5240
5256
  await this.teardown();
@@ -5260,7 +5276,7 @@ var PtySession = class {
5260
5276
  model: this.options.model
5261
5277
  });
5262
5278
  }
5263
- if (signal) {
5279
+ if (signal && feedPrompt) {
5264
5280
  this.abortHandler = () => {
5265
5281
  void this.teardown();
5266
5282
  };
@@ -5271,10 +5287,10 @@ var PtySession = class {
5271
5287
  }
5272
5288
  }
5273
5289
  if (this.bridge) {
5274
- this.unsubInput = this.bridge.onInput((data) => this.writeStdin(data));
5290
+ if (feedPrompt) this.attachInput();
5275
5291
  this.unsubResize = this.bridge.onResize((cols, rows) => this.resizePty(cols, rows));
5276
5292
  }
5277
- await this.feedPrompt();
5293
+ if (feedPrompt) await this.feedPrompt();
5278
5294
  } catch (err) {
5279
5295
  await this.teardown();
5280
5296
  throw err;
@@ -5314,7 +5330,11 @@ var PtySession = class {
5314
5330
  session_id: id,
5315
5331
  model: this.options.model
5316
5332
  });
5317
- this.sendChatEvent({ kind: "init", model: this.options.model, claudeSessionId: id });
5333
+ this.sendChatEvent({
5334
+ kind: "init",
5335
+ model: this.options.model,
5336
+ claudeSessionId: id
5337
+ });
5318
5338
  },
5319
5339
  (event) => this.sendChatEvent(event)
5320
5340
  );
@@ -5352,7 +5372,11 @@ var PtySession = class {
5352
5372
  session_id: id,
5353
5373
  model: this.options.model
5354
5374
  });
5355
- this.sendChatEvent({ kind: "init", model: this.options.model, claudeSessionId: id });
5375
+ this.sendChatEvent({
5376
+ kind: "init",
5377
+ model: this.options.model,
5378
+ claudeSessionId: id
5379
+ });
5356
5380
  },
5357
5381
  (event) => this.sendChatEvent(event)
5358
5382
  );
@@ -5466,9 +5490,19 @@ var PtySession = class {
5466
5490
  this.pendingSyntheticQuestionIds = [];
5467
5491
  this.questionResultRemap.clear();
5468
5492
  for (const toolUseId of orphaned) {
5469
- this.sendChatEvent({ kind: "tool_result", toolUseId, output: "", isError: false });
5493
+ this.sendChatEvent({
5494
+ kind: "tool_result",
5495
+ toolUseId,
5496
+ output: "",
5497
+ isError: false
5498
+ });
5470
5499
  }
5471
5500
  }
5501
+ /** Attach relay keystrokes only once a Git-gated turn is allowed to accept them. */
5502
+ attachInput() {
5503
+ if (!this.bridge || this.unsubInput) return;
5504
+ this.unsubInput = this.bridge.onInput((data) => this.writeStdin(data));
5505
+ }
5472
5506
  writeStdin(text) {
5473
5507
  this.pty?.write(text);
5474
5508
  }
@@ -5635,7 +5669,6 @@ var PtySession = class {
5635
5669
  pty.onExit((event) => {
5636
5670
  void this.finalizeOnExit(event.exitCode);
5637
5671
  });
5638
- this.spawnedAt = Date.now();
5639
5672
  this.sawTerminalSetup = false;
5640
5673
  this.probeWindow = null;
5641
5674
  this.wroteToProcess = false;
@@ -5679,7 +5712,7 @@ var PtySession = class {
5679
5712
  if (!needsRawReadyGate(this.adapter.capabilities)) return;
5680
5713
  const timing = resolveRawTuiProbeTiming();
5681
5714
  const { sentinel } = timing;
5682
- const start = this.spawnedAt || Date.now();
5715
+ const start = Date.now();
5683
5716
  const setupDeadline = start + timing.firstOutputMaxMs;
5684
5717
  while (!this._toreDown && Date.now() < setupDeadline) {
5685
5718
  if (this.sawTerminalSetup) break;
@@ -5963,7 +5996,12 @@ var PtySession = class {
5963
5996
  }
5964
5997
  if (!this.adapter.capabilities.structuredEvents) {
5965
5998
  if (exitCode === 0) {
5966
- this.pushEvent({ type: "result", subtype: "success", result: "", total_cost_usd: 0 });
5999
+ this.pushEvent({
6000
+ type: "result",
6001
+ subtype: "success",
6002
+ result: "",
6003
+ total_cost_usd: 0
6004
+ });
5967
6005
  } else {
5968
6006
  this.pushEvent({
5969
6007
  type: "result",
@@ -6124,6 +6162,9 @@ var PtyHarness = class _PtyHarness {
6124
6162
  authNoticeSent = false;
6125
6163
  /** Once-per-process guard on the pod-recycle escalation (see escalateToPodRecycle). */
6126
6164
  recycleRequested = false;
6165
+ disposed = false;
6166
+ prewarming = null;
6167
+ prewarmInFlight = null;
6127
6168
  /**
6128
6169
  * Wiggle the live pty's size so the CLI repaints its whole screen. No-op on
6129
6170
  * the SDK harness. Falls back to the parked session so an API reconnect while
@@ -6184,6 +6225,60 @@ var PtyHarness = class _PtyHarness {
6184
6225
  yield* this.drain(session);
6185
6226
  yield* this.recoverFailedDelivery(session, options, want);
6186
6227
  }
6228
+ /**
6229
+ * Prepare a fresh TUI while another boot task runs. This deliberately does
6230
+ * not send stdin or create an active event queue, so no model/tool work can
6231
+ * begin before the runner releases its checkout and WIP gates.
6232
+ */
6233
+ async prewarm(options) {
6234
+ if (this.prewarmInFlight) return this.prewarmInFlight;
6235
+ const pending = this.startPrewarm(options);
6236
+ this.prewarmInFlight = pending;
6237
+ try {
6238
+ return await pending;
6239
+ } finally {
6240
+ this.prewarmInFlight = null;
6241
+ }
6242
+ }
6243
+ async startPrewarm(options) {
6244
+ if (this.disposed || !this.adapter.capabilities.prewarm) return false;
6245
+ const startedAt = Date.now();
6246
+ const prepared = ensureSessionTarget(options, void 0);
6247
+ if (prepared !== options) {
6248
+ _PtyHarness.log.warn("prewarm had no session target \u2014 minted one", {
6249
+ sessionId: prepared.sessionId
6250
+ });
6251
+ }
6252
+ const fingerprint = this.fingerprintOf(prepared);
6253
+ if (this.parked?.canReuse(void 0, fingerprint) && !await this.parkedHomeDied(prepared)) {
6254
+ _PtyHarness.log.info("TUI prewarm reused parked process", {
6255
+ elapsedMs: Date.now() - startedAt
6256
+ });
6257
+ return true;
6258
+ }
6259
+ if (this.parked) {
6260
+ const stale = this.parked;
6261
+ this.parked = null;
6262
+ this.cancelEndedTimer();
6263
+ await stale.teardown();
6264
+ }
6265
+ if (this.disposed) return false;
6266
+ _PtyHarness.log.info("TUI prewarm starting fresh process");
6267
+ const session = await this.spawnSession("", prepared, void 0, true, (created) => {
6268
+ this.prewarming = created;
6269
+ });
6270
+ this.prewarming = null;
6271
+ if (this.disposed) {
6272
+ await session.teardown();
6273
+ this.notifyEnded();
6274
+ return false;
6275
+ }
6276
+ this.park(session);
6277
+ _PtyHarness.log.info("TUI prewarm process started", {
6278
+ elapsedMs: Date.now() - startedAt
6279
+ });
6280
+ return true;
6281
+ }
6187
6282
  /**
6188
6283
  * Did the shared `~/.claude` mount die while this session sat parked?
6189
6284
  *
@@ -6220,8 +6315,9 @@ var PtyHarness = class _PtyHarness {
6220
6315
  * environment preparation (config-home health, credential synthesis,
6221
6316
  * auth-readiness warning) and registering the parked-death watch.
6222
6317
  */
6223
- async spawnSession(prompt, options, want) {
6318
+ async spawnSession(prompt, options, want, parked = false, onAllocated) {
6224
6319
  const session = new PtySession(prompt, options, want, this.bridge, this.adapter);
6320
+ onAllocated?.(session);
6225
6321
  if (this.ownsClaudeConfigHome) {
6226
6322
  await ensureUsableClaudeConfigHome(options.cwd, _PtyHarness.log);
6227
6323
  }
@@ -6230,7 +6326,8 @@ var PtyHarness = class _PtyHarness {
6230
6326
  await this.warnIfAuthNotReady();
6231
6327
  }
6232
6328
  session.onExit(() => this.handleSessionExit(session));
6233
- await session.start();
6329
+ if (parked) await session.startParked();
6330
+ else await session.start();
6234
6331
  return session;
6235
6332
  }
6236
6333
  /**
@@ -6402,10 +6499,21 @@ var PtyHarness = class _PtyHarness {
6402
6499
  * the Connected-TUI tab hides promptly.
6403
6500
  */
6404
6501
  async dispose() {
6502
+ this.disposed = true;
6405
6503
  this.cancelEndedTimer();
6406
- const toKill = [this.parked, this.activeSession].filter((s) => s !== null);
6504
+ try {
6505
+ await this.prewarmInFlight;
6506
+ } catch (error) {
6507
+ _PtyHarness.log.warn("TUI prewarm failed during disposal", {
6508
+ error: error instanceof Error ? error.message : String(error)
6509
+ });
6510
+ }
6511
+ const toKill = [.../* @__PURE__ */ new Set([this.parked, this.activeSession, this.prewarming])].filter(
6512
+ (s) => s !== null
6513
+ );
6407
6514
  this.parked = null;
6408
6515
  this.activeSession = null;
6516
+ this.prewarming = null;
6409
6517
  for (const session of toKill) {
6410
6518
  try {
6411
6519
  await session.teardown();
@@ -6847,7 +6955,8 @@ var OpenCodeTuiAdapter = class {
6847
6955
  // opencode silently discards early stdin while the TUI paints; the pasted
6848
6956
  // text itself is lost, so the readiness probe must gate the first write
6849
6957
  // even though structured events exist now.
6850
- rawPromptGate: true
6958
+ rawPromptGate: true,
6959
+ prewarm: true
6851
6960
  };
6852
6961
  resolveBinary(env = this.env) {
6853
6962
  const override = env.CONVEYOR_OPENCODE_BIN;
@@ -7011,7 +7120,8 @@ var CodexTuiAdapter = class {
7011
7120
  structuredEvents: true,
7012
7121
  prefill: true,
7013
7122
  passiveTurns: true,
7014
- rawPromptGate: true
7123
+ rawPromptGate: true,
7124
+ prewarm: true
7015
7125
  };
7016
7126
  resolveBinary(env = this.env) {
7017
7127
  const path = findOnPath(env.CONVEYOR_CODEX_BIN ?? "codex", env);
@@ -8186,6 +8296,7 @@ function buildParentReviewPrompt() {
8186
8296
  var TYPE_PRIORITY = { rule: 0, doc: 1, file: 2, folder: 3 };
8187
8297
  var SUMMARY_SCAN_CHARS = 4e3;
8188
8298
  var SUMMARY_MAX_CHARS = 160;
8299
+ var CONTEXT_READ_CONCURRENCY = 4;
8189
8300
  var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
8190
8301
  ".png",
8191
8302
  ".jpg",
@@ -8288,24 +8399,61 @@ async function readFolderListing(folderPath) {
8288
8399
  return null;
8289
8400
  }
8290
8401
  }
8291
- async function resolveEntry(entry) {
8292
- const result = {
8293
- type: entry.type,
8294
- path: entry.path,
8295
- label: entry.label,
8296
- summary: null
8297
- };
8298
- if (entry.label) {
8299
- result.summary = truncateSummary(entry.label);
8402
+ var ContextReadCoordinator = class {
8403
+ availableSlots = CONTEXT_READ_CONCURRENCY;
8404
+ waitingReaders = [];
8405
+ pendingSummaries = /* @__PURE__ */ new Map();
8406
+ async resolveEntry(entry) {
8407
+ const result = {
8408
+ type: entry.type,
8409
+ path: entry.path,
8410
+ label: entry.label,
8411
+ summary: null
8412
+ };
8413
+ if (entry.label) {
8414
+ result.summary = truncateSummary(entry.label);
8415
+ return result;
8416
+ }
8417
+ result.summary = await this.readSummary(entry);
8300
8418
  return result;
8301
8419
  }
8302
- if (entry.type === "folder") {
8303
- result.summary = await readFolderListing(entry.path);
8304
- return result;
8420
+ readSummary(entry) {
8421
+ const kind = entry.type === "folder" ? "folder" : "file";
8422
+ const key = `${kind}:${entry.path}`;
8423
+ const pending = this.pendingSummaries.get(key);
8424
+ if (pending) return pending;
8425
+ const read = this.limit(
8426
+ () => kind === "folder" ? readFolderListing(entry.path) : readFileSummary(entry.path)
8427
+ );
8428
+ this.pendingSummaries.set(key, read);
8429
+ return read;
8305
8430
  }
8306
- result.summary = await readFileSummary(entry.path);
8307
- return result;
8308
- }
8431
+ async limit(read) {
8432
+ await this.acquireSlot();
8433
+ try {
8434
+ return await read();
8435
+ } finally {
8436
+ this.releaseSlot();
8437
+ }
8438
+ }
8439
+ async acquireSlot() {
8440
+ if (this.availableSlots > 0) {
8441
+ this.availableSlots -= 1;
8442
+ return;
8443
+ }
8444
+ await new Promise((resolve) => {
8445
+ this.waitingReaders.push(resolve);
8446
+ });
8447
+ }
8448
+ releaseSlot() {
8449
+ const nextReader = this.waitingReaders.shift();
8450
+ if (nextReader) {
8451
+ nextReader();
8452
+ return;
8453
+ }
8454
+ this.availableSlots += 1;
8455
+ }
8456
+ };
8309
8457
  function formatEntry(entry) {
8310
8458
  const suffix = entry.summary ? ` \u2014 ${entry.summary}` : "";
8311
8459
  return `- \`${entry.path}\`${suffix}`;
@@ -8360,39 +8508,33 @@ function formatResolvedTags(resolved, subProject, mentioned, runnerMode) {
8360
8508
  }
8361
8509
  return parts.join("\n");
8362
8510
  }
8363
- async function resolveEntries(contextPaths) {
8364
- if (!contextPaths?.length) return [];
8511
+ function resolveEntries(contextPaths, coordinator) {
8512
+ if (!contextPaths?.length) return Promise.resolve([]);
8365
8513
  const sorted = [...contextPaths].sort(
8366
8514
  (a, b) => (TYPE_PRIORITY[a.type] ?? 99) - (TYPE_PRIORITY[b.type] ?? 99)
8367
8515
  );
8368
- const results = [];
8369
- for (const entry of sorted) {
8370
- results.push(await resolveEntry(entry));
8371
- }
8372
- return results;
8516
+ return Promise.all(sorted.map((entry) => coordinator.resolveEntry(entry)));
8373
8517
  }
8374
8518
  function countResolved(entries) {
8375
8519
  const injected = entries.filter((e) => e.summary !== null).length;
8376
8520
  return { injected, skipped: entries.length - injected };
8377
8521
  }
8378
- async function resolveAssignedTags(assignedTags) {
8379
- const resolved = [];
8380
- let injected = 0;
8381
- let skipped = 0;
8382
- for (const tag of assignedTags) {
8383
- const entries = await resolveEntries(tag.contextPaths);
8384
- const counts = countResolved(entries);
8385
- injected += counts.injected;
8386
- skipped += counts.skipped;
8387
- resolved.push({
8522
+ async function resolveAssignedTags(assignedTags, coordinator) {
8523
+ const resolved = await Promise.all(
8524
+ assignedTags.map(async (tag) => ({
8388
8525
  tagName: tag.name,
8389
8526
  description: tag.description,
8390
- entries,
8527
+ entries: await resolveEntries(tag.contextPaths, coordinator),
8391
8528
  hasOverview: tag.hasOverview,
8392
8529
  overviewPath: tag.overviewPath ?? null
8393
- });
8394
- }
8395
- return { resolved, injected, skipped };
8530
+ }))
8531
+ );
8532
+ const counts = resolved.map((tag) => countResolved(tag.entries));
8533
+ return {
8534
+ resolved,
8535
+ injected: counts.reduce((total, current) => total + current.injected, 0),
8536
+ skipped: counts.reduce((total, current) => total + current.skipped, 0)
8537
+ };
8396
8538
  }
8397
8539
  async function resolveTagContext(projectTags, taskTagIds, _model, _betas, runnerMode, subProject, mentionedTagIds) {
8398
8540
  const taskTagIdSet = new Set(taskTagIds);
@@ -8406,30 +8548,26 @@ async function resolveTagContext(projectTags, taskTagIds, _model, _betas, runner
8406
8548
  if (!hasTagPaths && !hasSubProjectPaths && mentionedTags.length === 0) {
8407
8549
  return { injectedSection: "", stats: { injected: 0, skipped: 0 } };
8408
8550
  }
8409
- const {
8410
- resolved,
8411
- injected: tagInjected,
8412
- skipped: tagSkipped
8413
- } = await resolveAssignedTags(assignedTags);
8414
- const { resolved: mentionedResolved } = await resolveAssignedTags(mentionedTags);
8415
- let subProjectResolved = null;
8416
- let subInjected = 0;
8417
- let subSkipped = 0;
8418
- if (subProject && hasSubProjectPaths) {
8419
- const entries = await resolveEntries(subProject.contextPaths);
8420
- const counts = countResolved(entries);
8421
- subInjected = counts.injected;
8422
- subSkipped = counts.skipped;
8423
- subProjectResolved = { name: subProject.name, entries };
8424
- }
8551
+ const coordinator = new ContextReadCoordinator();
8552
+ const subProjectEntries = subProject && hasSubProjectPaths ? resolveEntries(subProject.contextPaths, coordinator) : Promise.resolve(null);
8553
+ const [assigned, mentioned, subProjectResolvedEntries] = await Promise.all([
8554
+ resolveAssignedTags(assignedTags, coordinator),
8555
+ resolveAssignedTags(mentionedTags, coordinator),
8556
+ subProjectEntries
8557
+ ]);
8558
+ const subProjectResolved = subProject && subProjectResolvedEntries ? { name: subProject.name, entries: subProjectResolvedEntries } : null;
8559
+ const subProjectCounts = subProjectResolvedEntries ? countResolved(subProjectResolvedEntries) : { injected: 0, skipped: 0 };
8425
8560
  return {
8426
8561
  injectedSection: formatResolvedTags(
8427
- resolved,
8562
+ assigned.resolved,
8428
8563
  subProjectResolved,
8429
- mentionedResolved,
8564
+ mentioned.resolved,
8430
8565
  runnerMode
8431
8566
  ),
8432
- stats: { injected: tagInjected + subInjected, skipped: tagSkipped + subSkipped }
8567
+ stats: {
8568
+ injected: assigned.injected + subProjectCounts.injected,
8569
+ skipped: assigned.skipped + subProjectCounts.skipped
8570
+ }
8433
8571
  };
8434
8572
  }
8435
8573
 
@@ -14207,7 +14345,11 @@ function buildQueryOptions(host, context) {
14207
14345
  const systemPromptText = buildSystemPrompt(
14208
14346
  host.config.mode,
14209
14347
  context,
14210
- { ...host.config, isAuto: host.isAuto, runtimeTui: process.env.CONVEYOR_TUI },
14348
+ {
14349
+ ...host.config,
14350
+ isAuto: host.isAuto,
14351
+ runtimeTui: process.env.CONVEYOR_TUI
14352
+ },
14211
14353
  host.setupLog,
14212
14354
  mode
14213
14355
  );
@@ -14268,7 +14410,11 @@ function buildMultimodalPrompt(textPrompt, context, skipImages = false) {
14268
14410
  for (const msg of context.chatHistory) {
14269
14411
  for (const f2 of msg.files ?? []) {
14270
14412
  if (f2.content && f2.contentEncoding === "base64") {
14271
- chatImages.push({ fileName: f2.fileName, mimeType: f2.mimeType, content: f2.content });
14413
+ chatImages.push({
14414
+ fileName: f2.fileName,
14415
+ mimeType: f2.mimeType,
14416
+ content: f2.content
14417
+ });
14272
14418
  }
14273
14419
  }
14274
14420
  }
@@ -14283,14 +14429,24 @@ function buildMultimodalPrompt(textPrompt, context, skipImages = false) {
14283
14429
  data: file.content ?? ""
14284
14430
  }
14285
14431
  });
14286
- blocks.push({ type: "text", text: `[Attached image: ${file.fileName} (${file.mimeType})]` });
14432
+ blocks.push({
14433
+ type: "text",
14434
+ text: `[Attached image: ${file.fileName} (${file.mimeType})]`
14435
+ });
14287
14436
  }
14288
14437
  for (const file of chatImages) {
14289
14438
  blocks.push({
14290
14439
  type: "image",
14291
- source: { type: "base64", media_type: file.mimeType, data: file.content }
14440
+ source: {
14441
+ type: "base64",
14442
+ media_type: file.mimeType,
14443
+ data: file.content
14444
+ }
14445
+ });
14446
+ blocks.push({
14447
+ type: "text",
14448
+ text: `[Chat image: ${file.fileName} (${file.mimeType})]`
14292
14449
  });
14293
- blocks.push({ type: "text", text: `[Chat image: ${file.fileName} (${file.mimeType})]` });
14294
14450
  }
14295
14451
  return blocks;
14296
14452
  }
@@ -14448,7 +14604,7 @@ async function* watchForParkedTui(inner, host, opts) {
14448
14604
  function takesPlannerOpeningTurn(host, mode) {
14449
14605
  return host.config.mode === "plan" && mode === "discovery";
14450
14606
  }
14451
- async function runSdkQuery(host, context, followUpContent, promptDeliveryOverride) {
14607
+ async function runSdkQuery(host, context, followUpContent, promptDeliveryOverride, freshPrewarmed = false) {
14452
14608
  if (host.isStopped()) return;
14453
14609
  const mode = host.agentMode;
14454
14610
  const isDiscoveryLike = mode === "discovery" || mode === "help";
@@ -14457,7 +14613,7 @@ async function runSdkQuery(host, context, followUpContent, promptDeliveryOverrid
14457
14613
  host.config.workspaceDir,
14458
14614
  host.config.mode === "code-review" && process.env.CONVEYOR_TUI !== "codex" ? "claude-code" : process.env.CONVEYOR_TUI
14459
14615
  );
14460
- const hasExistingSession = !!sessionStart.resume;
14616
+ const hasExistingSession = !!sessionStart.resume && !freshPrewarmed;
14461
14617
  const promptDelivery = promptDeliveryOverride ?? resolvePromptDelivery({
14462
14618
  harnessKind: host.harnessKind,
14463
14619
  runnerMode: host.config.mode,
@@ -14479,11 +14635,49 @@ async function runSdkQuery(host, context, followUpContent, promptDeliveryOverrid
14479
14635
  if (isDiscoveryLike && host.harnessKind === "sdk") {
14480
14636
  return;
14481
14637
  }
14482
- if (isDiscoveryLike && resume && !takesPlannerOpeningTurn(host, mode)) {
14638
+ if (isDiscoveryLike && resume && !freshPrewarmed && !takesPlannerOpeningTurn(host, mode)) {
14483
14639
  return;
14484
14640
  }
14485
14641
  await runInitialQuery(host, context, options, resume, promptDelivery);
14486
14642
  }
14643
+ async function prewarmInitialTuiQuery(host, context) {
14644
+ if (host.harnessKind !== "pty" || !host.harness.prewarm) return false;
14645
+ const mode = host.agentMode;
14646
+ const sessionStart = resolveSessionStart(
14647
+ sessionLineageKey(context.taskId, mode, host.config.mode),
14648
+ host.config.workspaceDir,
14649
+ host.config.mode === "code-review" && process.env.CONVEYOR_TUI !== "codex" ? "claude-code" : process.env.CONVEYOR_TUI
14650
+ );
14651
+ if (sessionStart.resume) return false;
14652
+ const promptDelivery = resolvePromptDelivery({
14653
+ harnessKind: host.harnessKind,
14654
+ runnerMode: host.config.mode,
14655
+ isAuto: host.isAuto,
14656
+ agentMode: mode,
14657
+ isFollowUp: false,
14658
+ hasExistingSession: false
14659
+ });
14660
+ const options = {
14661
+ ...buildQueryOptions(host, context),
14662
+ promptDelivery,
14663
+ ...sessionStart.sessionId ? { sessionId: sessionStart.sessionId } : {}
14664
+ };
14665
+ const initialPrompt = await buildInitialPrompt(
14666
+ host.config.mode,
14667
+ context,
14668
+ host.isAuto,
14669
+ host.agentMode,
14670
+ host.config.packExecution
14671
+ );
14672
+ const { appendSystemPrompt } = selectInitialPromptInput(
14673
+ promptDelivery,
14674
+ initialPrompt,
14675
+ context,
14676
+ options.appendSystemPrompt,
14677
+ host.harnessKind
14678
+ );
14679
+ return host.harness.prewarm({ ...options, appendSystemPrompt });
14680
+ }
14487
14681
  async function runFollowUpQuery(host, context, options, resume, followUpContent) {
14488
14682
  if (options.promptDelivery === "prefill") {
14489
14683
  await runPrefilledFollowUp(host, context, options, resume, followUpContent);
@@ -14809,7 +15003,10 @@ function handleRetryError(error, context, host, options, prevImageError) {
14809
15003
  return handleAuthError(context, host, options);
14810
15004
  }
14811
15005
  if (!isRetriableError(error)) throw error;
14812
- return { action: "continue", lastErrorWasImage: classifyImageError(error) || prevImageError };
15006
+ return {
15007
+ action: "continue",
15008
+ lastErrorWasImage: classifyImageError(error) || prevImageError
15009
+ };
14813
15010
  }
14814
15011
  function handleProcessResult(result, context, host, options) {
14815
15012
  if (result.modeRestart || host.isStopped()) return { action: "return" };
@@ -14826,10 +15023,16 @@ function handleProcessResult(result, context, host, options) {
14826
15023
  };
14827
15024
  }
14828
15025
  if (result.staleSession && context.claudeSessionId) {
14829
- return { action: "return_promise", promise: handleStaleSession(context, host, options) };
15026
+ return {
15027
+ action: "return_promise",
15028
+ promise: handleStaleSession(context, host, options)
15029
+ };
14830
15030
  }
14831
15031
  if (result.authError) {
14832
- return { action: "return_promise", promise: handleAuthError(context, host, options) };
15032
+ return {
15033
+ action: "return_promise",
15034
+ promise: handleAuthError(context, host, options)
15035
+ };
14833
15036
  }
14834
15037
  if (!result.retriable) return { action: "return" };
14835
15038
  return {
@@ -14937,6 +15140,7 @@ var QueryBridge = class {
14937
15140
  _apiOutageDetail = null;
14938
15141
  _keyCycleCount = 0;
14939
15142
  _abortController = null;
15143
+ freshPrewarmedInitial = false;
14940
15144
  /** Called by SessionRunner when ExitPlanMode triggers a mode transition. */
14941
15145
  onModeTransition;
14942
15146
  /** Called by tool handlers to soft-stop (abort query, keep session alive). */
@@ -14992,6 +15196,19 @@ var QueryBridge = class {
14992
15196
  forceRepaint() {
14993
15197
  this.harness.forceRepaint?.();
14994
15198
  }
15199
+ /** Warm a fresh interactive task TUI only. It receives no input until SessionRunner's Git gate releases. */
15200
+ async prewarmInitial(context) {
15201
+ try {
15202
+ const warmed = await prewarmInitialTuiQuery(this.buildHost(), context);
15203
+ this.freshPrewarmedInitial = warmed;
15204
+ return warmed;
15205
+ } catch (err) {
15206
+ logger6.warn("TUI prewarm failed; continuing with normal startup", {
15207
+ error: err instanceof Error ? err.message : String(err)
15208
+ });
15209
+ return false;
15210
+ }
15211
+ }
14995
15212
  stop() {
14996
15213
  this._stopped = true;
14997
15214
  this._abortController?.abort();
@@ -15041,7 +15258,7 @@ var QueryBridge = class {
15041
15258
  isAuto: this.mode.isAuto,
15042
15259
  agentMode: this.mode.effectiveMode,
15043
15260
  isFollowUp: false,
15044
- hasExistingSession: hasExistingSessionFile(context.taskId, this.runnerConfig.workspaceDir, {
15261
+ hasExistingSession: !this.freshPrewarmedInitial && hasExistingSessionFile(context.taskId, this.runnerConfig.workspaceDir, {
15045
15262
  agentMode: this.mode.effectiveMode,
15046
15263
  runnerMode: this.runnerConfig.mode
15047
15264
  })
@@ -15064,7 +15281,9 @@ var QueryBridge = class {
15064
15281
  this._abortController = new AbortController();
15065
15282
  const host = this.buildHost();
15066
15283
  try {
15067
- await runSdkQuery(host, context, followUpContent, promptDelivery);
15284
+ const freshPrewarmed = !followUpContent && this.freshPrewarmedInitial;
15285
+ this.freshPrewarmedInitial = false;
15286
+ await runSdkQuery(host, context, followUpContent, promptDelivery, freshPrewarmed);
15068
15287
  } catch (err) {
15069
15288
  const msg = err instanceof Error ? err.message : String(err);
15070
15289
  const isAbort = this._stopped || /abort/i.test(msg);
@@ -15781,7 +16000,10 @@ var SessionRunner = class _SessionRunner {
15781
16000
  });
15782
16001
  const initialMode = config.agentMode ?? (config.runnerMode === "pm" ? config.isAuto ? "auto" : "discovery" : "building");
15783
16002
  this.mode = new ModeController(initialMode, config.runnerMode, config.isAuto);
15784
- const lifecycleConfig = { ...DEFAULT_LIFECYCLE_CONFIG, ...config.lifecycle };
16003
+ const lifecycleConfig = {
16004
+ ...DEFAULT_LIFECYCLE_CONFIG,
16005
+ ...config.lifecycle
16006
+ };
15785
16007
  this.lifecycle = new Lifecycle(lifecycleConfig, {
15786
16008
  onHeartbeat: () => {
15787
16009
  const loopStatus = this.refreshLoopStatus();
@@ -16140,6 +16362,10 @@ var SessionRunner = class _SessionRunner {
16140
16362
  await this.shutdown("error");
16141
16363
  return;
16142
16364
  }
16365
+ this.mode.applyServerMode(this.fullContext?.agentMode, this.fullContext?.isAuto);
16366
+ this.mode.resolveInitialMode(this.taskContext);
16367
+ this.queryBridge = this.createQueryBridge();
16368
+ const prewarmInitial = this.queryBridge.prewarmInitial(this.fullContext);
16143
16369
  const gitState = await awaitGitReady({
16144
16370
  onLog: (m) => process.stderr.write(`[conveyor-agent] ${m}
16145
16371
  `)
@@ -16148,6 +16374,7 @@ var SessionRunner = class _SessionRunner {
16148
16374
  const message = gitState === "failed" ? "Workspace git preparation failed (see pod logs)" : "Workspace git preparation timed out (see pod logs)";
16149
16375
  this.connection.sendEvent({ type: "error", message });
16150
16376
  await this.callbacks.onEvent({ type: "error", message });
16377
+ await this.queryBridge.dispose();
16151
16378
  await this.shutdown("error");
16152
16379
  return;
16153
16380
  }
@@ -16161,8 +16388,8 @@ var SessionRunner = class _SessionRunner {
16161
16388
  process.stderr.write("[conveyor-agent] WARNING: task-branch checkout failed\n");
16162
16389
  }
16163
16390
  if (ok) void reportBootMilestone({ key: "branch_ready" });
16164
- await this.refreshSkillsForCheckout();
16165
16391
  }
16392
+ if (this.fullContext?.githubBranch) await this.refreshSkillsForCheckout();
16166
16393
  if (!this.stopped) {
16167
16394
  this.lifecycle.startGitFlush();
16168
16395
  }
@@ -16177,13 +16404,15 @@ var SessionRunner = class _SessionRunner {
16177
16404
  }
16178
16405
  }
16179
16406
  this.workspaceCommands?.notifyWorkspaceReady();
16180
- this.mode.applyServerMode(this.fullContext?.agentMode, this.fullContext?.isAuto);
16181
- this.mode.resolveInitialMode(this.taskContext);
16182
16407
  if (this.fullContext?.isAuto && PRE_BUILD_TASK_STATUSES.has(this.taskContext.status) && this.mode.isBuildCapable && hasTaskPlan(this.fullContext.plan)) {
16183
16408
  void this.connection.triggerIdentification().catch(() => {
16184
16409
  });
16185
16410
  }
16186
- this.queryBridge = this.createQueryBridge();
16411
+ await prewarmInitial;
16412
+ if (this.stopped) {
16413
+ await this.queryBridge.dispose();
16414
+ return;
16415
+ }
16187
16416
  this.logInitialization();
16188
16417
  const staleBatch = [...this.pendingMessages];
16189
16418
  const didExecuteInitialQuery = await this.executeInitialMode();
@@ -16376,7 +16605,11 @@ var SessionRunner = class _SessionRunner {
16376
16605
  }
16377
16606
  if (delivery === "prefill") {
16378
16607
  await this.setState("waiting_for_input");
16379
- await this.callbacks.onEvent({ type: "execute_mode", mode: effectiveMode, delivery });
16608
+ await this.callbacks.onEvent({
16609
+ type: "execute_mode",
16610
+ mode: effectiveMode,
16611
+ delivery
16612
+ });
16380
16613
  if (this.pendingMessages.length > 0) {
16381
16614
  if (!this.stopped) await this.setState("idle");
16382
16615
  return false;
@@ -16389,7 +16622,10 @@ var SessionRunner = class _SessionRunner {
16389
16622
  }
16390
16623
  } else {
16391
16624
  await this.setState("running");
16392
- await this.callbacks.onEvent({ type: "execute_mode", mode: effectiveMode });
16625
+ await this.callbacks.onEvent({
16626
+ type: "execute_mode",
16627
+ mode: effectiveMode
16628
+ });
16393
16629
  await this.executeQuery(void 0, delivery);
16394
16630
  await this.requeueWedgedInitialQuery(delivery);
16395
16631
  }
@@ -16872,7 +17108,11 @@ var SessionRunner = class _SessionRunner {
16872
17108
  const oldMode = this.mode.effectiveMode;
16873
17109
  process.stderr.write(`[conveyor-agent] Mode transition: ${oldMode} \u2192 ${newMode}
16874
17110
  `);
16875
- this.connection.sendEvent({ type: "mode_transition", from: oldMode, to: newMode });
17111
+ this.connection.sendEvent({
17112
+ type: "mode_transition",
17113
+ from: oldMode,
17114
+ to: newMode
17115
+ });
16876
17116
  this.mode.pendingModeRestart = true;
16877
17117
  this.connection.emitModeChanged(newMode);
16878
17118
  this.softStop();
@@ -128,7 +128,7 @@ function errText(err) {
128
128
  }
129
129
  async function syncTaskBranchToRepo(deps, paths) {
130
130
  const { git, log } = deps;
131
- const { branch, baseBranch } = deps.bundle.gitPlan;
131
+ const { branch } = deps.bundle.gitPlan;
132
132
  try {
133
133
  await git(["remote", "set-url", "origin", paths.remoteUrl], {
134
134
  cwd: paths.repoDir,
@@ -140,6 +140,18 @@ async function syncTaskBranchToRepo(deps, paths) {
140
140
  }
141
141
  const credentialFailure = await persistCredentialHelper(deps, paths);
142
142
  if (credentialFailure) return credentialFailure;
143
+ const [, resetSucceeded] = await Promise.all([
144
+ warmBaseBranch(deps, paths),
145
+ resetTrackedChanges(deps, paths)
146
+ ]);
147
+ if (!resetSucceeded) return { state: "failed", reason: "pre-checkout reset failed" };
148
+ log.info(`[boot] Repo remote ready; agent will checkout ${branch}`);
149
+ return { state: "ready" };
150
+ }
151
+ async function warmBaseBranch(deps, paths) {
152
+ const { git, log } = deps;
153
+ const { baseBranch } = deps.bundle.gitPlan;
154
+ const started = performance.now();
143
155
  try {
144
156
  await git(["fetch", "origin", `+refs/heads/${baseBranch}:refs/remotes/origin/${baseBranch}`], {
145
157
  cwd: paths.repoDir,
@@ -147,17 +159,24 @@ async function syncTaskBranchToRepo(deps, paths) {
147
159
  });
148
160
  } catch (err) {
149
161
  log.warn(`[boot] WARN: fetch origin/${baseBranch} failed: ${errText(err)}`);
162
+ } finally {
163
+ log.info(`[boot] step=gitFetchBase ms=${Math.round(performance.now() - started)}`);
150
164
  }
165
+ }
166
+ async function resetTrackedChanges(deps, paths) {
167
+ const { git, log } = deps;
168
+ const started = performance.now();
151
169
  try {
152
170
  await git(["reset", "--hard", "HEAD"], { cwd: paths.repoDir, timeoutMs: QUICK_GIT_TIMEOUT_MS });
171
+ return true;
153
172
  } catch (err) {
154
173
  log.error(
155
174
  `[boot] ERROR: failed to clean tracked repo changes before checkout: ${errText(err)}`
156
175
  );
157
- return { state: "failed", reason: "pre-checkout reset failed" };
176
+ return false;
177
+ } finally {
178
+ log.info(`[boot] step=gitResetTracked ms=${Math.round(performance.now() - started)}`);
158
179
  }
159
- log.info(`[boot] Repo remote ready; agent will checkout ${branch}`);
160
- return { state: "ready" };
161
180
  }
162
181
  async function persistCredentialHelper(deps, paths) {
163
182
  try {
@@ -5,10 +5,10 @@ import {
5
5
  readWorkspaceBytes,
6
6
  statWorkspacePath,
7
7
  workspacePathExists
8
- } from "./chunk-WS7QRB37.js";
8
+ } from "./chunk-JBGPARLG.js";
9
9
  import {
10
10
  reportBootMilestone
11
- } from "./chunk-GL2DIQEQ.js";
11
+ } from "./chunk-Q4FQOJ7D.js";
12
12
  import {
13
13
  runSetupCommand,
14
14
  runStartCommand,
package/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  WorkspaceCommandSupervisor,
8
8
  startWorkspaceCommandsAfterConnect,
9
9
  stopWorkspaceCommands
10
- } from "./chunk-GZRZGBIK.js";
10
+ } from "./chunk-SKTNJNXQ.js";
11
11
  import {
12
12
  DEFAULT_SONNET_MODEL,
13
13
  PtyHarness,
@@ -28,8 +28,8 @@ import {
28
28
  runUsageProbe,
29
29
  sampleKeyUsage,
30
30
  usesNativeUsageReporting
31
- } from "./chunk-N5LEVAGA.js";
32
- import "./chunk-SR66HQKB.js";
31
+ } from "./chunk-POK3QCGN.js";
32
+ import "./chunk-37J5MMQT.js";
33
33
  import {
34
34
  inheritedEnv,
35
35
  resolvePtySpawn,
@@ -45,8 +45,8 @@ import {
45
45
  createServiceLogger,
46
46
  fetchBootstrap,
47
47
  loadConveyorConfig
48
- } from "./chunk-WS7QRB37.js";
49
- import "./chunk-GL2DIQEQ.js";
48
+ } from "./chunk-JBGPARLG.js";
49
+ import "./chunk-Q4FQOJ7D.js";
50
50
  import "./chunk-W4LZ7R6Z.js";
51
51
  import "./chunk-372R6E4C.js";
52
52
  import "./chunk-IA45XHOA.js";
@@ -1206,7 +1206,7 @@ function wireSpawnChildren(mode, connection, supervisors, logger7) {
1206
1206
 
1207
1207
  // src/cli.ts
1208
1208
  if (process.argv[2] === "boot") {
1209
- const { runBoot } = await import("./boot-4ZNOCKFZ.js");
1209
+ const { runBoot } = await import("./boot-Z3EBJ7GX.js");
1210
1210
  process.exit(await runBoot(process.argv.slice(3)));
1211
1211
  }
1212
1212
  if (isLegacyEntrypointLaunch(process.env)) {
@@ -1459,7 +1459,7 @@ if (!RUNNER_MODES.includes(CONVEYOR_MODE)) {
1459
1459
  process.exit(1);
1460
1460
  }
1461
1461
  if (CONVEYOR_MODE === "serving") {
1462
- const { runServingSession } = await import("./serve-boot-RU5BYIK4.js");
1462
+ const { runServingSession } = await import("./serve-boot-4BUN4U44.js");
1463
1463
  exitContext.runnerMode = "serving";
1464
1464
  exitContext.sessionId = process.env.CONVEYOR_SESSION_ID ?? exitContext.sessionId;
1465
1465
  const outcome = await runServingSession({
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  SessionRunner,
3
3
  unshallowRepo
4
- } from "./chunk-N5LEVAGA.js";
5
- import "./chunk-SR66HQKB.js";
4
+ } from "./chunk-POK3QCGN.js";
5
+ import "./chunk-37J5MMQT.js";
6
6
  import "./chunk-W5INK3NE.js";
7
7
  import {
8
8
  AgentConnection,
@@ -17,8 +17,8 @@ import {
17
17
  stageAndCommit,
18
18
  updateRemoteToken,
19
19
  workspacePathExists
20
- } from "./chunk-WS7QRB37.js";
21
- import "./chunk-GL2DIQEQ.js";
20
+ } from "./chunk-JBGPARLG.js";
21
+ import "./chunk-Q4FQOJ7D.js";
22
22
  import {
23
23
  runAuthTokenCommand,
24
24
  runSetupCommand,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  WorkspaceCommandSupervisor
3
- } from "./chunk-GZRZGBIK.js";
3
+ } from "./chunk-SKTNJNXQ.js";
4
4
  import {
5
5
  AgentConnection,
6
6
  CodespacePortVisibility,
@@ -11,8 +11,8 @@ import {
11
11
  createServiceLogger,
12
12
  ensureOnTaskBranch,
13
13
  loadConveyorConfig
14
- } from "./chunk-WS7QRB37.js";
15
- import "./chunk-GL2DIQEQ.js";
14
+ } from "./chunk-JBGPARLG.js";
15
+ import "./chunk-Q4FQOJ7D.js";
16
16
  import "./chunk-W4LZ7R6Z.js";
17
17
  import "./chunk-IA45XHOA.js";
18
18
  import "./chunk-SQM2BQ7H.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-agent",
3
- "version": "11.0.19",
3
+ "version": "11.0.20",
4
4
  "description": "Conveyor Agent Runner v10 - PTY harness for the task chat (SDK harness for audit/project-chat). Agent-as-User architecture with BaseService patterns. Works locally too.",
5
5
  "keywords": [
6
6
  "agent",