@integrity-labs/agt-cli 0.28.300 → 0.28.301

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.
package/dist/bin/agt.js CHANGED
@@ -38,7 +38,7 @@ import {
38
38
  success,
39
39
  table,
40
40
  warn
41
- } from "../chunk-ITBY43DH.js";
41
+ } from "../chunk-HRER2SCW.js";
42
42
  import {
43
43
  CHANNEL_REGISTRY,
44
44
  DEFAULT_FRAMEWORK,
@@ -67,7 +67,7 @@ import {
67
67
  renderTemplate,
68
68
  resolveChannels,
69
69
  serializeManifestForSlackCli
70
- } from "../chunk-KMJHNKPQ.js";
70
+ } from "../chunk-E6L7SSE7.js";
71
71
  import "../chunk-XWVM4KPK.js";
72
72
 
73
73
  // src/bin/agt.ts
@@ -4826,7 +4826,7 @@ import { execFileSync, execSync } from "child_process";
4826
4826
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4827
4827
  import chalk18 from "chalk";
4828
4828
  import ora16 from "ora";
4829
- var cliVersion = true ? "0.28.300" : "dev";
4829
+ var cliVersion = true ? "0.28.301" : "dev";
4830
4830
  async function fetchLatestVersion() {
4831
4831
  const host2 = getHost();
4832
4832
  if (!host2) return null;
@@ -5843,7 +5843,7 @@ function handleError(err) {
5843
5843
  }
5844
5844
 
5845
5845
  // src/bin/agt.ts
5846
- var cliVersion2 = true ? "0.28.300" : "dev";
5846
+ var cliVersion2 = true ? "0.28.301" : "dev";
5847
5847
  var program = new Command();
5848
5848
  program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
5849
5849
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -2362,7 +2362,7 @@ function runTelegramPeerRules(diagnostics, charter, peers, teamPeers, grants, no
2362
2362
  for (let i = 0; i < peers.length; i++) {
2363
2363
  const peer = peers[i];
2364
2364
  const path = `multi_agent.telegram_peers[${i}]`;
2365
- const match = teamPeers.find((p) => p.telegram_bot_id === peer.bot_id);
2365
+ const match = teamPeers.find((p2) => p2.telegram_bot_id === peer.bot_id);
2366
2366
  if (peer.code_name === charter.code_name || match?.agent_id === charter.agent_id) {
2367
2367
  diagnostics.push({
2368
2368
  file: "CHARTER.md",
@@ -2473,7 +2473,7 @@ function runSlackPeerRules(diagnostics, charter, peers, teamPeers, grants, now)
2473
2473
  for (let i = 0; i < peers.length; i++) {
2474
2474
  const peer = peers[i];
2475
2475
  const path = `multi_agent.slack_peers[${i}]`;
2476
- const match = teamPeers.find((p) => p.slack_bot_user_id === peer.bot_user_id);
2476
+ const match = teamPeers.find((p2) => p2.slack_bot_user_id === peer.bot_user_id);
2477
2477
  if (peer.code_name === charter.code_name || match?.agent_id === charter.agent_id) {
2478
2478
  diagnostics.push({
2479
2479
  file: "CHARTER.md",
@@ -3097,6 +3097,167 @@ var ajv2 = new Ajv20202({ allErrors: true, strict: false });
3097
3097
  addFormats2(ajv2);
3098
3098
  var compiledMetaSchema = ajv2.compile(context_meta_schema_default);
3099
3099
 
3100
+ // ../../packages/core/dist/integrations/tool-tier-heuristic.js
3101
+ var READ_VERBS = "GET|LIST|FIND|FETCH|RETRIEVE|SEARCH|QUERY|DESCRIBE|INSPECT|SCAN|SHOW|VIEW|READ|EXPORT|DOWNLOAD";
3102
+ var NO_READ_VERB_ACTION = `(?!(?:^|.*[_-])(${READ_VERBS})[_-])`;
3103
+ var NO_READ_VERB_INCL_SUFFIX = `(?!(?:^|.*[_-])(${READ_VERBS})(?:[_-]|$))`;
3104
+ function p(re) {
3105
+ return { re, label: re.source };
3106
+ }
3107
+ function highRisk(core) {
3108
+ return { re: new RegExp(`^${NO_READ_VERB_ACTION}.*${core.source}`, "i"), label: core.source };
3109
+ }
3110
+ var TIER_PATTERNS = [
3111
+ {
3112
+ tier: "admin",
3113
+ patterns: [
3114
+ p(/_PERMISSION/i),
3115
+ p(/_GRANT[_S]?(_|$)/i),
3116
+ p(/_AUTHORI[SZ]E/i),
3117
+ // Reading OAuth grants / a webhook's config can expose secrets or the
3118
+ // full authorization surface, so — unlike _SETTINGS/_CONFIG — these
3119
+ // stay admin even with a read verb (deliberate; see the
3120
+ // tool-tier-heuristic test for HUBSPOT_LIST_GRANTED_OAUTH_SCOPES /
3121
+ // ATTIO_GET_WEBHOOK).
3122
+ p(/_OAUTH/i),
3123
+ p(/_WEBHOOK/i),
3124
+ // SETTINGS / CONFIG are admin only when MUTATED. A read verb anywhere —
3125
+ // prefix (GET_..._SETTINGS), infix (..._GET_..._SETTINGS), or suffix
3126
+ // (..._SETTINGS_GET / ..._SETTINGS_LIST) — means it's a settings
3127
+ // *lookup*, so it falls through to `read` and auto-executes instead of
3128
+ // routing to approval and hanging (e.g. GOOGLEANALYTICS_GET_DATA_RETENTION_SETTINGS,
3129
+ // GOOGLECALENDAR_LIST_SETTINGS, GOOGLECALENDAR_SETTINGS_GET). The suffix
3130
+ // form is safe HERE because the object noun (SETTINGS/CONFIG) is
3131
+ // unambiguous; the generic high-risk guard stays suffix-blind on purpose
3132
+ // (a trailing _LIST/_VIEW can be a noun — ENG-7684). Unlike
3133
+ // _OAUTH/_WEBHOOK/_CREDENTIAL/_VAULT/_PERMISSION above, reading app
3134
+ // settings/config is benign, so only the mutating form stays admin.
3135
+ p(new RegExp(`^${NO_READ_VERB_INCL_SUFFIX}.*_SETTINGS?(_|$)`, "i")),
3136
+ p(new RegExp(`^${NO_READ_VERB_INCL_SUFFIX}.*_CONFIG`, "i")),
3137
+ p(/_VAULT/i),
3138
+ p(/_CREDENTIAL/i),
3139
+ p(/_ENROL/i),
3140
+ p(/_REGISTER/i)
3141
+ ]
3142
+ },
3143
+ {
3144
+ tier: "write_destructive",
3145
+ patterns: [
3146
+ p(/_BATCH_DELETE/i),
3147
+ p(/_DELETE(_|$)/i),
3148
+ p(/_REVOKE/i),
3149
+ p(/_REMOVE(_|$)/i),
3150
+ p(/_TRASH/i),
3151
+ p(/_DROP(_|$)/i),
3152
+ p(/_CLEAR(_|$)/i),
3153
+ p(/_HIDE(_|$)/i),
3154
+ // Kebab-case verbs used by native MCP servers (e.g. xero's `void-invoice`).
3155
+ p(/^void-/i)
3156
+ ]
3157
+ },
3158
+ {
3159
+ // Every pattern here is read-verb-guarded (ENG-7684): a high-risk NOUN
3160
+ // (_EMAIL, _IMPORT, _FORWARD, _POST, _PUBLISH) inside a read-verb name
3161
+ // (…_GET_…, …_FETCH_…) is a read, not a high-risk action, and must
3162
+ // auto-execute instead of routing to approval.
3163
+ tier: "write_high_risk",
3164
+ patterns: [
3165
+ highRisk(/_BATCH_MODIFY/i),
3166
+ highRisk(/_SEND(_|$)/i),
3167
+ highRisk(/_POST(_|$)/i),
3168
+ highRisk(/_PUBLISH/i),
3169
+ highRisk(/_REPLY/i),
3170
+ // Message/email forwarding is high-risk. The negative lookbehind
3171
+ // exempts browser *navigation* forward (e.g. Anchor's
3172
+ // `anchor_navigate_forward`), which is benign and classifies as read;
3173
+ // the read-verb guard additionally exempts GMAIL_GET_AUTO_FORWARDING.
3174
+ highRisk(/(?<!navigate)_FORWARD/i),
3175
+ highRisk(/_EMAIL/i),
3176
+ highRisk(/_INVITE/i),
3177
+ highRisk(/_NOTIFY/i),
3178
+ highRisk(/_IMPORT/i),
3179
+ // Sharing-preference MUTATIONS grant external access to content —
3180
+ // exfiltration-shaped, so they must not fall through to the generic
3181
+ // `_ADD`/`_UPDATE` write patterns (ENG-6027 council finding: e.g.
3182
+ // GOOGLEDRIVE_ADD_FILE_SHARING_PREFERENCE). Anchored to a mutating
3183
+ // verb so read-shaped names (METAADS_LIST_*_SHARING_REQUESTS,
3184
+ // GOOGLEANALYTICS_GET_DATA_SHARING_SETTINGS) keep their read/admin
3185
+ // classification.
3186
+ highRisk(/_(ADD|UPDATE|SET|CREATE|MODIFY|CHANGE|ENABLE)_[A-Z0-9_]*SHAR(E|ING)/i)
3187
+ ]
3188
+ },
3189
+ {
3190
+ tier: "write",
3191
+ patterns: [
3192
+ p(/_ASSERT/i),
3193
+ p(/_UPSERT/i),
3194
+ p(/_PATCH/i),
3195
+ // The negative lookbehind prevents `MONDAY_GET_UPDATES` (and similar
3196
+ // "fetch the comment thread" reads) from being mis-tagged as a write
3197
+ // just because the noun happens to be "update".
3198
+ p(/(?<!_GET)_UPDATE/i),
3199
+ p(/_INSERT/i),
3200
+ p(/_CREATE/i),
3201
+ p(/_ADD(_|$)/i),
3202
+ p(/_MOVE(_|$)/i),
3203
+ p(/_COPY(_|$)/i),
3204
+ // Kebab-case verbs used by native MCP servers (e.g. xero).
3205
+ p(/^create-/i),
3206
+ p(/^update-/i),
3207
+ p(/^attach-/i)
3208
+ ]
3209
+ },
3210
+ {
3211
+ tier: "read",
3212
+ patterns: [
3213
+ p(/_GET/i),
3214
+ p(/_FIND/i),
3215
+ p(/_LIST/i),
3216
+ p(/_SEARCH/i),
3217
+ p(/_FETCH/i),
3218
+ p(/_RETRIEVE/i),
3219
+ p(/_EXPORT/i),
3220
+ p(/_DOWNLOAD/i),
3221
+ p(/_READ(_|$)/i),
3222
+ p(/_VIEW(_|$)/i),
3223
+ // Cloud-style verbs (used by aws_*, gcloud, kubectl etc.) and other
3224
+ // common read-shaped names that don't follow Composio's GET prefix.
3225
+ p(/_DESCRIBE/i),
3226
+ p(/_CHECK/i),
3227
+ p(/_INSPECT/i),
3228
+ p(/_QUERY/i),
3229
+ p(/_SCAN/i),
3230
+ p(/_SHOW(_|$)/i),
3231
+ // Native MCP servers use bare leading verbs in snake_case (Kajabi:
3232
+ // `get_landing_page`, `list_people`) or kebab-case (xero: `list-invoices`,
3233
+ // `get-invoice`; github: `search-code`; granola: `read-transcript`). The
3234
+ // uppercase/infix `_GET`/`_LIST` patterns miss both, so they fell through
3235
+ // to the `write` fallback. One delimiter-agnostic pattern covers every
3236
+ // read verb in either convention. Read is the lowest-precedence tier, so
3237
+ // a leading-verb MUTATION still matches earlier: `get_or_create_x` hits
3238
+ // `write` (_CREATE), `list_credentials` hits `admin` (_CREDENTIAL).
3239
+ // ENG-7684.
3240
+ p(new RegExp(`^(${READ_VERBS})[_-]`, "i")),
3241
+ // `report-*` (xero's `report-profit-and-loss`) — not a read verb but a
3242
+ // read-shaped native prefix. Anchored so it can't match report-* writers.
3243
+ p(/^report-/i),
3244
+ // ENG-5855: Anchor Browser observation tools (hosted MCP, `anchor_*`
3245
+ // names). Anchored to `^anchor_` so they only ever classify Anchor's
3246
+ // own tools and can't reclassify another toolkit's keys when the seed
3247
+ // is regenerated. The other read-shaped Anchor tools already match
3248
+ // generic patterns (`anchor_get_body_html` → _GET, `anchor_tab_list`
3249
+ // → _LIST). `anchor_network_requests` is deliberately NOT here — it
3250
+ // dumps auth headers/tokens, so it's raised to write_high_risk as a
3251
+ // manual escalation in the seed.
3252
+ p(/^anchor_navigate/i),
3253
+ p(/^anchor_snapshot/i),
3254
+ p(/^anchor_take_screenshot/i),
3255
+ p(/^anchor_wait_for/i),
3256
+ p(/^anchor_console_messages/i)
3257
+ ]
3258
+ }
3259
+ ];
3260
+
3100
3261
  // ../../packages/core/dist/integrations/augmented-live/markup.js
3101
3262
  var MARKUP_MARKER = "__augmentedLiveMarkup";
3102
3263
  var MARKUP_CONTROL_MARKER = "__augmentedLiveMarkupControl";
@@ -4354,11 +4515,11 @@ function resolveProbeTool(tools, override) {
4354
4515
  }
4355
4516
  function isAccountResolutionError(message) {
4356
4517
  const m = message.toLowerCase();
4357
- return ACCOUNT_RESOLUTION_ERROR_PATTERNS.some((p) => m.includes(p));
4518
+ return ACCOUNT_RESOLUTION_ERROR_PATTERNS.some((p2) => m.includes(p2));
4358
4519
  }
4359
4520
  function isUpstreamAuthError(message) {
4360
4521
  const m = message.toLowerCase();
4361
- if (UPSTREAM_AUTH_ERROR_PATTERNS.some((p) => m.includes(p)))
4522
+ if (UPSTREAM_AUTH_ERROR_PATTERNS.some((p2) => m.includes(p2)))
4362
4523
  return true;
4363
4524
  if (/\b(401|403)\s+client error/.test(m))
4364
4525
  return true;
@@ -5036,7 +5197,7 @@ var INTEGRATION_REGISTRY = [
5036
5197
  id: "video-gen",
5037
5198
  name: "Video Generation",
5038
5199
  category: "media",
5039
- description: "AI video generation from a text prompt. An agent passes a prompt to generate_video and gets back a short generated video with audio, which it can deliver to a chat channel. Augmented Team manages the model access for you - there is no key to enter. Generation runs direct against xAI (Grok Imagine Video 1.5 today). It is a PREMIUM, usage-billed capability: gated on a per-org opt-in and a monthly USD budget, and metered per second of generated video.",
5200
+ description: "AI video generation from a text prompt or an input image. An agent passes a prompt (plus optionally image_url) to generate_video and gets back a short generated video with audio, which it can deliver to a chat channel. Augmented Team manages the model access for you - there is no key to enter. Generation runs direct against xAI Grok Imagine: text-to-video on the base grok-imagine-video model, image-to-video on grok-imagine-video-1.5. It is a PREMIUM, usage-billed capability: gated on a per-org opt-in and a monthly USD budget, and metered per second of generated video.",
5040
5201
  // Platform-key model (mirrors Grok Voice / ADR-0031): Augmented holds one xAI
5041
5202
  // account key (XAI_API_KEY) and every customer render bills back to it, so
5042
5203
  // auth is `none` - customers never enter a key.
@@ -5063,6 +5224,10 @@ var INTEGRATION_REGISTRY = [
5063
5224
  pricing: "usage",
5064
5225
  note: "Billed per second of generated video; the rate depends on the resolution.",
5065
5226
  meters: [
5227
+ // 1.0 (grok-imagine-video) is the text-to-video model (ENG-7696: xAI's
5228
+ // 1.5 is image-to-video ONLY, so t2v runs on the base model).
5229
+ { event_type: "grok_imagine_video_1_0_480p", unit: "second" },
5230
+ { event_type: "grok_imagine_video_1_0_720p", unit: "second" },
5066
5231
  { event_type: "grok_imagine_video_1_5_480p", unit: "second" },
5067
5232
  { event_type: "grok_imagine_video_1_5_720p", unit: "second" },
5068
5233
  // 1080p is image-to-video only (xAI restriction); metered when the
@@ -6378,6 +6543,9 @@ function stripTrailingSlash(value) {
6378
6543
  return value.replace(/\/+$/, "");
6379
6544
  }
6380
6545
 
6546
+ // ../../packages/core/dist/delivery/scheduled-turn-marker.js
6547
+ var SCHEDULED_TURN_MARKER_FILENAME = ".current-scheduled-turn.json";
6548
+
6381
6549
  // ../../packages/core/dist/liveness/agent-liveness.js
6382
6550
  var FRESH_HEARTBEAT_THRESHOLD_MS = 2 * 60 * 1e3;
6383
6551
 
@@ -7588,6 +7756,20 @@ var FLAG_REGISTRY = [
7588
7756
  // explicit confirm (ADR-0022 §4).
7589
7757
  sensitive: true
7590
7758
  },
7759
+ {
7760
+ key: "notify-dispatch",
7761
+ 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). Enum leaves room for a later Slice 2 'filter' value (per-channel filters). Ships dark (default off).",
7762
+ flagType: "enum",
7763
+ allowedValues: ["off", "membership"],
7764
+ // Declared safe value is `off`: the mention_only gate stays in force, byte-
7765
+ // identical to today. membership is the deliberate, per-agent flip that
7766
+ // widens what wakes the agent.
7767
+ defaultValue: "off",
7768
+ envVar: "AGT_NOTIFY_DISPATCH",
7769
+ // membership widens agent-wake ingress (more inbound wakes = more cost /
7770
+ // surface), so flipping it on is worth an explicit confirm (ADR-0022 §4).
7771
+ sensitive: true
7772
+ },
7591
7773
  {
7592
7774
  key: "workflows-down-sync",
7593
7775
  description: "Down-sync active dynamic workflows to agents via /host/refresh (ADR-0012, ENG-6352). When on, the API populates the per-agent workflow set (team default \u222A agent override) and the claude-code adapter writes each as .claude/workflows/<name>.js. Boolean gate; ships dark.",
@@ -7981,8 +8163,8 @@ function minutesSinceLocalMidnight(now = /* @__PURE__ */ new Date(), timezone) {
7981
8163
  hourCycle: "h23"
7982
8164
  });
7983
8165
  const parts = fmt.formatToParts(now);
7984
- const hh = Number(parts.find((p) => p.type === "hour")?.value ?? "0");
7985
- const mm = Number(parts.find((p) => p.type === "minute")?.value ?? "0");
8166
+ const hh = Number(parts.find((p2) => p2.type === "hour")?.value ?? "0");
8167
+ const mm = Number(parts.find((p2) => p2.type === "minute")?.value ?? "0");
7986
8168
  if (Number.isFinite(hh) && Number.isFinite(mm)) return hh * 60 + mm;
7987
8169
  } catch {
7988
8170
  }
@@ -8329,10 +8511,10 @@ function resolveClaudeBinary() {
8329
8511
  "/opt/homebrew/bin/claude",
8330
8512
  "/usr/local/bin/claude"
8331
8513
  ];
8332
- for (const p of candidates) {
8333
- if (existsSync3(p)) {
8334
- cachedClaudePath = p;
8335
- return p;
8514
+ for (const p2 of candidates) {
8515
+ if (existsSync3(p2)) {
8516
+ cachedClaudePath = p2;
8517
+ return p2;
8336
8518
  }
8337
8519
  }
8338
8520
  return "claude";
@@ -8377,10 +8559,10 @@ function egressAllowlistHostPath(codeName, homeDir) {
8377
8559
  return join2(home, ".augmented", "_egress", `${codeName}.txt`);
8378
8560
  }
8379
8561
  function writeEgressAllowlist(codeName, domains, homeDir) {
8380
- const p = egressAllowlistHostPath(codeName, homeDir);
8381
- mkdirSync2(dirname(p), { recursive: true });
8382
- writeFileSync3(p, domains.join("\n") + "\n", { mode: 420 });
8383
- return p;
8562
+ const p2 = egressAllowlistHostPath(codeName, homeDir);
8563
+ mkdirSync2(dirname(p2), { recursive: true });
8564
+ writeFileSync3(p2, domains.join("\n") + "\n", { mode: 420 });
8565
+ return p2;
8384
8566
  }
8385
8567
  var EGRESS_DOCKER_TIMEOUT_MS = 1e4;
8386
8568
  function isNoSuchContainer(err) {
@@ -8413,7 +8595,7 @@ function restartEgressSidecar(codeName) {
8413
8595
  }
8414
8596
  }
8415
8597
  function buildDockerRunCommand(args) {
8416
- const { codeName, agentId, wrapperPath, projectDir, homeDir, runId, passApiKey, passOpenRouter, egress, forwardSlackReplyBinding, forwardBlockTurnEndAllMarkers, forwardKanbanWaiting } = args;
8598
+ const { codeName, agentId, wrapperPath, projectDir, homeDir, runId, passApiKey, passOpenRouter, egress, forwardSlackReplyBinding, forwardBlockTurnEndAllMarkers, forwardKanbanWaiting, forwardNotifyDispatch } = args;
8417
8599
  const q = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
8418
8600
  const agentDir = join2(homeDir, ".augmented", codeName);
8419
8601
  const agentIdDir = join2(homeDir, ".augmented", agentId);
@@ -8449,6 +8631,7 @@ function buildDockerRunCommand(args) {
8449
8631
  if (forwardSlackReplyBinding) envArgs.push("-e AGT_SLACK_REPLY_BINDING");
8450
8632
  if (forwardBlockTurnEndAllMarkers) envArgs.push("-e AGT_BLOCK_TURN_END_ALL_MARKERS_ENABLED");
8451
8633
  if (forwardKanbanWaiting) envArgs.push("-e AGT_KANBAN_WAITING_ENABLED");
8634
+ if (forwardNotifyDispatch) envArgs.push("-e AGT_NOTIFY_DISPATCH");
8452
8635
  const egressImage = process.env.AGT_EGRESS_IMAGE || "agt-squid:latest";
8453
8636
  const internalNet = `agt-net-${codeName}`;
8454
8637
  const squidName = `agt-squid-${codeName}`;
@@ -8647,9 +8830,9 @@ function readDirectChatSessionState(agentId) {
8647
8830
  }
8648
8831
  }
8649
8832
  function writeDirectChatSessionState(agentId, state) {
8650
- const p = directChatSessionStatePath(agentId);
8651
- mkdirSync2(dirname(p), { recursive: true });
8652
- writeFileSync3(p, JSON.stringify(state));
8833
+ const p2 = directChatSessionStatePath(agentId);
8834
+ mkdirSync2(dirname(p2), { recursive: true });
8835
+ writeFileSync3(p2, JSON.stringify(state));
8653
8836
  }
8654
8837
  function startPersistentSession(config) {
8655
8838
  const existing = sessions.get(config.codeName);
@@ -8707,11 +8890,11 @@ function spawnSession(config, session) {
8707
8890
  } else {
8708
8891
  const claudeDir = join2(homedir2(), ".claude");
8709
8892
  for (const filename of [".credentials.json", "credentials.json"]) {
8710
- const p = join2(claudeDir, filename);
8711
- if (existsSync3(p)) {
8893
+ const p2 = join2(claudeDir, filename);
8894
+ if (existsSync3(p2)) {
8712
8895
  try {
8713
- rmSync(p, { force: true });
8714
- log(`[persistent-session] Removed ${p} (api_key mode active \u2014 preventing OAuth fallback)`);
8896
+ rmSync(p2, { force: true });
8897
+ log(`[persistent-session] Removed ${p2} (api_key mode active \u2014 preventing OAuth fallback)`);
8715
8898
  } catch {
8716
8899
  }
8717
8900
  }
@@ -8799,6 +8982,9 @@ function spawnSession(config, session) {
8799
8982
  if (config.kanbanWaitingEnabled && !process.env["AGT_KANBAN_WAITING_ENABLED"]) {
8800
8983
  tmuxSessionEnvArgs.push("-e", "AGT_KANBAN_WAITING_ENABLED=true");
8801
8984
  }
8985
+ if (config.notifyDispatchMode && config.notifyDispatchMode !== "off" && !process.env["AGT_NOTIFY_DISPATCH"]) {
8986
+ tmuxSessionEnvArgs.push("-e", `AGT_NOTIFY_DISPATCH=${config.notifyDispatchMode}`);
8987
+ }
8802
8988
  const sessionHomeDir = process.env.HOME?.trim() || homedir2();
8803
8989
  let egress;
8804
8990
  if (egressMode(codeName) === "allowlist") {
@@ -8826,8 +9012,12 @@ function spawnSession(config, session) {
8826
9012
  // feature-gate-allow: registry-flag envVar operator-override precedence, not a new gate
8827
9013
  // ENG-7493 (ADR-0044): forward AGT_KANBAN_WAITING_ENABLED if it will be in
8828
9014
  // the session env (operator-set OR materialized from the flag above).
8829
- forwardKanbanWaiting: !!process.env["AGT_KANBAN_WAITING_ENABLED"] || !!config.kanbanWaitingEnabled
9015
+ forwardKanbanWaiting: !!process.env["AGT_KANBAN_WAITING_ENABLED"] || !!config.kanbanWaitingEnabled,
8830
9016
  // feature-gate-allow: registry-flag envVar operator-override precedence, not a new gate
9017
+ // ENG-7682 (notify Slice 1): forward AGT_NOTIFY_DISPATCH if it will be in
9018
+ // the session env (operator-set OR materialized from the flag above).
9019
+ forwardNotifyDispatch: !!process.env["AGT_NOTIFY_DISPATCH"] || // feature-gate-allow: registry-flag envVar operator-override precedence, not a new gate
9020
+ !!config.notifyDispatchMode && config.notifyDispatchMode !== "off"
8831
9021
  }) : JSON.stringify(wrapperPath);
8832
9022
  const tmuxEnv = {
8833
9023
  ...process.env,
@@ -8914,7 +9104,7 @@ function hasMcpChildren(tmuxSession) {
8914
9104
  { encoding: "utf-8" }
8915
9105
  ).trim();
8916
9106
  if (!claudePidOut) return false;
8917
- const pids = claudePidOut.split("\n").map((p) => Number(p)).filter((p) => p > 0);
9107
+ const pids = claudePidOut.split("\n").map((p2) => Number(p2)).filter((p2) => p2 > 0);
8918
9108
  if (pids.length === 0) return false;
8919
9109
  const claudePid = Math.max(...pids);
8920
9110
  const childrenOut = execSync(
@@ -8922,7 +9112,7 @@ function hasMcpChildren(tmuxSession) {
8922
9112
  { encoding: "utf-8" }
8923
9113
  ).trim();
8924
9114
  if (!childrenOut) return false;
8925
- const childPids = childrenOut.split("\n").map((p) => p.trim()).filter(Boolean);
9115
+ const childPids = childrenOut.split("\n").map((p2) => p2.trim()).filter(Boolean);
8926
9116
  for (const cp of childPids) {
8927
9117
  const cmdline = execSync(
8928
9118
  `cat /proc/${cp}/cmdline 2>/dev/null | tr '\\0' ' ' || ps -p ${cp} -o args= 2>/dev/null || true`,
@@ -9441,6 +9631,7 @@ export {
9441
9631
  resolveDmTarget,
9442
9632
  isResolveError,
9443
9633
  deriveConsoleUrl,
9634
+ SCHEDULED_TURN_MARKER_FILENAME,
9444
9635
  parseUsageBanner,
9445
9636
  formatRunMarker,
9446
9637
  parseTranscriptUsage,
@@ -9510,4 +9701,4 @@ export {
9510
9701
  stopAllSessionsAndWait,
9511
9702
  getProjectDir
9512
9703
  };
9513
- //# sourceMappingURL=chunk-KMJHNKPQ.js.map
9704
+ //# sourceMappingURL=chunk-E6L7SSE7.js.map