@integrity-labs/agt-cli 0.28.474 → 0.28.475

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.
@@ -18867,7 +18867,7 @@ var require_filters = __commonJS({
18867
18867
  return r.copySafeness(str, res);
18868
18868
  }
18869
18869
  _exports.indent = indent;
18870
- function join15(arr, del, attr) {
18870
+ function join14(arr, del, attr) {
18871
18871
  del = del || "";
18872
18872
  if (attr) {
18873
18873
  arr = lib.map(arr, function(v) {
@@ -18876,7 +18876,7 @@ var require_filters = __commonJS({
18876
18876
  }
18877
18877
  return arr.join(del);
18878
18878
  }
18879
- _exports.join = join15;
18879
+ _exports.join = join14;
18880
18880
  function last(arr) {
18881
18881
  return arr[arr.length - 1];
18882
18882
  }
@@ -30087,40 +30087,6 @@ function resolveHostBooleanFlag(opts) {
30087
30087
  if (cached2 !== void 0) return cached2;
30088
30088
  return opts.defaultValue;
30089
30089
  }
30090
- var USAGE_LIMIT_REACTIVE_FLAG_KEY = "usage-limit-reactive-notice";
30091
- function parseUsageLimitReactiveMode(raw) {
30092
- if (raw === void 0) return void 0;
30093
- const v = raw.trim().toLowerCase();
30094
- if (v === "") return void 0;
30095
- if (v === "off" || v === "shadow" || v === "enforce") return v;
30096
- const b = envBoolean(raw);
30097
- if (b === true) return "enforce";
30098
- if (b === false) return "off";
30099
- return void 0;
30100
- }
30101
- function cachedUsageLimitReactiveMode(path) {
30102
- try {
30103
- if (!existsSync4(path)) return void 0;
30104
- const parsed = JSON.parse(readFileSync6(path, "utf8"));
30105
- if (!parsed || typeof parsed !== "object") return void 0;
30106
- const flags = parsed.flags;
30107
- if (!flags || typeof flags !== "object") return void 0;
30108
- const value = flags[USAGE_LIMIT_REACTIVE_FLAG_KEY];
30109
- if (typeof value === "string") return parseUsageLimitReactiveMode(value);
30110
- if (typeof value === "boolean") return value ? "enforce" : "off";
30111
- return void 0;
30112
- } catch {
30113
- return void 0;
30114
- }
30115
- }
30116
- function resolveUsageLimitReactiveMode(opts) {
30117
- const env2 = opts?.env ?? process.env;
30118
- const modeOverride = parseUsageLimitReactiveMode(env2["AGT_USAGE_LIMIT_REACTIVE_MODE"]);
30119
- if (modeOverride !== void 0) return modeOverride;
30120
- const cached2 = cachedUsageLimitReactiveMode(opts?.cachePath ?? defaultFlagsCachePath());
30121
- if (cached2 !== void 0) return cached2;
30122
- return "off";
30123
- }
30124
30090
 
30125
30091
  // src/ack-reaction.ts
30126
30092
  var REPLY_WEDGED_THRESHOLD_MS = 5 * 60 * 1e3;
@@ -33691,30 +33657,11 @@ function parseResetDateTime(humanDate, now) {
33691
33657
  return resolved;
33692
33658
  }
33693
33659
 
33694
- // ../core/dist/claude-code-usage/usage-limit-marker.js
33695
- var USAGE_LIMIT_MARKER_FILENAME = "claude-usage-limit.json";
33696
- var USAGE_LIMIT_MARKER_VERSION = 1;
33697
- function parseUsageLimitMarker(raw) {
33698
- let parsed;
33699
- try {
33700
- parsed = JSON.parse(raw);
33701
- } catch {
33702
- return null;
33703
- }
33704
- if (typeof parsed !== "object" || parsed === null || parsed.version !== USAGE_LIMIT_MARKER_VERSION) {
33705
- return null;
33706
- }
33707
- const until = parsed.limited_until;
33708
- if (typeof until !== "string" || !Number.isFinite(Date.parse(until)))
33709
- return null;
33710
- return { version: USAGE_LIMIT_MARKER_VERSION, limited_until: until };
33711
- }
33712
- function resolveUsageLimitUntil(marker, now) {
33713
- if (!marker)
33714
- return null;
33715
- const until = new Date(marker.limited_until);
33716
- return until.getTime() > now.getTime() ? until : null;
33717
- }
33660
+ // ../core/dist/claude-code-usage/run-marker.js
33661
+ var RUN_MARKER_RE = /<!--\s*agt-run:([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\s*-->/;
33662
+ var RUN_MARKER_RE_GLOBAL = new RegExp(RUN_MARKER_RE.source, "g");
33663
+
33664
+ // ../core/dist/claude-code-usage/usage-limit-notice-text.js
33718
33665
  function formatUtcClock(date3) {
33719
33666
  const hours = date3.getUTCHours();
33720
33667
  const minutes = date3.getUTCMinutes();
@@ -34646,42 +34593,6 @@ var FLAG_REGISTRY = [
34646
34593
  // projectDefinition, so setting it does not roll FLAGS_SCHEMA_VERSION.
34647
34594
  since: "0.28.421"
34648
34595
  },
34649
- {
34650
- key: "usage-limit-reactive-notice",
34651
- description: "Report a Claude Code usage cap REACTIVELY instead of predicting it (ENG-8201). Today the manager guesses from the agent transcript that the next turn will be refused, writes a marker, and every channel MCP refuses to dispatch on the strength of that guess - so a wrong guess is a swallowed message, and because the notice is throttled per (channel, sender) while the DROP is not, the usual symptom is total silence rather than a wrong reply. A refused turn actually costs nothing (rejected in under a second, zero tokens) and Claude Code records it with the reset time in it, so there is no need to guess: dispatch, and report the refusal if one comes back. off = today behaviour (pre-dispatch marker gate, no watcher). shadow = still gate on the marker, but ALSO watch dispatched messages and log the refusal that would have been reported - measures the true-positive rate with no user-visible change. enforce = stop reading the marker before dispatch; every admitted human message reaches the agent and a refusal is answered in-thread with the reset time from the error itself. Read live from the heartbeat flags-cache (or the env override).",
34652
- flagType: "enum",
34653
- allowedValues: ["off", "shadow", "enforce"],
34654
- // Ships dark: off preserves today's gate byte-for-byte. shadow is a free
34655
- // local log line (the watch is a transcript read, no model spend), so it is a
34656
- // cheap soak; enforce changes what reaches the agent, so it is the audited
34657
- // per-org flip.
34658
- defaultValue: "off",
34659
- // Enum override AGT_USAGE_LIMIT_REACTIVE_MODE (off|shadow|enforce), resolved
34660
- // by resolveUsageLimitReactiveMode in the channel-server bundle.
34661
- envVar: "AGT_USAGE_LIMIT_REACTIVE_MODE",
34662
- // enforce sends a message to an agent the host currently believes is capped -
34663
- // a deliberate availability trade (the refusal is free, but it is still a
34664
- // dispatch the operator previously suppressed), so flipping toward it is an
34665
- // audited change (ADR-0022 sensitive-flag confirm).
34666
- sensitive: true,
34667
- // ENG-8149 / ENG-8229: the agt-cli that first carries
34668
- // resolveUsageLimitReactiveMode in ALL THREE channel servers - published from
34669
- // the ENG-8207 merge 0294fa1a8. Without this the flip-reach modal reports FULL
34670
- // reach, because an undefined `since` means "every host can honour it" - true
34671
- // for flags that predate the reach work, wrong for a NEW host-read flag whose
34672
- // reader older hosts simply do not have. Excluded from projectDefinition, so
34673
- // setting it does not roll FLAGS_SCHEMA_VERSION.
34674
- //
34675
- // Deliberately the LATER of the two versions this flag's reader shipped in.
34676
- // Unlike its siblings, this reader landed in two stages: direct-chat at the
34677
- // ENG-8201 Slice 2 publish, slack + telegram only at 0.28.450 (ENG-8207) - and
34678
- // `since` is one version per flag, so it cannot express "partially honoured".
34679
- // A host in between genuinely honours the flag for direct-chat and is still
34680
- // classified `stale`. That understates reach rather than overstating it, which
34681
- // is the safe direction, and it is the useful one while the flag sits at
34682
- // enforce and slack/telegram adoption is what an operator needs to track.
34683
- since: "0.28.450"
34684
- },
34685
34596
  {
34686
34597
  key: "slack-hot-thread-guard",
34687
34598
  description: "Server-side hot-thread guard on the slack.reply surface (ENG-7462). Prevents an agent posting a NEW top-level Slack message when it meant to reply inside the thread it is already working in - a prompt/memory rule proved insufficient (the agent had the rule and still slipped). When a reply would otherwise post to channel ROOT (no thread_ts / message_ts / inbound_id, no active kanban card) and the agent has a recent active thread in that channel (its last bot-posted thread, from the persisted trackedThreads cache, within a freshness window), the reply is redirected into that thread. proactive:true no longer implies channel root; posting at root becomes a deliberate action (the to_channel_root flag, or the thread_ts:null sentinel). off = guard never runs, replies with no coords root exactly as today (ships dark). shadow = compute + log the would-redirect but STILL post to root (measure the fire rate before acting). enforce = apply the redirect (a soft-block: redirect + inform, never a hard rejection). Read live from the heartbeat flags-cache (or the env override); enforce is a deliberate per-org flip after a shadow soak.",
@@ -35783,14 +35694,14 @@ function readLockHolder(path) {
35783
35694
  }
35784
35695
 
35785
35696
  // src/direct-chat-channel.ts
35786
- import { homedir as homedir5 } from "os";
35787
- import { join as join14 } from "path";
35697
+ import { homedir as homedir4 } from "os";
35698
+ import { join as join13 } from "path";
35788
35699
  import { randomUUID } from "crypto";
35789
35700
  import {
35790
35701
  watch,
35791
35702
  mkdirSync as mkdirSync5,
35792
35703
  writeFileSync as writeFileSync6,
35793
- readFileSync as readFileSync13,
35704
+ readFileSync as readFileSync12,
35794
35705
  readdirSync as readdirSync6,
35795
35706
  existsSync as existsSync6,
35796
35707
  renameSync as renameSync5,
@@ -36222,30 +36133,10 @@ function isMaintenanceModeActive(opts) {
36222
36133
  });
36223
36134
  }
36224
36135
 
36225
- // src/usage-limit-notice.ts
36136
+ // src/account-enforcement-notice.ts
36226
36137
  import { readFileSync as readFileSync11 } from "fs";
36227
36138
  import { homedir as homedir3 } from "os";
36228
36139
  import { join as join12 } from "path";
36229
- function usageLimitMarkerPath(codeName) {
36230
- if (!codeName) return null;
36231
- return join12(homedir3(), ".augmented", codeName, USAGE_LIMIT_MARKER_FILENAME);
36232
- }
36233
- function readUsageLimitUntil(opts) {
36234
- const path = opts.filePath ?? usageLimitMarkerPath(opts.codeName);
36235
- if (!path) return null;
36236
- let raw;
36237
- try {
36238
- raw = readFileSync11(path, "utf-8");
36239
- } catch {
36240
- return null;
36241
- }
36242
- return resolveUsageLimitUntil(parseUsageLimitMarker(raw), opts.now ?? /* @__PURE__ */ new Date());
36243
- }
36244
-
36245
- // src/account-enforcement-notice.ts
36246
- import { readFileSync as readFileSync12 } from "fs";
36247
- import { homedir as homedir4 } from "os";
36248
- import { join as join13 } from "path";
36249
36140
 
36250
36141
  // ../core/dist/channels/governance/sender-policy-decline.js
36251
36142
  function decideDeclineReply(input) {
@@ -36263,14 +36154,14 @@ function decideDeclineReply(input) {
36263
36154
  // src/account-enforcement-notice.ts
36264
36155
  function accountEnforcementMarkerPath(codeName) {
36265
36156
  if (!codeName) return null;
36266
- return join13(homedir4(), ".augmented", codeName, ACCOUNT_ENFORCEMENT_MARKER_FILENAME);
36157
+ return join12(homedir3(), ".augmented", codeName, ACCOUNT_ENFORCEMENT_MARKER_FILENAME);
36267
36158
  }
36268
36159
  function readAccountEnforcementLevel(opts) {
36269
36160
  const path = opts.filePath ?? accountEnforcementMarkerPath(opts.codeName);
36270
36161
  if (!path) return null;
36271
36162
  let raw;
36272
36163
  try {
36273
- raw = readFileSync12(path, "utf-8");
36164
+ raw = readFileSync11(path, "utf-8");
36274
36165
  } catch {
36275
36166
  return null;
36276
36167
  }
@@ -36288,6 +36179,17 @@ function shouldSendAccountWarn(opts) {
36288
36179
  }).reply;
36289
36180
  }
36290
36181
 
36182
+ // src/usage-limit-reactive-decision.ts
36183
+ import { createHash } from "crypto";
36184
+ function shouldArmWatch(opts) {
36185
+ return !opts.isBot && opts.replyOwed;
36186
+ }
36187
+ function describeUnparsedRefusal(text) {
36188
+ if (!text) return "refusal=absent";
36189
+ const hash = createHash("sha256").update(text).digest("hex").slice(0, 12);
36190
+ return `refusal_hash=${hash} refusal_len=${text.length}`;
36191
+ }
36192
+
36291
36193
  // src/direct-chat-channel.ts
36292
36194
  var DIRECT_CHAT_MAINTENANCE_CACHE = /* @__PURE__ */ new Map();
36293
36195
  var DIRECT_CHAT_MAINTENANCE_COOLDOWN_MS = (() => {
@@ -36306,21 +36208,21 @@ var DIRECT_CHAT_ACCOUNT_WARN_COOLDOWN_MS = (() => {
36306
36208
  var AGT_HOST = process.env.AGT_HOST;
36307
36209
  var AGT_API_KEY = process.env.AGT_API_KEY;
36308
36210
  var AGT_AGENT_ID = process.env.AGT_AGENT_ID;
36309
- var DIRECT_CHAT_AGENT_DIR = AGT_AGENT_ID ? join14(homedir5(), ".augmented", AGT_AGENT_ID) : null;
36211
+ var DIRECT_CHAT_AGENT_DIR = AGT_AGENT_ID ? join13(homedir4(), ".augmented", AGT_AGENT_ID) : null;
36310
36212
  var INBOUND_ATTACHMENTS_DIR = resolveInboundAttachmentsDir({
36311
36213
  codeName: process.env.AGT_AGENT_CODE_NAME,
36312
36214
  turnInitiatorFile: process.env.AGT_TURN_INITIATOR_FILE,
36313
36215
  agentId: AGT_AGENT_ID,
36314
- homeDir: homedir5()
36216
+ homeDir: homedir4()
36315
36217
  });
36316
36218
  var AGT_AGENT_CODE_NAME = process.env.AGT_AGENT_CODE_NAME;
36317
36219
  var directChatStderrLogStream = null;
36318
36220
  if (AGT_AGENT_CODE_NAME) {
36319
36221
  try {
36320
- const logDir = join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME);
36222
+ const logDir = join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME);
36321
36223
  mkdirSync5(logDir, { recursive: true });
36322
36224
  directChatStderrLogStream = createWriteStream(
36323
- join14(logDir, "direct-chat-channel-stderr.log"),
36225
+ join13(logDir, "direct-chat-channel-stderr.log"),
36324
36226
  { flags: "a", mode: 384 }
36325
36227
  );
36326
36228
  directChatStderrLogStream.on("error", () => {
@@ -36339,10 +36241,10 @@ if (AGT_AGENT_CODE_NAME) {
36339
36241
  } catch {
36340
36242
  }
36341
36243
  }
36342
- var PROGRESS_HEARTBEAT_PATH = AGT_AGENT_CODE_NAME ? join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME, "channel-progress-heartbeat.json") : null;
36343
- var DIRECT_CHAT_PENDING_INBOUND_DIR = AGT_AGENT_CODE_NAME ? join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-pending-inbound") : null;
36344
- var DIRECT_CHAT_DELIVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-inbound-delivery-ledger") : null;
36345
- var DIRECT_CHAT_CODE_NAME_AGENT_DIR = AGT_AGENT_CODE_NAME ? join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME) : null;
36244
+ var PROGRESS_HEARTBEAT_PATH = AGT_AGENT_CODE_NAME ? join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME, "channel-progress-heartbeat.json") : null;
36245
+ var DIRECT_CHAT_PENDING_INBOUND_DIR = AGT_AGENT_CODE_NAME ? join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-pending-inbound") : null;
36246
+ var DIRECT_CHAT_DELIVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-inbound-delivery-ledger") : null;
36247
+ var DIRECT_CHAT_CODE_NAME_AGENT_DIR = AGT_AGENT_CODE_NAME ? join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME) : null;
36346
36248
  var DIRECT_CHAT_STALE_MARKER_MS = 24 * 60 * 60 * 1e3;
36347
36249
  function recordDirectChatDelivery(sessionId, messageIds) {
36348
36250
  if (!sessionId) return;
@@ -36353,8 +36255,8 @@ function recordDirectChatDelivery(sessionId, messageIds) {
36353
36255
  delivered_at: (/* @__PURE__ */ new Date()).toISOString()
36354
36256
  });
36355
36257
  }
36356
- var DIRECT_CHAT_RECOVERY_OUTBOX_DIR = AGT_AGENT_CODE_NAME ? join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-recovery-outbox") : null;
36357
- var DIRECT_CHAT_RECOVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-direct-chat-recovery-ledger") : null;
36258
+ var DIRECT_CHAT_RECOVERY_OUTBOX_DIR = AGT_AGENT_CODE_NAME ? join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-recovery-outbox") : null;
36259
+ var DIRECT_CHAT_RECOVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-direct-chat-recovery-ledger") : null;
36358
36260
  var progressReceivedAt = /* @__PURE__ */ new Map();
36359
36261
  var directChatProgressState = { tracked: null };
36360
36262
  var directChatProgressTickRunning = false;
@@ -36373,7 +36275,7 @@ var directChatKanbanCardClient = createKanbanCardActiveClient({
36373
36275
  function readProgressHeartbeat() {
36374
36276
  if (!PROGRESS_HEARTBEAT_PATH || !existsSync6(PROGRESS_HEARTBEAT_PATH)) return null;
36375
36277
  try {
36376
- return parseProgressHeartbeat(readFileSync13(PROGRESS_HEARTBEAT_PATH, "utf-8"));
36278
+ return parseProgressHeartbeat(readFileSync12(PROGRESS_HEARTBEAT_PATH, "utf-8"));
36377
36279
  } catch {
36378
36280
  return null;
36379
36281
  }
@@ -36382,7 +36284,7 @@ function seedProgressHeartbeat() {
36382
36284
  if (!PROGRESS_HEARTBEAT_PATH) return;
36383
36285
  const tmp = `${PROGRESS_HEARTBEAT_PATH}.${process.pid}.tmp`;
36384
36286
  try {
36385
- mkdirSync5(join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME), { recursive: true });
36287
+ mkdirSync5(join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME), { recursive: true });
36386
36288
  writeFileSync6(tmp, serializeProgressHeartbeat(SEED_PROGRESS_STEP, Date.now()), { mode: 384 });
36387
36289
  renameSync5(tmp, PROGRESS_HEARTBEAT_PATH);
36388
36290
  } catch {
@@ -36577,7 +36479,7 @@ var inboundAttachmentDeps = {
36577
36479
  },
36578
36480
  ensureDir: (dir) => mkdirSync5(dir, { recursive: true }),
36579
36481
  writeFile: (path, bytes) => writeFileSync6(path, bytes, { mode: 384 }),
36580
- joinPath: (...parts) => join14(...parts),
36482
+ joinPath: (...parts) => join13(...parts),
36581
36483
  warn: (msg) => process.stderr.write(`${msg}
36582
36484
  `)
36583
36485
  };
@@ -36911,7 +36813,7 @@ function scheduleDirectChatBusyAck(sessionId, messageId, arrivedWhileBusy) {
36911
36813
  let paneLogFreshAgeMs = null;
36912
36814
  if (DIRECT_CHAT_CODE_NAME_AGENT_DIR) {
36913
36815
  try {
36914
- const paneMtimeMs = statSync4(join14(DIRECT_CHAT_CODE_NAME_AGENT_DIR, "pane.log")).mtimeMs;
36816
+ const paneMtimeMs = statSync4(join13(DIRECT_CHAT_CODE_NAME_AGENT_DIR, "pane.log")).mtimeMs;
36915
36817
  paneLogFreshAgeMs = Math.max(0, Date.now() - paneMtimeMs);
36916
36818
  } catch {
36917
36819
  }
@@ -37004,14 +36906,7 @@ function armUsageLimitWatch(args) {
37004
36906
  if (!refusal) return;
37005
36907
  if (!refusal.resetsAt) {
37006
36908
  process.stderr.write(
37007
- `direct-chat-channel: [usage-limit-reactive] mode=${args.mode} refusal detected for session=${args.sessionId} but no reset time in it (${refusal.text ?? "no text"}) - no notice
37008
- `
37009
- );
37010
- return;
37011
- }
37012
- if (args.mode === "shadow") {
37013
- process.stderr.write(
37014
- `direct-chat-channel: [usage-limit-reactive] mode=shadow WOULD notify session=${args.sessionId} message=${args.messageId} resets=${refusal.resetsAt.toISOString()}
36909
+ `direct-chat-channel: [usage-limit-reactive] refusal detected for session=${args.sessionId} but no reset time in it (${describeUnparsedRefusal(refusal.text)}) - no notice
37015
36910
  `
37016
36911
  );
37017
36912
  return;
@@ -37084,9 +36979,7 @@ async function pollForMessages(sinceMs) {
37084
36979
  const isNotice = msg.kind === "notice";
37085
36980
  const maintenanceActive = !isNotice && isMaintenanceModeActive();
37086
36981
  const accountMuted = !isNotice && !maintenanceActive ? readAccountEnforcementLevel({ codeName: AGT_AGENT_CODE_NAME ?? null }) === "mute" : false;
37087
- const reactiveMode = resolveUsageLimitReactiveMode();
37088
- const usageLimitUntil = !isNotice && !maintenanceActive && !accountMuted && reactiveMode !== "enforce" ? readUsageLimitUntil({ codeName: AGT_AGENT_CODE_NAME ?? null }) : null;
37089
- if (!isNotice && !maintenanceActive && !accountMuted && !usageLimitUntil) {
36982
+ if (!isNotice && !maintenanceActive && !accountMuted) {
37090
36983
  markProcessed(msg.id);
37091
36984
  claimTracker.track(msg.session_id, msg.id);
37092
36985
  if (!progressReceivedAt.has(msg.session_id)) {
@@ -37151,37 +37044,6 @@ async function pollForMessages(sinceMs) {
37151
37044
  if (throttle.reply) DIRECT_CHAT_ACCOUNT_MUTE_CACHE.delete(throttleKey);
37152
37045
  process.stderr.write(
37153
37046
  `direct-chat-channel: account-mute reply failed: ${err.message}
37154
- `
37155
- );
37156
- }
37157
- continue;
37158
- }
37159
- if (usageLimitUntil) {
37160
- const throttleKey = `${msg.session_id}|usage_limit`;
37161
- const throttle = decideDeclineReply({
37162
- cache: DIRECT_CHAT_USAGE_LIMIT_CACHE,
37163
- key: throttleKey,
37164
- cooldownMs: DIRECT_CHAT_MAINTENANCE_COOLDOWN_MS,
37165
- now: Date.now()
37166
- });
37167
- const route = throttle.reply ? "/host/direct-chat/reply" : "/host/direct-chat/consume";
37168
- const body = throttle.reply ? { agent_id: AGT_AGENT_ID, session_id: msg.session_id, content: buildUsageLimitReplyText(usageLimitUntil), message_ids: [msg.id], kind: "notice" } : { agent_id: AGT_AGENT_ID, session_id: msg.session_id, message_ids: [msg.id] };
37169
- try {
37170
- const res2 = await apiPost(route, body);
37171
- const data2 = await res2.json().catch(() => ({}));
37172
- if (res2.ok && data2.error == null) {
37173
- markProcessed(msg.id);
37174
- } else {
37175
- if (throttle.reply) DIRECT_CHAT_USAGE_LIMIT_CACHE.delete(throttleKey);
37176
- process.stderr.write(
37177
- `direct-chat-channel: usage-limit ${throttle.reply ? "reply" : "consume"} failed: ${data2.error ?? `HTTP ${res2.status}`}
37178
- `
37179
- );
37180
- }
37181
- } catch (err) {
37182
- if (throttle.reply) DIRECT_CHAT_USAGE_LIMIT_CACHE.delete(throttleKey);
37183
- process.stderr.write(
37184
- `direct-chat-channel: usage-limit reply failed: ${err.message}
37185
37047
  `
37186
37048
  );
37187
37049
  }
@@ -37264,9 +37126,8 @@ async function pollForMessages(sinceMs) {
37264
37126
  `direct-chat-channel: Injected message ${msg.id} (session=${msg.session_id})
37265
37127
  `
37266
37128
  );
37267
- if (!isNotice && reactiveMode !== "off") {
37129
+ if (shouldArmWatch({ isBot: false, replyOwed: !isNotice })) {
37268
37130
  armUsageLimitWatch({
37269
- mode: reactiveMode,
37270
37131
  sessionId: msg.session_id,
37271
37132
  messageId: msg.id,
37272
37133
  sinceMs: dispatchedAtMs
@@ -37385,7 +37246,7 @@ function sweepAgedDirectChatMarkersNow(thresholdMs) {
37385
37246
  const now = Date.now();
37386
37247
  const res = sweepAgedDirectChatMarkers(DIRECT_CHAT_PENDING_INBOUND_DIR, {
37387
37248
  readdir: (dir) => readdirSync6(dir),
37388
- readFile: (p2) => readFileSync13(p2, "utf8"),
37249
+ readFile: (p2) => readFileSync12(p2, "utf8"),
37389
37250
  unlink: (p2) => {
37390
37251
  if (existsSync6(p2)) unlinkSync4(p2);
37391
37252
  },
@@ -37421,7 +37282,7 @@ function sanitizeRecoveryText(text) {
37421
37282
  }
37422
37283
  function directChatRecoveryDeps() {
37423
37284
  return {
37424
- readFile: (p2) => readFileSync13(p2, "utf-8"),
37285
+ readFile: (p2) => readFileSync12(p2, "utf-8"),
37425
37286
  renameFile: (from, to) => renameSync5(from, to),
37426
37287
  unlinkFile: (p2) => {
37427
37288
  if (existsSync6(p2)) unlinkSync4(p2);
@@ -37434,7 +37295,7 @@ function directChatRecoveryDeps() {
37434
37295
  if (!DIRECT_CHAT_RECOVERY_LEDGER_DIR) return;
37435
37296
  if (markerName.includes("/") || markerName.includes("\\") || markerName.includes("..")) return;
37436
37297
  try {
37437
- const p2 = join14(DIRECT_CHAT_RECOVERY_LEDGER_DIR, markerName);
37298
+ const p2 = join13(DIRECT_CHAT_RECOVERY_LEDGER_DIR, markerName);
37438
37299
  if (existsSync6(p2)) unlinkSync4(p2);
37439
37300
  } catch {
37440
37301
  }
@@ -37470,7 +37331,7 @@ async function processDirectChatRecoveryOutboxFile(filename) {
37470
37331
  if (!enabled) return;
37471
37332
  directChatRecoveryInFlight.add(filename);
37472
37333
  try {
37473
- const fullPath = join14(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, filename);
37334
+ const fullPath = join13(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, filename);
37474
37335
  await consumeDirectChatRecoveryFile(fullPath, filename, directChatRecoveryDeps());
37475
37336
  } catch (err) {
37476
37337
  process.stderr.write(
@@ -37498,7 +37359,7 @@ if (DIRECT_CHAT_RECOVERY_OUTBOX_DIR) {
37498
37359
  if (!filename) return;
37499
37360
  const name = filename.toString();
37500
37361
  if (!name.endsWith(".json")) return;
37501
- if (existsSync6(join14(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, name))) {
37362
+ if (existsSync6(join13(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, name))) {
37502
37363
  void processDirectChatRecoveryOutboxFile(name);
37503
37364
  }
37504
37365
  });
@@ -39878,6 +39878,10 @@ var BANNER_PATTERNS = [
39878
39878
  ];
39879
39879
  var MS_PER_DAY = 24 * 60 * 60 * 1e3;
39880
39880
 
39881
+ // ../core/dist/claude-code-usage/run-marker.js
39882
+ var RUN_MARKER_RE = /<!--\s*agt-run:([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\s*-->/;
39883
+ var RUN_MARKER_RE_GLOBAL = new RegExp(RUN_MARKER_RE.source, "g");
39884
+
39881
39885
  // ../core/dist/claude-code-usage/rate-limit-classifier.js
39882
39886
  var UNKNOWN_RATE_LIMIT = Object.freeze({
39883
39887
  verdict: "unknown",
@@ -40536,42 +40540,6 @@ var FLAG_REGISTRY = [
40536
40540
  // projectDefinition, so setting it does not roll FLAGS_SCHEMA_VERSION.
40537
40541
  since: "0.28.421"
40538
40542
  },
40539
- {
40540
- key: "usage-limit-reactive-notice",
40541
- description: "Report a Claude Code usage cap REACTIVELY instead of predicting it (ENG-8201). Today the manager guesses from the agent transcript that the next turn will be refused, writes a marker, and every channel MCP refuses to dispatch on the strength of that guess - so a wrong guess is a swallowed message, and because the notice is throttled per (channel, sender) while the DROP is not, the usual symptom is total silence rather than a wrong reply. A refused turn actually costs nothing (rejected in under a second, zero tokens) and Claude Code records it with the reset time in it, so there is no need to guess: dispatch, and report the refusal if one comes back. off = today behaviour (pre-dispatch marker gate, no watcher). shadow = still gate on the marker, but ALSO watch dispatched messages and log the refusal that would have been reported - measures the true-positive rate with no user-visible change. enforce = stop reading the marker before dispatch; every admitted human message reaches the agent and a refusal is answered in-thread with the reset time from the error itself. Read live from the heartbeat flags-cache (or the env override).",
40542
- flagType: "enum",
40543
- allowedValues: ["off", "shadow", "enforce"],
40544
- // Ships dark: off preserves today's gate byte-for-byte. shadow is a free
40545
- // local log line (the watch is a transcript read, no model spend), so it is a
40546
- // cheap soak; enforce changes what reaches the agent, so it is the audited
40547
- // per-org flip.
40548
- defaultValue: "off",
40549
- // Enum override AGT_USAGE_LIMIT_REACTIVE_MODE (off|shadow|enforce), resolved
40550
- // by resolveUsageLimitReactiveMode in the channel-server bundle.
40551
- envVar: "AGT_USAGE_LIMIT_REACTIVE_MODE",
40552
- // enforce sends a message to an agent the host currently believes is capped -
40553
- // a deliberate availability trade (the refusal is free, but it is still a
40554
- // dispatch the operator previously suppressed), so flipping toward it is an
40555
- // audited change (ADR-0022 sensitive-flag confirm).
40556
- sensitive: true,
40557
- // ENG-8149 / ENG-8229: the agt-cli that first carries
40558
- // resolveUsageLimitReactiveMode in ALL THREE channel servers - published from
40559
- // the ENG-8207 merge 0294fa1a8. Without this the flip-reach modal reports FULL
40560
- // reach, because an undefined `since` means "every host can honour it" - true
40561
- // for flags that predate the reach work, wrong for a NEW host-read flag whose
40562
- // reader older hosts simply do not have. Excluded from projectDefinition, so
40563
- // setting it does not roll FLAGS_SCHEMA_VERSION.
40564
- //
40565
- // Deliberately the LATER of the two versions this flag's reader shipped in.
40566
- // Unlike its siblings, this reader landed in two stages: direct-chat at the
40567
- // ENG-8201 Slice 2 publish, slack + telegram only at 0.28.450 (ENG-8207) - and
40568
- // `since` is one version per flag, so it cannot express "partially honoured".
40569
- // A host in between genuinely honours the flag for direct-chat and is still
40570
- // classified `stale`. That understates reach rather than overstating it, which
40571
- // is the safe direction, and it is the useful one while the flag sits at
40572
- // enforce and slack/telegram adoption is what an operator needs to track.
40573
- since: "0.28.450"
40574
- },
40575
40543
  {
40576
40544
  key: "slack-hot-thread-guard",
40577
40545
  description: "Server-side hot-thread guard on the slack.reply surface (ENG-7462). Prevents an agent posting a NEW top-level Slack message when it meant to reply inside the thread it is already working in - a prompt/memory rule proved insufficient (the agent had the rule and still slipped). When a reply would otherwise post to channel ROOT (no thread_ts / message_ts / inbound_id, no active kanban card) and the agent has a recent active thread in that channel (its last bot-posted thread, from the persisted trackedThreads cache, within a freshness window), the reply is redirected into that thread. proactive:true no longer implies channel root; posting at root becomes a deliberate action (the to_channel_root flag, or the thread_ts:null sentinel). off = guard never runs, replies with no coords root exactly as today (ships dark). shadow = compute + log the would-redirect but STILL post to root (measure the fire rate before acting). enforce = apply the redirect (a soft-block: redirect + inform, never a hard rejection). Read live from the heartbeat flags-cache (or the env override); enforce is a deliberate per-org flip after a shadow soak.",