@integrity-labs/agt-cli 0.28.569 → 0.28.571

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.
@@ -35393,13 +35393,30 @@ var FLAG_REGISTRY = [
35393
35393
  // safe default — it resolves to `honors`, reporting every host as honouring
35394
35394
  // the flip, including hosts whose agt-cli has no reader at all.
35395
35395
  //
35396
- // 0.28.566 is the auto-publish cut from the ENG-8575 merge (583cef8d9,
35397
- // published 2026-08-12T08:32Z). Verified against the published tarball
35398
- // rather than inferred from the merge: `maybeScanToolCalls`,
35399
- // `tool-call-audit` and `tool-call-path-salt` are all present in
35400
- // package/dist/lib/manager-worker.js — the manager, which is the actual
35401
- // reader. The dist/mcp/* occurrences are bundling artifacts, not readers.
35402
- since: "0.28.566"
35396
+ // WHAT THIS VERSION HAS TO MEAN. Not "the first build with a reader" the
35397
+ // first build where flipping the flag does what the flag is documented to
35398
+ // do. Those diverged twice already, in the same direction:
35399
+ //
35400
+ // 0.28.566 (ENG-8575) — the first build with a reader. Pinned here and
35401
+ // correct on the day. It has the unbounded scan window and the coverage
35402
+ // rows that overstate (both ENG-8740), and no `logging_mode` enforcement
35403
+ // at all (ENG-8726) — so a hash-only agent on it emits plaintext
35404
+ // `argv0` / `url_host` / `mcp_tool`, which is precisely the governance
35405
+ // breach this epic exists to prevent.
35406
+ // 0.28.569 (ENG-8740) — bounded window, honest coverage intervals. Still
35407
+ // no hash-only enforcement. The pin was NOT moved at that merge and went
35408
+ // stale for a day; reach reported those hosts `honors`.
35409
+ // 0.28.570 (ENG-8726) — hash-only honoured at runtime. Current pin.
35410
+ //
35411
+ // MOVE THIS PIN whenever a change alters what arming the flag DOES on a
35412
+ // host, and verify it against the published tarball rather than inferring it
35413
+ // from the merge — `npm pack @integrity-labs/agt-cli@<v>` and grep
35414
+ // package/dist/lib/manager-worker.js (the manager is the actual reader; the
35415
+ // dist/mcp/* occurrences are bundling artifacts). For 0.28.570 the markers
35416
+ // are `readAgentLoggingMode` and `loggingModeWithholdsTargets`. Auto-publish
35417
+ // patch-bumps from whatever is on main, so if another CLI-touching PR lands
35418
+ // first the real cut is higher than this and the pin under-reports.
35419
+ since: "0.28.570"
35403
35420
  },
35404
35421
  {
35405
35422
  key: "conversation-eval-backend",
@@ -35704,9 +35721,9 @@ var FLAG_REGISTRY = [
35704
35721
  },
35705
35722
  {
35706
35723
  key: "notify-dispatch",
35707
- description: "Membership-based channel-notify dispatch (ENG-7682 / notify Slice 1). off = today's behaviour: a non-@mention top-level channel message is dropped by the mention_only engagement gate (SLACK_CHANNEL_RESPONSE_MODE). membership = the agent's Slack MCP ADMITS non-@mention channel messages in channels its bot is a member of (the Socket Mode websocket already receives them), waking the agent in-thread via the SAME existing wake path used for @mentions/DMs. Only the mention_only engagement gate is relaxed - the echo/dedup, bot_id/self, and peer-classifier safety leaves still apply, so this never opens a bot-to-bot wake loop. The channel server can't evaluate flags, so the manager materializes the resolved value into the AGT_NOTIFY_DISPATCH spawn env (operator/canary override, ADR-0022). filter = like membership (opt-out) but honours a per-channel mute list: a member-channel message wakes the agent UNLESS the user muted that channel via the /notify slash command. The manager materializes the muted set into AGT_NOTIFY_MUTED_CHANNELS from agent_notify_channel_prefs (ENG-7682 Slice 2). Ships dark (default off).",
35724
+ description: `Membership-based channel-notify dispatch (ENG-7682 / notify Slice 1). off = today's behaviour: a non-@mention top-level channel message is dropped by the mention_only engagement gate (SLACK_CHANNEL_RESPONSE_MODE). membership = the agent's Slack MCP ADMITS non-@mention channel messages in channels its bot is a member of (the Socket Mode websocket already receives them), waking the agent in-thread via the SAME existing wake path used for @mentions/DMs. Only the mention_only engagement gate is relaxed - the echo/dedup, bot_id/self, and peer-classifier safety leaves still apply, so this never opens a bot-to-bot wake loop. The channel server can't evaluate flags, so the manager materializes the resolved value into the AGT_NOTIFY_DISPATCH spawn env (operator/canary override, ADR-0022). filter = like membership (opt-out) but honours a per-channel mute list: a member-channel message wakes the agent UNLESS the user muted that channel via the /notify slash command. The manager materializes the muted set into AGT_NOTIFY_MUTED_CHANNELS from agent_notify_channel_prefs (ENG-7682 Slice 2). addressed = like filter (same per-channel mute, checked FIRST so a mute outranks being named), but a member-channel message additionally has to address THIS agent to wake it: a real Slack mention of its bot user id, \`@<code_name>\` typed verbatim, or the code name used as a vocative at the start of the message ("koda:", "hey koda"). @team / @everyone still wake everyone. This is the fix for one named agent waking every agent in a shared channel (ENG-8657); matching is deliberately conservative, so a name mentioned mid-sentence does NOT wake, and an agent whose identity is unknown to the channel server stays asleep rather than waking on everything. Ships dark (default off).`,
35708
35725
  flagType: "enum",
35709
- allowedValues: ["off", "membership", "filter"],
35726
+ allowedValues: ["off", "membership", "filter", "addressed"],
35710
35727
  // Declared safe value is `off`: the mention_only gate stays in force, byte-
35711
35728
  // identical to today. membership is the deliberate, per-agent flip that
35712
35729
  // widens what wakes the agent.
@@ -41284,13 +41284,30 @@ var FLAG_REGISTRY = [
41284
41284
  // safe default — it resolves to `honors`, reporting every host as honouring
41285
41285
  // the flip, including hosts whose agt-cli has no reader at all.
41286
41286
  //
41287
- // 0.28.566 is the auto-publish cut from the ENG-8575 merge (583cef8d9,
41288
- // published 2026-08-12T08:32Z). Verified against the published tarball
41289
- // rather than inferred from the merge: `maybeScanToolCalls`,
41290
- // `tool-call-audit` and `tool-call-path-salt` are all present in
41291
- // package/dist/lib/manager-worker.js — the manager, which is the actual
41292
- // reader. The dist/mcp/* occurrences are bundling artifacts, not readers.
41293
- since: "0.28.566"
41287
+ // WHAT THIS VERSION HAS TO MEAN. Not "the first build with a reader" the
41288
+ // first build where flipping the flag does what the flag is documented to
41289
+ // do. Those diverged twice already, in the same direction:
41290
+ //
41291
+ // 0.28.566 (ENG-8575) — the first build with a reader. Pinned here and
41292
+ // correct on the day. It has the unbounded scan window and the coverage
41293
+ // rows that overstate (both ENG-8740), and no `logging_mode` enforcement
41294
+ // at all (ENG-8726) — so a hash-only agent on it emits plaintext
41295
+ // `argv0` / `url_host` / `mcp_tool`, which is precisely the governance
41296
+ // breach this epic exists to prevent.
41297
+ // 0.28.569 (ENG-8740) — bounded window, honest coverage intervals. Still
41298
+ // no hash-only enforcement. The pin was NOT moved at that merge and went
41299
+ // stale for a day; reach reported those hosts `honors`.
41300
+ // 0.28.570 (ENG-8726) — hash-only honoured at runtime. Current pin.
41301
+ //
41302
+ // MOVE THIS PIN whenever a change alters what arming the flag DOES on a
41303
+ // host, and verify it against the published tarball rather than inferring it
41304
+ // from the merge — `npm pack @integrity-labs/agt-cli@<v>` and grep
41305
+ // package/dist/lib/manager-worker.js (the manager is the actual reader; the
41306
+ // dist/mcp/* occurrences are bundling artifacts). For 0.28.570 the markers
41307
+ // are `readAgentLoggingMode` and `loggingModeWithholdsTargets`. Auto-publish
41308
+ // patch-bumps from whatever is on main, so if another CLI-touching PR lands
41309
+ // first the real cut is higher than this and the pin under-reports.
41310
+ since: "0.28.570"
41294
41311
  },
41295
41312
  {
41296
41313
  key: "conversation-eval-backend",
@@ -41595,9 +41612,9 @@ var FLAG_REGISTRY = [
41595
41612
  },
41596
41613
  {
41597
41614
  key: "notify-dispatch",
41598
- description: "Membership-based channel-notify dispatch (ENG-7682 / notify Slice 1). off = today's behaviour: a non-@mention top-level channel message is dropped by the mention_only engagement gate (SLACK_CHANNEL_RESPONSE_MODE). membership = the agent's Slack MCP ADMITS non-@mention channel messages in channels its bot is a member of (the Socket Mode websocket already receives them), waking the agent in-thread via the SAME existing wake path used for @mentions/DMs. Only the mention_only engagement gate is relaxed - the echo/dedup, bot_id/self, and peer-classifier safety leaves still apply, so this never opens a bot-to-bot wake loop. The channel server can't evaluate flags, so the manager materializes the resolved value into the AGT_NOTIFY_DISPATCH spawn env (operator/canary override, ADR-0022). filter = like membership (opt-out) but honours a per-channel mute list: a member-channel message wakes the agent UNLESS the user muted that channel via the /notify slash command. The manager materializes the muted set into AGT_NOTIFY_MUTED_CHANNELS from agent_notify_channel_prefs (ENG-7682 Slice 2). Ships dark (default off).",
41615
+ description: `Membership-based channel-notify dispatch (ENG-7682 / notify Slice 1). off = today's behaviour: a non-@mention top-level channel message is dropped by the mention_only engagement gate (SLACK_CHANNEL_RESPONSE_MODE). membership = the agent's Slack MCP ADMITS non-@mention channel messages in channels its bot is a member of (the Socket Mode websocket already receives them), waking the agent in-thread via the SAME existing wake path used for @mentions/DMs. Only the mention_only engagement gate is relaxed - the echo/dedup, bot_id/self, and peer-classifier safety leaves still apply, so this never opens a bot-to-bot wake loop. The channel server can't evaluate flags, so the manager materializes the resolved value into the AGT_NOTIFY_DISPATCH spawn env (operator/canary override, ADR-0022). filter = like membership (opt-out) but honours a per-channel mute list: a member-channel message wakes the agent UNLESS the user muted that channel via the /notify slash command. The manager materializes the muted set into AGT_NOTIFY_MUTED_CHANNELS from agent_notify_channel_prefs (ENG-7682 Slice 2). addressed = like filter (same per-channel mute, checked FIRST so a mute outranks being named), but a member-channel message additionally has to address THIS agent to wake it: a real Slack mention of its bot user id, \`@<code_name>\` typed verbatim, or the code name used as a vocative at the start of the message ("koda:", "hey koda"). @team / @everyone still wake everyone. This is the fix for one named agent waking every agent in a shared channel (ENG-8657); matching is deliberately conservative, so a name mentioned mid-sentence does NOT wake, and an agent whose identity is unknown to the channel server stays asleep rather than waking on everything. Ships dark (default off).`,
41599
41616
  flagType: "enum",
41600
- allowedValues: ["off", "membership", "filter"],
41617
+ allowedValues: ["off", "membership", "filter", "addressed"],
41601
41618
  // Declared safe value is `off`: the mention_only gate stays in force, byte-
41602
41619
  // identical to today. membership is the deliberate, per-agent flip that
41603
41620
  // widens what wakes the agent.
@@ -14991,7 +14991,7 @@ var require_lib = __commonJS({
14991
14991
  ">": "&gt;",
14992
14992
  "\\": "&#92;"
14993
14993
  };
14994
- var escapeRegex2 = /[&"'<>\\]/g;
14994
+ var escapeRegex3 = /[&"'<>\\]/g;
14995
14995
  var _exports = module.exports = {};
14996
14996
  function hasOwnProp(obj, k) {
14997
14997
  return ObjProto.hasOwnProperty.call(obj, k);
@@ -15095,7 +15095,7 @@ var require_lib = __commonJS({
15095
15095
  }
15096
15096
  _exports.TemplateError = TemplateError2;
15097
15097
  function escape2(val) {
15098
- return val.replace(escapeRegex2, lookupEscape);
15098
+ return val.replace(escapeRegex3, lookupEscape);
15099
15099
  }
15100
15100
  _exports.escape = escape2;
15101
15101
  function isFunction(obj) {
@@ -35729,13 +35729,30 @@ var FLAG_REGISTRY = [
35729
35729
  // safe default — it resolves to `honors`, reporting every host as honouring
35730
35730
  // the flip, including hosts whose agt-cli has no reader at all.
35731
35731
  //
35732
- // 0.28.566 is the auto-publish cut from the ENG-8575 merge (583cef8d9,
35733
- // published 2026-08-12T08:32Z). Verified against the published tarball
35734
- // rather than inferred from the merge: `maybeScanToolCalls`,
35735
- // `tool-call-audit` and `tool-call-path-salt` are all present in
35736
- // package/dist/lib/manager-worker.js — the manager, which is the actual
35737
- // reader. The dist/mcp/* occurrences are bundling artifacts, not readers.
35738
- since: "0.28.566"
35732
+ // WHAT THIS VERSION HAS TO MEAN. Not "the first build with a reader" the
35733
+ // first build where flipping the flag does what the flag is documented to
35734
+ // do. Those diverged twice already, in the same direction:
35735
+ //
35736
+ // 0.28.566 (ENG-8575) — the first build with a reader. Pinned here and
35737
+ // correct on the day. It has the unbounded scan window and the coverage
35738
+ // rows that overstate (both ENG-8740), and no `logging_mode` enforcement
35739
+ // at all (ENG-8726) — so a hash-only agent on it emits plaintext
35740
+ // `argv0` / `url_host` / `mcp_tool`, which is precisely the governance
35741
+ // breach this epic exists to prevent.
35742
+ // 0.28.569 (ENG-8740) — bounded window, honest coverage intervals. Still
35743
+ // no hash-only enforcement. The pin was NOT moved at that merge and went
35744
+ // stale for a day; reach reported those hosts `honors`.
35745
+ // 0.28.570 (ENG-8726) — hash-only honoured at runtime. Current pin.
35746
+ //
35747
+ // MOVE THIS PIN whenever a change alters what arming the flag DOES on a
35748
+ // host, and verify it against the published tarball rather than inferring it
35749
+ // from the merge — `npm pack @integrity-labs/agt-cli@<v>` and grep
35750
+ // package/dist/lib/manager-worker.js (the manager is the actual reader; the
35751
+ // dist/mcp/* occurrences are bundling artifacts). For 0.28.570 the markers
35752
+ // are `readAgentLoggingMode` and `loggingModeWithholdsTargets`. Auto-publish
35753
+ // patch-bumps from whatever is on main, so if another CLI-touching PR lands
35754
+ // first the real cut is higher than this and the pin under-reports.
35755
+ since: "0.28.570"
35739
35756
  },
35740
35757
  {
35741
35758
  key: "conversation-eval-backend",
@@ -36040,9 +36057,9 @@ var FLAG_REGISTRY = [
36040
36057
  },
36041
36058
  {
36042
36059
  key: "notify-dispatch",
36043
- description: "Membership-based channel-notify dispatch (ENG-7682 / notify Slice 1). off = today's behaviour: a non-@mention top-level channel message is dropped by the mention_only engagement gate (SLACK_CHANNEL_RESPONSE_MODE). membership = the agent's Slack MCP ADMITS non-@mention channel messages in channels its bot is a member of (the Socket Mode websocket already receives them), waking the agent in-thread via the SAME existing wake path used for @mentions/DMs. Only the mention_only engagement gate is relaxed - the echo/dedup, bot_id/self, and peer-classifier safety leaves still apply, so this never opens a bot-to-bot wake loop. The channel server can't evaluate flags, so the manager materializes the resolved value into the AGT_NOTIFY_DISPATCH spawn env (operator/canary override, ADR-0022). filter = like membership (opt-out) but honours a per-channel mute list: a member-channel message wakes the agent UNLESS the user muted that channel via the /notify slash command. The manager materializes the muted set into AGT_NOTIFY_MUTED_CHANNELS from agent_notify_channel_prefs (ENG-7682 Slice 2). Ships dark (default off).",
36060
+ description: `Membership-based channel-notify dispatch (ENG-7682 / notify Slice 1). off = today's behaviour: a non-@mention top-level channel message is dropped by the mention_only engagement gate (SLACK_CHANNEL_RESPONSE_MODE). membership = the agent's Slack MCP ADMITS non-@mention channel messages in channels its bot is a member of (the Socket Mode websocket already receives them), waking the agent in-thread via the SAME existing wake path used for @mentions/DMs. Only the mention_only engagement gate is relaxed - the echo/dedup, bot_id/self, and peer-classifier safety leaves still apply, so this never opens a bot-to-bot wake loop. The channel server can't evaluate flags, so the manager materializes the resolved value into the AGT_NOTIFY_DISPATCH spawn env (operator/canary override, ADR-0022). filter = like membership (opt-out) but honours a per-channel mute list: a member-channel message wakes the agent UNLESS the user muted that channel via the /notify slash command. The manager materializes the muted set into AGT_NOTIFY_MUTED_CHANNELS from agent_notify_channel_prefs (ENG-7682 Slice 2). addressed = like filter (same per-channel mute, checked FIRST so a mute outranks being named), but a member-channel message additionally has to address THIS agent to wake it: a real Slack mention of its bot user id, \`@<code_name>\` typed verbatim, or the code name used as a vocative at the start of the message ("koda:", "hey koda"). @team / @everyone still wake everyone. This is the fix for one named agent waking every agent in a shared channel (ENG-8657); matching is deliberately conservative, so a name mentioned mid-sentence does NOT wake, and an agent whose identity is unknown to the channel server stays asleep rather than waking on everything. Ships dark (default off).`,
36044
36061
  flagType: "enum",
36045
- allowedValues: ["off", "membership", "filter"],
36062
+ allowedValues: ["off", "membership", "filter", "addressed"],
36046
36063
  // Declared safe value is `off`: the mention_only gate stays in force, byte-
36047
36064
  // identical to today. membership is the deliberate, per-agent flip that
36048
36065
  // widens what wakes the agent.
@@ -39891,6 +39908,26 @@ function matchesAddressedTeam(text) {
39891
39908
  if (/^(everyone|all)\s*[:,—-]/i.test(t)) return true;
39892
39909
  return false;
39893
39910
  }
39911
+ function matchesAddressedAgent(text, agent) {
39912
+ const t = text.trim();
39913
+ if (t.length === 0) return false;
39914
+ const botUserId2 = agent.botUserId?.trim();
39915
+ if (botUserId2 && new RegExp(`<@${escapeRegex2(botUserId2)}(?:\\|[^>]*)?>`).test(t)) return true;
39916
+ const codeName = agent.codeName?.trim();
39917
+ if (!codeName) return false;
39918
+ const name = escapeRegex2(codeName);
39919
+ if (new RegExp(`(?:^|\\s)@${name}(?=$|[\\s.,!?;:])`, "i").test(t)) return true;
39920
+ if (new RegExp(`^${name}\\s*[:,\u2014-]`, "i").test(t)) return true;
39921
+ if (new RegExp(
39922
+ `^(hey|hi|hello|howdy|good (morning|afternoon|evening)|morning|afternoon)\\s+${name}(?=$|[\\s,.!?:])`,
39923
+ "i"
39924
+ ).test(t))
39925
+ return true;
39926
+ return false;
39927
+ }
39928
+ function escapeRegex2(value) {
39929
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
39930
+ }
39894
39931
  function channelMessageShouldRespond(text, mode) {
39895
39932
  if (mode === "all") return true;
39896
39933
  if (mode === "mention_only") return false;
@@ -39903,6 +39940,7 @@ function parseNotifyDispatchMode(raw) {
39903
39940
  const v = raw.trim().toLowerCase();
39904
39941
  if (v === "membership") return "membership";
39905
39942
  if (v === "filter") return "filter";
39943
+ if (v === "addressed") return "addressed";
39906
39944
  return "off";
39907
39945
  }
39908
39946
  function parseMutedChannels(raw) {
@@ -39911,12 +39949,17 @@ function parseMutedChannels(raw) {
39911
39949
  raw.split(",").map((s) => s.trim()).filter(Boolean)
39912
39950
  );
39913
39951
  }
39914
- function channelMessageShouldWake(text, responseMode, notifyMode, channelId, mutedChannels) {
39952
+ function channelMessageShouldWake(text, responseMode, notifyMode, channelId, mutedChannels, agent) {
39915
39953
  if (notifyMode === "membership") return true;
39916
39954
  if (notifyMode === "filter") {
39917
39955
  if (channelId && mutedChannels && mutedChannels.has(channelId)) return false;
39918
39956
  return true;
39919
39957
  }
39958
+ if (notifyMode === "addressed") {
39959
+ if (channelId && mutedChannels && mutedChannels.has(channelId)) return false;
39960
+ if (!agent) return false;
39961
+ return matchesAddressedAgent(text, agent);
39962
+ }
39920
39963
  return channelMessageShouldRespond(text, responseMode);
39921
39964
  }
39922
39965
  function parseNotifyCommand(text, currentChannelId) {
@@ -39926,6 +39969,15 @@ function parseNotifyCommand(text, currentChannelId) {
39926
39969
  if (arg === "" || arg === "status") return { action: "status", channelId: currentChannelId };
39927
39970
  return { action: "help", channelId: currentChannelId };
39928
39971
  }
39972
+ function notifyStatusMessage(muted, mode) {
39973
+ if (mode === "filter") {
39974
+ return muted ? ":mute: This channel is *muted* \u2014 I won\u2019t wake on its messages (an @-mention still reaches me). `/notify on` to resume." : ":bell: This channel is *active* \u2014 I wake on its messages. `/notify off` to mute.";
39975
+ }
39976
+ if (mode === "addressed") {
39977
+ return muted ? ":mute: This channel is *muted* \u2014 I won\u2019t wake on its messages, including ones that name me (a direct @-mention still reaches me). `/notify on` to resume." : ":bell: This channel is *active* \u2014 I wake on messages that address me by name, not on every message here (an @-mention always reaches me). `/notify off` to mute.";
39978
+ }
39979
+ return muted ? ":grey_question: Your *mute* for this channel is *saved but not in effect* \u2014 I\u2019m not in a per-channel dispatch mode right now, so it isn\u2019t changing what wakes me. It applies as soon as an operator enables one." : ":grey_question: *No mute saved* for this channel \u2014 though it wouldn\u2019t apply yet either way: I\u2019m not in a per-channel dispatch mode right now. `/notify off` saves one for when an operator enables it.";
39980
+ }
39929
39981
 
39930
39982
  // src/slack-list-channels.ts
39931
39983
  function normaliseForMatch(s) {
@@ -42870,7 +42922,8 @@ async function handleNotifyCommand(payload, codeName) {
42870
42922
  );
42871
42923
  return;
42872
42924
  }
42873
- const inactiveNote = NOTIFY_DISPATCH_MODE === "filter" ? "" : " _(note: I\u2019m not in per-channel filter mode right now, so this is saved but won\u2019t take effect until an operator enables it.)_";
42925
+ const muteIsLive = NOTIFY_DISPATCH_MODE === "filter" || NOTIFY_DISPATCH_MODE === "addressed";
42926
+ const inactiveNote = muteIsLive ? "" : " _(note: I\u2019m not in a per-channel dispatch mode right now, so this is saved but won\u2019t take effect until an operator enables it.)_";
42874
42927
  const { action } = parseNotifyCommand(payload.text, channelId);
42875
42928
  if (action === "help") {
42876
42929
  await postEphemeralViaResponseUrl(
@@ -42884,7 +42937,9 @@ async function handleNotifyCommand(payload, codeName) {
42884
42937
  const muted = MUTED_CHANNELS.has(channelId);
42885
42938
  await postEphemeralViaResponseUrl(
42886
42939
  responseUrl,
42887
- (muted ? ":mute: This channel is *muted* \u2014 I won\u2019t wake on its messages (an @-mention still reaches me). `/notify on` to resume." : ":bell: This channel is *active* \u2014 I wake on its messages. `/notify off` to mute.") + inactiveNote,
42940
+ // Pass the MODE, not muteIsLive: `filter` and `addressed` both honour the
42941
+ // mute but do not wake alike, and the status line has to say which.
42942
+ notifyStatusMessage(muted, NOTIFY_DISPATCH_MODE),
42888
42943
  codeName
42889
42944
  );
42890
42945
  return;
@@ -45405,7 +45460,20 @@ async function seedMutedChannelsFromApi() {
45405
45460
  }
45406
45461
  }
45407
45462
  function connectSocketModeSafely() {
45408
- if (NOTIFY_DISPATCH_MODE === "filter") void seedMutedChannelsFromApi();
45463
+ void startSocketModeAfterSeedingMutes();
45464
+ }
45465
+ async function startSocketModeAfterSeedingMutes() {
45466
+ if (NOTIFY_DISPATCH_MODE === "filter" || NOTIFY_DISPATCH_MODE === "addressed") {
45467
+ try {
45468
+ await seedMutedChannelsFromApi();
45469
+ } catch (err) {
45470
+ process.stderr.write(
45471
+ `slack-channel: notify-prefs seed threw, connecting anyway: ${err.message}
45472
+ `
45473
+ );
45474
+ }
45475
+ }
45476
+ if (isShuttingDown) return;
45409
45477
  void runOrRetry(connectSocketMode, {
45410
45478
  retryDelayMs: 1e4,
45411
45479
  onError: (err) => process.stderr.write(
@@ -45831,7 +45899,10 @@ async function connectSocketMode() {
45831
45899
  CHANNEL_RESPONSE_MODE,
45832
45900
  NOTIFY_DISPATCH_MODE,
45833
45901
  evt.channel,
45834
- MUTED_CHANNELS
45902
+ MUTED_CHANNELS,
45903
+ // ENG-8657: who this agent is, so `addressed` can tell a message
45904
+ // naming IT from one naming a different agent in the same channel.
45905
+ { botUserId, codeName: AGENT_CODE_NAME }
45835
45906
  ))
45836
45907
  return;
45837
45908
  }
@@ -35888,13 +35888,30 @@ var FLAG_REGISTRY = [
35888
35888
  // safe default — it resolves to `honors`, reporting every host as honouring
35889
35889
  // the flip, including hosts whose agt-cli has no reader at all.
35890
35890
  //
35891
- // 0.28.566 is the auto-publish cut from the ENG-8575 merge (583cef8d9,
35892
- // published 2026-08-12T08:32Z). Verified against the published tarball
35893
- // rather than inferred from the merge: `maybeScanToolCalls`,
35894
- // `tool-call-audit` and `tool-call-path-salt` are all present in
35895
- // package/dist/lib/manager-worker.js — the manager, which is the actual
35896
- // reader. The dist/mcp/* occurrences are bundling artifacts, not readers.
35897
- since: "0.28.566"
35891
+ // WHAT THIS VERSION HAS TO MEAN. Not "the first build with a reader" the
35892
+ // first build where flipping the flag does what the flag is documented to
35893
+ // do. Those diverged twice already, in the same direction:
35894
+ //
35895
+ // 0.28.566 (ENG-8575) — the first build with a reader. Pinned here and
35896
+ // correct on the day. It has the unbounded scan window and the coverage
35897
+ // rows that overstate (both ENG-8740), and no `logging_mode` enforcement
35898
+ // at all (ENG-8726) — so a hash-only agent on it emits plaintext
35899
+ // `argv0` / `url_host` / `mcp_tool`, which is precisely the governance
35900
+ // breach this epic exists to prevent.
35901
+ // 0.28.569 (ENG-8740) — bounded window, honest coverage intervals. Still
35902
+ // no hash-only enforcement. The pin was NOT moved at that merge and went
35903
+ // stale for a day; reach reported those hosts `honors`.
35904
+ // 0.28.570 (ENG-8726) — hash-only honoured at runtime. Current pin.
35905
+ //
35906
+ // MOVE THIS PIN whenever a change alters what arming the flag DOES on a
35907
+ // host, and verify it against the published tarball rather than inferring it
35908
+ // from the merge — `npm pack @integrity-labs/agt-cli@<v>` and grep
35909
+ // package/dist/lib/manager-worker.js (the manager is the actual reader; the
35910
+ // dist/mcp/* occurrences are bundling artifacts). For 0.28.570 the markers
35911
+ // are `readAgentLoggingMode` and `loggingModeWithholdsTargets`. Auto-publish
35912
+ // patch-bumps from whatever is on main, so if another CLI-touching PR lands
35913
+ // first the real cut is higher than this and the pin under-reports.
35914
+ since: "0.28.570"
35898
35915
  },
35899
35916
  {
35900
35917
  key: "conversation-eval-backend",
@@ -36199,9 +36216,9 @@ var FLAG_REGISTRY = [
36199
36216
  },
36200
36217
  {
36201
36218
  key: "notify-dispatch",
36202
- description: "Membership-based channel-notify dispatch (ENG-7682 / notify Slice 1). off = today's behaviour: a non-@mention top-level channel message is dropped by the mention_only engagement gate (SLACK_CHANNEL_RESPONSE_MODE). membership = the agent's Slack MCP ADMITS non-@mention channel messages in channels its bot is a member of (the Socket Mode websocket already receives them), waking the agent in-thread via the SAME existing wake path used for @mentions/DMs. Only the mention_only engagement gate is relaxed - the echo/dedup, bot_id/self, and peer-classifier safety leaves still apply, so this never opens a bot-to-bot wake loop. The channel server can't evaluate flags, so the manager materializes the resolved value into the AGT_NOTIFY_DISPATCH spawn env (operator/canary override, ADR-0022). filter = like membership (opt-out) but honours a per-channel mute list: a member-channel message wakes the agent UNLESS the user muted that channel via the /notify slash command. The manager materializes the muted set into AGT_NOTIFY_MUTED_CHANNELS from agent_notify_channel_prefs (ENG-7682 Slice 2). Ships dark (default off).",
36219
+ description: `Membership-based channel-notify dispatch (ENG-7682 / notify Slice 1). off = today's behaviour: a non-@mention top-level channel message is dropped by the mention_only engagement gate (SLACK_CHANNEL_RESPONSE_MODE). membership = the agent's Slack MCP ADMITS non-@mention channel messages in channels its bot is a member of (the Socket Mode websocket already receives them), waking the agent in-thread via the SAME existing wake path used for @mentions/DMs. Only the mention_only engagement gate is relaxed - the echo/dedup, bot_id/self, and peer-classifier safety leaves still apply, so this never opens a bot-to-bot wake loop. The channel server can't evaluate flags, so the manager materializes the resolved value into the AGT_NOTIFY_DISPATCH spawn env (operator/canary override, ADR-0022). filter = like membership (opt-out) but honours a per-channel mute list: a member-channel message wakes the agent UNLESS the user muted that channel via the /notify slash command. The manager materializes the muted set into AGT_NOTIFY_MUTED_CHANNELS from agent_notify_channel_prefs (ENG-7682 Slice 2). addressed = like filter (same per-channel mute, checked FIRST so a mute outranks being named), but a member-channel message additionally has to address THIS agent to wake it: a real Slack mention of its bot user id, \`@<code_name>\` typed verbatim, or the code name used as a vocative at the start of the message ("koda:", "hey koda"). @team / @everyone still wake everyone. This is the fix for one named agent waking every agent in a shared channel (ENG-8657); matching is deliberately conservative, so a name mentioned mid-sentence does NOT wake, and an agent whose identity is unknown to the channel server stays asleep rather than waking on everything. Ships dark (default off).`,
36203
36220
  flagType: "enum",
36204
- allowedValues: ["off", "membership", "filter"],
36221
+ allowedValues: ["off", "membership", "filter", "addressed"],
36205
36222
  // Declared safe value is `off`: the mention_only gate stays in force, byte-
36206
36223
  // identical to today. membership is the deliberate, per-agent flip that
36207
36224
  // widens what wakes the agent.
@@ -41,7 +41,7 @@ import {
41
41
  writeDirectChatSessionState,
42
42
  writeEgressAllowlist,
43
43
  writePersistentClaudeWrapper
44
- } from "./chunk-7O2TXBWR.js";
44
+ } from "./chunk-72K46XUZ.js";
45
45
  import "./chunk-XWVM4KPK.js";
46
46
  export {
47
47
  EGRESS_BASELINE_DOMAINS,
@@ -87,4 +87,4 @@ export {
87
87
  writeEgressAllowlist,
88
88
  writePersistentClaudeWrapper
89
89
  };
90
- //# sourceMappingURL=persistent-session-WUNZJXCI.js.map
90
+ //# sourceMappingURL=persistent-session-74MH2XTM.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  paneLogPath
3
- } from "./chunk-7O2TXBWR.js";
3
+ } from "./chunk-72K46XUZ.js";
4
4
  import "./chunk-XWVM4KPK.js";
5
5
 
6
6
  // src/lib/responsiveness-probe.ts
@@ -689,4 +689,4 @@ export {
689
689
  readAndResetSlackReplyBindingClassifications,
690
690
  readAndResetSlackReplyTargetClassifications
691
691
  };
692
- //# sourceMappingURL=responsiveness-probe-V3P5TGBH.js.map
692
+ //# sourceMappingURL=responsiveness-probe-5VNQQZNJ.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.28.569",
3
+ "version": "0.28.571",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {