@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.
- package/dist/bin/agt.js +5 -5
- package/dist/{chunk-65F44JJJ.js → chunk-3KVS22KX.js} +101 -11
- package/dist/chunk-3KVS22KX.js.map +1 -0
- package/dist/{chunk-CFJONCHN.js → chunk-64DXAOQQ.js} +33 -1
- package/dist/{chunk-CFJONCHN.js.map → chunk-64DXAOQQ.js.map} +1 -1
- package/dist/{chunk-WLB2E3PO.js → chunk-XCGOVUGI.js} +8 -5
- package/dist/{chunk-WLB2E3PO.js.map → chunk-XCGOVUGI.js.map} +1 -1
- package/dist/{claude-pair-runtime-4BISLPPZ.js → claude-pair-runtime-B6DFCLT3.js} +2 -2
- package/dist/lib/manager-worker.js +243 -56
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +32 -0
- package/dist/mcp/index.js +32 -0
- package/dist/mcp/origami.js +32 -0
- package/dist/mcp/slack-channel.js +32 -0
- package/dist/mcp/telegram-channel.js +32 -0
- package/dist/{pane-fatal-error-EL336LRO.js → pane-fatal-error-JORQ5OPV.js} +58 -16
- package/dist/pane-fatal-error-JORQ5OPV.js.map +1 -0
- package/dist/{persistent-session-VRAVB743.js → persistent-session-75DOT6JV.js} +9 -3
- package/dist/{responsiveness-probe-QTYKXBH7.js → responsiveness-probe-YFUIBZZV.js} +3 -3
- package/dist/{session-auth-dead-JJPNV3YQ.js → session-auth-dead-JN4EBUCN.js} +2 -2
- package/dist/transcript-mount-health-OHE6IVJV.js +79 -0
- package/dist/transcript-mount-health-OHE6IVJV.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-65F44JJJ.js.map +0 -1
- package/dist/pane-fatal-error-EL336LRO.js.map +0 -1
- /package/dist/{claude-pair-runtime-4BISLPPZ.js.map → claude-pair-runtime-B6DFCLT3.js.map} +0 -0
- /package/dist/{persistent-session-VRAVB743.js.map → persistent-session-75DOT6JV.js.map} +0 -0
- /package/dist/{responsiveness-probe-QTYKXBH7.js.map → responsiveness-probe-YFUIBZZV.js.map} +0 -0
- /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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
14150
|
-
var
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
17141
|
-
|
|
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
|
-
...
|
|
17147
|
-
...
|
|
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
|
-
|
|
17153
|
-
|
|
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)
|
|
17188
|
+
if (!verdict.transcriptBanner) bannerBeat.clear(codeName);
|
|
17176
17189
|
if (kind === null) {
|
|
17177
17190
|
paneFatalStreak.delete(codeName);
|
|
17178
|
-
|
|
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
|
-
|
|
17195
|
-
|
|
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 (!
|
|
17212
|
-
|
|
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
|
-
|
|
17219
|
-
|
|
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 ${
|
|
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
|
-
`
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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));
|