@integrity-labs/agt-cli 0.28.829 → 0.28.831

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. package/dist/bin/agt.js +5 -5
  2. package/dist/{chunk-GJY3KZG6.js → chunk-4ZPOP7EW.js} +36 -11
  3. package/dist/{chunk-GJY3KZG6.js.map → chunk-4ZPOP7EW.js.map} +1 -1
  4. package/dist/{chunk-6HTCP6D5.js → chunk-N4QVPPYS.js} +2 -2
  5. package/dist/{chunk-E75YCJTE.js → chunk-PODKITVQ.js} +4 -4
  6. package/dist/{claude-pair-runtime-UTDZXJKO.js → claude-pair-runtime-PUWAIK73.js} +2 -2
  7. package/dist/lib/manager-worker.js +13 -13
  8. package/dist/mcp/augmented-admin.js +1 -1
  9. package/dist/mcp/direct-chat-channel.js +88 -13
  10. package/dist/mcp/index.js +35 -10
  11. package/dist/mcp/origami.js +35 -10
  12. package/dist/mcp/slack-channel.js +115 -13
  13. package/dist/mcp/telegram-channel.js +107 -13
  14. package/dist/{persistent-session-6YTEDS3H.js → persistent-session-W23U7GQU.js} +3 -3
  15. package/dist/{responsiveness-probe-5B2WA5G3.js → responsiveness-probe-IRQKIEBW.js} +3 -3
  16. package/dist/{session-auth-dead-LFNU6AUU.js → session-auth-dead-VDDXVJTX.js} +2 -2
  17. package/package.json +1 -1
  18. /package/dist/{chunk-6HTCP6D5.js.map → chunk-N4QVPPYS.js.map} +0 -0
  19. /package/dist/{chunk-E75YCJTE.js.map → chunk-PODKITVQ.js.map} +0 -0
  20. /package/dist/{claude-pair-runtime-UTDZXJKO.js.map → claude-pair-runtime-PUWAIK73.js.map} +0 -0
  21. /package/dist/{persistent-session-6YTEDS3H.js.map → persistent-session-W23U7GQU.js.map} +0 -0
  22. /package/dist/{responsiveness-probe-5B2WA5G3.js.map → responsiveness-probe-IRQKIEBW.js.map} +0 -0
  23. /package/dist/{session-auth-dead-LFNU6AUU.js.map → session-auth-dead-VDDXVJTX.js.map} +0 -0
@@ -18,7 +18,7 @@ import {
18
18
  rotateDailySession,
19
19
  sessionFileExists,
20
20
  todayLocalIso
21
- } from "./chunk-GJY3KZG6.js";
21
+ } from "./chunk-4ZPOP7EW.js";
22
22
  import {
23
23
  reapOrphanChannelMcps
24
24
  } from "./chunk-XWVM4KPK.js";
@@ -5326,4 +5326,4 @@ export {
5326
5326
  stopAllSessionsAndWait,
5327
5327
  getProjectDir
5328
5328
  };
5329
- //# sourceMappingURL=chunk-6HTCP6D5.js.map
5329
+ //# sourceMappingURL=chunk-N4QVPPYS.js.map
@@ -16,7 +16,7 @@ import {
16
16
  parseEnvIntegrations,
17
17
  shellQuote,
18
18
  summarizeUnanswerablePane
19
- } from "./chunk-6HTCP6D5.js";
19
+ } from "./chunk-N4QVPPYS.js";
20
20
  import {
21
21
  BIND_FAILURE_QUARANTINE_THRESHOLD,
22
22
  INTEGRATIONS_SECTION_END,
@@ -74,7 +74,7 @@ import {
74
74
  sessionTranscriptDir,
75
75
  worseConnectivityOutcome,
76
76
  wrapScheduledTaskPrompt
77
- } from "./chunk-GJY3KZG6.js";
77
+ } from "./chunk-4ZPOP7EW.js";
78
78
  import {
79
79
  parsePsRows
80
80
  } from "./chunk-XWVM4KPK.js";
@@ -6535,7 +6535,7 @@ function exchangeFailureKind(err) {
6535
6535
  }
6536
6536
 
6537
6537
  // src/lib/api-client.ts
6538
- var agtCliVersion = true ? "0.28.829" : "dev";
6538
+ var agtCliVersion = true ? "0.28.831" : "dev";
6539
6539
  var lastConfigHash = null;
6540
6540
  function setConfigHash(hash) {
6541
6541
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -10843,4 +10843,4 @@ export {
10843
10843
  managerInstallSystemUnitCommand,
10844
10844
  managerUninstallSystemUnitCommand
10845
10845
  };
10846
- //# sourceMappingURL=chunk-E75YCJTE.js.map
10846
+ //# sourceMappingURL=chunk-PODKITVQ.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-6YTEDS3H.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-W23U7GQU.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-UTDZXJKO.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-PUWAIK73.js.map
@@ -60,7 +60,7 @@ import {
60
60
  safeWriteJsonAtomic,
61
61
  setConfigHash,
62
62
  tripClass
63
- } from "../chunk-E75YCJTE.js";
63
+ } from "../chunk-PODKITVQ.js";
64
64
  import {
65
65
  getProjectDir as getProjectDir2,
66
66
  getReadyTasks,
@@ -126,7 +126,7 @@ import {
126
126
  takeZombieDetection,
127
127
  toOpencodeModel,
128
128
  writeEgressAllowlist
129
- } from "../chunk-6HTCP6D5.js";
129
+ } from "../chunk-N4QVPPYS.js";
130
130
  import {
131
131
  ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
132
132
  AnchorSessionClient,
@@ -221,7 +221,7 @@ import {
221
221
  subagentActivityAgeSeconds,
222
222
  sumTranscriptUsageInWindow,
223
223
  transcriptActivityAgeSeconds
224
- } from "../chunk-GJY3KZG6.js";
224
+ } from "../chunk-4ZPOP7EW.js";
225
225
  import {
226
226
  reapOrphanChannelMcps
227
227
  } from "../chunk-XWVM4KPK.js";
@@ -12928,7 +12928,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
12928
12928
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
12929
12929
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
12930
12930
  async function channelInboundActivityAgeSecondsFor(codeName) {
12931
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-5B2WA5G3.js");
12931
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-IRQKIEBW.js");
12932
12932
  const newest = newestPendingInboundActivityMtimeMs(dirname10(paneLogPath(codeName)));
12933
12933
  if (newest === null) return null;
12934
12934
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -13596,7 +13596,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
13596
13596
  var lastVersionCheckAt = 0;
13597
13597
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
13598
13598
  var lastResponsivenessProbeAt = 0;
13599
- var agtCliVersion = true ? "0.28.829" : "dev";
13599
+ var agtCliVersion = true ? "0.28.831" : "dev";
13600
13600
  function resolveBrewPath(execFileSync2) {
13601
13601
  try {
13602
13602
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -15186,7 +15186,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
15186
15186
  if (codeNames.length === 0) return;
15187
15187
  void (async () => {
15188
15188
  try {
15189
- const { collectDiagnostics } = await import("../persistent-session-6YTEDS3H.js");
15189
+ const { collectDiagnostics } = await import("../persistent-session-W23U7GQU.js");
15190
15190
  await api.post("/host/heartbeat", {
15191
15191
  host_id: hostId,
15192
15192
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -15328,7 +15328,7 @@ async function pollCycleInner() {
15328
15328
  }
15329
15329
  try {
15330
15330
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
15331
- const { collectDiagnostics } = await import("../persistent-session-6YTEDS3H.js");
15331
+ const { collectDiagnostics } = await import("../persistent-session-W23U7GQU.js");
15332
15332
  const diagCodeNames = [...agentState.persistentSessionAgents];
15333
15333
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor) : void 0;
15334
15334
  let tailscaleHostname;
@@ -15497,7 +15497,7 @@ async function pollCycleInner() {
15497
15497
  collectPanelessActivityProbes,
15498
15498
  getResponsivenessIntervalMs,
15499
15499
  occupancyQualificationClassifications
15500
- } = await import("../responsiveness-probe-5B2WA5G3.js");
15500
+ } = await import("../responsiveness-probe-IRQKIEBW.js");
15501
15501
  const probeIntervalMs = getResponsivenessIntervalMs();
15502
15502
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
15503
15503
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -15614,7 +15614,7 @@ async function pollCycleInner() {
15614
15614
  collectResponsivenessProbes,
15615
15615
  livePendingInboundOldestAgeSeconds,
15616
15616
  parkPendingInbound
15617
- } = await import("../responsiveness-probe-5B2WA5G3.js");
15617
+ } = await import("../responsiveness-probe-IRQKIEBW.js");
15618
15618
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
15619
15619
  const wedgeNow = /* @__PURE__ */ new Date();
15620
15620
  const liveAgents = agentState.persistentSessionAgents;
@@ -15770,7 +15770,7 @@ async function pollCycleInner() {
15770
15770
  }
15771
15771
  try {
15772
15772
  const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-JA437JIB.js");
15773
- const { probeSessionAuth } = await import("../session-auth-dead-LFNU6AUU.js");
15773
+ const { probeSessionAuth } = await import("../session-auth-dead-VDDXVJTX.js");
15774
15774
  const observations = [];
15775
15775
  const pendingCacheCommits = [];
15776
15776
  const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
@@ -20003,7 +20003,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
20003
20003
  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}`));
20004
20004
  void (async () => {
20005
20005
  try {
20006
- const { collectDiagnostics } = await import("../persistent-session-6YTEDS3H.js");
20006
+ const { collectDiagnostics } = await import("../persistent-session-W23U7GQU.js");
20007
20007
  await api.post("/host/heartbeat", {
20008
20008
  host_id: hostId,
20009
20009
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -20049,7 +20049,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
20049
20049
  }
20050
20050
  try {
20051
20051
  const hostId = await getHostId();
20052
- const { collectDiagnostics } = await import("../persistent-session-6YTEDS3H.js");
20052
+ const { collectDiagnostics } = await import("../persistent-session-W23U7GQU.js");
20053
20053
  await api.post("/host/heartbeat", {
20054
20054
  host_id: hostId,
20055
20055
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -20685,7 +20685,7 @@ async function processClaudePairSessions(agents) {
20685
20685
  killPairSession,
20686
20686
  pairTmuxSession,
20687
20687
  finalizeClaudePairOnboarding
20688
- } = await import("../claude-pair-runtime-UTDZXJKO.js");
20688
+ } = await import("../claude-pair-runtime-PUWAIK73.js");
20689
20689
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
20690
20690
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
20691
20691
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -21812,7 +21812,7 @@ server.registerTool(
21812
21812
  );
21813
21813
  server.registerTool(
21814
21814
  "debug_inspect_dead_letters",
21815
- { description: "List an agent's DEAD-LETTERED / quarantined inbound \u2014 customer messages that were parked on the host instead of delivered (so the agent never saw them), rather than silently lost. Use when a user says \"the agent never replied\" but nothing shows in the normal flow, or to audit what fell into the dead-letter path. Resolves the agent's current host and reads two on-disk stores over SSM: `stale` (markers moved aside on a wedge-respawn because the agent couldn't receive) and `cleared:<stamp>` (markers the clear_pending_inbound remedial action moved aside). Returns { agent_id, code_name, host, markers[], total, ssm_status } where each marker is { index, store, channel (slack|telegram), marker_name, received_at, undeliverable, discretionary, replay_count, conversation, message_ref } \u2014 routing metadata only, NEVER the message body. To re-inject one, pass its exact { channel, store, marker_name } to debug_replay_dead_letter. Fails closed for an unauthorized org; every call is audited as a cross-org host access. Pass { agent_id }.", inputSchema: inspectDeadLettersSchema },
21815
+ { description: 'List an agent\'s DEAD-LETTERED / quarantined inbound \u2014 customer messages that were parked on the host instead of delivered (so the agent never saw them), rather than silently lost. Use when a user says "the agent never replied" but nothing shows in the normal flow, or to audit what fell into the dead-letter path. Resolves the agent\'s current host and reads two on-disk stores over SSM: `stale` (markers moved aside on a wedge-respawn because the agent couldn\'t receive) and `cleared:<stamp>` (markers the clear_pending_inbound remedial action moved aside). Returns { agent_id, code_name, host, markers[], total, ssm_status } where each marker is { index, store, channel (slack|telegram), marker_name, received_at, undeliverable, discretionary, replay_count, has_payload, conversation, message_ref } \u2014 routing metadata only, NEVER the message body. `has_payload` is a TRI-STATE (true | false | null) saying whether a replay payload exists, never the payload itself - `null` means this host did not report it (an agt-cli predating the field, or an unparseable marker) and must NOT be read as \\"no payload\\": it is what separates a marker that was eligible for replay and never re-pushed from one that was structurally unreplayable, and those need opposite fixes. `replay_count` is replays already PUSHED \u2014 0 means none was ever attempted (the marker write omits the field; the replay path increments it), so 0 is a fact rather than missing data and says nothing about the payload. To re-inject one, pass its exact { channel, store, marker_name } to debug_replay_dead_letter. Fails closed for an unauthorized org; every call is audited as a cross-org host access. Pass { agent_id }.', inputSchema: inspectDeadLettersSchema },
21816
21816
  async (args) => {
21817
21817
  try {
21818
21818
  const result = await client.inspectDeadLetters(args);
@@ -30289,10 +30289,19 @@ var UNDELIVERABLE_NOTICE_THROTTLE_MS = 5 * 60 * 1e3;
30289
30289
  function shouldPostUndeliverableNotice(lastNoticeAtMs, nowMs, throttleMs = UNDELIVERABLE_NOTICE_THROTTLE_MS) {
30290
30290
  return lastNoticeAtMs == null || nowMs - lastNoticeAtMs >= throttleMs;
30291
30291
  }
30292
- function undeliverableNoticeText(replay = channelReplayEnabled()) {
30293
- return noticePromiseIsHonest(replay) ? "\u23F3 I can't get to this right now \u2014 no need to resend; I'll pick it up automatically as soon as I'm free." : "\u23F3 I can't get to this right now. Please resend in a few minutes \u2014 I may not see this one.";
30292
+ function undeliverableNoticeText(replay) {
30293
+ const honest = noticePromiseIsHonest(replay);
30294
+ return honest ? "\u23F3 I can't get to this right now \u2014 no need to resend; I'll pick it up automatically as soon as I'm free." : "\u23F3 I can't get to this right now. Please resend in a few minutes \u2014 I may not see this one.";
30295
+ }
30296
+ function undeliverableNoticeTextForRepeat(i) {
30297
+ if (i.priorNotices <= 0) return undeliverableNoticeText(i.replay);
30298
+ if (i.priorNotices === 1) {
30299
+ return noticePromiseIsHonest(i.replay) ? "\u23F3 Still stuck on this one \u2014 the automatic pickup I mentioned has not happened. Please resend when you can." : "\u23F3 Still stuck on this one, and I still have not picked it up. Resending is the reliable way through.";
30300
+ }
30301
+ return null;
30294
30302
  }
30295
30303
  function noticePromiseIsHonest(replay) {
30304
+ if (replay === void 0) return false;
30296
30305
  if (typeof replay === "boolean") return replay;
30297
30306
  return markerReplayable({
30298
30307
  enabled: replay.enabled ?? channelReplayEnabled(),
@@ -30383,6 +30392,13 @@ function channelReplayEnabled() {
30383
30392
  defaultValue: true
30384
30393
  });
30385
30394
  }
30395
+ function combineMarkerReplayFacts(markers) {
30396
+ if (markers.length === 0) return null;
30397
+ return {
30398
+ hasPayload: markers.every((m) => m.hasPayload),
30399
+ discretionary: markers.some((m) => m.discretionary === true)
30400
+ };
30401
+ }
30386
30402
  function markerReplayable(i) {
30387
30403
  if (!i.enabled) return false;
30388
30404
  if (!i.hasPayload) return false;
@@ -36674,7 +36690,7 @@ var FLAG_REGISTRY = [
36674
36690
  },
36675
36691
  {
36676
36692
  key: "auto-resume-enabled",
36677
- description: "DO NOT ARM YET (ENG-8395): this flag has no `since` set until a follow-up bisects it from the published agt-cli dist, and an unset `since` makes the flip-reach estimate report FULL reach for a reader that is host-side \u2014 it will tell you a flip reached hosts that have no code to honour it. Arm only once that follow-up has landed. Bounded BLIND auto-resume for circuit-breaker pauses (ENG-6088): at most one unattended resume per trip cycle, fired once the trip driver has been quiet for the configured window and only for provisioning-reload trips (the ENG-7577 class gate \u2014 a crash-class trip still needs an operator). Superseded wherever `resume-reconciler` is on: that path proves the dependency recovered instead of assuming it, and the blind timer is its flag-off fallback. Boolean gate; ships dark. ENG-8395 promoted this from a raw host env var because AGT_AUTO_RESUME_ENABLED lives in the host env file, so its grain is per-HOST \u2014 one flip arms every agent that host runs (agt-aws-1 carries 14), which made the canary-then-fleet rollout its own documentation prescribes impossible. As a registry flag it resolves per org/team/host/AGENT, so one agent can genuinely be cut over first. Read host-side by the manager (agt-cli), not centrally.",
36693
+ description: "Bounded BLIND auto-resume for circuit-breaker pauses (ENG-6088): at most one unattended resume per trip cycle, fired once the trip driver has been quiet for the configured window and only for provisioning-reload trips (the ENG-7577 class gate \u2014 a crash-class trip still needs an operator). Superseded wherever `resume-reconciler` is on: that path proves the dependency recovered instead of assuming it, and the blind timer is its flag-off fallback. Boolean gate; ships dark. ENG-8395 promoted this from a raw host env var because AGT_AUTO_RESUME_ENABLED lives in the host env file, so its grain is per-HOST \u2014 one flip arms every agent that host runs (agt-aws-1 carries 14), which made the canary-then-fleet rollout its own documentation prescribes impossible. As a registry flag it resolves per org/team/host/AGENT, so one agent can genuinely be cut over first. Read host-side by the manager (agt-cli), not centrally.",
36678
36694
  flagType: "boolean",
36679
36695
  // Declared safe value is `false` — identical to today's behaviour on a host
36680
36696
  // that has never set the env var. Fail-safe direction on a flag-DB read
@@ -36691,16 +36707,41 @@ var FLAG_REGISTRY = [
36691
36707
  // An unattended resume is a real availability change — the agent starts
36692
36708
  // spawning sessions again with no human in the loop — so arming it is a
36693
36709
  // deliberate, confirmed write (ADR-0022 sensitive-flag confirm).
36694
- sensitive: true
36695
- // ENG-8395 AC5: `since` is deliberately UNSET at merge. It must be bisected
36696
- // from the PUBLISHED agt-cli dist once the artifact carrying the host-side
36697
- // reader exists, never guessed auto-resume.ts is host-side, so an
36698
- // under-`since` host has no consumer for this flag and a guessed value makes
36699
- // the flip-reach modal promise reach it does not have (the defect caught on
36700
- // ENG-8344 / PR #4014). Precedent for the bisect method: slack-hot-thread-guard
36701
- // = 0.28.339, slack-scheduled-channel-guard = 0.28.421. Setting it later is
36702
- // safe: `since` is excluded from projectDefinition, so it does not roll
36710
+ sensitive: true,
36711
+ // ENG-10034: bisected from the PUBLISHED agt-cli dists, not from git history —
36712
+ // auto-resume.ts is host-side, so what matters is the first ARTIFACT a host
36713
+ // could be running that contains a consumer for this flag.
36714
+ //
36715
+ // METHOD, so it can be re-run rather than trusted: download each candidate
36716
+ // tarball from the npm registry and grep its contents for the flag-specific
36717
+ // wiring. Binary search over the 22 versions published either side of
36718
+ // ENG-8395's merge gave a clean one-release boundary, eight minutes wide:
36719
+ //
36720
+ // 0.28.506 2026-08-03T22:29:22Z readAutoResumeEnvOverride ✗ AUTO_RESUME_FLAG_KEY ✗ 'auto-resume-enabled' ✗
36721
+ // 0.28.507 2026-08-03T22:37:00Z readAutoResumeEnvOverride ✓ AUTO_RESUME_FLAG_KEY ✓ 'auto-resume-enabled' ✓
36722
+ //
36723
+ // All three symbols are checked rather than one. `getBooleanForAgent` alone
36724
+ // would have been the wrong probe — it is present in BOTH builds, because the
36725
+ // generic resolver long predates this flag. A `since` bisected on a symbol the
36726
+ // flag does not depend on is a number that looks rigorous and is not.
36727
+ //
36728
+ // ENG-8395 AC5 left this unset on purpose and said why: an unset `since` makes
36729
+ // the flip-reach estimate report FULL reach for a host-side reader, promising
36730
+ // reach it does not have (the defect caught on ENG-8344 / PR #4014). The
36731
+ // follow-up it was waiting on was never filed, so the flag sat un-armable for
36732
+ // a month and ENG-6088's bounded auto-resume stayed dark fleet-wide — a
36733
+ // customer agent sat breaker-paused 2h08m on 2026-09-05 with the recovery path
36734
+ // silently disabled. That is what an administrative blocker recorded only in a
36735
+ // code comment costs.
36736
+ //
36737
+ // Same method as its precedents: slack-hot-thread-guard = 0.28.339,
36738
+ // slack-scheduled-channel-guard = 0.28.421 (ENG-8149). Setting it now is safe:
36739
+ // `since` is excluded from projectDefinition, so it does not roll
36703
36740
  // FLAGS_SCHEMA_VERSION.
36741
+ //
36742
+ // This does NOT arm the flag. defaultValue stays false and `sensitive` stays
36743
+ // true; arming is a separate, deliberate decision that belongs to ENG-6066.
36744
+ since: "0.28.507"
36704
36745
  },
36705
36746
  {
36706
36747
  key: "host-poll-rate-alarm",
@@ -39671,6 +39712,7 @@ await mcp.connect(new StdioServerTransport());
39671
39712
  var processedIds = /* @__PURE__ */ new Set();
39672
39713
  var lastBusyAckNoticeAt = /* @__PURE__ */ new Map();
39673
39714
  var lastUndeliverableNoticeAt = /* @__PURE__ */ new Map();
39715
+ var undeliverableNoticeCount = /* @__PURE__ */ new Map();
39674
39716
  var lastTurnFailedNoticeAt = /* @__PURE__ */ new Map();
39675
39717
  async function postDirectChatNoticeMessage(sessionId, content) {
39676
39718
  try {
@@ -39705,14 +39747,47 @@ function postDirectChatBusyAckNotice(sessionId) {
39705
39747
  }
39706
39748
  })();
39707
39749
  }
39750
+ function directChatSessionReplayFacts(sessionId) {
39751
+ if (!DIRECT_CHAT_PENDING_INBOUND_DIR) return null;
39752
+ const found = [];
39753
+ try {
39754
+ clearDirectChatPendingMarkersForSession(
39755
+ DIRECT_CHAT_PENDING_INBOUND_DIR,
39756
+ sessionId,
39757
+ (fullPath) => {
39758
+ try {
39759
+ const marker = JSON.parse(readFileSync11(fullPath, "utf-8"));
39760
+ found.push({ hasPayload: Boolean(marker.payload), discretionary: marker.discretionary });
39761
+ } catch {
39762
+ found.push({ hasPayload: false });
39763
+ }
39764
+ }
39765
+ );
39766
+ } catch {
39767
+ return null;
39768
+ }
39769
+ const facts = combineMarkerReplayFacts(found);
39770
+ return facts ? { enabled: channelReplayEnabled(), ...facts } : null;
39771
+ }
39708
39772
  function postDirectChatUndeliverableNotice(sessionId) {
39709
39773
  const now = Date.now();
39710
39774
  if (!shouldPostUndeliverableNotice(lastUndeliverableNoticeAt.get(sessionId), now)) {
39711
39775
  return;
39712
39776
  }
39713
39777
  lastUndeliverableNoticeAt.set(sessionId, now);
39778
+ const text = undeliverableNoticeTextForRepeat({
39779
+ replay: directChatSessionReplayFacts(sessionId) ?? void 0,
39780
+ priorNotices: undeliverableNoticeCount.get(sessionId) ?? 0
39781
+ });
39782
+ if (text === null) {
39783
+ lastUndeliverableNoticeAt.delete(sessionId);
39784
+ return;
39785
+ }
39714
39786
  void (async () => {
39715
- const ok = await postDirectChatNoticeMessage(sessionId, undeliverableNoticeText());
39787
+ const ok = await postDirectChatNoticeMessage(sessionId, text);
39788
+ if (ok) {
39789
+ undeliverableNoticeCount.set(sessionId, (undeliverableNoticeCount.get(sessionId) ?? 0) + 1);
39790
+ }
39716
39791
  if (!ok) {
39717
39792
  lastUndeliverableNoticeAt.delete(sessionId);
39718
39793
  process.stderr.write(
package/dist/mcp/index.js CHANGED
@@ -28403,7 +28403,7 @@ var FLAG_REGISTRY = [
28403
28403
  },
28404
28404
  {
28405
28405
  key: "auto-resume-enabled",
28406
- description: "DO NOT ARM YET (ENG-8395): this flag has no `since` set until a follow-up bisects it from the published agt-cli dist, and an unset `since` makes the flip-reach estimate report FULL reach for a reader that is host-side \u2014 it will tell you a flip reached hosts that have no code to honour it. Arm only once that follow-up has landed. Bounded BLIND auto-resume for circuit-breaker pauses (ENG-6088): at most one unattended resume per trip cycle, fired once the trip driver has been quiet for the configured window and only for provisioning-reload trips (the ENG-7577 class gate \u2014 a crash-class trip still needs an operator). Superseded wherever `resume-reconciler` is on: that path proves the dependency recovered instead of assuming it, and the blind timer is its flag-off fallback. Boolean gate; ships dark. ENG-8395 promoted this from a raw host env var because AGT_AUTO_RESUME_ENABLED lives in the host env file, so its grain is per-HOST \u2014 one flip arms every agent that host runs (agt-aws-1 carries 14), which made the canary-then-fleet rollout its own documentation prescribes impossible. As a registry flag it resolves per org/team/host/AGENT, so one agent can genuinely be cut over first. Read host-side by the manager (agt-cli), not centrally.",
28406
+ description: "Bounded BLIND auto-resume for circuit-breaker pauses (ENG-6088): at most one unattended resume per trip cycle, fired once the trip driver has been quiet for the configured window and only for provisioning-reload trips (the ENG-7577 class gate \u2014 a crash-class trip still needs an operator). Superseded wherever `resume-reconciler` is on: that path proves the dependency recovered instead of assuming it, and the blind timer is its flag-off fallback. Boolean gate; ships dark. ENG-8395 promoted this from a raw host env var because AGT_AUTO_RESUME_ENABLED lives in the host env file, so its grain is per-HOST \u2014 one flip arms every agent that host runs (agt-aws-1 carries 14), which made the canary-then-fleet rollout its own documentation prescribes impossible. As a registry flag it resolves per org/team/host/AGENT, so one agent can genuinely be cut over first. Read host-side by the manager (agt-cli), not centrally.",
28407
28407
  flagType: "boolean",
28408
28408
  // Declared safe value is `false` — identical to today's behaviour on a host
28409
28409
  // that has never set the env var. Fail-safe direction on a flag-DB read
@@ -28420,16 +28420,41 @@ var FLAG_REGISTRY = [
28420
28420
  // An unattended resume is a real availability change — the agent starts
28421
28421
  // spawning sessions again with no human in the loop — so arming it is a
28422
28422
  // deliberate, confirmed write (ADR-0022 sensitive-flag confirm).
28423
- sensitive: true
28424
- // ENG-8395 AC5: `since` is deliberately UNSET at merge. It must be bisected
28425
- // from the PUBLISHED agt-cli dist once the artifact carrying the host-side
28426
- // reader exists, never guessed auto-resume.ts is host-side, so an
28427
- // under-`since` host has no consumer for this flag and a guessed value makes
28428
- // the flip-reach modal promise reach it does not have (the defect caught on
28429
- // ENG-8344 / PR #4014). Precedent for the bisect method: slack-hot-thread-guard
28430
- // = 0.28.339, slack-scheduled-channel-guard = 0.28.421. Setting it later is
28431
- // safe: `since` is excluded from projectDefinition, so it does not roll
28423
+ sensitive: true,
28424
+ // ENG-10034: bisected from the PUBLISHED agt-cli dists, not from git history —
28425
+ // auto-resume.ts is host-side, so what matters is the first ARTIFACT a host
28426
+ // could be running that contains a consumer for this flag.
28427
+ //
28428
+ // METHOD, so it can be re-run rather than trusted: download each candidate
28429
+ // tarball from the npm registry and grep its contents for the flag-specific
28430
+ // wiring. Binary search over the 22 versions published either side of
28431
+ // ENG-8395's merge gave a clean one-release boundary, eight minutes wide:
28432
+ //
28433
+ // 0.28.506 2026-08-03T22:29:22Z readAutoResumeEnvOverride ✗ AUTO_RESUME_FLAG_KEY ✗ 'auto-resume-enabled' ✗
28434
+ // 0.28.507 2026-08-03T22:37:00Z readAutoResumeEnvOverride ✓ AUTO_RESUME_FLAG_KEY ✓ 'auto-resume-enabled' ✓
28435
+ //
28436
+ // All three symbols are checked rather than one. `getBooleanForAgent` alone
28437
+ // would have been the wrong probe — it is present in BOTH builds, because the
28438
+ // generic resolver long predates this flag. A `since` bisected on a symbol the
28439
+ // flag does not depend on is a number that looks rigorous and is not.
28440
+ //
28441
+ // ENG-8395 AC5 left this unset on purpose and said why: an unset `since` makes
28442
+ // the flip-reach estimate report FULL reach for a host-side reader, promising
28443
+ // reach it does not have (the defect caught on ENG-8344 / PR #4014). The
28444
+ // follow-up it was waiting on was never filed, so the flag sat un-armable for
28445
+ // a month and ENG-6088's bounded auto-resume stayed dark fleet-wide — a
28446
+ // customer agent sat breaker-paused 2h08m on 2026-09-05 with the recovery path
28447
+ // silently disabled. That is what an administrative blocker recorded only in a
28448
+ // code comment costs.
28449
+ //
28450
+ // Same method as its precedents: slack-hot-thread-guard = 0.28.339,
28451
+ // slack-scheduled-channel-guard = 0.28.421 (ENG-8149). Setting it now is safe:
28452
+ // `since` is excluded from projectDefinition, so it does not roll
28432
28453
  // FLAGS_SCHEMA_VERSION.
28454
+ //
28455
+ // This does NOT arm the flag. defaultValue stays false and `sensitive` stays
28456
+ // true; arming is a separate, deliberate decision that belongs to ENG-6066.
28457
+ since: "0.28.507"
28433
28458
  },
28434
28459
  {
28435
28460
  key: "host-poll-rate-alarm",
@@ -42356,7 +42356,7 @@ var FLAG_REGISTRY = [
42356
42356
  },
42357
42357
  {
42358
42358
  key: "auto-resume-enabled",
42359
- description: "DO NOT ARM YET (ENG-8395): this flag has no `since` set until a follow-up bisects it from the published agt-cli dist, and an unset `since` makes the flip-reach estimate report FULL reach for a reader that is host-side \u2014 it will tell you a flip reached hosts that have no code to honour it. Arm only once that follow-up has landed. Bounded BLIND auto-resume for circuit-breaker pauses (ENG-6088): at most one unattended resume per trip cycle, fired once the trip driver has been quiet for the configured window and only for provisioning-reload trips (the ENG-7577 class gate \u2014 a crash-class trip still needs an operator). Superseded wherever `resume-reconciler` is on: that path proves the dependency recovered instead of assuming it, and the blind timer is its flag-off fallback. Boolean gate; ships dark. ENG-8395 promoted this from a raw host env var because AGT_AUTO_RESUME_ENABLED lives in the host env file, so its grain is per-HOST \u2014 one flip arms every agent that host runs (agt-aws-1 carries 14), which made the canary-then-fleet rollout its own documentation prescribes impossible. As a registry flag it resolves per org/team/host/AGENT, so one agent can genuinely be cut over first. Read host-side by the manager (agt-cli), not centrally.",
42359
+ description: "Bounded BLIND auto-resume for circuit-breaker pauses (ENG-6088): at most one unattended resume per trip cycle, fired once the trip driver has been quiet for the configured window and only for provisioning-reload trips (the ENG-7577 class gate \u2014 a crash-class trip still needs an operator). Superseded wherever `resume-reconciler` is on: that path proves the dependency recovered instead of assuming it, and the blind timer is its flag-off fallback. Boolean gate; ships dark. ENG-8395 promoted this from a raw host env var because AGT_AUTO_RESUME_ENABLED lives in the host env file, so its grain is per-HOST \u2014 one flip arms every agent that host runs (agt-aws-1 carries 14), which made the canary-then-fleet rollout its own documentation prescribes impossible. As a registry flag it resolves per org/team/host/AGENT, so one agent can genuinely be cut over first. Read host-side by the manager (agt-cli), not centrally.",
42360
42360
  flagType: "boolean",
42361
42361
  // Declared safe value is `false` — identical to today's behaviour on a host
42362
42362
  // that has never set the env var. Fail-safe direction on a flag-DB read
@@ -42373,16 +42373,41 @@ var FLAG_REGISTRY = [
42373
42373
  // An unattended resume is a real availability change — the agent starts
42374
42374
  // spawning sessions again with no human in the loop — so arming it is a
42375
42375
  // deliberate, confirmed write (ADR-0022 sensitive-flag confirm).
42376
- sensitive: true
42377
- // ENG-8395 AC5: `since` is deliberately UNSET at merge. It must be bisected
42378
- // from the PUBLISHED agt-cli dist once the artifact carrying the host-side
42379
- // reader exists, never guessed auto-resume.ts is host-side, so an
42380
- // under-`since` host has no consumer for this flag and a guessed value makes
42381
- // the flip-reach modal promise reach it does not have (the defect caught on
42382
- // ENG-8344 / PR #4014). Precedent for the bisect method: slack-hot-thread-guard
42383
- // = 0.28.339, slack-scheduled-channel-guard = 0.28.421. Setting it later is
42384
- // safe: `since` is excluded from projectDefinition, so it does not roll
42376
+ sensitive: true,
42377
+ // ENG-10034: bisected from the PUBLISHED agt-cli dists, not from git history —
42378
+ // auto-resume.ts is host-side, so what matters is the first ARTIFACT a host
42379
+ // could be running that contains a consumer for this flag.
42380
+ //
42381
+ // METHOD, so it can be re-run rather than trusted: download each candidate
42382
+ // tarball from the npm registry and grep its contents for the flag-specific
42383
+ // wiring. Binary search over the 22 versions published either side of
42384
+ // ENG-8395's merge gave a clean one-release boundary, eight minutes wide:
42385
+ //
42386
+ // 0.28.506 2026-08-03T22:29:22Z readAutoResumeEnvOverride ✗ AUTO_RESUME_FLAG_KEY ✗ 'auto-resume-enabled' ✗
42387
+ // 0.28.507 2026-08-03T22:37:00Z readAutoResumeEnvOverride ✓ AUTO_RESUME_FLAG_KEY ✓ 'auto-resume-enabled' ✓
42388
+ //
42389
+ // All three symbols are checked rather than one. `getBooleanForAgent` alone
42390
+ // would have been the wrong probe — it is present in BOTH builds, because the
42391
+ // generic resolver long predates this flag. A `since` bisected on a symbol the
42392
+ // flag does not depend on is a number that looks rigorous and is not.
42393
+ //
42394
+ // ENG-8395 AC5 left this unset on purpose and said why: an unset `since` makes
42395
+ // the flip-reach estimate report FULL reach for a host-side reader, promising
42396
+ // reach it does not have (the defect caught on ENG-8344 / PR #4014). The
42397
+ // follow-up it was waiting on was never filed, so the flag sat un-armable for
42398
+ // a month and ENG-6088's bounded auto-resume stayed dark fleet-wide — a
42399
+ // customer agent sat breaker-paused 2h08m on 2026-09-05 with the recovery path
42400
+ // silently disabled. That is what an administrative blocker recorded only in a
42401
+ // code comment costs.
42402
+ //
42403
+ // Same method as its precedents: slack-hot-thread-guard = 0.28.339,
42404
+ // slack-scheduled-channel-guard = 0.28.421 (ENG-8149). Setting it now is safe:
42405
+ // `since` is excluded from projectDefinition, so it does not roll
42385
42406
  // FLAGS_SCHEMA_VERSION.
42407
+ //
42408
+ // This does NOT arm the flag. defaultValue stays false and `sensitive` stays
42409
+ // true; arming is a separate, deliberate decision that belongs to ENG-6066.
42410
+ since: "0.28.507"
42386
42411
  },
42387
42412
  {
42388
42413
  key: "host-poll-rate-alarm",