@integrity-labs/agt-cli 0.28.460 → 0.28.461

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.
@@ -30,7 +30,7 @@ import {
30
30
  resolveConnectivityProbe,
31
31
  worseConnectivityOutcome,
32
32
  wrapScheduledTaskPrompt
33
- } from "./chunk-BWH5XTDU.js";
33
+ } from "./chunk-QZUECTC7.js";
34
34
  import {
35
35
  parsePsRows
36
36
  } from "./chunk-XWVM4KPK.js";
@@ -4911,7 +4911,7 @@ function requireHost() {
4911
4911
  }
4912
4912
 
4913
4913
  // src/lib/api-client.ts
4914
- var agtCliVersion = true ? "0.28.460" : "dev";
4914
+ var agtCliVersion = true ? "0.28.461" : "dev";
4915
4915
  var lastConfigHash = null;
4916
4916
  function setConfigHash(hash) {
4917
4917
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -7449,4 +7449,4 @@ export {
7449
7449
  managerInstallSystemUnitCommand,
7450
7450
  managerUninstallSystemUnitCommand
7451
7451
  };
7452
- //# sourceMappingURL=chunk-EBSFYBRI.js.map
7452
+ //# sourceMappingURL=chunk-WCYGJANF.js.map
@@ -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-KGRCIIS5.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-HRVZVAIL.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-YNOY2ATX.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-VTW57E4U.js.map
@@ -42,7 +42,7 @@ import {
42
42
  resolveEffectivePinRaw,
43
43
  safeWriteJsonAtomic,
44
44
  setConfigHash
45
- } from "../chunk-EBSFYBRI.js";
45
+ } from "../chunk-WCYGJANF.js";
46
46
  import {
47
47
  getProjectDir as getProjectDir2,
48
48
  getReadyTasks,
@@ -164,7 +164,7 @@ import {
164
164
  toOpencodeModel,
165
165
  transcriptActivityAgeSeconds,
166
166
  writeEgressAllowlist
167
- } from "../chunk-BWH5XTDU.js";
167
+ } from "../chunk-QZUECTC7.js";
168
168
  import {
169
169
  reapOrphanChannelMcps
170
170
  } from "../chunk-XWVM4KPK.js";
@@ -9976,7 +9976,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
9976
9976
  var lastVersionCheckAt = 0;
9977
9977
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
9978
9978
  var lastResponsivenessProbeAt = 0;
9979
- var agtCliVersion = true ? "0.28.460" : "dev";
9979
+ var agtCliVersion = true ? "0.28.461" : "dev";
9980
9980
  function resolveBrewPath(execFileSync2) {
9981
9981
  try {
9982
9982
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -11137,7 +11137,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
11137
11137
  if (codeNames.length === 0) return;
11138
11138
  void (async () => {
11139
11139
  try {
11140
- const { collectDiagnostics } = await import("../persistent-session-KGRCIIS5.js");
11140
+ const { collectDiagnostics } = await import("../persistent-session-HRVZVAIL.js");
11141
11141
  await api.post("/host/heartbeat", {
11142
11142
  host_id: hostId,
11143
11143
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor)
@@ -11244,7 +11244,7 @@ async function pollCycle() {
11244
11244
  }
11245
11245
  try {
11246
11246
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
11247
- const { collectDiagnostics } = await import("../persistent-session-KGRCIIS5.js");
11247
+ const { collectDiagnostics } = await import("../persistent-session-HRVZVAIL.js");
11248
11248
  const diagCodeNames = [...agentState.persistentSessionAgents];
11249
11249
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor) : void 0;
11250
11250
  let tailscaleHostname;
@@ -11358,7 +11358,7 @@ async function pollCycle() {
11358
11358
  collectResponsivenessProbes,
11359
11359
  collectPanelessActivityProbes,
11360
11360
  getResponsivenessIntervalMs
11361
- } = await import("../responsiveness-probe-4FVGB6NY.js");
11361
+ } = await import("../responsiveness-probe-UUVXQIQ4.js");
11362
11362
  const probeIntervalMs = getResponsivenessIntervalMs();
11363
11363
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
11364
11364
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -11422,7 +11422,7 @@ async function pollCycle() {
11422
11422
  collectResponsivenessProbes,
11423
11423
  livePendingInboundOldestAgeSeconds,
11424
11424
  parkPendingInbound
11425
- } = await import("../responsiveness-probe-4FVGB6NY.js");
11425
+ } = await import("../responsiveness-probe-UUVXQIQ4.js");
11426
11426
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
11427
11427
  const wedgeNow = /* @__PURE__ */ new Date();
11428
11428
  const liveAgents = agentState.persistentSessionAgents;
@@ -14800,7 +14800,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
14800
14800
  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}`));
14801
14801
  void (async () => {
14802
14802
  try {
14803
- const { collectDiagnostics } = await import("../persistent-session-KGRCIIS5.js");
14803
+ const { collectDiagnostics } = await import("../persistent-session-HRVZVAIL.js");
14804
14804
  await api.post("/host/heartbeat", {
14805
14805
  host_id: hostId,
14806
14806
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
@@ -14850,7 +14850,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
14850
14850
  }
14851
14851
  try {
14852
14852
  const hostId = await getHostId();
14853
- const { collectDiagnostics } = await import("../persistent-session-KGRCIIS5.js");
14853
+ const { collectDiagnostics } = await import("../persistent-session-HRVZVAIL.js");
14854
14854
  await api.post("/host/heartbeat", {
14855
14855
  host_id: hostId,
14856
14856
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
@@ -15303,7 +15303,7 @@ async function processClaudePairSessions(agents) {
15303
15303
  killPairSession,
15304
15304
  pairTmuxSession,
15305
15305
  finalizeClaudePairOnboarding
15306
- } = await import("../claude-pair-runtime-YNOY2ATX.js");
15306
+ } = await import("../claude-pair-runtime-VTW57E4U.js");
15307
15307
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
15308
15308
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
15309
15309
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -34522,6 +34522,12 @@ var FLAG_REGISTRY = [
34522
34522
  // operational decision with blast radius, so mutations require confirmation.
34523
34523
  sensitive: true
34524
34524
  },
34525
+ {
34526
+ key: "promise-outstanding-alarm",
34527
+ description: 'Outstanding-interim-promise alarm (ENG-8265): when ON, the responsiveness-probe route creates a per-agent CloudWatch alarm on `PromiseOutstandingOldestAgeSeconds` \u2014 an inbound the agent acknowledged with an interim reply ("on it") and never answered substantively. Closes the blind spot where an ack satisfied channel-silent-loss, refreshed pending-inbound, and left agent_stall with no in_progress card to see, so a broken promise looked like a served request. Defaults ON (armed on deploy) because the alert it opens is `info` severity \u2014 dashboard-only, never paged \u2014 so a day-one false positive costs a visible row, not a woken human. Flip OFF from the admin Feature Flags page to disarm stage-wide; the window itself is tuned with the AUGMENTED_PROMISE_OUTSTANDING_THRESHOLD_SECONDS API tunable (default 1800).',
34528
+ flagType: "boolean",
34529
+ defaultValue: true
34530
+ },
34525
34531
  {
34526
34532
  key: "connectivity-probe",
34527
34533
  description: "Host-side rolling integration connectivity probe (ENG-5641): when ON, the manager probes each integration ~hourly using the agent's real creds/MCP and reports to /host/integration-connectivity, which populates last_connectivity_* and feeds the central escalation evaluator (integration-connectivity-escalation) and reconnect notifications. It is the only continuous writer of last_connectivity_status (the monitor cron only reads it). Migrated from the raw AGT_CONNECTIVITY_PROBE_ENABLED env gate to this registry flag (ENG-7220) so both halves of the connectivity subsystem are flag-managed; the env var is retained as the highest-precedence operator override (env override > flag value > this default). Boolean gate; ships dark.",
@@ -40412,6 +40412,12 @@ var FLAG_REGISTRY = [
40412
40412
  // operational decision with blast radius, so mutations require confirmation.
40413
40413
  sensitive: true
40414
40414
  },
40415
+ {
40416
+ key: "promise-outstanding-alarm",
40417
+ description: 'Outstanding-interim-promise alarm (ENG-8265): when ON, the responsiveness-probe route creates a per-agent CloudWatch alarm on `PromiseOutstandingOldestAgeSeconds` \u2014 an inbound the agent acknowledged with an interim reply ("on it") and never answered substantively. Closes the blind spot where an ack satisfied channel-silent-loss, refreshed pending-inbound, and left agent_stall with no in_progress card to see, so a broken promise looked like a served request. Defaults ON (armed on deploy) because the alert it opens is `info` severity \u2014 dashboard-only, never paged \u2014 so a day-one false positive costs a visible row, not a woken human. Flip OFF from the admin Feature Flags page to disarm stage-wide; the window itself is tuned with the AUGMENTED_PROMISE_OUTSTANDING_THRESHOLD_SECONDS API tunable (default 1800).',
40418
+ flagType: "boolean",
40419
+ defaultValue: true
40420
+ },
40415
40421
  {
40416
40422
  key: "connectivity-probe",
40417
40423
  description: "Host-side rolling integration connectivity probe (ENG-5641): when ON, the manager probes each integration ~hourly using the agent's real creds/MCP and reports to /host/integration-connectivity, which populates last_connectivity_* and feeds the central escalation evaluator (integration-connectivity-escalation) and reconnect notifications. It is the only continuous writer of last_connectivity_status (the monitor cron only reads it). Migrated from the raw AGT_CONNECTIVITY_PROBE_ENABLED env gate to this registry flag (ENG-7220) so both halves of the connectivity subsystem are flag-managed; the env var is retained as the highest-precedence operator override (env override > flag value > this default). Boolean gate; ships dark.",
@@ -34752,6 +34752,12 @@ var FLAG_REGISTRY = [
34752
34752
  // operational decision with blast radius, so mutations require confirmation.
34753
34753
  sensitive: true
34754
34754
  },
34755
+ {
34756
+ key: "promise-outstanding-alarm",
34757
+ description: 'Outstanding-interim-promise alarm (ENG-8265): when ON, the responsiveness-probe route creates a per-agent CloudWatch alarm on `PromiseOutstandingOldestAgeSeconds` \u2014 an inbound the agent acknowledged with an interim reply ("on it") and never answered substantively. Closes the blind spot where an ack satisfied channel-silent-loss, refreshed pending-inbound, and left agent_stall with no in_progress card to see, so a broken promise looked like a served request. Defaults ON (armed on deploy) because the alert it opens is `info` severity \u2014 dashboard-only, never paged \u2014 so a day-one false positive costs a visible row, not a woken human. Flip OFF from the admin Feature Flags page to disarm stage-wide; the window itself is tuned with the AUGMENTED_PROMISE_OUTSTANDING_THRESHOLD_SECONDS API tunable (default 1800).',
34758
+ flagType: "boolean",
34759
+ defaultValue: true
34760
+ },
34755
34761
  {
34756
34762
  key: "connectivity-probe",
34757
34763
  description: "Host-side rolling integration connectivity probe (ENG-5641): when ON, the manager probes each integration ~hourly using the agent's real creds/MCP and reports to /host/integration-connectivity, which populates last_connectivity_* and feeds the central escalation evaluator (integration-connectivity-escalation) and reconnect notifications. It is the only continuous writer of last_connectivity_status (the monitor cron only reads it). Migrated from the raw AGT_CONNECTIVITY_PROBE_ENABLED env gate to this registry flag (ENG-7220) so both halves of the connectivity subsystem are flag-managed; the env var is retained as the highest-precedence operator override (env override > flag value > this default). Boolean gate; ships dark.",
@@ -37350,6 +37356,30 @@ function clearOldestSlackPendingMarkerInChannel(dir, channel, clear = defaultCle
37350
37356
  }
37351
37357
  }
37352
37358
 
37359
+ // ../core/dist/channels/interim-promise.js
37360
+ function decideMarkerEngagement(marker, kind, nowIso) {
37361
+ const alreadySeen = typeof marker?.seen_at === "string" && marker.seen_at !== "";
37362
+ const alreadyPromised = typeof marker?.promised_at === "string" && marker.promised_at !== "";
37363
+ if (kind === "seen") {
37364
+ return alreadySeen ? { stamp: null, promised: alreadyPromised } : { stamp: { seen_at: nowIso }, promised: alreadyPromised };
37365
+ }
37366
+ if (alreadyPromised)
37367
+ return { stamp: null, promised: true };
37368
+ return {
37369
+ stamp: alreadySeen ? { promised_at: nowIso } : { seen_at: nowIso, promised_at: nowIso },
37370
+ promised: true
37371
+ };
37372
+ }
37373
+ function describePromiseStampOutcome(tally, replyToolName) {
37374
+ if (tally.attempted > tally.stamped) {
37375
+ return "WARNING: this was recorded as an interim ack but the outstanding-promise marker could NOT be written, so nothing is tracking that you still owe a final reply. Do not rely on a reminder \u2014 post your substantive answer in this same turn.";
37376
+ }
37377
+ if (tally.stamped > 0) {
37378
+ return `Recorded as an interim ack \u2014 your final answer is still owed and is being tracked until you send it as a separate ${replyToolName} with interim omitted.`;
37379
+ }
37380
+ return null;
37381
+ }
37382
+
37353
37383
  // src/recovery-ledger.ts
37354
37384
  import { existsSync as existsSync5, unlinkSync as unlinkSync2 } from "fs";
37355
37385
  import { join as join11 } from "path";
@@ -40301,16 +40331,34 @@ function rewriteSlackMarkerInPlace(path, marker) {
40301
40331
  }
40302
40332
  }
40303
40333
  function markSlackMarkerSeenInPlace(fullPath) {
40334
+ markSlackMarkerEngagedInPlace(fullPath, { promise: false });
40335
+ }
40336
+ function markSlackMarkerPromisedInPlace(fullPath) {
40337
+ return markSlackMarkerEngagedInPlace(fullPath, { promise: true });
40338
+ }
40339
+ function markSlackMarkerEngagedInPlace(fullPath, opts) {
40304
40340
  let marker;
40305
40341
  try {
40306
40342
  marker = JSON.parse(readFileSync21(fullPath, "utf-8"));
40307
40343
  } catch {
40308
- return;
40344
+ return false;
40309
40345
  }
40310
- if (marker.seen_at) return;
40311
- marker.seen_at = (/* @__PURE__ */ new Date()).toISOString();
40346
+ const decision = decideMarkerEngagement(
40347
+ marker,
40348
+ opts.promise ? "interim_ack" : "seen",
40349
+ (/* @__PURE__ */ new Date()).toISOString()
40350
+ );
40351
+ if (!decision.stamp) return opts.promise ? decision.promised : false;
40352
+ Object.assign(marker, decision.stamp);
40312
40353
  if (marker.undeliverable) delete marker.undeliverable;
40313
40354
  rewriteSlackMarkerInPlace(fullPath, marker);
40355
+ if (!opts.promise) return false;
40356
+ try {
40357
+ const readBack = JSON.parse(readFileSync21(fullPath, "utf-8"));
40358
+ return typeof readBack.promised_at === "string" && readBack.promised_at.length > 0;
40359
+ } catch {
40360
+ return false;
40361
+ }
40314
40362
  }
40315
40363
  function attachSlackReplayPayload(channel, threadTs, messageTs, payload) {
40316
40364
  const path = slackPendingInboundPath(channel, threadTs, messageTs);
@@ -40493,11 +40541,20 @@ function clearSlackMarkerFileWithHeal(fullPath) {
40493
40541
  }
40494
40542
  }
40495
40543
  function markSlackMarkerSeenWithHeal(fullPath) {
40544
+ healThenEngageSlackMarker(fullPath, { promise: false });
40545
+ }
40546
+ function markSlackMarkerPromisedWithHeal(fullPath) {
40547
+ const stamped = healThenEngageSlackMarker(fullPath, { promise: true });
40548
+ slackPromiseStampOutcome.attempted += 1;
40549
+ if (stamped) slackPromiseStampOutcome.stamped += 1;
40550
+ }
40551
+ var slackPromiseStampOutcome = { attempted: 0, stamped: 0 };
40552
+ function healThenEngageSlackMarker(fullPath, opts) {
40496
40553
  let marker = null;
40497
40554
  try {
40498
40555
  marker = JSON.parse(readFileSync21(fullPath, "utf-8"));
40499
40556
  } catch {
40500
- return;
40557
+ return false;
40501
40558
  }
40502
40559
  if (decideRecoveryHeal({
40503
40560
  wasUndeliverable: marker.undeliverable === true,
@@ -40506,7 +40563,7 @@ function markSlackMarkerSeenWithHeal(fullPath) {
40506
40563
  healSlackUndeliverable(marker.channel, marker.message_ts);
40507
40564
  deleteSlackUndeliverableNotice(undeliverableNoticeConversationKeyFromMarker(marker));
40508
40565
  }
40509
- markSlackMarkerSeenInPlace(fullPath);
40566
+ return opts.promise ? markSlackMarkerPromisedInPlace(fullPath) : (markSlackMarkerSeenInPlace(fullPath), false);
40510
40567
  }
40511
40568
  function clearAllSlackPendingMarkersForThread2(channel, threadTs) {
40512
40569
  clearAllSlackPendingMarkersForThread(
@@ -40550,6 +40607,22 @@ function markSeenSlackPendingMarkerByMessageTs2(channel, messageTs) {
40550
40607
  markSlackMarkerSeenWithHeal
40551
40608
  );
40552
40609
  }
40610
+ function markPromisedAllSlackPendingMarkersForThread(channel, threadTs) {
40611
+ markSeenAllSlackPendingMarkersForThread(
40612
+ SLACK_PENDING_INBOUND_DIR,
40613
+ channel,
40614
+ threadTs,
40615
+ markSlackMarkerPromisedWithHeal
40616
+ );
40617
+ }
40618
+ function markPromisedSlackPendingMarkerByMessageTs(channel, messageTs) {
40619
+ markSeenSlackPendingMarkerByMessageTs(
40620
+ SLACK_PENDING_INBOUND_DIR,
40621
+ channel,
40622
+ messageTs,
40623
+ markSlackMarkerPromisedWithHeal
40624
+ );
40625
+ }
40553
40626
  function slackNextRetryName(filename) {
40554
40627
  const match = filename.match(/^(.*?)(?:\.retry-(\d+))?\.json$/);
40555
40628
  if (!match) return null;
@@ -43073,17 +43146,19 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
43073
43146
  const settleChannel = effectiveChannel;
43074
43147
  const settleMessageTs = effectiveMessageTs;
43075
43148
  const settlePendingMarker = () => {
43149
+ slackPromiseStampOutcome.attempted = 0;
43150
+ slackPromiseStampOutcome.stamped = 0;
43076
43151
  if (!settleChannel) return;
43077
43152
  if (settleMessageTs) {
43078
43153
  if (interim) {
43079
- markSeenSlackPendingMarkerByMessageTs2(settleChannel, settleMessageTs);
43080
- if (settleThreadTs) markSeenAllSlackPendingMarkersForThread2(settleChannel, settleThreadTs);
43154
+ markPromisedSlackPendingMarkerByMessageTs(settleChannel, settleMessageTs);
43155
+ if (settleThreadTs) markPromisedAllSlackPendingMarkersForThread(settleChannel, settleThreadTs);
43081
43156
  } else {
43082
43157
  clearSlackPendingMarkerByMessageTs2(settleChannel, settleMessageTs);
43083
43158
  if (settleThreadTs) clearPendingMessage(settleChannel, settleThreadTs);
43084
43159
  }
43085
43160
  } else if (settleThreadTs) {
43086
- if (interim) markSeenAllSlackPendingMarkersForThread2(settleChannel, settleThreadTs);
43161
+ if (interim) markPromisedAllSlackPendingMarkersForThread(settleChannel, settleThreadTs);
43087
43162
  else clearPendingMessage(settleChannel, settleThreadTs);
43088
43163
  } else if (!interim) {
43089
43164
  clearOldestSlackPendingMarkerInChannel2(settleChannel);
@@ -43169,6 +43244,16 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
43169
43244
  reason: scheduledDest?.retargeted ? "scheduled-task" : channelGuard.corrected ? "dm-channel-guard" : null
43170
43245
  });
43171
43246
  if (redirectNote) base += `. ${redirectNote}`;
43247
+ if (interim) {
43248
+ const promiseNote = describePromiseStampOutcome(slackPromiseStampOutcome, "slack.reply");
43249
+ if (promiseNote) base += `. ${promiseNote}`;
43250
+ if (slackPromiseStampOutcome.attempted > slackPromiseStampOutcome.stamped) {
43251
+ process.stderr.write(
43252
+ `slack-channel(${AGENT_CODE_NAME}): promise_stamp_failed channel=${redactSlackId(effectiveChannel)} attempted=${slackPromiseStampOutcome.attempted} stamped=${slackPromiseStampOutcome.stamped}
43253
+ `
43254
+ );
43255
+ }
43256
+ }
43172
43257
  const sentTs = typeof data.ts === "string" ? data.ts : void 0;
43173
43258
  await maybeSendSlackAccountWarn({ channel: effectiveChannel, threadTs: effectiveThreadTs });
43174
43259
  return {
@@ -30145,6 +30145,30 @@ import {
30145
30145
  import { homedir as homedir7 } from "os";
30146
30146
  import { basename, extname, join as join17, resolve as resolve2 } from "path";
30147
30147
 
30148
+ // ../core/dist/channels/interim-promise.js
30149
+ function decideMarkerEngagement(marker, kind, nowIso) {
30150
+ const alreadySeen = typeof marker?.seen_at === "string" && marker.seen_at !== "";
30151
+ const alreadyPromised = typeof marker?.promised_at === "string" && marker.promised_at !== "";
30152
+ if (kind === "seen") {
30153
+ return alreadySeen ? { stamp: null, promised: alreadyPromised } : { stamp: { seen_at: nowIso }, promised: alreadyPromised };
30154
+ }
30155
+ if (alreadyPromised)
30156
+ return { stamp: null, promised: true };
30157
+ return {
30158
+ stamp: alreadySeen ? { promised_at: nowIso } : { seen_at: nowIso, promised_at: nowIso },
30159
+ promised: true
30160
+ };
30161
+ }
30162
+ function describePromiseStampOutcome(tally, replyToolName) {
30163
+ if (tally.attempted > tally.stamped) {
30164
+ return "WARNING: this was recorded as an interim ack but the outstanding-promise marker could NOT be written, so nothing is tracking that you still owe a final reply. Do not rely on a reminder \u2014 post your substantive answer in this same turn.";
30165
+ }
30166
+ if (tally.stamped > 0) {
30167
+ return `Recorded as an interim ack \u2014 your final answer is still owed and is being tracked until you send it as a separate ${replyToolName} with interim omitted.`;
30168
+ }
30169
+ return null;
30170
+ }
30171
+
30148
30172
  // src/channel-attachments.ts
30149
30173
  import { homedir } from "os";
30150
30174
  import { join, resolve, sep } from "path";
@@ -35054,6 +35078,12 @@ var FLAG_REGISTRY = [
35054
35078
  // operational decision with blast radius, so mutations require confirmation.
35055
35079
  sensitive: true
35056
35080
  },
35081
+ {
35082
+ key: "promise-outstanding-alarm",
35083
+ description: 'Outstanding-interim-promise alarm (ENG-8265): when ON, the responsiveness-probe route creates a per-agent CloudWatch alarm on `PromiseOutstandingOldestAgeSeconds` \u2014 an inbound the agent acknowledged with an interim reply ("on it") and never answered substantively. Closes the blind spot where an ack satisfied channel-silent-loss, refreshed pending-inbound, and left agent_stall with no in_progress card to see, so a broken promise looked like a served request. Defaults ON (armed on deploy) because the alert it opens is `info` severity \u2014 dashboard-only, never paged \u2014 so a day-one false positive costs a visible row, not a woken human. Flip OFF from the admin Feature Flags page to disarm stage-wide; the window itself is tuned with the AUGMENTED_PROMISE_OUTSTANDING_THRESHOLD_SECONDS API tunable (default 1800).',
35084
+ flagType: "boolean",
35085
+ defaultValue: true
35086
+ },
35057
35087
  {
35058
35088
  key: "connectivity-probe",
35059
35089
  description: "Host-side rolling integration connectivity probe (ENG-5641): when ON, the manager probes each integration ~hourly using the agent's real creds/MCP and reports to /host/integration-connectivity, which populates last_connectivity_* and feeds the central escalation evaluator (integration-connectivity-escalation) and reconnect notifications. It is the only continuous writer of last_connectivity_status (the monitor cron only reads it). Migrated from the raw AGT_CONNECTIVITY_PROBE_ENABLED env gate to this registry flag (ENG-7220) so both halves of the connectivity subsystem are flag-managed; the env var is retained as the highest-precedence operator override (env override > flag value > this default). Boolean gate; ships dark.",
@@ -40278,16 +40308,34 @@ function clearTelegramMarkerFileWithHeal(fullPath) {
40278
40308
  }
40279
40309
  }
40280
40310
  function markTelegramMarkerSeenInPlace(fullPath) {
40311
+ markTelegramMarkerEngagedInPlace(fullPath, { promise: false });
40312
+ }
40313
+ function markTelegramMarkerPromisedInPlace(fullPath) {
40314
+ return markTelegramMarkerEngagedInPlace(fullPath, { promise: true });
40315
+ }
40316
+ function markTelegramMarkerEngagedInPlace(fullPath, opts) {
40281
40317
  let marker;
40282
40318
  try {
40283
40319
  marker = JSON.parse(readFileSync17(fullPath, "utf-8"));
40284
40320
  } catch {
40285
- return;
40321
+ return false;
40286
40322
  }
40287
- if (marker.seen_at) return;
40288
- marker.seen_at = (/* @__PURE__ */ new Date()).toISOString();
40323
+ const decision = decideMarkerEngagement(
40324
+ marker,
40325
+ opts.promise ? "interim_ack" : "seen",
40326
+ (/* @__PURE__ */ new Date()).toISOString()
40327
+ );
40328
+ if (!decision.stamp) return opts.promise ? decision.promised : false;
40329
+ Object.assign(marker, decision.stamp);
40289
40330
  if (marker.undeliverable) delete marker.undeliverable;
40290
40331
  rewriteTelegramMarkerInPlace(fullPath, marker);
40332
+ if (!opts.promise) return false;
40333
+ try {
40334
+ const readBack = JSON.parse(readFileSync17(fullPath, "utf-8"));
40335
+ return typeof readBack.promised_at === "string" && readBack.promised_at.length > 0;
40336
+ } catch {
40337
+ return false;
40338
+ }
40291
40339
  }
40292
40340
  function markTelegramMarkerSeenWithHeal(fullPath) {
40293
40341
  let marker = null;
@@ -40304,6 +40352,23 @@ function markTelegramMarkerSeenWithHeal(fullPath) {
40304
40352
  }
40305
40353
  markTelegramMarkerSeenInPlace(fullPath);
40306
40354
  }
40355
+ function markTelegramMarkerPromisedWithHeal(fullPath) {
40356
+ let marker = null;
40357
+ try {
40358
+ marker = JSON.parse(readFileSync17(fullPath, "utf-8"));
40359
+ } catch {
40360
+ return;
40361
+ }
40362
+ if (decideRecoveryHeal({
40363
+ wasUndeliverable: marker.undeliverable === true,
40364
+ hasTarget: Boolean(marker.chat_id)
40365
+ }) === "heal") {
40366
+ notifyBackOnline(marker.chat_id);
40367
+ }
40368
+ telegramPromiseStampOutcome.attempted += 1;
40369
+ if (markTelegramMarkerPromisedInPlace(fullPath)) telegramPromiseStampOutcome.stamped += 1;
40370
+ }
40371
+ var telegramPromiseStampOutcome = { attempted: 0, stamped: 0 };
40307
40372
  function readPendingInboundMarker(chatId, messageId) {
40308
40373
  const path = pendingInboundPath(chatId, messageId);
40309
40374
  if (!path || !existsSync9(path)) return null;
@@ -41066,6 +41131,23 @@ function markSeenPendingMessage(chatId, cutoffMs = Number.POSITIVE_INFINITY) {
41066
41131
  cutoffMs
41067
41132
  );
41068
41133
  }
41134
+ function markPromisedPendingMessage(chatId, cutoffMs = Number.POSITIVE_INFINITY) {
41135
+ telegramPromiseStampOutcome.attempted = 0;
41136
+ telegramPromiseStampOutcome.stamped = 0;
41137
+ if (!PENDING_INBOUND_DIR || !existsSync9(PENDING_INBOUND_DIR)) return;
41138
+ markSeenAllTelegramPendingMarkersForChat(
41139
+ PENDING_INBOUND_DIR,
41140
+ chatId,
41141
+ markTelegramMarkerPromisedWithHeal,
41142
+ cutoffMs
41143
+ );
41144
+ if (telegramPromiseStampOutcome.attempted > telegramPromiseStampOutcome.stamped) {
41145
+ process.stderr.write(
41146
+ `telegram-channel(${AGENT_CODE_NAME}): promise_stamp_failed chat=${redactId(chatId)} attempted=${telegramPromiseStampOutcome.attempted} stamped=${telegramPromiseStampOutcome.stamped}
41147
+ `
41148
+ );
41149
+ }
41150
+ }
41069
41151
  function noteThreadActivity(chatId, cutoffMs = Number.POSITIVE_INFINITY) {
41070
41152
  if (!chatId) return;
41071
41153
  markSeenPendingMessage(chatId, cutoffMs);
@@ -41481,9 +41563,14 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
41481
41563
  };
41482
41564
  }
41483
41565
  recordReply(chat_id, "", tgThrottleNow, tgThrottleCfg);
41566
+ let promiseNote = null;
41484
41567
  if (name === "telegram.reply") {
41485
- if (interim) markSeenPendingMessage(chat_id, drainCutoffMs);
41486
- else clearPendingMessage(chat_id, drainCutoffMs);
41568
+ if (interim) {
41569
+ markPromisedPendingMessage(chat_id, drainCutoffMs);
41570
+ promiseNote = describePromiseStampOutcome(telegramPromiseStampOutcome, "telegram.reply");
41571
+ } else {
41572
+ clearPendingMessage(chat_id, drainCutoffMs);
41573
+ }
41487
41574
  writeInboundDeliveryLedgerEntry(DELIVERY_LEDGER_DIR, {
41488
41575
  inbound_id: telegramInboundId(chat_id, reply_to_message_id ? String(reply_to_message_id) : ""),
41489
41576
  source: "telegram",
@@ -41492,7 +41579,9 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
41492
41579
  });
41493
41580
  }
41494
41581
  await maybeSendTelegramAccountWarn({ chatId: chat_id });
41495
- return { content: [{ type: "text", text: "sent" }] };
41582
+ return {
41583
+ content: [{ type: "text", text: promiseNote ? `sent. ${promiseNote}` : "sent" }]
41584
+ };
41496
41585
  } catch (err) {
41497
41586
  return {
41498
41587
  content: [{ type: "text", text: `Failed: ${err.message}` }],
@@ -36,7 +36,7 @@ import {
36
36
  writeDirectChatSessionState,
37
37
  writeEgressAllowlist,
38
38
  writePersistentClaudeWrapper
39
- } from "./chunk-BWH5XTDU.js";
39
+ } from "./chunk-QZUECTC7.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-KGRCIIS5.js.map
80
+ //# sourceMappingURL=persistent-session-HRVZVAIL.js.map