@integrity-labs/agt-cli 0.28.449 → 0.28.450

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.
@@ -18870,7 +18870,7 @@ var require_filters = __commonJS({
18870
18870
  return r.copySafeness(str, res);
18871
18871
  }
18872
18872
  _exports.indent = indent;
18873
- function join20(arr, del, attr) {
18873
+ function join21(arr, del, attr) {
18874
18874
  del = del || "";
18875
18875
  if (attr) {
18876
18876
  arr = lib.map(arr, function(v) {
@@ -18879,7 +18879,7 @@ var require_filters = __commonJS({
18879
18879
  }
18880
18880
  return arr.join(del);
18881
18881
  }
18882
- _exports.join = join20;
18882
+ _exports.join = join21;
18883
18883
  function last(arr) {
18884
18884
  return arr[arr.length - 1];
18885
18885
  }
@@ -22480,11 +22480,11 @@ async function waitForResolution(cfg, callbackId, opts) {
22480
22480
  }
22481
22481
  } catch {
22482
22482
  }
22483
- await sleep(interval);
22483
+ await sleep2(interval);
22484
22484
  }
22485
22485
  return { kind: "timeout" };
22486
22486
  }
22487
- function sleep(ms) {
22487
+ function sleep2(ms) {
22488
22488
  return new Promise((r) => setTimeout(r, ms));
22489
22489
  }
22490
22490
  function generateOptionToken() {
@@ -30393,6 +30393,40 @@ function resolveSlackScheduledChannelGuardMode(opts) {
30393
30393
  if (cached2 !== void 0) return clampScheduledChannelGuardMode(cached2);
30394
30394
  return "shadow";
30395
30395
  }
30396
+ var USAGE_LIMIT_REACTIVE_FLAG_KEY = "usage-limit-reactive-notice";
30397
+ function parseUsageLimitReactiveMode(raw) {
30398
+ if (raw === void 0) return void 0;
30399
+ const v = raw.trim().toLowerCase();
30400
+ if (v === "") return void 0;
30401
+ if (v === "off" || v === "shadow" || v === "enforce") return v;
30402
+ const b = envBoolean(raw);
30403
+ if (b === true) return "enforce";
30404
+ if (b === false) return "off";
30405
+ return void 0;
30406
+ }
30407
+ function cachedUsageLimitReactiveMode(path) {
30408
+ try {
30409
+ if (!existsSync(path)) return void 0;
30410
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
30411
+ if (!parsed || typeof parsed !== "object") return void 0;
30412
+ const flags = parsed.flags;
30413
+ if (!flags || typeof flags !== "object") return void 0;
30414
+ const value = flags[USAGE_LIMIT_REACTIVE_FLAG_KEY];
30415
+ if (typeof value === "string") return parseUsageLimitReactiveMode(value);
30416
+ if (typeof value === "boolean") return value ? "enforce" : "off";
30417
+ return void 0;
30418
+ } catch {
30419
+ return void 0;
30420
+ }
30421
+ }
30422
+ function resolveUsageLimitReactiveMode(opts) {
30423
+ const env2 = opts?.env ?? process.env;
30424
+ const modeOverride = parseUsageLimitReactiveMode(env2["AGT_USAGE_LIMIT_REACTIVE_MODE"]);
30425
+ if (modeOverride !== void 0) return modeOverride;
30426
+ const cached2 = cachedUsageLimitReactiveMode(opts?.cachePath ?? defaultFlagsCachePath());
30427
+ if (cached2 !== void 0) return cached2;
30428
+ return "off";
30429
+ }
30396
30430
 
30397
30431
  // src/maintenance-mode.ts
30398
30432
  var FLAG_KEY = "platform-maintenance-mode";
@@ -33734,7 +33768,113 @@ var BANNER_PATTERNS = [
33734
33768
  // pct=100.
33735
33769
  new RegExp(`${SUBJECT}hit\\s+your\\s+(?:[a-z0-9-]+\\s+)?limit${SEP}resets\\s+(${RESET_DATE})`, "i")
33736
33770
  ];
33771
+ function parseUsageBanner(text, now = /* @__PURE__ */ new Date()) {
33772
+ let bestIndex = -1;
33773
+ let best = null;
33774
+ for (let i = 0; i < BANNER_PATTERNS.length; i++) {
33775
+ const pattern = new RegExp(BANNER_PATTERNS[i].source, "gi");
33776
+ let match;
33777
+ while ((match = pattern.exec(text)) !== null) {
33778
+ if (match.index === pattern.lastIndex)
33779
+ pattern.lastIndex++;
33780
+ let pct;
33781
+ let resetStr;
33782
+ if (i === 0) {
33783
+ pct = Number.parseInt(match[1], 10);
33784
+ resetStr = match[2];
33785
+ } else {
33786
+ pct = 100;
33787
+ resetStr = match[1];
33788
+ }
33789
+ if (!Number.isFinite(pct) || pct < 0 || pct > 100)
33790
+ continue;
33791
+ const nextChar = text[match.index + match[0].length];
33792
+ if (nextChar !== void 0 && /[A-Za-z0-9]/.test(nextChar))
33793
+ continue;
33794
+ const weekResetsAt = parseResetDateTime(resetStr, now);
33795
+ if (!weekResetsAt)
33796
+ continue;
33797
+ if (match.index >= bestIndex) {
33798
+ bestIndex = match.index;
33799
+ best = { pct, weekResetsAt };
33800
+ }
33801
+ }
33802
+ }
33803
+ return best;
33804
+ }
33805
+ var MONTHS = [
33806
+ "jan",
33807
+ "feb",
33808
+ "mar",
33809
+ "apr",
33810
+ "may",
33811
+ "jun",
33812
+ "jul",
33813
+ "aug",
33814
+ "sep",
33815
+ "oct",
33816
+ "nov",
33817
+ "dec"
33818
+ ];
33819
+ var TIME_TAIL = /,\s*(\d{1,2})(?::(\d{2}))?\s*(am|pm)(?:\s*\(?UTC\)?)?\s*$/i;
33820
+ var TIME_ONLY = /^(\d{1,2})(?::(\d{2}))?\s*(am|pm)(?:\s*\(?UTC\)?)?$/i;
33737
33821
  var MS_PER_DAY = 24 * 60 * 60 * 1e3;
33822
+ function parseAmPm(hourStr, minStr, ampm) {
33823
+ const rawHour = Number.parseInt(hourStr, 10);
33824
+ if (!Number.isFinite(rawHour) || rawHour < 1 || rawHour > 12)
33825
+ return null;
33826
+ let minute = 0;
33827
+ if (minStr) {
33828
+ minute = Number.parseInt(minStr, 10);
33829
+ if (!Number.isFinite(minute) || minute < 0 || minute > 59)
33830
+ return null;
33831
+ }
33832
+ const isPm = ampm.toLowerCase() === "pm";
33833
+ return { hour: rawHour % 12 + (isPm ? 12 : 0), minute };
33834
+ }
33835
+ function parseResetDateTime(humanDate, now) {
33836
+ const trimmed = humanDate.trim();
33837
+ const timeOnly = trimmed.match(TIME_ONLY);
33838
+ if (timeOnly) {
33839
+ const hm = parseAmPm(timeOnly[1], timeOnly[2], timeOnly[3]);
33840
+ if (!hm)
33841
+ return null;
33842
+ const todayAt = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), hm.hour, hm.minute);
33843
+ return new Date(todayAt <= now.getTime() ? todayAt + MS_PER_DAY : todayAt);
33844
+ }
33845
+ const timeMatch = trimmed.match(TIME_TAIL);
33846
+ const dateOnly = timeMatch ? trimmed.slice(0, timeMatch.index).trim() : trimmed;
33847
+ const parts = dateOnly.split(/\s+/);
33848
+ if (parts.length !== 2)
33849
+ return null;
33850
+ const month = MONTHS.indexOf(parts[0].slice(0, 3).toLowerCase());
33851
+ if (month < 0)
33852
+ return null;
33853
+ const day = Number.parseInt(parts[1], 10);
33854
+ if (!Number.isFinite(day) || day < 1 || day > 31)
33855
+ return null;
33856
+ let hour = 0;
33857
+ let minute = 0;
33858
+ if (timeMatch) {
33859
+ const hm = parseAmPm(timeMatch[1], timeMatch[2], timeMatch[3]);
33860
+ if (!hm)
33861
+ return null;
33862
+ hour = hm.hour;
33863
+ minute = hm.minute;
33864
+ }
33865
+ const baseYear = now.getUTCFullYear();
33866
+ let resolved = null;
33867
+ let bestDelta = Number.POSITIVE_INFINITY;
33868
+ for (const y of [baseYear - 1, baseYear, baseYear + 1]) {
33869
+ const candidate = new Date(Date.UTC(y, month, day, hour, minute));
33870
+ const delta = Math.abs(candidate.getTime() - now.getTime());
33871
+ if (delta < bestDelta) {
33872
+ bestDelta = delta;
33873
+ resolved = candidate;
33874
+ }
33875
+ }
33876
+ return resolved;
33877
+ }
33738
33878
 
33739
33879
  // ../core/dist/claude-code-usage/usage-limit-marker.js
33740
33880
  var USAGE_LIMIT_MARKER_FILENAME = "claude-usage-limit.json";
@@ -33779,6 +33919,101 @@ var UNKNOWN_RATE_LIMIT = Object.freeze({
33779
33919
  resetsAt: null,
33780
33920
  text: null
33781
33921
  });
33922
+ function contentText(record2) {
33923
+ const candidates = [record2.content];
33924
+ const message = record2.message;
33925
+ if (typeof message === "object" && message !== null) {
33926
+ candidates.push(message.content);
33927
+ }
33928
+ const parts = [];
33929
+ for (const candidate of candidates) {
33930
+ if (typeof candidate === "string") {
33931
+ if (candidate)
33932
+ parts.push(candidate);
33933
+ continue;
33934
+ }
33935
+ if (!Array.isArray(candidate))
33936
+ continue;
33937
+ for (const block of candidate) {
33938
+ if (typeof block === "string") {
33939
+ if (block)
33940
+ parts.push(block);
33941
+ continue;
33942
+ }
33943
+ if (typeof block !== "object" || block === null)
33944
+ continue;
33945
+ const text = block.text;
33946
+ if (typeof text === "string" && text)
33947
+ parts.push(text);
33948
+ }
33949
+ }
33950
+ const joined = parts.join("\n").trim();
33951
+ return joined ? joined : null;
33952
+ }
33953
+ function classifyTranscriptLine(line, startMs, endMs, now) {
33954
+ const trimmed = line.trim();
33955
+ if (!trimmed)
33956
+ return null;
33957
+ let obj;
33958
+ try {
33959
+ obj = JSON.parse(trimmed);
33960
+ } catch {
33961
+ return null;
33962
+ }
33963
+ if (typeof obj !== "object" || obj === null)
33964
+ return null;
33965
+ const record2 = obj;
33966
+ if (record2.type !== "assistant")
33967
+ return null;
33968
+ const ts = record2.timestamp;
33969
+ if (typeof ts !== "string" || !ts)
33970
+ return null;
33971
+ const tsMs = new Date(ts).getTime();
33972
+ if (!Number.isFinite(tsMs) || tsMs < startMs || tsMs > endMs)
33973
+ return null;
33974
+ if (record2.error === "rate_limit" || record2.apiErrorStatus === 429) {
33975
+ const text = contentText(record2);
33976
+ const observation = text ? parseUsageBanner(text, now ?? new Date(endMs)) : null;
33977
+ return { verdict: "capped", atMs: tsMs, resetsAt: observation?.weekResetsAt ?? null, text };
33978
+ }
33979
+ if (record2.isApiErrorMessage === true)
33980
+ return null;
33981
+ const message = record2.message;
33982
+ if (typeof message !== "object" || message === null)
33983
+ return null;
33984
+ const msg = message;
33985
+ if (msg.model === "<synthetic>")
33986
+ return null;
33987
+ const usage = msg.usage;
33988
+ if (typeof usage !== "object" || usage === null)
33989
+ return null;
33990
+ const u = usage;
33991
+ const spent = Number(u.input_tokens ?? 0) + Number(u.output_tokens ?? 0) + Number(u.cache_creation_input_tokens ?? 0) + Number(u.cache_read_input_tokens ?? 0);
33992
+ if (!Number.isFinite(spent) || spent <= 0)
33993
+ return null;
33994
+ return { verdict: "serving", atMs: tsMs, resetsAt: null, text: null };
33995
+ }
33996
+ function pickNewerClassification(current, next) {
33997
+ if (next.verdict === "unknown")
33998
+ return current;
33999
+ if (current.verdict === "unknown")
34000
+ return next;
34001
+ return next.atMs >= current.atMs ? next : current;
34002
+ }
34003
+ function classifyTranscriptRateLimit(jsonl, startMs, endMs, now) {
34004
+ let newest = UNKNOWN_RATE_LIMIT;
34005
+ for (const line of jsonl.split("\n")) {
34006
+ const classified = classifyTranscriptLine(line, startMs, endMs, now);
34007
+ if (classified)
34008
+ newest = pickNewerClassification(newest, classified);
34009
+ }
34010
+ return newest;
34011
+ }
34012
+
34013
+ // ../core/dist/claude-code-usage/transcript-location.js
34014
+ function encodeClaudeProjectPath(projectDir) {
34015
+ return "-" + projectDir.replace(/^\//, "").replace(/[/.]/g, "-");
34016
+ }
33782
34017
 
33783
34018
  // ../core/dist/account-enforcement/marker.js
33784
34019
  var ACCOUNT_ENFORCEMENT_MARKER_FILENAME = "account-enforcement.json";
@@ -36309,11 +36544,102 @@ function emitToolCallMarkupRedactionTelemetry(channel) {
36309
36544
  }
36310
36545
  }
36311
36546
 
36547
+ // src/rate-limit-watch.ts
36548
+ import { readFileSync as readFileSync6, readdirSync as readdirSync2, statSync } from "fs";
36549
+ import { homedir as homedir5 } from "os";
36550
+ import { join as join7 } from "path";
36551
+ var DEFAULT_WATCH_MS = 5e3;
36552
+ var DEFAULT_POLL_MS = 400;
36553
+ function agentTranscriptDir(opts) {
36554
+ const cwd = opts?.cwd ?? process.cwd();
36555
+ const home = opts?.home ?? homedir5();
36556
+ return join7(home, ".claude", "projects", encodeClaudeProjectPath(cwd));
36557
+ }
36558
+ function classifyTranscriptSince(opts) {
36559
+ const dir = opts.transcriptDir ?? agentTranscriptDir({ cwd: opts.cwd, home: opts.home });
36560
+ let entries;
36561
+ try {
36562
+ entries = readdirSync2(dir);
36563
+ } catch {
36564
+ return UNKNOWN_RATE_LIMIT;
36565
+ }
36566
+ let newest = UNKNOWN_RATE_LIMIT;
36567
+ for (const name of entries) {
36568
+ if (!name.endsWith(".jsonl")) continue;
36569
+ const path = join7(dir, name);
36570
+ try {
36571
+ const st = statSync(path);
36572
+ if (!st.isFile() || st.mtimeMs < opts.sinceMs) continue;
36573
+ } catch {
36574
+ continue;
36575
+ }
36576
+ let content;
36577
+ try {
36578
+ content = readFileSync6(path, "utf-8");
36579
+ } catch {
36580
+ continue;
36581
+ }
36582
+ newest = pickNewerClassification(
36583
+ newest,
36584
+ classifyTranscriptRateLimit(content, opts.sinceMs, opts.nowMs, new Date(opts.nowMs))
36585
+ );
36586
+ }
36587
+ return newest;
36588
+ }
36589
+ var sleep = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
36590
+ async function watchForRateLimitRefusal(opts) {
36591
+ const now = opts.now ?? (() => Date.now());
36592
+ const wait = opts.wait ?? sleep;
36593
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_WATCH_MS;
36594
+ const pollMs = opts.pollMs ?? DEFAULT_POLL_MS;
36595
+ const deadline = now() + timeoutMs;
36596
+ for (; ; ) {
36597
+ let result;
36598
+ try {
36599
+ result = classifyTranscriptSince({
36600
+ sinceMs: opts.sinceMs,
36601
+ nowMs: now(),
36602
+ transcriptDir: opts.transcriptDir,
36603
+ cwd: opts.cwd,
36604
+ home: opts.home
36605
+ });
36606
+ } catch {
36607
+ return null;
36608
+ }
36609
+ if (result.verdict === "capped") return result;
36610
+ if (result.verdict === "serving") return null;
36611
+ if (now() >= deadline) return null;
36612
+ await wait(pollMs);
36613
+ }
36614
+ }
36615
+
36616
+ // src/usage-limit-reactive-decision.ts
36617
+ import { createHash } from "crypto";
36618
+ function shouldReadPredictiveMarker(mode) {
36619
+ return mode !== "enforce";
36620
+ }
36621
+ function armedWatchMode(opts) {
36622
+ if (opts.mode === "off") return null;
36623
+ if (opts.isBot || !opts.replyOwed) return null;
36624
+ return opts.mode;
36625
+ }
36626
+ function decideRefusalAction(opts) {
36627
+ const { refusal } = opts;
36628
+ if (!refusal || refusal.verdict !== "capped") return "none";
36629
+ if (!refusal.resetsAt) return "missing-reset";
36630
+ return opts.mode === "shadow" ? "shadow-log" : "notify";
36631
+ }
36632
+ function describeUnparsedRefusal(text) {
36633
+ if (!text) return "refusal=absent";
36634
+ const hash = createHash("sha256").update(text).digest("hex").slice(0, 12);
36635
+ return `refusal_hash=${hash} refusal_len=${text.length}`;
36636
+ }
36637
+
36312
36638
  // src/reply-intent-runtime.ts
36313
36639
  import { execFile as execFile2 } from "child_process";
36314
36640
  import { existsSync as existsSync3, mkdirSync, writeFileSync as writeFileSync2 } from "fs";
36315
- import { homedir as homedir5 } from "os";
36316
- import { join as join7 } from "path";
36641
+ import { homedir as homedir6 } from "os";
36642
+ import { join as join8 } from "path";
36317
36643
  var DEFAULT_CLAUDE_EVAL_MODEL = "claude-haiku-4-5-20251001";
36318
36644
  var DEFAULT_ANTHROPIC_MESSAGES_URL = "https://api.anthropic.com/v1/messages";
36319
36645
  var ANTHROPIC_API_VERSION = "2023-06-01";
@@ -36412,12 +36738,12 @@ async function runAnthropicMessages(prompt, opts) {
36412
36738
  var emptyMcpConfigPath = null;
36413
36739
  function ensureEmptyMcpConfig() {
36414
36740
  if (emptyMcpConfigPath && existsSync3(emptyMcpConfigPath)) return emptyMcpConfigPath;
36415
- const dir = join7(homedir5(), ".augmented");
36741
+ const dir = join8(homedir6(), ".augmented");
36416
36742
  try {
36417
36743
  mkdirSync(dir, { recursive: true });
36418
36744
  } catch {
36419
36745
  }
36420
- const p2 = join7(dir, ".reply-intent-empty-mcp.json");
36746
+ const p2 = join8(dir, ".reply-intent-empty-mcp.json");
36421
36747
  writeFileSync2(p2, JSON.stringify({ mcpServers: {} }));
36422
36748
  emptyMcpConfigPath = p2;
36423
36749
  return p2;
@@ -36442,7 +36768,7 @@ function runClaudeP(prompt, model) {
36442
36768
  execFile2(
36443
36769
  "claude",
36444
36770
  args,
36445
- { cwd: homedir5(), timeout: CLASSIFY_TIMEOUT_MS, maxBuffer: 1 << 20 },
36771
+ { cwd: homedir6(), timeout: CLASSIFY_TIMEOUT_MS, maxBuffer: 1 << 20 },
36446
36772
  (err, stdout) => {
36447
36773
  if (err) {
36448
36774
  reject(err);
@@ -36564,8 +36890,8 @@ function emitTransientApiErrorTelemetry(channel, match, original) {
36564
36890
  }
36565
36891
 
36566
36892
  // src/slack-pending-inbound-cleanup.ts
36567
- import { existsSync as existsSync4, readdirSync as readdirSync2, statSync, unlinkSync } from "fs";
36568
- import { join as join8 } from "path";
36893
+ import { existsSync as existsSync4, readdirSync as readdirSync3, statSync as statSync2, unlinkSync } from "fs";
36894
+ import { join as join9 } from "path";
36569
36895
  function sanitizeMarkerSegment(value) {
36570
36896
  return value.replace(/[^A-Za-z0-9_-]/g, "_");
36571
36897
  }
@@ -36579,9 +36905,9 @@ function applyToMatchingMarkers(dir, prefix, suffix, op) {
36579
36905
  if (!dir) return 0;
36580
36906
  let applied = 0;
36581
36907
  try {
36582
- for (const f of readdirSync2(dir)) {
36908
+ for (const f of readdirSync3(dir)) {
36583
36909
  if (!f.startsWith(prefix) || !f.endsWith(suffix)) continue;
36584
- op(join8(dir, f));
36910
+ op(join9(dir, f));
36585
36911
  applied += 1;
36586
36912
  }
36587
36913
  } catch {
@@ -36610,11 +36936,11 @@ function clearOldestSlackPendingMarkerInChannel(dir, channel, clear = defaultCle
36610
36936
  if (!dir) return null;
36611
36937
  const channelPrefix = `${sanitizeMarkerSegment(channel)}__`;
36612
36938
  try {
36613
- const entries = readdirSync2(dir).filter((f) => f.startsWith(channelPrefix) && f.endsWith(".json")).map((f) => {
36614
- const full = join8(dir, f);
36939
+ const entries = readdirSync3(dir).filter((f) => f.startsWith(channelPrefix) && f.endsWith(".json")).map((f) => {
36940
+ const full = join9(dir, f);
36615
36941
  let mtime = 0;
36616
36942
  try {
36617
- mtime = statSync(full).mtimeMs;
36943
+ mtime = statSync2(full).mtimeMs;
36618
36944
  } catch {
36619
36945
  }
36620
36946
  return { name: f, full, mtime };
@@ -36630,12 +36956,12 @@ function clearOldestSlackPendingMarkerInChannel(dir, channel, clear = defaultCle
36630
36956
 
36631
36957
  // src/recovery-ledger.ts
36632
36958
  import { existsSync as existsSync5, unlinkSync as unlinkSync2 } from "fs";
36633
- import { join as join9 } from "path";
36959
+ import { join as join10 } from "path";
36634
36960
  function recoveryLedgerEntryExists(ledgerDir, markerName, exists = (p2) => existsSync5(p2)) {
36635
36961
  if (!ledgerDir || !markerName) return false;
36636
36962
  if (markerName.includes("/") || markerName.includes("\\") || markerName.includes("..")) return false;
36637
36963
  try {
36638
- return exists(join9(ledgerDir, markerName));
36964
+ return exists(join10(ledgerDir, markerName));
36639
36965
  } catch {
36640
36966
  return false;
36641
36967
  }
@@ -36646,7 +36972,7 @@ function removeRecoveryLedgerEntry(ledgerDir, markerName, unlink = (p2) => {
36646
36972
  if (!ledgerDir || !markerName) return;
36647
36973
  if (markerName.includes("/") || markerName.includes("\\") || markerName.includes("..")) return;
36648
36974
  try {
36649
- unlink(join9(ledgerDir, markerName));
36975
+ unlink(join10(ledgerDir, markerName));
36650
36976
  } catch {
36651
36977
  }
36652
36978
  }
@@ -36883,18 +37209,18 @@ function applyHotThreadGuard(input) {
36883
37209
  }
36884
37210
 
36885
37211
  // src/slack-hot-thread-telemetry.ts
36886
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "fs";
36887
- import { join as join10 } from "path";
37212
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync3 } from "fs";
37213
+ import { join as join11 } from "path";
36888
37214
  var HOT_THREAD_CLASSIFICATION_COUNTER_SUFFIX = "-hot-thread-classifications.json";
36889
37215
  function hotThreadKey(mode, outcome, proactive) {
36890
37216
  return `${mode}|${outcome}|${proactive ? "true" : "false"}`;
36891
37217
  }
36892
37218
  function recordHotThreadClassification(agentDir, channel, classification) {
36893
37219
  if (!agentDir || !channel) return;
36894
- const path = join10(agentDir, `${channel}${HOT_THREAD_CLASSIFICATION_COUNTER_SUFFIX}`);
37220
+ const path = join11(agentDir, `${channel}${HOT_THREAD_CLASSIFICATION_COUNTER_SUFFIX}`);
36895
37221
  let counts = {};
36896
37222
  try {
36897
- const parsed = JSON.parse(readFileSync6(path, "utf-8"));
37223
+ const parsed = JSON.parse(readFileSync7(path, "utf-8"));
36898
37224
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
36899
37225
  for (const [k, v] of Object.entries(parsed)) {
36900
37226
  if (typeof v === "number" && Number.isInteger(v) && v >= 0) counts[k] = v;
@@ -36911,7 +37237,7 @@ function recordHotThreadClassification(agentDir, channel, classification) {
36911
37237
  }
36912
37238
 
36913
37239
  // src/restart-confirm.ts
36914
- import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync7, renameSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "fs";
37240
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync8, renameSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "fs";
36915
37241
  import { dirname } from "path";
36916
37242
  import { randomUUID } from "crypto";
36917
37243
  var RESTART_CONFIRM_MAX_AGE_MS = 10 * 60 * 1e3;
@@ -36937,7 +37263,7 @@ function writeRestartConfirmMarker(filePath, marker) {
36937
37263
  function readRestartConfirmMarker(filePath) {
36938
37264
  try {
36939
37265
  if (!existsSync6(filePath)) return null;
36940
- const parsed = JSON.parse(readFileSync7(filePath, "utf8"));
37266
+ const parsed = JSON.parse(readFileSync8(filePath, "utf8"));
36941
37267
  if (!parsed || typeof parsed !== "object") return null;
36942
37268
  return parsed;
36943
37269
  } catch {
@@ -37082,21 +37408,21 @@ import {
37082
37408
  ftruncateSync,
37083
37409
  mkdirSync as mkdirSync9,
37084
37410
  openSync,
37085
- readFileSync as readFileSync19,
37086
- readdirSync as readdirSync5,
37411
+ readFileSync as readFileSync20,
37412
+ readdirSync as readdirSync6,
37087
37413
  renameSync as renameSync5,
37088
- statSync as statSync3,
37414
+ statSync as statSync4,
37089
37415
  unlinkSync as unlinkSync7,
37090
37416
  watch,
37091
37417
  writeFileSync as writeFileSync14,
37092
37418
  writeSync
37093
37419
  } from "fs";
37094
- import { basename, join as join19, resolve as resolve2 } from "path";
37095
- import { homedir as homedir6 } from "os";
37096
- import { createHash as createHash2, randomUUID as randomUUID2 } from "crypto";
37420
+ import { basename, join as join20, resolve as resolve2 } from "path";
37421
+ import { homedir as homedir7 } from "os";
37422
+ import { createHash as createHash3, randomUUID as randomUUID2 } from "crypto";
37097
37423
 
37098
37424
  // src/slack-thread-store.ts
37099
- import { mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
37425
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
37100
37426
  import { dirname as dirname2 } from "path";
37101
37427
  function isParticipatingThread(entry) {
37102
37428
  if (!entry) return false;
@@ -37111,7 +37437,7 @@ function loadThreadStore(filePath, opts = {}) {
37111
37437
  const ttlMs = ttlDays * 24 * 60 * 60 * 1e3;
37112
37438
  let raw;
37113
37439
  try {
37114
- raw = readFileSync8(filePath, "utf-8");
37440
+ raw = readFileSync9(filePath, "utf-8");
37115
37441
  } catch {
37116
37442
  return { threads: /* @__PURE__ */ new Map(), pruned: 0 };
37117
37443
  }
@@ -37212,7 +37538,7 @@ function isThreadEntry(value) {
37212
37538
  }
37213
37539
 
37214
37540
  // src/dm-restart-notice.ts
37215
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync9, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "fs";
37541
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync10, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "fs";
37216
37542
  import { dirname as dirname3 } from "path";
37217
37543
  var RECENT_DM_VERSION = 1;
37218
37544
  var DEFAULT_RECENT_DM_TTL_MS = 30 * 60 * 1e3;
@@ -37236,7 +37562,7 @@ function loadRecentDms(filePath, opts = {}) {
37236
37562
  const ttlMs = opts.ttlMs ?? DEFAULT_RECENT_DM_TTL_MS;
37237
37563
  let raw;
37238
37564
  try {
37239
- raw = readFileSync9(filePath, "utf-8");
37565
+ raw = readFileSync10(filePath, "utf-8");
37240
37566
  } catch (err) {
37241
37567
  const code = err.code;
37242
37568
  if (code !== "ENOENT") {
@@ -37321,7 +37647,7 @@ var CHANNEL_ADD_RESTART_MAX_AGE_MS = 15 * 60 * 1e3;
37321
37647
  function readChannelAddRestartMarker(filePath) {
37322
37648
  let raw;
37323
37649
  try {
37324
- raw = readFileSync9(filePath, "utf-8");
37650
+ raw = readFileSync10(filePath, "utf-8");
37325
37651
  } catch {
37326
37652
  return null;
37327
37653
  }
@@ -37379,13 +37705,13 @@ async function runOrRetry(fn, opts) {
37379
37705
  }
37380
37706
 
37381
37707
  // src/turn-initiator-marker.ts
37382
- import { writeFileSync as writeFileSync7, readFileSync as readFileSync10, mkdirSync as mkdirSync5, renameSync as renameSync2 } from "fs";
37383
- import { dirname as dirname4, join as join11 } from "path";
37708
+ import { writeFileSync as writeFileSync7, readFileSync as readFileSync11, mkdirSync as mkdirSync5, renameSync as renameSync2 } from "fs";
37709
+ import { dirname as dirname4, join as join12 } from "path";
37384
37710
  var TURN_INITIATOR_MAX_AGE_MS = 5 * 60 * 1e3;
37385
37711
  var TURN_INITIATOR_LEDGER_MAX_ENTRIES = 20;
37386
37712
  var TURN_INITIATOR_LEDGER_FILENAME = ".turn-initiator-ledger.json";
37387
37713
  function turnInitiatorLedgerPath(singleSlotFile) {
37388
- return join11(dirname4(singleSlotFile), TURN_INITIATOR_LEDGER_FILENAME);
37714
+ return join12(dirname4(singleSlotFile), TURN_INITIATOR_LEDGER_FILENAME);
37389
37715
  }
37390
37716
  function foldTurnInitiatorLedger(existing, marker, maxAgeMs = TURN_INITIATOR_MAX_AGE_MS, maxEntries = TURN_INITIATOR_LEDGER_MAX_ENTRIES) {
37391
37717
  const now = marker.ts;
@@ -37410,7 +37736,7 @@ function updateTurnInitiatorLedger(singleSlotFile, marker) {
37410
37736
  const ledgerFile = turnInitiatorLedgerPath(singleSlotFile);
37411
37737
  let existing = null;
37412
37738
  try {
37413
- const parsed = JSON.parse(readFileSync10(ledgerFile, "utf8"));
37739
+ const parsed = JSON.parse(readFileSync11(ledgerFile, "utf8"));
37414
37740
  if (parsed && parsed.v === 1 && Array.isArray(parsed.entries)) existing = parsed;
37415
37741
  } catch {
37416
37742
  }
@@ -37437,7 +37763,7 @@ function writeTurnInitiatorMarker(input) {
37437
37763
  }
37438
37764
 
37439
37765
  // src/slack-bot-photo.ts
37440
- import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
37766
+ import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "fs";
37441
37767
  import { dirname as dirname5 } from "path";
37442
37768
  async function applyBotPhoto(opts) {
37443
37769
  const fetchImpl = opts.fetchImpl ?? fetch;
@@ -37447,7 +37773,7 @@ async function applyBotPhoto(opts) {
37447
37773
  const { token, avatarUrl, markerPath } = opts;
37448
37774
  if (markerPath && existsSync7(markerPath)) {
37449
37775
  try {
37450
- if (readFileSync11(markerPath, "utf-8").trim() === avatarUrl) {
37776
+ if (readFileSync12(markerPath, "utf-8").trim() === avatarUrl) {
37451
37777
  return { status: "skipped-unchanged" };
37452
37778
  }
37453
37779
  } catch {
@@ -37572,8 +37898,8 @@ function conversationalLaneMeta(expectsReply = true) {
37572
37898
  }
37573
37899
 
37574
37900
  // src/inbound-lane-telemetry.ts
37575
- import { readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
37576
- import { join as join12 } from "path";
37901
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
37902
+ import { join as join13 } from "path";
37577
37903
  var LANE_CLASSIFICATION_COUNTER_SUFFIX = "-lane-classifications.json";
37578
37904
  var SUSPECTED_MISCLASSIFICATION_KEY = "suspected_misclassification";
37579
37905
  var HUMAN_CHANNEL_SOURCES = /* @__PURE__ */ new Set([
@@ -37590,10 +37916,10 @@ function isSuspectedMisclassification(lane, source) {
37590
37916
  }
37591
37917
  function recordLaneClassification(agentDir, channel, classification) {
37592
37918
  if (!agentDir) return;
37593
- const path = join12(agentDir, `${channel}${LANE_CLASSIFICATION_COUNTER_SUFFIX}`);
37919
+ const path = join13(agentDir, `${channel}${LANE_CLASSIFICATION_COUNTER_SUFFIX}`);
37594
37920
  let counts = {};
37595
37921
  try {
37596
- const parsed = JSON.parse(readFileSync12(path, "utf-8"));
37922
+ const parsed = JSON.parse(readFileSync13(path, "utf-8"));
37597
37923
  if (parsed && typeof parsed === "object") counts = parsed;
37598
37924
  } catch {
37599
37925
  }
@@ -37609,8 +37935,8 @@ function recordLaneClassification(agentDir, channel, classification) {
37609
37935
  }
37610
37936
 
37611
37937
  // src/slack-inbound-registry.ts
37612
- import { readdirSync as readdirSync3, readFileSync as readFileSync13 } from "fs";
37613
- import { join as join13 } from "path";
37938
+ import { readdirSync as readdirSync4, readFileSync as readFileSync14 } from "fs";
37939
+ import { join as join14 } from "path";
37614
37940
  var DEFAULT_MAX_ENTRIES = 500;
37615
37941
  var DEFAULT_CLEARED_TTL_MS = 6 * 60 * 60 * 1e3;
37616
37942
  function entryKey(channel, messageTs) {
@@ -37722,7 +38048,7 @@ function createInboundRegistry(opts = {}) {
37722
38048
  function seedFromMarkerDir(dir) {
37723
38049
  let names;
37724
38050
  try {
37725
- names = readdirSync3(dir);
38051
+ names = readdirSync4(dir);
37726
38052
  } catch {
37727
38053
  return;
37728
38054
  }
@@ -37731,7 +38057,7 @@ function createInboundRegistry(opts = {}) {
37731
38057
  if (name.includes(".retry-") || name.includes(".poison")) continue;
37732
38058
  let marker;
37733
38059
  try {
37734
- marker = JSON.parse(readFileSync13(join13(dir, name), "utf-8"));
38060
+ marker = JSON.parse(readFileSync14(join14(dir, name), "utf-8"));
37735
38061
  } catch {
37736
38062
  continue;
37737
38063
  }
@@ -37768,16 +38094,16 @@ function createInboundRegistry(opts = {}) {
37768
38094
  }
37769
38095
 
37770
38096
  // src/slack-inbound-id.ts
37771
- import { createHash } from "crypto";
38097
+ import { createHash as createHash2 } from "crypto";
37772
38098
  var INBOUND_ID_HEX_LEN = 12;
37773
38099
  function slackInboundId(channel, threadTs, messageTs) {
37774
- const digest = createHash("sha256").update(`${channel}|${threadTs}|${messageTs}`).digest("hex").slice(0, INBOUND_ID_HEX_LEN);
38100
+ const digest = createHash2("sha256").update(`${channel}|${threadTs}|${messageTs}`).digest("hex").slice(0, INBOUND_ID_HEX_LEN);
37775
38101
  return `ib_${digest}`;
37776
38102
  }
37777
38103
 
37778
38104
  // src/inbound-delivery-ledger.ts
37779
- import { existsSync as existsSync8, mkdirSync as mkdirSync7, readdirSync as readdirSync4, readFileSync as readFileSync14, renameSync as renameSync3, writeFileSync as writeFileSync10 } from "fs";
37780
- import { join as join14 } from "path";
38105
+ import { existsSync as existsSync8, mkdirSync as mkdirSync7, readdirSync as readdirSync5, readFileSync as readFileSync15, renameSync as renameSync3, writeFileSync as writeFileSync10 } from "fs";
38106
+ import { join as join15 } from "path";
37781
38107
  function safeInboundId(inboundId) {
37782
38108
  return inboundId.replace(/[^A-Za-z0-9_-]/g, "_");
37783
38109
  }
@@ -37785,8 +38111,8 @@ var defaultDeps = {
37785
38111
  mkdir: (dir) => mkdirSync7(dir, { recursive: true }),
37786
38112
  writeFile: (path, data) => writeFileSync10(path, data, "utf8"),
37787
38113
  rename: (from, to) => renameSync3(from, to),
37788
- readdir: (dir) => readdirSync4(dir),
37789
- readFile: (path) => readFileSync14(path, "utf8"),
38114
+ readdir: (dir) => readdirSync5(dir),
38115
+ readFile: (path) => readFileSync15(path, "utf8"),
37790
38116
  exists: (path) => existsSync8(path)
37791
38117
  };
37792
38118
  function writeInboundDeliveryLedgerEntry(dir, record2, deps = defaultDeps) {
@@ -37795,7 +38121,7 @@ function writeInboundDeliveryLedgerEntry(dir, record2, deps = defaultDeps) {
37795
38121
  if (!safe || safe.includes("/") || safe.includes("\\") || safe.includes("..")) return;
37796
38122
  try {
37797
38123
  deps.mkdir(dir);
37798
- const final = join14(dir, `${safe}.json`);
38124
+ const final = join15(dir, `${safe}.json`);
37799
38125
  const tmp = `${final}.tmp`;
37800
38126
  deps.writeFile(tmp, JSON.stringify(record2));
37801
38127
  deps.rename(tmp, final);
@@ -37951,8 +38277,8 @@ function describeChannelRedirect(input) {
37951
38277
  }
37952
38278
 
37953
38279
  // src/slack-reply-binding-telemetry.ts
37954
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "fs";
37955
- import { join as join15 } from "path";
38280
+ import { readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
38281
+ import { join as join16 } from "path";
37956
38282
  var REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX = "-reply-binding-classifications.json";
37957
38283
  var UNKNOWN_INBOUND_ID_KEY = "unknown_inbound_id";
37958
38284
  var CHANNEL_MISTARGET_CORRECTED_KEY = "channel_mistarget_corrected";
@@ -37967,10 +38293,10 @@ function slackReplyBindingMode() {
37967
38293
  }
37968
38294
  function recordReplyBindingClassification(agentDir, channel, input) {
37969
38295
  if (!agentDir) return;
37970
- const path = join15(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
38296
+ const path = join16(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
37971
38297
  let counts = {};
37972
38298
  try {
37973
- const parsed = JSON.parse(readFileSync15(path, "utf-8"));
38299
+ const parsed = JSON.parse(readFileSync16(path, "utf-8"));
37974
38300
  if (parsed && typeof parsed === "object") counts = parsed;
37975
38301
  } catch {
37976
38302
  }
@@ -37985,10 +38311,10 @@ function recordReplyBindingClassification(agentDir, channel, input) {
37985
38311
  }
37986
38312
  function recordScheduledChannelOverride(agentDir, channel, input) {
37987
38313
  if (!agentDir) return;
37988
- const path = join15(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
38314
+ const path = join16(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
37989
38315
  let counts = {};
37990
38316
  try {
37991
- const parsed = JSON.parse(readFileSync15(path, "utf-8"));
38317
+ const parsed = JSON.parse(readFileSync16(path, "utf-8"));
37992
38318
  if (parsed && typeof parsed === "object") counts = parsed;
37993
38319
  } catch {
37994
38320
  }
@@ -38001,10 +38327,10 @@ function recordScheduledChannelOverride(agentDir, channel, input) {
38001
38327
  }
38002
38328
  function recordChannelMistarget(agentDir, channel, input) {
38003
38329
  if (!agentDir) return;
38004
- const path = join15(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
38330
+ const path = join16(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
38005
38331
  let counts = {};
38006
38332
  try {
38007
- const parsed = JSON.parse(readFileSync15(path, "utf-8"));
38333
+ const parsed = JSON.parse(readFileSync16(path, "utf-8"));
38008
38334
  if (parsed && typeof parsed === "object") counts = parsed;
38009
38335
  } catch {
38010
38336
  }
@@ -38019,8 +38345,8 @@ function recordChannelMistarget(agentDir, channel, input) {
38019
38345
  }
38020
38346
 
38021
38347
  // src/slack-reply-target-telemetry.ts
38022
- import { readFileSync as readFileSync16, writeFileSync as writeFileSync12 } from "fs";
38023
- import { join as join16 } from "path";
38348
+ import { readFileSync as readFileSync17, writeFileSync as writeFileSync12 } from "fs";
38349
+ import { join as join17 } from "path";
38024
38350
  var REPLY_TARGET_CLASSIFICATION_COUNTER_SUFFIX = "-reply-target-classifications.json";
38025
38351
  function pendingThreadsBucket(n) {
38026
38352
  if (n <= 0) return "0";
@@ -38053,10 +38379,10 @@ function classifyReplyTarget(input) {
38053
38379
  }
38054
38380
  function recordReplyTargetClassification(agentDir, channel, classification) {
38055
38381
  if (!agentDir) return;
38056
- const path = join16(agentDir, `${channel}${REPLY_TARGET_CLASSIFICATION_COUNTER_SUFFIX}`);
38382
+ const path = join17(agentDir, `${channel}${REPLY_TARGET_CLASSIFICATION_COUNTER_SUFFIX}`);
38057
38383
  let counts = {};
38058
38384
  try {
38059
- const parsed = JSON.parse(readFileSync16(path, "utf-8"));
38385
+ const parsed = JSON.parse(readFileSync17(path, "utf-8"));
38060
38386
  if (parsed && typeof parsed === "object") counts = parsed;
38061
38387
  } catch {
38062
38388
  }
@@ -38072,8 +38398,8 @@ function recordReplyTargetClassification(agentDir, channel, classification) {
38072
38398
  }
38073
38399
 
38074
38400
  // src/scheduled-turn-marker.ts
38075
- import { readFileSync as readFileSync17, unlinkSync as unlinkSync5 } from "fs";
38076
- import { join as join17 } from "path";
38401
+ import { readFileSync as readFileSync18, unlinkSync as unlinkSync5 } from "fs";
38402
+ import { join as join18 } from "path";
38077
38403
  var SCHEDULED_TURN_MARKER_FILENAME2 = ".current-scheduled-turn.json";
38078
38404
  var SCHEDULED_TURN_MAX_AGE_MS = 15 * 60 * 1e3;
38079
38405
  function validateScheduledTurnMarker(raw, now, maxAgeMs = SCHEDULED_TURN_MAX_AGE_MS) {
@@ -38111,7 +38437,7 @@ function readScheduledTurnMarker(agentDir, now = Date.now()) {
38111
38437
  if (!agentDir) return null;
38112
38438
  try {
38113
38439
  const raw = JSON.parse(
38114
- readFileSync17(join17(agentDir, SCHEDULED_TURN_MARKER_FILENAME2), "utf8")
38440
+ readFileSync18(join18(agentDir, SCHEDULED_TURN_MARKER_FILENAME2), "utf8")
38115
38441
  );
38116
38442
  return validateScheduledTurnMarker(raw, now);
38117
38443
  } catch {
@@ -38121,7 +38447,7 @@ function readScheduledTurnMarker(agentDir, now = Date.now()) {
38121
38447
  function clearScheduledTurnMarker(agentDir) {
38122
38448
  if (!agentDir) return;
38123
38449
  try {
38124
- unlinkSync5(join17(agentDir, SCHEDULED_TURN_MARKER_FILENAME2));
38450
+ unlinkSync5(join18(agentDir, SCHEDULED_TURN_MARKER_FILENAME2));
38125
38451
  } catch {
38126
38452
  }
38127
38453
  }
@@ -38919,14 +39245,14 @@ async function actuateHostRestart(opts) {
38919
39245
  import {
38920
39246
  existsSync as existsSync9,
38921
39247
  mkdirSync as mkdirSync8,
38922
- readFileSync as readFileSync18,
39248
+ readFileSync as readFileSync19,
38923
39249
  renameSync as renameSync4,
38924
- statSync as statSync2,
39250
+ statSync as statSync3,
38925
39251
  unlinkSync as unlinkSync6,
38926
39252
  utimesSync,
38927
39253
  writeFileSync as writeFileSync13
38928
39254
  } from "fs";
38929
- import { join as join18 } from "path";
39255
+ import { join as join19 } from "path";
38930
39256
  var STALE_LOCK_MS = 9e4;
38931
39257
  var HEARTBEAT_INTERVAL_MS = 3e4;
38932
39258
  function defaultIsPidAlive(pid) {
@@ -38949,7 +39275,7 @@ function acquireMcpSpawnLock(args) {
38949
39275
  const nowMs = options.nowMs ?? (() => Date.now());
38950
39276
  const lockMtimeMs = options.lockMtimeMs ?? defaultLockMtimeMs;
38951
39277
  const staleMs = options.staleMs ?? STALE_LOCK_MS;
38952
- const path = join18(agentDir, basename2);
39278
+ const path = join19(agentDir, basename2);
38953
39279
  const existing = readLockHolder(path);
38954
39280
  if (existing) {
38955
39281
  if (existing.pid === selfPid) {
@@ -39008,7 +39334,7 @@ function startMcpSpawnLockHeartbeat(lockPath, opts = {}) {
39008
39334
  }
39009
39335
  function defaultLockMtimeMs(path) {
39010
39336
  try {
39011
- return statSync2(path).mtimeMs;
39337
+ return statSync3(path).mtimeMs;
39012
39338
  } catch {
39013
39339
  return null;
39014
39340
  }
@@ -39016,7 +39342,7 @@ function defaultLockMtimeMs(path) {
39016
39342
  function readLockHolder(path) {
39017
39343
  if (!existsSync9(path)) return null;
39018
39344
  try {
39019
- const raw = readFileSync18(path, "utf8");
39345
+ const raw = readFileSync19(path, "utf8");
39020
39346
  const parsed = JSON.parse(raw);
39021
39347
  const pid = typeof parsed.pid === "number" ? parsed.pid : Number(parsed.pid);
39022
39348
  if (!Number.isFinite(pid) || pid <= 0) return null;
@@ -39247,6 +39573,49 @@ async function maybeSendUsageLimitNotice(args) {
39247
39573
  clearTimeout(timeoutId);
39248
39574
  }
39249
39575
  }
39576
+ function armSlackUsageLimitWatch(args) {
39577
+ void (async () => {
39578
+ try {
39579
+ const refusal = await watchForRateLimitRefusal({ sinceMs: args.sinceMs });
39580
+ const action = decideRefusalAction({ mode: args.mode, refusal });
39581
+ if (action === "none") return;
39582
+ if (action === "missing-reset") {
39583
+ process.stderr.write(
39584
+ `slack-channel(${AGENT_CODE_NAME}): [usage-limit-reactive] mode=${args.mode} refusal detected for channel=${redactSlackId(args.channel)} but no reset time in it (${describeUnparsedRefusal(refusal?.text)}) - no notice
39585
+ `
39586
+ );
39587
+ return;
39588
+ }
39589
+ const resetsAt = refusal?.resetsAt;
39590
+ if (!resetsAt) return;
39591
+ if (action === "shadow-log") {
39592
+ process.stderr.write(
39593
+ `slack-channel(${AGENT_CODE_NAME}): [usage-limit-reactive] mode=shadow WOULD notify channel=${redactSlackId(args.channel)} ts=${redactSlackId(args.messageTs)} resets=${resetsAt.toISOString()}
39594
+ `
39595
+ );
39596
+ return;
39597
+ }
39598
+ await maybeSendUsageLimitNotice({
39599
+ channel: args.channel,
39600
+ senderId: args.senderId,
39601
+ threadTs: args.threadTs,
39602
+ limitedUntil: resetsAt
39603
+ });
39604
+ if (args.channel && args.messageTs) {
39605
+ clearSlackPendingMarkerByMessageTs2(args.channel, args.messageTs);
39606
+ }
39607
+ process.stderr.write(
39608
+ `slack-channel(${AGENT_CODE_NAME}): [usage-limit-reactive] reported refusal for channel=${redactSlackId(args.channel)} ts=${redactSlackId(args.messageTs)} resets=${resetsAt.toISOString()}
39609
+ `
39610
+ );
39611
+ } catch (err) {
39612
+ process.stderr.write(
39613
+ `slack-channel(${AGENT_CODE_NAME}): [usage-limit-reactive] watch failed for channel=${redactSlackId(args.channel)}: ${err.message}
39614
+ `
39615
+ );
39616
+ }
39617
+ })();
39618
+ }
39250
39619
  var SLACK_ACCOUNT_MUTE_NOTICE_CACHE = /* @__PURE__ */ new Map();
39251
39620
  async function maybeSendAccountMuteNotice(args) {
39252
39621
  if (!BOT_TOKEN) return;
@@ -39422,18 +39791,18 @@ var SLACK_TEAM_PEER_USER_IDS = parseTeamPeerUserIdsEnv(
39422
39791
  process.env.SLACK_TEAM_PEER_USER_IDS
39423
39792
  );
39424
39793
  var PEER_HINT_SEEN = /* @__PURE__ */ new Set();
39425
- var SLACK_AGENT_DIR = AGENT_CODE_NAME ? join19(homedir6(), ".augmented", AGENT_CODE_NAME) : null;
39426
- var SLACK_MCP_CONFIG_PATH = SLACK_AGENT_DIR ? join19(SLACK_AGENT_DIR, "project", ".mcp.json") : null;
39794
+ var SLACK_AGENT_DIR = AGENT_CODE_NAME ? join20(homedir7(), ".augmented", AGENT_CODE_NAME) : null;
39795
+ var SLACK_MCP_CONFIG_PATH = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "project", ".mcp.json") : null;
39427
39796
  var liveAllowedUsersCache = null;
39428
39797
  function readLiveAllowedUsers() {
39429
39798
  if (!SLACK_MCP_CONFIG_PATH) return null;
39430
39799
  try {
39431
- const mtimeMs = statSync3(SLACK_MCP_CONFIG_PATH).mtimeMs;
39800
+ const mtimeMs = statSync4(SLACK_MCP_CONFIG_PATH).mtimeMs;
39432
39801
  if (liveAllowedUsersCache && liveAllowedUsersCache.mtimeMs === mtimeMs) {
39433
39802
  return liveAllowedUsersCache.value;
39434
39803
  }
39435
39804
  const value = extractAllowedUsersFromMcpJson(
39436
- readFileSync19(SLACK_MCP_CONFIG_PATH, "utf-8")
39805
+ readFileSync20(SLACK_MCP_CONFIG_PATH, "utf-8")
39437
39806
  );
39438
39807
  if (value === null) return null;
39439
39808
  liveAllowedUsersCache = { mtimeMs, value };
@@ -39449,12 +39818,12 @@ var livePingAllowedUsersCache = null;
39449
39818
  function readLivePingAllowedUsers() {
39450
39819
  if (!SLACK_MCP_CONFIG_PATH) return null;
39451
39820
  try {
39452
- const mtimeMs = statSync3(SLACK_MCP_CONFIG_PATH).mtimeMs;
39821
+ const mtimeMs = statSync4(SLACK_MCP_CONFIG_PATH).mtimeMs;
39453
39822
  if (livePingAllowedUsersCache && livePingAllowedUsersCache.mtimeMs === mtimeMs) {
39454
39823
  return livePingAllowedUsersCache.value;
39455
39824
  }
39456
39825
  const value = extractPingAllowedUsersFromMcpJson(
39457
- readFileSync19(SLACK_MCP_CONFIG_PATH, "utf-8")
39826
+ readFileSync20(SLACK_MCP_CONFIG_PATH, "utf-8")
39458
39827
  );
39459
39828
  if (value === null) return null;
39460
39829
  livePingAllowedUsersCache = { mtimeMs, value };
@@ -39466,20 +39835,20 @@ function readLivePingAllowedUsers() {
39466
39835
  function getEffectivePingAllowedUsers() {
39467
39836
  return readLivePingAllowedUsers() ?? PING_ALLOWED_USERS;
39468
39837
  }
39469
- var SLACK_PENDING_INBOUND_DIR = SLACK_AGENT_DIR ? join19(SLACK_AGENT_DIR, "slack-pending-inbound") : null;
39470
- var SLACK_RESTART_CONTEXT_DIR = SLACK_AGENT_DIR ? join19(SLACK_AGENT_DIR, "slack-restart-context") : null;
39471
- var SLACK_RECOVERY_OUTBOX_DIR = SLACK_AGENT_DIR ? join19(SLACK_AGENT_DIR, "slack-recovery-outbox") : null;
39472
- var SLACK_RECOVERY_LEDGER_DIR = SLACK_AGENT_DIR ? join19(SLACK_AGENT_DIR, ".agt-slack-recovery-ledger") : null;
39473
- var SLACK_DELIVERY_LEDGER_DIR = SLACK_AGENT_DIR ? join19(SLACK_AGENT_DIR, ".agt-inbound-delivery-ledger") : null;
39838
+ var SLACK_PENDING_INBOUND_DIR = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-pending-inbound") : null;
39839
+ var SLACK_RESTART_CONTEXT_DIR = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-restart-context") : null;
39840
+ var SLACK_RECOVERY_OUTBOX_DIR = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-recovery-outbox") : null;
39841
+ var SLACK_RECOVERY_LEDGER_DIR = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, ".agt-slack-recovery-ledger") : null;
39842
+ var SLACK_DELIVERY_LEDGER_DIR = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, ".agt-inbound-delivery-ledger") : null;
39474
39843
  var slackInboundRegistry = createInboundRegistry();
39475
- var SLACK_RESTART_CONFIRM_FILE = SLACK_AGENT_DIR ? join19(SLACK_AGENT_DIR, "slack-restart-confirm.json") : null;
39476
- var SLACK_RECENT_DMS_FILE = SLACK_AGENT_DIR ? join19(SLACK_AGENT_DIR, "slack-recent-dms.json") : null;
39477
- var SLACK_CHANNEL_ADD_RESTART_FILE = SLACK_AGENT_DIR ? join19(SLACK_AGENT_DIR, "slack-channel-add-restart.json") : null;
39844
+ var SLACK_RESTART_CONFIRM_FILE = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-restart-confirm.json") : null;
39845
+ var SLACK_RECENT_DMS_FILE = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-recent-dms.json") : null;
39846
+ var SLACK_CHANNEL_ADD_RESTART_FILE = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-channel-add-restart.json") : null;
39478
39847
  var SLACK_MAX_RECOVERY_ATTEMPTS = 3;
39479
- var SLACK_AVATAR_MARKER_PATH = SLACK_AGENT_DIR ? join19(SLACK_AGENT_DIR, "slack-avatar-applied") : null;
39848
+ var SLACK_AVATAR_MARKER_PATH = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-avatar-applied") : null;
39480
39849
  function redactSlackId(id) {
39481
39850
  if (!id) return "<none>";
39482
- return createHash2("sha256").update(id).digest("hex").slice(0, 8);
39851
+ return createHash3("sha256").update(id).digest("hex").slice(0, 8);
39483
39852
  }
39484
39853
  function safeSlackMarkerName(channel, threadTs, messageTs) {
39485
39854
  const safe = (s) => s.replace(/[^A-Za-z0-9_-]/g, "_");
@@ -39487,7 +39856,7 @@ function safeSlackMarkerName(channel, threadTs, messageTs) {
39487
39856
  }
39488
39857
  function slackPendingInboundPath(channel, threadTs, messageTs) {
39489
39858
  if (!SLACK_PENDING_INBOUND_DIR) return null;
39490
- return join19(SLACK_PENDING_INBOUND_DIR, safeSlackMarkerName(channel, threadTs, messageTs));
39859
+ return join20(SLACK_PENDING_INBOUND_DIR, safeSlackMarkerName(channel, threadTs, messageTs));
39491
39860
  }
39492
39861
  function writeSlackPendingInboundMarker(channel, threadTs, messageTs, undeliverable = false, discretionary = false, payload) {
39493
39862
  const path = slackPendingInboundPath(channel, threadTs, messageTs);
@@ -39538,7 +39907,7 @@ function rewriteSlackMarkerInPlace(path, marker) {
39538
39907
  function markSlackMarkerSeenInPlace(fullPath) {
39539
39908
  let marker;
39540
39909
  try {
39541
- marker = JSON.parse(readFileSync19(fullPath, "utf-8"));
39910
+ marker = JSON.parse(readFileSync20(fullPath, "utf-8"));
39542
39911
  } catch {
39543
39912
  return;
39544
39913
  }
@@ -39552,7 +39921,7 @@ function attachSlackReplayPayload(channel, threadTs, messageTs, payload) {
39552
39921
  if (!path) return;
39553
39922
  let marker;
39554
39923
  try {
39555
- marker = JSON.parse(readFileSync19(path, "utf-8"));
39924
+ marker = JSON.parse(readFileSync20(path, "utf-8"));
39556
39925
  } catch {
39557
39926
  return;
39558
39927
  }
@@ -39563,7 +39932,7 @@ function readSlackPendingInboundMarker(channel, threadTs, messageTs) {
39563
39932
  const path = slackPendingInboundPath(channel, threadTs, messageTs);
39564
39933
  if (!path || !existsSync10(path)) return null;
39565
39934
  try {
39566
- return JSON.parse(readFileSync19(path, "utf-8"));
39935
+ return JSON.parse(readFileSync20(path, "utf-8"));
39567
39936
  } catch {
39568
39937
  return null;
39569
39938
  }
@@ -39679,7 +40048,7 @@ function scheduleBusyAck(channel, threadTs, messageTs, isThreadReply, arrivedWhi
39679
40048
  let paneLogFreshAgeMs = null;
39680
40049
  if (SLACK_AGENT_DIR) {
39681
40050
  try {
39682
- const paneMtimeMs = statSync3(join19(SLACK_AGENT_DIR, "pane.log")).mtimeMs;
40051
+ const paneMtimeMs = statSync4(join20(SLACK_AGENT_DIR, "pane.log")).mtimeMs;
39683
40052
  paneLogFreshAgeMs = Math.max(0, Date.now() - paneMtimeMs);
39684
40053
  } catch {
39685
40054
  }
@@ -39712,7 +40081,7 @@ function __resetSlackBusyAckNoticeThrottle() {
39712
40081
  function clearSlackMarkerFileWithHeal(fullPath) {
39713
40082
  let marker = null;
39714
40083
  try {
39715
- marker = JSON.parse(readFileSync19(fullPath, "utf-8"));
40084
+ marker = JSON.parse(readFileSync20(fullPath, "utf-8"));
39716
40085
  } catch {
39717
40086
  }
39718
40087
  if (marker && decideRecoveryHeal({
@@ -39730,7 +40099,7 @@ function clearSlackMarkerFileWithHeal(fullPath) {
39730
40099
  function markSlackMarkerSeenWithHeal(fullPath) {
39731
40100
  let marker = null;
39732
40101
  try {
39733
- marker = JSON.parse(readFileSync19(fullPath, "utf-8"));
40102
+ marker = JSON.parse(readFileSync20(fullPath, "utf-8"));
39734
40103
  } catch {
39735
40104
  return;
39736
40105
  }
@@ -39799,10 +40168,10 @@ function slackNextRetryName(filename) {
39799
40168
  async function processSlackRecoveryOutboxFile(filename) {
39800
40169
  if (!SLACK_RECOVERY_OUTBOX_DIR) return;
39801
40170
  if (filename.endsWith(".poison.json") || filename.endsWith(".tmp")) return;
39802
- const fullPath = join19(SLACK_RECOVERY_OUTBOX_DIR, filename);
40171
+ const fullPath = join20(SLACK_RECOVERY_OUTBOX_DIR, filename);
39803
40172
  let payload;
39804
40173
  try {
39805
- payload = JSON.parse(readFileSync19(fullPath, "utf-8"));
40174
+ payload = JSON.parse(readFileSync20(fullPath, "utf-8"));
39806
40175
  } catch (err) {
39807
40176
  process.stderr.write(
39808
40177
  `slack-channel(${AGENT_CODE_NAME}): recovery outbox parse failed (${filename}): ${err.message}
@@ -39906,7 +40275,7 @@ async function processSlackRecoveryOutboxFile(filename) {
39906
40275
  const next = slackNextRetryName(filename);
39907
40276
  if (next) {
39908
40277
  try {
39909
- renameSync5(fullPath, join19(SLACK_RECOVERY_OUTBOX_DIR, next.next));
40278
+ renameSync5(fullPath, join20(SLACK_RECOVERY_OUTBOX_DIR, next.next));
39910
40279
  if (next.attempt >= SLACK_MAX_RECOVERY_ATTEMPTS) {
39911
40280
  process.stderr.write(
39912
40281
  `slack-channel(${AGENT_CODE_NAME}): ghost-reply recovery exhausted retries \u2014 moved to ${next.next}
@@ -39937,7 +40306,7 @@ function scanSlackRecoveryRetries() {
39937
40306
  if (!SLACK_RECOVERY_OUTBOX_DIR) return;
39938
40307
  let entries;
39939
40308
  try {
39940
- entries = readdirSync5(SLACK_RECOVERY_OUTBOX_DIR);
40309
+ entries = readdirSync6(SLACK_RECOVERY_OUTBOX_DIR);
39941
40310
  } catch {
39942
40311
  return;
39943
40312
  }
@@ -39946,7 +40315,7 @@ function scanSlackRecoveryRetries() {
39946
40315
  if (!f.includes(".retry-") || f.endsWith(".poison.json")) continue;
39947
40316
  let mtimeMs;
39948
40317
  try {
39949
- mtimeMs = statSync3(join19(SLACK_RECOVERY_OUTBOX_DIR, f)).mtimeMs;
40318
+ mtimeMs = statSync4(join20(SLACK_RECOVERY_OUTBOX_DIR, f)).mtimeMs;
39950
40319
  } catch {
39951
40320
  continue;
39952
40321
  }
@@ -39967,7 +40336,7 @@ function startSlackRecoveryOutboxWatcher() {
39967
40336
  return;
39968
40337
  }
39969
40338
  try {
39970
- for (const f of readdirSync5(SLACK_RECOVERY_OUTBOX_DIR)) {
40339
+ for (const f of readdirSync6(SLACK_RECOVERY_OUTBOX_DIR)) {
39971
40340
  if (isFirstAttemptSlackOutboxFile(f)) void processSlackRecoveryOutboxFile(f);
39972
40341
  }
39973
40342
  } catch {
@@ -39976,7 +40345,7 @@ function startSlackRecoveryOutboxWatcher() {
39976
40345
  const watcher = watch(SLACK_RECOVERY_OUTBOX_DIR, (event, filename) => {
39977
40346
  if (event !== "rename" || !filename) return;
39978
40347
  if (!isFirstAttemptSlackOutboxFile(filename)) return;
39979
- if (existsSync10(join19(SLACK_RECOVERY_OUTBOX_DIR, filename))) {
40348
+ if (existsSync10(join20(SLACK_RECOVERY_OUTBOX_DIR, filename))) {
39980
40349
  void processSlackRecoveryOutboxFile(filename);
39981
40350
  }
39982
40351
  });
@@ -39991,7 +40360,7 @@ function startSlackRecoveryOutboxWatcher() {
39991
40360
  retryTimer.unref?.();
39992
40361
  }
39993
40362
  startSlackRecoveryOutboxWatcher();
39994
- var SLACK_NOTICE_OUTBOX_DIR = SLACK_AGENT_DIR ? join19(SLACK_AGENT_DIR, "slack-notice-outbox") : null;
40363
+ var SLACK_NOTICE_OUTBOX_DIR = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-notice-outbox") : null;
39995
40364
  var SLACK_NOTICE_MAX_AGE_MS = 9e4;
39996
40365
  var SLACK_NOTICE_INFLIGHT = /* @__PURE__ */ new Set();
39997
40366
  async function processSlackNoticeOutboxFile(filename) {
@@ -39999,11 +40368,11 @@ async function processSlackNoticeOutboxFile(filename) {
39999
40368
  if (filename.startsWith(".") || filename.endsWith(".tmp") || !filename.endsWith(".json")) return;
40000
40369
  if (SLACK_NOTICE_INFLIGHT.has(filename)) return;
40001
40370
  SLACK_NOTICE_INFLIGHT.add(filename);
40002
- const fullPath = join19(SLACK_NOTICE_OUTBOX_DIR, filename);
40371
+ const fullPath = join20(SLACK_NOTICE_OUTBOX_DIR, filename);
40003
40372
  try {
40004
40373
  let mtimeMs;
40005
40374
  try {
40006
- mtimeMs = statSync3(fullPath).mtimeMs;
40375
+ mtimeMs = statSync4(fullPath).mtimeMs;
40007
40376
  } catch {
40008
40377
  return;
40009
40378
  }
@@ -40016,7 +40385,7 @@ async function processSlackNoticeOutboxFile(filename) {
40016
40385
  }
40017
40386
  let payload;
40018
40387
  try {
40019
- const parsed = JSON.parse(readFileSync19(fullPath, "utf-8"));
40388
+ const parsed = JSON.parse(readFileSync20(fullPath, "utf-8"));
40020
40389
  if (!parsed || typeof parsed !== "object") throw new Error("not an object");
40021
40390
  payload = parsed;
40022
40391
  } catch {
@@ -40099,13 +40468,13 @@ function startSlackNoticeOutboxWatcher() {
40099
40468
  return;
40100
40469
  }
40101
40470
  try {
40102
- for (const f of readdirSync5(SLACK_NOTICE_OUTBOX_DIR)) void processSlackNoticeOutboxFile(f);
40471
+ for (const f of readdirSync6(SLACK_NOTICE_OUTBOX_DIR)) void processSlackNoticeOutboxFile(f);
40103
40472
  } catch {
40104
40473
  }
40105
40474
  try {
40106
40475
  const watcher = watch(SLACK_NOTICE_OUTBOX_DIR, (event, filename) => {
40107
40476
  if (event !== "rename" || !filename) return;
40108
- if (existsSync10(join19(SLACK_NOTICE_OUTBOX_DIR, filename))) {
40477
+ if (existsSync10(join20(SLACK_NOTICE_OUTBOX_DIR, filename))) {
40109
40478
  void processSlackNoticeOutboxFile(filename);
40110
40479
  }
40111
40480
  });
@@ -40128,7 +40497,7 @@ function sweepSlackStaleMarkers(thresholdMs) {
40128
40497
  if (!existsSync10(SLACK_PENDING_INBOUND_DIR)) return;
40129
40498
  let filenames;
40130
40499
  try {
40131
- filenames = readdirSync5(SLACK_PENDING_INBOUND_DIR);
40500
+ filenames = readdirSync6(SLACK_PENDING_INBOUND_DIR);
40132
40501
  } catch (err) {
40133
40502
  process.stderr.write(
40134
40503
  `slack-channel(${AGENT_CODE_NAME}): stale-marker readdir failed: ${err.message}
@@ -40142,10 +40511,10 @@ function sweepSlackStaleMarkers(thresholdMs) {
40142
40511
  for (const filename of filenames) {
40143
40512
  if (!filename.endsWith(".json")) continue;
40144
40513
  if (filename.endsWith(".tmp")) continue;
40145
- const fullPath = join19(SLACK_PENDING_INBOUND_DIR, filename);
40514
+ const fullPath = join20(SLACK_PENDING_INBOUND_DIR, filename);
40146
40515
  let marker;
40147
40516
  try {
40148
- marker = JSON.parse(readFileSync19(fullPath, "utf-8"));
40517
+ marker = JSON.parse(readFileSync20(fullPath, "utf-8"));
40149
40518
  } catch (err) {
40150
40519
  process.stderr.write(
40151
40520
  `slack-channel(${AGENT_CODE_NAME}): stale-marker parse failed for ${redactSlackId(filename)}: ${err.message}
@@ -40203,13 +40572,13 @@ var slackOrphanSweepTimer = setInterval(() => {
40203
40572
  checkSlackWatchdogGiveUpNotice();
40204
40573
  }, orphanSweepIntervalMs());
40205
40574
  slackOrphanSweepTimer.unref?.();
40206
- var SLACK_PROGRESS_HEARTBEAT_PATH = SLACK_AGENT_DIR ? join19(SLACK_AGENT_DIR, "channel-progress-heartbeat.json") : null;
40575
+ var SLACK_PROGRESS_HEARTBEAT_PATH = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "channel-progress-heartbeat.json") : null;
40207
40576
  var slackTrackedProgress = null;
40208
40577
  var slackProgressTickRunning = false;
40209
40578
  function readSlackProgressHeartbeat() {
40210
40579
  if (!SLACK_PROGRESS_HEARTBEAT_PATH || !existsSync10(SLACK_PROGRESS_HEARTBEAT_PATH)) return null;
40211
40580
  try {
40212
- return parseProgressHeartbeat(readFileSync19(SLACK_PROGRESS_HEARTBEAT_PATH, "utf-8"));
40581
+ return parseProgressHeartbeat(readFileSync20(SLACK_PROGRESS_HEARTBEAT_PATH, "utf-8"));
40213
40582
  } catch {
40214
40583
  return null;
40215
40584
  }
@@ -40232,11 +40601,11 @@ function findSlackProgressTarget() {
40232
40601
  let best = null;
40233
40602
  let bestMs = Infinity;
40234
40603
  try {
40235
- for (const name of readdirSync5(SLACK_PENDING_INBOUND_DIR)) {
40604
+ for (const name of readdirSync6(SLACK_PENDING_INBOUND_DIR)) {
40236
40605
  if (!name.endsWith(".json")) continue;
40237
40606
  let m;
40238
40607
  try {
40239
- m = JSON.parse(readFileSync19(join19(SLACK_PENDING_INBOUND_DIR, name), "utf-8"));
40608
+ m = JSON.parse(readFileSync20(join20(SLACK_PENDING_INBOUND_DIR, name), "utf-8"));
40240
40609
  } catch {
40241
40610
  continue;
40242
40611
  }
@@ -40383,11 +40752,11 @@ function listPendingSlackConversations() {
40383
40752
  if (!SLACK_PENDING_INBOUND_DIR || !existsSync10(SLACK_PENDING_INBOUND_DIR)) return [];
40384
40753
  const byKey = /* @__PURE__ */ new Map();
40385
40754
  try {
40386
- for (const name of readdirSync5(SLACK_PENDING_INBOUND_DIR)) {
40755
+ for (const name of readdirSync6(SLACK_PENDING_INBOUND_DIR)) {
40387
40756
  if (!name.endsWith(".json")) continue;
40388
40757
  try {
40389
40758
  const marker = JSON.parse(
40390
- readFileSync19(join19(SLACK_PENDING_INBOUND_DIR, name), "utf8")
40759
+ readFileSync20(join20(SLACK_PENDING_INBOUND_DIR, name), "utf8")
40391
40760
  );
40392
40761
  if (typeof marker.channel !== "string" || !marker.channel) continue;
40393
40762
  if (typeof marker.thread_ts !== "string" || !marker.thread_ts) continue;
@@ -40439,7 +40808,7 @@ function postSlackWatchdogGiveUpNotice(channel, threadTs, isThreadReply, reason)
40439
40808
  }
40440
40809
  function checkSlackWatchdogGiveUpNotice() {
40441
40810
  if (!SLACK_AGENT_DIR) return;
40442
- const signal = readGiveUpSignal(join19(SLACK_AGENT_DIR, GIVE_UP_SIGNAL_FILENAME));
40811
+ const signal = readGiveUpSignal(join20(SLACK_AGENT_DIR, GIVE_UP_SIGNAL_FILENAME));
40443
40812
  const signalAtMs = signal?.atMs ?? null;
40444
40813
  const act = decideGiveUpNotice({
40445
40814
  signalAtMs,
@@ -40471,7 +40840,7 @@ function readRestartTopicForMarker(filename, channel, threadTs) {
40471
40840
  if (!SLACK_RESTART_CONTEXT_DIR) return null;
40472
40841
  let raw;
40473
40842
  try {
40474
- raw = readFileSync19(join19(SLACK_RESTART_CONTEXT_DIR, filename), "utf-8");
40843
+ raw = readFileSync20(join20(SLACK_RESTART_CONTEXT_DIR, filename), "utf-8");
40475
40844
  } catch {
40476
40845
  return null;
40477
40846
  }
@@ -40480,7 +40849,7 @@ function readRestartTopicForMarker(filename, channel, threadTs) {
40480
40849
  function removeRestartContextHint(filename) {
40481
40850
  if (!SLACK_RESTART_CONTEXT_DIR) return;
40482
40851
  try {
40483
- unlinkSync7(join19(SLACK_RESTART_CONTEXT_DIR, filename));
40852
+ unlinkSync7(join20(SLACK_RESTART_CONTEXT_DIR, filename));
40484
40853
  } catch {
40485
40854
  }
40486
40855
  }
@@ -40488,14 +40857,14 @@ function clearAllRestartContextHints() {
40488
40857
  if (!SLACK_RESTART_CONTEXT_DIR) return;
40489
40858
  let names;
40490
40859
  try {
40491
- names = readdirSync5(SLACK_RESTART_CONTEXT_DIR);
40860
+ names = readdirSync6(SLACK_RESTART_CONTEXT_DIR);
40492
40861
  } catch {
40493
40862
  return;
40494
40863
  }
40495
40864
  for (const name of names) {
40496
40865
  if (!name.endsWith(".json")) continue;
40497
40866
  try {
40498
- unlinkSync7(join19(SLACK_RESTART_CONTEXT_DIR, name));
40867
+ unlinkSync7(join20(SLACK_RESTART_CONTEXT_DIR, name));
40499
40868
  } catch {
40500
40869
  }
40501
40870
  }
@@ -40512,7 +40881,7 @@ async function notifyStrandedInboundsOnFirstConnect() {
40512
40881
  if (!SLACK_PENDING_INBOUND_DIR || !existsSync10(SLACK_PENDING_INBOUND_DIR)) return;
40513
40882
  let filenames;
40514
40883
  try {
40515
- filenames = readdirSync5(SLACK_PENDING_INBOUND_DIR);
40884
+ filenames = readdirSync6(SLACK_PENDING_INBOUND_DIR);
40516
40885
  } catch {
40517
40886
  hadFailure = true;
40518
40887
  return;
@@ -40522,10 +40891,10 @@ async function notifyStrandedInboundsOnFirstConnect() {
40522
40891
  let notified = 0;
40523
40892
  for (const filename of filenames) {
40524
40893
  if (!filename.endsWith(".json")) continue;
40525
- const fullPath = join19(SLACK_PENDING_INBOUND_DIR, filename);
40894
+ const fullPath = join20(SLACK_PENDING_INBOUND_DIR, filename);
40526
40895
  let marker;
40527
40896
  try {
40528
- marker = JSON.parse(readFileSync19(fullPath, "utf-8"));
40897
+ marker = JSON.parse(readFileSync20(fullPath, "utf-8"));
40529
40898
  } catch {
40530
40899
  continue;
40531
40900
  }
@@ -40699,7 +41068,7 @@ function noteThreadActivityByMessageTs(channel, messageTs) {
40699
41068
  markSeenAllSlackPendingMarkersForThread2(channel, messageTs);
40700
41069
  markSeenSlackPendingMarkerByMessageTs2(channel, messageTs);
40701
41070
  }
40702
- var RESTART_FLAGS_DIR = join19(homedir6(), ".augmented", "restart-flags");
41071
+ var RESTART_FLAGS_DIR = join20(homedir7(), ".augmented", "restart-flags");
40703
41072
  function actuateHostRestartSlack() {
40704
41073
  return actuateHostRestart({
40705
41074
  agtHost: AGT_HOST,
@@ -40720,10 +41089,10 @@ function buildAugmentedSlackMetadata() {
40720
41089
  };
40721
41090
  }
40722
41091
  function hashChannelId(id) {
40723
- return createHash2("sha256").update(id).digest("hex").slice(0, 8);
41092
+ return createHash3("sha256").update(id).digest("hex").slice(0, 8);
40724
41093
  }
40725
41094
  function hashId(id) {
40726
- return createHash2("sha256").update(id).digest("hex").slice(0, 8);
41095
+ return createHash3("sha256").update(id).digest("hex").slice(0, 8);
40727
41096
  }
40728
41097
  async function postSlackMessage(body) {
40729
41098
  const augmentedMeta = buildAugmentedSlackMetadata();
@@ -41304,7 +41673,7 @@ async function handleSlashCommandEnvelope(payload) {
41304
41673
  if (!existsSync10(RESTART_FLAGS_DIR)) {
41305
41674
  mkdirSync9(RESTART_FLAGS_DIR, { recursive: true });
41306
41675
  }
41307
- const flagPath = join19(RESTART_FLAGS_DIR, `${codeName}.flag`);
41676
+ const flagPath = join20(RESTART_FLAGS_DIR, `${codeName}.flag`);
41308
41677
  const flag = {
41309
41678
  codeName,
41310
41679
  source: "slack",
@@ -41447,7 +41816,7 @@ async function handleRestartCommand(opts) {
41447
41816
  if (!existsSync10(RESTART_FLAGS_DIR)) {
41448
41817
  mkdirSync9(RESTART_FLAGS_DIR, { recursive: true });
41449
41818
  }
41450
- const flagPath = join19(RESTART_FLAGS_DIR, `${codeName}.flag`);
41819
+ const flagPath = join20(RESTART_FLAGS_DIR, `${codeName}.flag`);
41451
41820
  const flag = {
41452
41821
  codeName,
41453
41822
  source: "slack",
@@ -41569,7 +41938,7 @@ var SLACK_HOT_THREAD_WINDOW_MS = parseHotThreadWindowMs(
41569
41938
  );
41570
41939
  function resolveThreadStorePath() {
41571
41940
  if (!AGENT_CODE_NAME) return null;
41572
- return join19(homedir6(), ".augmented", AGENT_CODE_NAME, "slack-tracked-threads.json");
41941
+ return join20(homedir7(), ".augmented", AGENT_CODE_NAME, "slack-tracked-threads.json");
41573
41942
  }
41574
41943
  function parseTtlDays(raw) {
41575
41944
  if (!raw) return void 0;
@@ -41608,9 +41977,9 @@ if (!BOT_TOKEN || !APP_TOKEN) {
41608
41977
  var slackStderrLogStream = null;
41609
41978
  if (AGENT_CODE_NAME) {
41610
41979
  try {
41611
- const logDir = join19(homedir6(), ".augmented", AGENT_CODE_NAME);
41980
+ const logDir = join20(homedir7(), ".augmented", AGENT_CODE_NAME);
41612
41981
  mkdirSync9(logDir, { recursive: true });
41613
- slackStderrLogStream = createWriteStream(join19(logDir, "slack-channel-stderr.log"), {
41982
+ slackStderrLogStream = createWriteStream(join20(logDir, "slack-channel-stderr.log"), {
41614
41983
  flags: "a",
41615
41984
  mode: 384
41616
41985
  });
@@ -42486,7 +42855,7 @@ ${result.formatted}` : "No messages in range, or the bot is not a member of this
42486
42855
  isError: true
42487
42856
  };
42488
42857
  }
42489
- const allowedRoot = resolve2(homedir6(), ".augmented", AGENT_CODE_NAME, "project") + "/";
42858
+ const allowedRoot = resolve2(homedir7(), ".augmented", AGENT_CODE_NAME, "project") + "/";
42490
42859
  const resolvedPath = resolve2(path);
42491
42860
  if (!resolvedPath.startsWith(allowedRoot)) {
42492
42861
  return {
@@ -42500,7 +42869,7 @@ ${result.formatted}` : "No messages in range, or the bot is not a member of this
42500
42869
  let bytes;
42501
42870
  let size;
42502
42871
  try {
42503
- const stat2 = statSync3(resolvedPath);
42872
+ const stat2 = statSync4(resolvedPath);
42504
42873
  if (!stat2.isFile()) {
42505
42874
  return {
42506
42875
  content: [{ type: "text", text: `Upload refused: ${resolvedPath} is not a regular file.` }],
@@ -42508,7 +42877,7 @@ ${result.formatted}` : "No messages in range, or the bot is not a member of this
42508
42877
  };
42509
42878
  }
42510
42879
  size = stat2.size;
42511
- bytes = readFileSync19(resolvedPath);
42880
+ bytes = readFileSync20(resolvedPath);
42512
42881
  } catch (err) {
42513
42882
  return {
42514
42883
  content: [{ type: "text", text: `Failed to read file: ${err.message}` }],
@@ -43163,7 +43532,7 @@ function isDownloadableFileId(fileId, channel) {
43163
43532
  }
43164
43533
  function redactAugmentedPaths2(msg) {
43165
43534
  return msg.replaceAll(
43166
- new RegExp(`${homedir6().replace(/[.*+?^${}()|[\\]\\\\]/g, "\\\\$&")}/\\.augmented/[^\\s'"\`]*`, "g"),
43535
+ new RegExp(`${homedir7().replace(/[.*+?^${}()|[\\]\\\\]/g, "\\\\$&")}/\\.augmented/[^\\s'"\`]*`, "g"),
43167
43536
  "<augmented-path>"
43168
43537
  );
43169
43538
  }
@@ -43283,7 +43652,7 @@ async function replayPendingSlackMarkers() {
43283
43652
  if (!sessionAlive) return;
43284
43653
  let filenames;
43285
43654
  try {
43286
- filenames = readdirSync5(SLACK_PENDING_INBOUND_DIR);
43655
+ filenames = readdirSync6(SLACK_PENDING_INBOUND_DIR);
43287
43656
  } catch {
43288
43657
  return;
43289
43658
  }
@@ -43291,7 +43660,7 @@ async function replayPendingSlackMarkers() {
43291
43660
  let paneFreshAgeMs = null;
43292
43661
  if (SLACK_AGENT_DIR) {
43293
43662
  try {
43294
- paneFreshAgeMs = Math.max(0, now - statSync3(join19(SLACK_AGENT_DIR, "pane.log")).mtimeMs);
43663
+ paneFreshAgeMs = Math.max(0, now - statSync4(join20(SLACK_AGENT_DIR, "pane.log")).mtimeMs);
43295
43664
  } catch {
43296
43665
  }
43297
43666
  }
@@ -43299,10 +43668,10 @@ async function replayPendingSlackMarkers() {
43299
43668
  const entries = [];
43300
43669
  for (const name of filenames) {
43301
43670
  if (!name.endsWith(".json") || name.endsWith(".tmp")) continue;
43302
- const fullPath = join19(SLACK_PENDING_INBOUND_DIR, name);
43671
+ const fullPath = join20(SLACK_PENDING_INBOUND_DIR, name);
43303
43672
  let marker;
43304
43673
  try {
43305
- marker = JSON.parse(readFileSync19(fullPath, "utf-8"));
43674
+ marker = JSON.parse(readFileSync20(fullPath, "utf-8"));
43306
43675
  } catch {
43307
43676
  continue;
43308
43677
  }
@@ -43649,7 +44018,7 @@ async function connectSocketMode() {
43649
44018
  const passedIdentity = access.kind !== "drop" || access.reason.startsWith("peer:");
43650
44019
  if (passedIdentity) recordActivity("inbound");
43651
44020
  if (access.kind === "drop") {
43652
- const channelHash = createHash2("sha256").update(evt.channel ?? "").digest("hex").slice(0, 8);
44021
+ const channelHash = createHash3("sha256").update(evt.channel ?? "").digest("hex").slice(0, 8);
43653
44022
  const subtypeSuffix = access.reason === "content:subtype" ? ` subtype=${evt.subtype ?? "none"}` : "";
43654
44023
  process.stderr.write(
43655
44024
  `slack-channel: inbound drop reason=${access.reason}${subtypeSuffix} channel=${channelHash} ts=${redactSlackId(evt.ts)}
@@ -43774,7 +44143,8 @@ async function connectSocketMode() {
43774
44143
  });
43775
44144
  return;
43776
44145
  }
43777
- const usageLimitUntil = !isBot ? readUsageLimitUntil({ codeName: AGENT_CODE_NAME }) : null;
44146
+ const reactiveMode = resolveUsageLimitReactiveMode();
44147
+ const usageLimitUntil = !isBot && shouldReadPredictiveMarker(reactiveMode) ? readUsageLimitUntil({ codeName: AGENT_CODE_NAME }) : null;
43778
44148
  if (usageLimitUntil) {
43779
44149
  process.stderr.write(
43780
44150
  `slack-channel(${AGENT_CODE_NAME}): usage-limit active until ${usageLimitUntil.toISOString()} \u2014 notice, no dispatch (channel=${redactSlackId(evt.channel)})
@@ -43833,7 +44203,7 @@ async function connectSocketMode() {
43833
44203
  if (evt.type === "message" && evt.channel && !isDirectMessage) {
43834
44204
  if (isThreadReply) {
43835
44205
  const logThreadDrop = (reason) => {
43836
- const channelHash = createHash2("sha256").update(evt.channel ?? "").digest("hex").slice(0, 8);
44206
+ const channelHash = createHash3("sha256").update(evt.channel ?? "").digest("hex").slice(0, 8);
43837
44207
  process.stderr.write(
43838
44208
  `slack-channel(${AGENT_CODE_NAME}): thread-reply drop reason=${reason} auto_follow=${THREAD_AUTO_FOLLOW} channel=${channelHash} ts=${redactSlackId(evt.ts)}
43839
44209
  `
@@ -43899,7 +44269,7 @@ async function connectSocketMode() {
43899
44269
  let paneLogFreshAgeMs = null;
43900
44270
  if (SLACK_AGENT_DIR) {
43901
44271
  try {
43902
- const paneMtimeMs = statSync3(join19(SLACK_AGENT_DIR, "pane.log")).mtimeMs;
44272
+ const paneMtimeMs = statSync4(join20(SLACK_AGENT_DIR, "pane.log")).mtimeMs;
43903
44273
  paneLogFreshAgeMs = Math.max(0, Date.now() - paneMtimeMs);
43904
44274
  } catch {
43905
44275
  }
@@ -44065,10 +44435,26 @@ ${forwarded.text}` : forwarded.text;
44065
44435
  });
44066
44436
  clearScheduledTurnMarker(SLACK_AGENT_DIR);
44067
44437
  }
44438
+ const dispatchedAtMs = Date.now();
44068
44439
  await mcp.notification({
44069
44440
  method: "notifications/claude/channel",
44070
44441
  params: replayPayload
44071
44442
  });
44443
+ const watchMode = armedWatchMode({
44444
+ mode: reactiveMode,
44445
+ isBot: isFromBot,
44446
+ replyOwed: shouldEngage
44447
+ });
44448
+ if (watchMode) {
44449
+ armSlackUsageLimitWatch({
44450
+ mode: watchMode,
44451
+ channel,
44452
+ senderId: evt.user,
44453
+ threadTs,
44454
+ messageTs: ts,
44455
+ sinceMs: dispatchedAtMs
44456
+ });
44457
+ }
44072
44458
  if (shouldEngage) seedSlackProgressHeartbeat();
44073
44459
  if (channel) {
44074
44460
  conversationIngestClient?.ingest({