@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-
|
|
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
|
|
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
|
|
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
|
-
|
|
341
|
-
|
|
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
|
|
350
|
+
return { restart: false, firstPoll, changed };
|
|
348
351
|
}
|
|
349
352
|
if (framework !== "claude-code") {
|
|
350
|
-
return { restart: false, firstPoll
|
|
353
|
+
return { restart: false, firstPoll, changed };
|
|
351
354
|
}
|
|
352
355
|
if (!sessionHealthy) {
|
|
353
|
-
return { restart: false, firstPoll
|
|
356
|
+
return { restart: false, firstPoll, changed };
|
|
354
357
|
}
|
|
355
358
|
if (channelSetRestartAlreadyScheduled) {
|
|
356
|
-
return { restart: false, firstPoll
|
|
359
|
+
return { restart: false, firstPoll, changed };
|
|
357
360
|
}
|
|
358
|
-
return { restart: true, firstPoll
|
|
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([
|
|
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
|
|
3636
|
-
import { dirname as dirname4, join as
|
|
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
|
|
3719
|
+
return join12(agentRootDir, "managed-skills.json");
|
|
3640
3720
|
}
|
|
3641
3721
|
function readManagedSkillManifest(path) {
|
|
3642
3722
|
try {
|
|
3643
|
-
if (!
|
|
3644
|
-
const parsed = JSON.parse(
|
|
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
|
|
3666
|
-
import { join as
|
|
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 =
|
|
3767
|
+
managerLogPath = join13(homedir5(), ".augmented", "manager.log");
|
|
3688
3768
|
mkdirSync5(dirname5(managerLogPath), { recursive: true });
|
|
3689
|
-
if (
|
|
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 =
|
|
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
|
|
3876
|
-
import { join as
|
|
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 =
|
|
3969
|
+
const claudeDir = join14(homedir6(), ".claude");
|
|
3890
3970
|
for (const filename of [".credentials.json", "credentials.json"]) {
|
|
3891
|
-
const p =
|
|
3892
|
-
if (
|
|
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
|
|
3907
|
-
import { join as
|
|
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
|
-
|
|
4040
|
-
|
|
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 (
|
|
4044
|
-
const content =
|
|
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
|
|
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 =
|
|
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
|
|
5288
|
+
import { join as join17 } from "path";
|
|
5209
5289
|
function claudePidFilePath() {
|
|
5210
|
-
return
|
|
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
|
|
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
|
|
5492
|
+
import { join as join18 } from "path";
|
|
5413
5493
|
import { randomUUID } from "crypto";
|
|
5414
5494
|
function restartFlagsDir() {
|
|
5415
|
-
return
|
|
5495
|
+
return join18(homedir9(), ".augmented", "restart-flags");
|
|
5416
5496
|
}
|
|
5417
5497
|
function flagPath(codeName) {
|
|
5418
|
-
return
|
|
5498
|
+
return join18(restartFlagsDir(), `${codeName}.flag`);
|
|
5419
5499
|
}
|
|
5420
5500
|
function readRestartFlags() {
|
|
5421
5501
|
const dir = restartFlagsDir();
|
|
5422
|
-
if (!
|
|
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 =
|
|
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 (
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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
|
-
|
|
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.
|
|
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 (
|
|
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) =>
|
|
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 (
|
|
7179
|
-
const raw =
|
|
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 (
|
|
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
|
|
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 =
|
|
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 &&
|
|
7600
|
-
const dir =
|
|
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 =
|
|
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
|
|
7787
|
+
return join19(config?.configDir ?? join19(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
|
|
7698
7788
|
}
|
|
7699
7789
|
function channelHashCacheDir() {
|
|
7700
|
-
return config?.configDir ??
|
|
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 ??
|
|
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 ??
|
|
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 =
|
|
7788
|
-
const claudeMdPath =
|
|
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 =
|
|
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 =
|
|
8329
|
+
const paneTail = readFileSync16(paneLogPath(codeName), "utf8").slice(-65536);
|
|
8223
8330
|
const transient = detectTransientApiErrorInLog(paneTail);
|
|
8224
8331
|
if (transient) {
|
|
8225
|
-
const wedgeHome =
|
|
8226
|
-
if (
|
|
8332
|
+
const wedgeHome = join19(homedir10(), ".augmented", codeName);
|
|
8333
|
+
if (existsSync10(wedgeHome)) {
|
|
8227
8334
|
atomicWriteFileSync(
|
|
8228
|
-
|
|
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 =
|
|
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 =
|
|
8565
|
-
if (!
|
|
8671
|
+
const dir = join19(homedir10(), ".augmented", codeName);
|
|
8672
|
+
if (!existsSync10(dir)) return;
|
|
8566
8673
|
atomicWriteFileSync(
|
|
8567
|
-
|
|
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 =
|
|
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:
|
|
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 =
|
|
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 =
|
|
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 =
|
|
8948
|
-
const existing =
|
|
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 =
|
|
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 = !
|
|
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 =
|
|
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 =
|
|
9003
|
-
if (
|
|
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(
|
|
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(
|
|
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 =
|
|
9039
|
-
if (
|
|
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(
|
|
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 &&
|
|
9209
|
+
if (written && existsSync10(agentDir)) {
|
|
9103
9210
|
const driftedFiles = [];
|
|
9104
9211
|
for (const [file, expectedHash] of written) {
|
|
9105
|
-
const localHash = hashFile(
|
|
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(
|
|
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 =
|
|
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(
|
|
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:
|
|
9334
|
-
framework:
|
|
9335
|
-
sessionHealthy:
|
|
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 =
|
|
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 =
|
|
9468
|
-
const projectMcpPath =
|
|
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(
|
|
9604
|
+
mcpConfig = JSON.parse(readFileSync16(provisionMcpPath, "utf-8"));
|
|
9472
9605
|
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
9473
9606
|
} catch {
|
|
9474
9607
|
}
|
|
9475
|
-
const localDirectChatChannel =
|
|
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 (
|
|
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:
|
|
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 =
|
|
9522
|
-
if (
|
|
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 =
|
|
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 =
|
|
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 &&
|
|
9750
|
+
if (mcpPath && existsSync10(mcpPath)) {
|
|
9618
9751
|
try {
|
|
9619
|
-
const cfg = JSON.parse(
|
|
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 =
|
|
9645
|
-
const envIntPath =
|
|
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 =
|
|
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 =
|
|
9661
|
-
const postWriteEnv =
|
|
9662
|
-
const mcpContent =
|
|
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:
|
|
9764
|
-
const mcpConfig = JSON.parse(
|
|
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
|
-
|
|
10044
|
+
join19(homedir11(), ".augmented", agent.code_name, "skills"),
|
|
9912
10045
|
// Claude Code — project tree
|
|
9913
|
-
|
|
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
|
-
|
|
10049
|
+
join19(agentDir, ".claude", "skills")
|
|
9917
10050
|
];
|
|
9918
|
-
const existingDirs = candidateSkillDirs.filter((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 =
|
|
9933
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
9973
|
-
|
|
9974
|
-
|
|
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 =
|
|
9980
|
-
if (
|
|
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 =
|
|
10184
|
-
mcpJsonParsed = JSON.parse(
|
|
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 &&
|
|
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(
|
|
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 =
|
|
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 =
|
|
10592
|
-
const claudeMdPath =
|
|
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 =
|
|
11841
|
-
const memoryDir =
|
|
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 (
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 (
|
|
12061
|
+
if (existsSync10(filePath)) {
|
|
11929
12062
|
let existing = "";
|
|
11930
12063
|
try {
|
|
11931
|
-
existing =
|
|
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 (
|
|
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 (
|
|
12189
|
-
const raw =
|
|
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=${
|
|
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 =
|
|
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 =
|
|
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 =
|
|
12341
|
-
if (
|
|
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 (!
|
|
12357
|
-
return createHash11("sha256").update(
|
|
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 =
|
|
12422
|
-
const dst =
|
|
12423
|
-
if (!
|
|
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 =
|
|
12574
|
+
const localMcpPath = join19(targetDir, "index.js");
|
|
12441
12575
|
try {
|
|
12442
|
-
const agentsDir =
|
|
12443
|
-
if (
|
|
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 =
|
|
12581
|
+
const mcpJsonPath = join19(agentsDir, entry.name, subdir, ".mcp.json");
|
|
12448
12582
|
try {
|
|
12449
|
-
const raw =
|
|
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"];
|