@integrity-labs/agt-cli 0.28.313 → 0.28.314

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.
@@ -39,7 +39,7 @@ import {
39
39
  requireHost,
40
40
  safeWriteJsonAtomic,
41
41
  setConfigHash
42
- } from "../chunk-57W744KO.js";
42
+ } from "../chunk-R5AKZYDG.js";
43
43
  import {
44
44
  getProjectDir as getProjectDir2,
45
45
  getReadyTasks,
@@ -134,9 +134,9 @@ import {
134
134
 
135
135
  // src/lib/manager-worker.ts
136
136
  import { createHash as createHash11 } from "crypto";
137
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync9, rmSync as rmSync4, readdirSync as readdirSync5, statSync as statSync4, copyFileSync } from "fs";
137
+ import { readFileSync as readFileSync16, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync10, rmSync as rmSync4, readdirSync as readdirSync5, statSync as statSync4, copyFileSync } from "fs";
138
138
  import { execFileSync as syncExecFile } from "child_process";
139
- import { join as join18, dirname as dirname6 } from "path";
139
+ import { join as join19, dirname as dirname6 } from "path";
140
140
  import { homedir as homedir10 } from "os";
141
141
  import { fileURLToPath } from "url";
142
142
 
@@ -331,31 +331,34 @@ function resolveChannelLaunchFlags(channelConfigs, quarantinedChannels) {
331
331
  function decideSenderPolicyRestart(input) {
332
332
  const {
333
333
  previousHash,
334
+ currentPolicyRestrictive,
334
335
  currentHash,
335
336
  sessionMode,
336
337
  framework,
337
338
  sessionHealthy,
338
339
  channelSetRestartAlreadyScheduled
339
340
  } = input;
340
- if (previousHash === void 0) {
341
- return { restart: false, firstPoll: true, changed: false };
342
- }
343
- if (previousHash === currentHash) {
341
+ const firstPoll = previousHash === void 0;
342
+ if (!firstPoll && previousHash === currentHash) {
344
343
  return { restart: false, firstPoll: false, changed: false };
345
344
  }
345
+ if (firstPoll && !currentPolicyRestrictive) {
346
+ return { restart: false, firstPoll: true, changed: false };
347
+ }
348
+ const changed = !firstPoll;
346
349
  if (sessionMode !== "persistent") {
347
- return { restart: false, firstPoll: false, changed: true };
350
+ return { restart: false, firstPoll, changed };
348
351
  }
349
352
  if (framework !== "claude-code") {
350
- return { restart: false, firstPoll: false, changed: true };
353
+ return { restart: false, firstPoll, changed };
351
354
  }
352
355
  if (!sessionHealthy) {
353
- return { restart: false, firstPoll: false, changed: true };
356
+ return { restart: false, firstPoll, changed };
354
357
  }
355
358
  if (channelSetRestartAlreadyScheduled) {
356
- return { restart: false, firstPoll: false, changed: true };
359
+ return { restart: false, firstPoll, changed };
357
360
  }
358
- return { restart: true, firstPoll: false, changed: true };
361
+ return { restart: true, firstPoll, changed };
359
362
  }
360
363
 
361
364
  // src/lib/sender-policy-normalize.ts
@@ -400,6 +403,13 @@ function normalizeSenderPolicyForHash(policy) {
400
403
  function computeSenderPolicyRestartHash(policy) {
401
404
  return createHash3("sha256").update(canonicalJson({ senderPolicy: normalizeSenderPolicyForHash(policy) })).digest("hex");
402
405
  }
406
+ function isSenderPolicyRestrictive(policy) {
407
+ if (policy === null || policy === void 0) return false;
408
+ if (typeof policy !== "object") return true;
409
+ const p = policy;
410
+ if (p.internal_only === true) return true;
411
+ return p.mode !== "all";
412
+ }
403
413
 
404
414
  // src/lib/msteams-behaviour-restart.ts
405
415
  function extractMsTeamsBehaviourSubset(config2) {
@@ -654,7 +664,17 @@ var PROVISIONING_RELOAD_REASONS = /* @__PURE__ */ new Set([
654
664
  "bind-remediation",
655
665
  // ENG-7576: the dashboard integration-add stop itself - the first restart of
656
666
  // the very burst this class exists for, previously uncounted entirely.
657
- "integration-change"
667
+ "integration-change",
668
+ // ENG-7771: a sender_policy delivery restart is a deliberate config-delivery
669
+ // reload (operator changed the policy, or the fail-closed first-poll verify
670
+ // after a manager restart with no persisted baseline), not a crash. On the
671
+ // tight crash tally, a host whose sender-policy-baseline.json write keeps
672
+ // failing (disk full, permissions) would convert the fail-closed restart
673
+ // into repeated crash tallies across a multi-deploy day and trip the
674
+ // breaker - taking the agent DOWN, which is strictly worse than the stale
675
+ // policy the restart exists to fix. The looser provisioning tally still
676
+ // trips + pages on sustained thrash.
677
+ "sender-policy-change"
658
678
  ]);
659
679
  function isProvisioningReloadReason(reason) {
660
680
  return PROVISIONING_RELOAD_REASONS.has(reason);
@@ -1402,7 +1422,10 @@ var GATEABLE_RESTART_REASONS = /* @__PURE__ */ new Set([
1402
1422
  function isGateableRestartReason(reason) {
1403
1423
  return reason != null && GATEABLE_RESTART_REASONS.has(reason);
1404
1424
  }
1405
- var WINDOW_EXEMPT_RESTART_REASONS = /* @__PURE__ */ new Set(["channel-set-change"]);
1425
+ var WINDOW_EXEMPT_RESTART_REASONS = /* @__PURE__ */ new Set([
1426
+ "channel-set-change",
1427
+ "sender-policy-change"
1428
+ ]);
1406
1429
  function isWindowExemptRestartReason(reason) {
1407
1430
  return reason != null && WINDOW_EXEMPT_RESTART_REASONS.has(reason);
1408
1431
  }
@@ -3193,6 +3216,63 @@ function saveChannelHashCache(source, configDir) {
3193
3216
  }
3194
3217
  }
3195
3218
 
3219
+ // src/lib/sender-policy-baseline.ts
3220
+ import { existsSync as existsSync4, readFileSync as readFileSync11 } from "fs";
3221
+ import { join as join11 } from "path";
3222
+ var BASELINE_FILENAME = "sender-policy-baseline.json";
3223
+ var SENDER_POLICY_BASELINE_VERSION = 1;
3224
+ function getSenderPolicyBaselineFile(configDir) {
3225
+ return join11(configDir, BASELINE_FILENAME);
3226
+ }
3227
+ function loadSenderPolicyBaseline(target, configDir, log2) {
3228
+ const path = getSenderPolicyBaselineFile(configDir);
3229
+ if (!existsSync4(path)) return;
3230
+ let parsed;
3231
+ try {
3232
+ parsed = JSON.parse(readFileSync11(path, "utf-8"));
3233
+ } catch (err) {
3234
+ log2?.(
3235
+ `[sender-policy] discarding corrupt ${BASELINE_FILENAME} (${err.message}) - restrictive-policy agents will take one fail-closed restart`
3236
+ );
3237
+ return;
3238
+ }
3239
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
3240
+ log2?.(
3241
+ `[sender-policy] discarding malformed ${BASELINE_FILENAME} (not an object) - restrictive-policy agents will take one fail-closed restart`
3242
+ );
3243
+ return;
3244
+ }
3245
+ const obj = parsed;
3246
+ if (obj.version !== SENDER_POLICY_BASELINE_VERSION) {
3247
+ log2?.(
3248
+ `[sender-policy] discarding ${BASELINE_FILENAME} with version ${String(obj.version)} (expected ${SENDER_POLICY_BASELINE_VERSION}) - hash semantics changed; restrictive-policy agents will take one fail-closed restart`
3249
+ );
3250
+ return;
3251
+ }
3252
+ const entries = obj.senderPolicy;
3253
+ if (!entries || typeof entries !== "object" || Array.isArray(entries)) return;
3254
+ for (const [agentId, hash] of Object.entries(entries)) {
3255
+ if (typeof hash === "string" && hash.length > 0) target.set(agentId, hash);
3256
+ }
3257
+ }
3258
+ function saveSenderPolicyBaseline(source, configDir, log2) {
3259
+ const path = getSenderPolicyBaselineFile(configDir);
3260
+ const senderPolicy = {};
3261
+ for (const [agentId, hash] of source) senderPolicy[agentId] = hash;
3262
+ const payload = JSON.stringify(
3263
+ { version: SENDER_POLICY_BASELINE_VERSION, senderPolicy },
3264
+ null,
3265
+ 2
3266
+ );
3267
+ try {
3268
+ atomicWriteFileSync(path, payload);
3269
+ } catch (err) {
3270
+ log2?.(
3271
+ `[sender-policy] failed to persist ${BASELINE_FILENAME} (non-fatal): ${err.message}`
3272
+ );
3273
+ }
3274
+ }
3275
+
3196
3276
  // src/lib/channel-sweep.ts
3197
3277
  import { execFileSync } from "child_process";
3198
3278
  var CHANNEL_BASENAMES = [
@@ -3632,16 +3712,16 @@ function planGlobalSkillSync(globalSkills, prevIds, hashOf, knownHash, options)
3632
3712
  }
3633
3713
 
3634
3714
  // src/lib/manager/managed-skill-manifest.ts
3635
- import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync11, writeFileSync as writeFileSync5 } from "fs";
3636
- import { dirname as dirname4, join as join11 } from "path";
3715
+ import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync12, writeFileSync as writeFileSync5 } from "fs";
3716
+ import { dirname as dirname4, join as join12 } from "path";
3637
3717
  var MANIFEST_VERSION = 1;
3638
3718
  function managedSkillManifestPath(agentRootDir) {
3639
- return join11(agentRootDir, "managed-skills.json");
3719
+ return join12(agentRootDir, "managed-skills.json");
3640
3720
  }
3641
3721
  function readManagedSkillManifest(path) {
3642
3722
  try {
3643
- if (!existsSync4(path)) return /* @__PURE__ */ new Set();
3644
- const parsed = JSON.parse(readFileSync11(path, "utf-8"));
3723
+ if (!existsSync5(path)) return /* @__PURE__ */ new Set();
3724
+ const parsed = JSON.parse(readFileSync12(path, "utf-8"));
3645
3725
  const ids = Array.isArray(parsed?.globalSkillIds) ? parsed.globalSkillIds : [];
3646
3726
  return new Set(ids.filter((id) => typeof id === "string" && id.length > 0));
3647
3727
  } catch {
@@ -3662,8 +3742,8 @@ function writeManagedSkillManifest(path, ids) {
3662
3742
 
3663
3743
  // src/lib/manager/runtime.ts
3664
3744
  import { createHash as createHash6 } from "crypto";
3665
- import { readFileSync as readFileSync12, appendFileSync, mkdirSync as mkdirSync5, chmodSync, existsSync as existsSync5 } from "fs";
3666
- import { join as join12, dirname as dirname5 } from "path";
3745
+ import { readFileSync as readFileSync13, appendFileSync, mkdirSync as mkdirSync5, chmodSync, existsSync as existsSync6 } from "fs";
3746
+ import { join as join13, dirname as dirname5 } from "path";
3667
3747
  import { homedir as homedir5 } from "os";
3668
3748
  function redactForDiskLog(value) {
3669
3749
  try {
@@ -3684,9 +3764,9 @@ function log(msg) {
3684
3764
  `;
3685
3765
  if (!managerLogPath) {
3686
3766
  try {
3687
- managerLogPath = join12(homedir5(), ".augmented", "manager.log");
3767
+ managerLogPath = join13(homedir5(), ".augmented", "manager.log");
3688
3768
  mkdirSync5(dirname5(managerLogPath), { recursive: true });
3689
- if (existsSync5(managerLogPath)) {
3769
+ if (existsSync6(managerLogPath)) {
3690
3770
  chmodSync(managerLogPath, 384);
3691
3771
  }
3692
3772
  } catch {
@@ -3714,7 +3794,7 @@ function sha256(content) {
3714
3794
  }
3715
3795
  function hashFile(filePath) {
3716
3796
  try {
3717
- const content = readFileSync12(filePath, "utf-8");
3797
+ const content = readFileSync13(filePath, "utf-8");
3718
3798
  return sha256(content);
3719
3799
  } catch {
3720
3800
  return null;
@@ -3872,8 +3952,8 @@ function resolveModelChain(refreshData) {
3872
3952
  }
3873
3953
 
3874
3954
  // src/lib/manager/claude-auth.ts
3875
- import { existsSync as existsSync6, rmSync as rmSync2 } from "fs";
3876
- import { join as join13 } from "path";
3955
+ import { existsSync as existsSync7, rmSync as rmSync2 } from "fs";
3956
+ import { join as join14 } from "path";
3877
3957
  import { homedir as homedir6 } from "os";
3878
3958
  async function applyClaudeAuthToEnv(childEnv, label) {
3879
3959
  const apiKey = getApiKey();
@@ -3886,10 +3966,10 @@ async function applyClaudeAuthToEnv(childEnv, label) {
3886
3966
  throw new Error("claude_auth_mode=api_key but /host/exchange returned no decrypted key");
3887
3967
  }
3888
3968
  childEnv.ANTHROPIC_API_KEY = exchange.anthropicApiKey;
3889
- const claudeDir = join13(homedir6(), ".claude");
3969
+ const claudeDir = join14(homedir6(), ".claude");
3890
3970
  for (const filename of [".credentials.json", "credentials.json"]) {
3891
- const p = join13(claudeDir, filename);
3892
- if (existsSync6(p)) {
3971
+ const p = join14(claudeDir, filename);
3972
+ if (existsSync7(p)) {
3893
3973
  try {
3894
3974
  rmSync2(p, { force: true });
3895
3975
  log(`[${label}] Removed ${p} (api_key mode \u2014 preventing OAuth fallback)`);
@@ -3903,8 +3983,8 @@ async function applyClaudeAuthToEnv(childEnv, label) {
3903
3983
  }
3904
3984
 
3905
3985
  // src/lib/manager/kanban/parsers.ts
3906
- import { existsSync as existsSync7, readFileSync as readFileSync13 } from "fs";
3907
- import { join as join14 } from "path";
3986
+ import { existsSync as existsSync8, readFileSync as readFileSync14 } from "fs";
3987
+ import { join as join15 } from "path";
3908
3988
  var STANDUP_TEMPLATES = /* @__PURE__ */ new Set(["daily-standup", "end-of-day-summary"]);
3909
3989
  var TASK_UPDATE_TEMPLATES = /* @__PURE__ */ new Set(["hourly-status", "task-update"]);
3910
3990
  var PLAN_TEMPLATES = /* @__PURE__ */ new Set(["morning-plan"]);
@@ -4036,12 +4116,12 @@ function getBuiltInSkillContent(skillId) {
4036
4116
  if (builtInSkillCache.has(skillId)) return builtInSkillCache.get(skillId);
4037
4117
  try {
4038
4118
  const candidates = [
4039
- join14(process.cwd(), "skills", skillId, "SKILL.md"),
4040
- join14(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "..", "..", "skills", skillId, "SKILL.md")
4119
+ join15(process.cwd(), "skills", skillId, "SKILL.md"),
4120
+ join15(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "..", "..", "skills", skillId, "SKILL.md")
4041
4121
  ];
4042
4122
  for (const candidate of candidates) {
4043
- if (existsSync7(candidate)) {
4044
- const content = readFileSync13(candidate, "utf-8");
4123
+ if (existsSync8(candidate)) {
4124
+ const content = readFileSync14(candidate, "utf-8");
4045
4125
  const files = [{ relativePath: "SKILL.md", content }];
4046
4126
  builtInSkillCache.set(skillId, files);
4047
4127
  return files;
@@ -4714,7 +4794,7 @@ function closeScheduledRunsForCode(codeName, outcome, reason) {
4714
4794
  import { createHash as createHash9 } from "crypto";
4715
4795
  import { writeFileSync as writeFileSync6, renameSync } from "fs";
4716
4796
  import { homedir as homedir7 } from "os";
4717
- import { join as join15 } from "path";
4797
+ import { join as join16 } from "path";
4718
4798
 
4719
4799
  // src/lib/manager/delivery/scheduled-output.ts
4720
4800
  async function deliverScheduledTaskOutput(agentCodeName, agentId, rawTarget, body, taskId) {
@@ -5018,7 +5098,7 @@ function resolveScheduledSlackTarget(task) {
5018
5098
  }
5019
5099
  function stampScheduledTurnMarker(codeName, taskId, target) {
5020
5100
  try {
5021
- const file = join15(homedir7(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
5101
+ const file = join16(homedir7(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
5022
5102
  const marker = { ts: Date.now(), task_id: taskId, ...target ? { target } : {} };
5023
5103
  const tmp = `${file}.tmp`;
5024
5104
  writeFileSync6(tmp, JSON.stringify(marker), "utf8");
@@ -5205,9 +5285,9 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
5205
5285
  // src/lib/manager/scheduler/execution.ts
5206
5286
  import { createHash as createHash10 } from "crypto";
5207
5287
  import { homedir as homedir8 } from "os";
5208
- import { join as join16 } from "path";
5288
+ import { join as join17 } from "path";
5209
5289
  function claudePidFilePath() {
5210
- return join16(homedir8(), ".augmented", "manager-claude-pids.json");
5290
+ return join17(homedir8(), ".augmented", "manager-claude-pids.json");
5211
5291
  }
5212
5292
  var inFlightClaudePids = /* @__PURE__ */ new Map();
5213
5293
  function registerClaudeSpawn(record) {
@@ -5407,24 +5487,24 @@ function partitionActionableByPoison(actionable, states, config2) {
5407
5487
  }
5408
5488
 
5409
5489
  // src/lib/restart-flags.ts
5410
- import { existsSync as existsSync8, mkdirSync as mkdirSync6, readdirSync as readdirSync4, readFileSync as readFileSync14, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "fs";
5490
+ import { existsSync as existsSync9, mkdirSync as mkdirSync6, readdirSync as readdirSync4, readFileSync as readFileSync15, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "fs";
5411
5491
  import { homedir as homedir9 } from "os";
5412
- import { join as join17 } from "path";
5492
+ import { join as join18 } from "path";
5413
5493
  import { randomUUID } from "crypto";
5414
5494
  function restartFlagsDir() {
5415
- return join17(homedir9(), ".augmented", "restart-flags");
5495
+ return join18(homedir9(), ".augmented", "restart-flags");
5416
5496
  }
5417
5497
  function flagPath(codeName) {
5418
- return join17(restartFlagsDir(), `${codeName}.flag`);
5498
+ return join18(restartFlagsDir(), `${codeName}.flag`);
5419
5499
  }
5420
5500
  function readRestartFlags() {
5421
5501
  const dir = restartFlagsDir();
5422
- if (!existsSync8(dir)) return [];
5502
+ if (!existsSync9(dir)) return [];
5423
5503
  const out = [];
5424
5504
  for (const entry of readdirSync4(dir)) {
5425
5505
  if (!entry.endsWith(".flag")) continue;
5426
5506
  try {
5427
- const raw = readFileSync14(join17(dir, entry), "utf8");
5507
+ const raw = readFileSync15(join18(dir, entry), "utf8");
5428
5508
  const parsed = JSON.parse(raw);
5429
5509
  if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
5430
5510
  parsed.codeName = entry.replace(/\.flag$/, "");
@@ -5442,7 +5522,7 @@ function readRestartFlags() {
5442
5522
  }
5443
5523
  function deleteRestartFlag(codeName) {
5444
5524
  const path = flagPath(codeName);
5445
- if (existsSync8(path)) {
5525
+ if (existsSync9(path)) {
5446
5526
  rmSync3(path, { force: true });
5447
5527
  }
5448
5528
  }
@@ -6472,6 +6552,15 @@ function scheduleSessionRestart(codeName, delayMs, reason, breakerReason = "hot-
6472
6552
  }
6473
6553
  stopPersistentSession(codeName, log);
6474
6554
  markRestartStopped(codeName, log);
6555
+ {
6556
+ const baselineAgentId = agentState.codeNameToAgentId.get(codeName);
6557
+ if (baselineAgentId) {
6558
+ persistSenderPolicyBaselineEntry(
6559
+ baselineAgentId,
6560
+ agentState.knownSenderPolicyHashes.get(baselineAgentId)
6561
+ );
6562
+ }
6563
+ }
6475
6564
  runningMcpHashes.delete(codeName);
6476
6565
  sessionLaunchManagedStructure.delete(codeName);
6477
6566
  recordRestartForBreaker(codeName, breakerReason);
@@ -6655,7 +6744,7 @@ var runningChannelSecretHashes = /* @__PURE__ */ new Map();
6655
6744
  var sessionLaunchManagedStructure = /* @__PURE__ */ new Map();
6656
6745
  function projectMcpHash(_codeName, projectDir) {
6657
6746
  try {
6658
- const raw = readFileSync15(join18(projectDir, ".mcp.json"), "utf-8");
6747
+ const raw = readFileSync16(join19(projectDir, ".mcp.json"), "utf-8");
6659
6748
  return createHash11("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
6660
6749
  } catch {
6661
6750
  return null;
@@ -6663,7 +6752,7 @@ function projectMcpHash(_codeName, projectDir) {
6663
6752
  }
6664
6753
  function projectMcpKeys(_codeName, projectDir) {
6665
6754
  try {
6666
- const raw = readFileSync15(join18(projectDir, ".mcp.json"), "utf-8");
6755
+ const raw = readFileSync16(join19(projectDir, ".mcp.json"), "utf-8");
6667
6756
  const parsed = JSON.parse(raw);
6668
6757
  const servers = parsed.mcpServers;
6669
6758
  if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
@@ -6681,7 +6770,7 @@ function seedSessionLaunchBaselines(codeName, projectDir) {
6681
6770
  else runningMcpServerKeys.delete(codeName);
6682
6771
  let launchStructure = null;
6683
6772
  try {
6684
- const raw = readFileSync15(join18(projectDir, ".mcp.json"), "utf-8");
6773
+ const raw = readFileSync16(join19(projectDir, ".mcp.json"), "utf-8");
6685
6774
  launchStructure = managedMcpStructureHashFromFile(
6686
6775
  JSON.parse(raw),
6687
6776
  isManagedMcpServerKey
@@ -6781,7 +6870,7 @@ async function runAgentSessionToolBindProbes(agent, integrations, projectDir, op
6781
6870
  if (result && result.rebindCandidates.length > 0 && hostFlagStore().getBoolean("session-tool-rebind")) {
6782
6871
  let mcpJsonForRebind = null;
6783
6872
  try {
6784
- mcpJsonForRebind = JSON.parse(readFileSync15(join18(projectDir, ".mcp.json"), "utf-8"));
6873
+ mcpJsonForRebind = JSON.parse(readFileSync16(join19(projectDir, ".mcp.json"), "utf-8"));
6785
6874
  } catch {
6786
6875
  mcpJsonForRebind = null;
6787
6876
  }
@@ -6910,7 +6999,7 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
6910
6999
  function projectChannelSecretHash(projectDir) {
6911
7000
  try {
6912
7001
  const entries = parseEnvIntegrations(
6913
- readFileSync15(join18(projectDir, ".env.integrations"), "utf-8")
7002
+ readFileSync16(join19(projectDir, ".env.integrations"), "utf-8")
6914
7003
  );
6915
7004
  return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
6916
7005
  } catch {
@@ -6990,6 +7079,7 @@ function clearAgentCaches(agentId, codeName) {
6990
7079
  mcpFlapDampener.forget(codeName);
6991
7080
  deferLogThrottle.delete(codeName);
6992
7081
  if (channelCacheMutated) saveChannelHashCache2();
7082
+ removeSenderPolicyBaselineEntry(agentId);
6993
7083
  }
6994
7084
  var cachedFrameworkVersion = null;
6995
7085
  var cachedMaintenanceWindow = null;
@@ -6997,7 +7087,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
6997
7087
  var lastVersionCheckAt = 0;
6998
7088
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
6999
7089
  var lastResponsivenessProbeAt = 0;
7000
- var agtCliVersion = true ? "0.28.313" : "dev";
7090
+ var agtCliVersion = true ? "0.28.314" : "dev";
7001
7091
  function resolveBrewPath(execFileSync2) {
7002
7092
  try {
7003
7093
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -7010,7 +7100,7 @@ function resolveBrewPath(execFileSync2) {
7010
7100
  "/usr/local/bin/brew"
7011
7101
  ];
7012
7102
  for (const path of fallbacks) {
7013
- if (existsSync9(path)) return path;
7103
+ if (existsSync10(path)) return path;
7014
7104
  }
7015
7105
  return null;
7016
7106
  }
@@ -7020,7 +7110,7 @@ function claudeBinaryInstalled(execFileSync2) {
7020
7110
  "/opt/homebrew/bin/claude",
7021
7111
  "/usr/local/bin/claude"
7022
7112
  ];
7023
- if (canonical.some((path) => existsSync9(path))) return true;
7113
+ if (canonical.some((path) => existsSync10(path))) return true;
7024
7114
  try {
7025
7115
  execFileSync2("which", ["claude"], { timeout: 5e3 });
7026
7116
  return true;
@@ -7175,8 +7265,8 @@ function claudeManagedSettingsPath() {
7175
7265
  function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
7176
7266
  try {
7177
7267
  let settings = {};
7178
- if (existsSync9(path)) {
7179
- const raw = readFileSync15(path, "utf-8").trim();
7268
+ if (existsSync10(path)) {
7269
+ const raw = readFileSync16(path, "utf-8").trim();
7180
7270
  if (raw) {
7181
7271
  let parsed;
7182
7272
  try {
@@ -7238,7 +7328,7 @@ async function ensureFrameworkBinary(frameworkId) {
7238
7328
  if (!process.env.PATH?.split(":").includes(brewBinDir)) {
7239
7329
  process.env.PATH = `${brewBinDir}:${process.env.PATH ?? ""}`;
7240
7330
  }
7241
- if (existsSync9("/home/linuxbrew/.linuxbrew/bin/claude")) {
7331
+ if (existsSync10("/home/linuxbrew/.linuxbrew/bin/claude")) {
7242
7332
  log("Claude Code installed successfully");
7243
7333
  } else {
7244
7334
  log("Claude Code install completed but binary not found at expected path \u2014 check brew logs");
@@ -7294,7 +7384,7 @@ ${r.stderr}`;
7294
7384
  }
7295
7385
  var UPDATE_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
7296
7386
  function selfUpdateAppliedMarkerPath() {
7297
- return join18(homedir10(), ".augmented", ".last-self-update-applied");
7387
+ return join19(homedir10(), ".augmented", ".last-self-update-applied");
7298
7388
  }
7299
7389
  var selfUpdateUpToDateLogged = false;
7300
7390
  var restartAfterUpgrade = false;
@@ -7318,7 +7408,7 @@ async function checkAndUpdateCli(opts) {
7318
7408
  const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
7319
7409
  if (!isBrewFormula && !isNpmGlobal) return "noop";
7320
7410
  const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
7321
- const markerPath = join18(homedir10(), ".augmented", ".last-update-check");
7411
+ const markerPath = join19(homedir10(), ".augmented", ".last-update-check");
7322
7412
  if (!force) {
7323
7413
  try {
7324
7414
  const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
@@ -7596,13 +7686,13 @@ async function checkClaudeAuth() {
7596
7686
  }
7597
7687
  var evalEmptyMcpConfigPath = null;
7598
7688
  function ensureEvalEmptyMcpConfig() {
7599
- if (evalEmptyMcpConfigPath && existsSync9(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
7600
- const dir = join18(homedir10(), ".augmented");
7689
+ if (evalEmptyMcpConfigPath && existsSync10(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
7690
+ const dir = join19(homedir10(), ".augmented");
7601
7691
  try {
7602
7692
  mkdirSync7(dir, { recursive: true });
7603
7693
  } catch {
7604
7694
  }
7605
- const p = join18(dir, ".eval-empty-mcp.json");
7695
+ const p = join19(dir, ".eval-empty-mcp.json");
7606
7696
  writeFileSync8(p, JSON.stringify({ mcpServers: {} }));
7607
7697
  evalEmptyMcpConfigPath = p;
7608
7698
  return p;
@@ -7694,10 +7784,10 @@ function resolveConversationEvalBackend() {
7694
7784
  return conversationEvalBackend;
7695
7785
  }
7696
7786
  function getStateFile() {
7697
- return join18(config?.configDir ?? join18(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
7787
+ return join19(config?.configDir ?? join19(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
7698
7788
  }
7699
7789
  function channelHashCacheDir() {
7700
- return config?.configDir ?? join18(process.env["HOME"] ?? "/tmp", ".augmented");
7790
+ return config?.configDir ?? join19(process.env["HOME"] ?? "/tmp", ".augmented");
7701
7791
  }
7702
7792
  function loadChannelHashCache2() {
7703
7793
  loadChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
@@ -7705,10 +7795,27 @@ function loadChannelHashCache2() {
7705
7795
  function saveChannelHashCache2() {
7706
7796
  saveChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
7707
7797
  }
7798
+ var persistedSenderPolicyBaseline = /* @__PURE__ */ new Map();
7799
+ function loadSenderPolicyBaseline2() {
7800
+ loadSenderPolicyBaseline(persistedSenderPolicyBaseline, channelHashCacheDir(), log);
7801
+ for (const [agentId, hash] of persistedSenderPolicyBaseline) {
7802
+ agentState.knownSenderPolicyHashes.set(agentId, hash);
7803
+ }
7804
+ }
7805
+ function persistSenderPolicyBaselineEntry(agentId, hash) {
7806
+ if (hash === void 0) return;
7807
+ if (persistedSenderPolicyBaseline.get(agentId) === hash) return;
7808
+ persistedSenderPolicyBaseline.set(agentId, hash);
7809
+ saveSenderPolicyBaseline(persistedSenderPolicyBaseline, channelHashCacheDir(), log);
7810
+ }
7811
+ function removeSenderPolicyBaselineEntry(agentId) {
7812
+ if (!persistedSenderPolicyBaseline.delete(agentId)) return;
7813
+ saveSenderPolicyBaseline(persistedSenderPolicyBaseline, channelHashCacheDir(), log);
7814
+ }
7708
7815
  var _channelQuarantineStore = null;
7709
7816
  function channelQuarantineStore() {
7710
7817
  if (!_channelQuarantineStore) {
7711
- const dir = config?.configDir ?? join18(process.env["HOME"] ?? "/tmp", ".augmented");
7818
+ const dir = config?.configDir ?? join19(process.env["HOME"] ?? "/tmp", ".augmented");
7712
7819
  _channelQuarantineStore = new ChannelQuarantineStore(defaultQuarantinePath(dir));
7713
7820
  }
7714
7821
  return _channelQuarantineStore;
@@ -7716,7 +7823,7 @@ function channelQuarantineStore() {
7716
7823
  var _hostFlagStore = null;
7717
7824
  function hostFlagStore() {
7718
7825
  if (!_hostFlagStore) {
7719
- const dir = config?.configDir ?? join18(process.env["HOME"] ?? "/tmp", ".augmented");
7826
+ const dir = config?.configDir ?? join19(process.env["HOME"] ?? "/tmp", ".augmented");
7720
7827
  _hostFlagStore = new HostFlagStore({ cachePath: defaultFlagsCachePath(dir), log });
7721
7828
  }
7722
7829
  return _hostFlagStore;
@@ -7784,12 +7891,12 @@ function parseSkillFrontmatter(content) {
7784
7891
  }
7785
7892
  async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
7786
7893
  const { readdirSync: readdirSync6, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync9 } = await import("fs");
7787
- const skillsDir = join18(configDir, codeName, "project", ".claude", "skills");
7788
- const claudeMdPath = join18(configDir, codeName, "project", "CLAUDE.md");
7894
+ const skillsDir = join19(configDir, codeName, "project", ".claude", "skills");
7895
+ const claudeMdPath = join19(configDir, codeName, "project", "CLAUDE.md");
7789
7896
  if (!ex(skillsDir) || !ex(claudeMdPath)) return;
7790
7897
  const entries = [];
7791
7898
  for (const dir of readdirSync6(skillsDir).sort()) {
7792
- const skillFile = join18(skillsDir, dir, "SKILL.md");
7899
+ const skillFile = join19(skillsDir, dir, "SKILL.md");
7793
7900
  if (!ex(skillFile)) continue;
7794
7901
  try {
7795
7902
  const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
@@ -8219,13 +8326,13 @@ async function pollCycle() {
8219
8326
  );
8220
8327
  if (hostFlagStore().getBoolean("wedge-transient-notice")) {
8221
8328
  try {
8222
- const paneTail = readFileSync15(paneLogPath(codeName), "utf8").slice(-65536);
8329
+ const paneTail = readFileSync16(paneLogPath(codeName), "utf8").slice(-65536);
8223
8330
  const transient = detectTransientApiErrorInLog(paneTail);
8224
8331
  if (transient) {
8225
- const wedgeHome = join18(homedir10(), ".augmented", codeName);
8226
- if (existsSync9(wedgeHome)) {
8332
+ const wedgeHome = join19(homedir10(), ".augmented", codeName);
8333
+ if (existsSync10(wedgeHome)) {
8227
8334
  atomicWriteFileSync(
8228
- join18(wedgeHome, "watchdog-give-up.json"),
8335
+ join19(wedgeHome, "watchdog-give-up.json"),
8229
8336
  JSON.stringify({
8230
8337
  gave_up_at: wedgeNow.toISOString(),
8231
8338
  reason: "transient_overload"
@@ -8474,7 +8581,7 @@ async function pollCycle() {
8474
8581
  } catch {
8475
8582
  }
8476
8583
  killAgentChannelProcesses(prev.codeName, { log });
8477
- const agentDir = join18(adapter.getAgentDir(prev.codeName), "provision");
8584
+ const agentDir = join19(adapter.getAgentDir(prev.codeName), "provision");
8478
8585
  await cleanupAgentFiles(prev.codeName, agentDir);
8479
8586
  clearAgentCaches(prev.agentId, prev.codeName);
8480
8587
  }
@@ -8561,10 +8668,10 @@ async function pollCycle() {
8561
8668
  // pending-inbound marker. Best-effort: a write failure is logged by
8562
8669
  // the watchdog, never fails the poll cycle.
8563
8670
  signalGiveUp: (codeName) => {
8564
- const dir = join18(homedir10(), ".augmented", codeName);
8565
- if (!existsSync9(dir)) return;
8671
+ const dir = join19(homedir10(), ".augmented", codeName);
8672
+ if (!existsSync10(dir)) return;
8566
8673
  atomicWriteFileSync(
8567
- join18(dir, "watchdog-give-up.json"),
8674
+ join19(dir, "watchdog-give-up.json"),
8568
8675
  JSON.stringify({ gave_up_at: (/* @__PURE__ */ new Date()).toISOString() })
8569
8676
  );
8570
8677
  }
@@ -8694,7 +8801,7 @@ async function processAgent(agent, agentStates) {
8694
8801
  }
8695
8802
  const now = (/* @__PURE__ */ new Date()).toISOString();
8696
8803
  const adapter = resolveAgentFramework(agent.code_name);
8697
- let agentDir = join18(adapter.getAgentDir(agent.code_name), "provision");
8804
+ let agentDir = join19(adapter.getAgentDir(agent.code_name), "provision");
8698
8805
  if (agent.status === "draft" || agent.status === "paused") {
8699
8806
  if (previousKnownStatus !== agent.status) {
8700
8807
  log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
@@ -8740,7 +8847,7 @@ async function processAgent(agent, agentStates) {
8740
8847
  const residuals = {
8741
8848
  gatewayRunning: false,
8742
8849
  portAllocated: false,
8743
- provisionDirExists: existsSync9(agentDir)
8850
+ provisionDirExists: existsSync10(agentDir)
8744
8851
  };
8745
8852
  if (!hasRevokedResiduals(residuals)) {
8746
8853
  agentStates.push({
@@ -8878,7 +8985,7 @@ async function processAgent(agent, agentStates) {
8878
8985
  const frameworkId = refreshData.agent.framework ?? DEFAULT_FRAMEWORK;
8879
8986
  agentFrameworkCache.set(agent.code_name, frameworkId);
8880
8987
  const frameworkAdapter = getFramework(frameworkId);
8881
- agentDir = join18(frameworkAdapter.getAgentDir(agent.code_name), "provision");
8988
+ agentDir = join19(frameworkAdapter.getAgentDir(agent.code_name), "provision");
8882
8989
  cacheAgentDeliveryMetadata(agent.code_name, refreshData);
8883
8990
  agentRestartTimezoneInputs.set(agent.code_name, {
8884
8991
  agentTimezone: typeof refreshData.agent.timezone === "string" ? refreshData.agent.timezone : null,
@@ -8925,7 +9032,7 @@ async function processAgent(agent, agentStates) {
8925
9032
  const changedFiles = [];
8926
9033
  mkdirSync7(agentDir, { recursive: true });
8927
9034
  for (const artifact of artifacts) {
8928
- const filePath = join18(agentDir, artifact.relativePath);
9035
+ const filePath = join19(agentDir, artifact.relativePath);
8929
9036
  let existingHash;
8930
9037
  let newHash;
8931
9038
  let writeContent = artifact.content;
@@ -8944,8 +9051,8 @@ async function processAgent(agent, agentStates) {
8944
9051
  };
8945
9052
  newHash = sha256(stripDynamicSections(artifact.content));
8946
9053
  try {
8947
- const projectClaudeMd = join18(config.configDir, agent.code_name, "project", "CLAUDE.md");
8948
- const existing = readFileSync15(projectClaudeMd, "utf-8");
9054
+ const projectClaudeMd = join19(config.configDir, agent.code_name, "project", "CLAUDE.md");
9055
+ const existing = readFileSync16(projectClaudeMd, "utf-8");
8949
9056
  existingHash = sha256(stripDynamicSections(existing));
8950
9057
  } catch {
8951
9058
  existingHash = null;
@@ -8963,7 +9070,7 @@ async function processAgent(agent, agentStates) {
8963
9070
  const generatorKeys = Object.keys(generatorServers);
8964
9071
  let existingRaw = "";
8965
9072
  try {
8966
- existingRaw = readFileSync15(filePath, "utf-8");
9073
+ existingRaw = readFileSync16(filePath, "utf-8");
8967
9074
  } catch {
8968
9075
  }
8969
9076
  const existingServers = parseMcp(existingRaw);
@@ -8985,12 +9092,12 @@ async function processAgent(agent, agentStates) {
8985
9092
  }
8986
9093
  }
8987
9094
  if (changedFiles.length > 0) {
8988
- const isFirst = !existsSync9(join18(agentDir, "CHARTER.md"));
9095
+ const isFirst = !existsSync10(join19(agentDir, "CHARTER.md"));
8989
9096
  const verb = isFirst ? "Provisioning" : "Updating";
8990
9097
  const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
8991
9098
  log(`${verb} '${agent.code_name}': ${fileNames}`);
8992
9099
  for (const file of changedFiles) {
8993
- const filePath = join18(agentDir, file.relativePath);
9100
+ const filePath = join19(agentDir, file.relativePath);
8994
9101
  mkdirSync7(dirname6(filePath), { recursive: true });
8995
9102
  if (file.relativePath === ".mcp.json") {
8996
9103
  safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
@@ -8999,12 +9106,12 @@ async function processAgent(agent, agentStates) {
8999
9106
  }
9000
9107
  }
9001
9108
  try {
9002
- const provSkillsDir = join18(agentDir, ".claude", "skills");
9003
- if (existsSync9(provSkillsDir)) {
9109
+ const provSkillsDir = join19(agentDir, ".claude", "skills");
9110
+ if (existsSync10(provSkillsDir)) {
9004
9111
  for (const folder of readdirSync5(provSkillsDir)) {
9005
9112
  if (folder.startsWith("knowledge-")) {
9006
9113
  try {
9007
- rmSync4(join18(provSkillsDir, folder), { recursive: true });
9114
+ rmSync4(join19(provSkillsDir, folder), { recursive: true });
9008
9115
  } catch {
9009
9116
  }
9010
9117
  }
@@ -9017,7 +9124,7 @@ async function processAgent(agent, agentStates) {
9017
9124
  const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
9018
9125
  const hashes = /* @__PURE__ */ new Map();
9019
9126
  for (const file of trackedFiles2) {
9020
- const h = hashFile(join18(agentDir, file));
9127
+ const h = hashFile(join19(agentDir, file));
9021
9128
  if (h) hashes.set(file, h);
9022
9129
  }
9023
9130
  agentState.writtenHashes.set(agent.agent_id, hashes);
@@ -9035,14 +9142,14 @@ async function processAgent(agent, agentStates) {
9035
9142
  }
9036
9143
  if (Array.isArray(refreshData.workflows)) {
9037
9144
  try {
9038
- const provWorkflowsDir = join18(agentDir, ".claude", "workflows");
9039
- if (existsSync9(provWorkflowsDir)) {
9145
+ const provWorkflowsDir = join19(agentDir, ".claude", "workflows");
9146
+ if (existsSync10(provWorkflowsDir)) {
9040
9147
  const expected = new Set(refreshData.workflows.map((w) => `${w.name}.js`));
9041
9148
  for (const file of readdirSync5(provWorkflowsDir)) {
9042
9149
  if (!file.endsWith(".js")) continue;
9043
9150
  if (expected.has(file)) continue;
9044
9151
  try {
9045
- rmSync4(join18(provWorkflowsDir, file));
9152
+ rmSync4(join19(provWorkflowsDir, file));
9046
9153
  } catch {
9047
9154
  }
9048
9155
  }
@@ -9099,10 +9206,10 @@ async function processAgent(agent, agentStates) {
9099
9206
  }
9100
9207
  let lastDriftCheckAt = now;
9101
9208
  const written = agentState.writtenHashes.get(agent.agent_id);
9102
- if (written && existsSync9(agentDir)) {
9209
+ if (written && existsSync10(agentDir)) {
9103
9210
  const driftedFiles = [];
9104
9211
  for (const [file, expectedHash] of written) {
9105
- const localHash = hashFile(join18(agentDir, file));
9212
+ const localHash = hashFile(join19(agentDir, file));
9106
9213
  if (localHash && localHash !== expectedHash) {
9107
9214
  driftedFiles.push(file);
9108
9215
  }
@@ -9113,7 +9220,7 @@ async function processAgent(agent, agentStates) {
9113
9220
  try {
9114
9221
  const localHashes = {};
9115
9222
  for (const file of driftedFiles) {
9116
- localHashes[file] = hashFile(join18(agentDir, file));
9223
+ localHashes[file] = hashFile(join19(agentDir, file));
9117
9224
  }
9118
9225
  await api.post("/host/drift", {
9119
9226
  agent_id: agent.agent_id,
@@ -9300,7 +9407,7 @@ async function processAgent(agent, agentStates) {
9300
9407
  const addedChannels = [...restartDecision.added];
9301
9408
  const writeDmNoticeMarkers = isChannelAddRestart ? () => {
9302
9409
  try {
9303
- const agentAugmentedDir = join18(homedir10(), ".augmented", agent.code_name);
9410
+ const agentAugmentedDir = join19(homedir10(), ".augmented", agent.code_name);
9304
9411
  mkdirSync7(agentAugmentedDir, { recursive: true });
9305
9412
  const markerJson = JSON.stringify({
9306
9413
  version: 1,
@@ -9308,7 +9415,7 @@ async function processAgent(agent, agentStates) {
9308
9415
  added: addedChannels
9309
9416
  });
9310
9417
  for (const file of ["slack-channel-add-restart.json", "telegram-channel-add-restart.json"]) {
9311
- atomicWriteFileSync(join18(agentAugmentedDir, file), markerJson);
9418
+ atomicWriteFileSync(join19(agentAugmentedDir, file), markerJson);
9312
9419
  }
9313
9420
  } catch (err) {
9314
9421
  log(`[hot-reload] channel-add DM-notice marker write failed for '${agent.code_name}' (non-fatal): ${err.message}`);
@@ -9326,20 +9433,26 @@ async function processAgent(agent, agentStates) {
9326
9433
  const hasSenderPolicyChannel = currentChannelIds.has("slack") || currentChannelIds.has("msteams");
9327
9434
  const senderPolicyForRestartHash = refreshData.sender_policy ?? null;
9328
9435
  const senderPolicyHash = computeSenderPolicyRestartHash(senderPolicyForRestartHash);
9436
+ const senderPolicyRestrictive = isSenderPolicyRestrictive(senderPolicyForRestartHash);
9329
9437
  const prevSenderPolicyHash = agentState.knownSenderPolicyHashes.get(agent.agent_id);
9438
+ const spSessionMode = refreshData.agent.session_mode;
9439
+ const spFramework = agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK;
9440
+ const spSessionHealthy = isSessionHealthy(agent.code_name);
9330
9441
  const senderPolicyDecision = hasSenderPolicyChannel ? decideSenderPolicyRestart({
9331
9442
  previousHash: prevSenderPolicyHash,
9443
+ currentPolicyRestrictive: senderPolicyRestrictive,
9332
9444
  currentHash: senderPolicyHash,
9333
- sessionMode: refreshData.agent.session_mode,
9334
- framework: agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK,
9335
- sessionHealthy: isSessionHealthy(agent.code_name),
9445
+ sessionMode: spSessionMode,
9446
+ framework: spFramework,
9447
+ sessionHealthy: spSessionHealthy,
9336
9448
  channelSetRestartAlreadyScheduled: channelSetRestartScheduled
9337
9449
  }) : { restart: false, firstPoll: prevSenderPolicyHash === void 0, changed: false };
9338
9450
  if (senderPolicyDecision.restart) {
9451
+ const isVerifyRestart = senderPolicyDecision.firstPoll;
9339
9452
  log(
9340
- `[hot-reload] sender_policy changed for '${agent.code_name}' (${prevSenderPolicyHash?.slice(0, 8) ?? "first"} \u2192 ${senderPolicyHash.slice(0, 8)}) \u2014 restarting session`
9453
+ isVerifyRestart ? `[hot-reload] sender_policy delivery baseline unknown for '${agent.code_name}' with a restrictive policy (\u2192 ${senderPolicyHash.slice(0, 8)}) \u2014 restarting session to guarantee enforcement (fail closed, ENG-7771)` : `[hot-reload] sender_policy changed for '${agent.code_name}' (${prevSenderPolicyHash?.slice(0, 8) ?? "first"} \u2192 ${senderPolicyHash.slice(0, 8)}) \u2014 restarting session`
9341
9454
  );
9342
- const notice = "Your sender_policy has been updated. Restarting session shortly so the channel MCP servers pick up the new gate.";
9455
+ const notice = isVerifyRestart ? "Your manager was updated and needs to restart your session to make sure your configured sender policy is enforced by the channel MCP servers." : "Your sender_policy has been updated. Restarting session shortly so the channel MCP servers pick up the new gate.";
9343
9456
  const delivered = await injectMessage(
9344
9457
  agent.code_name,
9345
9458
  "system",
@@ -9356,11 +9469,22 @@ async function processAgent(agent, agentStates) {
9356
9469
  scheduleSessionRestart(
9357
9470
  agent.code_name,
9358
9471
  delay,
9359
- "sender_policy change",
9472
+ isVerifyRestart ? "sender policy verify (unknown baseline)" : "sender_policy change",
9360
9473
  "sender-policy-change"
9361
9474
  );
9362
9475
  }
9363
9476
  agentState.knownSenderPolicyHashes.set(agent.agent_id, senderPolicyHash);
9477
+ const hasLiveSenderPolicyConsumer = hasSenderPolicyChannel && spSessionHealthy && spSessionMode === "persistent" && spFramework === "claude-code";
9478
+ if (!hasLiveSenderPolicyConsumer) {
9479
+ persistSenderPolicyBaselineEntry(agent.agent_id, senderPolicyHash);
9480
+ } else if (senderPolicyDecision.firstPoll && !senderPolicyRestrictive) {
9481
+ if (persistedSenderPolicyBaseline.get(agent.agent_id) !== senderPolicyHash) {
9482
+ log(
9483
+ `[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)`
9484
+ );
9485
+ }
9486
+ persistSenderPolicyBaselineEntry(agent.agent_id, senderPolicyHash);
9487
+ }
9364
9488
  let msteamsBehaviourRestartScheduled = false;
9365
9489
  if (currentChannelIds.has("msteams")) {
9366
9490
  const msteamsEntry = refreshData.channel_configs?.["msteams"];
@@ -9371,6 +9495,12 @@ async function processAgent(agent, agentStates) {
9371
9495
  const prevBehaviourHash = agentState.knownMsTeamsBehaviourHashes.get(agent.agent_id);
9372
9496
  const behaviourDecision = decideSenderPolicyRestart({
9373
9497
  previousHash: prevBehaviourHash,
9498
+ // ENG-7771 scoped the persisted-baseline + first-poll fail-safe to
9499
+ // sender_policy only; the behaviour baselines keep the legacy
9500
+ // "first poll never restarts" semantics until the follow-up that
9501
+ // migrates them onto the sidecar (their maps share the same
9502
+ // wipe-on-manager-restart pathology).
9503
+ currentPolicyRestrictive: false,
9374
9504
  currentHash: behaviourHash,
9375
9505
  sessionMode: refreshData.agent.session_mode,
9376
9506
  framework: agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK,
@@ -9418,6 +9548,9 @@ async function processAgent(agent, agentStates) {
9418
9548
  const prevSlackBehaviourHash = agentState.knownSlackBehaviourHashes.get(agent.agent_id);
9419
9549
  const slackBehaviourDecision = decideSenderPolicyRestart({
9420
9550
  previousHash: prevSlackBehaviourHash,
9551
+ // See the msteams call above — behaviour baselines are out of
9552
+ // ENG-7771's scope; legacy first-poll semantics until the follow-up.
9553
+ currentPolicyRestrictive: false,
9421
9554
  currentHash: slackBehaviourHash,
9422
9555
  sessionMode: refreshData.agent.session_mode,
9423
9556
  framework: agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK,
@@ -9461,24 +9594,24 @@ async function processAgent(agent, agentStates) {
9461
9594
  if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK) === "claude-code") {
9462
9595
  try {
9463
9596
  const agentProvisionDir = agentDir;
9464
- const projectDir = join18(homedir10(), ".augmented", agent.code_name, "project");
9597
+ const projectDir = join19(homedir10(), ".augmented", agent.code_name, "project");
9465
9598
  mkdirSync7(agentProvisionDir, { recursive: true });
9466
9599
  mkdirSync7(projectDir, { recursive: true });
9467
- const provisionMcpPath = join18(agentProvisionDir, ".mcp.json");
9468
- const projectMcpPath = join18(projectDir, ".mcp.json");
9600
+ const provisionMcpPath = join19(agentProvisionDir, ".mcp.json");
9601
+ const projectMcpPath = join19(projectDir, ".mcp.json");
9469
9602
  let mcpConfig = { mcpServers: {} };
9470
9603
  try {
9471
- mcpConfig = JSON.parse(readFileSync15(provisionMcpPath, "utf-8"));
9604
+ mcpConfig = JSON.parse(readFileSync16(provisionMcpPath, "utf-8"));
9472
9605
  if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
9473
9606
  } catch {
9474
9607
  }
9475
- const localDirectChatChannel = join18(homedir10(), ".augmented", "_mcp", "direct-chat-channel.js");
9608
+ const localDirectChatChannel = join19(homedir10(), ".augmented", "_mcp", "direct-chat-channel.js");
9476
9609
  const directChatTeamSettings = refreshData.team?.settings;
9477
9610
  const directChatTz = (() => {
9478
9611
  const tz = directChatTeamSettings?.["timezone"];
9479
9612
  return typeof tz === "string" && tz.trim() !== "" ? tz.trim() : void 0;
9480
9613
  })();
9481
- if (existsSync9(localDirectChatChannel)) {
9614
+ if (existsSync10(localDirectChatChannel)) {
9482
9615
  const directChatEnv = {
9483
9616
  AGT_HOST: requireHost(),
9484
9617
  // ENG-5901 Track D: templated — the manager exports the real
@@ -9498,7 +9631,7 @@ async function processAgent(agent, agentStates) {
9498
9631
  // ~/.augmented/<codeName>/.current-turn-initiator.json. Note getAgentDir
9499
9632
  // returns the agent root (NOT the /provision subdir `agentDir` points at),
9500
9633
  // so it byte-matches the broker readers' path.
9501
- AGT_TURN_INITIATOR_FILE: join18(
9634
+ AGT_TURN_INITIATOR_FILE: join19(
9502
9635
  frameworkAdapter.getAgentDir(agent.code_name),
9503
9636
  ".current-turn-initiator.json"
9504
9637
  )
@@ -9518,8 +9651,8 @@ async function processAgent(agent, agentStates) {
9518
9651
  log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
9519
9652
  }
9520
9653
  }
9521
- const staleChannelsPath = join18(projectDir, ".mcp-channels.json");
9522
- if (existsSync9(staleChannelsPath)) {
9654
+ const staleChannelsPath = join19(projectDir, ".mcp-channels.json");
9655
+ if (existsSync10(staleChannelsPath)) {
9523
9656
  try {
9524
9657
  rmSync4(staleChannelsPath, { force: true });
9525
9658
  } catch {
@@ -9590,7 +9723,7 @@ async function processAgent(agent, agentStates) {
9590
9723
  }
9591
9724
  if (hostFlagStore().getBoolean("connectivity-probe")) {
9592
9725
  try {
9593
- const probeProjectDir = join18(homedir10(), ".augmented", agent.code_name, "project");
9726
+ const probeProjectDir = join19(homedir10(), ".augmented", agent.code_name, "project");
9594
9727
  await runAgentConnectivityProbes(agent, integrations, probeProjectDir);
9595
9728
  } catch (err) {
9596
9729
  log(`Connectivity probe failed for '${agent.code_name}': ${err.message}`);
@@ -9601,7 +9734,7 @@ async function processAgent(agent, agentStates) {
9601
9734
  const forceDue = attemptsLeft > 0;
9602
9735
  let probeRan = false;
9603
9736
  try {
9604
- const probeProjectDir = join18(homedir10(), ".augmented", agent.code_name, "project");
9737
+ const probeProjectDir = join19(homedir10(), ".augmented", agent.code_name, "project");
9605
9738
  probeRan = await runAgentSessionToolBindProbes(agent, integrations, probeProjectDir, { forceDue });
9606
9739
  } catch (err) {
9607
9740
  log(`Session-tool-bind probe failed for '${agent.code_name}': ${err.message}`);
@@ -9614,9 +9747,9 @@ async function processAgent(agent, agentStates) {
9614
9747
  }
9615
9748
  if (frameworkAdapter.removeMcpServer && frameworkAdapter.getMcpPath) {
9616
9749
  const mcpPath = frameworkAdapter.getMcpPath(agent.code_name);
9617
- if (mcpPath && existsSync9(mcpPath)) {
9750
+ if (mcpPath && existsSync10(mcpPath)) {
9618
9751
  try {
9619
- const cfg = JSON.parse(readFileSync15(mcpPath, "utf-8"));
9752
+ const cfg = JSON.parse(readFileSync16(mcpPath, "utf-8"));
9620
9753
  const expectedRemoteKeys = new Set(
9621
9754
  integrations.map((i) => i.definition_id)
9622
9755
  );
@@ -9641,11 +9774,11 @@ async function processAgent(agent, agentStates) {
9641
9774
  recordConfigChurnEvent(agent.agent_id, agent.code_name, FLAP_CHANNEL_INTEGRATIONS, intMembership);
9642
9775
  }
9643
9776
  if (intHash !== prevIntHash) {
9644
- const projectDir = join18(homedir10(), ".augmented", agent.code_name, "project");
9645
- const envIntPath = join18(projectDir, ".env.integrations");
9777
+ const projectDir = join19(homedir10(), ".augmented", agent.code_name, "project");
9778
+ const envIntPath = join19(projectDir, ".env.integrations");
9646
9779
  let preWriteEnv;
9647
9780
  try {
9648
- preWriteEnv = readFileSync15(envIntPath, "utf-8");
9781
+ preWriteEnv = readFileSync16(envIntPath, "utf-8");
9649
9782
  } catch {
9650
9783
  preWriteEnv = void 0;
9651
9784
  }
@@ -9657,9 +9790,9 @@ async function processAgent(agent, agentStates) {
9657
9790
  let rotationHandled = true;
9658
9791
  if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
9659
9792
  try {
9660
- const projectMcpPath = join18(projectDir, ".mcp.json");
9661
- const postWriteEnv = readFileSync15(envIntPath, "utf-8");
9662
- const mcpContent = readFileSync15(projectMcpPath, "utf-8");
9793
+ const projectMcpPath = join19(projectDir, ".mcp.json");
9794
+ const postWriteEnv = readFileSync16(envIntPath, "utf-8");
9795
+ const mcpContent = readFileSync16(projectMcpPath, "utf-8");
9663
9796
  const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
9664
9797
  const mcpJsonForReap = JSON.parse(mcpContent);
9665
9798
  const affectedServerKeys = findMcpServersUsingVars(mcpJsonForReap, changedVars);
@@ -9760,8 +9893,8 @@ async function processAgent(agent, agentStates) {
9760
9893
  const mcpPath = frameworkAdapter.getMcpPath(agent.code_name);
9761
9894
  if (mcpPath) {
9762
9895
  try {
9763
- const { readFileSync: readFileSync16 } = await import("fs");
9764
- const mcpConfig = JSON.parse(readFileSync16(mcpPath, "utf-8"));
9896
+ const { readFileSync: readFileSync17 } = await import("fs");
9897
+ const mcpConfig = JSON.parse(readFileSync17(mcpPath, "utf-8"));
9765
9898
  if (mcpConfig.mcpServers) {
9766
9899
  for (const key of Object.keys(mcpConfig.mcpServers)) {
9767
9900
  if (isManagedMcpServerKey(key) && !expectedServerIds.has(key)) {
@@ -9908,14 +10041,14 @@ async function processAgent(agent, agentStates) {
9908
10041
  const frameworkId2 = frameworkAdapter.id;
9909
10042
  const candidateSkillDirs = [
9910
10043
  // Claude Code — framework runtime tree
9911
- join18(homedir11(), ".augmented", agent.code_name, "skills"),
10044
+ join19(homedir11(), ".augmented", agent.code_name, "skills"),
9912
10045
  // Claude Code — project tree
9913
- join18(homedir11(), ".augmented", agent.code_name, "project", ".claude", "skills"),
10046
+ join19(homedir11(), ".augmented", agent.code_name, "project", ".claude", "skills"),
9914
10047
  // Defensive: legacy provision-side path, not currently an
9915
10048
  // install target but cheap to sweep.
9916
- join18(agentDir, ".claude", "skills")
10049
+ join19(agentDir, ".claude", "skills")
9917
10050
  ];
9918
- const existingDirs = candidateSkillDirs.filter((d) => existsSync9(d));
10051
+ const existingDirs = candidateSkillDirs.filter((d) => existsSync10(d));
9919
10052
  const discoveredEntries = /* @__PURE__ */ new Set();
9920
10053
  for (const dir of existingDirs) {
9921
10054
  try {
@@ -9929,8 +10062,8 @@ async function processAgent(agent, agentStates) {
9929
10062
  }
9930
10063
  const removeSkillFolder = (entry, reason) => {
9931
10064
  for (const dir of existingDirs) {
9932
- const p = join18(dir, entry);
9933
- if (existsSync9(p)) {
10065
+ const p = join19(dir, entry);
10066
+ if (existsSync10(p)) {
9934
10067
  rmSync5(p, { recursive: true, force: true });
9935
10068
  }
9936
10069
  }
@@ -9949,7 +10082,7 @@ async function processAgent(agent, agentStates) {
9949
10082
  const sharedSkillsPayload = refreshAny.shared_skills;
9950
10083
  const desiredResolved = globalSkillsPayload !== void 0 || sharedSkillsPayload !== void 0;
9951
10084
  const manifestPath = managedSkillManifestPath(
9952
- join18(homedir10(), ".augmented", agent.code_name)
10085
+ join19(homedir10(), ".augmented", agent.code_name)
9953
10086
  );
9954
10087
  const prevIds = /* @__PURE__ */ new Set([
9955
10088
  ...agentState.knownGlobalSkillIds.get(agent.agent_id) ?? /* @__PURE__ */ new Set(),
@@ -9969,15 +10102,15 @@ async function processAgent(agent, agentStates) {
9969
10102
  }
9970
10103
  if (plan.removes.length) {
9971
10104
  const globalSkillDirs = [
9972
- join18(homedir10(), ".augmented", agent.code_name, "skills"),
9973
- join18(homedir10(), ".augmented", agent.code_name, "project", ".claude", "skills"),
9974
- join18(agentDir, ".claude", "skills")
10105
+ join19(homedir10(), ".augmented", agent.code_name, "skills"),
10106
+ join19(homedir10(), ".augmented", agent.code_name, "project", ".claude", "skills"),
10107
+ join19(agentDir, ".claude", "skills")
9975
10108
  ];
9976
10109
  for (const id of plan.removes) {
9977
10110
  let prunedAny = false;
9978
10111
  for (const dir of globalSkillDirs) {
9979
- const p = join18(dir, id);
9980
- if (existsSync9(p) && existsSync9(join18(p, "SKILL.md"))) {
10112
+ const p = join19(dir, id);
10113
+ if (existsSync10(p) && existsSync10(join19(p, "SKILL.md"))) {
9981
10114
  rmSync4(p, { recursive: true, force: true });
9982
10115
  prunedAny = true;
9983
10116
  }
@@ -10180,8 +10313,8 @@ async function processAgent(agent, agentStates) {
10180
10313
  const sess = getSessionState(agent.code_name);
10181
10314
  let mcpJsonParsed = null;
10182
10315
  try {
10183
- const mcpPath = join18(getProjectDir(agent.code_name), ".mcp.json");
10184
- mcpJsonParsed = JSON.parse(readFileSync15(mcpPath, "utf-8"));
10316
+ const mcpPath = join19(getProjectDir(agent.code_name), ".mcp.json");
10317
+ mcpJsonParsed = JSON.parse(readFileSync16(mcpPath, "utf-8"));
10185
10318
  } catch {
10186
10319
  }
10187
10320
  reapMissingMcpSessions({
@@ -10506,10 +10639,10 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
10506
10639
  }
10507
10640
  }
10508
10641
  const trackedFiles = frameworkAdapter.driftTrackedFiles();
10509
- if (trackedFiles.length > 0 && existsSync9(agentDir)) {
10642
+ if (trackedFiles.length > 0 && existsSync10(agentDir)) {
10510
10643
  const hashes = /* @__PURE__ */ new Map();
10511
10644
  for (const file of trackedFiles) {
10512
- const h = hashFile(join18(agentDir, file));
10645
+ const h = hashFile(join19(agentDir, file));
10513
10646
  if (h) hashes.set(file, h);
10514
10647
  }
10515
10648
  agentState.writtenHashes.set(agent.agent_id, hashes);
@@ -10524,7 +10657,7 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
10524
10657
  refreshData.agent.onboarding_state
10525
10658
  );
10526
10659
  const obStep = obState.step;
10527
- const markerPath = join18(homedir10(), ".augmented", agent.code_name, "onboarding-drive.json");
10660
+ const markerPath = join19(homedir10(), ".augmented", agent.code_name, "onboarding-drive.json");
10528
10661
  const marker = readOnboardingDriveMarker(markerPath);
10529
10662
  const decision = decideOnboardingDrive(obStep, marker, Date.now(), obState.generation ?? 0);
10530
10663
  if (decision.clearMarker) {
@@ -10588,8 +10721,8 @@ var egressAllowlistEqual = (a, b) => a.length === b.length && a.every((d, i) =>
10588
10721
  async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
10589
10722
  const codeName = agent.code_name;
10590
10723
  const projectDir = getProjectDir(codeName);
10591
- const mcpConfigPath = join18(projectDir, ".mcp.json");
10592
- const claudeMdPath = join18(projectDir, "CLAUDE.md");
10724
+ const mcpConfigPath = join19(projectDir, ".mcp.json");
10725
+ const claudeMdPath = join19(projectDir, "CLAUDE.md");
10593
10726
  if (restartBreaker.isTripped(codeName)) {
10594
10727
  const trip = restartBreaker.getTrip(codeName);
10595
10728
  return {
@@ -11837,8 +11970,8 @@ function parseMemoryFile(raw, fallbackName) {
11837
11970
  };
11838
11971
  }
11839
11972
  async function syncMemories(agent, configDir, log2) {
11840
- const projectDir = join18(configDir, agent.code_name, "project");
11841
- const memoryDir = join18(projectDir, "memory");
11973
+ const projectDir = join19(configDir, agent.code_name, "project");
11974
+ const memoryDir = join19(projectDir, "memory");
11842
11975
  const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
11843
11976
  if (isFreshSync) {
11844
11977
  log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
@@ -11849,14 +11982,14 @@ async function syncMemories(agent, configDir, log2) {
11849
11982
  }
11850
11983
  pendingFreshMemorySync.delete(agent.agent_id);
11851
11984
  }
11852
- if (existsSync9(memoryDir)) {
11985
+ if (existsSync10(memoryDir)) {
11853
11986
  const prevHashes = memoryFileHashes.get(agent.agent_id) ?? /* @__PURE__ */ new Map();
11854
11987
  const currentHashes = /* @__PURE__ */ new Map();
11855
11988
  const changedMemories = [];
11856
11989
  for (const file of readdirSync5(memoryDir)) {
11857
11990
  if (!file.endsWith(".md")) continue;
11858
11991
  try {
11859
- const raw = readFileSync15(join18(memoryDir, file), "utf-8");
11992
+ const raw = readFileSync16(join19(memoryDir, file), "utf-8");
11860
11993
  const fileHash = createHash11("sha256").update(raw).digest("hex").slice(0, 16);
11861
11994
  currentHashes.set(file, fileHash);
11862
11995
  if (prevHashes.get(file) === fileHash) continue;
@@ -11881,7 +12014,7 @@ async function syncMemories(agent, configDir, log2) {
11881
12014
  } catch (err) {
11882
12015
  for (const mem of changedMemories) {
11883
12016
  for (const [file] of currentHashes) {
11884
- const parsed = parseMemoryFile(readFileSync15(join18(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
12017
+ const parsed = parseMemoryFile(readFileSync16(join19(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
11885
12018
  if (parsed?.name === mem.name) currentHashes.delete(file);
11886
12019
  }
11887
12020
  }
@@ -11894,7 +12027,7 @@ async function syncMemories(agent, configDir, log2) {
11894
12027
  }
11895
12028
  }
11896
12029
  async function downloadMemories(agent, memoryDir, log2, { force }) {
11897
- const localFiles = existsSync9(memoryDir) ? readdirSync5(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
12030
+ const localFiles = existsSync10(memoryDir) ? readdirSync5(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
11898
12031
  const localListHash = createHash11("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
11899
12032
  const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
11900
12033
  const prevDownload = lastDownloadHash.get(agent.agent_id);
@@ -11916,7 +12049,7 @@ async function downloadMemories(agent, memoryDir, log2, { force }) {
11916
12049
  const mem = dbMemories.memories[i];
11917
12050
  const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
11918
12051
  const slug = rawSlug || `memory-${i}`;
11919
- const filePath = join18(memoryDir, `${slug}.md`);
12052
+ const filePath = join19(memoryDir, `${slug}.md`);
11920
12053
  const desired = `---
11921
12054
  name: ${JSON.stringify(mem.name)}
11922
12055
  type: ${mem.type}
@@ -11925,10 +12058,10 @@ description: ${JSON.stringify(mem.content.slice(0, 200))}
11925
12058
 
11926
12059
  ${mem.content}
11927
12060
  `;
11928
- if (existsSync9(filePath)) {
12061
+ if (existsSync10(filePath)) {
11929
12062
  let existing = "";
11930
12063
  try {
11931
- existing = readFileSync15(filePath, "utf-8");
12064
+ existing = readFileSync16(filePath, "utf-8");
11932
12065
  } catch {
11933
12066
  }
11934
12067
  if (existing === desired) continue;
@@ -11952,7 +12085,7 @@ ${mem.content}
11952
12085
  }
11953
12086
  }
11954
12087
  async function cleanupAgentFiles(codeName, agentDir) {
11955
- if (existsSync9(agentDir)) {
12088
+ if (existsSync10(agentDir)) {
11956
12089
  try {
11957
12090
  rmSync4(agentDir, { recursive: true, force: true });
11958
12091
  log(`Removed provision directory for '${codeName}'`);
@@ -12061,6 +12194,7 @@ function startPolling() {
12061
12194
  livenessTimer.unref();
12062
12195
  void startCaffeinate();
12063
12196
  loadChannelHashCache2();
12197
+ loadSenderPolicyBaseline2();
12064
12198
  hostFlagStore().init();
12065
12199
  log(`Starting poll loop (interval=${config.intervalMs}ms, configDir=${config.configDir})`);
12066
12200
  void killAllAgtTmuxSessions().catch(() => {
@@ -12185,8 +12319,8 @@ function startManager(opts) {
12185
12319
  config = opts;
12186
12320
  try {
12187
12321
  const stateFile = getStateFile();
12188
- if (existsSync9(stateFile)) {
12189
- const raw = readFileSync15(stateFile, "utf-8");
12322
+ if (existsSync10(stateFile)) {
12323
+ const raw = readFileSync16(stateFile, "utf-8");
12190
12324
  const parsed = JSON.parse(raw);
12191
12325
  if (Array.isArray(parsed.agents)) {
12192
12326
  state6.agents = parsed.agents;
@@ -12213,7 +12347,7 @@ function startManager(opts) {
12213
12347
  log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
12214
12348
  }
12215
12349
  log(
12216
- `[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join18(homedir10(), ".augmented", "manager.log")}`
12350
+ `[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join19(homedir10(), ".augmented", "manager.log")}`
12217
12351
  );
12218
12352
  deployMcpAssets();
12219
12353
  reapOrphanChannelMcps({ log });
@@ -12234,7 +12368,7 @@ async function reapOrphanedClaudePids() {
12234
12368
  const looksLikeClaude = (pid) => {
12235
12369
  if (process.platform !== "linux") return true;
12236
12370
  try {
12237
- const comm = readFileSync15(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
12371
+ const comm = readFileSync16(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
12238
12372
  return comm.includes("claude");
12239
12373
  } catch {
12240
12374
  return false;
@@ -12331,14 +12465,14 @@ function restartRunningChannelMcps(basenames) {
12331
12465
  }
12332
12466
  }
12333
12467
  function deployMcpAssets() {
12334
- const targetDir = join18(homedir10(), ".augmented", "_mcp");
12468
+ const targetDir = join19(homedir10(), ".augmented", "_mcp");
12335
12469
  mkdirSync7(targetDir, { recursive: true });
12336
12470
  const moduleDir = dirname6(fileURLToPath(import.meta.url));
12337
12471
  let mcpSourceDir = "";
12338
12472
  let dir = moduleDir;
12339
12473
  for (let i = 0; i < 6; i++) {
12340
- const candidate = join18(dir, "dist", "mcp");
12341
- if (existsSync9(join18(candidate, "index.js"))) {
12474
+ const candidate = join19(dir, "dist", "mcp");
12475
+ if (existsSync10(join19(candidate, "index.js"))) {
12342
12476
  mcpSourceDir = candidate;
12343
12477
  break;
12344
12478
  }
@@ -12353,8 +12487,8 @@ function deployMcpAssets() {
12353
12487
  const changedBasenames = [];
12354
12488
  const fileHash = (p) => {
12355
12489
  try {
12356
- if (!existsSync9(p)) return null;
12357
- return createHash11("sha256").update(readFileSync15(p)).digest("hex");
12490
+ if (!existsSync10(p)) return null;
12491
+ return createHash11("sha256").update(readFileSync16(p)).digest("hex");
12358
12492
  } catch {
12359
12493
  return null;
12360
12494
  }
@@ -12418,9 +12552,9 @@ function deployMcpAssets() {
12418
12552
  // needs restarting to pick up a token rotation.
12419
12553
  "xero.js"
12420
12554
  ]) {
12421
- const src = join18(mcpSourceDir, file);
12422
- const dst = join18(targetDir, file);
12423
- if (!existsSync9(src)) continue;
12555
+ const src = join19(mcpSourceDir, file);
12556
+ const dst = join19(targetDir, file);
12557
+ if (!existsSync10(src)) continue;
12424
12558
  const before = fileHash(dst);
12425
12559
  try {
12426
12560
  copyFileSync(src, dst);
@@ -12437,16 +12571,16 @@ function deployMcpAssets() {
12437
12571
  log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
12438
12572
  restartRunningChannelMcps(changedBasenames);
12439
12573
  }
12440
- const localMcpPath = join18(targetDir, "index.js");
12574
+ const localMcpPath = join19(targetDir, "index.js");
12441
12575
  try {
12442
- const agentsDir = join18(homedir10(), ".augmented", "agents");
12443
- if (existsSync9(agentsDir)) {
12576
+ const agentsDir = join19(homedir10(), ".augmented", "agents");
12577
+ if (existsSync10(agentsDir)) {
12444
12578
  for (const entry of readdirSync5(agentsDir, { withFileTypes: true })) {
12445
12579
  if (!entry.isDirectory()) continue;
12446
12580
  for (const subdir of ["provision", "project"]) {
12447
- const mcpJsonPath = join18(agentsDir, entry.name, subdir, ".mcp.json");
12581
+ const mcpJsonPath = join19(agentsDir, entry.name, subdir, ".mcp.json");
12448
12582
  try {
12449
- const raw = readFileSync15(mcpJsonPath, "utf-8");
12583
+ const raw = readFileSync16(mcpJsonPath, "utf-8");
12450
12584
  if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
12451
12585
  const mcpConfig = JSON.parse(raw);
12452
12586
  const augServer = mcpConfig.mcpServers?.["augmented"];