@integrity-labs/agt-cli 0.28.1067 → 0.28.1069

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.
Files changed (28) hide show
  1. package/dist/bin/agt.js +5 -5
  2. package/dist/{chunk-PN7B4DLS.js → chunk-CFJONCHN.js} +11 -1
  3. package/dist/{chunk-PN7B4DLS.js.map → chunk-CFJONCHN.js.map} +1 -1
  4. package/dist/{chunk-NZF55T6D.js → chunk-CO2ODT4I.js} +11 -5
  5. package/dist/{chunk-NZF55T6D.js.map → chunk-CO2ODT4I.js.map} +1 -1
  6. package/dist/{chunk-OW6XCSOU.js → chunk-FHUYRSCF.js} +101 -11
  7. package/dist/chunk-FHUYRSCF.js.map +1 -0
  8. package/dist/{claude-pair-runtime-NCDM5KHM.js → claude-pair-runtime-Z7SMBMUG.js} +2 -2
  9. package/dist/lib/manager-worker.js +361 -36
  10. package/dist/lib/manager-worker.js.map +1 -1
  11. package/dist/mcp/direct-chat-channel.js +10 -0
  12. package/dist/mcp/index.js +10 -0
  13. package/dist/mcp/origami.js +10 -0
  14. package/dist/mcp/slack-channel.js +10 -0
  15. package/dist/mcp/telegram-channel.js +10 -0
  16. package/dist/pane-fatal-error-EL336LRO.js +127 -0
  17. package/dist/pane-fatal-error-EL336LRO.js.map +1 -0
  18. package/dist/{persistent-session-ELDC5JFR.js → persistent-session-52A2G7D7.js} +9 -3
  19. package/dist/{responsiveness-probe-HUUU2MFX.js → responsiveness-probe-SJCP4V4X.js} +3 -3
  20. package/dist/{session-auth-dead-BRMWKA3Y.js → session-auth-dead-JJPNV3YQ.js} +2 -2
  21. package/dist/transcript-mount-health-OHE6IVJV.js +79 -0
  22. package/dist/transcript-mount-health-OHE6IVJV.js.map +1 -0
  23. package/package.json +1 -1
  24. package/dist/chunk-OW6XCSOU.js.map +0 -1
  25. /package/dist/{claude-pair-runtime-NCDM5KHM.js.map → claude-pair-runtime-Z7SMBMUG.js.map} +0 -0
  26. /package/dist/{persistent-session-ELDC5JFR.js.map → persistent-session-52A2G7D7.js.map} +0 -0
  27. /package/dist/{responsiveness-probe-HUUU2MFX.js.map → responsiveness-probe-SJCP4V4X.js.map} +0 -0
  28. /package/dist/{session-auth-dead-BRMWKA3Y.js.map → session-auth-dead-JJPNV3YQ.js.map} +0 -0
@@ -266,7 +266,7 @@ async function spawnPairSession(session) {
266
266
  return { ok: true };
267
267
  } catch {
268
268
  }
269
- const { resolveClaudeBinary } = await import("./persistent-session-ELDC5JFR.js");
269
+ const { resolveClaudeBinary } = await import("./persistent-session-52A2G7D7.js");
270
270
  const claudeBin = resolveClaudeBinary();
271
271
  const pairEnv = {
272
272
  ...process.env,
@@ -734,4 +734,4 @@ export {
734
734
  startClaudePair,
735
735
  submitClaudePairCode
736
736
  };
737
- //# sourceMappingURL=claude-pair-runtime-NCDM5KHM.js.map
737
+ //# sourceMappingURL=claude-pair-runtime-Z7SMBMUG.js.map
@@ -67,7 +67,7 @@ import {
67
67
  safeWriteJsonAtomic,
68
68
  setConfigHash,
69
69
  tripClass
70
- } from "../chunk-NZF55T6D.js";
70
+ } from "../chunk-CO2ODT4I.js";
71
71
  import {
72
72
  getProjectDir as getProjectDir2,
73
73
  getReadyTasks,
@@ -154,7 +154,7 @@ import {
154
154
  webFetchBaselineValue,
155
155
  webFetchRestartNeeded,
156
156
  writeEgressAllowlist
157
- } from "../chunk-OW6XCSOU.js";
157
+ } from "../chunk-FHUYRSCF.js";
158
158
  import {
159
159
  ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
160
160
  AnchorSessionClient,
@@ -263,7 +263,7 @@ import {
263
263
  subagentActivityAgeSeconds,
264
264
  sumTranscriptUsageInWindow,
265
265
  transcriptActivityAgeSeconds
266
- } from "../chunk-PN7B4DLS.js";
266
+ } from "../chunk-CFJONCHN.js";
267
267
  import {
268
268
  classifyUnanswerablePane,
269
269
  paneRemedy
@@ -309,7 +309,7 @@ function defaultUnique() {
309
309
  // src/lib/manager-worker.ts
310
310
  import { execFileSync as syncExecFile } from "child_process";
311
311
  import { join as join43, dirname as dirname11, delimiter as pathDelimiter } from "path";
312
- import { homedir as homedir17 } from "os";
312
+ import { homedir as homedir17, platform as platform3 } from "os";
313
313
  import { fileURLToPath as fileURLToPath2 } from "url";
314
314
 
315
315
  // ../../packages/core/dist/provisioning/channel-policy-env.js
@@ -3292,6 +3292,24 @@ async function maybePollHostUsage(deps) {
3292
3292
  }
3293
3293
  }
3294
3294
 
3295
+ // src/lib/claude-host-args.ts
3296
+ var HOST_CLAUDE_RETENTION_SETTINGS = JSON.stringify({ cleanupPeriodDays: 3650 });
3297
+ function hostClaudeOneShotArgs(emptyMcpConfigPath) {
3298
+ return [
3299
+ // No project config, no MCP, no tools: these exercise the model or auth only.
3300
+ "--mcp-config",
3301
+ emptyMcpConfigPath,
3302
+ "--strict-mcp-config",
3303
+ "--permission-mode",
3304
+ "auto",
3305
+ "--allowedTools",
3306
+ "",
3307
+ // ENG-11277: never age anything out of the shared ~/.claude from here.
3308
+ "--settings",
3309
+ HOST_CLAUDE_RETENTION_SETTINGS
3310
+ ];
3311
+ }
3312
+
3295
3313
  // src/lib/claude-account-fingerprint.ts
3296
3314
  import { createHash as createHash6 } from "crypto";
3297
3315
  import { readFile as readFile3, readdir as readdir3 } from "fs/promises";
@@ -14123,7 +14141,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
14123
14141
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
14124
14142
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
14125
14143
  async function channelInboundActivityAgeSecondsFor(codeName) {
14126
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-HUUU2MFX.js");
14144
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-SJCP4V4X.js");
14127
14145
  const newest = newestPendingInboundActivityMtimeMs(dirname11(paneLogPath(codeName)));
14128
14146
  if (newest === null) return null;
14129
14147
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -14144,6 +14162,15 @@ function inboundHeldMinutesFor(codeName) {
14144
14162
  }
14145
14163
  var consecutiveWedgeCycles = /* @__PURE__ */ new Map();
14146
14164
  var wedgeExemptionLogged = /* @__PURE__ */ new Set();
14165
+ var transcriptMountStreak = /* @__PURE__ */ new Map();
14166
+ var transcriptMountRestarts = /* @__PURE__ */ new Map();
14167
+ var transcriptMountReported = /* @__PURE__ */ new Set();
14168
+ var containerPidCache = /* @__PURE__ */ new Map();
14169
+ var transcriptMountEscalatedAt = /* @__PURE__ */ new Map();
14170
+ var paneFatalStreak = /* @__PURE__ */ new Map();
14171
+ var paneFatalRestarts = /* @__PURE__ */ new Map();
14172
+ var paneFatalReported = /* @__PURE__ */ new Set();
14173
+ var paneBannerWarned = /* @__PURE__ */ new Set();
14147
14174
  var wedgeRestartsByCard = /* @__PURE__ */ new Map();
14148
14175
  function noteInbound(codeName) {
14149
14176
  lastInboundMs.set(codeName, Date.now());
@@ -14871,7 +14898,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
14871
14898
  var lastVersionCheckAt = 0;
14872
14899
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
14873
14900
  var lastResponsivenessProbeAt = 0;
14874
- var agtCliVersion = true ? "0.28.1067" : "dev";
14901
+ var agtCliVersion = true ? "0.28.1069" : "dev";
14875
14902
  function resolveBrewPath(execFileSync3) {
14876
14903
  try {
14877
14904
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -15865,13 +15892,7 @@ async function runClaudeRuntimeAuthProbe() {
15865
15892
  "text",
15866
15893
  // Same isolation as conversation-eval: no project config, no MCP, no tools.
15867
15894
  // The probe must exercise AUTH and nothing else.
15868
- "--mcp-config",
15869
- emptyMcp,
15870
- "--strict-mcp-config",
15871
- "--permission-mode",
15872
- "auto",
15873
- "--allowedTools",
15874
- ""
15895
+ ...hostClaudeOneShotArgs(emptyMcp)
15875
15896
  ];
15876
15897
  try {
15877
15898
  const { stdout, stderr } = await execFilePromiseLong(resolveClaudeBinary(), args, {
@@ -15906,13 +15927,7 @@ async function runHostUsageCommand() {
15906
15927
  const emptyMcp = ensureEvalEmptyMcpConfig();
15907
15928
  const args = [
15908
15929
  ...USAGE_COMMAND_ARGS,
15909
- "--mcp-config",
15910
- emptyMcp,
15911
- "--strict-mcp-config",
15912
- "--permission-mode",
15913
- "auto",
15914
- "--allowedTools",
15915
- ""
15930
+ ...hostClaudeOneShotArgs(emptyMcp)
15916
15931
  ];
15917
15932
  const { stdout } = await execFilePromiseLong(resolveClaudeBinary(), args, {
15918
15933
  cwd: homedir17(),
@@ -15984,13 +15999,7 @@ async function runEvalClaude(prompt, model) {
15984
15999
  "--output-format",
15985
16000
  "text",
15986
16001
  // Isolation: only the empty MCP config, ignore project/user config + no tools.
15987
- "--mcp-config",
15988
- emptyMcp,
15989
- "--strict-mcp-config",
15990
- "--permission-mode",
15991
- "auto",
15992
- "--allowedTools",
15993
- ""
16002
+ ...hostClaudeOneShotArgs(emptyMcp)
15994
16003
  ];
15995
16004
  const { stdout } = await execFilePromiseLong(resolveClaudeBinary(), args, {
15996
16005
  cwd: homedir17(),
@@ -16506,7 +16515,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
16506
16515
  if (codeNames.length === 0) return;
16507
16516
  void (async () => {
16508
16517
  try {
16509
- const { collectDiagnostics } = await import("../persistent-session-ELDC5JFR.js");
16518
+ const { collectDiagnostics } = await import("../persistent-session-52A2G7D7.js");
16510
16519
  await api.post("/host/heartbeat", {
16511
16520
  host_id: hostId,
16512
16521
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -16648,7 +16657,7 @@ async function pollCycleInner() {
16648
16657
  }
16649
16658
  try {
16650
16659
  const { detectHostSecurity } = await import("../host-security-KQYYZZVW.js");
16651
- const { collectDiagnostics } = await import("../persistent-session-ELDC5JFR.js");
16660
+ const { collectDiagnostics } = await import("../persistent-session-52A2G7D7.js");
16652
16661
  const diagCodeNames = [...agentState.persistentSessionAgents];
16653
16662
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor) : void 0;
16654
16663
  let tailscaleHostname;
@@ -16856,7 +16865,7 @@ async function pollCycleInner() {
16856
16865
  collectPanelessActivityProbes,
16857
16866
  getResponsivenessIntervalMs,
16858
16867
  occupancyQualificationClassifications
16859
- } = await import("../responsiveness-probe-HUUU2MFX.js");
16868
+ } = await import("../responsiveness-probe-SJCP4V4X.js");
16860
16869
  const probeIntervalMs = getResponsivenessIntervalMs();
16861
16870
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
16862
16871
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -16973,7 +16982,7 @@ async function pollCycleInner() {
16973
16982
  collectResponsivenessProbes,
16974
16983
  livePendingInboundOldestAgeSeconds,
16975
16984
  parkPendingInbound
16976
- } = await import("../responsiveness-probe-HUUU2MFX.js");
16985
+ } = await import("../responsiveness-probe-SJCP4V4X.js");
16977
16986
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-M6AFZWNU.js");
16978
16987
  const wedgeNow = /* @__PURE__ */ new Date();
16979
16988
  const liveAgents = agentState.persistentSessionAgents;
@@ -17127,9 +17136,325 @@ async function pollCycleInner() {
17127
17136
  } catch (err) {
17128
17137
  log(`[wedge] detection failed: ${err.message}`);
17129
17138
  }
17139
+ try {
17140
+ const {
17141
+ classifyPane,
17142
+ decidePaneFatalAction,
17143
+ pruneRestartHistory,
17144
+ resolvePaneFatalConfig
17145
+ } = await import("../pane-fatal-error-EL336LRO.js");
17146
+ const fatalConfig = resolvePaneFatalConfig();
17147
+ const liveAgents = agentState.persistentSessionAgents;
17148
+ for (const tracked of [
17149
+ ...paneFatalStreak.keys(),
17150
+ ...paneFatalRestarts.keys(),
17151
+ ...paneFatalReported,
17152
+ ...paneBannerWarned
17153
+ ]) {
17154
+ if (!liveAgents.has(tracked)) {
17155
+ paneFatalStreak.delete(tracked);
17156
+ paneFatalRestarts.delete(tracked);
17157
+ paneFatalReported.delete(tracked);
17158
+ paneBannerWarned.delete(tracked);
17159
+ }
17160
+ }
17161
+ if (fatalConfig.mode !== "off") {
17162
+ const fatalNowMs = Date.now();
17163
+ for (const codeName of liveAgents) {
17164
+ if ((agentFrameworkCache.get(codeName) ?? DEFAULT_FRAMEWORK) !== "claude-code") continue;
17165
+ if (!isSessionHealthy(codeName)) {
17166
+ paneFatalStreak.delete(codeName);
17167
+ continue;
17168
+ }
17169
+ let pane = null;
17170
+ try {
17171
+ pane = syncExecFile("tmux", ["capture-pane", "-t", `agt-${codeName}`, "-p", "-J"], {
17172
+ stdio: ["ignore", "pipe", "ignore"],
17173
+ timeout: 2e3
17174
+ }).toString();
17175
+ } catch {
17176
+ pane = null;
17177
+ }
17178
+ const verdict = classifyPane(pane);
17179
+ const kind = verdict.kind;
17180
+ if (!verdict.transcriptBanner) paneBannerWarned.delete(codeName);
17181
+ if (kind === null) {
17182
+ paneFatalStreak.delete(codeName);
17183
+ paneFatalReported.delete(codeName);
17184
+ continue;
17185
+ }
17186
+ const prev = paneFatalStreak.get(codeName);
17187
+ const cycles = prev && prev.kind === kind ? prev.cycles + 1 : 1;
17188
+ paneFatalStreak.set(codeName, { kind, cycles });
17189
+ const history = pruneRestartHistory(paneFatalRestarts.get(codeName) ?? [], fatalNowMs, fatalConfig);
17190
+ paneFatalRestarts.set(codeName, history);
17191
+ const action = decidePaneFatalAction(
17192
+ { kind, consecutiveCycles: cycles, recentRestartsMs: history, nowMs: fatalNowMs },
17193
+ fatalConfig
17194
+ );
17195
+ if (action === "none") continue;
17196
+ const fatalAgentId = agentState.codeNameToAgentId.get(codeName);
17197
+ const detail = `agent=${codeName} kind=${kind} fatalTurns=${verdict.fatalTurns} transcriptBanner=${verdict.transcriptBanner} cycles=${cycles} restartsInWindow=${history.length}`;
17198
+ if (action === "warn") {
17199
+ if (!paneBannerWarned.has(codeName)) {
17200
+ paneBannerWarned.add(codeName);
17201
+ log(
17202
+ `[pane-fatal] "Transcript writes are failing" in the status bar but turns are still being answered \u2014 NOT respawning; recommend a restart at a quiet moment ${detail}`
17203
+ );
17204
+ if (fatalAgentId) {
17205
+ void reportReaperEvent(
17206
+ fatalAgentId,
17207
+ "session-fatal-error-reaper",
17208
+ "alert",
17209
+ 'Claude Code reports "Transcript writes are failing" while the session is still answering; transcripts and compaction may be lost, a restart is recommended'
17210
+ );
17211
+ }
17212
+ }
17213
+ continue;
17214
+ }
17215
+ if (action === "would-restart") {
17216
+ if (!paneFatalReported.has(codeName)) {
17217
+ paneFatalReported.add(codeName);
17218
+ log(`[pane-fatal] SHADOW would force-fresh respawn ${detail}`);
17219
+ }
17220
+ continue;
17221
+ }
17222
+ if (action === "give-up") {
17223
+ if (!paneFatalReported.has(codeName)) {
17224
+ paneFatalReported.add(codeName);
17225
+ log(
17226
+ `[pane-fatal] restart budget spent (${fatalConfig.maxRestartsInWindow} in ${Math.round(fatalConfig.restartWindowMs / 6e4)}m) and the fatal error is back \u2014 NOT restarting again; a human has to look ${detail}`
17227
+ );
17228
+ if (fatalAgentId) {
17229
+ void reportReaperEvent(
17230
+ fatalAgentId,
17231
+ "session-fatal-error-reaper",
17232
+ "blocked",
17233
+ `Session keeps failing with "${kind}" after ${history.length} fresh respawn(s); stopped auto-restarting`
17234
+ );
17235
+ }
17236
+ }
17237
+ continue;
17238
+ }
17239
+ try {
17240
+ const newId = rotateSessionForWedge(codeName);
17241
+ try {
17242
+ syncExecFile("tmux", ["kill-session", "-t", `agt-${codeName}`], { stdio: "ignore" });
17243
+ } catch {
17244
+ }
17245
+ stopPersistentSessionAndForgetMcpBaseline(
17246
+ codeName,
17247
+ "pane-fatal-error",
17248
+ void 0,
17249
+ { outcome: "failed", message: `pane fatal error (${kind})` },
17250
+ {
17251
+ reason: `session answered every turn with "${kind}"; forced a fresh respawn (ENG-11278)`,
17252
+ detail: {
17253
+ fatal_kind: kind,
17254
+ fatal_turns: verdict.fatalTurns,
17255
+ transcript_banner: verdict.transcriptBanner,
17256
+ consecutive_cycles: cycles,
17257
+ restarts_in_window: history.length
17258
+ }
17259
+ }
17260
+ );
17261
+ const { parkPendingInbound } = await import("../responsiveness-probe-SJCP4V4X.js");
17262
+ const { parked, deadLettered } = parkPendingInbound(codeName, new Date(fatalNowMs));
17263
+ paneFatalStreak.delete(codeName);
17264
+ paneFatalRestarts.set(codeName, [...history, fatalNowMs]);
17265
+ log(
17266
+ `[pane-fatal] forced fresh respawn ${detail} \u2192 new session ${newId} (transcript preserved, ${parked} inbound parked, ${deadLettered} dead-lettered)`
17267
+ );
17268
+ if (fatalAgentId) {
17269
+ void reportReaperEvent(
17270
+ fatalAgentId,
17271
+ "session-fatal-error-reaper",
17272
+ "restart",
17273
+ `Session was answering every turn with "${kind}"; forced a fresh respawn`
17274
+ );
17275
+ }
17276
+ } catch (err) {
17277
+ log(`[pane-fatal] force-fresh respawn failed for ${codeName}: ${err.message}`);
17278
+ }
17279
+ }
17280
+ }
17281
+ } catch (err) {
17282
+ log(`[pane-fatal] detection failed: ${err.message}`);
17283
+ }
17284
+ try {
17285
+ const {
17286
+ probeContainerTranscriptMounts,
17287
+ decideTranscriptMountAction,
17288
+ resolveTranscriptMountConfig,
17289
+ TRANSCRIPT_MOUNT_ESCALATION_REFRESH_MS,
17290
+ bindSourceEscalations
17291
+ } = await import("../transcript-mount-health-OHE6IVJV.js");
17292
+ const { transcriptBindSourcesFor, ensureTranscriptBindSources } = await import("../persistent-session-52A2G7D7.js");
17293
+ const mountConfig = resolveTranscriptMountConfig();
17294
+ const liveAgents = agentState.persistentSessionAgents;
17295
+ for (const tracked of [
17296
+ ...transcriptMountStreak.keys(),
17297
+ ...transcriptMountRestarts.keys(),
17298
+ ...transcriptMountReported,
17299
+ ...containerPidCache.keys()
17300
+ ]) {
17301
+ if (!liveAgents.has(tracked)) {
17302
+ transcriptMountStreak.delete(tracked);
17303
+ transcriptMountRestarts.delete(tracked);
17304
+ transcriptMountReported.delete(tracked);
17305
+ containerPidCache.delete(tracked);
17306
+ transcriptMountEscalatedAt.delete(`${tracked}:give-up`);
17307
+ transcriptMountEscalatedAt.delete(`${tracked}:layout`);
17308
+ transcriptMountEscalatedAt.delete(`${tracked}:io`);
17309
+ }
17310
+ }
17311
+ const escalateTranscriptMount = (codeName, agentId, cause, action, reason, nowMs) => {
17312
+ const key = `${codeName}:${cause}`;
17313
+ const last = transcriptMountEscalatedAt.get(key);
17314
+ if (last !== void 0 && nowMs - last < TRANSCRIPT_MOUNT_ESCALATION_REFRESH_MS) return false;
17315
+ transcriptMountEscalatedAt.set(key, nowMs);
17316
+ if (mountConfig.mode === "enforce") {
17317
+ void reportReaperEvent(agentId, "transcript-mount-reaper", action, reason);
17318
+ }
17319
+ return last === void 0;
17320
+ };
17321
+ if (mountConfig.mode !== "off" && platform3() === "linux") {
17322
+ const mountNowMs = Date.now();
17323
+ const homeDirForBinds = process.env.HOME?.trim() || homedir17();
17324
+ for (const codeName of liveAgents) {
17325
+ if (effectiveIsolationMode(codeName) !== "docker") continue;
17326
+ if (!isSessionHealthy(codeName)) {
17327
+ transcriptMountStreak.delete(codeName);
17328
+ containerPidCache.delete(codeName);
17329
+ continue;
17330
+ }
17331
+ const agentId = agentState.codeNameToAgentId.get(codeName);
17332
+ if (!agentId) continue;
17333
+ let pid = containerPidCache.get(codeName) ?? null;
17334
+ if (pid !== null && !existsSync19(`/proc/${pid}`)) pid = null;
17335
+ if (pid === null) {
17336
+ try {
17337
+ const out = syncExecFile("docker", ["inspect", "-f", "{{.State.Pid}}", `agt-${codeName}`], {
17338
+ stdio: ["ignore", "pipe", "ignore"],
17339
+ timeout: 5e3
17340
+ }).toString().trim();
17341
+ const parsed = Number.parseInt(out, 10);
17342
+ pid = Number.isInteger(parsed) && parsed > 0 ? parsed : null;
17343
+ } catch {
17344
+ pid = null;
17345
+ }
17346
+ if (pid !== null) containerPidCache.set(codeName, pid);
17347
+ }
17348
+ const src = transcriptBindSourcesFor({
17349
+ homeDir: homeDirForBinds,
17350
+ agentId,
17351
+ projectDir: getProjectDir(codeName)
17352
+ });
17353
+ const verdict = probeContainerTranscriptMounts({
17354
+ pid,
17355
+ // Mask (parent) first: an unlinked mask root is the cause even when
17356
+ // the nested slug bind still resolves.
17357
+ binds: [
17358
+ { containerPath: src.projects, hostPath: src.mask },
17359
+ { containerPath: src.own, hostPath: src.own }
17360
+ ],
17361
+ stat: (path) => statSync14(path)
17362
+ });
17363
+ if (verdict.state !== "orphaned") {
17364
+ transcriptMountStreak.delete(codeName);
17365
+ if (verdict.state === "ok") {
17366
+ transcriptMountReported.delete(codeName);
17367
+ transcriptMountEscalatedAt.delete(`${codeName}:give-up`);
17368
+ const { refused } = ensureTranscriptBindSources({
17369
+ homeDir: homeDirForBinds,
17370
+ agentId,
17371
+ projectDir: getProjectDir(codeName)
17372
+ });
17373
+ const escalations = bindSourceEscalations(refused);
17374
+ for (const cause of ["layout", "io"]) {
17375
+ if (!escalations.some((e) => e.cause === cause)) transcriptMountEscalatedAt.delete(`${codeName}:${cause}`);
17376
+ }
17377
+ for (const e of escalations) {
17378
+ if (escalateTranscriptMount(codeName, agentId, e.cause, e.action, e.message, mountNowMs)) {
17379
+ log(`[transcript-mount] bind source ${e.cause} problem for agent=${codeName}: ${e.message}`);
17380
+ }
17381
+ }
17382
+ }
17383
+ continue;
17384
+ }
17385
+ const cycles = (transcriptMountStreak.get(codeName) ?? 0) + 1;
17386
+ transcriptMountStreak.set(codeName, cycles);
17387
+ const history = (transcriptMountRestarts.get(codeName) ?? []).filter(
17388
+ (t) => mountNowMs - t < mountConfig.restartWindowMs
17389
+ );
17390
+ transcriptMountRestarts.set(codeName, history);
17391
+ const action = decideTranscriptMountAction(
17392
+ { verdict, consecutiveCycles: cycles, recentRestartsMs: history, nowMs: mountNowMs },
17393
+ mountConfig
17394
+ );
17395
+ if (action === "none") continue;
17396
+ const detail = `agent=${codeName} path=${verdict.path} reason=${verdict.reason} cycles=${cycles} restartsInWindow=${history.length}`;
17397
+ if (action === "would-restart") {
17398
+ if (!transcriptMountReported.has(codeName)) {
17399
+ transcriptMountReported.add(codeName);
17400
+ log(`[transcript-mount] SHADOW would respawn (container transcript dir orphaned) ${detail}`);
17401
+ }
17402
+ continue;
17403
+ }
17404
+ if (action === "give-up") {
17405
+ if (!transcriptMountReported.has(codeName)) {
17406
+ transcriptMountReported.add(codeName);
17407
+ log(
17408
+ `[transcript-mount] restart budget spent and the transcript dir is orphaned again \u2014 NOT respawning; something on the host keeps removing it ${detail}`
17409
+ );
17410
+ }
17411
+ escalateTranscriptMount(
17412
+ codeName,
17413
+ agentId,
17414
+ "give-up",
17415
+ "blocked",
17416
+ `Container transcript directory ${verdict.path} is orphaned (${verdict.reason}) again after ${history.length} respawn(s) in the window; transcript writes and compaction are failing ENOENT. Stopped auto-restarting: something on the host keeps removing the bind source.`,
17417
+ mountNowMs
17418
+ );
17419
+ continue;
17420
+ }
17421
+ try {
17422
+ stopPersistentSessionAndForgetMcpBaseline(
17423
+ codeName,
17424
+ "transcript-mount-orphaned",
17425
+ void 0,
17426
+ { outcome: "failed", message: `transcript mount orphaned (${verdict.reason})` },
17427
+ {
17428
+ reason: `transcript bind ${verdict.path} orphaned (${verdict.reason}); respawn to re-bind (ENG-11277)`,
17429
+ detail: {
17430
+ mount_path: verdict.path,
17431
+ mount_state: verdict.reason,
17432
+ consecutive_cycles: cycles,
17433
+ restarts_in_window: history.length
17434
+ }
17435
+ }
17436
+ );
17437
+ containerPidCache.delete(codeName);
17438
+ transcriptMountStreak.delete(codeName);
17439
+ transcriptMountRestarts.set(codeName, [...history, mountNowMs]);
17440
+ log(`[transcript-mount] respawning to re-bind orphaned transcript mount ${detail}`);
17441
+ void reportReaperEvent(
17442
+ agentId,
17443
+ "transcript-mount-reaper",
17444
+ "restart",
17445
+ `Container transcript directory ${verdict.path} was ${verdict.reason}; transcript writes and compaction were failing ENOENT. Respawned to re-bind.`
17446
+ );
17447
+ } catch (err) {
17448
+ log(`[transcript-mount] respawn failed for ${codeName}: ${err.message}`);
17449
+ }
17450
+ }
17451
+ }
17452
+ } catch (err) {
17453
+ log(`[transcript-mount] probe failed: ${err.message}`);
17454
+ }
17130
17455
  try {
17131
17456
  const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-VR5QGP3J.js");
17132
- const { probeSessionAuth } = await import("../session-auth-dead-BRMWKA3Y.js");
17457
+ const { probeSessionAuth } = await import("../session-auth-dead-JJPNV3YQ.js");
17133
17458
  const observations = [];
17134
17459
  const pendingCacheCommits = [];
17135
17460
  const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
@@ -21694,7 +22019,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
21694
22019
  try {
21695
22020
  const freshId = rotateSessionForWedge(codeName);
21696
22021
  consecutiveWedgeCycles.delete(codeName);
21697
- const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-HUUU2MFX.js");
22022
+ const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-SJCP4V4X.js");
21698
22023
  const { parked, deadLettered } = parkForRestart(codeName, /* @__PURE__ */ new Date());
21699
22024
  const parkNote = parked > 0 ? `, ${parked} inbound parked` : "";
21700
22025
  const deadNote = deadLettered > 0 ? `, ${deadLettered} undeliverable dead-lettered` : "";
@@ -21737,7 +22062,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
21737
22062
  void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
21738
22063
  void (async () => {
21739
22064
  try {
21740
- const { collectDiagnostics } = await import("../persistent-session-ELDC5JFR.js");
22065
+ const { collectDiagnostics } = await import("../persistent-session-52A2G7D7.js");
21741
22066
  await api.post("/host/heartbeat", {
21742
22067
  host_id: hostId,
21743
22068
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -21788,7 +22113,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
21788
22113
  }
21789
22114
  try {
21790
22115
  const hostId = await getHostId();
21791
- const { collectDiagnostics } = await import("../persistent-session-ELDC5JFR.js");
22116
+ const { collectDiagnostics } = await import("../persistent-session-52A2G7D7.js");
21792
22117
  await api.post("/host/heartbeat", {
21793
22118
  host_id: hostId,
21794
22119
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -22460,7 +22785,7 @@ async function processClaudePairSessions(agents) {
22460
22785
  // cannot take it for itself — by the time it runs, the write it is looking
22461
22786
  // for may already have happened.
22462
22787
  snapshotPairConfig
22463
- } = await import("../claude-pair-runtime-NCDM5KHM.js");
22788
+ } = await import("../claude-pair-runtime-Z7SMBMUG.js");
22464
22789
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
22465
22790
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
22466
22791
  const killed = await killPairSession(pairTmuxSession(pairId));