@integrity-labs/agt-cli 0.28.327 → 0.28.329

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.
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
100
100
  return { ok: true };
101
101
  } catch {
102
102
  }
103
- const { resolveClaudeBinary } = await import("./persistent-session-BICDYHOC.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-ENQXJNBJ.js");
104
104
  const claudeBin = resolveClaudeBinary();
105
105
  const pairEnv = {
106
106
  ...process.env,
@@ -373,4 +373,4 @@ export {
373
373
  startClaudePair,
374
374
  submitClaudePairCode
375
375
  };
376
- //# sourceMappingURL=claude-pair-runtime-BOFTEAQC.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-T7EFAWS5.js.map
@@ -43,7 +43,7 @@ import {
43
43
  requireHost,
44
44
  safeWriteJsonAtomic,
45
45
  setConfigHash
46
- } from "../chunk-EQMRT6OT.js";
46
+ } from "../chunk-AOSBSVNB.js";
47
47
  import {
48
48
  getProjectDir as getProjectDir2,
49
49
  getReadyTasks,
@@ -132,7 +132,7 @@ import {
132
132
  takeZombieDetection,
133
133
  transcriptActivityAgeSeconds,
134
134
  writeEgressAllowlist
135
- } from "../chunk-BSTFCC62.js";
135
+ } from "../chunk-J2WYEOBH.js";
136
136
  import {
137
137
  reapOrphanChannelMcps
138
138
  } from "../chunk-XWVM4KPK.js";
@@ -8386,7 +8386,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
8386
8386
  var lastVersionCheckAt = 0;
8387
8387
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
8388
8388
  var lastResponsivenessProbeAt = 0;
8389
- var agtCliVersion = true ? "0.28.327" : "dev";
8389
+ var agtCliVersion = true ? "0.28.329" : "dev";
8390
8390
  function resolveBrewPath(execFileSync2) {
8391
8391
  try {
8392
8392
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -9282,7 +9282,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
9282
9282
  if (codeNames.length === 0) return;
9283
9283
  void (async () => {
9284
9284
  try {
9285
- const { collectDiagnostics } = await import("../persistent-session-BICDYHOC.js");
9285
+ const { collectDiagnostics } = await import("../persistent-session-ENQXJNBJ.js");
9286
9286
  await api.post("/host/heartbeat", {
9287
9287
  host_id: hostId,
9288
9288
  agent_diagnostics: collectDiagnostics(codeNames)
@@ -9381,7 +9381,7 @@ async function pollCycle() {
9381
9381
  }
9382
9382
  try {
9383
9383
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
9384
- const { collectDiagnostics } = await import("../persistent-session-BICDYHOC.js");
9384
+ const { collectDiagnostics } = await import("../persistent-session-ENQXJNBJ.js");
9385
9385
  const diagCodeNames = [...agentState.persistentSessionAgents];
9386
9386
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
9387
9387
  let tailscaleHostname;
@@ -9530,7 +9530,7 @@ async function pollCycle() {
9530
9530
  const {
9531
9531
  collectResponsivenessProbes,
9532
9532
  getResponsivenessIntervalMs
9533
- } = await import("../responsiveness-probe-FEAFPNUF.js");
9533
+ } = await import("../responsiveness-probe-OJJESVVX.js");
9534
9534
  const probeIntervalMs = getResponsivenessIntervalMs();
9535
9535
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
9536
9536
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -9562,7 +9562,7 @@ async function pollCycle() {
9562
9562
  collectResponsivenessProbes,
9563
9563
  livePendingInboundOldestAgeSeconds,
9564
9564
  parkPendingInbound
9565
- } = await import("../responsiveness-probe-FEAFPNUF.js");
9565
+ } = await import("../responsiveness-probe-OJJESVVX.js");
9566
9566
  const { getProjectDir: wedgeProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
9567
9567
  const wedgeNow = /* @__PURE__ */ new Date();
9568
9568
  const liveAgents = agentState.persistentSessionAgents;
@@ -12660,7 +12660,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
12660
12660
  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}`));
12661
12661
  void (async () => {
12662
12662
  try {
12663
- const { collectDiagnostics } = await import("../persistent-session-BICDYHOC.js");
12663
+ const { collectDiagnostics } = await import("../persistent-session-ENQXJNBJ.js");
12664
12664
  await api.post("/host/heartbeat", {
12665
12665
  host_id: hostId,
12666
12666
  agent_diagnostics: collectDiagnostics([codeName])
@@ -12710,7 +12710,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
12710
12710
  }
12711
12711
  try {
12712
12712
  const hostId = await getHostId();
12713
- const { collectDiagnostics } = await import("../persistent-session-BICDYHOC.js");
12713
+ const { collectDiagnostics } = await import("../persistent-session-ENQXJNBJ.js");
12714
12714
  await api.post("/host/heartbeat", {
12715
12715
  host_id: hostId,
12716
12716
  agent_diagnostics: collectDiagnostics([codeName])
@@ -13208,7 +13208,7 @@ async function processClaudePairSessions(agents) {
13208
13208
  killPairSession,
13209
13209
  pairTmuxSession,
13210
13210
  finalizeClaudePairOnboarding
13211
- } = await import("../claude-pair-runtime-BOFTEAQC.js");
13211
+ } = await import("../claude-pair-runtime-T7EFAWS5.js");
13212
13212
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
13213
13213
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
13214
13214
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -14255,6 +14255,129 @@ function writeTurnInitiatorMarker(input) {
14255
14255
  }
14256
14256
  }
14257
14257
 
14258
+ // src/direct-chat-pending-inbound.ts
14259
+ import {
14260
+ existsSync as existsSync2,
14261
+ mkdirSync as mkdirSync2,
14262
+ readdirSync,
14263
+ renameSync as renameSync2,
14264
+ unlinkSync,
14265
+ writeFileSync as writeFileSync2
14266
+ } from "fs";
14267
+ import { join as join3 } from "path";
14268
+ function hexEncodeSegment(value) {
14269
+ return Buffer.from(value, "utf8").toString("hex");
14270
+ }
14271
+ function directChatMarkerName(sessionId, messageId) {
14272
+ return `${hexEncodeSegment(sessionId)}__${hexEncodeSegment(messageId)}.json`;
14273
+ }
14274
+ var defaultClearMarkerFile = (fullPath) => {
14275
+ try {
14276
+ if (existsSync2(fullPath)) unlinkSync(fullPath);
14277
+ } catch {
14278
+ }
14279
+ };
14280
+ function directChatInboundId(sessionId, messageId) {
14281
+ return `direct-chat|${sessionId.length}|${sessionId}|${messageId}`;
14282
+ }
14283
+ function writeDirectChatPendingInboundMarker(dir, sessionId, messageId) {
14284
+ if (!dir || !sessionId || !messageId) return;
14285
+ try {
14286
+ mkdirSync2(dir, { recursive: true });
14287
+ const marker = {
14288
+ channel: "direct-chat",
14289
+ session_id: sessionId,
14290
+ message_id: messageId,
14291
+ received_at: (/* @__PURE__ */ new Date()).toISOString(),
14292
+ inbound_id: directChatInboundId(sessionId, messageId)
14293
+ };
14294
+ const final = join3(dir, directChatMarkerName(sessionId, messageId));
14295
+ const tmp = `${final}.tmp`;
14296
+ writeFileSync2(tmp, JSON.stringify(marker), "utf8");
14297
+ renameSync2(tmp, final);
14298
+ } catch {
14299
+ }
14300
+ }
14301
+ function clearDirectChatPendingMarkersForSession(dir, sessionId, op = defaultClearMarkerFile) {
14302
+ if (!dir || !sessionId) return 0;
14303
+ const prefix = `${hexEncodeSegment(sessionId)}__`;
14304
+ let cleared = 0;
14305
+ let names;
14306
+ try {
14307
+ names = readdirSync(dir);
14308
+ } catch {
14309
+ return 0;
14310
+ }
14311
+ for (const name of names) {
14312
+ if (!name.startsWith(prefix) || !name.endsWith(".json")) continue;
14313
+ op(join3(dir, name));
14314
+ cleared += 1;
14315
+ }
14316
+ return cleared;
14317
+ }
14318
+
14319
+ // src/direct-chat-recovery-outbox.ts
14320
+ async function consumeDirectChatRecoveryFile(fullPath, filename, deps) {
14321
+ if (filename.endsWith(".tmp") || filename.endsWith(".poison")) return "skipped";
14322
+ let payload;
14323
+ try {
14324
+ payload = JSON.parse(deps.readFile(fullPath));
14325
+ } catch (err) {
14326
+ deps.log(`recovery outbox parse failed (${filename}): ${err.message}`);
14327
+ try {
14328
+ deps.renameFile(fullPath, `${fullPath}.parse-error.poison`);
14329
+ } catch {
14330
+ }
14331
+ return "poison";
14332
+ }
14333
+ if (!payload || !payload.session_id || !payload.text) {
14334
+ deps.log(`recovery outbox malformed (${filename}): missing session_id or text`);
14335
+ if (payload && payload.marker_name) {
14336
+ try {
14337
+ deps.removeLedgerEntry(payload.marker_name);
14338
+ } catch {
14339
+ }
14340
+ }
14341
+ try {
14342
+ deps.renameFile(fullPath, `${fullPath}.malformed.poison`);
14343
+ } catch {
14344
+ }
14345
+ return "poison";
14346
+ }
14347
+ const content = deps.sanitize(payload.text);
14348
+ const messageIds = deps.peekClaims(payload.session_id);
14349
+ let result;
14350
+ try {
14351
+ result = await deps.deliver({
14352
+ sessionId: payload.session_id,
14353
+ content,
14354
+ messageIds
14355
+ });
14356
+ } catch (err) {
14357
+ result = { ok: false, error: err.message };
14358
+ }
14359
+ if (result.ok && !result.error) {
14360
+ deps.clearClaims(payload.session_id, messageIds);
14361
+ deps.clearMarkers(payload.session_id);
14362
+ if (payload.marker_name) deps.removeLedgerEntry(payload.marker_name);
14363
+ try {
14364
+ deps.unlinkFile(fullPath);
14365
+ } catch {
14366
+ }
14367
+ deps.log(`ghost-reply recovery sent (session=${payload.session_id})`);
14368
+ return "delivered";
14369
+ }
14370
+ if (payload.marker_name) deps.removeLedgerEntry(payload.marker_name);
14371
+ try {
14372
+ deps.unlinkFile(fullPath);
14373
+ } catch {
14374
+ }
14375
+ deps.log(
14376
+ `ghost-reply recovery send failed (session=${payload.session_id}): ${result.error ?? "unknown"} - re-armed for retry`
14377
+ );
14378
+ return "failed";
14379
+ }
14380
+
14258
14381
  // src/direct-chat-poll-guard.ts
14259
14382
  function evaluatePollGuard(state, nowMs, stuckMs) {
14260
14383
  if (!state.inFlight) return { run: true, stuck: false };
@@ -14277,14 +14400,14 @@ async function fetchWithTimeout(input, init, timeoutMs, fetchImpl = fetch) {
14277
14400
 
14278
14401
  // src/mcp-spawn-lock.ts
14279
14402
  import {
14280
- existsSync as existsSync2,
14281
- mkdirSync as mkdirSync2,
14403
+ existsSync as existsSync3,
14404
+ mkdirSync as mkdirSync3,
14282
14405
  readFileSync as readFileSync3,
14283
- renameSync as renameSync2,
14284
- unlinkSync,
14285
- writeFileSync as writeFileSync2
14406
+ renameSync as renameSync3,
14407
+ unlinkSync as unlinkSync2,
14408
+ writeFileSync as writeFileSync3
14286
14409
  } from "fs";
14287
- import { join as join3 } from "path";
14410
+ import { join as join4 } from "path";
14288
14411
  function defaultIsPidAlive(pid) {
14289
14412
  if (!Number.isFinite(pid) || pid <= 0) return false;
14290
14413
  try {
@@ -14302,7 +14425,7 @@ function acquireMcpSpawnLock(args) {
14302
14425
  const isPidAlive = options.isPidAlive ?? defaultIsPidAlive;
14303
14426
  const selfPid = options.selfPid ?? process.pid;
14304
14427
  const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
14305
- const path = join3(agentDir, basename);
14428
+ const path = join4(agentDir, basename);
14306
14429
  const existing = readLockHolder(path);
14307
14430
  if (existing) {
14308
14431
  if (existing.pid === selfPid) {
@@ -14312,11 +14435,11 @@ function acquireMcpSpawnLock(args) {
14312
14435
  return { kind: "blocked", path, holder: existing };
14313
14436
  }
14314
14437
  }
14315
- mkdirSync2(agentDir, { recursive: true, mode: 448 });
14438
+ mkdirSync3(agentDir, { recursive: true, mode: 448 });
14316
14439
  const tmpPath = `${path}.${selfPid}.tmp`;
14317
14440
  const payload = { pid: selfPid, started_at: now() };
14318
- writeFileSync2(tmpPath, JSON.stringify(payload), { mode: 384 });
14319
- renameSync2(tmpPath, path);
14441
+ writeFileSync3(tmpPath, JSON.stringify(payload), { mode: 384 });
14442
+ renameSync3(tmpPath, path);
14320
14443
  return { kind: "acquired", path };
14321
14444
  }
14322
14445
  function releaseMcpSpawnLock(lockPath, opts = {}) {
@@ -14326,12 +14449,12 @@ function releaseMcpSpawnLock(lockPath, opts = {}) {
14326
14449
  if (!existing) return;
14327
14450
  if (existing.pid !== selfPid) return;
14328
14451
  try {
14329
- unlinkSync(lockPath);
14452
+ unlinkSync2(lockPath);
14330
14453
  } catch {
14331
14454
  }
14332
14455
  }
14333
14456
  function readLockHolder(path) {
14334
- if (!existsSync2(path)) return null;
14457
+ if (!existsSync3(path)) return null;
14335
14458
  try {
14336
14459
  const raw = readFileSync3(path, "utf8");
14337
14460
  const parsed = JSON.parse(raw);
@@ -14346,35 +14469,36 @@ function readLockHolder(path) {
14346
14469
 
14347
14470
  // src/direct-chat-channel.ts
14348
14471
  import { homedir as homedir2 } from "os";
14349
- import { join as join6 } from "path";
14472
+ import { join as join7 } from "path";
14350
14473
  import { randomUUID } from "crypto";
14351
14474
  import {
14352
14475
  watch,
14353
- mkdirSync as mkdirSync3,
14354
- writeFileSync as writeFileSync3,
14476
+ mkdirSync as mkdirSync4,
14477
+ writeFileSync as writeFileSync4,
14355
14478
  readFileSync as readFileSync5,
14356
- existsSync as existsSync4,
14357
- renameSync as renameSync3,
14358
- unlinkSync as unlinkSync2
14479
+ readdirSync as readdirSync2,
14480
+ existsSync as existsSync5,
14481
+ renameSync as renameSync4,
14482
+ unlinkSync as unlinkSync3
14359
14483
  } from "fs";
14360
14484
 
14361
14485
  // src/direct-chat-inbound-attachments.ts
14362
- import { dirname as dirname2, join as join4 } from "path";
14486
+ import { dirname as dirname2, join as join5 } from "path";
14363
14487
  var MAX_INBOUND_ATTACHMENT_BYTES = 10 * 1024 * 1024;
14364
14488
  var INBOUND_ATTACHMENTS_SUBDIR = "direct-chat-inbound";
14365
14489
  function resolveInboundAttachmentsDir(input) {
14366
14490
  const { codeName, turnInitiatorFile, agentId, homeDir } = input;
14367
14491
  const codeNameTrimmed = typeof codeName === "string" ? codeName.trim() : "";
14368
14492
  if (codeNameTrimmed) {
14369
- return join4(homeDir, ".augmented", codeNameTrimmed, INBOUND_ATTACHMENTS_SUBDIR);
14493
+ return join5(homeDir, ".augmented", codeNameTrimmed, INBOUND_ATTACHMENTS_SUBDIR);
14370
14494
  }
14371
14495
  const initiator = typeof turnInitiatorFile === "string" ? turnInitiatorFile.trim() : "";
14372
14496
  if (initiator) {
14373
- return join4(dirname2(initiator), INBOUND_ATTACHMENTS_SUBDIR);
14497
+ return join5(dirname2(initiator), INBOUND_ATTACHMENTS_SUBDIR);
14374
14498
  }
14375
14499
  const agentIdTrimmed = typeof agentId === "string" ? agentId.trim() : "";
14376
14500
  if (agentIdTrimmed) {
14377
- return join4(homeDir, ".augmented", agentIdTrimmed, INBOUND_ATTACHMENTS_SUBDIR);
14501
+ return join5(homeDir, ".augmented", agentIdTrimmed, INBOUND_ATTACHMENTS_SUBDIR);
14378
14502
  }
14379
14503
  return null;
14380
14504
  }
@@ -14472,11 +14596,11 @@ async function downloadInboundAttachments(attachments, dir, deps) {
14472
14596
  }
14473
14597
 
14474
14598
  // src/flags-cache-read.ts
14475
- import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
14599
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
14476
14600
  import { homedir } from "os";
14477
- import { join as join5 } from "path";
14601
+ import { join as join6 } from "path";
14478
14602
  function defaultFlagsCachePath() {
14479
- return join5(homedir(), ".augmented", "flags-cache.json");
14603
+ return join6(homedir(), ".augmented", "flags-cache.json");
14480
14604
  }
14481
14605
  function envBoolean(raw) {
14482
14606
  if (raw === void 0) return void 0;
@@ -14488,7 +14612,7 @@ function envBoolean(raw) {
14488
14612
  }
14489
14613
  function cachedBoolean(key, path) {
14490
14614
  try {
14491
- if (!existsSync3(path)) return void 0;
14615
+ if (!existsSync4(path)) return void 0;
14492
14616
  const parsed = JSON.parse(readFileSync4(path, "utf8"));
14493
14617
  if (!parsed || typeof parsed !== "object") return void 0;
14494
14618
  const flags = parsed.flags;
@@ -14826,7 +14950,7 @@ var DIRECT_CHAT_MAINTENANCE_COOLDOWN_MS = (() => {
14826
14950
  var AGT_HOST = process.env.AGT_HOST;
14827
14951
  var AGT_API_KEY = process.env.AGT_API_KEY;
14828
14952
  var AGT_AGENT_ID = process.env.AGT_AGENT_ID;
14829
- var DIRECT_CHAT_AGENT_DIR = AGT_AGENT_ID ? join6(homedir2(), ".augmented", AGT_AGENT_ID) : null;
14953
+ var DIRECT_CHAT_AGENT_DIR = AGT_AGENT_ID ? join7(homedir2(), ".augmented", AGT_AGENT_ID) : null;
14830
14954
  var INBOUND_ATTACHMENTS_DIR = resolveInboundAttachmentsDir({
14831
14955
  codeName: process.env.AGT_AGENT_CODE_NAME,
14832
14956
  turnInitiatorFile: process.env.AGT_TURN_INITIATOR_FILE,
@@ -14834,7 +14958,10 @@ var INBOUND_ATTACHMENTS_DIR = resolveInboundAttachmentsDir({
14834
14958
  homeDir: homedir2()
14835
14959
  });
14836
14960
  var AGT_AGENT_CODE_NAME = process.env.AGT_AGENT_CODE_NAME;
14837
- var PROGRESS_HEARTBEAT_PATH = AGT_AGENT_CODE_NAME ? join6(homedir2(), ".augmented", AGT_AGENT_CODE_NAME, "channel-progress-heartbeat.json") : null;
14961
+ var PROGRESS_HEARTBEAT_PATH = AGT_AGENT_CODE_NAME ? join7(homedir2(), ".augmented", AGT_AGENT_CODE_NAME, "channel-progress-heartbeat.json") : null;
14962
+ var DIRECT_CHAT_PENDING_INBOUND_DIR = AGT_AGENT_CODE_NAME ? join7(homedir2(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-pending-inbound") : null;
14963
+ var DIRECT_CHAT_RECOVERY_OUTBOX_DIR = AGT_AGENT_CODE_NAME ? join7(homedir2(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-recovery-outbox") : null;
14964
+ var DIRECT_CHAT_RECOVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join7(homedir2(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-direct-chat-recovery-ledger") : null;
14838
14965
  var progressReceivedAt = /* @__PURE__ */ new Map();
14839
14966
  var directChatProgressState = { tracked: null };
14840
14967
  var directChatProgressTickRunning = false;
@@ -14851,7 +14978,7 @@ var directChatKanbanCardClient = createKanbanCardActiveClient({
14851
14978
  `)
14852
14979
  });
14853
14980
  function readProgressHeartbeat() {
14854
- if (!PROGRESS_HEARTBEAT_PATH || !existsSync4(PROGRESS_HEARTBEAT_PATH)) return null;
14981
+ if (!PROGRESS_HEARTBEAT_PATH || !existsSync5(PROGRESS_HEARTBEAT_PATH)) return null;
14855
14982
  try {
14856
14983
  return parseProgressHeartbeat(readFileSync5(PROGRESS_HEARTBEAT_PATH, "utf-8"));
14857
14984
  } catch {
@@ -14862,12 +14989,12 @@ function seedProgressHeartbeat() {
14862
14989
  if (!PROGRESS_HEARTBEAT_PATH) return;
14863
14990
  const tmp = `${PROGRESS_HEARTBEAT_PATH}.${process.pid}.tmp`;
14864
14991
  try {
14865
- mkdirSync3(join6(homedir2(), ".augmented", AGT_AGENT_CODE_NAME), { recursive: true });
14866
- writeFileSync3(tmp, serializeProgressHeartbeat(SEED_PROGRESS_STEP, Date.now()), { mode: 384 });
14867
- renameSync3(tmp, PROGRESS_HEARTBEAT_PATH);
14992
+ mkdirSync4(join7(homedir2(), ".augmented", AGT_AGENT_CODE_NAME), { recursive: true });
14993
+ writeFileSync4(tmp, serializeProgressHeartbeat(SEED_PROGRESS_STEP, Date.now()), { mode: 384 });
14994
+ renameSync4(tmp, PROGRESS_HEARTBEAT_PATH);
14868
14995
  } catch {
14869
14996
  try {
14870
- unlinkSync2(tmp);
14997
+ unlinkSync3(tmp);
14871
14998
  } catch {
14872
14999
  }
14873
15000
  }
@@ -15020,9 +15147,9 @@ var inboundAttachmentDeps = {
15020
15147
  bytes: async () => new Uint8Array(await res.arrayBuffer())
15021
15148
  };
15022
15149
  },
15023
- ensureDir: (dir) => mkdirSync3(dir, { recursive: true }),
15024
- writeFile: (path, bytes) => writeFileSync3(path, bytes, { mode: 384 }),
15025
- joinPath: (...parts) => join6(...parts),
15150
+ ensureDir: (dir) => mkdirSync4(dir, { recursive: true }),
15151
+ writeFile: (path, bytes) => writeFileSync4(path, bytes, { mode: 384 }),
15152
+ joinPath: (...parts) => join7(...parts),
15026
15153
  warn: (msg) => process.stderr.write(`${msg}
15027
15154
  `)
15028
15155
  };
@@ -15190,6 +15317,7 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
15190
15317
  };
15191
15318
  }
15192
15319
  claimTracker.clear(session_id, message_ids);
15320
+ clearDirectChatPendingMarkersForSession(DIRECT_CHAT_PENDING_INBOUND_DIR, session_id);
15193
15321
  const messageId = data.message_id;
15194
15322
  for (let i = 1; i < slices.length; i++) {
15195
15323
  await sleep(STREAM_REPLY_FLUSH_MS);
@@ -15234,6 +15362,7 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
15234
15362
  };
15235
15363
  }
15236
15364
  claimTracker.clear(session_id, message_ids);
15365
+ clearDirectChatPendingMarkersForSession(DIRECT_CHAT_PENDING_INBOUND_DIR, session_id);
15237
15366
  return { content: [{ type: "text", text: "sent" }] };
15238
15367
  } catch (err) {
15239
15368
  return {
@@ -15262,6 +15391,7 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
15262
15391
  };
15263
15392
  }
15264
15393
  claimTracker.clear(session_id, message_ids);
15394
+ clearDirectChatPendingMarkersForSession(DIRECT_CHAT_PENDING_INBOUND_DIR, session_id);
15265
15395
  return { content: [{ type: "text", text: "consumed" }] };
15266
15396
  } catch (err) {
15267
15397
  return {
@@ -15361,6 +15491,13 @@ async function pollForMessages(sinceMs) {
15361
15491
  }
15362
15492
  }
15363
15493
  });
15494
+ if (!isNotice) {
15495
+ writeDirectChatPendingInboundMarker(
15496
+ DIRECT_CHAT_PENDING_INBOUND_DIR,
15497
+ msg.session_id,
15498
+ msg.id
15499
+ );
15500
+ }
15364
15501
  if (!isNotice && msg.sender_id) {
15365
15502
  writeTurnInitiatorMarker({
15366
15503
  channel: "direct-chat",
@@ -15450,7 +15587,7 @@ var doorbellWatcher = null;
15450
15587
  var safetyNetTimer = null;
15451
15588
  if (DOORBELL_ENABLED && DIRECT_CHAT_AGENT_DIR) {
15452
15589
  try {
15453
- mkdirSync3(DIRECT_CHAT_AGENT_DIR, { recursive: true });
15590
+ mkdirSync4(DIRECT_CHAT_AGENT_DIR, { recursive: true });
15454
15591
  } catch {
15455
15592
  }
15456
15593
  const sessionState = readDirectChatSessionState(DIRECT_CHAT_AGENT_DIR, Date.now());
@@ -15494,6 +15631,106 @@ if (PROGRESS_HEARTBEAT_PATH) {
15494
15631
  }, PROGRESS_TICK_MS);
15495
15632
  progressTickTimer.unref?.();
15496
15633
  }
15634
+ function sanitizeRecoveryText(text) {
15635
+ const preamble = stripRepostPreambleWithMeta(text);
15636
+ if (preamble.stripped) emitPreambleStripTelemetry("direct_chat", preamble.shape);
15637
+ const guarded = redactToolCallMarkup(preamble.text);
15638
+ if (guarded.redacted) emitToolCallMarkupRedactionTelemetry("direct_chat");
15639
+ const apiErr = rewriteTransientApiError(guarded.text);
15640
+ if (apiErr.rewritten) emitTransientApiErrorTelemetry("direct_chat", apiErr.match, apiErr.original);
15641
+ return apiErr.text;
15642
+ }
15643
+ function directChatRecoveryDeps() {
15644
+ return {
15645
+ readFile: (p) => readFileSync5(p, "utf-8"),
15646
+ renameFile: (from, to) => renameSync4(from, to),
15647
+ unlinkFile: (p) => {
15648
+ if (existsSync5(p)) unlinkSync3(p);
15649
+ },
15650
+ sanitize: sanitizeRecoveryText,
15651
+ peekClaims: (sessionId) => claimTracker.peek(sessionId),
15652
+ clearClaims: (sessionId, ids) => claimTracker.clear(sessionId, ids),
15653
+ clearMarkers: (sessionId) => clearDirectChatPendingMarkersForSession(DIRECT_CHAT_PENDING_INBOUND_DIR, sessionId),
15654
+ removeLedgerEntry: (markerName) => {
15655
+ if (!DIRECT_CHAT_RECOVERY_LEDGER_DIR) return;
15656
+ if (markerName.includes("/") || markerName.includes("\\") || markerName.includes("..")) return;
15657
+ try {
15658
+ const p = join7(DIRECT_CHAT_RECOVERY_LEDGER_DIR, markerName);
15659
+ if (existsSync5(p)) unlinkSync3(p);
15660
+ } catch {
15661
+ }
15662
+ },
15663
+ deliver: async ({ sessionId, content, messageIds }) => {
15664
+ try {
15665
+ const res = await apiPost("/host/direct-chat/reply", {
15666
+ agent_id: AGT_AGENT_ID,
15667
+ session_id: sessionId,
15668
+ content,
15669
+ message_ids: messageIds
15670
+ });
15671
+ const data = await res.json().catch(() => ({}));
15672
+ if (!res.ok || data.error) return { ok: false, error: data.error ?? `HTTP ${res.status}` };
15673
+ return { ok: true };
15674
+ } catch (err) {
15675
+ return { ok: false, error: err.message };
15676
+ }
15677
+ },
15678
+ log: (line) => process.stderr.write(`direct-chat-channel(${AGT_AGENT_CODE_NAME}): ${line}
15679
+ `)
15680
+ };
15681
+ }
15682
+ var directChatRecoveryInFlight = /* @__PURE__ */ new Set();
15683
+ async function processDirectChatRecoveryOutboxFile(filename) {
15684
+ if (!DIRECT_CHAT_RECOVERY_OUTBOX_DIR) return;
15685
+ if (directChatRecoveryInFlight.has(filename)) return;
15686
+ const enabled = resolveHostBooleanFlag({
15687
+ key: "direct-chat-recovery",
15688
+ envVar: "AGT_DIRECT_CHAT_RECOVERY_ENABLED",
15689
+ defaultValue: false
15690
+ });
15691
+ if (!enabled) return;
15692
+ directChatRecoveryInFlight.add(filename);
15693
+ try {
15694
+ const fullPath = join7(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, filename);
15695
+ await consumeDirectChatRecoveryFile(fullPath, filename, directChatRecoveryDeps());
15696
+ } catch (err) {
15697
+ process.stderr.write(
15698
+ `direct-chat-channel(${AGT_AGENT_CODE_NAME}): recovery consume failed (${filename}): ${err.message}
15699
+ `
15700
+ );
15701
+ } finally {
15702
+ directChatRecoveryInFlight.delete(filename);
15703
+ }
15704
+ }
15705
+ var directChatRecoveryWatcher = null;
15706
+ if (DIRECT_CHAT_RECOVERY_OUTBOX_DIR) {
15707
+ try {
15708
+ mkdirSync4(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, { recursive: true, mode: 448 });
15709
+ } catch {
15710
+ }
15711
+ try {
15712
+ for (const f of readdirSync2(DIRECT_CHAT_RECOVERY_OUTBOX_DIR)) {
15713
+ if (f.endsWith(".json")) void processDirectChatRecoveryOutboxFile(f);
15714
+ }
15715
+ } catch {
15716
+ }
15717
+ try {
15718
+ directChatRecoveryWatcher = watch(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, (_event, filename) => {
15719
+ if (!filename) return;
15720
+ const name = filename.toString();
15721
+ if (!name.endsWith(".json")) return;
15722
+ if (existsSync5(join7(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, name))) {
15723
+ void processDirectChatRecoveryOutboxFile(name);
15724
+ }
15725
+ });
15726
+ directChatRecoveryWatcher.unref?.();
15727
+ } catch (err) {
15728
+ process.stderr.write(
15729
+ `direct-chat-channel(${AGT_AGENT_CODE_NAME}): recovery watcher failed (${err.message})
15730
+ `
15731
+ );
15732
+ }
15733
+ }
15497
15734
  var isShuttingDown = false;
15498
15735
  function shutdown(reason) {
15499
15736
  if (isShuttingDown) return;
@@ -39592,7 +39592,8 @@ var WAITING_KINDS = [
39592
39592
  "pr-merged",
39593
39593
  "human",
39594
39594
  "external",
39595
- "other"
39595
+ "other",
39596
+ "approval"
39596
39597
  ];
39597
39598
  var WAITING_KIND_SET = new Set(WAITING_KINDS);
39598
39599
 
@@ -39985,6 +39986,16 @@ var FLAG_REGISTRY = [
39985
39986
  defaultValue: false,
39986
39987
  envVar: "AGT_LIVE_STREAM_PRODUCER_ENABLED"
39987
39988
  },
39989
+ {
39990
+ key: "auto-provision-agt-live",
39991
+ description: "Auto-provision the Augmented Live integration (free tier, watermarked) into every NEW organization as an org-scoped install (ENG-7819). Consumed in TWO places: the seed_default_live_integration AFTER INSERT trigger on organizations reads the EXPLICIT feature_flags row (a plpgsql trigger cannot see this compiled default, so dark = no row = trigger no-ops; flipping the flag on this page writes the row the trigger reads - GLOBAL value only, per-org overrides are not consulted by the trigger), and the POST /organizations route evaluates it normally to send the owner provisioning notice. Restricted-posture orgs are skipped; opt-out (remove/block) is permanent - no reconciler. Boolean gate; ships dark. Pre-flip gates: docs/operator/default-integrations-admission.md.",
39992
+ flagType: "boolean",
39993
+ defaultValue: false,
39994
+ // Grants every new open org a public-publishing capability by default;
39995
+ // flipping it on is fleet-shaping and worth an explicit confirm (ADR-0022
39996
+ // §4, same treatment as augmented-support-auto-provision).
39997
+ sensitive: true
39998
+ },
39988
39999
  {
39989
40000
  key: "admin-live-pane",
39990
40001
  description: "Live agent pane streaming on the platform-admin surfaces (ENG-6588): the agent Diagnostics tab and the /admin embed poll GET /admin/agents/:id/pane (tmux capture-pane over SSM) ~every 3s for a bounded window. Boolean gate; ships dark; when OFF the route returns feature_disabled and the UI falls back to the 30s static diagnostics snapshot. It is the no-deploy kill switch bounding the shared-SSM blast radius (SSM SendCommand throttles account-wide, shared with incident-response runbooks).",
@@ -40097,6 +40108,16 @@ var FLAG_REGISTRY = [
40097
40108
  // canary is a high-blast-radius change worth an explicit confirm.
40098
40109
  sensitive: true
40099
40110
  },
40111
+ {
40112
+ key: "direct-chat-recovery",
40113
+ description: "Always-on direct-chat ghost-reply recovery (ENG-7814, ENG-6722 slice E). direct-chat has no recovery-outbox by default: block-turn-end (channel-block-turn-end) only makes the MODEL re-send and is dark/canary, so a direct-chat turn answered as plain text with no direct_chat.reply is lost. When ON, the ghost-reply Stop hook, for an owed and unanswered direct-chat inbound where block-turn-end did not fire, writes the last assistant text to a direct-chat-recovery-outbox that the direct-chat MCP consumes and POSTs to /host/direct-chat/reply for the session, re-sending the reply the agent produced but never delivered. session_id is unambiguous (one session per marker), so there is no cross-thread mis-correlation risk (why direct-chat can safely re-send where Slack needs the ENG-7806 ledger). Confirm-before-clear: the pending marker is cleared only after the POST confirms; a per-marker recovery ledger caps one in-flight recovery per inbound and re-arms on failure. Independent of channel-block-turn-end (either can be on). The env var AGT_DIRECT_CHAT_RECOVERY_ENABLED is the operator/host override the bash hook reads directly (materialized by the manager) and the MCP resolves via the flags cache. Boolean gate; ships dark, flip per host/org to canary before fleet rollout.",
40114
+ flagType: "boolean",
40115
+ defaultValue: false,
40116
+ envVar: "AGT_DIRECT_CHAT_RECOVERY_ENABLED",
40117
+ // Re-sends a reply on the agent behalf (a customer-visible send); flipping it
40118
+ // beyond a canary is a blast-radius change worth an explicit confirm.
40119
+ sensitive: true
40120
+ },
40100
40121
  {
40101
40122
  key: "ghost-reply-intent-classifier",
40102
40123
  description: `Intentional-non-reply suppression on the ghost-reply RECOVERY path (ENG-7096, ENG-7478). The recovery-outbox consumer in the channel MCP only ever fires for turns where the agent ended with text but did NOT call the matching reply tool for that conversation - a set that includes DELIBERATE non-replies and internal third-person self-status narration ("Filed CS-1443... standing by"). A cheap model (the conversation-eval backend, AGT_CONV_EVAL_*) classifies the recovered text as a real message for the user (deliver) or internal not-replying / self-status narration (suppress), keyed on grammatical person, biased to DELIVER and fail-open (a classifier outage degrades to today's behaviour, never a dropped real reply). off = classifier never runs, every recovered reply is posted exactly as today (ships dark, == the old boolean-false). shadow = classify + log the would-suppress verdict for operator adjudication but STILL DELIVER (measure the suppression rate before acting). enforce = actually suppress on a clean high-confidence suppress verdict. The channel server reads this live from the heartbeat flags-cache (or the env override); enforce is a deliberate, audited per-org flip after a shadow soak.`,
@@ -36,7 +36,7 @@ import {
36
36
  writeDirectChatSessionState,
37
37
  writeEgressAllowlist,
38
38
  writePersistentClaudeWrapper
39
- } from "./chunk-BSTFCC62.js";
39
+ } from "./chunk-J2WYEOBH.js";
40
40
  import "./chunk-XWVM4KPK.js";
41
41
  export {
42
42
  EGRESS_BASELINE_DOMAINS,
@@ -77,4 +77,4 @@ export {
77
77
  writeEgressAllowlist,
78
78
  writePersistentClaudeWrapper
79
79
  };
80
- //# sourceMappingURL=persistent-session-BICDYHOC.js.map
80
+ //# sourceMappingURL=persistent-session-ENQXJNBJ.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  paneLogPath
3
- } from "./chunk-BSTFCC62.js";
3
+ } from "./chunk-J2WYEOBH.js";
4
4
  import "./chunk-XWVM4KPK.js";
5
5
 
6
6
  // src/lib/responsiveness-probe.ts
@@ -427,4 +427,4 @@ export {
427
427
  readAndResetSlackReplyBindingClassifications,
428
428
  readAndResetSlackReplyTargetClassifications
429
429
  };
430
- //# sourceMappingURL=responsiveness-probe-FEAFPNUF.js.map
430
+ //# sourceMappingURL=responsiveness-probe-OJJESVVX.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.28.327",
3
+ "version": "0.28.329",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {