@integrity-labs/agt-cli 0.28.320 → 0.28.321

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-CJSATK6B.js";
41
+ } from "../chunk-52RHLSXN.js";
42
42
  import {
43
43
  AnchorSessionClient,
44
44
  CHANNEL_REGISTRY,
@@ -4827,7 +4827,7 @@ import { execFileSync, execSync } from "child_process";
4827
4827
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4828
4828
  import chalk18 from "chalk";
4829
4829
  import ora16 from "ora";
4830
- var cliVersion = true ? "0.28.320" : "dev";
4830
+ var cliVersion = true ? "0.28.321" : "dev";
4831
4831
  async function fetchLatestVersion() {
4832
4832
  const host2 = getHost();
4833
4833
  if (!host2) return null;
@@ -5931,7 +5931,7 @@ function handleError(err) {
5931
5931
  }
5932
5932
 
5933
5933
  // src/bin/agt.ts
5934
- var cliVersion2 = true ? "0.28.320" : "dev";
5934
+ var cliVersion2 = true ? "0.28.321" : "dev";
5935
5935
  var program = new Command();
5936
5936
  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");
5937
5937
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -6705,7 +6705,7 @@ function requireHost() {
6705
6705
  }
6706
6706
 
6707
6707
  // src/lib/api-client.ts
6708
- var agtCliVersion = true ? "0.28.320" : "dev";
6708
+ var agtCliVersion = true ? "0.28.321" : "dev";
6709
6709
  var lastConfigHash = null;
6710
6710
  function setConfigHash(hash) {
6711
6711
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -9102,4 +9102,4 @@ export {
9102
9102
  managerInstallSystemUnitCommand,
9103
9103
  managerUninstallSystemUnitCommand
9104
9104
  };
9105
- //# sourceMappingURL=chunk-CJSATK6B.js.map
9105
+ //# sourceMappingURL=chunk-52RHLSXN.js.map
@@ -43,7 +43,7 @@ import {
43
43
  requireHost,
44
44
  safeWriteJsonAtomic,
45
45
  setConfigHash
46
- } from "../chunk-CJSATK6B.js";
46
+ } from "../chunk-52RHLSXN.js";
47
47
  import {
48
48
  getProjectDir as getProjectDir2,
49
49
  getReadyTasks,
@@ -518,6 +518,9 @@ function extractMsTeamsBehaviourSubset(config2) {
518
518
  adaptive_cards_ask_user_enabled: adaptiveCardsEnabled && config2?.["adaptive_cards_ask_user_enabled"] === true
519
519
  };
520
520
  }
521
+ function isMsTeamsBehaviourRestrictive(_subset) {
522
+ return false;
523
+ }
521
524
 
522
525
  // src/lib/slack-behaviour-restart.ts
523
526
  function extractSlackBehaviourSubset(config2) {
@@ -534,6 +537,9 @@ function extractSlackBehaviourSubset(config2) {
534
537
  allowed_users: Array.isArray(rawAllowed) ? rawAllowed.filter((v) => typeof v === "string" && v.trim().length > 0).map((v) => v.trim()) : []
535
538
  };
536
539
  }
540
+ function isSlackBehaviourRestrictive(subset) {
541
+ return subset.allowed_users.length > 0;
542
+ }
537
543
 
538
544
  // src/lib/onboarding-drive.ts
539
545
  import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync, writeFileSync as writeFileSync2 } from "fs";
@@ -3315,6 +3321,14 @@ import { existsSync as existsSync4, readFileSync as readFileSync11 } from "fs";
3315
3321
  import { join as join11 } from "path";
3316
3322
  var BASELINE_FILENAME = "sender-policy-baseline.json";
3317
3323
  var SENDER_POLICY_BASELINE_VERSION = 1;
3324
+ var BASELINE_CONCERNS = ["senderPolicy", "slackBehaviour", "msteamsBehaviour"];
3325
+ function createDeliveryBaselineMaps() {
3326
+ return {
3327
+ senderPolicy: /* @__PURE__ */ new Map(),
3328
+ slackBehaviour: /* @__PURE__ */ new Map(),
3329
+ msteamsBehaviour: /* @__PURE__ */ new Map()
3330
+ };
3331
+ }
3318
3332
  function getSenderPolicyBaselineFile(configDir) {
3319
3333
  return join11(configDir, BASELINE_FILENAME);
3320
3334
  }
@@ -3343,27 +3357,31 @@ function loadSenderPolicyBaseline(target, configDir, log2) {
3343
3357
  );
3344
3358
  return;
3345
3359
  }
3346
- const entries = obj.senderPolicy;
3347
- if (!entries || typeof entries !== "object" || Array.isArray(entries)) return;
3348
- for (const [agentId, hash] of Object.entries(entries)) {
3349
- if (typeof hash === "string" && hash.length > 0) target.set(agentId, hash);
3360
+ for (const concern of BASELINE_CONCERNS) {
3361
+ const entries = obj[concern];
3362
+ if (!entries || typeof entries !== "object" || Array.isArray(entries)) continue;
3363
+ for (const [agentId, hash] of Object.entries(entries)) {
3364
+ if (typeof hash === "string" && hash.length > 0) target[concern].set(agentId, hash);
3365
+ }
3350
3366
  }
3351
3367
  }
3352
3368
  function saveSenderPolicyBaseline(source, configDir, log2) {
3353
3369
  const path = getSenderPolicyBaselineFile(configDir);
3354
- const senderPolicy = {};
3355
- for (const [agentId, hash] of source) senderPolicy[agentId] = hash;
3356
- const payload = JSON.stringify(
3357
- { version: SENDER_POLICY_BASELINE_VERSION, senderPolicy },
3358
- null,
3359
- 2
3360
- );
3370
+ const payloadObj = { version: SENDER_POLICY_BASELINE_VERSION };
3371
+ for (const concern of BASELINE_CONCERNS) {
3372
+ const entries = {};
3373
+ for (const [agentId, hash] of source[concern]) entries[agentId] = hash;
3374
+ payloadObj[concern] = entries;
3375
+ }
3376
+ const payload = JSON.stringify(payloadObj, null, 2);
3361
3377
  try {
3362
3378
  atomicWriteFileSync(path, payload);
3379
+ return true;
3363
3380
  } catch (err) {
3364
3381
  log2?.(
3365
3382
  `[sender-policy] failed to persist ${BASELINE_FILENAME} (non-fatal): ${err.message}`
3366
3383
  );
3384
+ return false;
3367
3385
  }
3368
3386
  }
3369
3387
 
@@ -7746,10 +7764,21 @@ function scheduleSessionRestart(codeName, delayMs, reason, breakerReason = "hot-
7746
7764
  {
7747
7765
  const baselineAgentId = agentState.codeNameToAgentId.get(codeName);
7748
7766
  if (baselineAgentId) {
7749
- persistSenderPolicyBaselineEntry(
7767
+ persistDeliveryBaselineEntry(
7768
+ "senderPolicy",
7750
7769
  baselineAgentId,
7751
7770
  agentState.knownSenderPolicyHashes.get(baselineAgentId)
7752
7771
  );
7772
+ persistDeliveryBaselineEntry(
7773
+ "slackBehaviour",
7774
+ baselineAgentId,
7775
+ agentState.knownSlackBehaviourHashes.get(baselineAgentId)
7776
+ );
7777
+ persistDeliveryBaselineEntry(
7778
+ "msteamsBehaviour",
7779
+ baselineAgentId,
7780
+ agentState.knownMsTeamsBehaviourHashes.get(baselineAgentId)
7781
+ );
7753
7782
  }
7754
7783
  }
7755
7784
  runningMcpHashes.delete(codeName);
@@ -8272,7 +8301,7 @@ function clearAgentCaches(agentId, codeName) {
8272
8301
  mcpFlapDampener.forget(codeName);
8273
8302
  deferLogThrottle.delete(codeName);
8274
8303
  if (channelCacheMutated) saveChannelHashCache2();
8275
- removeSenderPolicyBaselineEntry(agentId);
8304
+ removeDeliveryBaselineEntries(agentId);
8276
8305
  }
8277
8306
  var cachedFrameworkVersion = null;
8278
8307
  var cachedMaintenanceWindow = null;
@@ -8280,7 +8309,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
8280
8309
  var lastVersionCheckAt = 0;
8281
8310
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
8282
8311
  var lastResponsivenessProbeAt = 0;
8283
- var agtCliVersion = true ? "0.28.320" : "dev";
8312
+ var agtCliVersion = true ? "0.28.321" : "dev";
8284
8313
  function resolveBrewPath(execFileSync2) {
8285
8314
  try {
8286
8315
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -8988,22 +9017,46 @@ function loadChannelHashCache2() {
8988
9017
  function saveChannelHashCache2() {
8989
9018
  saveChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
8990
9019
  }
8991
- var persistedSenderPolicyBaseline = /* @__PURE__ */ new Map();
9020
+ var persistedDeliveryBaseline = createDeliveryBaselineMaps();
8992
9021
  function loadSenderPolicyBaseline2() {
8993
- loadSenderPolicyBaseline(persistedSenderPolicyBaseline, channelHashCacheDir(), log);
8994
- for (const [agentId, hash] of persistedSenderPolicyBaseline) {
9022
+ loadSenderPolicyBaseline(persistedDeliveryBaseline, channelHashCacheDir(), log);
9023
+ for (const [agentId, hash] of persistedDeliveryBaseline.senderPolicy) {
8995
9024
  agentState.knownSenderPolicyHashes.set(agentId, hash);
8996
9025
  }
9026
+ for (const [agentId, hash] of persistedDeliveryBaseline.slackBehaviour) {
9027
+ agentState.knownSlackBehaviourHashes.set(agentId, hash);
9028
+ }
9029
+ for (const [agentId, hash] of persistedDeliveryBaseline.msteamsBehaviour) {
9030
+ agentState.knownMsTeamsBehaviourHashes.set(agentId, hash);
9031
+ }
9032
+ }
9033
+ var deliveryBaselineDirty = false;
9034
+ function saveDeliveryBaseline() {
9035
+ deliveryBaselineDirty = !saveSenderPolicyBaseline(
9036
+ persistedDeliveryBaseline,
9037
+ channelHashCacheDir(),
9038
+ log
9039
+ );
9040
+ }
9041
+ function flushDeliveryBaselineIfDirty() {
9042
+ if (deliveryBaselineDirty) saveDeliveryBaseline();
8997
9043
  }
8998
- function persistSenderPolicyBaselineEntry(agentId, hash) {
9044
+ function persistDeliveryBaselineEntry(concern, agentId, hash) {
8999
9045
  if (hash === void 0) return;
9000
- if (persistedSenderPolicyBaseline.get(agentId) === hash) return;
9001
- persistedSenderPolicyBaseline.set(agentId, hash);
9002
- saveSenderPolicyBaseline(persistedSenderPolicyBaseline, channelHashCacheDir(), log);
9046
+ if (persistedDeliveryBaseline[concern].get(agentId) === hash && !deliveryBaselineDirty) return;
9047
+ persistedDeliveryBaseline[concern].set(agentId, hash);
9048
+ saveDeliveryBaseline();
9049
+ }
9050
+ function removeDeliveryBaselineEntry(concern, agentId) {
9051
+ if (!persistedDeliveryBaseline[concern].delete(agentId) && !deliveryBaselineDirty) return;
9052
+ saveDeliveryBaseline();
9003
9053
  }
9004
- function removeSenderPolicyBaselineEntry(agentId) {
9005
- if (!persistedSenderPolicyBaseline.delete(agentId)) return;
9006
- saveSenderPolicyBaseline(persistedSenderPolicyBaseline, channelHashCacheDir(), log);
9054
+ function removeDeliveryBaselineEntries(agentId) {
9055
+ let mutated = false;
9056
+ for (const map of Object.values(persistedDeliveryBaseline)) {
9057
+ if (map.delete(agentId)) mutated = true;
9058
+ }
9059
+ if (mutated || deliveryBaselineDirty) saveDeliveryBaseline();
9007
9060
  }
9008
9061
  var _channelQuarantineStore = null;
9009
9062
  function channelQuarantineStore() {
@@ -9165,6 +9218,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
9165
9218
  async function pollCycle() {
9166
9219
  if (!config) return;
9167
9220
  if (restartAfterUpgrade) return;
9221
+ flushDeliveryBaselineIfDirty();
9168
9222
  try {
9169
9223
  await processRestartFlags({
9170
9224
  log,
@@ -10670,14 +10724,14 @@ async function processAgent(agent, agentStates) {
10670
10724
  agentState.knownSenderPolicyHashes.set(agent.agent_id, senderPolicyHash);
10671
10725
  const hasLiveSenderPolicyConsumer = hasSenderPolicyChannel && spSessionHealthy && spSessionMode === "persistent" && spFramework === "claude-code";
10672
10726
  if (!hasLiveSenderPolicyConsumer) {
10673
- persistSenderPolicyBaselineEntry(agent.agent_id, senderPolicyHash);
10727
+ persistDeliveryBaselineEntry("senderPolicy", agent.agent_id, senderPolicyHash);
10674
10728
  } else if (senderPolicyDecision.firstPoll && !senderPolicyRestrictive) {
10675
- if (persistedSenderPolicyBaseline.get(agent.agent_id) !== senderPolicyHash) {
10729
+ if (persistedDeliveryBaseline.senderPolicy.get(agent.agent_id) !== senderPolicyHash) {
10676
10730
  log(
10677
10731
  `[sender-policy] baseline established without restart for '${agent.code_name}' (policy is non-restrictive); a policy loosened while the baseline was unknown requires an agent restart to take effect (ENG-7771)`
10678
10732
  );
10679
10733
  }
10680
- persistSenderPolicyBaselineEntry(agent.agent_id, senderPolicyHash);
10734
+ persistDeliveryBaselineEntry("senderPolicy", agent.agent_id, senderPolicyHash);
10681
10735
  }
10682
10736
  let msteamsBehaviourRestartScheduled = false;
10683
10737
  if (currentChannelIds.has("msteams")) {
@@ -10687,18 +10741,14 @@ async function processAgent(agent, agentStates) {
10687
10741
  );
10688
10742
  const behaviourHash = createHash12("sha256").update(canonicalJson(behaviourSubset)).digest("hex");
10689
10743
  const prevBehaviourHash = agentState.knownMsTeamsBehaviourHashes.get(agent.agent_id);
10744
+ const msteamsBehaviourRestrictive = isMsTeamsBehaviourRestrictive(behaviourSubset);
10690
10745
  const behaviourDecision = decideSenderPolicyRestart({
10691
10746
  previousHash: prevBehaviourHash,
10692
- // ENG-7771 scoped the persisted-baseline + first-poll fail-safe to
10693
- // sender_policy only; the behaviour baselines keep the legacy
10694
- // "first poll never restarts" semantics until the follow-up that
10695
- // migrates them onto the sidecar (their maps share the same
10696
- // wipe-on-manager-restart pathology).
10697
- currentPolicyRestrictive: false,
10747
+ currentPolicyRestrictive: msteamsBehaviourRestrictive,
10698
10748
  currentHash: behaviourHash,
10699
- sessionMode: refreshData.agent.session_mode,
10700
- framework: agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK,
10701
- sessionHealthy: isSessionHealthy(agent.code_name),
10749
+ sessionMode: spSessionMode,
10750
+ framework: spFramework,
10751
+ sessionHealthy: spSessionHealthy,
10702
10752
  // A channel-set or sender-policy restart scheduled this tick will
10703
10753
  // respawn the MCP children with the freshly-written env for free.
10704
10754
  channelSetRestartAlreadyScheduled: channelSetRestartScheduled || senderPolicyDecision.restart
@@ -10730,8 +10780,15 @@ async function processAgent(agent, agentStates) {
10730
10780
  msteamsBehaviourRestartScheduled = true;
10731
10781
  }
10732
10782
  agentState.knownMsTeamsBehaviourHashes.set(agent.agent_id, behaviourHash);
10783
+ const hasLiveMsTeamsBehaviourConsumer = spSessionHealthy && spSessionMode === "persistent" && spFramework === "claude-code";
10784
+ if (!hasLiveMsTeamsBehaviourConsumer) {
10785
+ persistDeliveryBaselineEntry("msteamsBehaviour", agent.agent_id, behaviourHash);
10786
+ } else if (behaviourDecision.firstPoll && !msteamsBehaviourRestrictive) {
10787
+ persistDeliveryBaselineEntry("msteamsBehaviour", agent.agent_id, behaviourHash);
10788
+ }
10733
10789
  } else {
10734
10790
  agentState.knownMsTeamsBehaviourHashes.delete(agent.agent_id);
10791
+ removeDeliveryBaselineEntry("msteamsBehaviour", agent.agent_id);
10735
10792
  }
10736
10793
  if (currentChannelIds.has("slack")) {
10737
10794
  const slackEntry = refreshData.channel_configs?.["slack"];
@@ -10740,25 +10797,25 @@ async function processAgent(agent, agentStates) {
10740
10797
  );
10741
10798
  const slackBehaviourHash = createHash12("sha256").update(canonicalJson(slackBehaviourSubset)).digest("hex");
10742
10799
  const prevSlackBehaviourHash = agentState.knownSlackBehaviourHashes.get(agent.agent_id);
10800
+ const slackBehaviourRestrictive = isSlackBehaviourRestrictive(slackBehaviourSubset);
10743
10801
  const slackBehaviourDecision = decideSenderPolicyRestart({
10744
10802
  previousHash: prevSlackBehaviourHash,
10745
- // See the msteams call above — behaviour baselines are out of
10746
- // ENG-7771's scope; legacy first-poll semantics until the follow-up.
10747
- currentPolicyRestrictive: false,
10803
+ currentPolicyRestrictive: slackBehaviourRestrictive,
10748
10804
  currentHash: slackBehaviourHash,
10749
- sessionMode: refreshData.agent.session_mode,
10750
- framework: agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK,
10751
- sessionHealthy: isSessionHealthy(agent.code_name),
10805
+ sessionMode: spSessionMode,
10806
+ framework: spFramework,
10807
+ sessionHealthy: spSessionHealthy,
10752
10808
  // A channel-set, sender-policy, or msteams-behaviour restart
10753
10809
  // scheduled this tick respawns the MCP children with the
10754
10810
  // freshly-written env for free.
10755
10811
  channelSetRestartAlreadyScheduled: channelSetRestartScheduled || senderPolicyDecision.restart || msteamsBehaviourRestartScheduled
10756
10812
  });
10757
10813
  if (slackBehaviourDecision.restart) {
10814
+ const isSlackVerifyRestart = slackBehaviourDecision.firstPoll;
10758
10815
  log(
10759
- `[hot-reload] slack behaviour settings changed for '${agent.code_name}' (${prevSlackBehaviourHash?.slice(0, 8) ?? "first"} \u2192 ${slackBehaviourHash.slice(0, 8)}) \u2014 restarting session`
10816
+ isSlackVerifyRestart ? `[hot-reload] slack behaviour delivery baseline unknown for '${agent.code_name}' with a restrictive allowed_users list (\u2192 ${slackBehaviourHash.slice(0, 8)}) \u2014 restarting session to guarantee enforcement (fail closed, ENG-7779)` : `[hot-reload] slack behaviour settings changed for '${agent.code_name}' (${prevSlackBehaviourHash?.slice(0, 8) ?? "first"} \u2192 ${slackBehaviourHash.slice(0, 8)}) \u2014 restarting session`
10760
10817
  );
10761
- const slackBehaviourNotice = "Your Slack channel behaviour settings were updated. Restarting session shortly so the slack-channel MCP picks up the new configuration.";
10818
+ const slackBehaviourNotice = isSlackVerifyRestart ? "Your manager was updated and needs to restart your session to make sure your configured Slack access controls are enforced by the channel MCP server." : "Your Slack channel behaviour settings were updated. Restarting session shortly so the slack-channel MCP picks up the new configuration.";
10762
10819
  const slackBehaviourDelivered = await injectMessage(
10763
10820
  agent.code_name,
10764
10821
  "system",
@@ -10775,13 +10832,20 @@ async function processAgent(agent, agentStates) {
10775
10832
  scheduleSessionRestart(
10776
10833
  agent.code_name,
10777
10834
  slackBehaviourDelay,
10778
- "slack behaviour change",
10835
+ isSlackVerifyRestart ? "slack behaviour verify (unknown baseline)" : "slack behaviour change",
10779
10836
  "channel-behaviour-change"
10780
10837
  );
10781
10838
  }
10782
10839
  agentState.knownSlackBehaviourHashes.set(agent.agent_id, slackBehaviourHash);
10840
+ const hasLiveSlackBehaviourConsumer = spSessionHealthy && spSessionMode === "persistent" && spFramework === "claude-code";
10841
+ if (!hasLiveSlackBehaviourConsumer) {
10842
+ persistDeliveryBaselineEntry("slackBehaviour", agent.agent_id, slackBehaviourHash);
10843
+ } else if (slackBehaviourDecision.firstPoll && !slackBehaviourRestrictive) {
10844
+ persistDeliveryBaselineEntry("slackBehaviour", agent.agent_id, slackBehaviourHash);
10845
+ }
10783
10846
  } else {
10784
10847
  agentState.knownSlackBehaviourHashes.delete(agent.agent_id);
10848
+ removeDeliveryBaselineEntry("slackBehaviour", agent.agent_id);
10785
10849
  }
10786
10850
  }
10787
10851
  const agentSessionMode = refreshData.agent.session_mode;