@integrity-labs/agt-cli 0.28.1068 → 0.28.1070

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 (29) hide show
  1. package/dist/bin/agt.js +5 -5
  2. package/dist/{chunk-65F44JJJ.js → chunk-3KVS22KX.js} +101 -11
  3. package/dist/chunk-3KVS22KX.js.map +1 -0
  4. package/dist/{chunk-CFJONCHN.js → chunk-64DXAOQQ.js} +33 -1
  5. package/dist/{chunk-CFJONCHN.js.map → chunk-64DXAOQQ.js.map} +1 -1
  6. package/dist/{chunk-WLB2E3PO.js → chunk-XCGOVUGI.js} +8 -5
  7. package/dist/{chunk-WLB2E3PO.js.map → chunk-XCGOVUGI.js.map} +1 -1
  8. package/dist/{claude-pair-runtime-4BISLPPZ.js → claude-pair-runtime-B6DFCLT3.js} +2 -2
  9. package/dist/lib/manager-worker.js +243 -56
  10. package/dist/lib/manager-worker.js.map +1 -1
  11. package/dist/mcp/direct-chat-channel.js +32 -0
  12. package/dist/mcp/index.js +32 -0
  13. package/dist/mcp/origami.js +32 -0
  14. package/dist/mcp/slack-channel.js +32 -0
  15. package/dist/mcp/telegram-channel.js +32 -0
  16. package/dist/{pane-fatal-error-EL336LRO.js → pane-fatal-error-JORQ5OPV.js} +58 -16
  17. package/dist/pane-fatal-error-JORQ5OPV.js.map +1 -0
  18. package/dist/{persistent-session-VRAVB743.js → persistent-session-75DOT6JV.js} +9 -3
  19. package/dist/{responsiveness-probe-QTYKXBH7.js → responsiveness-probe-YFUIBZZV.js} +3 -3
  20. package/dist/{session-auth-dead-JJPNV3YQ.js → session-auth-dead-JN4EBUCN.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-65F44JJJ.js.map +0 -1
  25. package/dist/pane-fatal-error-EL336LRO.js.map +0 -1
  26. /package/dist/{claude-pair-runtime-4BISLPPZ.js.map → claude-pair-runtime-B6DFCLT3.js.map} +0 -0
  27. /package/dist/{persistent-session-VRAVB743.js.map → persistent-session-75DOT6JV.js.map} +0 -0
  28. /package/dist/{responsiveness-probe-QTYKXBH7.js.map → responsiveness-probe-YFUIBZZV.js.map} +0 -0
  29. /package/dist/{session-auth-dead-JJPNV3YQ.js.map → session-auth-dead-JN4EBUCN.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-VRAVB743.js");
269
+ const { resolveClaudeBinary } = await import("./persistent-session-75DOT6JV.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-4BISLPPZ.js.map
737
+ //# sourceMappingURL=claude-pair-runtime-B6DFCLT3.js.map
@@ -67,7 +67,7 @@ import {
67
67
  safeWriteJsonAtomic,
68
68
  setConfigHash,
69
69
  tripClass
70
- } from "../chunk-WLB2E3PO.js";
70
+ } from "../chunk-XCGOVUGI.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-65F44JJJ.js";
157
+ } from "../chunk-3KVS22KX.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-CFJONCHN.js";
266
+ } from "../chunk-64DXAOQQ.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-QTYKXBH7.js");
14144
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-YFUIBZZV.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,10 +14162,16 @@ 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();
14147
14170
  var paneFatalStreak = /* @__PURE__ */ new Map();
14148
14171
  var paneFatalRestarts = /* @__PURE__ */ new Map();
14149
- var paneFatalReported = /* @__PURE__ */ new Set();
14150
- var paneBannerWarned = /* @__PURE__ */ new Set();
14172
+ var paneFatalShadowLogged = /* @__PURE__ */ new Set();
14173
+ var paneGiveUpHeartbeat = null;
14174
+ var paneBannerHeartbeat = null;
14151
14175
  var wedgeRestartsByCard = /* @__PURE__ */ new Map();
14152
14176
  function noteInbound(codeName) {
14153
14177
  lastInboundMs.set(codeName, Date.now());
@@ -14875,7 +14899,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
14875
14899
  var lastVersionCheckAt = 0;
14876
14900
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
14877
14901
  var lastResponsivenessProbeAt = 0;
14878
- var agtCliVersion = true ? "0.28.1068" : "dev";
14902
+ var agtCliVersion = true ? "0.28.1070" : "dev";
14879
14903
  function resolveBrewPath(execFileSync3) {
14880
14904
  try {
14881
14905
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -15869,13 +15893,7 @@ async function runClaudeRuntimeAuthProbe() {
15869
15893
  "text",
15870
15894
  // Same isolation as conversation-eval: no project config, no MCP, no tools.
15871
15895
  // The probe must exercise AUTH and nothing else.
15872
- "--mcp-config",
15873
- emptyMcp,
15874
- "--strict-mcp-config",
15875
- "--permission-mode",
15876
- "auto",
15877
- "--allowedTools",
15878
- ""
15896
+ ...hostClaudeOneShotArgs(emptyMcp)
15879
15897
  ];
15880
15898
  try {
15881
15899
  const { stdout, stderr } = await execFilePromiseLong(resolveClaudeBinary(), args, {
@@ -15910,13 +15928,7 @@ async function runHostUsageCommand() {
15910
15928
  const emptyMcp = ensureEvalEmptyMcpConfig();
15911
15929
  const args = [
15912
15930
  ...USAGE_COMMAND_ARGS,
15913
- "--mcp-config",
15914
- emptyMcp,
15915
- "--strict-mcp-config",
15916
- "--permission-mode",
15917
- "auto",
15918
- "--allowedTools",
15919
- ""
15931
+ ...hostClaudeOneShotArgs(emptyMcp)
15920
15932
  ];
15921
15933
  const { stdout } = await execFilePromiseLong(resolveClaudeBinary(), args, {
15922
15934
  cwd: homedir17(),
@@ -15988,13 +16000,7 @@ async function runEvalClaude(prompt, model) {
15988
16000
  "--output-format",
15989
16001
  "text",
15990
16002
  // Isolation: only the empty MCP config, ignore project/user config + no tools.
15991
- "--mcp-config",
15992
- emptyMcp,
15993
- "--strict-mcp-config",
15994
- "--permission-mode",
15995
- "auto",
15996
- "--allowedTools",
15997
- ""
16003
+ ...hostClaudeOneShotArgs(emptyMcp)
15998
16004
  ];
15999
16005
  const { stdout } = await execFilePromiseLong(resolveClaudeBinary(), args, {
16000
16006
  cwd: homedir17(),
@@ -16510,7 +16516,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
16510
16516
  if (codeNames.length === 0) return;
16511
16517
  void (async () => {
16512
16518
  try {
16513
- const { collectDiagnostics } = await import("../persistent-session-VRAVB743.js");
16519
+ const { collectDiagnostics } = await import("../persistent-session-75DOT6JV.js");
16514
16520
  await api.post("/host/heartbeat", {
16515
16521
  host_id: hostId,
16516
16522
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -16652,7 +16658,7 @@ async function pollCycleInner() {
16652
16658
  }
16653
16659
  try {
16654
16660
  const { detectHostSecurity } = await import("../host-security-KQYYZZVW.js");
16655
- const { collectDiagnostics } = await import("../persistent-session-VRAVB743.js");
16661
+ const { collectDiagnostics } = await import("../persistent-session-75DOT6JV.js");
16656
16662
  const diagCodeNames = [...agentState.persistentSessionAgents];
16657
16663
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor) : void 0;
16658
16664
  let tailscaleHostname;
@@ -16860,7 +16866,7 @@ async function pollCycleInner() {
16860
16866
  collectPanelessActivityProbes,
16861
16867
  getResponsivenessIntervalMs,
16862
16868
  occupancyQualificationClassifications
16863
- } = await import("../responsiveness-probe-QTYKXBH7.js");
16869
+ } = await import("../responsiveness-probe-YFUIBZZV.js");
16864
16870
  const probeIntervalMs = getResponsivenessIntervalMs();
16865
16871
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
16866
16872
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -16977,7 +16983,7 @@ async function pollCycleInner() {
16977
16983
  collectResponsivenessProbes,
16978
16984
  livePendingInboundOldestAgeSeconds,
16979
16985
  parkPendingInbound
16980
- } = await import("../responsiveness-probe-QTYKXBH7.js");
16986
+ } = await import("../responsiveness-probe-YFUIBZZV.js");
16981
16987
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-M6AFZWNU.js");
16982
16988
  const wedgeNow = /* @__PURE__ */ new Date();
16983
16989
  const liveAgents = agentState.persistentSessionAgents;
@@ -17133,24 +17139,31 @@ async function pollCycleInner() {
17133
17139
  }
17134
17140
  try {
17135
17141
  const {
17142
+ AlertHeartbeat,
17136
17143
  classifyPane,
17137
17144
  decidePaneFatalAction,
17138
17145
  pruneRestartHistory,
17139
17146
  resolvePaneFatalConfig
17140
- } = await import("../pane-fatal-error-EL336LRO.js");
17141
- const fatalConfig = resolvePaneFatalConfig();
17147
+ } = await import("../pane-fatal-error-JORQ5OPV.js");
17148
+ paneGiveUpHeartbeat ??= new AlertHeartbeat();
17149
+ paneBannerHeartbeat ??= new AlertHeartbeat();
17150
+ const giveUpBeat = paneGiveUpHeartbeat;
17151
+ const bannerBeat = paneBannerHeartbeat;
17152
+ const fatalConfig = resolvePaneFatalConfig(hostFlagStore().getString("pane-fatal-restart-mode"));
17142
17153
  const liveAgents = agentState.persistentSessionAgents;
17143
17154
  for (const tracked of [
17144
17155
  ...paneFatalStreak.keys(),
17145
17156
  ...paneFatalRestarts.keys(),
17146
- ...paneFatalReported,
17147
- ...paneBannerWarned
17157
+ ...paneFatalShadowLogged,
17158
+ ...giveUpBeat.keys(),
17159
+ ...bannerBeat.keys()
17148
17160
  ]) {
17149
17161
  if (!liveAgents.has(tracked)) {
17150
17162
  paneFatalStreak.delete(tracked);
17151
17163
  paneFatalRestarts.delete(tracked);
17152
- paneFatalReported.delete(tracked);
17153
- paneBannerWarned.delete(tracked);
17164
+ paneFatalShadowLogged.delete(tracked);
17165
+ giveUpBeat.clear(tracked);
17166
+ bannerBeat.clear(tracked);
17154
17167
  }
17155
17168
  }
17156
17169
  if (fatalConfig.mode !== "off") {
@@ -17172,10 +17185,11 @@ async function pollCycleInner() {
17172
17185
  }
17173
17186
  const verdict = classifyPane(pane);
17174
17187
  const kind = verdict.kind;
17175
- if (!verdict.transcriptBanner) paneBannerWarned.delete(codeName);
17188
+ if (!verdict.transcriptBanner) bannerBeat.clear(codeName);
17176
17189
  if (kind === null) {
17177
17190
  paneFatalStreak.delete(codeName);
17178
- paneFatalReported.delete(codeName);
17191
+ paneFatalShadowLogged.delete(codeName);
17192
+ giveUpBeat.clear(codeName);
17179
17193
  continue;
17180
17194
  }
17181
17195
  const prev = paneFatalStreak.get(codeName);
@@ -17187,14 +17201,15 @@ async function pollCycleInner() {
17187
17201
  { kind, consecutiveCycles: cycles, recentRestartsMs: history, nowMs: fatalNowMs },
17188
17202
  fatalConfig
17189
17203
  );
17204
+ if (action !== "give-up") giveUpBeat.clear(codeName);
17190
17205
  if (action === "none") continue;
17191
17206
  const fatalAgentId = agentState.codeNameToAgentId.get(codeName);
17192
17207
  const detail = `agent=${codeName} kind=${kind} fatalTurns=${verdict.fatalTurns} transcriptBanner=${verdict.transcriptBanner} cycles=${cycles} restartsInWindow=${history.length}`;
17193
17208
  if (action === "warn") {
17194
- if (!paneBannerWarned.has(codeName)) {
17195
- paneBannerWarned.add(codeName);
17209
+ const firstWarn = !bannerBeat.active(codeName);
17210
+ if (bannerBeat.due(codeName, fatalNowMs)) {
17196
17211
  log(
17197
- `[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}`
17212
+ `[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 ${firstWarn ? "" : "(still present) "}${detail}`
17198
17213
  );
17199
17214
  if (fatalAgentId) {
17200
17215
  void reportReaperEvent(
@@ -17208,24 +17223,25 @@ async function pollCycleInner() {
17208
17223
  continue;
17209
17224
  }
17210
17225
  if (action === "would-restart") {
17211
- if (!paneFatalReported.has(codeName)) {
17212
- paneFatalReported.add(codeName);
17226
+ if (!paneFatalShadowLogged.has(codeName)) {
17227
+ paneFatalShadowLogged.add(codeName);
17213
17228
  log(`[pane-fatal] SHADOW would force-fresh respawn ${detail}`);
17214
17229
  }
17215
17230
  continue;
17216
17231
  }
17217
17232
  if (action === "give-up") {
17218
- if (!paneFatalReported.has(codeName)) {
17219
- paneFatalReported.add(codeName);
17233
+ const firstGiveUp = !giveUpBeat.active(codeName);
17234
+ if (giveUpBeat.due(codeName, fatalNowMs)) {
17235
+ const windowMin = Math.round(fatalConfig.restartWindowMs / 6e4);
17220
17236
  log(
17221
- `[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}`
17237
+ `[pane-fatal] restart budget spent (${fatalConfig.maxRestartsInWindow} in ${windowMin}m) and the fatal error is ${firstGiveUp ? "back" : "still there"} \u2014 NOT restarting again; a human has to look ${detail}`
17222
17238
  );
17223
17239
  if (fatalAgentId) {
17224
17240
  void reportReaperEvent(
17225
17241
  fatalAgentId,
17226
17242
  "session-fatal-error-reaper",
17227
17243
  "blocked",
17228
- `Session keeps failing with "${kind}" after ${history.length} fresh respawn(s); stopped auto-restarting`
17244
+ `after ${history.length} fresh respawn(s) in ${windowMin}m the session keeps failing every turn with "${kind}". Needs a human: check the agent's transcript mount (/root/.claude/projects, see ENG-11277) and its pane, then restart it`
17229
17245
  );
17230
17246
  }
17231
17247
  }
@@ -17253,7 +17269,7 @@ async function pollCycleInner() {
17253
17269
  }
17254
17270
  }
17255
17271
  );
17256
- const { parkPendingInbound } = await import("../responsiveness-probe-QTYKXBH7.js");
17272
+ const { parkPendingInbound } = await import("../responsiveness-probe-YFUIBZZV.js");
17257
17273
  const { parked, deadLettered } = parkPendingInbound(codeName, new Date(fatalNowMs));
17258
17274
  paneFatalStreak.delete(codeName);
17259
17275
  paneFatalRestarts.set(codeName, [...history, fatalNowMs]);
@@ -17276,9 +17292,180 @@ async function pollCycleInner() {
17276
17292
  } catch (err) {
17277
17293
  log(`[pane-fatal] detection failed: ${err.message}`);
17278
17294
  }
17295
+ try {
17296
+ const {
17297
+ probeContainerTranscriptMounts,
17298
+ decideTranscriptMountAction,
17299
+ resolveTranscriptMountConfig,
17300
+ TRANSCRIPT_MOUNT_ESCALATION_REFRESH_MS,
17301
+ bindSourceEscalations
17302
+ } = await import("../transcript-mount-health-OHE6IVJV.js");
17303
+ const { transcriptBindSourcesFor, ensureTranscriptBindSources } = await import("../persistent-session-75DOT6JV.js");
17304
+ const mountConfig = resolveTranscriptMountConfig();
17305
+ const liveAgents = agentState.persistentSessionAgents;
17306
+ for (const tracked of [
17307
+ ...transcriptMountStreak.keys(),
17308
+ ...transcriptMountRestarts.keys(),
17309
+ ...transcriptMountReported,
17310
+ ...containerPidCache.keys()
17311
+ ]) {
17312
+ if (!liveAgents.has(tracked)) {
17313
+ transcriptMountStreak.delete(tracked);
17314
+ transcriptMountRestarts.delete(tracked);
17315
+ transcriptMountReported.delete(tracked);
17316
+ containerPidCache.delete(tracked);
17317
+ transcriptMountEscalatedAt.delete(`${tracked}:give-up`);
17318
+ transcriptMountEscalatedAt.delete(`${tracked}:layout`);
17319
+ transcriptMountEscalatedAt.delete(`${tracked}:io`);
17320
+ }
17321
+ }
17322
+ const escalateTranscriptMount = (codeName, agentId, cause, action, reason, nowMs) => {
17323
+ const key = `${codeName}:${cause}`;
17324
+ const last = transcriptMountEscalatedAt.get(key);
17325
+ if (last !== void 0 && nowMs - last < TRANSCRIPT_MOUNT_ESCALATION_REFRESH_MS) return false;
17326
+ transcriptMountEscalatedAt.set(key, nowMs);
17327
+ if (mountConfig.mode === "enforce") {
17328
+ void reportReaperEvent(agentId, "transcript-mount-reaper", action, reason);
17329
+ }
17330
+ return last === void 0;
17331
+ };
17332
+ if (mountConfig.mode !== "off" && platform3() === "linux") {
17333
+ const mountNowMs = Date.now();
17334
+ const homeDirForBinds = process.env.HOME?.trim() || homedir17();
17335
+ for (const codeName of liveAgents) {
17336
+ if (effectiveIsolationMode(codeName) !== "docker") continue;
17337
+ if (!isSessionHealthy(codeName)) {
17338
+ transcriptMountStreak.delete(codeName);
17339
+ containerPidCache.delete(codeName);
17340
+ continue;
17341
+ }
17342
+ const agentId = agentState.codeNameToAgentId.get(codeName);
17343
+ if (!agentId) continue;
17344
+ let pid = containerPidCache.get(codeName) ?? null;
17345
+ if (pid !== null && !existsSync19(`/proc/${pid}`)) pid = null;
17346
+ if (pid === null) {
17347
+ try {
17348
+ const out = syncExecFile("docker", ["inspect", "-f", "{{.State.Pid}}", `agt-${codeName}`], {
17349
+ stdio: ["ignore", "pipe", "ignore"],
17350
+ timeout: 5e3
17351
+ }).toString().trim();
17352
+ const parsed = Number.parseInt(out, 10);
17353
+ pid = Number.isInteger(parsed) && parsed > 0 ? parsed : null;
17354
+ } catch {
17355
+ pid = null;
17356
+ }
17357
+ if (pid !== null) containerPidCache.set(codeName, pid);
17358
+ }
17359
+ const src = transcriptBindSourcesFor({
17360
+ homeDir: homeDirForBinds,
17361
+ agentId,
17362
+ projectDir: getProjectDir(codeName)
17363
+ });
17364
+ const verdict = probeContainerTranscriptMounts({
17365
+ pid,
17366
+ // Mask (parent) first: an unlinked mask root is the cause even when
17367
+ // the nested slug bind still resolves.
17368
+ binds: [
17369
+ { containerPath: src.projects, hostPath: src.mask },
17370
+ { containerPath: src.own, hostPath: src.own }
17371
+ ],
17372
+ stat: (path) => statSync14(path)
17373
+ });
17374
+ if (verdict.state !== "orphaned") {
17375
+ transcriptMountStreak.delete(codeName);
17376
+ if (verdict.state === "ok") {
17377
+ transcriptMountReported.delete(codeName);
17378
+ transcriptMountEscalatedAt.delete(`${codeName}:give-up`);
17379
+ const { refused } = ensureTranscriptBindSources({
17380
+ homeDir: homeDirForBinds,
17381
+ agentId,
17382
+ projectDir: getProjectDir(codeName)
17383
+ });
17384
+ const escalations = bindSourceEscalations(refused);
17385
+ for (const cause of ["layout", "io"]) {
17386
+ if (!escalations.some((e) => e.cause === cause)) transcriptMountEscalatedAt.delete(`${codeName}:${cause}`);
17387
+ }
17388
+ for (const e of escalations) {
17389
+ if (escalateTranscriptMount(codeName, agentId, e.cause, e.action, e.message, mountNowMs)) {
17390
+ log(`[transcript-mount] bind source ${e.cause} problem for agent=${codeName}: ${e.message}`);
17391
+ }
17392
+ }
17393
+ }
17394
+ continue;
17395
+ }
17396
+ const cycles = (transcriptMountStreak.get(codeName) ?? 0) + 1;
17397
+ transcriptMountStreak.set(codeName, cycles);
17398
+ const history = (transcriptMountRestarts.get(codeName) ?? []).filter(
17399
+ (t) => mountNowMs - t < mountConfig.restartWindowMs
17400
+ );
17401
+ transcriptMountRestarts.set(codeName, history);
17402
+ const action = decideTranscriptMountAction(
17403
+ { verdict, consecutiveCycles: cycles, recentRestartsMs: history, nowMs: mountNowMs },
17404
+ mountConfig
17405
+ );
17406
+ if (action === "none") continue;
17407
+ const detail = `agent=${codeName} path=${verdict.path} reason=${verdict.reason} cycles=${cycles} restartsInWindow=${history.length}`;
17408
+ if (action === "would-restart") {
17409
+ if (!transcriptMountReported.has(codeName)) {
17410
+ transcriptMountReported.add(codeName);
17411
+ log(`[transcript-mount] SHADOW would respawn (container transcript dir orphaned) ${detail}`);
17412
+ }
17413
+ continue;
17414
+ }
17415
+ if (action === "give-up") {
17416
+ if (!transcriptMountReported.has(codeName)) {
17417
+ transcriptMountReported.add(codeName);
17418
+ log(
17419
+ `[transcript-mount] restart budget spent and the transcript dir is orphaned again \u2014 NOT respawning; something on the host keeps removing it ${detail}`
17420
+ );
17421
+ }
17422
+ escalateTranscriptMount(
17423
+ codeName,
17424
+ agentId,
17425
+ "give-up",
17426
+ "blocked",
17427
+ `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.`,
17428
+ mountNowMs
17429
+ );
17430
+ continue;
17431
+ }
17432
+ try {
17433
+ stopPersistentSessionAndForgetMcpBaseline(
17434
+ codeName,
17435
+ "transcript-mount-orphaned",
17436
+ void 0,
17437
+ { outcome: "failed", message: `transcript mount orphaned (${verdict.reason})` },
17438
+ {
17439
+ reason: `transcript bind ${verdict.path} orphaned (${verdict.reason}); respawn to re-bind (ENG-11277)`,
17440
+ detail: {
17441
+ mount_path: verdict.path,
17442
+ mount_state: verdict.reason,
17443
+ consecutive_cycles: cycles,
17444
+ restarts_in_window: history.length
17445
+ }
17446
+ }
17447
+ );
17448
+ containerPidCache.delete(codeName);
17449
+ transcriptMountStreak.delete(codeName);
17450
+ transcriptMountRestarts.set(codeName, [...history, mountNowMs]);
17451
+ log(`[transcript-mount] respawning to re-bind orphaned transcript mount ${detail}`);
17452
+ void reportReaperEvent(
17453
+ agentId,
17454
+ "transcript-mount-reaper",
17455
+ "restart",
17456
+ `Container transcript directory ${verdict.path} was ${verdict.reason}; transcript writes and compaction were failing ENOENT. Respawned to re-bind.`
17457
+ );
17458
+ } catch (err) {
17459
+ log(`[transcript-mount] respawn failed for ${codeName}: ${err.message}`);
17460
+ }
17461
+ }
17462
+ }
17463
+ } catch (err) {
17464
+ log(`[transcript-mount] probe failed: ${err.message}`);
17465
+ }
17279
17466
  try {
17280
17467
  const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-VR5QGP3J.js");
17281
- const { probeSessionAuth } = await import("../session-auth-dead-JJPNV3YQ.js");
17468
+ const { probeSessionAuth } = await import("../session-auth-dead-JN4EBUCN.js");
17282
17469
  const observations = [];
17283
17470
  const pendingCacheCommits = [];
17284
17471
  const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
@@ -21843,7 +22030,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
21843
22030
  try {
21844
22031
  const freshId = rotateSessionForWedge(codeName);
21845
22032
  consecutiveWedgeCycles.delete(codeName);
21846
- const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-QTYKXBH7.js");
22033
+ const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-YFUIBZZV.js");
21847
22034
  const { parked, deadLettered } = parkForRestart(codeName, /* @__PURE__ */ new Date());
21848
22035
  const parkNote = parked > 0 ? `, ${parked} inbound parked` : "";
21849
22036
  const deadNote = deadLettered > 0 ? `, ${deadLettered} undeliverable dead-lettered` : "";
@@ -21886,7 +22073,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
21886
22073
  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}`));
21887
22074
  void (async () => {
21888
22075
  try {
21889
- const { collectDiagnostics } = await import("../persistent-session-VRAVB743.js");
22076
+ const { collectDiagnostics } = await import("../persistent-session-75DOT6JV.js");
21890
22077
  await api.post("/host/heartbeat", {
21891
22078
  host_id: hostId,
21892
22079
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -21937,7 +22124,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
21937
22124
  }
21938
22125
  try {
21939
22126
  const hostId = await getHostId();
21940
- const { collectDiagnostics } = await import("../persistent-session-VRAVB743.js");
22127
+ const { collectDiagnostics } = await import("../persistent-session-75DOT6JV.js");
21941
22128
  await api.post("/host/heartbeat", {
21942
22129
  host_id: hostId,
21943
22130
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -22609,7 +22796,7 @@ async function processClaudePairSessions(agents) {
22609
22796
  // cannot take it for itself — by the time it runs, the write it is looking
22610
22797
  // for may already have happened.
22611
22798
  snapshotPairConfig
22612
- } = await import("../claude-pair-runtime-4BISLPPZ.js");
22799
+ } = await import("../claude-pair-runtime-B6DFCLT3.js");
22613
22800
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
22614
22801
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
22615
22802
  const killed = await killPairSession(pairTmuxSession(pairId));