@integrity-labs/agt-cli 0.28.300 → 0.28.302

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-D5BJLFH7.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-5WQATS6J.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.302" : "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.302" : "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
 
@@ -7060,6 +7228,73 @@ var gdriveCommentsTriggerAdapter = {
7060
7228
  };
7061
7229
  registerTriggerSource(gdriveCommentsTriggerAdapter);
7062
7230
 
7231
+ // ../../packages/core/dist/triggers/adapters/video-render.js
7232
+ var VIDEO_RENDER_TRIGGER_PROVIDER = "video_render";
7233
+ function isFetcher(v) {
7234
+ return !!v && typeof v.fetchRenderState === "function";
7235
+ }
7236
+ function sanitizeCode(code) {
7237
+ if (!code)
7238
+ return null;
7239
+ const cleaned = code.trim().toLowerCase().replace(/[^a-z0-9_]/g, "").slice(0, 64);
7240
+ return cleaned || null;
7241
+ }
7242
+ function collectInstruction(config) {
7243
+ return `Collect it now: call generate_video with ONLY {"request_id": "${config.resume_handle}"} (do not resend the prompt - resubmitting starts a new billed render). The tool returns a short-lived download URL; download it to a file under your project directory and deliver it with your channel's upload_file tool.`;
7244
+ }
7245
+ async function poll(ctx, trigger) {
7246
+ const config = trigger.config;
7247
+ if (!config.request_id || !config.resume_handle) {
7248
+ throw new Error("video_render trigger config requires request_id and resume_handle");
7249
+ }
7250
+ if (!isFetcher(ctx.credentials)) {
7251
+ throw new Error("video_render poll requires a VideoRenderStatusFetcher via ctx.credentials");
7252
+ }
7253
+ const state = await ctx.credentials.fetchRenderState(config.request_id);
7254
+ if (state.state === "pending") {
7255
+ return { events: [], cursor: ctx.cursor };
7256
+ }
7257
+ const occurredAt = (/* @__PURE__ */ new Date()).toISOString();
7258
+ const base = {
7259
+ provider: VIDEO_RENDER_TRIGGER_PROVIDER,
7260
+ occurredAt,
7261
+ // One event per render, ever - immutable identity, dedup-enforced.
7262
+ dedupKey: `vr:${config.request_id}`,
7263
+ // Platform-originated content only (see module header) - renders the clean
7264
+ // un-fenced internal header instead of the external-content fence.
7265
+ sourceTrust: "internal",
7266
+ meaningful: true
7267
+ };
7268
+ let event;
7269
+ if (state.state === "done") {
7270
+ event = {
7271
+ ...base,
7272
+ title: "Video render complete",
7273
+ body: `Your video render has finished. ${collectInstruction(config)}`
7274
+ };
7275
+ } else if (state.state === "failed") {
7276
+ const code = sanitizeCode(state.code);
7277
+ event = {
7278
+ ...base,
7279
+ title: "Video render failed",
7280
+ body: `Your video render failed provider-side${code ? ` (code: ${code})` : ""}. It was not delivered and cannot be collected. If the video is still needed, submit a new generate_video request (a fresh prompt - the old request_id is dead).`
7281
+ };
7282
+ } else {
7283
+ event = {
7284
+ ...base,
7285
+ title: "Video render expired",
7286
+ body: `Your video render expired before it was collected (the provider no longer holds the output). If the video is still needed, submit a new generate_video request (a fresh prompt - the old request_id is dead).`
7287
+ };
7288
+ }
7289
+ return { events: [event], cursor: ctx.cursor, complete: true };
7290
+ }
7291
+ var videoRenderTriggerAdapter = {
7292
+ provider: VIDEO_RENDER_TRIGGER_PROVIDER,
7293
+ kind: "poll",
7294
+ poll
7295
+ };
7296
+ registerTriggerSource(videoRenderTriggerAdapter);
7297
+
7063
7298
  // ../../packages/core/dist/feature-flags/registry.js
7064
7299
  var FLAG_REGISTRY = [
7065
7300
  {
@@ -7588,6 +7823,20 @@ var FLAG_REGISTRY = [
7588
7823
  // explicit confirm (ADR-0022 §4).
7589
7824
  sensitive: true
7590
7825
  },
7826
+ {
7827
+ key: "notify-dispatch",
7828
+ 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).",
7829
+ flagType: "enum",
7830
+ allowedValues: ["off", "membership"],
7831
+ // Declared safe value is `off`: the mention_only gate stays in force, byte-
7832
+ // identical to today. membership is the deliberate, per-agent flip that
7833
+ // widens what wakes the agent.
7834
+ defaultValue: "off",
7835
+ envVar: "AGT_NOTIFY_DISPATCH",
7836
+ // membership widens agent-wake ingress (more inbound wakes = more cost /
7837
+ // surface), so flipping it on is worth an explicit confirm (ADR-0022 §4).
7838
+ sensitive: true
7839
+ },
7591
7840
  {
7592
7841
  key: "workflows-down-sync",
7593
7842
  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 +8230,8 @@ function minutesSinceLocalMidnight(now = /* @__PURE__ */ new Date(), timezone) {
7981
8230
  hourCycle: "h23"
7982
8231
  });
7983
8232
  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");
8233
+ const hh = Number(parts.find((p2) => p2.type === "hour")?.value ?? "0");
8234
+ const mm = Number(parts.find((p2) => p2.type === "minute")?.value ?? "0");
7986
8235
  if (Number.isFinite(hh) && Number.isFinite(mm)) return hh * 60 + mm;
7987
8236
  } catch {
7988
8237
  }
@@ -8329,10 +8578,10 @@ function resolveClaudeBinary() {
8329
8578
  "/opt/homebrew/bin/claude",
8330
8579
  "/usr/local/bin/claude"
8331
8580
  ];
8332
- for (const p of candidates) {
8333
- if (existsSync3(p)) {
8334
- cachedClaudePath = p;
8335
- return p;
8581
+ for (const p2 of candidates) {
8582
+ if (existsSync3(p2)) {
8583
+ cachedClaudePath = p2;
8584
+ return p2;
8336
8585
  }
8337
8586
  }
8338
8587
  return "claude";
@@ -8377,10 +8626,10 @@ function egressAllowlistHostPath(codeName, homeDir) {
8377
8626
  return join2(home, ".augmented", "_egress", `${codeName}.txt`);
8378
8627
  }
8379
8628
  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;
8629
+ const p2 = egressAllowlistHostPath(codeName, homeDir);
8630
+ mkdirSync2(dirname(p2), { recursive: true });
8631
+ writeFileSync3(p2, domains.join("\n") + "\n", { mode: 420 });
8632
+ return p2;
8384
8633
  }
8385
8634
  var EGRESS_DOCKER_TIMEOUT_MS = 1e4;
8386
8635
  function isNoSuchContainer(err) {
@@ -8413,7 +8662,7 @@ function restartEgressSidecar(codeName) {
8413
8662
  }
8414
8663
  }
8415
8664
  function buildDockerRunCommand(args) {
8416
- const { codeName, agentId, wrapperPath, projectDir, homeDir, runId, passApiKey, passOpenRouter, egress, forwardSlackReplyBinding, forwardBlockTurnEndAllMarkers, forwardKanbanWaiting } = args;
8665
+ const { codeName, agentId, wrapperPath, projectDir, homeDir, runId, passApiKey, passOpenRouter, egress, forwardSlackReplyBinding, forwardBlockTurnEndAllMarkers, forwardKanbanWaiting, forwardNotifyDispatch } = args;
8417
8666
  const q = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
8418
8667
  const agentDir = join2(homeDir, ".augmented", codeName);
8419
8668
  const agentIdDir = join2(homeDir, ".augmented", agentId);
@@ -8449,6 +8698,7 @@ function buildDockerRunCommand(args) {
8449
8698
  if (forwardSlackReplyBinding) envArgs.push("-e AGT_SLACK_REPLY_BINDING");
8450
8699
  if (forwardBlockTurnEndAllMarkers) envArgs.push("-e AGT_BLOCK_TURN_END_ALL_MARKERS_ENABLED");
8451
8700
  if (forwardKanbanWaiting) envArgs.push("-e AGT_KANBAN_WAITING_ENABLED");
8701
+ if (forwardNotifyDispatch) envArgs.push("-e AGT_NOTIFY_DISPATCH");
8452
8702
  const egressImage = process.env.AGT_EGRESS_IMAGE || "agt-squid:latest";
8453
8703
  const internalNet = `agt-net-${codeName}`;
8454
8704
  const squidName = `agt-squid-${codeName}`;
@@ -8647,9 +8897,9 @@ function readDirectChatSessionState(agentId) {
8647
8897
  }
8648
8898
  }
8649
8899
  function writeDirectChatSessionState(agentId, state) {
8650
- const p = directChatSessionStatePath(agentId);
8651
- mkdirSync2(dirname(p), { recursive: true });
8652
- writeFileSync3(p, JSON.stringify(state));
8900
+ const p2 = directChatSessionStatePath(agentId);
8901
+ mkdirSync2(dirname(p2), { recursive: true });
8902
+ writeFileSync3(p2, JSON.stringify(state));
8653
8903
  }
8654
8904
  function startPersistentSession(config) {
8655
8905
  const existing = sessions.get(config.codeName);
@@ -8707,11 +8957,11 @@ function spawnSession(config, session) {
8707
8957
  } else {
8708
8958
  const claudeDir = join2(homedir2(), ".claude");
8709
8959
  for (const filename of [".credentials.json", "credentials.json"]) {
8710
- const p = join2(claudeDir, filename);
8711
- if (existsSync3(p)) {
8960
+ const p2 = join2(claudeDir, filename);
8961
+ if (existsSync3(p2)) {
8712
8962
  try {
8713
- rmSync(p, { force: true });
8714
- log(`[persistent-session] Removed ${p} (api_key mode active \u2014 preventing OAuth fallback)`);
8963
+ rmSync(p2, { force: true });
8964
+ log(`[persistent-session] Removed ${p2} (api_key mode active \u2014 preventing OAuth fallback)`);
8715
8965
  } catch {
8716
8966
  }
8717
8967
  }
@@ -8799,6 +9049,9 @@ function spawnSession(config, session) {
8799
9049
  if (config.kanbanWaitingEnabled && !process.env["AGT_KANBAN_WAITING_ENABLED"]) {
8800
9050
  tmuxSessionEnvArgs.push("-e", "AGT_KANBAN_WAITING_ENABLED=true");
8801
9051
  }
9052
+ if (config.notifyDispatchMode && config.notifyDispatchMode !== "off" && !process.env["AGT_NOTIFY_DISPATCH"]) {
9053
+ tmuxSessionEnvArgs.push("-e", `AGT_NOTIFY_DISPATCH=${config.notifyDispatchMode}`);
9054
+ }
8802
9055
  const sessionHomeDir = process.env.HOME?.trim() || homedir2();
8803
9056
  let egress;
8804
9057
  if (egressMode(codeName) === "allowlist") {
@@ -8826,8 +9079,12 @@ function spawnSession(config, session) {
8826
9079
  // feature-gate-allow: registry-flag envVar operator-override precedence, not a new gate
8827
9080
  // ENG-7493 (ADR-0044): forward AGT_KANBAN_WAITING_ENABLED if it will be in
8828
9081
  // the session env (operator-set OR materialized from the flag above).
8829
- forwardKanbanWaiting: !!process.env["AGT_KANBAN_WAITING_ENABLED"] || !!config.kanbanWaitingEnabled
9082
+ forwardKanbanWaiting: !!process.env["AGT_KANBAN_WAITING_ENABLED"] || !!config.kanbanWaitingEnabled,
8830
9083
  // feature-gate-allow: registry-flag envVar operator-override precedence, not a new gate
9084
+ // ENG-7682 (notify Slice 1): forward AGT_NOTIFY_DISPATCH if it will be in
9085
+ // the session env (operator-set OR materialized from the flag above).
9086
+ forwardNotifyDispatch: !!process.env["AGT_NOTIFY_DISPATCH"] || // feature-gate-allow: registry-flag envVar operator-override precedence, not a new gate
9087
+ !!config.notifyDispatchMode && config.notifyDispatchMode !== "off"
8831
9088
  }) : JSON.stringify(wrapperPath);
8832
9089
  const tmuxEnv = {
8833
9090
  ...process.env,
@@ -8914,7 +9171,7 @@ function hasMcpChildren(tmuxSession) {
8914
9171
  { encoding: "utf-8" }
8915
9172
  ).trim();
8916
9173
  if (!claudePidOut) return false;
8917
- const pids = claudePidOut.split("\n").map((p) => Number(p)).filter((p) => p > 0);
9174
+ const pids = claudePidOut.split("\n").map((p2) => Number(p2)).filter((p2) => p2 > 0);
8918
9175
  if (pids.length === 0) return false;
8919
9176
  const claudePid = Math.max(...pids);
8920
9177
  const childrenOut = execSync(
@@ -8922,7 +9179,7 @@ function hasMcpChildren(tmuxSession) {
8922
9179
  { encoding: "utf-8" }
8923
9180
  ).trim();
8924
9181
  if (!childrenOut) return false;
8925
- const childPids = childrenOut.split("\n").map((p) => p.trim()).filter(Boolean);
9182
+ const childPids = childrenOut.split("\n").map((p2) => p2.trim()).filter(Boolean);
8926
9183
  for (const cp of childPids) {
8927
9184
  const cmdline = execSync(
8928
9185
  `cat /proc/${cp}/cmdline 2>/dev/null | tr '\\0' ' ' || ps -p ${cp} -o args= 2>/dev/null || true`,
@@ -9441,6 +9698,7 @@ export {
9441
9698
  resolveDmTarget,
9442
9699
  isResolveError,
9443
9700
  deriveConsoleUrl,
9701
+ SCHEDULED_TURN_MARKER_FILENAME,
9444
9702
  parseUsageBanner,
9445
9703
  formatRunMarker,
9446
9704
  parseTranscriptUsage,
@@ -9510,4 +9768,4 @@ export {
9510
9768
  stopAllSessionsAndWait,
9511
9769
  getProjectDir
9512
9770
  };
9513
- //# sourceMappingURL=chunk-KMJHNKPQ.js.map
9771
+ //# sourceMappingURL=chunk-5WQATS6J.js.map