@integrity-labs/agt-cli 0.28.565 → 0.28.567

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.
@@ -53,7 +53,7 @@ import {
53
53
  safeWriteJsonAtomic,
54
54
  setConfigHash,
55
55
  tripClass
56
- } from "../chunk-I6EWKBSV.js";
56
+ } from "../chunk-IALXJ6H3.js";
57
57
  import {
58
58
  getProjectDir as getProjectDir2,
59
59
  getReadyTasks,
@@ -182,17 +182,17 @@ import {
182
182
  toOpencodeModel,
183
183
  transcriptActivityAgeSeconds,
184
184
  writeEgressAllowlist
185
- } from "../chunk-TOGADVFR.js";
185
+ } from "../chunk-FSWAPB5J.js";
186
186
  import {
187
187
  reapOrphanChannelMcps
188
188
  } from "../chunk-XWVM4KPK.js";
189
189
 
190
190
  // src/lib/manager-worker.ts
191
- import { createHash as createHash16 } from "crypto";
192
- import { readFileSync as readFileSync22, writeFileSync as writeFileSync13, mkdirSync as mkdirSync10, existsSync as existsSync12, rmSync as rmSync5, readdirSync as readdirSync8, statSync as statSync7, copyFileSync } from "fs";
191
+ import { createHash as createHash17 } from "crypto";
192
+ import { readFileSync as readFileSync26, writeFileSync as writeFileSync14, mkdirSync as mkdirSync11, existsSync as existsSync14, rmSync as rmSync5, readdirSync as readdirSync9, statSync as statSync8, copyFileSync } from "fs";
193
193
  import { execFileSync as syncExecFile } from "child_process";
194
- import { join as join29, dirname as dirname8, delimiter as pathDelimiter } from "path";
195
- import { homedir as homedir12 } from "os";
194
+ import { join as join33, dirname as dirname9, delimiter as pathDelimiter } from "path";
195
+ import { homedir as homedir15 } from "os";
196
196
  import { fileURLToPath } from "url";
197
197
 
198
198
  // src/lib/claude-code-upgrade-throttle.ts
@@ -3503,14 +3503,804 @@ async function reportSkip2(api2, agentId, conversationId, log2, codeName) {
3503
3503
  }
3504
3504
  }
3505
3505
 
3506
- // src/lib/activity-cache-monitor.ts
3507
- import { existsSync as existsSync3, readFileSync as readFileSync11 } from "fs";
3506
+ // src/lib/tool-call-audit.ts
3507
+ import { homedir as homedir9 } from "os";
3508
+ import { join as join17 } from "path";
3509
+
3510
+ // src/lib/tool-call-path-salt.ts
3511
+ import { randomBytes } from "crypto";
3512
+ import { existsSync as existsSync3, mkdirSync as mkdirSync5, readFileSync as readFileSync11, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
3508
3513
  import { homedir as homedir7 } from "os";
3509
- import { join as join14 } from "path";
3510
- var MIN_CHECK_INTERVAL_MS6 = 6e4;
3511
- var STATS_CACHE_PATH = join14(homedir7(), ".claude", "stats-cache.json");
3514
+ import { dirname as dirname5, join as join14 } from "path";
3515
+ var SALT_BYTES = 32;
3516
+ var SALT_RE = /^[0-9a-f]{64}$/;
3517
+ function pathSaltPath(codeName, homeDir) {
3518
+ const home = homeDir ?? (process.env["HOME"]?.trim() || homedir7());
3519
+ const key = agentRuntimeKey(codeName, homeDir);
3520
+ return join14(home, ".augmented", key, "tool-call-path-salt");
3521
+ }
3522
+ function readToolCallPathSalt(codeName, homeDir) {
3523
+ let file;
3524
+ try {
3525
+ file = pathSaltPath(codeName, homeDir);
3526
+ } catch {
3527
+ return null;
3528
+ }
3529
+ try {
3530
+ if (existsSync3(file)) {
3531
+ const existing = readFileSync11(file, "utf-8").trim();
3532
+ if (SALT_RE.test(existing)) return existing;
3533
+ }
3534
+ } catch {
3535
+ }
3536
+ const salt = randomBytes(SALT_BYTES).toString("hex");
3537
+ const tmp = `${file}.tmp.${process.pid}`;
3538
+ try {
3539
+ mkdirSync5(dirname5(file), { recursive: true, mode: 448 });
3540
+ writeFileSync6(tmp, `${salt}
3541
+ `, { encoding: "utf-8", mode: 384 });
3542
+ renameSync3(tmp, file);
3543
+ } catch {
3544
+ try {
3545
+ unlinkSync(tmp);
3546
+ } catch {
3547
+ }
3548
+ return null;
3549
+ }
3550
+ return salt;
3551
+ }
3552
+
3553
+ // src/lib/tool-call-scan.ts
3554
+ import { statSync as statSync4 } from "fs";
3555
+
3556
+ // src/lib/host-archive-address.ts
3557
+ import { readFileSync as readFileSync12 } from "fs";
3558
+ var DEFAULT_ARCHIVE_ADDRESS_PATH = "/var/lib/augmented/session-archive-address.json";
3559
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
3560
+ var cache = /* @__PURE__ */ new Map();
3561
+ function str(value) {
3562
+ if (typeof value !== "string") return null;
3563
+ const trimmed = value.trim();
3564
+ return trimmed.length > 0 ? trimmed : null;
3565
+ }
3566
+ function readHostArchiveAddress(path) {
3567
+ const file = path ?? process.env["ARCHIVE_ADDRESS_FILE"]?.trim() ?? process.env["AGT_SESSION_ARCHIVE_ADDRESS_FILE"]?.trim() ?? DEFAULT_ARCHIVE_ADDRESS_PATH;
3568
+ const now = Date.now();
3569
+ const hit = cache.get(file);
3570
+ if (hit && now - hit.at < CACHE_TTL_MS) return hit.value;
3571
+ let value = null;
3572
+ try {
3573
+ const raw = readFileSync12(file, "utf-8");
3574
+ const parsed = JSON.parse(raw);
3575
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
3576
+ const obj = parsed;
3577
+ const bucket = str(obj["bucket"]);
3578
+ const keyPrefix = str(obj["key_prefix"]);
3579
+ if (bucket && keyPrefix) {
3580
+ value = {
3581
+ bucket,
3582
+ region: str(obj["region"]),
3583
+ instanceId: str(obj["instance_id"]),
3584
+ keyPrefix
3585
+ };
3586
+ }
3587
+ }
3588
+ } catch {
3589
+ value = null;
3590
+ }
3591
+ cache.set(file, { at: now, value });
3592
+ return value;
3593
+ }
3594
+
3595
+ // src/lib/tool-call-extractor.ts
3596
+ import { closeSync, fstatSync, openSync, readFileSync as readFileSync13, readSync, readdirSync as readdirSync4 } from "fs";
3597
+ import { basename, join as join15, relative } from "path";
3598
+ import { StringDecoder } from "string_decoder";
3599
+
3600
+ // src/lib/tool-call-redaction.ts
3601
+ import { createHmac } from "crypto";
3602
+
3603
+ // ../../packages/core/dist/tool-calls/input-hash.js
3604
+ import { createHash as createHash7 } from "crypto";
3605
+ function hashToolInput(input) {
3606
+ if (input === void 0)
3607
+ return null;
3608
+ try {
3609
+ return createHash7("sha256").update(canonicalJson2(input)).digest("hex");
3610
+ } catch {
3611
+ return null;
3612
+ }
3613
+ }
3614
+ function canonicalJson2(value) {
3615
+ if (value === null || typeof value !== "object")
3616
+ return JSON.stringify(value) ?? "null";
3617
+ if (Array.isArray(value))
3618
+ return `[${value.map(canonicalJson2).join(",")}]`;
3619
+ const entries = Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
3620
+ return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson2(v)}`).join(",")}}`;
3621
+ }
3622
+
3623
+ // src/lib/tool-call-redaction.ts
3624
+ var REDACTION_RULE_VERSION = "r2";
3625
+ var REDACTED_TARGET_SHAPES = {
3626
+ argv0: /^[A-Za-z0-9._+-]{1,64}$/,
3627
+ mcp_tool: /^[A-Za-z0-9._+-]{1,64}$/,
3628
+ path_hash: /^[0-9a-f]{32}$/,
3629
+ url_host: /^[A-Za-z0-9.-]{1,253}$/
3630
+ };
3631
+ var NONE = { target: null, kind: "none" };
3632
+ var SAFE_IDENTIFIER_RE = /^[A-Za-z0-9._+-]{1,64}$/;
3633
+ var ENV_ASSIGNMENT_RE = /^[A-Za-z_][A-Za-z0-9_]*=/;
3634
+ function hashPath(path, salt) {
3635
+ if (!salt) return null;
3636
+ return createHmac("sha256", salt).update(path).digest("hex").slice(0, 32);
3637
+ }
3638
+ function parseArgv0(command) {
3639
+ const firstLine = command.split("\n", 1)[0] ?? "";
3640
+ const tokens = firstLine.trim().split(/\s+/).filter(Boolean);
3641
+ let i = 0;
3642
+ while (i < tokens.length && ENV_ASSIGNMENT_RE.test(tokens[i])) i++;
3643
+ const token = tokens[i];
3644
+ if (!token) return { name: null, isPath: false };
3645
+ if (token.includes("/")) return { name: token, isPath: true };
3646
+ return { name: SAFE_IDENTIFIER_RE.test(token) ? token : null, isPath: false };
3647
+ }
3648
+ function stringField(input, field) {
3649
+ if (!input || typeof input !== "object" || Array.isArray(input)) return null;
3650
+ const v = input[field];
3651
+ return typeof v === "string" && v.length > 0 ? v : null;
3652
+ }
3653
+ function parseMcpTool(toolName) {
3654
+ const m = /^mcp__[^_]+(?:_[^_]+)*?__(.+)$/.exec(toolName);
3655
+ const tool = m?.[1];
3656
+ return tool && SAFE_IDENTIFIER_RE.test(tool) ? tool : null;
3657
+ }
3658
+ function redactToolTarget(toolName, input, ctx) {
3659
+ const out = redactToolTargetInner(toolName, input, ctx);
3660
+ if (out.kind === "none") return out.target === null ? out : NONE;
3661
+ return out.target !== null && REDACTED_TARGET_SHAPES[out.kind].test(out.target) ? out : NONE;
3662
+ }
3663
+ function redactToolTargetInner(toolName, input, ctx) {
3664
+ if (ctx.hashOnly) return NONE;
3665
+ if (toolName.startsWith("mcp__")) {
3666
+ const tool = parseMcpTool(toolName);
3667
+ return tool ? { target: tool, kind: "mcp_tool" } : NONE;
3668
+ }
3669
+ switch (toolName) {
3670
+ case "Bash": {
3671
+ const command = stringField(input, "command");
3672
+ if (!command) return NONE;
3673
+ const { name, isPath } = parseArgv0(command);
3674
+ if (!name) return NONE;
3675
+ if (isPath) {
3676
+ const hashed = hashPath(name, ctx.pathHashSalt);
3677
+ return hashed ? { target: hashed, kind: "path_hash" } : NONE;
3678
+ }
3679
+ const scrubbed = scrubSensitive(name);
3680
+ return SAFE_IDENTIFIER_RE.test(scrubbed) ? { target: scrubbed, kind: "argv0" } : NONE;
3681
+ }
3682
+ // `MultiEdit`, `NotebookEdit` and `NotebookRead` are allowlisted WITHOUT
3683
+ // having been observed — 0 occurrences each across 81 real transcripts,
3684
+ // where only `Edit` appears. Normally that is exactly the speculative
3685
+ // widening this module refuses to do, so the exception is worth stating: the
3686
+ // sole disclosure on this arm is a keyed hash. If one of these names turns
3687
+ // out to belong to some unrelated future tool, the row carries an unreadable
3688
+ // digest of whatever its path field held — no content escapes either way.
3689
+ // Against that, omitting a real file tool is a SILENT audit gap, which is
3690
+ // the costlier error. (CodeRabbit.)
3691
+ case "Read":
3692
+ case "Write":
3693
+ case "Edit":
3694
+ case "MultiEdit": {
3695
+ const path = stringField(input, "file_path");
3696
+ if (!path) return NONE;
3697
+ const hashed = hashPath(path, ctx.pathHashSalt);
3698
+ return hashed ? { target: hashed, kind: "path_hash" } : NONE;
3699
+ }
3700
+ case "NotebookEdit":
3701
+ case "NotebookRead": {
3702
+ const path = stringField(input, "notebook_path");
3703
+ if (!path) return NONE;
3704
+ const hashed = hashPath(path, ctx.pathHashSalt);
3705
+ return hashed ? { target: hashed, kind: "path_hash" } : NONE;
3706
+ }
3707
+ case "WebFetch": {
3708
+ const url = stringField(input, "url");
3709
+ if (!url) return NONE;
3710
+ try {
3711
+ const host = new URL(url).hostname;
3712
+ return host ? { target: host, kind: "url_host" } : NONE;
3713
+ } catch {
3714
+ return NONE;
3715
+ }
3716
+ }
3717
+ default:
3718
+ return NONE;
3719
+ }
3720
+ }
3721
+
3722
+ // src/lib/tool-call-extractor.ts
3723
+ var EXTRACTOR_VERSION = "e1";
3724
+ function enumerateSessionTranscripts(transcriptDir, sessionId, projectsRoot) {
3725
+ const files = [];
3726
+ const mainAbs = join15(transcriptDir, `${sessionId}.jsonl`);
3727
+ files.push({
3728
+ absPath: mainAbs,
3729
+ relPath: relative(projectsRoot, mainAbs),
3730
+ ref: "main",
3731
+ isSubagent: false,
3732
+ subagentId: null
3733
+ });
3734
+ const subDir = join15(transcriptDir, sessionId, "subagents");
3735
+ let entries;
3736
+ try {
3737
+ entries = readdirSync4(subDir);
3738
+ } catch {
3739
+ return files;
3740
+ }
3741
+ for (const name of entries) {
3742
+ if (!name.endsWith(".jsonl")) continue;
3743
+ const abs = join15(subDir, name);
3744
+ const stem = basename(name, ".jsonl");
3745
+ files.push({
3746
+ absPath: abs,
3747
+ relPath: relative(projectsRoot, abs),
3748
+ ref: `subagent:${stem}`,
3749
+ isSubagent: true,
3750
+ subagentId: stem.startsWith("agent-") ? stem.slice("agent-".length) : stem
3751
+ });
3752
+ }
3753
+ return files;
3754
+ }
3755
+ function scanLines(lines, file, opts) {
3756
+ const pending2 = /* @__PURE__ */ new Map();
3757
+ const ordered = [];
3758
+ for (const [lineOffset, rawLine, byteStart] of lines) {
3759
+ const trimmed = rawLine.trim();
3760
+ if (trimmed.length === 0) continue;
3761
+ let record;
3762
+ try {
3763
+ record = JSON.parse(trimmed);
3764
+ } catch {
3765
+ continue;
3766
+ }
3767
+ if (typeof record !== "object" || record === null) continue;
3768
+ const message = record.message;
3769
+ const blocks = message && typeof message === "object" && Array.isArray(message.content) ? message.content : null;
3770
+ if (!blocks) continue;
3771
+ for (const raw of blocks) {
3772
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
3773
+ const block = raw;
3774
+ if (block.type === "tool_use") {
3775
+ const id = typeof block.id === "string" ? block.id : null;
3776
+ const name = typeof block.name === "string" ? block.name : null;
3777
+ if (!id || !name) continue;
3778
+ const { target, kind } = redactToolTarget(name, block.input, opts.redaction);
3779
+ const occurredAt = typeof record.timestamp === "string" ? record.timestamp : null;
3780
+ const built = {
3781
+ tool_use_id: id,
3782
+ tool_name: name,
3783
+ occurred_at: occurredAt,
3784
+ session_id: typeof record.sessionId === "string" ? record.sessionId : null,
3785
+ transcript_rel_path: file.relPath,
3786
+ transcript_ref: file.ref,
3787
+ line_offset: lineOffset,
3788
+ // The FILE is the sole authority, deliberately — not `record.isSidechain`.
3789
+ //
3790
+ // These three fields are one fact stated three ways and must not be
3791
+ // able to contradict each other: `is_subagent` true iff
3792
+ // `transcript_ref` starts with `subagent:` iff `subagent_id` is set.
3793
+ // Letting `record.isSidechain` raise `is_subagent` on its own could
3794
+ // produce is_subagent=true with transcript_ref='main' and a null
3795
+ // subagent_id — a row claiming a delegated worker made the call while
3796
+ // addressing the parent's transcript. `transcript_ref` is an EVIDENCE
3797
+ // ADDRESS: it must name the file the line actually lives in, so the
3798
+ // file has to win and the other two follow it. (CodeRabbit.)
3799
+ //
3800
+ // Nothing is lost today: no main-transcript record in the measured
3801
+ // corpus carried isSidechain on a tool_use, and every sidecar record
3802
+ // did. If Claude Code ever inlines sidechain turns into the main file,
3803
+ // record-level sidechain-ness needs its own field rather than
3804
+ // overloading this one.
3805
+ is_subagent: file.isSubagent,
3806
+ subagent_id: file.isSubagent ? typeof record.agentId === "string" && record.agentId ? record.agentId : file.subagentId : null,
3807
+ is_error: null,
3808
+ // resolved on pairing below
3809
+ input_sha256: hashToolInput(block.input),
3810
+ redacted_target: target,
3811
+ redacted_target_kind: kind,
3812
+ extractor_version: EXTRACTOR_VERSION,
3813
+ redaction_rule_version: REDACTION_RULE_VERSION,
3814
+ archive_bucket: opts.archive?.bucket ?? null,
3815
+ archive_region: opts.archive?.region ?? null,
3816
+ host_instance_id: opts.archive?.instanceId ?? null,
3817
+ archive_key_prefix: opts.archive?.keyPrefix ?? null
3818
+ };
3819
+ ordered.push(built);
3820
+ pending2.set(id, { record: built, byteStart });
3821
+ continue;
3822
+ }
3823
+ if (block.type === "tool_result") {
3824
+ const id = typeof block.tool_use_id === "string" ? block.tool_use_id : null;
3825
+ if (!id) continue;
3826
+ const call = pending2.get(id);
3827
+ if (!call) continue;
3828
+ call.record.is_error = "is_error" in block && block.is_error === null ? null : block.is_error === true;
3829
+ pending2.delete(id);
3830
+ }
3831
+ }
3832
+ }
3833
+ return { records: ordered, pending: pending2 };
3834
+ }
3835
+ var WINDOW_CHUNK_BYTES = 64 * 1024;
3836
+ function extractTranscriptWindow(file, opts, from) {
3837
+ let fd;
3838
+ try {
3839
+ fd = openSync(file.absPath, "r");
3840
+ } catch {
3841
+ return {
3842
+ records: [],
3843
+ endByte: from.byteOffset,
3844
+ endLine: from.lineOffset,
3845
+ unpaired: [],
3846
+ missing: true,
3847
+ rewound: false
3848
+ };
3849
+ }
3850
+ let startByte = from.byteOffset;
3851
+ let startLine = from.lineOffset;
3852
+ let rewound = false;
3853
+ try {
3854
+ const { size } = fstatSync(fd);
3855
+ if (startByte > size) {
3856
+ startByte = 0;
3857
+ startLine = 0;
3858
+ rewound = true;
3859
+ }
3860
+ } catch {
3861
+ }
3862
+ const decoder = new StringDecoder("utf8");
3863
+ const buf = Buffer.allocUnsafe(WINDOW_CHUNK_BYTES);
3864
+ let position = startByte;
3865
+ let runningByte = startByte;
3866
+ let lineOffset = startLine;
3867
+ let carry = "";
3868
+ const pairs = [];
3869
+ try {
3870
+ for (; ; ) {
3871
+ const bytesRead = readSync(fd, buf, 0, WINDOW_CHUNK_BYTES, position);
3872
+ if (bytesRead <= 0) break;
3873
+ position += bytesRead;
3874
+ carry += decoder.write(buf.subarray(0, bytesRead));
3875
+ let nl;
3876
+ while ((nl = carry.indexOf("\n")) !== -1) {
3877
+ const line = carry.slice(0, nl);
3878
+ pairs.push([lineOffset, line, runningByte]);
3879
+ runningByte += Buffer.byteLength(line, "utf8") + 1;
3880
+ lineOffset += 1;
3881
+ carry = carry.slice(nl + 1);
3882
+ }
3883
+ }
3884
+ } catch {
3885
+ } finally {
3886
+ try {
3887
+ closeSync(fd);
3888
+ } catch {
3889
+ }
3890
+ }
3891
+ const { records, pending: pending2 } = scanLines(pairs, file, opts);
3892
+ const unpaired = [...pending2.values()].map((p) => ({
3893
+ toolUseId: p.record.tool_use_id,
3894
+ byteStart: p.byteStart,
3895
+ lineOffset: p.record.line_offset
3896
+ })).sort((a, b) => a.byteStart - b.byteStart);
3897
+ return { records, endByte: runningByte, endLine: lineOffset, unpaired, missing: false, rewound };
3898
+ }
3899
+
3900
+ // src/lib/tool-call-cursor.ts
3901
+ import { existsSync as existsSync4, readFileSync as readFileSync14 } from "fs";
3902
+ import { homedir as homedir8 } from "os";
3903
+ import { join as join16 } from "path";
3904
+ var COVERAGE_DISPOSITIONS = [
3905
+ "ok",
3906
+ "not_entitled",
3907
+ "ingest_failed",
3908
+ "batch_rejected",
3909
+ "agent_unbound",
3910
+ "transcript_missing"
3911
+ ];
3912
+ function mayAdvance(outcome) {
3913
+ switch (outcome.kind) {
3914
+ case "ingested":
3915
+ return true;
3916
+ // Definitive: nothing will EVER be collected for this org. Holding would
3917
+ // re-offer the same lines forever against an answer that cannot change.
3918
+ case "not_entitled":
3919
+ return true;
3920
+ // A producer bug. Retrying is futile and holding wedges every later call
3921
+ // behind it, so step over — loudly, and counted.
3922
+ case "batch_rejected":
3923
+ return true;
3924
+ case "agent_unbound":
3925
+ return false;
3926
+ case "ingest_failed":
3927
+ return false;
3928
+ }
3929
+ }
3930
+ function dispositionFor(outcome) {
3931
+ switch (outcome.kind) {
3932
+ case "ingested":
3933
+ return "ok";
3934
+ case "not_entitled":
3935
+ return "not_entitled";
3936
+ case "batch_rejected":
3937
+ return "batch_rejected";
3938
+ case "agent_unbound":
3939
+ return "agent_unbound";
3940
+ case "ingest_failed":
3941
+ return "ingest_failed";
3942
+ }
3943
+ }
3944
+ var UNPAIRED_GRACE_MS = 30 * 60 * 1e3;
3945
+ var KEY_SEP = "\0";
3946
+ function cursorKey(sessionId, transcriptRef) {
3947
+ return `${sessionId ?? ""}${KEY_SEP}${transcriptRef}`;
3948
+ }
3949
+ function parseCursorKey(key) {
3950
+ const i = key.indexOf(KEY_SEP);
3951
+ if (i < 0) return { sessionId: null, transcriptRef: key };
3952
+ const sessionId = key.slice(0, i);
3953
+ return { sessionId: sessionId.length > 0 ? sessionId : null, transcriptRef: key.slice(i + 1) };
3954
+ }
3955
+ function cursorStatePath(codeName, homeDir) {
3956
+ const home = homeDir ?? (process.env["HOME"]?.trim() || homedir8());
3957
+ const key = agentRuntimeKey(codeName, homeDir);
3958
+ return join16(home, ".augmented", key, "tool-call-cursors.json");
3959
+ }
3960
+ function loadCursors(path) {
3961
+ const out = /* @__PURE__ */ new Map();
3962
+ if (!existsSync4(path)) return out;
3963
+ try {
3964
+ const parsed = JSON.parse(readFileSync14(path, "utf-8"));
3965
+ if (!parsed || parsed.version !== 1 || typeof parsed.files !== "object") return out;
3966
+ for (const [k, v] of Object.entries(parsed.files)) {
3967
+ if (!v || typeof v !== "object") continue;
3968
+ const offsetsOk = ["byteOffset", "lineOffset", "startedFromLine", "callsExtracted"].every((f) => {
3969
+ const n = v[f];
3970
+ return n === void 0 || typeof n === "number" && Number.isSafeInteger(n) && n >= 0;
3971
+ });
3972
+ if (typeof v.byteOffset !== "number" || typeof v.lineOffset !== "number" || !offsetsOk) continue;
3973
+ out.set(k, {
3974
+ byteOffset: v.byteOffset,
3975
+ lineOffset: v.lineOffset,
3976
+ startedFromLine: typeof v.startedFromLine === "number" ? v.startedFromLine : 0,
3977
+ callsExtracted: typeof v.callsExtracted === "number" ? v.callsExtracted : 0,
3978
+ unpairedSince: typeof v.unpairedSince === "string" ? v.unpairedSince : null,
3979
+ lastDisposition: COVERAGE_DISPOSITIONS.includes(v.lastDisposition) ? v.lastDisposition : "ok",
3980
+ lastScanAt: typeof v.lastScanAt === "string" ? v.lastScanAt : (/* @__PURE__ */ new Date(0)).toISOString(),
3981
+ firstScanAt: typeof v.firstScanAt === "string" ? v.firstScanAt : (/* @__PURE__ */ new Date(0)).toISOString(),
3982
+ transcriptRelPath: typeof v.transcriptRelPath === "string" ? v.transcriptRelPath : null
3983
+ });
3984
+ }
3985
+ } catch {
3986
+ }
3987
+ return out;
3988
+ }
3989
+ function saveCursors(path, cursors) {
3990
+ const files = {};
3991
+ for (const [k, v] of cursors) files[k] = v;
3992
+ atomicWriteFileSync(path, JSON.stringify({ version: 1, files }, null, 2));
3993
+ }
3994
+ function nextCursor(args) {
3995
+ const { previous, endByte, endLine, earliestUnpaired, outcome, nowMs } = args;
3996
+ const nowIso = new Date(nowMs).toISOString();
3997
+ const disposition = dispositionFor(outcome);
3998
+ if (!mayAdvance(outcome)) {
3999
+ return { ...previous, lastDisposition: disposition, lastScanAt: nowIso };
4000
+ }
4001
+ const callsExtracted = previous.callsExtracted + args.callsExtracted;
4002
+ if (!earliestUnpaired) {
4003
+ return {
4004
+ ...previous,
4005
+ byteOffset: endByte,
4006
+ lineOffset: endLine,
4007
+ callsExtracted,
4008
+ unpairedSince: null,
4009
+ lastDisposition: disposition,
4010
+ lastScanAt: nowIso
4011
+ };
4012
+ }
4013
+ const since = previous.unpairedSince ?? nowIso;
4014
+ const waited = nowMs - Date.parse(since);
4015
+ if (!Number.isFinite(waited) || waited >= UNPAIRED_GRACE_MS) {
4016
+ return {
4017
+ ...previous,
4018
+ byteOffset: endByte,
4019
+ lineOffset: endLine,
4020
+ callsExtracted,
4021
+ unpairedSince: null,
4022
+ lastDisposition: disposition,
4023
+ lastScanAt: nowIso
4024
+ };
4025
+ }
4026
+ return {
4027
+ ...previous,
4028
+ byteOffset: Math.max(previous.byteOffset, Math.min(endByte, earliestUnpaired.byteStart)),
4029
+ lineOffset: Math.max(previous.lineOffset, Math.min(endLine, earliestUnpaired.lineOffset)),
4030
+ callsExtracted,
4031
+ unpairedSince: since,
4032
+ lastDisposition: disposition,
4033
+ lastScanAt: nowIso
4034
+ };
4035
+ }
4036
+ function initialCursor(args) {
4037
+ const iso = new Date(args.nowMs).toISOString();
4038
+ return {
4039
+ byteOffset: args.startByte,
4040
+ lineOffset: args.startLine,
4041
+ startedFromLine: args.startLine,
4042
+ callsExtracted: 0,
4043
+ unpairedSince: null,
4044
+ lastDisposition: "ok",
4045
+ lastScanAt: iso,
4046
+ firstScanAt: iso,
4047
+ transcriptRelPath: args.transcriptRelPath
4048
+ };
4049
+ }
4050
+ function coverageRowFor(key, cursor, versions) {
4051
+ const { sessionId, transcriptRef } = parseCursorKey(key);
4052
+ return {
4053
+ session_id: sessionId,
4054
+ transcript_ref: transcriptRef,
4055
+ transcript_rel_path: cursor.transcriptRelPath,
4056
+ through_line: cursor.lineOffset,
4057
+ through_byte: cursor.byteOffset,
4058
+ started_from_line: cursor.startedFromLine,
4059
+ calls_extracted: cursor.callsExtracted,
4060
+ last_disposition: cursor.lastDisposition,
4061
+ extractor_version: versions.extractor,
4062
+ redaction_rule_version: versions.redaction
4063
+ };
4064
+ }
4065
+
4066
+ // src/lib/tool-call-scan.ts
4067
+ var MAX_CALLS_PER_POST = 500;
4068
+ var MAX_COVERAGE_ROWS_PER_POST = 200;
4069
+ function classifyIngestResult(result, error) {
4070
+ if (error) {
4071
+ if (error instanceof ApiError) {
4072
+ if (error.status === 404) return { kind: "agent_unbound" };
4073
+ if (error.status === 400 && error.body?.["code"] === "batch_too_large") {
4074
+ return { kind: "ingest_failed", reason: `oversize batch (HTTP 400): ${error.message}` };
4075
+ }
4076
+ if (error.status >= 400 && error.status < 500) {
4077
+ return { kind: "batch_rejected", reason: `HTTP ${error.status}: ${error.message}` };
4078
+ }
4079
+ return { kind: "ingest_failed", reason: `HTTP ${error.status}: ${error.message}` };
4080
+ }
4081
+ return { kind: "ingest_failed", reason: String(error?.message ?? error) };
4082
+ }
4083
+ const body = result ?? {};
4084
+ if (body["entitled"] === false) return { kind: "not_entitled" };
4085
+ if (body["ok"] === false) {
4086
+ return { kind: "ingest_failed", reason: String(body["message"] ?? "ok:false") };
4087
+ }
4088
+ return { kind: "ingested" };
4089
+ }
4090
+ function chunk(items, size) {
4091
+ const out = [];
4092
+ for (let i = 0; i < items.length; i += size) out.push(items.slice(i, i + size));
4093
+ return out;
4094
+ }
4095
+ function endOfFile(absPath) {
4096
+ try {
4097
+ return { byteOffset: statSync4(absPath).size, lineOffset: 0 };
4098
+ } catch {
4099
+ return null;
4100
+ }
4101
+ }
4102
+ async function scanAgentToolCalls(args) {
4103
+ const now = args.now ?? Date.now;
4104
+ const log2 = args.log;
4105
+ const summary = {
4106
+ filesScanned: 0,
4107
+ callsExtracted: 0,
4108
+ callsIngested: 0,
4109
+ filesHeld: 0,
4110
+ coverageReported: 0,
4111
+ notEntitled: false
4112
+ };
4113
+ const path = args.cursorPath ?? cursorStatePath(args.codeName, args.homeDir);
4114
+ const cursors = loadCursors(path);
4115
+ const extractOpts = {
4116
+ transcriptDir: args.transcriptDir,
4117
+ archive: readHostArchiveAddress(),
4118
+ redaction: { pathHashSalt: args.pathHashSalt, hashOnly: args.hashOnly }
4119
+ };
4120
+ const seen = /* @__PURE__ */ new Set();
4121
+ const files = [];
4122
+ for (const sessionId of args.sessionIds) {
4123
+ for (const f of enumerateSessionTranscripts(args.transcriptDir, sessionId, args.projectsRoot)) {
4124
+ const key = cursorKey(sessionId, f.ref);
4125
+ if (seen.has(key)) continue;
4126
+ seen.add(key);
4127
+ files.push({ key, file: f });
4128
+ }
4129
+ }
4130
+ const touched = [];
4131
+ for (const { key, file } of files) {
4132
+ let cursor = cursors.get(key);
4133
+ if (!cursor) {
4134
+ const end = endOfFile(file.absPath);
4135
+ if (!end) continue;
4136
+ cursor = initialCursor({
4137
+ startByte: args.backfill ? 0 : end.byteOffset,
4138
+ startLine: 0,
4139
+ transcriptRelPath: file.relPath,
4140
+ nowMs: now()
4141
+ });
4142
+ cursors.set(key, cursor);
4143
+ touched.push(key);
4144
+ if (!args.backfill && end.byteOffset > 0) {
4145
+ log2(
4146
+ `[tool-call-scan] first-seen ${file.relPath} ref=${file.ref} \u2014 starting at byte ${end.byteOffset} (scan-from-now; set backfill to include the existing ${end.byteOffset}B)`
4147
+ );
4148
+ }
4149
+ if (!args.backfill) continue;
4150
+ }
4151
+ const window = extractTranscriptWindow(file, extractOpts, {
4152
+ byteOffset: cursor.byteOffset,
4153
+ lineOffset: cursor.lineOffset
4154
+ });
4155
+ summary.filesScanned += 1;
4156
+ if (window.missing) {
4157
+ cursors.set(key, { ...cursor, lastDisposition: "transcript_missing", lastScanAt: new Date(now()).toISOString() });
4158
+ touched.push(key);
4159
+ continue;
4160
+ }
4161
+ if (window.rewound) {
4162
+ log2(`[tool-call-scan] ${file.relPath} ref=${file.ref} shrank below the cursor \u2014 re-reading from 0`);
4163
+ }
4164
+ summary.callsExtracted += window.records.length;
4165
+ const unpairedIds = new Set(window.unpaired.map((u) => u.toolUseId));
4166
+ const sendable = window.records.filter((r) => !unpairedIds.has(r.tool_use_id));
4167
+ let outcome = { kind: "ingested" };
4168
+ let attempted = false;
4169
+ let ingested = 0;
4170
+ for (const batch of chunk(sendable, MAX_CALLS_PER_POST)) {
4171
+ attempted = true;
4172
+ const res = await postCalls(args.api, args.agentId, batch);
4173
+ outcome = res.outcome;
4174
+ ingested += res.ingested;
4175
+ if (outcome.kind === "not_entitled") summary.notEntitled = true;
4176
+ if (outcome.kind !== "ingested" && outcome.kind !== "not_entitled") break;
4177
+ }
4178
+ summary.callsIngested += ingested;
4179
+ const computed = nextCursor({
4180
+ previous: cursor,
4181
+ endByte: window.endByte,
4182
+ endLine: window.endLine,
4183
+ earliestUnpaired: window.unpaired[0] ?? null,
4184
+ outcome,
4185
+ callsExtracted: sendable.length,
4186
+ nowMs: now()
4187
+ });
4188
+ const advanced = attempted ? computed : { ...computed, lastDisposition: cursor.lastDisposition };
4189
+ if (advanced.byteOffset === cursor.byteOffset && outcome.kind === "ingest_failed") {
4190
+ summary.filesHeld += 1;
4191
+ log2(
4192
+ `[tool-call-scan] HOLDING cursor for ${file.relPath} ref=${file.ref} at byte ${cursor.byteOffset}: ${outcome.reason}`
4193
+ );
4194
+ }
4195
+ cursors.set(key, advanced);
4196
+ touched.push(key);
4197
+ if (outcome.kind === "agent_unbound") {
4198
+ log2(`[tool-call-scan] host is not bound to agent ${args.agentId} \u2014 stopping this tick`);
4199
+ break;
4200
+ }
4201
+ }
4202
+ saveCursors(path, cursors);
4203
+ summary.coverageReported = await reportCoverage(args, cursors, touched, log2);
4204
+ return summary;
4205
+ }
4206
+ async function postCalls(api2, agentId, calls) {
4207
+ try {
4208
+ const res = await api2.post(
4209
+ "/host/tool-calls",
4210
+ { agent_id: agentId, calls }
4211
+ );
4212
+ const outcome = classifyIngestResult(res);
4213
+ return { outcome, ingested: typeof res?.ingested === "number" ? res.ingested : 0 };
4214
+ } catch (err) {
4215
+ return { outcome: classifyIngestResult(void 0, err), ingested: 0 };
4216
+ }
4217
+ }
4218
+ async function reportCoverage(args, cursors, touched, log2) {
4219
+ const rows = [];
4220
+ for (const key of new Set(touched)) {
4221
+ const c = cursors.get(key);
4222
+ if (c) rows.push(coverageRowFor(key, c, { extractor: EXTRACTOR_VERSION, redaction: REDACTION_RULE_VERSION }));
4223
+ }
4224
+ if (rows.length === 0) return 0;
4225
+ let reported = 0;
4226
+ for (const batch of chunk(rows, MAX_COVERAGE_ROWS_PER_POST)) {
4227
+ try {
4228
+ await args.api.post("/host/tool-calls/coverage", { agent_id: args.agentId, coverage: batch });
4229
+ reported += batch.length;
4230
+ } catch (err) {
4231
+ log2(`[tool-call-scan] coverage report failed (${batch.length} rows): ${String(err)}`);
4232
+ break;
4233
+ }
4234
+ }
4235
+ return reported;
4236
+ }
4237
+
4238
+ // src/lib/tool-call-audit.ts
4239
+ var MIN_CHECK_INTERVAL_MS6 = 10 * 6e4;
4240
+ var ENTITLEMENT_RECHECK_MS = 30 * 6e4;
4241
+ var state5 = /* @__PURE__ */ new Map();
4242
+ function entitlementLatch(entry, nowMs) {
4243
+ if (!entry?.notEntitledAt) return false;
4244
+ return !hasElapsed(entry.notEntitledAt, nowMs, ENTITLEMENT_RECHECK_MS);
4245
+ }
4246
+ function hasElapsed(sinceMs, nowMs, windowMs) {
4247
+ const delta = nowMs - sinceMs;
4248
+ if (!Number.isFinite(delta) || delta < 0) return true;
4249
+ return delta >= windowMs;
4250
+ }
4251
+ async function maybeScanToolCalls(args) {
4252
+ const { api: api2, codeName, agentId, log: log2 } = args;
4253
+ const nowFn = args.now ?? Date.now;
4254
+ const nowMs = nowFn();
4255
+ try {
4256
+ const existing = state5.get(codeName);
4257
+ if (existing && !hasElapsed(existing.lastCheckedAt, nowMs, MIN_CHECK_INTERVAL_MS6)) return;
4258
+ if (entitlementLatch(existing, nowMs)) {
4259
+ state5.set(codeName, { lastCheckedAt: nowMs, notEntitledAt: existing?.notEntitledAt ?? null });
4260
+ return;
4261
+ }
4262
+ state5.set(codeName, { lastCheckedAt: nowMs, notEntitledAt: existing?.notEntitledAt ?? null });
4263
+ const salt = readToolCallPathSalt(codeName, args.homeDir);
4264
+ if (!salt) {
4265
+ log2(`[tool-call-audit] ${codeName}: no path-hash salt available \u2014 file targets withheld`);
4266
+ }
4267
+ const home = args.homeDir ?? (process.env["HOME"]?.trim() || homedir9());
4268
+ const projectsRoot = args.projectsRoot ?? join17(home, ".claude", "projects");
4269
+ const transcriptDir = args.transcriptDir ?? sessionTranscriptDir(getProjectDir(codeName));
4270
+ const current = peekCurrentSession(codeName);
4271
+ const sessionIds = current ? [current.sessionId] : [];
4272
+ const summary = await scanAgentToolCalls({
4273
+ api: api2,
4274
+ agentId,
4275
+ codeName,
4276
+ transcriptDir,
4277
+ projectsRoot,
4278
+ sessionIds,
4279
+ pathHashSalt: salt ?? "",
4280
+ ...args.hashOnly === void 0 ? {} : { hashOnly: args.hashOnly },
4281
+ log: log2,
4282
+ now: nowFn,
4283
+ ...args.homeDir === void 0 ? {} : { homeDir: args.homeDir },
4284
+ ...args.cursorPath === void 0 ? {} : { cursorPath: args.cursorPath }
4285
+ });
4286
+ if (summary.notEntitled) {
4287
+ state5.set(codeName, { lastCheckedAt: nowMs, notEntitledAt: nowMs });
4288
+ } else if (summary.callsIngested > 0) {
4289
+ state5.set(codeName, { lastCheckedAt: nowMs, notEntitledAt: null });
4290
+ }
4291
+ } catch (err) {
4292
+ log2(`[tool-call-audit] ${codeName}: scan failed: ${err.message}`);
4293
+ }
4294
+ }
4295
+
4296
+ // src/lib/activity-cache-monitor.ts
4297
+ import { existsSync as existsSync5, readFileSync as readFileSync15 } from "fs";
4298
+ import { homedir as homedir10 } from "os";
4299
+ import { join as join18 } from "path";
4300
+ var MIN_CHECK_INTERVAL_MS7 = 6e4;
4301
+ var STATS_CACHE_PATH = join18(homedir10(), ".claude", "stats-cache.json");
3512
4302
  var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
3513
- var state5 = { lastObservedDate: null, lastCheckedAt: 0 };
4303
+ var state6 = { lastObservedDate: null, lastCheckedAt: 0 };
3514
4304
  function selectNewDailyRows(raw, lastObservedDate) {
3515
4305
  let parsed;
3516
4306
  try {
@@ -3549,24 +4339,24 @@ async function maybeReportActivityCache(args) {
3549
4339
  const { api: api2, log: log2 } = args;
3550
4340
  const now = args.now ?? /* @__PURE__ */ new Date();
3551
4341
  const nowMs = now.getTime();
3552
- if (nowMs - state5.lastCheckedAt < MIN_CHECK_INTERVAL_MS6) return;
3553
- state5.lastCheckedAt = nowMs;
3554
- if (!existsSync3(STATS_CACHE_PATH)) {
4342
+ if (nowMs - state6.lastCheckedAt < MIN_CHECK_INTERVAL_MS7) return;
4343
+ state6.lastCheckedAt = nowMs;
4344
+ if (!existsSync5(STATS_CACHE_PATH)) {
3555
4345
  return;
3556
4346
  }
3557
4347
  let raw;
3558
4348
  try {
3559
- raw = readFileSync11(STATS_CACHE_PATH, "utf-8");
4349
+ raw = readFileSync15(STATS_CACHE_PATH, "utf-8");
3560
4350
  } catch (err) {
3561
4351
  log2(`[activity-cache] readFileSync failed: ${err.message}`);
3562
4352
  return;
3563
4353
  }
3564
- const rows = selectNewDailyRows(raw, state5.lastObservedDate);
4354
+ const rows = selectNewDailyRows(raw, state6.lastObservedDate);
3565
4355
  if (rows.length === 0) return;
3566
4356
  for (const row of rows) {
3567
4357
  try {
3568
4358
  await api2.post("/host/activity-observations", row);
3569
- state5.lastObservedDate = row.date;
4359
+ state6.lastObservedDate = row.date;
3570
4360
  } catch (err) {
3571
4361
  log2(
3572
4362
  `[activity-cache] POST /host/activity-observations failed for date=${row.date}: ${err.message}`
@@ -3741,7 +4531,7 @@ function bundleFingerprint(files) {
3741
4531
  }
3742
4532
 
3743
4533
  // src/lib/channel-config-hash.ts
3744
- import { createHash as createHash7 } from "crypto";
4534
+ import { createHash as createHash8 } from "crypto";
3745
4535
  var DERIVED_PRINCIPAL_ID_LIST_KEYS = [
3746
4536
  "allowed_users",
3747
4537
  "diagnostic_chat_ids",
@@ -3762,7 +4552,7 @@ function normalizeChannelConfigForHash(config2) {
3762
4552
  }
3763
4553
  var CHANNEL_WRITE_VERSION = 9;
3764
4554
  function computeChannelConfigHash(input) {
3765
- return createHash7("sha256").update(
4555
+ return createHash8("sha256").update(
3766
4556
  canonicalJson({
3767
4557
  writeVersion: CHANNEL_WRITE_VERSION,
3768
4558
  cliVersion: input.cliVersion,
@@ -3781,18 +4571,18 @@ function computeChannelConfigHash(input) {
3781
4571
  }
3782
4572
 
3783
4573
  // src/lib/channel-hash-cache.ts
3784
- import { existsSync as existsSync4, readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "fs";
3785
- import { join as join15 } from "path";
4574
+ import { existsSync as existsSync6, readFileSync as readFileSync16, writeFileSync as writeFileSync7 } from "fs";
4575
+ import { join as join19 } from "path";
3786
4576
  var CACHE_FILENAME = "channel-hash-cache.json";
3787
4577
  function getChannelHashCacheFile(configDir) {
3788
- return join15(configDir, CACHE_FILENAME);
4578
+ return join19(configDir, CACHE_FILENAME);
3789
4579
  }
3790
4580
  function loadChannelHashCache(target, configDir) {
3791
4581
  const path = getChannelHashCacheFile(configDir);
3792
- if (!existsSync4(path)) return;
4582
+ if (!existsSync6(path)) return;
3793
4583
  let parsed;
3794
4584
  try {
3795
- parsed = JSON.parse(readFileSync12(path, "utf-8"));
4585
+ parsed = JSON.parse(readFileSync16(path, "utf-8"));
3796
4586
  } catch {
3797
4587
  return;
3798
4588
  }
@@ -3806,14 +4596,14 @@ function saveChannelHashCache(source, configDir) {
3806
4596
  const obj = {};
3807
4597
  for (const [key, value] of source) obj[key] = value;
3808
4598
  try {
3809
- writeFileSync6(path, JSON.stringify(obj, null, 2));
4599
+ writeFileSync7(path, JSON.stringify(obj, null, 2));
3810
4600
  } catch {
3811
4601
  }
3812
4602
  }
3813
4603
 
3814
4604
  // src/lib/sender-policy-baseline.ts
3815
- import { existsSync as existsSync5, readFileSync as readFileSync13 } from "fs";
3816
- import { join as join16 } from "path";
4605
+ import { existsSync as existsSync7, readFileSync as readFileSync17 } from "fs";
4606
+ import { join as join20 } from "path";
3817
4607
  var BASELINE_FILENAME = "sender-policy-baseline.json";
3818
4608
  var SENDER_POLICY_BASELINE_VERSION = 1;
3819
4609
  var BASELINE_CONCERNS = ["senderPolicy", "slackBehaviour", "msteamsBehaviour"];
@@ -3825,14 +4615,14 @@ function createDeliveryBaselineMaps() {
3825
4615
  };
3826
4616
  }
3827
4617
  function getSenderPolicyBaselineFile(configDir) {
3828
- return join16(configDir, BASELINE_FILENAME);
4618
+ return join20(configDir, BASELINE_FILENAME);
3829
4619
  }
3830
4620
  function loadSenderPolicyBaseline(target, configDir, log2) {
3831
4621
  const path = getSenderPolicyBaselineFile(configDir);
3832
- if (!existsSync5(path)) return;
4622
+ if (!existsSync7(path)) return;
3833
4623
  let parsed;
3834
4624
  try {
3835
- parsed = JSON.parse(readFileSync13(path, "utf-8"));
4625
+ parsed = JSON.parse(readFileSync17(path, "utf-8"));
3836
4626
  } catch (err) {
3837
4627
  log2?.(
3838
4628
  `[sender-policy] discarding corrupt ${BASELINE_FILENAME} (${err.message}) - restrictive-policy agents will take one fail-closed restart`
@@ -4355,37 +5145,37 @@ function planGlobalSkillSync(globalSkills, prevIds, hashOf, knownHash, options)
4355
5145
  }
4356
5146
 
4357
5147
  // src/lib/manager/integration-skill-cache.ts
4358
- import { join as join17 } from "path";
5148
+ import { join as join21 } from "path";
4359
5149
  function integrationSkillHashKey(agentId, skillId) {
4360
5150
  return `plugin-skill:${agentId}:${skillId}`;
4361
5151
  }
4362
- function shouldWriteIntegrationSkill(cache2, agentId, skillId, contentHash) {
4363
- return cache2.get(integrationSkillHashKey(agentId, skillId)) !== contentHash;
5152
+ function shouldWriteIntegrationSkill(cache3, agentId, skillId, contentHash) {
5153
+ return cache3.get(integrationSkillHashKey(agentId, skillId)) !== contentHash;
4364
5154
  }
4365
- function rememberIntegrationSkill(cache2, agentId, skillId, contentHash) {
4366
- cache2.set(integrationSkillHashKey(agentId, skillId), contentHash);
5155
+ function rememberIntegrationSkill(cache3, agentId, skillId, contentHash) {
5156
+ cache3.set(integrationSkillHashKey(agentId, skillId), contentHash);
4367
5157
  }
4368
- function forgetIntegrationSkill(cache2, agentId, skillId) {
4369
- cache2.delete(integrationSkillHashKey(agentId, skillId));
5158
+ function forgetIntegrationSkill(cache3, agentId, skillId) {
5159
+ cache3.delete(integrationSkillHashKey(agentId, skillId));
4370
5160
  }
4371
5161
  function removeIntegrationSkillFolder(opts) {
4372
5162
  forgetIntegrationSkill(opts.cache, opts.agentId, opts.entry);
4373
5163
  for (const dir of opts.dirs) {
4374
- opts.removeDir(join17(dir, opts.entry));
5164
+ opts.removeDir(join21(dir, opts.entry));
4375
5165
  }
4376
5166
  }
4377
5167
 
4378
5168
  // src/lib/manager/managed-skill-manifest.ts
4379
- import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "fs";
4380
- import { dirname as dirname5, join as join18 } from "path";
5169
+ import { existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync18, writeFileSync as writeFileSync8 } from "fs";
5170
+ import { dirname as dirname6, join as join22 } from "path";
4381
5171
  var MANIFEST_VERSION = 1;
4382
5172
  function managedSkillManifestPath(agentRootDir) {
4383
- return join18(agentRootDir, "managed-skills.json");
5173
+ return join22(agentRootDir, "managed-skills.json");
4384
5174
  }
4385
5175
  function readManagedSkillManifest(path) {
4386
5176
  try {
4387
- if (!existsSync6(path)) return /* @__PURE__ */ new Set();
4388
- const parsed = JSON.parse(readFileSync14(path, "utf-8"));
5177
+ if (!existsSync8(path)) return /* @__PURE__ */ new Set();
5178
+ const parsed = JSON.parse(readFileSync18(path, "utf-8"));
4389
5179
  const ids = Array.isArray(parsed?.globalSkillIds) ? parsed.globalSkillIds : [];
4390
5180
  return new Set(ids.filter((id) => typeof id === "string" && id.length > 0));
4391
5181
  } catch {
@@ -4394,12 +5184,12 @@ function readManagedSkillManifest(path) {
4394
5184
  }
4395
5185
  function writeManagedSkillManifest(path, ids) {
4396
5186
  try {
4397
- mkdirSync5(dirname5(path), { recursive: true });
5187
+ mkdirSync6(dirname6(path), { recursive: true });
4398
5188
  const body = {
4399
5189
  version: MANIFEST_VERSION,
4400
5190
  globalSkillIds: [...ids].sort()
4401
5191
  };
4402
- writeFileSync7(path, JSON.stringify(body, null, 2));
5192
+ writeFileSync8(path, JSON.stringify(body, null, 2));
4403
5193
  } catch {
4404
5194
  }
4405
5195
  }
@@ -4497,9 +5287,9 @@ function resolveModelChain(refreshData) {
4497
5287
  }
4498
5288
 
4499
5289
  // src/lib/manager/claude-auth.ts
4500
- import { existsSync as existsSync7, rmSync as rmSync3 } from "fs";
4501
- import { join as join19 } from "path";
4502
- import { homedir as homedir8 } from "os";
5290
+ import { existsSync as existsSync9, rmSync as rmSync3 } from "fs";
5291
+ import { join as join23 } from "path";
5292
+ import { homedir as homedir11 } from "os";
4503
5293
  async function applyClaudeAuthToEnv(childEnv, label) {
4504
5294
  const apiKey = getApiKey();
4505
5295
  if (!apiKey) {
@@ -4511,10 +5301,10 @@ async function applyClaudeAuthToEnv(childEnv, label) {
4511
5301
  throw new Error("claude_auth_mode=api_key but /host/exchange returned no decrypted key");
4512
5302
  }
4513
5303
  childEnv.ANTHROPIC_API_KEY = exchange.anthropicApiKey;
4514
- const claudeDir = join19(homedir8(), ".claude");
5304
+ const claudeDir = join23(homedir11(), ".claude");
4515
5305
  for (const filename of [".credentials.json", "credentials.json"]) {
4516
- const p = join19(claudeDir, filename);
4517
- if (existsSync7(p)) {
5306
+ const p = join23(claudeDir, filename);
5307
+ if (existsSync9(p)) {
4518
5308
  try {
4519
5309
  rmSync3(p, { force: true });
4520
5310
  log(`[${label}] Removed ${p} (api_key mode \u2014 preventing OAuth fallback)`);
@@ -4595,8 +5385,8 @@ function heartbeatRuntimeAuthFields(probeVerdict) {
4595
5385
  }
4596
5386
 
4597
5387
  // src/lib/manager/kanban/parsers.ts
4598
- import { existsSync as existsSync8, readFileSync as readFileSync15 } from "fs";
4599
- import { join as join20 } from "path";
5388
+ import { existsSync as existsSync10, readFileSync as readFileSync19 } from "fs";
5389
+ import { join as join24 } from "path";
4600
5390
  var STANDUP_TEMPLATES = /* @__PURE__ */ new Set(["daily-standup", "end-of-day-summary"]);
4601
5391
  var TASK_UPDATE_TEMPLATES = /* @__PURE__ */ new Set(["hourly-status", "task-update"]);
4602
5392
  var PLAN_TEMPLATES = /* @__PURE__ */ new Set(["morning-plan"]);
@@ -4632,21 +5422,21 @@ function nudgeIntervalForCount(nudgeCount, fullCadenceMs, maxCadenceMs) {
4632
5422
  const exponent = Math.max(0, Math.min(nudgeCount - 1, 8));
4633
5423
  return Math.min(fullCadenceMs * 3 ** exponent, Math.max(maxCadenceMs, fullCadenceMs));
4634
5424
  }
4635
- function shouldNudgeUnchangedBoard(signature, state7, now, fullCadenceMs, maxCadenceMs = fullCadenceMs) {
4636
- if (!state7) return true;
4637
- if (state7.signature !== signature) return true;
4638
- return now - state7.nudgedAt >= nudgeIntervalForCount(state7.nudgeCount ?? 1, fullCadenceMs, maxCadenceMs);
5425
+ function shouldNudgeUnchangedBoard(signature, state8, now, fullCadenceMs, maxCadenceMs = fullCadenceMs) {
5426
+ if (!state8) return true;
5427
+ if (state8.signature !== signature) return true;
5428
+ return now - state8.nudgedAt >= nudgeIntervalForCount(state8.nudgeCount ?? 1, fullCadenceMs, maxCadenceMs);
4639
5429
  }
4640
5430
  function failureRetryIntervalForCount(failureCount, baseMs, maxMs) {
4641
5431
  const exponent = Math.max(0, Math.min(failureCount - 1, 8));
4642
5432
  return Math.min(baseMs * 3 ** exponent, Math.max(maxMs, baseMs));
4643
5433
  }
4644
5434
  var KANBAN_NOTICE_BREAKER_THRESHOLD = 5;
4645
- function shouldAttemptNoticeEnqueue(state7, now, baseMs, maxMs, breakerThreshold = KANBAN_NOTICE_BREAKER_THRESHOLD) {
4646
- const failures = state7?.failureCount ?? 0;
5435
+ function shouldAttemptNoticeEnqueue(state8, now, baseMs, maxMs, breakerThreshold = KANBAN_NOTICE_BREAKER_THRESHOLD) {
5436
+ const failures = state8?.failureCount ?? 0;
4647
5437
  if (failures <= 0) return { attempt: true, breakerOpen: false };
4648
5438
  const breakerOpen = failures >= breakerThreshold;
4649
- const failedAt = state7?.failedAt;
5439
+ const failedAt = state8?.failedAt;
4650
5440
  const due = failedAt === void 0 || failedAt > now || now - failedAt >= failureRetryIntervalForCount(failures, baseMs, maxMs);
4651
5441
  return { attempt: due, breakerOpen };
4652
5442
  }
@@ -4748,12 +5538,12 @@ function getBuiltInSkillContent(skillId) {
4748
5538
  if (builtInSkillCache.has(skillId)) return builtInSkillCache.get(skillId);
4749
5539
  try {
4750
5540
  const candidates = [
4751
- join20(process.cwd(), "skills", skillId, "SKILL.md"),
4752
- join20(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "..", "..", "skills", skillId, "SKILL.md")
5541
+ join24(process.cwd(), "skills", skillId, "SKILL.md"),
5542
+ join24(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "..", "..", "skills", skillId, "SKILL.md")
4753
5543
  ];
4754
5544
  for (const candidate of candidates) {
4755
- if (existsSync8(candidate)) {
4756
- const content = readFileSync15(candidate, "utf-8");
5545
+ if (existsSync10(candidate)) {
5546
+ const content = readFileSync19(candidate, "utf-8");
4757
5547
  const files = [{ relativePath: "SKILL.md", content }];
4758
5548
  builtInSkillCache.set(skillId, files);
4759
5549
  return files;
@@ -4894,19 +5684,19 @@ function formatBoardForPrompt(items, template) {
4894
5684
  }
4895
5685
 
4896
5686
  // src/lib/manager/kanban/nudge-state-cache.ts
4897
- import { existsSync as existsSync9, readFileSync as readFileSync16, writeFileSync as writeFileSync8 } from "fs";
4898
- import { join as join21 } from "path";
5687
+ import { existsSync as existsSync11, readFileSync as readFileSync20, writeFileSync as writeFileSync9 } from "fs";
5688
+ import { join as join25 } from "path";
4899
5689
  var CACHE_FILENAME2 = "kanban-nudge-state.json";
4900
5690
  var KANBAN_NUDGE_STATE_VERSION = 1;
4901
5691
  function getKanbanNudgeStateFile(configDir) {
4902
- return join21(configDir, CACHE_FILENAME2);
5692
+ return join25(configDir, CACHE_FILENAME2);
4903
5693
  }
4904
5694
  function loadKanbanNudgeState(target, configDir) {
4905
5695
  const path = getKanbanNudgeStateFile(configDir);
4906
- if (!existsSync9(path)) return;
5696
+ if (!existsSync11(path)) return;
4907
5697
  let parsed;
4908
5698
  try {
4909
- parsed = JSON.parse(readFileSync16(path, "utf-8"));
5699
+ parsed = JSON.parse(readFileSync20(path, "utf-8"));
4910
5700
  } catch {
4911
5701
  return;
4912
5702
  }
@@ -4936,15 +5726,15 @@ function loadKanbanNudgeState(target, configDir) {
4936
5726
  function saveKanbanNudgeState(source, configDir) {
4937
5727
  const path = getKanbanNudgeStateFile(configDir);
4938
5728
  const agents = {};
4939
- for (const [codeName, state7] of source) agents[codeName] = state7;
5729
+ for (const [codeName, state8] of source) agents[codeName] = state8;
4940
5730
  try {
4941
- writeFileSync8(path, JSON.stringify({ version: KANBAN_NUDGE_STATE_VERSION, agents }, null, 2));
5731
+ writeFileSync9(path, JSON.stringify({ version: KANBAN_NUDGE_STATE_VERSION, agents }, null, 2));
4942
5732
  } catch {
4943
5733
  }
4944
5734
  }
4945
5735
 
4946
5736
  // src/lib/manager/kanban/notify.ts
4947
- import { createHash as createHash8 } from "crypto";
5737
+ import { createHash as createHash9 } from "crypto";
4948
5738
  async function enqueueKanbanNotice(opts) {
4949
5739
  try {
4950
5740
  const res = await api.post(
@@ -4959,7 +5749,7 @@ async function enqueueKanbanNotice(opts) {
4959
5749
  return res.ok === true;
4960
5750
  } catch (err) {
4961
5751
  const errText = err instanceof Error ? err.message : String(err);
4962
- const errId = createHash8("sha256").update(errText).digest("hex").slice(0, 12);
5752
+ const errId = createHash9("sha256").update(errText).digest("hex").slice(0, 12);
4963
5753
  log(`[kanban] notice enqueue failed for agent_id=${opts.agentId} error_id=${errId}`);
4964
5754
  return false;
4965
5755
  }
@@ -4974,7 +5764,7 @@ async function cancelKanbanNotice(agentId) {
4974
5764
  return typeof res.cancelled === "number" ? res.cancelled : 0;
4975
5765
  } catch (err) {
4976
5766
  const errText = err instanceof Error ? err.message : String(err);
4977
- const errId = createHash8("sha256").update(errText).digest("hex").slice(0, 12);
5767
+ const errId = createHash9("sha256").update(errText).digest("hex").slice(0, 12);
4978
5768
  log(`[kanban] notice cancel failed for agent_id=${agentId} error_id=${errId}`);
4979
5769
  return null;
4980
5770
  }
@@ -5380,7 +6170,7 @@ function deriveScheduledTaskNotify(task) {
5380
6170
  }
5381
6171
 
5382
6172
  // src/lib/manager/scheduler/runs.ts
5383
- import { createHash as createHash9 } from "crypto";
6173
+ import { createHash as createHash10 } from "crypto";
5384
6174
  async function startRun(opts) {
5385
6175
  try {
5386
6176
  const res = await api.post(
@@ -5395,7 +6185,7 @@ async function startRun(opts) {
5395
6185
  };
5396
6186
  } catch (err) {
5397
6187
  const errText = err instanceof Error ? err.message : String(err);
5398
- const errId = createHash9("sha256").update(errText).digest("hex").slice(0, 12);
6188
+ const errId = createHash10("sha256").update(errText).digest("hex").slice(0, 12);
5399
6189
  log(`[runs] start failed for agent_id=${opts.agent_id} source_type=${opts.source_type} error_id=${errId}`);
5400
6190
  return { run_id: null, kanban_item_id: null };
5401
6191
  }
@@ -5434,7 +6224,7 @@ async function finishRun(runId, outcome, options = {}) {
5434
6224
  return;
5435
6225
  } catch (err) {
5436
6226
  const errText = err instanceof Error ? err.message : String(err);
5437
- const errId = createHash9("sha256").update(errText).digest("hex").slice(0, 12);
6227
+ const errId = createHash10("sha256").update(errText).digest("hex").slice(0, 12);
5438
6228
  const status = err instanceof ApiError ? err.status : 0;
5439
6229
  if (isRetryableFinishError(err) && attempt < maxRetries) {
5440
6230
  log(
@@ -5463,7 +6253,7 @@ async function fetchPriorScheduledRuns(agentId, taskId) {
5463
6253
  return rows.filter((r) => typeof r.output_text === "string" && r.output_text.length > 0).map((r) => ({ startedAt: r.started_at, output: r.output_text }));
5464
6254
  } catch (err) {
5465
6255
  const errText = err instanceof Error ? err.message : String(err);
5466
- const errId = createHash9("sha256").update(errText).digest("hex").slice(0, 12);
6256
+ const errId = createHash10("sha256").update(errText).digest("hex").slice(0, 12);
5467
6257
  log(`[runs] prior-runs lookup failed for task_id=${taskId} error_id=${errId}`);
5468
6258
  return [];
5469
6259
  }
@@ -5512,13 +6302,13 @@ function closeScheduledRunsForCode(codeName, outcome, reason) {
5512
6302
  }
5513
6303
 
5514
6304
  // src/lib/manager/scheduler/kanban-route.ts
5515
- import { createHash as createHash11 } from "crypto";
5516
- import { writeFileSync as writeFileSync9, renameSync as renameSync3, mkdirSync as mkdirSync6, readFileSync as readFileSync17, unlinkSync } from "fs";
5517
- import { homedir as homedir9 } from "os";
5518
- import { join as join22, dirname as dirname6 } from "path";
6305
+ import { createHash as createHash12 } from "crypto";
6306
+ import { writeFileSync as writeFileSync10, renameSync as renameSync4, mkdirSync as mkdirSync7, readFileSync as readFileSync21, unlinkSync as unlinkSync2 } from "fs";
6307
+ import { homedir as homedir12 } from "os";
6308
+ import { join as join26, dirname as dirname7 } from "path";
5519
6309
 
5520
6310
  // src/lib/manager/scheduler/notify.ts
5521
- import { createHash as createHash10 } from "crypto";
6311
+ import { createHash as createHash11 } from "crypto";
5522
6312
  async function enqueueScheduledTaskNotice(opts) {
5523
6313
  try {
5524
6314
  const res = await api.post(
@@ -5535,7 +6325,7 @@ async function enqueueScheduledTaskNotice(opts) {
5535
6325
  return res.ok === true;
5536
6326
  } catch (err) {
5537
6327
  const errText = err instanceof Error ? err.message : String(err);
5538
- const errId = createHash10("sha256").update(errText).digest("hex").slice(0, 12);
6328
+ const errId = createHash11("sha256").update(errText).digest("hex").slice(0, 12);
5539
6329
  log(
5540
6330
  `[scheduled-kanban] notice enqueue failed for agent_id=${opts.agentId} task_id=${opts.taskId} error_id=${errId}`
5541
6331
  );
@@ -5765,8 +6555,8 @@ async function runScheduledCardDelivery(codeName, agentId, cardId, completedBy,
5765
6555
  markScheduledCardDeliveryComplete(cardId);
5766
6556
  return "terminal";
5767
6557
  }
5768
- const state7 = claudeSchedulerStates.get(codeName) ?? loadSchedulerState(codeName);
5769
- const task = state7.tasks[card.source_ref];
6558
+ const state8 = claudeSchedulerStates.get(codeName) ?? loadSchedulerState(codeName);
6559
+ const task = state8.tasks[card.source_ref];
5770
6560
  if (!task) {
5771
6561
  log(`[scheduled-kanban] delivery: no scheduler task for source_ref=${card.source_ref} on '${codeName}' \u2014 skipping`);
5772
6562
  markScheduledCardDeliveryComplete(cardId);
@@ -5874,21 +6664,21 @@ function resolveScheduledSlackTarget(task) {
5874
6664
  }
5875
6665
  function stampScheduledTurnMarker(codeName, taskId, target) {
5876
6666
  try {
5877
- const file = join22(homedir9(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
6667
+ const file = join26(homedir12(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
5878
6668
  const marker = { ts: Date.now(), task_id: taskId, ...target ? { target } : {} };
5879
6669
  const tmp = `${file}.tmp`;
5880
- writeFileSync9(tmp, JSON.stringify(marker), "utf8");
5881
- renameSync3(tmp, file);
6670
+ writeFileSync10(tmp, JSON.stringify(marker), "utf8");
6671
+ renameSync4(tmp, file);
5882
6672
  } catch (err) {
5883
6673
  log(`[scheduled-kanban] scheduled-turn marker write failed for '${codeName}': ${err.message}`);
5884
6674
  }
5885
6675
  }
5886
6676
  function clearScheduledTurnMarkerForTask(codeName, taskId) {
5887
- const file = join22(homedir9(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
6677
+ const file = join26(homedir12(), ".augmented", codeName, SCHEDULED_TURN_MARKER_FILENAME);
5888
6678
  try {
5889
- const raw = JSON.parse(readFileSync17(file, "utf8"));
6679
+ const raw = JSON.parse(readFileSync21(file, "utf8"));
5890
6680
  if (typeof raw?.task_id !== "string" || raw.task_id !== taskId) return;
5891
- unlinkSync(file);
6681
+ unlinkSync2(file);
5892
6682
  log(`[scheduled-kanban] scheduled-turn marker cleared for '${codeName}' (task ${taskId} complete)`);
5893
6683
  } catch {
5894
6684
  }
@@ -5946,9 +6736,9 @@ async function routeScheduledTaskViaKanban(codeName, agentId, task, prompt, dura
5946
6736
  return false;
5947
6737
  }
5948
6738
  try {
5949
- const doorbell = directChatDoorbellPath(agentId, homedir9());
5950
- mkdirSync6(dirname6(doorbell), { recursive: true });
5951
- writeFileSync9(doorbell, String(Date.now()));
6739
+ const doorbell = directChatDoorbellPath(agentId, homedir12());
6740
+ mkdirSync7(dirname7(doorbell), { recursive: true });
6741
+ writeFileSync10(doorbell, String(Date.now()));
5952
6742
  } catch (err) {
5953
6743
  log(`[scheduled-kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
5954
6744
  }
@@ -6014,24 +6804,24 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
6014
6804
  const assertion = parseDeliverAssertion(rawOutput);
6015
6805
  if (!assertion.deliver) {
6016
6806
  const trimmed = (rawOutput ?? "").trim();
6017
- const outputHash = trimmed.length === 0 ? "empty" : createHash11("sha256").update(trimmed).digest("hex").slice(0, 12);
6807
+ const outputHash = trimmed.length === 0 ? "empty" : createHash12("sha256").update(trimmed).digest("hex").slice(0, 12);
6018
6808
  log(`[claude-scheduler] Suppressed by delivery_policy=conditional for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 ${assertion.vacuous ? "deliver marker had a vacuous reason" : "no deliver marker"}; output_len=${trimmed.length} output_hash=${outputHash}`);
6019
6809
  if (delivery?.mode === "announce" && delivery.to) {
6020
6810
  await reportDeliveryStatus(agentId, delivery.taskId, { status: "skipped", error_code: "SUPPRESSED_BY_POLICY" });
6021
6811
  }
6022
6812
  return { ok: true };
6023
6813
  }
6024
- const reasonHash = createHash11("sha256").update(assertion.reason ?? "").digest("hex").slice(0, 12);
6814
+ const reasonHash = createHash12("sha256").update(assertion.reason ?? "").digest("hex").slice(0, 12);
6025
6815
  log(`[claude-scheduler] Delivering conditional run for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 agent asserted a concrete trigger (reason_len=${(assertion.reason ?? "").length} reason_hash=${reasonHash})`);
6026
6816
  rawOutput = assertion.deliverable;
6027
6817
  }
6028
6818
  const classification = classifyOutput(rawOutput);
6029
6819
  if (classification.action === "suppress") {
6030
6820
  const trimmed = (rawOutput ?? "").trim();
6031
- const outputHash = trimmed.length === 0 ? "empty" : createHash11("sha256").update(trimmed).digest("hex").slice(0, 12);
6821
+ const outputHash = trimmed.length === 0 ? "empty" : createHash12("sha256").update(trimmed).digest("hex").slice(0, 12);
6032
6822
  log(`[claude-scheduler] Suppressing delivery for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 output_len=${trimmed.length} output_hash=${outputHash}`);
6033
6823
  if (classification.suppressedNotes) {
6034
- const notesHash = createHash11("sha256").update(classification.suppressedNotes).digest("hex").slice(0, 12);
6824
+ const notesHash = createHash12("sha256").update(classification.suppressedNotes).digest("hex").slice(0, 12);
6035
6825
  log(`[claude-scheduler] Suppressed notes for '${codeName}' (task=${delivery?.taskId ?? "n/a"}) \u2014 notes_len=${classification.suppressedNotes.length} notes_hash=${notesHash}`);
6036
6826
  }
6037
6827
  if (delivery?.mode === "announce" && delivery.to) {
@@ -6097,13 +6887,13 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
6097
6887
  }
6098
6888
 
6099
6889
  // src/lib/manager/scheduler/execution.ts
6100
- import { createHash as createHash12 } from "crypto";
6101
- import { homedir as homedir10 } from "os";
6102
- import { join as join24 } from "path";
6890
+ import { createHash as createHash13 } from "crypto";
6891
+ import { homedir as homedir13 } from "os";
6892
+ import { join as join28 } from "path";
6103
6893
 
6104
6894
  // src/lib/agent-serving-probe.ts
6105
- import { readFileSync as readFileSync18, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
6106
- import { join as join23 } from "path";
6895
+ import { readFileSync as readFileSync22, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
6896
+ import { join as join27 } from "path";
6107
6897
  var RATE_LIMIT_WINDOW_MS = 6 * 60 * 60 * 1e3;
6108
6898
  function probeRateLimit(args) {
6109
6899
  const now = args.now ?? /* @__PURE__ */ new Date();
@@ -6112,23 +6902,23 @@ function probeRateLimit(args) {
6112
6902
  const dir = args.transcriptDir ?? sessionTranscriptDir(args.projectDir);
6113
6903
  let entries;
6114
6904
  try {
6115
- entries = readdirSync4(dir);
6905
+ entries = readdirSync5(dir);
6116
6906
  } catch {
6117
6907
  return UNKNOWN_RATE_LIMIT;
6118
6908
  }
6119
6909
  let newest = UNKNOWN_RATE_LIMIT;
6120
6910
  for (const name of entries) {
6121
6911
  if (!name.endsWith(".jsonl")) continue;
6122
- const path = join23(dir, name);
6912
+ const path = join27(dir, name);
6123
6913
  try {
6124
- const st = statSync4(path);
6914
+ const st = statSync5(path);
6125
6915
  if (!st.isFile() || st.mtimeMs < startMs) continue;
6126
6916
  } catch {
6127
6917
  continue;
6128
6918
  }
6129
6919
  let content;
6130
6920
  try {
6131
- content = readFileSync18(path, "utf-8");
6921
+ content = readFileSync22(path, "utf-8");
6132
6922
  } catch {
6133
6923
  continue;
6134
6924
  }
@@ -6190,7 +6980,7 @@ function shouldLogUsageCapDeferral(site, codeName, limitedUntil) {
6190
6980
 
6191
6981
  // src/lib/manager/scheduler/execution.ts
6192
6982
  function claudePidFilePath() {
6193
- return join24(homedir10(), ".augmented", "manager-claude-pids.json");
6983
+ return join28(homedir13(), ".augmented", "manager-claude-pids.json");
6194
6984
  }
6195
6985
  var inFlightClaudePids = /* @__PURE__ */ new Map();
6196
6986
  function registerClaudeSpawn(record) {
@@ -6210,24 +7000,24 @@ function unregisterClaudeSpawn(pid) {
6210
7000
  }
6211
7001
  async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData, durableScheduledNudge = false) {
6212
7002
  const codeName = agent.code_name;
6213
- const stableTasksHash = createHash12("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
6214
- const boardHash = boardItems.length > 0 ? createHash12("sha256").update(JSON.stringify(boardItems.map((b) => ({ id: b.id, title: b.title, status: b.status, priority: b.priority, deliverable: b.deliverable })))).digest("hex").slice(0, 16) : "empty";
7003
+ const stableTasksHash = createHash13("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
7004
+ const boardHash = boardItems.length > 0 ? createHash13("sha256").update(JSON.stringify(boardItems.map((b) => ({ id: b.id, title: b.title, status: b.status, priority: b.priority, deliverable: b.deliverable })))).digest("hex").slice(0, 16) : "empty";
6215
7005
  const resolvedModels = resolveModelChain(refreshData);
6216
- const modelsHash = createHash12("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
7006
+ const modelsHash = createHash13("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
6217
7007
  const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
6218
7008
  const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
6219
7009
  if (combinedHash !== prevHash) {
6220
7010
  const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
6221
- const state8 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
6222
- claudeSchedulerStates.set(codeName, state8);
7011
+ const state9 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
7012
+ claudeSchedulerStates.set(codeName, state9);
6223
7013
  agentState.knownTasksHashes.set(agent.agent_id, combinedHash);
6224
7014
  log(`[claude-scheduler] Tasks synced for '${codeName}' (${taskInputs.length} task(s))`);
6225
7015
  }
6226
7016
  if (!claudeSchedulerStates.has(codeName)) {
6227
7017
  claudeSchedulerStates.set(codeName, loadSchedulerState(codeName));
6228
7018
  }
6229
- const state7 = claudeSchedulerStates.get(codeName);
6230
- const ready = getReadyTasks(state7, inFlightClaudeTasks);
7019
+ const state8 = claudeSchedulerStates.get(codeName);
7020
+ const ready = getReadyTasks(state8, inFlightClaudeTasks);
6231
7021
  if (ready.length === 0) return;
6232
7022
  const limitedUntil = readUsageCapUntil({ codeName, projectDir: getProjectDir(codeName) });
6233
7023
  if (limitedUntil) {
@@ -6260,19 +7050,19 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
6260
7050
  }
6261
7051
 
6262
7052
  // src/lib/occupancy-gate.ts
6263
- import { closeSync, openSync, readdirSync as readdirSync5, readSync, statSync as statSync5 } from "fs";
6264
- import { join as join25 } from "path";
7053
+ import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync6, readSync as readSync2, statSync as statSync6 } from "fs";
7054
+ import { join as join29 } from "path";
6265
7055
  var TAIL_BYTES = 256 * 1024;
6266
7056
  var MAX_RECORD_ALIGN_BYTES = 8 * 1024 * 1024;
6267
7057
  var GATE_MAX_BUCKET_AGE_MS = 30 * 6e4;
6268
7058
  var TRANSCRIPT_MTIME_WINDOW_MS4 = GATE_MAX_BUCKET_AGE_MS + DEFAULT_NEIGHBOURHOOD_MS + 6e4;
6269
- var cache = /* @__PURE__ */ new Map();
7059
+ var cache2 = /* @__PURE__ */ new Map();
6270
7060
  function readAlignedTail(path, tailBytes, maxAlignBytes) {
6271
7061
  let fd = null;
6272
7062
  try {
6273
- const size = statSync5(path).size;
7063
+ const size = statSync6(path).size;
6274
7064
  if (size <= 0) return { content: "", complete: true, truncated: false };
6275
- fd = openSync(path, "r");
7065
+ fd = openSync2(path, "r");
6276
7066
  let readStart = Math.max(0, size - tailBytes);
6277
7067
  if (readStart > 0) {
6278
7068
  const scanFloor = Math.max(0, readStart - maxAlignBytes);
@@ -6283,7 +7073,7 @@ function readAlignedTail(path, tailBytes, maxAlignBytes) {
6283
7073
  const from = Math.max(scanFloor, pos - CHUNK);
6284
7074
  const len2 = pos - from;
6285
7075
  const b = Buffer.allocUnsafe(len2);
6286
- if (readSync(fd, b, 0, len2, from) !== len2) return null;
7076
+ if (readSync2(fd, b, 0, len2, from) !== len2) return null;
6287
7077
  const idx = b.lastIndexOf(10);
6288
7078
  if (idx !== -1) {
6289
7079
  boundary = from + idx + 1;
@@ -6301,14 +7091,14 @@ function readAlignedTail(path, tailBytes, maxAlignBytes) {
6301
7091
  }
6302
7092
  const len = size - readStart;
6303
7093
  const buf = Buffer.allocUnsafe(len);
6304
- if (readSync(fd, buf, 0, len, readStart) !== len) return null;
7094
+ if (readSync2(fd, buf, 0, len, readStart) !== len) return null;
6305
7095
  return { content: buf.toString("utf-8", 0, len), complete: true, truncated: readStart > 0 };
6306
7096
  } catch {
6307
7097
  return null;
6308
7098
  } finally {
6309
7099
  if (fd != null) {
6310
7100
  try {
6311
- closeSync(fd);
7101
+ closeSync2(fd);
6312
7102
  } catch {
6313
7103
  }
6314
7104
  }
@@ -6340,26 +7130,26 @@ function candidateTranscriptPaths(dir) {
6340
7130
  const paths = [];
6341
7131
  let top;
6342
7132
  try {
6343
- top = readdirSync5(dir);
7133
+ top = readdirSync6(dir);
6344
7134
  } catch {
6345
7135
  return { paths, complete: false };
6346
7136
  }
6347
7137
  let complete = true;
6348
7138
  for (const name of top) {
6349
7139
  if (name.endsWith(".jsonl")) {
6350
- paths.push(join25(dir, name));
7140
+ paths.push(join29(dir, name));
6351
7141
  continue;
6352
7142
  }
6353
- const subDir = join25(dir, name, "subagents");
7143
+ const subDir = join29(dir, name, "subagents");
6354
7144
  let subs;
6355
7145
  try {
6356
- subs = readdirSync5(subDir);
7146
+ subs = readdirSync6(subDir);
6357
7147
  } catch (err) {
6358
7148
  if (!isAbsentDirError(err)) complete = false;
6359
7149
  continue;
6360
7150
  }
6361
7151
  for (const sub of subs) {
6362
- if (sub.endsWith(".jsonl")) paths.push(join25(subDir, sub));
7152
+ if (sub.endsWith(".jsonl")) paths.push(join29(subDir, sub));
6363
7153
  }
6364
7154
  }
6365
7155
  return { paths, complete };
@@ -6369,7 +7159,7 @@ function collectQualifyingTurns(codeName, nowMs, opts = {}) {
6369
7159
  const tailBytes = opts.tailBytes ?? TAIL_BYTES;
6370
7160
  const maxAlignBytes = opts.maxAlignBytes ?? MAX_RECORD_ALIGN_BYTES;
6371
7161
  const sinceMs = nowMs - TRANSCRIPT_MTIME_WINDOW_MS4;
6372
- const agentCache = cache.get(codeName) ?? /* @__PURE__ */ new Map();
7162
+ const agentCache = cache2.get(codeName) ?? /* @__PURE__ */ new Map();
6373
7163
  const nextCache = /* @__PURE__ */ new Map();
6374
7164
  const all = /* @__PURE__ */ new Set();
6375
7165
  let transcriptsRead = 0;
@@ -6382,7 +7172,7 @@ function collectQualifyingTurns(codeName, nowMs, opts = {}) {
6382
7172
  for (const path of paths) {
6383
7173
  let st;
6384
7174
  try {
6385
- st = statSync5(path);
7175
+ st = statSync6(path);
6386
7176
  } catch (err) {
6387
7177
  if (!isAbsentDirError(err)) complete = false;
6388
7178
  continue;
@@ -6418,7 +7208,7 @@ function collectQualifyingTurns(codeName, nowMs, opts = {}) {
6418
7208
  }
6419
7209
  for (const t of turns) all.add(t);
6420
7210
  }
6421
- cache.set(codeName, nextCache);
7211
+ cache2.set(codeName, nextCache);
6422
7212
  return { turns: [...all].sort((a, b) => a - b), transcriptsRead, complete, coveredFromMs };
6423
7213
  }
6424
7214
  function qualifyBuckets(buckets, qualifying, mode, nowMs, neighbourhoodMs = DEFAULT_NEIGHBOURHOOD_MS) {
@@ -6454,14 +7244,14 @@ function qualifyBuckets(buckets, qualifying, mode, nowMs, neighbourhoodMs = DEFA
6454
7244
  }
6455
7245
 
6456
7246
  // src/lib/pane-occupancy-sampler.ts
6457
- import { statSync as statSync6 } from "fs";
7247
+ import { statSync as statSync7 } from "fs";
6458
7248
  var SAMPLE_INTERVAL_MS = 1e4;
6459
7249
  var IDLE_GAP_MS = 12e4;
6460
7250
  var POST_IDLE_CREDIT_MS = 6e4;
6461
7251
  var lastMtimeMs = /* @__PURE__ */ new Map();
6462
7252
  function paneMtimeMs(codeName) {
6463
7253
  try {
6464
- return statSync6(paneLogPath(codeName)).mtimeMs;
7254
+ return statSync7(paneLogPath(codeName)).mtimeMs;
6465
7255
  } catch {
6466
7256
  return null;
6467
7257
  }
@@ -6507,7 +7297,7 @@ function stopPaneOccupancySampler() {
6507
7297
  }
6508
7298
 
6509
7299
  // src/lib/opencode-slack-ingest.ts
6510
- import { createHash as createHash13 } from "crypto";
7300
+ import { createHash as createHash14 } from "crypto";
6511
7301
 
6512
7302
  // ../../packages/core/dist/channels/slack-rich-text.js
6513
7303
  var MAX_DEPTH = 12;
@@ -7458,7 +8248,7 @@ function startSlackIngest(config2) {
7458
8248
  // src/lib/opencode-slack-ingest.ts
7459
8249
  var ingests = /* @__PURE__ */ new Map();
7460
8250
  function fingerprint(params) {
7461
- return createHash13("sha256").update(
8251
+ return createHash14("sha256").update(
7462
8252
  JSON.stringify({
7463
8253
  appToken: params.appToken,
7464
8254
  botToken: params.botToken,
@@ -7539,7 +8329,7 @@ function stopAllOpencodeSlackIngests(log2) {
7539
8329
  }
7540
8330
 
7541
8331
  // src/lib/manager/opencode-scheduler.ts
7542
- import { createHash as createHash14 } from "crypto";
8332
+ import { createHash as createHash15 } from "crypto";
7543
8333
  var MAX_OPENCODE_SCHED_CONCURRENCY = 2;
7544
8334
  var opencodeSchedulerStates = /* @__PURE__ */ new Map();
7545
8335
  var inFlightOpencodeTasks = /* @__PURE__ */ new Set();
@@ -7553,19 +8343,19 @@ function shouldDeliver(task, reply) {
7553
8343
  }
7554
8344
  async function syncAndCheckOpencodeScheduler(agent, tasks, refreshData) {
7555
8345
  const codeName = agent.code_name;
7556
- const tasksHash = createHash14("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
8346
+ const tasksHash = createHash15("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
7557
8347
  if (knownOpencodeTaskHashes.get(agent.agent_id) !== tasksHash) {
7558
8348
  const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
7559
- const state8 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
7560
- opencodeSchedulerStates.set(codeName, state8);
8349
+ const state9 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
8350
+ opencodeSchedulerStates.set(codeName, state9);
7561
8351
  knownOpencodeTaskHashes.set(agent.agent_id, tasksHash);
7562
8352
  log(`[opencode-scheduler] tasks synced for '${codeName}' (${taskInputs.length} task(s))`);
7563
8353
  }
7564
8354
  if (!opencodeSchedulerStates.has(codeName)) {
7565
8355
  opencodeSchedulerStates.set(codeName, loadSchedulerState(codeName));
7566
8356
  }
7567
- const state7 = opencodeSchedulerStates.get(codeName);
7568
- const ready = getReadyTasks(state7, inFlightOpencodeTasks);
8357
+ const state8 = opencodeSchedulerStates.get(codeName);
8358
+ const ready = getReadyTasks(state8, inFlightOpencodeTasks);
7569
8359
  if (ready.length === 0) return;
7570
8360
  if (!isOpencodeSessionHealthy(codeName)) {
7571
8361
  log(`[opencode-scheduler] '${codeName}' has ${ready.length} due task(s) but no healthy serve yet - deferring`);
@@ -7631,10 +8421,10 @@ async function fireOpencodeScheduledTask(agent, task) {
7631
8421
  }
7632
8422
 
7633
8423
  // src/lib/opencode-telegram-ingest.ts
7634
- import { createHash as createHash15 } from "crypto";
7635
- import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync19, renameSync as renameSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync10 } from "fs";
8424
+ import { createHash as createHash16 } from "crypto";
8425
+ import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync23, renameSync as renameSync5, unlinkSync as unlinkSync3, writeFileSync as writeFileSync11 } from "fs";
7636
8426
  import { randomUUID } from "crypto";
7637
- import { join as join26 } from "path";
8427
+ import { join as join30 } from "path";
7638
8428
 
7639
8429
  // src/lib/telegram-ingest.ts
7640
8430
  import https2 from "https";
@@ -8167,7 +8957,7 @@ function anySignal(signals) {
8167
8957
  // src/lib/opencode-telegram-ingest.ts
8168
8958
  var ingests2 = /* @__PURE__ */ new Map();
8169
8959
  function fingerprint2(params) {
8170
- return createHash15("sha256").update(
8960
+ return createHash16("sha256").update(
8171
8961
  JSON.stringify({
8172
8962
  botToken: params.botToken,
8173
8963
  allowedChats: [...params.allowedChats].sort(),
@@ -8182,7 +8972,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
8182
8972
  let filePath;
8183
8973
  try {
8184
8974
  dir = getFramework("opencode").getAgentDir(codeName);
8185
- filePath = join26(dir, "telegram-getupdates-offset-opencode.json");
8975
+ filePath = join30(dir, "telegram-getupdates-offset-opencode.json");
8186
8976
  } catch {
8187
8977
  dir = null;
8188
8978
  filePath = null;
@@ -8191,7 +8981,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
8191
8981
  load() {
8192
8982
  if (!filePath) return 0;
8193
8983
  try {
8194
- const parsed = JSON.parse(readFileSync19(filePath, "utf-8"));
8984
+ const parsed = JSON.parse(readFileSync23(filePath, "utf-8"));
8195
8985
  if (currentBotId != null && typeof parsed?.bot_id === "number" && parsed.bot_id !== currentBotId) {
8196
8986
  log2(`[telegram-ingest:${codeName}] offset cursor belongs to a different bot; ignoring (bot swap)`);
8197
8987
  return 0;
@@ -8209,8 +8999,8 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
8209
8999
  if (!filePath || !dir) return;
8210
9000
  const tmpPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
8211
9001
  try {
8212
- mkdirSync7(dir, { recursive: true, mode: 448 });
8213
- writeFileSync10(
9002
+ mkdirSync8(dir, { recursive: true, mode: 448 });
9003
+ writeFileSync11(
8214
9004
  tmpPath,
8215
9005
  JSON.stringify({
8216
9006
  offset,
@@ -8220,11 +9010,11 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
8220
9010
  }),
8221
9011
  { mode: 384 }
8222
9012
  );
8223
- renameSync4(tmpPath, filePath);
9013
+ renameSync5(tmpPath, filePath);
8224
9014
  } catch (err) {
8225
9015
  log2(`[telegram-ingest:${codeName}] offset persist failed: ${err instanceof Error ? err.message : String(err)}`);
8226
9016
  try {
8227
- if (existsSync10(tmpPath)) unlinkSync2(tmpPath);
9017
+ if (existsSync12(tmpPath)) unlinkSync3(tmpPath);
8228
9018
  } catch {
8229
9019
  }
8230
9020
  }
@@ -8440,10 +9230,10 @@ function recordWedgeForCards(states, inProgressCardIds, nowMs, config2) {
8440
9230
  function pruneCardStates(states, liveInProgressCardIds, nowMs, config2) {
8441
9231
  const live = liveInProgressCardIds instanceof Set ? liveInProgressCardIds : new Set(liveInProgressCardIds);
8442
9232
  const next = /* @__PURE__ */ new Map();
8443
- for (const [id, state7] of states) {
9233
+ for (const [id, state8] of states) {
8444
9234
  if (!live.has(id)) continue;
8445
- if (nowMs - state7.lastWedgeAtMs > config2.cooldownMs) continue;
8446
- next.set(id, state7);
9235
+ if (nowMs - state8.lastWedgeAtMs > config2.cooldownMs) continue;
9236
+ next.set(id, state8);
8447
9237
  }
8448
9238
  return next;
8449
9239
  }
@@ -8461,24 +9251,24 @@ function partitionActionableByPoison(actionable, states, config2) {
8461
9251
  }
8462
9252
 
8463
9253
  // src/lib/restart-flags.ts
8464
- import { existsSync as existsSync11, mkdirSync as mkdirSync8, readdirSync as readdirSync6, readFileSync as readFileSync20, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync11 } from "fs";
8465
- import { homedir as homedir11 } from "os";
8466
- import { join as join27 } from "path";
9254
+ import { existsSync as existsSync13, mkdirSync as mkdirSync9, readdirSync as readdirSync7, readFileSync as readFileSync24, renameSync as renameSync6, rmSync as rmSync4, writeFileSync as writeFileSync12 } from "fs";
9255
+ import { homedir as homedir14 } from "os";
9256
+ import { join as join31 } from "path";
8467
9257
  import { randomUUID as randomUUID2 } from "crypto";
8468
9258
  function restartFlagsDir() {
8469
- return join27(homedir11(), ".augmented", "restart-flags");
9259
+ return join31(homedir14(), ".augmented", "restart-flags");
8470
9260
  }
8471
9261
  function flagPath(codeName) {
8472
- return join27(restartFlagsDir(), `${codeName}.flag`);
9262
+ return join31(restartFlagsDir(), `${codeName}.flag`);
8473
9263
  }
8474
9264
  function readRestartFlags() {
8475
9265
  const dir = restartFlagsDir();
8476
- if (!existsSync11(dir)) return [];
9266
+ if (!existsSync13(dir)) return [];
8477
9267
  const out = [];
8478
- for (const entry of readdirSync6(dir)) {
9268
+ for (const entry of readdirSync7(dir)) {
8479
9269
  if (!entry.endsWith(".flag")) continue;
8480
9270
  try {
8481
- const raw = readFileSync20(join27(dir, entry), "utf8");
9271
+ const raw = readFileSync24(join31(dir, entry), "utf8");
8482
9272
  const parsed = JSON.parse(raw);
8483
9273
  if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
8484
9274
  parsed.codeName = entry.replace(/\.flag$/, "");
@@ -8496,7 +9286,7 @@ function readRestartFlags() {
8496
9286
  }
8497
9287
  function deleteRestartFlag(codeName) {
8498
9288
  const path = flagPath(codeName);
8499
- if (existsSync11(path)) {
9289
+ if (existsSync13(path)) {
8500
9290
  rmSync4(path, { force: true });
8501
9291
  }
8502
9292
  }
@@ -8596,8 +9386,8 @@ async function sendError(flag, opts, text) {
8596
9386
  }
8597
9387
 
8598
9388
  // src/lib/restart-context.ts
8599
- import { readdirSync as readdirSync7, readFileSync as readFileSync21, writeFileSync as writeFileSync12, mkdirSync as mkdirSync9, unlinkSync as unlinkSync3 } from "fs";
8600
- import { dirname as dirname7, join as join28 } from "path";
9389
+ import { readdirSync as readdirSync8, readFileSync as readFileSync25, writeFileSync as writeFileSync13, mkdirSync as mkdirSync10, unlinkSync as unlinkSync4 } from "fs";
9390
+ import { dirname as dirname8, join as join32 } from "path";
8601
9391
  var SLACK_PENDING_INBOUND_DIRNAME = "slack-pending-inbound";
8602
9392
  var SLACK_RESTART_CONTEXT_DIRNAME = "slack-restart-context";
8603
9393
  var MAX_TOPIC_CHARS = 140;
@@ -8606,13 +9396,13 @@ var RECONSTRUCT_WINDOW_MS = 7 * 24 * 60 * 60 * 1e3;
8606
9396
  var WINDOW_PAD_MS3 = 5 * 6e4;
8607
9397
  var DEFAULT_MAX_MARKERS_PER_AGENT = 25;
8608
9398
  function augmentedAgentDir(codeName) {
8609
- return dirname7(getProjectDir(codeName));
9399
+ return dirname8(getProjectDir(codeName));
8610
9400
  }
8611
9401
  function slackPendingInboundDir(codeName) {
8612
- return join28(augmentedAgentDir(codeName), SLACK_PENDING_INBOUND_DIRNAME);
9402
+ return join32(augmentedAgentDir(codeName), SLACK_PENDING_INBOUND_DIRNAME);
8613
9403
  }
8614
9404
  function slackRestartContextDir(codeName) {
8615
- return join28(augmentedAgentDir(codeName), SLACK_RESTART_CONTEXT_DIRNAME);
9405
+ return join32(augmentedAgentDir(codeName), SLACK_RESTART_CONTEXT_DIRNAME);
8616
9406
  }
8617
9407
  function sanitizeTopic(raw) {
8618
9408
  const cleaned = raw.replace(/\s+/g, " ").trim().replace(/[<>]/g, " ").replace(/\s+/g, " ").trim();
@@ -8647,14 +9437,14 @@ function computeRestartContextHints(markers, allTurns, nowMs, reconstruct = reco
8647
9437
  }
8648
9438
  function safeReaddir(dir) {
8649
9439
  try {
8650
- return readdirSync7(dir);
9440
+ return readdirSync8(dir);
8651
9441
  } catch {
8652
9442
  return [];
8653
9443
  }
8654
9444
  }
8655
9445
  function readStrandedMarker(path) {
8656
9446
  try {
8657
- const parsed = JSON.parse(readFileSync21(path, "utf-8"));
9447
+ const parsed = JSON.parse(readFileSync25(path, "utf-8"));
8658
9448
  if (typeof parsed.channel === "string" && typeof parsed.thread_ts === "string") {
8659
9449
  return { channel: parsed.channel, thread_ts: parsed.thread_ts };
8660
9450
  }
@@ -8663,8 +9453,8 @@ function readStrandedMarker(path) {
8663
9453
  return null;
8664
9454
  }
8665
9455
  function writeHintFile(path, dir, hint) {
8666
- mkdirSync9(dir, { recursive: true, mode: 448 });
8667
- writeFileSync12(path, JSON.stringify(hint), { mode: 384 });
9456
+ mkdirSync10(dir, { recursive: true, mode: 448 });
9457
+ writeFileSync13(path, JSON.stringify(hint), { mode: 384 });
8668
9458
  }
8669
9459
  function pruneHintsExcept(codeName, freshFilenames) {
8670
9460
  const ctxDir = slackRestartContextDir(codeName);
@@ -8672,7 +9462,7 @@ function pruneHintsExcept(codeName, freshFilenames) {
8672
9462
  if (!filename.endsWith(".json")) continue;
8673
9463
  if (freshFilenames.has(filename)) continue;
8674
9464
  try {
8675
- unlinkSync3(join28(ctxDir, filename));
9465
+ unlinkSync4(join32(ctxDir, filename));
8676
9466
  } catch {
8677
9467
  }
8678
9468
  }
@@ -8693,7 +9483,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
8693
9483
  }
8694
9484
  const markers = [];
8695
9485
  for (const filename of markerFilenames.slice(0, cap)) {
8696
- const parsed = readStrandedMarker(join28(markerDir, filename));
9486
+ const parsed = readStrandedMarker(join32(markerDir, filename));
8697
9487
  if (parsed) markers.push({ filename, channel: parsed.channel, thread_ts: parsed.thread_ts });
8698
9488
  }
8699
9489
  if (markers.length === 0) {
@@ -8707,7 +9497,7 @@ function refreshSlackRestartContextHints(codeNames, opts = {}) {
8707
9497
  const freshFilenames = /* @__PURE__ */ new Set();
8708
9498
  for (const { filename, hint } of hints) {
8709
9499
  try {
8710
- writeHintFile(join28(ctxDir, filename), ctxDir, hint);
9500
+ writeHintFile(join32(ctxDir, filename), ctxDir, hint);
8711
9501
  freshFilenames.add(filename);
8712
9502
  } catch (err) {
8713
9503
  log2(`[restart-context] ${codeName}: hint write failed for ${filename}: ${err.message}`);
@@ -9329,8 +10119,8 @@ var KNOWN_SAFE_TAIL_SIGNATURES = /* @__PURE__ */ new Set(["session_id_in_use"]);
9329
10119
  function shouldSkipRevokedCleanup(previousKnownStatus) {
9330
10120
  return previousKnownStatus === "revoked";
9331
10121
  }
9332
- function hasRevokedResiduals(state7) {
9333
- return state7.gatewayRunning || state7.portAllocated || state7.provisionDirExists;
10122
+ function hasRevokedResiduals(state8) {
10123
+ return state8.gatewayRunning || state8.portAllocated || state8.provisionDirExists;
9334
10124
  }
9335
10125
  var pendingSessionRestarts = /* @__PURE__ */ new Map();
9336
10126
  var lastRestartWasExternal = /* @__PURE__ */ new Map();
@@ -9508,12 +10298,12 @@ function maybeClearStaleTrip(agent) {
9508
10298
  const marker = getAutoResumeMarker(codeName);
9509
10299
  const isSelfResume = marker !== void 0 && Date.now() - marker.autoResumedAt < AUTO_RESUME_SELF_WINDOW_MS;
9510
10300
  if (!isSelfResume) deleteAutoResumeMarker(codeName);
9511
- state6 = {
9512
- ...state6,
10301
+ state7 = {
10302
+ ...state7,
9513
10303
  circuitBreakerTrips: restartBreaker.serialize(),
9514
10304
  circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
9515
10305
  };
9516
- send({ type: "state-update", state: state6 });
10306
+ send({ type: "state-update", state: state7 });
9517
10307
  }
9518
10308
  var autoResumeMarkers = /* @__PURE__ */ new Map();
9519
10309
  function autoResumeMarkerKey(codeName) {
@@ -9605,12 +10395,12 @@ function maybeAutoResume(agent) {
9605
10395
  restartBreaker.clear(codeName);
9606
10396
  reportedTrips.delete(codeName);
9607
10397
  dependencyRecoveryLedger.clear(codeName);
9608
- state6 = {
9609
- ...state6,
10398
+ state7 = {
10399
+ ...state7,
9610
10400
  circuitBreakerTrips: restartBreaker.serialize(),
9611
10401
  circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
9612
10402
  };
9613
- send({ type: "state-update", state: state6 });
10403
+ send({ type: "state-update", state: state7 });
9614
10404
  log(`[auto-resume] agent=${codeName} resumed \u2014 re-trip within backoff window will stay paused (ENG-6088)`);
9615
10405
  } else {
9616
10406
  autoResumeStandDowns.add(`${codeName}:${trippedAt}`);
@@ -9719,12 +10509,12 @@ async function maybeResumeReconcile(agent) {
9719
10509
  restartBreaker.clear(codeName);
9720
10510
  reportedTrips.delete(codeName);
9721
10511
  dependencyRecoveryLedger.clear(codeName);
9722
- state6 = {
9723
- ...state6,
10512
+ state7 = {
10513
+ ...state7,
9724
10514
  circuitBreakerTrips: restartBreaker.serialize(),
9725
10515
  circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
9726
10516
  };
9727
- send({ type: "state-update", state: state6 });
10517
+ send({ type: "state-update", state: state7 });
9728
10518
  log(`[resume-reconciler] agent=${codeName} resumed \u2014 a re-trip within the backoff window will latch unstable (ENG-6383)`);
9729
10519
  } else {
9730
10520
  autoResumeStandDowns.add(standDownKey);
@@ -9888,6 +10678,23 @@ function cancelPendingSessionRestart(codeName) {
9888
10678
  log(`[hot-reload] Cancelled pending restart timer for '${codeName}' (another teardown path is handling it)`);
9889
10679
  }
9890
10680
  var lastSpawnOutcomeByAgent = /* @__PURE__ */ new Map();
10681
+ var lastSpawnDecisionByAgent = /* @__PURE__ */ new Map();
10682
+ function recordSpawnOutcome(codeName, result) {
10683
+ lastSpawnOutcomeByAgent.set(codeName, {
10684
+ spawnAttempted: result.spawnAttempted,
10685
+ sessionHealthyAfter: result.sessionHealthyAfter
10686
+ });
10687
+ if (result.decision) lastSpawnDecisionByAgent.set(codeName, result.decision);
10688
+ }
10689
+ function spawnOutcomeForDiagnostics(codeName) {
10690
+ const last = lastSpawnOutcomeByAgent.get(codeName);
10691
+ if (!last) return void 0;
10692
+ return {
10693
+ spawnAttempted: last.spawnAttempted,
10694
+ sessionHealthyAfter: last.sessionHealthyAfter,
10695
+ lastDecision: lastSpawnDecisionByAgent.get(codeName) ?? null
10696
+ };
10697
+ }
9891
10698
  function spawnWasRefusedWithNoSession(codeName) {
9892
10699
  const last = lastSpawnOutcomeByAgent.get(codeName);
9893
10700
  if (!last) return false;
@@ -10057,7 +10864,7 @@ function performLazyDayRolloverReset(codeName, agentTimezone) {
10057
10864
  }
10058
10865
  function paneLogAgeSecondsFor(codeName) {
10059
10866
  try {
10060
- const mtimeMs = statSync7(paneLogPath(codeName)).mtimeMs;
10867
+ const mtimeMs = statSync8(paneLogPath(codeName)).mtimeMs;
10061
10868
  return Math.max(0, Math.floor((Date.now() - mtimeMs) / 1e3));
10062
10869
  } catch (err) {
10063
10870
  if (err?.code === "ENOENT") return null;
@@ -10106,7 +10913,7 @@ function restartGateFor(codeName, reason) {
10106
10913
  }
10107
10914
  function isHostBusyForForcedUpdate(opts) {
10108
10915
  const now = /* @__PURE__ */ new Date();
10109
- for (const agent of state6.agents) {
10916
+ for (const agent of state7.agents) {
10110
10917
  const decision = decideRestartGate({
10111
10918
  window: null,
10112
10919
  paneLogAgeSeconds: paneLogAgeSecondsFor(agent.codeName),
@@ -10139,7 +10946,7 @@ function runPendingForcedUpdate() {
10139
10946
  relaxed
10140
10947
  } = decidePendingForcedUpdate({
10141
10948
  requestedAt: requestedUpdateAt,
10142
- lastProcessedAt: state6.lastUpdateRequestProcessedAt ?? null,
10949
+ lastProcessedAt: state7.lastUpdateRequestProcessedAt ?? null,
10143
10950
  deferStreak: forcedUpdateDeferStreak,
10144
10951
  nowMs: Date.now(),
10145
10952
  isHostBusy: (isRelaxed) => isHostBusyForForcedUpdate({ relaxed: isRelaxed })
@@ -10173,7 +10980,7 @@ function runPendingForcedUpdate() {
10173
10980
  log(
10174
10981
  forcedUpdate === "consume-deadline" ? `[self-update] WARN "Update CLI now" requested at ${requestedUpdateAt} has been pending ${describePendingFor(pendingForMs)} and the host still reads busy \u2014 running the window-bypassing self-update anyway (ENG-8449 hard deadline). A live turn may be interrupted; the operator asked for this update explicitly.` : `[self-update] "Update CLI now" requested at ${requestedUpdateAt} \u2014 running window-bypassing self-update now (host idle${relaxed ? ", relaxed gate" : ""}).`
10175
10982
  );
10176
- const prevProcessedAt = state6.lastUpdateRequestProcessedAt ?? null;
10983
+ const prevProcessedAt = state7.lastUpdateRequestProcessedAt ?? null;
10177
10984
  void checkAndUpdateCli({ force: true }).then((outcome) => {
10178
10985
  if (!shouldConsumeForcedUpdate(outcome)) {
10179
10986
  log(
@@ -10184,11 +10991,11 @@ function runPendingForcedUpdate() {
10184
10991
  log(
10185
10992
  outcome === "updated" ? `[self-update] "Update CLI now" completed \u2014 upgrade installed; manager restart scheduled.` : `[self-update] "Update CLI now" completed \u2014 host was already on the latest in-channel build; nothing to install.`
10186
10993
  );
10187
- state6.lastUpdateRequestProcessedAt = requestedUpdateAt;
10994
+ state7.lastUpdateRequestProcessedAt = requestedUpdateAt;
10188
10995
  try {
10189
- atomicWriteFileSync(getStateFile(), JSON.stringify(state6, null, 2));
10996
+ atomicWriteFileSync(getStateFile(), JSON.stringify(state7, null, 2));
10190
10997
  } catch (err) {
10191
- state6.lastUpdateRequestProcessedAt = prevProcessedAt;
10998
+ state7.lastUpdateRequestProcessedAt = prevProcessedAt;
10192
10999
  log(
10193
11000
  `[self-update] failed to persist update-request ack; retrying next poll: ${err.message}`
10194
11001
  );
@@ -10207,15 +11014,15 @@ var runningChannelSecretHashes = /* @__PURE__ */ new Map();
10207
11014
  var sessionLaunchManagedStructure = /* @__PURE__ */ new Map();
10208
11015
  function projectMcpHash(_codeName, projectDir) {
10209
11016
  try {
10210
- const raw = readFileSync22(join29(projectDir, ".mcp.json"), "utf-8");
10211
- return createHash16("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
11017
+ const raw = readFileSync26(join33(projectDir, ".mcp.json"), "utf-8");
11018
+ return createHash17("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
10212
11019
  } catch {
10213
11020
  return null;
10214
11021
  }
10215
11022
  }
10216
11023
  function projectMcpKeys(_codeName, projectDir) {
10217
11024
  try {
10218
- const raw = readFileSync22(join29(projectDir, ".mcp.json"), "utf-8");
11025
+ const raw = readFileSync26(join33(projectDir, ".mcp.json"), "utf-8");
10219
11026
  const parsed = JSON.parse(raw);
10220
11027
  const servers = parsed.mcpServers;
10221
11028
  if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
@@ -10233,7 +11040,7 @@ function seedSessionLaunchBaselines(codeName, projectDir) {
10233
11040
  else runningMcpServerKeys.delete(codeName);
10234
11041
  let launchStructure = null;
10235
11042
  try {
10236
- const raw = readFileSync22(join29(projectDir, ".mcp.json"), "utf-8");
11043
+ const raw = readFileSync26(join33(projectDir, ".mcp.json"), "utf-8");
10237
11044
  launchStructure = managedMcpStructureHashFromFile(
10238
11045
  JSON.parse(raw),
10239
11046
  isManagedMcpServerKey
@@ -10343,7 +11150,7 @@ async function runAgentSessionToolBindProbes(agent, integrations, projectDir, op
10343
11150
  if (result && result.rebindCandidates.length > 0 && hostFlagStore().getBoolean("session-tool-rebind")) {
10344
11151
  let mcpJsonForRebind = null;
10345
11152
  try {
10346
- mcpJsonForRebind = JSON.parse(readFileSync22(join29(projectDir, ".mcp.json"), "utf-8"));
11153
+ mcpJsonForRebind = JSON.parse(readFileSync26(join33(projectDir, ".mcp.json"), "utf-8"));
10347
11154
  } catch {
10348
11155
  mcpJsonForRebind = null;
10349
11156
  }
@@ -10487,7 +11294,7 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
10487
11294
  function projectChannelSecretHash(projectDir) {
10488
11295
  try {
10489
11296
  const entries = parseEnvIntegrations(
10490
- readFileSync22(join29(projectDir, ".env.integrations"), "utf-8")
11297
+ readFileSync26(join33(projectDir, ".env.integrations"), "utf-8")
10491
11298
  );
10492
11299
  return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
10493
11300
  } catch {
@@ -10528,7 +11335,7 @@ var STALE_TASK_THRESHOLD_MS = (() => {
10528
11335
  })();
10529
11336
  var taskDisplayInfo = /* @__PURE__ */ new Map();
10530
11337
  var activeChannels = /* @__PURE__ */ new Map();
10531
- var state6 = {
11338
+ var state7 = {
10532
11339
  pid: process.pid,
10533
11340
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
10534
11341
  lastPollAt: null,
@@ -10583,7 +11390,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
10583
11390
  var lastVersionCheckAt = 0;
10584
11391
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
10585
11392
  var lastResponsivenessProbeAt = 0;
10586
- var agtCliVersion = true ? "0.28.565" : "dev";
11393
+ var agtCliVersion = true ? "0.28.567" : "dev";
10587
11394
  function resolveBrewPath(execFileSync2) {
10588
11395
  try {
10589
11396
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -10596,7 +11403,7 @@ function resolveBrewPath(execFileSync2) {
10596
11403
  "/usr/local/bin/brew"
10597
11404
  ];
10598
11405
  for (const path of fallbacks) {
10599
- if (existsSync12(path)) return path;
11406
+ if (existsSync14(path)) return path;
10600
11407
  }
10601
11408
  return null;
10602
11409
  }
@@ -10606,7 +11413,7 @@ function claudeBinaryInstalled(execFileSync2) {
10606
11413
  "/opt/homebrew/bin/claude",
10607
11414
  "/usr/local/bin/claude"
10608
11415
  ];
10609
- if (canonical.some((path) => existsSync12(path))) return true;
11416
+ if (canonical.some((path) => existsSync14(path))) return true;
10610
11417
  try {
10611
11418
  execFileSync2("which", ["claude"], { timeout: 5e3 });
10612
11419
  return true;
@@ -10678,7 +11485,7 @@ async function ensureToolkitCli(toolkitSlug) {
10678
11485
  toolkitCliEnsured.add(toolkitSlug);
10679
11486
  return;
10680
11487
  }
10681
- brewBinDir = dirname8(brewPath);
11488
+ brewBinDir = dirname9(brewPath);
10682
11489
  const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
10683
11490
  log(`[toolkit-install] ${toolkitSlug}: installing via brew (${pkg})\u2026`);
10684
11491
  if (isRoot) {
@@ -10915,8 +11722,8 @@ function claudeManagedSettingsPath() {
10915
11722
  function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
10916
11723
  try {
10917
11724
  let settings = {};
10918
- if (existsSync12(path)) {
10919
- const raw = readFileSync22(path, "utf-8").trim();
11725
+ if (existsSync14(path)) {
11726
+ const raw = readFileSync26(path, "utf-8").trim();
10920
11727
  if (raw) {
10921
11728
  let parsed;
10922
11729
  try {
@@ -10932,8 +11739,8 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
10932
11739
  }
10933
11740
  if (settings.channelsEnabled === true) return "ok";
10934
11741
  settings.channelsEnabled = true;
10935
- mkdirSync10(dirname8(path), { recursive: true });
10936
- writeFileSync13(path, `${JSON.stringify(settings, null, 2)}
11742
+ mkdirSync11(dirname9(path), { recursive: true });
11743
+ writeFileSync14(path, `${JSON.stringify(settings, null, 2)}
10937
11744
  `);
10938
11745
  log(`[managed-settings] set channelsEnabled:true in ${path} (ENG-5786 \u2014 unblocks Claude Code channels)`);
10939
11746
  return "ok";
@@ -10971,7 +11778,7 @@ async function ensureOpencodeBinary() {
10971
11778
  try {
10972
11779
  const prefix = execFileSync2("npm", ["prefix", "-g"], { encoding: "utf-8", timeout: 1e4 }).trim();
10973
11780
  if (prefix) {
10974
- const npmBin = join29(prefix, "bin");
11781
+ const npmBin = join33(prefix, "bin");
10975
11782
  const current = (process.env.PATH ?? "").split(pathDelimiter);
10976
11783
  if (!current.includes(npmBin)) {
10977
11784
  process.env.PATH = [npmBin, ...current.filter(Boolean)].join(pathDelimiter);
@@ -11028,11 +11835,11 @@ async function ensureFrameworkBinary(frameworkId) {
11028
11835
  log(`Claude Code install failed: ${err.message}`);
11029
11836
  return;
11030
11837
  }
11031
- const brewBinDir = dirname8(brewPath);
11838
+ const brewBinDir = dirname9(brewPath);
11032
11839
  if (!process.env.PATH?.split(":").includes(brewBinDir)) {
11033
11840
  process.env.PATH = `${brewBinDir}:${process.env.PATH ?? ""}`;
11034
11841
  }
11035
- if (existsSync12("/home/linuxbrew/.linuxbrew/bin/claude")) {
11842
+ if (existsSync14("/home/linuxbrew/.linuxbrew/bin/claude")) {
11036
11843
  log("Claude Code installed successfully");
11037
11844
  } else {
11038
11845
  log("Claude Code install completed but binary not found at expected path \u2014 check brew logs");
@@ -11088,7 +11895,7 @@ ${r.stderr}`;
11088
11895
  }
11089
11896
  var UPDATE_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
11090
11897
  function selfUpdateAppliedMarkerPath() {
11091
- return join29(homedir12(), ".augmented", ".last-self-update-applied");
11898
+ return join33(homedir15(), ".augmented", ".last-self-update-applied");
11092
11899
  }
11093
11900
  var selfUpdateUpToDateLogged = false;
11094
11901
  var selfUpdatePinnedLogged = false;
@@ -11117,7 +11924,7 @@ async function checkAndUpdateCli(opts) {
11117
11924
  const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
11118
11925
  if (!isBrewFormula && !isNpmGlobal) return "noop";
11119
11926
  const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
11120
- const markerPath = join29(homedir12(), ".augmented", ".last-update-check");
11927
+ const markerPath = join33(homedir15(), ".augmented", ".last-update-check");
11121
11928
  if (!force) {
11122
11929
  try {
11123
11930
  const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
@@ -11523,7 +12330,7 @@ async function runClaudeRuntimeAuthProbe() {
11523
12330
  ];
11524
12331
  try {
11525
12332
  const { stdout, stderr } = await execFilePromiseLong(resolveClaudeBinary(), args, {
11526
- cwd: homedir12(),
12333
+ cwd: homedir15(),
11527
12334
  timeout: RUNTIME_AUTH_PROBE_TIMEOUT_MS,
11528
12335
  stdin: "ignore",
11529
12336
  env: childEnv,
@@ -11569,14 +12376,14 @@ async function checkClaudeAuth() {
11569
12376
  }
11570
12377
  var evalEmptyMcpConfigPath = null;
11571
12378
  function ensureEvalEmptyMcpConfig() {
11572
- if (evalEmptyMcpConfigPath && existsSync12(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
11573
- const dir = join29(homedir12(), ".augmented");
12379
+ if (evalEmptyMcpConfigPath && existsSync14(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
12380
+ const dir = join33(homedir15(), ".augmented");
11574
12381
  try {
11575
- mkdirSync10(dir, { recursive: true });
12382
+ mkdirSync11(dir, { recursive: true });
11576
12383
  } catch {
11577
12384
  }
11578
- const p = join29(dir, ".eval-empty-mcp.json");
11579
- writeFileSync13(p, JSON.stringify({ mcpServers: {} }));
12385
+ const p = join33(dir, ".eval-empty-mcp.json");
12386
+ writeFileSync14(p, JSON.stringify({ mcpServers: {} }));
11580
12387
  evalEmptyMcpConfigPath = p;
11581
12388
  return p;
11582
12389
  }
@@ -11601,7 +12408,7 @@ async function runEvalClaude(prompt, model) {
11601
12408
  ""
11602
12409
  ];
11603
12410
  const { stdout } = await execFilePromiseLong(resolveClaudeBinary(), args, {
11604
- cwd: homedir12(),
12411
+ cwd: homedir15(),
11605
12412
  timeout: 12e4,
11606
12413
  stdin: "ignore",
11607
12414
  env: childEnv,
@@ -11613,6 +12420,9 @@ async function runEvalClaude(prompt, model) {
11613
12420
  function memoryExtractionEnabled() {
11614
12421
  return hostFlagStore().getBoolean("memory-extraction");
11615
12422
  }
12423
+ function toolCallAuditEnabled() {
12424
+ return hostFlagStore().getBoolean("tool-call-audit");
12425
+ }
11616
12426
  function conversationScorerSuppressed() {
11617
12427
  return meteredScorerSuppressed(
11618
12428
  getCachedClaudeAuthMode(),
@@ -11667,10 +12477,10 @@ function resolveConversationEvalBackend() {
11667
12477
  return conversationEvalBackend;
11668
12478
  }
11669
12479
  function getStateFile() {
11670
- return join29(config?.configDir ?? join29(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
12480
+ return join33(config?.configDir ?? join33(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
11671
12481
  }
11672
12482
  function channelHashCacheDir() {
11673
- return config?.configDir ?? join29(process.env["HOME"] ?? "/tmp", ".augmented");
12483
+ return config?.configDir ?? join33(process.env["HOME"] ?? "/tmp", ".augmented");
11674
12484
  }
11675
12485
  function loadChannelHashCache2() {
11676
12486
  loadChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
@@ -11724,7 +12534,7 @@ function removeDeliveryBaselineEntries(agentId) {
11724
12534
  var _channelQuarantineStore = null;
11725
12535
  function channelQuarantineStore() {
11726
12536
  if (!_channelQuarantineStore) {
11727
- const dir = config?.configDir ?? join29(process.env["HOME"] ?? "/tmp", ".augmented");
12537
+ const dir = config?.configDir ?? join33(process.env["HOME"] ?? "/tmp", ".augmented");
11728
12538
  _channelQuarantineStore = new ChannelQuarantineStore(defaultQuarantinePath(dir));
11729
12539
  }
11730
12540
  return _channelQuarantineStore;
@@ -11741,7 +12551,7 @@ function claudeMdSizeFor(codeName) {
11741
12551
  var _hostFlagStore = null;
11742
12552
  function hostFlagStore() {
11743
12553
  if (!_hostFlagStore) {
11744
- const dir = config?.configDir ?? join29(process.env["HOME"] ?? "/tmp", ".augmented");
12554
+ const dir = config?.configDir ?? join33(process.env["HOME"] ?? "/tmp", ".augmented");
11745
12555
  _hostFlagStore = new HostFlagStore({ cachePath: defaultFlagsCachePath(dir), log });
11746
12556
  }
11747
12557
  return _hostFlagStore;
@@ -11814,13 +12624,13 @@ function parseSkillFrontmatter(content) {
11814
12624
  return out;
11815
12625
  }
11816
12626
  async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
11817
- const { readdirSync: readdirSync9, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync14 } = await import("fs");
11818
- const skillsDir = join29(configDir, codeName, "project", ".claude", "skills");
11819
- const claudeMdPath = join29(configDir, codeName, "project", "CLAUDE.md");
12627
+ const { readdirSync: readdirSync10, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync15 } = await import("fs");
12628
+ const skillsDir = join33(configDir, codeName, "project", ".claude", "skills");
12629
+ const claudeMdPath = join33(configDir, codeName, "project", "CLAUDE.md");
11820
12630
  if (!ex(skillsDir) || !ex(claudeMdPath)) return;
11821
12631
  const entries = [];
11822
- for (const dir of readdirSync9(skillsDir).sort()) {
11823
- const skillFile = join29(skillsDir, dir, "SKILL.md");
12632
+ for (const dir of readdirSync10(skillsDir).sort()) {
12633
+ const skillFile = join33(skillsDir, dir, "SKILL.md");
11824
12634
  if (!ex(skillFile)) continue;
11825
12635
  try {
11826
12636
  const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
@@ -11864,7 +12674,7 @@ ${SKILLS_INDEX_END}`;
11864
12674
  next = current.trimEnd() + "\n\n" + section + "\n";
11865
12675
  }
11866
12676
  if (next !== current) {
11867
- writeFileSync14(claudeMdPath, next, "utf-8");
12677
+ writeFileSync15(claudeMdPath, next, "utf-8");
11868
12678
  log2(
11869
12679
  injectSkillList ? `Refreshed skills index in CLAUDE.md for '${codeName}' (${entries.length} skills)` : `Refreshed CLAUDE.md managed block for '${codeName}' (skill list suppressed by claude-md-skills-index=false; ${entries.length} skills on disk)`
11870
12680
  );
@@ -11887,10 +12697,10 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
11887
12697
  if (codeNames.length === 0) return;
11888
12698
  void (async () => {
11889
12699
  try {
11890
- const { collectDiagnostics } = await import("../persistent-session-MLLLDI5U.js");
12700
+ const { collectDiagnostics } = await import("../persistent-session-DVTSZAPE.js");
11891
12701
  await api.post("/host/heartbeat", {
11892
12702
  host_id: hostId,
11893
- agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor)
12703
+ agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics)
11894
12704
  });
11895
12705
  } catch (err) {
11896
12706
  log(`[restart] post-respawn diagnostics flush failed: ${err.message}`);
@@ -11984,7 +12794,7 @@ async function pollCycle() {
11984
12794
  const now = Date.now();
11985
12795
  if (now - lastVersionCheckAt > VERSION_CHECK_INTERVAL_MS) {
11986
12796
  try {
11987
- const firstAgent = state6.agents[0];
12797
+ const firstAgent = state7.agents[0];
11988
12798
  const versionAdapter = firstAgent ? resolveAgentFramework(firstAgent.codeName) : getFramework(DEFAULT_FRAMEWORK);
11989
12799
  if (versionAdapter.getVersion) {
11990
12800
  cachedFrameworkVersion = await versionAdapter.getVersion();
@@ -11995,9 +12805,9 @@ async function pollCycle() {
11995
12805
  }
11996
12806
  try {
11997
12807
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
11998
- const { collectDiagnostics } = await import("../persistent-session-MLLLDI5U.js");
12808
+ const { collectDiagnostics } = await import("../persistent-session-DVTSZAPE.js");
11999
12809
  const diagCodeNames = [...agentState.persistentSessionAgents];
12000
- const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor) : void 0;
12810
+ const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics) : void 0;
12001
12811
  let tailscaleHostname;
12002
12812
  try {
12003
12813
  const { execSync: es } = await import("child_process");
@@ -12025,10 +12835,10 @@ async function pollCycle() {
12025
12835
  claudeAuth = await detectClaudeAuth();
12026
12836
  } catch (err) {
12027
12837
  const errText = err instanceof Error ? err.message : String(err);
12028
- const errId = createHash16("sha256").update(errText).digest("hex").slice(0, 12);
12838
+ const errId = createHash17("sha256").update(errText).digest("hex").slice(0, 12);
12029
12839
  log(`Claude auth detection failed (error_id=${errId})`);
12030
12840
  }
12031
- const hostHasClaudeCode = state6.agents.some(
12841
+ const hostHasClaudeCode = state7.agents.some(
12032
12842
  (a) => agentFrameworkCache.get(a.codeName) === "claude-code"
12033
12843
  );
12034
12844
  if (hostHasClaudeCode) {
@@ -12078,7 +12888,7 @@ async function pollCycle() {
12078
12888
  // ENG-6692: ack the last consumed "Update CLI now" timestamp so the API
12079
12889
  // clears hosts.update_requested_at. Echoes our persisted dedup marker;
12080
12890
  // null until we've ever consumed one.
12081
- update_request_processed_at: state6.lastUpdateRequestProcessedAt ?? null
12891
+ update_request_processed_at: state7.lastUpdateRequestProcessedAt ?? null
12082
12892
  });
12083
12893
  if (hbResp?.maintenance_window) {
12084
12894
  cachedMaintenanceWindow = hbResp.maintenance_window;
@@ -12118,7 +12928,7 @@ async function pollCycle() {
12118
12928
  collectPanelessActivityProbes,
12119
12929
  getResponsivenessIntervalMs,
12120
12930
  occupancyQualificationClassifications
12121
- } = await import("../responsiveness-probe-QMAIFW4P.js");
12931
+ } = await import("../responsiveness-probe-KEFPJXQ6.js");
12122
12932
  const probeIntervalMs = getResponsivenessIntervalMs();
12123
12933
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
12124
12934
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -12209,7 +13019,7 @@ async function pollCycle() {
12209
13019
  collectResponsivenessProbes,
12210
13020
  livePendingInboundOldestAgeSeconds,
12211
13021
  parkPendingInbound
12212
- } = await import("../responsiveness-probe-QMAIFW4P.js");
13022
+ } = await import("../responsiveness-probe-KEFPJXQ6.js");
12213
13023
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
12214
13024
  const wedgeNow = /* @__PURE__ */ new Date();
12215
13025
  const liveAgents = agentState.persistentSessionAgents;
@@ -12298,13 +13108,13 @@ async function pollCycle() {
12298
13108
  );
12299
13109
  if (hostFlagStore().getBoolean("wedge-transient-notice")) {
12300
13110
  try {
12301
- const paneTail = readFileSync22(paneLogPath(codeName), "utf8").slice(-65536);
13111
+ const paneTail = readFileSync26(paneLogPath(codeName), "utf8").slice(-65536);
12302
13112
  const transient = detectTransientApiErrorInLog(paneTail);
12303
13113
  if (transient) {
12304
- const wedgeHome = join29(homedir12(), ".augmented", codeName);
12305
- if (existsSync12(wedgeHome)) {
13114
+ const wedgeHome = join33(homedir15(), ".augmented", codeName);
13115
+ if (existsSync14(wedgeHome)) {
12306
13116
  atomicWriteFileSync(
12307
- join29(wedgeHome, "watchdog-give-up.json"),
13117
+ join33(wedgeHome, "watchdog-give-up.json"),
12308
13118
  JSON.stringify({
12309
13119
  gave_up_at: wedgeNow.toISOString(),
12310
13120
  reason: "transient_overload"
@@ -12434,7 +13244,7 @@ async function pollCycle() {
12434
13244
  const requested = agent.restart_requested_at ?? null;
12435
13245
  if (!requested) continue;
12436
13246
  if (restartInFlight.has(agent.agent_id)) continue;
12437
- const prev = state6.agents.find((a) => a.agentId === agent.agent_id);
13247
+ const prev = state7.agents.find((a) => a.agentId === agent.agent_id);
12438
13248
  const lastProcessed = prev?.lastRestartProcessedAt ?? null;
12439
13249
  const alreadyServiced = lastProcessed != null && Date.parse(lastProcessed) >= Date.parse(requested);
12440
13250
  if (!alreadyServiced) {
@@ -12513,7 +13323,7 @@ async function pollCycle() {
12513
13323
  const processOrder = fastRespawn ? reorderRestartedFirst(agents, new Set(restartAcks.keys())) : agents;
12514
13324
  for (const agent of processOrder) {
12515
13325
  if (restartInFlight.has(agent.agent_id)) {
12516
- const existing = state6.agents.find((a) => a.agentId === agent.agent_id);
13326
+ const existing = state7.agents.find((a) => a.agentId === agent.agent_id);
12517
13327
  if (existing) {
12518
13328
  agentStates.push(existing);
12519
13329
  continue;
@@ -12523,7 +13333,7 @@ async function pollCycle() {
12523
13333
  await processAgent(agent, agentStates);
12524
13334
  } catch (err) {
12525
13335
  log(`Error processing agent '${agent.code_name}': ${err.message}`);
12526
- const existing = state6.agents.find((a) => a.agentId === agent.agent_id);
13336
+ const existing = state7.agents.find((a) => a.agentId === agent.agent_id);
12527
13337
  if (existing) {
12528
13338
  agentStates.push(existing);
12529
13339
  } else {
@@ -12552,12 +13362,12 @@ async function pollCycle() {
12552
13362
  void maybeReportActivityCache({ api, log });
12553
13363
  const restartAckStateChanged = applyRestartAcks({
12554
13364
  agentStates,
12555
- priorAgents: state6.agents,
13365
+ priorAgents: state7.agents,
12556
13366
  restartAcks
12557
13367
  });
12558
13368
  if (restartAckStateChanged) {
12559
13369
  try {
12560
- const ackedState = { ...state6, agents: agentStates };
13370
+ const ackedState = { ...state7, agents: agentStates };
12561
13371
  atomicWriteFileSync(getStateFile(), JSON.stringify(ackedState, null, 2));
12562
13372
  } catch (err) {
12563
13373
  log(`[restart] failed to persist ack immediately: ${err.message}`);
@@ -12579,13 +13389,13 @@ async function pollCycle() {
12579
13389
  } catch {
12580
13390
  }
12581
13391
  const currentIds = new Set(agents.map((a) => a.agent_id));
12582
- for (const prev of state6.agents) {
13392
+ for (const prev of state7.agents) {
12583
13393
  if (!currentIds.has(prev.agentId)) {
12584
13394
  log(`Agent '${prev.codeName}' removed from host (deleted or unassigned)`);
12585
13395
  const adapter = resolveAgentFramework(prev.codeName);
12586
13396
  stopAgentRuntime2(prev.codeName, "removed-from-host");
12587
13397
  killAgentChannelProcesses(prev.codeName, { log });
12588
- const agentDir = join29(adapter.getAgentDir(prev.codeName), "provision");
13398
+ const agentDir = join33(adapter.getAgentDir(prev.codeName), "provision");
12589
13399
  await cleanupAgentFiles(prev.codeName, agentDir);
12590
13400
  clearAgentCaches(prev.agentId, prev.codeName);
12591
13401
  }
@@ -12672,10 +13482,10 @@ async function pollCycle() {
12672
13482
  // pending-inbound marker. Best-effort: a write failure is logged by
12673
13483
  // the watchdog, never fails the poll cycle.
12674
13484
  signalGiveUp: (codeName) => {
12675
- const dir = join29(homedir12(), ".augmented", codeName);
12676
- if (!existsSync12(dir)) return;
13485
+ const dir = join33(homedir15(), ".augmented", codeName);
13486
+ if (!existsSync14(dir)) return;
12677
13487
  atomicWriteFileSync(
12678
- join29(dir, "watchdog-give-up.json"),
13488
+ join33(dir, "watchdog-give-up.json"),
12679
13489
  JSON.stringify({ gave_up_at: (/* @__PURE__ */ new Date()).toISOString() })
12680
13490
  );
12681
13491
  }
@@ -12716,10 +13526,10 @@ async function pollCycle() {
12716
13526
  }
12717
13527
  } catch {
12718
13528
  }
12719
- state6 = {
12720
- ...state6,
13529
+ state7 = {
13530
+ ...state7,
12721
13531
  lastPollAt: (/* @__PURE__ */ new Date()).toISOString(),
12722
- pollCount: state6.pollCount + 1,
13532
+ pollCount: state7.pollCount + 1,
12723
13533
  agents: agentStates,
12724
13534
  // ENG-5441: serialise trip state on every poll so manager restarts
12725
13535
  // never silently clear a tripped breaker. Cheap — only tripped
@@ -12733,9 +13543,9 @@ async function pollCycle() {
12733
13543
  consecutivePollFailures = 0;
12734
13544
  }
12735
13545
  verifyPendingRestarts(Date.now());
12736
- send({ type: "state-update", state: state6 });
13546
+ send({ type: "state-update", state: state7 });
12737
13547
  } catch (err) {
12738
- state6.errorCount++;
13548
+ state7.errorCount++;
12739
13549
  const message = err.message;
12740
13550
  log(`Poll error: ${message}`);
12741
13551
  send({ type: "error", message });
@@ -12820,10 +13630,18 @@ async function processAgent(agent, agentStates) {
12820
13630
  onModelCallError: (err) => reportManagerModelCallError("memory_extraction", err, memBackend.model ?? null)
12821
13631
  });
12822
13632
  }
13633
+ if (toolCallAuditEnabled()) {
13634
+ void maybeScanToolCalls({
13635
+ api,
13636
+ codeName: agent.code_name,
13637
+ agentId: agent.agent_id,
13638
+ log
13639
+ });
13640
+ }
12823
13641
  }
12824
13642
  const now = (/* @__PURE__ */ new Date()).toISOString();
12825
13643
  const adapter = resolveAgentFramework(agent.code_name);
12826
- let agentDir = join29(adapter.getAgentDir(agent.code_name), "provision");
13644
+ let agentDir = join33(adapter.getAgentDir(agent.code_name), "provision");
12827
13645
  if (agent.status === "draft" || agent.status === "paused") {
12828
13646
  if (previousKnownStatus !== agent.status) {
12829
13647
  log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
@@ -12863,7 +13681,7 @@ async function processAgent(agent, agentStates) {
12863
13681
  const residuals = {
12864
13682
  gatewayRunning: false,
12865
13683
  portAllocated: false,
12866
- provisionDirExists: existsSync12(agentDir)
13684
+ provisionDirExists: existsSync14(agentDir)
12867
13685
  };
12868
13686
  if (!hasRevokedResiduals(residuals)) {
12869
13687
  agentStates.push({
@@ -12920,11 +13738,11 @@ async function processAgent(agent, agentStates) {
12920
13738
  const marker = getAutoResumeMarker(agent.code_name);
12921
13739
  const isSelfResume = marker !== void 0 && Date.now() - marker.autoResumedAt < AUTO_RESUME_SELF_WINDOW_MS;
12922
13740
  if (!isSelfResume && deleteAutoResumeMarker(agent.code_name)) {
12923
- state6 = {
12924
- ...state6,
13741
+ state7 = {
13742
+ ...state7,
12925
13743
  circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
12926
13744
  };
12927
- send({ type: "state-update", state: state6 });
13745
+ send({ type: "state-update", state: state7 });
12928
13746
  log(`[auto-resume] Cleared auto-resume marker for '${agent.code_name}' on operator resume \u2014 credit re-armed (ENG-6088)`);
12929
13747
  }
12930
13748
  }
@@ -12955,7 +13773,7 @@ async function processAgent(agent, agentStates) {
12955
13773
  });
12956
13774
  } catch (err) {
12957
13775
  log(`Refresh failed for '${agent.code_name}': ${err.message}`);
12958
- const existing = state6.agents.find((a) => a.agentId === agent.agent_id);
13776
+ const existing = state7.agents.find((a) => a.agentId === agent.agent_id);
12959
13777
  agentStates.push(existing ?? {
12960
13778
  agentId: agent.agent_id,
12961
13779
  codeName: agent.code_name,
@@ -12997,7 +13815,7 @@ async function processAgent(agent, agentStates) {
12997
13815
  const frameworkId = refreshData.agent.framework ?? DEFAULT_FRAMEWORK;
12998
13816
  agentFrameworkCache.set(agent.code_name, frameworkId);
12999
13817
  const frameworkAdapter = getFramework(frameworkId);
13000
- agentDir = join29(frameworkAdapter.getAgentDir(agent.code_name), "provision");
13818
+ agentDir = join33(frameworkAdapter.getAgentDir(agent.code_name), "provision");
13001
13819
  cacheAgentDeliveryMetadata(agent.code_name, refreshData);
13002
13820
  agentRestartTimezoneInputs.set(agent.code_name, {
13003
13821
  agentTimezone: typeof refreshData.agent.timezone === "string" ? refreshData.agent.timezone : null,
@@ -13019,7 +13837,7 @@ async function processAgent(agent, agentStates) {
13019
13837
  const charterVersion = refreshData.charter.version;
13020
13838
  const toolsVersion = refreshData.tools.version;
13021
13839
  const known = agentState.knownVersions.get(agent.agent_id);
13022
- let lastProvisionAt = state6.agents.find((a) => a.agentId === agent.agent_id)?.lastProvisionAt ?? null;
13840
+ let lastProvisionAt = state7.agents.find((a) => a.agentId === agent.agent_id)?.lastProvisionAt ?? null;
13023
13841
  const quarantinedChannels = channelQuarantineStore().getQuarantinedKeys(agent.code_name);
13024
13842
  const currentChannelIds = setWithout(
13025
13843
  launchableChannelIds(refreshData.channel_configs),
@@ -13044,9 +13862,9 @@ async function processAgent(agent, agentStates) {
13044
13862
  try {
13045
13863
  const artifacts = generateArtifacts(agent, refreshData, frameworkAdapter, renderIntegrationsSection);
13046
13864
  const changedFiles = [];
13047
- mkdirSync10(agentDir, { recursive: true });
13865
+ mkdirSync11(agentDir, { recursive: true });
13048
13866
  for (const artifact of artifacts) {
13049
- const filePath = join29(agentDir, artifact.relativePath);
13867
+ const filePath = join33(agentDir, artifact.relativePath);
13050
13868
  let existingHash;
13051
13869
  let newHash;
13052
13870
  let writeContent = artifact.content;
@@ -13065,8 +13883,8 @@ async function processAgent(agent, agentStates) {
13065
13883
  };
13066
13884
  newHash = sha256(stripDynamicSections(artifact.content));
13067
13885
  try {
13068
- const projectClaudeMd = join29(config.configDir, agent.code_name, "project", "CLAUDE.md");
13069
- const existing = readFileSync22(projectClaudeMd, "utf-8");
13886
+ const projectClaudeMd = join33(config.configDir, agent.code_name, "project", "CLAUDE.md");
13887
+ const existing = readFileSync26(projectClaudeMd, "utf-8");
13070
13888
  existingHash = sha256(stripDynamicSections(existing));
13071
13889
  } catch {
13072
13890
  existingHash = null;
@@ -13084,7 +13902,7 @@ async function processAgent(agent, agentStates) {
13084
13902
  const generatorKeys = Object.keys(generatorServers);
13085
13903
  let existingRaw = "";
13086
13904
  try {
13087
- existingRaw = readFileSync22(filePath, "utf-8");
13905
+ existingRaw = readFileSync26(filePath, "utf-8");
13088
13906
  } catch {
13089
13907
  }
13090
13908
  const existingServers = parseMcp(existingRaw);
@@ -13100,7 +13918,7 @@ async function processAgent(agent, agentStates) {
13100
13918
  } else if (artifact.relativePath === "opencode.json") {
13101
13919
  let existingRaw = null;
13102
13920
  try {
13103
- existingRaw = readFileSync22(filePath, "utf-8");
13921
+ existingRaw = readFileSync26(filePath, "utf-8");
13104
13922
  } catch {
13105
13923
  }
13106
13924
  const mergeResult = mergeOpencodeConfigArtifact(artifact.content, existingRaw);
@@ -13116,26 +13934,26 @@ async function processAgent(agent, agentStates) {
13116
13934
  }
13117
13935
  }
13118
13936
  if (changedFiles.length > 0) {
13119
- const isFirst = !existsSync12(join29(agentDir, "CHARTER.md"));
13937
+ const isFirst = !existsSync14(join33(agentDir, "CHARTER.md"));
13120
13938
  const verb = isFirst ? "Provisioning" : "Updating";
13121
13939
  const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
13122
13940
  log(`${verb} '${agent.code_name}': ${fileNames}`);
13123
13941
  for (const file of changedFiles) {
13124
- const filePath = join29(agentDir, file.relativePath);
13125
- mkdirSync10(dirname8(filePath), { recursive: true });
13942
+ const filePath = join33(agentDir, file.relativePath);
13943
+ mkdirSync11(dirname9(filePath), { recursive: true });
13126
13944
  if (file.relativePath === ".mcp.json") {
13127
13945
  safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
13128
13946
  } else {
13129
- writeFileSync13(filePath, file.content);
13947
+ writeFileSync14(filePath, file.content);
13130
13948
  }
13131
13949
  }
13132
13950
  try {
13133
- const provSkillsDir = join29(agentDir, ".claude", "skills");
13134
- if (existsSync12(provSkillsDir)) {
13135
- for (const folder of readdirSync8(provSkillsDir)) {
13951
+ const provSkillsDir = join33(agentDir, ".claude", "skills");
13952
+ if (existsSync14(provSkillsDir)) {
13953
+ for (const folder of readdirSync9(provSkillsDir)) {
13136
13954
  if (folder.startsWith("knowledge-")) {
13137
13955
  try {
13138
- rmSync5(join29(provSkillsDir, folder), { recursive: true });
13956
+ rmSync5(join33(provSkillsDir, folder), { recursive: true });
13139
13957
  } catch {
13140
13958
  }
13141
13959
  }
@@ -13148,7 +13966,7 @@ async function processAgent(agent, agentStates) {
13148
13966
  const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
13149
13967
  const hashes = /* @__PURE__ */ new Map();
13150
13968
  for (const file of trackedFiles2) {
13151
- const h = hashFile(join29(agentDir, file));
13969
+ const h = hashFile(join33(agentDir, file));
13152
13970
  if (h) hashes.set(file, h);
13153
13971
  }
13154
13972
  agentState.writtenHashes.set(agent.agent_id, hashes);
@@ -13166,14 +13984,14 @@ async function processAgent(agent, agentStates) {
13166
13984
  }
13167
13985
  if (Array.isArray(refreshData.workflows)) {
13168
13986
  try {
13169
- const provWorkflowsDir = join29(agentDir, ".claude", "workflows");
13170
- if (existsSync12(provWorkflowsDir)) {
13987
+ const provWorkflowsDir = join33(agentDir, ".claude", "workflows");
13988
+ if (existsSync14(provWorkflowsDir)) {
13171
13989
  const expected = new Set(refreshData.workflows.map((w) => `${w.name}.js`));
13172
- for (const file of readdirSync8(provWorkflowsDir)) {
13990
+ for (const file of readdirSync9(provWorkflowsDir)) {
13173
13991
  if (!file.endsWith(".js")) continue;
13174
13992
  if (expected.has(file)) continue;
13175
13993
  try {
13176
- rmSync5(join29(provWorkflowsDir, file));
13994
+ rmSync5(join33(provWorkflowsDir, file));
13177
13995
  } catch {
13178
13996
  }
13179
13997
  }
@@ -13252,10 +14070,10 @@ async function processAgent(agent, agentStates) {
13252
14070
  }
13253
14071
  let lastDriftCheckAt = now;
13254
14072
  const written = agentState.writtenHashes.get(agent.agent_id);
13255
- if (written && existsSync12(agentDir)) {
14073
+ if (written && existsSync14(agentDir)) {
13256
14074
  const driftedFiles = [];
13257
14075
  for (const [file, expectedHash] of written) {
13258
- const localHash = hashFile(join29(agentDir, file));
14076
+ const localHash = hashFile(join33(agentDir, file));
13259
14077
  if (localHash && localHash !== expectedHash) {
13260
14078
  driftedFiles.push(file);
13261
14079
  }
@@ -13266,7 +14084,7 @@ async function processAgent(agent, agentStates) {
13266
14084
  try {
13267
14085
  const localHashes = {};
13268
14086
  for (const file of driftedFiles) {
13269
- localHashes[file] = hashFile(join29(agentDir, file));
14087
+ localHashes[file] = hashFile(join33(agentDir, file));
13270
14088
  }
13271
14089
  await api.post("/host/drift", {
13272
14090
  agent_id: agent.agent_id,
@@ -13468,15 +14286,15 @@ async function processAgent(agent, agentStates) {
13468
14286
  const addedChannels = [...restartDecision.added];
13469
14287
  const writeDmNoticeMarkers = isChannelAddRestart ? () => {
13470
14288
  try {
13471
- const agentAugmentedDir = join29(homedir12(), ".augmented", agent.code_name);
13472
- mkdirSync10(agentAugmentedDir, { recursive: true });
14289
+ const agentAugmentedDir = join33(homedir15(), ".augmented", agent.code_name);
14290
+ mkdirSync11(agentAugmentedDir, { recursive: true });
13473
14291
  const markerJson = JSON.stringify({
13474
14292
  version: 1,
13475
14293
  at: (/* @__PURE__ */ new Date()).toISOString(),
13476
14294
  added: addedChannels
13477
14295
  });
13478
14296
  for (const file of ["slack-channel-add-restart.json", "telegram-channel-add-restart.json"]) {
13479
- atomicWriteFileSync(join29(agentAugmentedDir, file), markerJson);
14297
+ atomicWriteFileSync(join33(agentAugmentedDir, file), markerJson);
13480
14298
  }
13481
14299
  } catch (err) {
13482
14300
  log(`[hot-reload] channel-add DM-notice marker write failed for '${agent.code_name}' (non-fatal): ${err.message}`);
@@ -13552,7 +14370,7 @@ async function processAgent(agent, agentStates) {
13552
14370
  const behaviourSubset = extractMsTeamsBehaviourSubset(
13553
14371
  msteamsEntry?.config
13554
14372
  );
13555
- const behaviourHash = createHash16("sha256").update(canonicalJson(behaviourSubset)).digest("hex");
14373
+ const behaviourHash = createHash17("sha256").update(canonicalJson(behaviourSubset)).digest("hex");
13556
14374
  const prevBehaviourHash = agentState.knownMsTeamsBehaviourHashes.get(agent.agent_id);
13557
14375
  const msteamsBehaviourRestrictive = isMsTeamsBehaviourRestrictive(behaviourSubset);
13558
14376
  const behaviourDecision = decideSenderPolicyRestart({
@@ -13608,7 +14426,7 @@ async function processAgent(agent, agentStates) {
13608
14426
  const slackBehaviourSubset = extractSlackBehaviourSubset(
13609
14427
  slackEntry?.config
13610
14428
  );
13611
- const slackBehaviourHash = createHash16("sha256").update(canonicalJson(slackBehaviourSubset)).digest("hex");
14429
+ const slackBehaviourHash = createHash17("sha256").update(canonicalJson(slackBehaviourSubset)).digest("hex");
13612
14430
  const prevSlackBehaviourHash = agentState.knownSlackBehaviourHashes.get(agent.agent_id);
13613
14431
  const slackBehaviourRestrictive = isSlackBehaviourRestrictive(slackBehaviourSubset);
13614
14432
  const slackBehaviourDecision = decideSenderPolicyRestart({
@@ -13665,24 +14483,24 @@ async function processAgent(agent, agentStates) {
13665
14483
  if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK) === "claude-code") {
13666
14484
  try {
13667
14485
  const agentProvisionDir = agentDir;
13668
- const projectDir = join29(homedir12(), ".augmented", agent.code_name, "project");
13669
- mkdirSync10(agentProvisionDir, { recursive: true });
13670
- mkdirSync10(projectDir, { recursive: true });
13671
- const provisionMcpPath = join29(agentProvisionDir, ".mcp.json");
13672
- const projectMcpPath = join29(projectDir, ".mcp.json");
14486
+ const projectDir = join33(homedir15(), ".augmented", agent.code_name, "project");
14487
+ mkdirSync11(agentProvisionDir, { recursive: true });
14488
+ mkdirSync11(projectDir, { recursive: true });
14489
+ const provisionMcpPath = join33(agentProvisionDir, ".mcp.json");
14490
+ const projectMcpPath = join33(projectDir, ".mcp.json");
13673
14491
  let mcpConfig = { mcpServers: {} };
13674
14492
  try {
13675
- mcpConfig = JSON.parse(readFileSync22(provisionMcpPath, "utf-8"));
14493
+ mcpConfig = JSON.parse(readFileSync26(provisionMcpPath, "utf-8"));
13676
14494
  if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
13677
14495
  } catch {
13678
14496
  }
13679
- const localDirectChatChannel = join29(homedir12(), ".augmented", "_mcp", "direct-chat-channel.js");
14497
+ const localDirectChatChannel = join33(homedir15(), ".augmented", "_mcp", "direct-chat-channel.js");
13680
14498
  const directChatTeamSettings = refreshData.team?.settings;
13681
14499
  const directChatTz = (() => {
13682
14500
  const tz = directChatTeamSettings?.["timezone"];
13683
14501
  return typeof tz === "string" && tz.trim() !== "" ? tz.trim() : void 0;
13684
14502
  })();
13685
- if (existsSync12(localDirectChatChannel)) {
14503
+ if (existsSync14(localDirectChatChannel)) {
13686
14504
  const directChatEnv = {
13687
14505
  AGT_HOST: requireHost(),
13688
14506
  // ENG-5901 Track D: templated — the manager exports the real
@@ -13702,7 +14520,7 @@ async function processAgent(agent, agentStates) {
13702
14520
  // ~/.augmented/<codeName>/.current-turn-initiator.json. Note getAgentDir
13703
14521
  // returns the agent root (NOT the /provision subdir `agentDir` points at),
13704
14522
  // so it byte-matches the broker readers' path.
13705
- AGT_TURN_INITIATOR_FILE: join29(
14523
+ AGT_TURN_INITIATOR_FILE: join33(
13706
14524
  frameworkAdapter.getAgentDir(agent.code_name),
13707
14525
  ".current-turn-initiator.json"
13708
14526
  )
@@ -13722,8 +14540,8 @@ async function processAgent(agent, agentStates) {
13722
14540
  log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
13723
14541
  }
13724
14542
  }
13725
- const staleChannelsPath = join29(projectDir, ".mcp-channels.json");
13726
- if (existsSync12(staleChannelsPath)) {
14543
+ const staleChannelsPath = join33(projectDir, ".mcp-channels.json");
14544
+ if (existsSync14(staleChannelsPath)) {
13727
14545
  try {
13728
14546
  rmSync5(staleChannelsPath, { force: true });
13729
14547
  } catch {
@@ -13733,7 +14551,7 @@ async function processAgent(agent, agentStates) {
13733
14551
  log(`Failed to provision direct-chat channel for '${agent.code_name}': ${err.message}`);
13734
14552
  }
13735
14553
  }
13736
- let lastSecretsProvisionAt = state6.agents.find((a) => a.agentId === agent.agent_id)?.lastSecretsProvisionAt ?? null;
14554
+ let lastSecretsProvisionAt = state7.agents.find((a) => a.agentId === agent.agent_id)?.lastSecretsProvisionAt ?? null;
13737
14555
  let secretsHash = agentState.knownSecretsHashes.get(agent.agent_id) ?? null;
13738
14556
  try {
13739
14557
  const secretsData = await api.post("/host/secrets", { agent_id: agent.agent_id });
@@ -13812,7 +14630,7 @@ async function processAgent(agent, agentStates) {
13812
14630
  }
13813
14631
  if (hostFlagStore().getBoolean("connectivity-probe")) {
13814
14632
  try {
13815
- const probeProjectDir = join29(homedir12(), ".augmented", agent.code_name, "project");
14633
+ const probeProjectDir = join33(homedir15(), ".augmented", agent.code_name, "project");
13816
14634
  let probeSet = integrations;
13817
14635
  try {
13818
14636
  const quarantined = await api.post("/host/agent-integrations/quarantined", { agent_id: agent.agent_id });
@@ -13858,7 +14676,7 @@ async function processAgent(agent, agentStates) {
13858
14676
  const forceDue = attemptsLeft > 0;
13859
14677
  let probeRan = false;
13860
14678
  try {
13861
- const probeProjectDir = join29(homedir12(), ".augmented", agent.code_name, "project");
14679
+ const probeProjectDir = join33(homedir15(), ".augmented", agent.code_name, "project");
13862
14680
  probeRan = await runAgentSessionToolBindProbes(agent, integrations, probeProjectDir, { forceDue });
13863
14681
  } catch (err) {
13864
14682
  log(`Session-tool-bind probe failed for '${agent.code_name}': ${err.message}`);
@@ -13935,11 +14753,11 @@ async function processAgent(agent, agentStates) {
13935
14753
  const intHash = computeIntegrationsHash(integrations);
13936
14754
  const prevIntHash = agentState.knownIntegrationHashes.get(agent.agent_id);
13937
14755
  if (intHash !== prevIntHash) {
13938
- const projectDir = join29(homedir12(), ".augmented", agent.code_name, "project");
13939
- const envIntPath = join29(projectDir, ".env.integrations");
14756
+ const projectDir = join33(homedir15(), ".augmented", agent.code_name, "project");
14757
+ const envIntPath = join33(projectDir, ".env.integrations");
13940
14758
  let preWriteEnv;
13941
14759
  try {
13942
- preWriteEnv = readFileSync22(envIntPath, "utf-8");
14760
+ preWriteEnv = readFileSync26(envIntPath, "utf-8");
13943
14761
  } catch {
13944
14762
  preWriteEnv = void 0;
13945
14763
  }
@@ -13958,9 +14776,9 @@ async function processAgent(agent, agentStates) {
13958
14776
  }
13959
14777
  if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
13960
14778
  try {
13961
- const projectMcpPath = join29(projectDir, ".mcp.json");
13962
- const postWriteEnv = readFileSync22(envIntPath, "utf-8");
13963
- const mcpContent = readFileSync22(projectMcpPath, "utf-8");
14779
+ const projectMcpPath = join33(projectDir, ".mcp.json");
14780
+ const postWriteEnv = readFileSync26(envIntPath, "utf-8");
14781
+ const mcpContent = readFileSync26(projectMcpPath, "utf-8");
13964
14782
  const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
13965
14783
  const mcpJsonForReap = JSON.parse(mcpContent);
13966
14784
  const affectedServerKeys = findMcpServersUsingVars(mcpJsonForReap, changedVars);
@@ -14051,10 +14869,10 @@ async function processAgent(agent, agentStates) {
14051
14869
  desiredEntries.push({ serverId, url, headers: mcpHeaders, name: tk.toolkit_name });
14052
14870
  }
14053
14871
  const hashBasis = desiredEntries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => {
14054
- const headersHash = createHash16("sha256").update(canonicalJson(e.headers ?? {})).digest("hex").slice(0, 16);
14872
+ const headersHash = createHash17("sha256").update(canonicalJson(e.headers ?? {})).digest("hex").slice(0, 16);
14055
14873
  return `${e.serverId}|${e.url}|${headersHash}`;
14056
14874
  }).join("\n");
14057
- const mcpHash = createHash16("sha256").update(hashBasis).digest("hex").slice(0, 16);
14875
+ const mcpHash = createHash17("sha256").update(hashBasis).digest("hex").slice(0, 16);
14058
14876
  const prevMcpHash = agentState.knownManagedMcpHashes.get(agent.agent_id);
14059
14877
  const structureHash = managedMcpStructureHash(desiredEntries);
14060
14878
  const prevStructureHash = agentState.knownManagedMcpStructure.get(agent.agent_id);
@@ -14069,7 +14887,7 @@ async function processAgent(agent, agentStates) {
14069
14887
  if (mcpHash !== prevMcpHash) {
14070
14888
  for (const e of desiredEntries) {
14071
14889
  frameworkAdapter.writeMcpServer(agent.code_name, e.serverId, { url: e.url, headers: e.headers });
14072
- const urlHash = createHash16("sha256").update(e.url).digest("hex").slice(0, 12);
14890
+ const urlHash = createHash17("sha256").update(e.url).digest("hex").slice(0, 12);
14073
14891
  log(`[managed-toolkit] ${agent.code_name}: wrote '${e.name}' (serverId=${e.serverId}, url_hash=${urlHash})`);
14074
14892
  }
14075
14893
  if (frameworkAdapter.removeMcpServer && frameworkAdapter.readMcpServers) {
@@ -14171,7 +14989,7 @@ async function processAgent(agent, agentStates) {
14171
14989
  if (frameworkAdapter.installSkillFiles) {
14172
14990
  const currentIntegrationSkillIds = /* @__PURE__ */ new Set();
14173
14991
  const installedIntegrationSkills = [];
14174
- const { createHash: createHash17 } = await import("crypto");
14992
+ const { createHash: createHash18 } = await import("crypto");
14175
14993
  const refreshAny = refreshData;
14176
14994
  const contexts = refreshAny.integration_contexts ?? refreshAny.plugin_contexts ?? [];
14177
14995
  const contextBySlug = /* @__PURE__ */ new Map();
@@ -14200,7 +15018,7 @@ async function processAgent(agent, agentStates) {
14200
15018
  )
14201
15019
  }));
14202
15020
  const bundle = buildIntegrationBundle(renderedScopes);
14203
- const contentHash = createHash17("sha256").update(bundleFingerprint(bundle.files)).digest("hex").slice(0, 12);
15021
+ const contentHash = createHash18("sha256").update(bundleFingerprint(bundle.files)).digest("hex").slice(0, 12);
14204
15022
  if (!shouldWriteIntegrationSkill(
14205
15023
  agentState.knownSkillHashes,
14206
15024
  agent.agent_id,
@@ -14223,23 +15041,23 @@ async function processAgent(agent, agentStates) {
14223
15041
  }
14224
15042
  }
14225
15043
  try {
14226
- const { readdirSync: readdirSync9, rmSync: rmSync6 } = await import("fs");
14227
- const { homedir: homedir13 } = await import("os");
15044
+ const { readdirSync: readdirSync10, rmSync: rmSync6 } = await import("fs");
15045
+ const { homedir: homedir16 } = await import("os");
14228
15046
  const frameworkId2 = frameworkAdapter.id;
14229
15047
  const candidateSkillDirs = [
14230
15048
  // Claude Code — framework runtime tree
14231
- join29(homedir13(), ".augmented", agent.code_name, "skills"),
15049
+ join33(homedir16(), ".augmented", agent.code_name, "skills"),
14232
15050
  // Claude Code — project tree
14233
- join29(homedir13(), ".augmented", agent.code_name, "project", ".claude", "skills"),
15051
+ join33(homedir16(), ".augmented", agent.code_name, "project", ".claude", "skills"),
14234
15052
  // Defensive: legacy provision-side path, not currently an
14235
15053
  // install target but cheap to sweep.
14236
- join29(agentDir, ".claude", "skills")
15054
+ join33(agentDir, ".claude", "skills")
14237
15055
  ];
14238
- const existingDirs = candidateSkillDirs.filter((d) => existsSync12(d));
15056
+ const existingDirs = candidateSkillDirs.filter((d) => existsSync14(d));
14239
15057
  const discoveredEntries = /* @__PURE__ */ new Set();
14240
15058
  for (const dir of existingDirs) {
14241
15059
  try {
14242
- for (const entry of readdirSync9(dir)) {
15060
+ for (const entry of readdirSync10(dir)) {
14243
15061
  if (entry.startsWith("plugin-") || entry.startsWith("integration-")) {
14244
15062
  discoveredEntries.add(entry);
14245
15063
  }
@@ -14254,7 +15072,7 @@ async function processAgent(agent, agentStates) {
14254
15072
  entry,
14255
15073
  dirs: existingDirs,
14256
15074
  removeDir: (p) => {
14257
- if (existsSync12(p)) {
15075
+ if (existsSync14(p)) {
14258
15076
  rmSync6(p, { recursive: true, force: true });
14259
15077
  }
14260
15078
  }
@@ -14274,7 +15092,7 @@ async function processAgent(agent, agentStates) {
14274
15092
  const sharedSkillsPayload = refreshAny.shared_skills;
14275
15093
  const desiredResolved = globalSkillsPayload !== void 0 || sharedSkillsPayload !== void 0;
14276
15094
  const manifestPath = managedSkillManifestPath(
14277
- join29(homedir12(), ".augmented", agent.code_name)
15095
+ join33(homedir15(), ".augmented", agent.code_name)
14278
15096
  );
14279
15097
  const prevIds = /* @__PURE__ */ new Set([
14280
15098
  ...agentState.knownGlobalSkillIds.get(agent.agent_id) ?? /* @__PURE__ */ new Set(),
@@ -14283,7 +15101,7 @@ async function processAgent(agent, agentStates) {
14283
15101
  const plan = planGlobalSkillSync(
14284
15102
  [...globalSkillsPayload ?? [], ...sharedSkillsPayload ?? []],
14285
15103
  prevIds,
14286
- (content) => createHash17("sha256").update(content).digest("hex").slice(0, 12),
15104
+ (content) => createHash18("sha256").update(content).digest("hex").slice(0, 12),
14287
15105
  (skillId) => agentState.knownSkillHashes.get(`global-skill:${agent.agent_id}:${skillId}`),
14288
15106
  { desiredResolved }
14289
15107
  );
@@ -14294,15 +15112,15 @@ async function processAgent(agent, agentStates) {
14294
15112
  }
14295
15113
  if (plan.removes.length) {
14296
15114
  const globalSkillDirs = [
14297
- join29(homedir12(), ".augmented", agent.code_name, "skills"),
14298
- join29(homedir12(), ".augmented", agent.code_name, "project", ".claude", "skills"),
14299
- join29(agentDir, ".claude", "skills")
15115
+ join33(homedir15(), ".augmented", agent.code_name, "skills"),
15116
+ join33(homedir15(), ".augmented", agent.code_name, "project", ".claude", "skills"),
15117
+ join33(agentDir, ".claude", "skills")
14300
15118
  ];
14301
15119
  for (const id of plan.removes) {
14302
15120
  let prunedAny = false;
14303
15121
  for (const dir of globalSkillDirs) {
14304
- const p = join29(dir, id);
14305
- if (existsSync12(p) && existsSync12(join29(p, "SKILL.md"))) {
15122
+ const p = join33(dir, id);
15123
+ if (existsSync14(p) && existsSync14(join33(p, "SKILL.md"))) {
14306
15124
  rmSync5(p, { recursive: true, force: true });
14307
15125
  prunedAny = true;
14308
15126
  }
@@ -14334,7 +15152,7 @@ async function processAgent(agent, agentStates) {
14334
15152
  const slug = hook.integration_slug ?? hook.plugin_slug;
14335
15153
  if (!slug) continue;
14336
15154
  try {
14337
- const scriptHash = createHash17("sha256").update(hook.script).digest("hex").slice(0, 12);
15155
+ const scriptHash = createHash18("sha256").update(hook.script).digest("hex").slice(0, 12);
14338
15156
  const hookKey = `${agent.agent_id}:${frameworkAdapter.id}:plugin-hook:${slug}:on_install`;
14339
15157
  if (agentState.knownSkillHashes.get(hookKey) === scriptHash) continue;
14340
15158
  const result = await frameworkAdapter.executePluginHook({
@@ -14349,9 +15167,9 @@ async function processAgent(agent, agentStates) {
14349
15167
  } else if (result.timedOut) {
14350
15168
  log(`Integration hook on_install '${slug}' TIMED OUT for '${agent.code_name}' after ${result.durationMs}ms`);
14351
15169
  } else {
14352
- const stderrHash = createHash17("sha256").update(result.stderr).digest("hex").slice(0, 12);
15170
+ const stderrHash = createHash18("sha256").update(result.stderr).digest("hex").slice(0, 12);
14353
15171
  const missingCmd = result.exitCode === 127 ? extractCommandNotFound(result.stderr) : null;
14354
- const missingCmdHash = missingCmd ? createHash17("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
15172
+ const missingCmdHash = missingCmd ? createHash18("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
14355
15173
  log(
14356
15174
  `Integration hook on_install '${slug}' exited ${result.exitCode} for '${agent.code_name}' ` + (missingCmdHash ? `[missing_command_hash=${missingCmdHash}] ` : "") + `[stderr_hash=${stderrHash} stderr_len=${result.stderr.length}]`
14357
15175
  );
@@ -14504,10 +15322,7 @@ async function processAgent(agent, agentStates) {
14504
15322
  log(
14505
15323
  `[persistent-session-decision] agent=${agent.code_name} decision=${psResult.decision} spawn_attempted=${psResult.spawnAttempted} session_healthy_after=${psResult.sessionHealthyAfter}${detailSuffix}`
14506
15324
  );
14507
- lastSpawnOutcomeByAgent.set(agent.code_name, {
14508
- spawnAttempted: psResult.spawnAttempted,
14509
- sessionHealthyAfter: psResult.sessionHealthyAfter
14510
- });
15325
+ recordSpawnOutcome(agent.code_name, psResult);
14511
15326
  const stuck = persistentSessionStuckTracker.record({
14512
15327
  codeName: agent.code_name,
14513
15328
  sessionHealthy: psResult.sessionHealthyAfter,
@@ -14537,8 +15352,8 @@ async function processAgent(agent, agentStates) {
14537
15352
  const sess = getSessionState(agent.code_name);
14538
15353
  let mcpJsonParsed = null;
14539
15354
  try {
14540
- const mcpPath = join29(getProjectDir(agent.code_name), ".mcp.json");
14541
- mcpJsonParsed = JSON.parse(readFileSync22(mcpPath, "utf-8"));
15355
+ const mcpPath = join33(getProjectDir(agent.code_name), ".mcp.json");
15356
+ mcpJsonParsed = JSON.parse(readFileSync26(mcpPath, "utf-8"));
14542
15357
  } catch {
14543
15358
  }
14544
15359
  reapMissingMcpSessions({
@@ -14968,10 +15783,10 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
14968
15783
  }
14969
15784
  }
14970
15785
  const trackedFiles = frameworkAdapter.driftTrackedFiles();
14971
- if (trackedFiles.length > 0 && existsSync12(agentDir)) {
15786
+ if (trackedFiles.length > 0 && existsSync14(agentDir)) {
14972
15787
  const hashes = /* @__PURE__ */ new Map();
14973
15788
  for (const file of trackedFiles) {
14974
- const h = hashFile(join29(agentDir, file));
15789
+ const h = hashFile(join33(agentDir, file));
14975
15790
  if (h) hashes.set(file, h);
14976
15791
  }
14977
15792
  agentState.writtenHashes.set(agent.agent_id, hashes);
@@ -14986,7 +15801,7 @@ Retried to the limit after repeated stalls \u2014 needs a look.`).catch(() => {
14986
15801
  refreshData.agent.onboarding_state
14987
15802
  );
14988
15803
  const obStep = obState.step;
14989
- const markerPath = join29(homedir12(), ".augmented", agent.code_name, "onboarding-drive.json");
15804
+ const markerPath = join33(homedir15(), ".augmented", agent.code_name, "onboarding-drive.json");
14990
15805
  const marker = readOnboardingDriveMarker(markerPath);
14991
15806
  const decision = decideOnboardingDrive(obStep, marker, Date.now(), obState.generation ?? 0);
14992
15807
  if (decision.clearMarker) {
@@ -15074,7 +15889,7 @@ async function ensureOpencodeRuntime(agent, refreshData, agentTimezone) {
15074
15889
  }
15075
15890
  stopOpencodeSlackIngest(codeName, log);
15076
15891
  stopOpencodeTelegramIngest(codeName, log);
15077
- const opencodeProjectDir = join29(getFramework("opencode").getAgentDir(codeName), "provision");
15892
+ const opencodeProjectDir = join33(getFramework("opencode").getAgentDir(codeName), "provision");
15078
15893
  const serveEnv = {
15079
15894
  AGT_HOST: requireHost(),
15080
15895
  AGT_API_KEY: getApiKey() ?? void 0,
@@ -15129,8 +15944,8 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
15129
15944
  });
15130
15945
  }
15131
15946
  const projectDir = getProjectDir(codeName);
15132
- const mcpConfigPath = join29(projectDir, ".mcp.json");
15133
- const claudeMdPath = join29(projectDir, "CLAUDE.md");
15947
+ const mcpConfigPath = join33(projectDir, ".mcp.json");
15948
+ const claudeMdPath = join33(projectDir, "CLAUDE.md");
15134
15949
  if (restartBreaker.isTripped(codeName)) {
15135
15950
  const trip = restartBreaker.getTrip(codeName);
15136
15951
  return {
@@ -15341,7 +16156,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
15341
16156
  const ctx = getLastFailureContext(codeName);
15342
16157
  const recovery = prepareForRespawn(codeName);
15343
16158
  const tailSummary = !ctx.tail ? "" : KNOWN_SAFE_TAIL_SIGNATURES.has(ctx.signature) ? `; last pane output (${PANE_TAIL_PREVIEW_LINES} of ~20 lines):
15344
- ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash16("sha256").update(ctx.tail).digest("hex").slice(0, 12)} (raw at ~/.augmented/${codeName}/pane.log)`;
16159
+ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash17("sha256").update(ctx.tail).digest("hex").slice(0, 12)} (raw at ~/.augmented/${codeName}/pane.log)`;
15345
16160
  const sigSummary = ctx.signature !== "unknown" ? `; signature=${ctx.signature}` : "";
15346
16161
  const recoverySummary = recovery ? `; recovery=${recovery}` : "";
15347
16162
  log(
@@ -15355,7 +16170,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash16("sha256")
15355
16170
  );
15356
16171
  getHostId().then((hostId) => {
15357
16172
  if (!hostId) return;
15358
- const paneTailHash = zombie.paneTail ? `sha256:${createHash16("sha256").update(zombie.paneTail).digest("hex").slice(0, 12)}` : null;
16173
+ const paneTailHash = zombie.paneTail ? `sha256:${createHash17("sha256").update(zombie.paneTail).digest("hex").slice(0, 12)}` : null;
15359
16174
  return api.post("/host/events", {
15360
16175
  host_id: hostId,
15361
16176
  agent_code_name: codeName,
@@ -15510,7 +16325,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash16("sha256")
15510
16325
  if (!claudeAuthTupleBySession.has(codeName)) {
15511
16326
  claudeAuthTupleBySession.set(codeName, currentAuthTuple);
15512
16327
  }
15513
- const stableTasksHash = createHash16("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
16328
+ const stableTasksHash = createHash17("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
15514
16329
  const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
15515
16330
  if (stableTasksHash !== prevHash) {
15516
16331
  const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
@@ -15521,9 +16336,9 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash16("sha256")
15521
16336
  } else if (!claudeSchedulerStates.has(codeName)) {
15522
16337
  claudeSchedulerStates.set(codeName, loadSchedulerState(codeName));
15523
16338
  }
15524
- const state7 = claudeSchedulerStates.get(codeName);
15525
- if (state7) {
15526
- const ready = getReadyTasks(state7, inFlightClaudeTasks);
16339
+ const state8 = claudeSchedulerStates.get(codeName);
16340
+ if (state8) {
16341
+ const ready = getReadyTasks(state8, inFlightClaudeTasks);
15527
16342
  if (ready.length > 0) {
15528
16343
  log(`[persistent-session] ${ready.length} ready task(s) for '${codeName}': ${ready.map((t) => `${t.name}(next=${t.nextFireAt ? new Date(t.nextFireAt).toISOString() : "null"})`).join(", ")}`);
15529
16344
  }
@@ -15711,7 +16526,7 @@ function restartReasonStampsTiming(reason) {
15711
16526
  return reason === "integration-change";
15712
16527
  }
15713
16528
  async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
15714
- const prev = state6.agents.find((a) => a.agentId === agentId);
16529
+ const prev = state7.agents.find((a) => a.agentId === agentId);
15715
16530
  const codeName = prev?.codeName;
15716
16531
  if (!codeName) return;
15717
16532
  const lastProcessed = prev?.lastRestartProcessedAt ?? null;
@@ -15754,6 +16569,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
15754
16569
  [],
15755
16570
  refreshData
15756
16571
  );
16572
+ recordSpawnOutcome(codeName, result);
15757
16573
  if (result.decision !== "spawn" || !result.sessionHealthyAfter) {
15758
16574
  log(`[restart-lane] respawn not confirmed for '${codeName}' (decision=${result.decision}) - leaving for slow poll`);
15759
16575
  return;
@@ -15761,10 +16577,10 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
15761
16577
  void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
15762
16578
  void (async () => {
15763
16579
  try {
15764
- const { collectDiagnostics } = await import("../persistent-session-MLLLDI5U.js");
16580
+ const { collectDiagnostics } = await import("../persistent-session-DVTSZAPE.js");
15765
16581
  await api.post("/host/heartbeat", {
15766
16582
  host_id: hostId,
15767
- agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
16583
+ agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics)
15768
16584
  });
15769
16585
  } catch (err) {
15770
16586
  log(`[restart-lane] post-respawn diagnostics flush failed for '${codeName}': ${err.message}`);
@@ -15772,7 +16588,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
15772
16588
  })();
15773
16589
  prev.lastRestartProcessedAt = requestedAt;
15774
16590
  try {
15775
- atomicWriteFileSync(getStateFile(), JSON.stringify(state6, null, 2));
16591
+ atomicWriteFileSync(getStateFile(), JSON.stringify(state7, null, 2));
15776
16592
  } catch (err) {
15777
16593
  log(`[restart-lane] failed to persist ack for '${codeName}': ${err.message}`);
15778
16594
  }
@@ -15782,7 +16598,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
15782
16598
  }
15783
16599
  }
15784
16600
  async function respawnAgentAfterMcpStop(codeName, reason) {
15785
- const prev = state6.agents.find((a) => a.codeName === codeName);
16601
+ const prev = state7.agents.find((a) => a.codeName === codeName);
15786
16602
  if (!prev) return;
15787
16603
  const agentId = prev.agentId;
15788
16604
  if (restartInFlight.has(agentId)) return;
@@ -15803,6 +16619,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
15803
16619
  [],
15804
16620
  refreshData
15805
16621
  );
16622
+ recordSpawnOutcome(codeName, result);
15806
16623
  if (result.decision !== "spawn" || !result.sessionHealthyAfter) {
15807
16624
  log(
15808
16625
  `[fast-mcp-respawn] respawn not confirmed for '${codeName}' (decision=${result.decision}) - leaving for slow poll`
@@ -15811,10 +16628,10 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
15811
16628
  }
15812
16629
  try {
15813
16630
  const hostId = await getHostId();
15814
- const { collectDiagnostics } = await import("../persistent-session-MLLLDI5U.js");
16631
+ const { collectDiagnostics } = await import("../persistent-session-DVTSZAPE.js");
15815
16632
  await api.post("/host/heartbeat", {
15816
16633
  host_id: hostId,
15817
- agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
16634
+ agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics)
15818
16635
  });
15819
16636
  } catch (err) {
15820
16637
  log(`[fast-mcp-respawn] post-respawn diagnostics flush failed for '${codeName}': ${err.message}`);
@@ -15919,7 +16736,7 @@ function ensureRealtimeKanbanStarted(agentStates) {
15919
16736
  );
15920
16737
  }
15921
16738
  }).catch((err) => {
15922
- const errId = createHash16("sha256").update(err instanceof Error ? err.message : String(err)).digest("hex").slice(0, 12);
16739
+ const errId = createHash17("sha256").update(err instanceof Error ? err.message : String(err)).digest("hex").slice(0, 12);
15923
16740
  log(
15924
16741
  `[realtime] Work trigger enqueue threw for '${agent.codeName}' item_id=${item.id} error_id=${errId} \u2014 hybrid nudge will retry`
15925
16742
  );
@@ -16073,7 +16890,7 @@ async function processDirectChatMessageOpencode(agent, msg) {
16073
16890
  body
16074
16891
  });
16075
16892
  recordCursorAdvanceOutcome(
16076
- dirname8(paneLogPath(agent.codeName)),
16893
+ dirname9(paneLogPath(agent.codeName)),
16077
16894
  "direct-chat-manager",
16078
16895
  "reply",
16079
16896
  verdict
@@ -16103,7 +16920,7 @@ async function processDirectChatMessageOpencode(agent, msg) {
16103
16920
  } catch (err) {
16104
16921
  if (!recorded) {
16105
16922
  recordCursorAdvanceOutcome(
16106
- dirname8(paneLogPath(agent.codeName)),
16923
+ dirname9(paneLogPath(agent.codeName)),
16107
16924
  "direct-chat-manager",
16108
16925
  "reply",
16109
16926
  { outcome: "failed", error: err.message, expected: 1 }
@@ -16154,9 +16971,9 @@ async function processDirectChatMessage(agent, msg) {
16154
16971
  const useDoorbell = hostFlagStore().getBoolean("direct-chat-doorbell") || isolationMode(agent.codeName) === "docker";
16155
16972
  if (useDoorbell) {
16156
16973
  try {
16157
- const doorbell = directChatDoorbellPath(agent.agentId, homedir12());
16158
- mkdirSync10(dirname8(doorbell), { recursive: true });
16159
- writeFileSync13(doorbell, String(Date.now()));
16974
+ const doorbell = directChatDoorbellPath(agent.agentId, homedir15());
16975
+ mkdirSync11(dirname9(doorbell), { recursive: true });
16976
+ writeFileSync14(doorbell, String(Date.now()));
16160
16977
  log(`[direct-chat] Doorbell rung for '${agent.codeName}' (msg=${msg.id}) \u2014 in-session MCP will pull via the cursor`);
16161
16978
  return;
16162
16979
  } catch (err) {
@@ -16205,10 +17022,10 @@ function getKanbanNudgeState(codeName) {
16205
17022
  function loadKanbanNudgeStateFromDisk() {
16206
17023
  loadKanbanNudgeState(kanbanNudgeStateByCode, channelHashCacheDir());
16207
17024
  }
16208
- function setKanbanNudgeState(codeName, state7) {
17025
+ function setKanbanNudgeState(codeName, state8) {
16209
17026
  const key = kanbanNudgeStateKey(codeName);
16210
17027
  if (key !== codeName) kanbanNudgeStateByCode.delete(codeName);
16211
- kanbanNudgeStateByCode.set(key, state7);
17028
+ kanbanNudgeStateByCode.set(key, state8);
16212
17029
  saveKanbanNudgeState(kanbanNudgeStateByCode, channelHashCacheDir());
16213
17030
  }
16214
17031
  function clearKanbanNudgeState(codeName) {
@@ -16283,9 +17100,9 @@ ${formatRunMarker(run_id)}` : KANBAN_CHECK_COMMAND;
16283
17100
  }
16284
17101
  if (run_id) openInjectedRunByCode.set(codeName, run_id);
16285
17102
  try {
16286
- const doorbell = directChatDoorbellPath(agentId, homedir12());
16287
- mkdirSync10(dirname8(doorbell), { recursive: true });
16288
- writeFileSync13(doorbell, String(Date.now()));
17103
+ const doorbell = directChatDoorbellPath(agentId, homedir15());
17104
+ mkdirSync11(dirname9(doorbell), { recursive: true });
17105
+ writeFileSync14(doorbell, String(Date.now()));
16289
17106
  } catch (err) {
16290
17107
  log(`[kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
16291
17108
  }
@@ -16389,7 +17206,7 @@ async function processClaudePairSessions(agents) {
16389
17206
  killPairSession,
16390
17207
  pairTmuxSession,
16391
17208
  finalizeClaudePairOnboarding
16392
- } = await import("../claude-pair-runtime-63Y4MIMU.js");
17209
+ } = await import("../claude-pair-runtime-4C5NQQHR.js");
16393
17210
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
16394
17211
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
16395
17212
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -16643,8 +17460,8 @@ function parseMemoryFile(raw, fallbackName) {
16643
17460
  };
16644
17461
  }
16645
17462
  async function syncMemories(agent, configDir, log2) {
16646
- const projectDir = join29(configDir, agent.code_name, "project");
16647
- const memoryDir = join29(projectDir, "memory");
17463
+ const projectDir = join33(configDir, agent.code_name, "project");
17464
+ const memoryDir = join33(projectDir, "memory");
16648
17465
  const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
16649
17466
  if (isFreshSync) {
16650
17467
  log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
@@ -16655,15 +17472,15 @@ async function syncMemories(agent, configDir, log2) {
16655
17472
  }
16656
17473
  pendingFreshMemorySync.delete(agent.agent_id);
16657
17474
  }
16658
- if (existsSync12(memoryDir)) {
17475
+ if (existsSync14(memoryDir)) {
16659
17476
  const prevHashes = memoryFileHashes.get(agent.agent_id) ?? /* @__PURE__ */ new Map();
16660
17477
  const currentHashes = /* @__PURE__ */ new Map();
16661
17478
  const changedMemories = [];
16662
- for (const file of readdirSync8(memoryDir)) {
17479
+ for (const file of readdirSync9(memoryDir)) {
16663
17480
  if (!file.endsWith(".md")) continue;
16664
17481
  try {
16665
- const raw = readFileSync22(join29(memoryDir, file), "utf-8");
16666
- const fileHash = createHash16("sha256").update(raw).digest("hex").slice(0, 16);
17482
+ const raw = readFileSync26(join33(memoryDir, file), "utf-8");
17483
+ const fileHash = createHash17("sha256").update(raw).digest("hex").slice(0, 16);
16667
17484
  currentHashes.set(file, fileHash);
16668
17485
  if (prevHashes.get(file) === fileHash) continue;
16669
17486
  const parsed = parseMemoryFile(raw, file.replace(/\.md$/, ""));
@@ -16687,7 +17504,7 @@ async function syncMemories(agent, configDir, log2) {
16687
17504
  } catch (err) {
16688
17505
  for (const mem of changedMemories) {
16689
17506
  for (const [file] of currentHashes) {
16690
- const parsed = parseMemoryFile(readFileSync22(join29(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
17507
+ const parsed = parseMemoryFile(readFileSync26(join33(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
16691
17508
  if (parsed?.name === mem.name) currentHashes.delete(file);
16692
17509
  }
16693
17510
  }
@@ -16700,29 +17517,29 @@ async function syncMemories(agent, configDir, log2) {
16700
17517
  }
16701
17518
  }
16702
17519
  async function downloadMemories(agent, memoryDir, log2, { force }) {
16703
- const localFiles = existsSync12(memoryDir) ? readdirSync8(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
16704
- const localListHash = createHash16("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
17520
+ const localFiles = existsSync14(memoryDir) ? readdirSync9(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
17521
+ const localListHash = createHash17("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
16705
17522
  const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
16706
17523
  const prevDownload = lastDownloadHash.get(agent.agent_id);
16707
17524
  try {
16708
17525
  const dbMemories = await api.post("/host/memories", {
16709
17526
  agent_id: agent.agent_id
16710
17527
  });
16711
- const responseHash = createHash16("sha256").update(JSON.stringify(dbMemories.memories ?? [])).digest("hex").slice(0, 16);
17528
+ const responseHash = createHash17("sha256").update(JSON.stringify(dbMemories.memories ?? [])).digest("hex").slice(0, 16);
16712
17529
  if (!force && prevDownload && prevLocalHash === localListHash && lastDownloadHash.get(agent.agent_id) === responseHash) {
16713
17530
  return true;
16714
17531
  }
16715
17532
  lastDownloadHash.set(agent.agent_id, responseHash);
16716
17533
  lastLocalFileHash.set(agent.agent_id, localListHash);
16717
17534
  if (dbMemories.memories?.length) {
16718
- mkdirSync10(memoryDir, { recursive: true });
17535
+ mkdirSync11(memoryDir, { recursive: true });
16719
17536
  let written = 0;
16720
17537
  let overwritten = 0;
16721
17538
  for (let i = 0; i < dbMemories.memories.length; i++) {
16722
17539
  const mem = dbMemories.memories[i];
16723
17540
  const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
16724
17541
  const slug = rawSlug || `memory-${i}`;
16725
- const filePath = join29(memoryDir, `${slug}.md`);
17542
+ const filePath = join33(memoryDir, `${slug}.md`);
16726
17543
  const desired = `---
16727
17544
  name: ${JSON.stringify(mem.name)}
16728
17545
  type: ${mem.type}
@@ -16731,23 +17548,23 @@ description: ${JSON.stringify(mem.content.slice(0, 200))}
16731
17548
 
16732
17549
  ${mem.content}
16733
17550
  `;
16734
- if (existsSync12(filePath)) {
17551
+ if (existsSync14(filePath)) {
16735
17552
  let existing = "";
16736
17553
  try {
16737
- existing = readFileSync22(filePath, "utf-8");
17554
+ existing = readFileSync26(filePath, "utf-8");
16738
17555
  } catch {
16739
17556
  }
16740
17557
  if (existing === desired) continue;
16741
- writeFileSync13(filePath, desired);
17558
+ writeFileSync14(filePath, desired);
16742
17559
  overwritten++;
16743
17560
  } else {
16744
- writeFileSync13(filePath, desired);
17561
+ writeFileSync14(filePath, desired);
16745
17562
  written++;
16746
17563
  }
16747
17564
  }
16748
17565
  if (written > 0 || overwritten > 0) {
16749
- const updatedFiles = readdirSync8(memoryDir).filter((f) => f.endsWith(".md")).sort();
16750
- lastLocalFileHash.set(agent.agent_id, createHash16("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
17566
+ const updatedFiles = readdirSync9(memoryDir).filter((f) => f.endsWith(".md")).sort();
17567
+ lastLocalFileHash.set(agent.agent_id, createHash17("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
16751
17568
  log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
16752
17569
  }
16753
17570
  }
@@ -16758,7 +17575,7 @@ ${mem.content}
16758
17575
  }
16759
17576
  }
16760
17577
  async function cleanupAgentFiles(codeName, agentDir) {
16761
- if (existsSync12(agentDir)) {
17578
+ if (existsSync14(agentDir)) {
16762
17579
  try {
16763
17580
  rmSync5(agentDir, { recursive: true, force: true });
16764
17581
  log(`Removed provision directory for '${codeName}'`);
@@ -16821,7 +17638,7 @@ async function driveArtifactStreaming() {
16821
17638
  }
16822
17639
  async function driveArtifactStreamingInner() {
16823
17640
  const liveIds = /* @__PURE__ */ new Set();
16824
- for (const agent of state6.agents) {
17641
+ for (const agent of state7.agents) {
16825
17642
  if (!agent.agentId || !agent.codeName || agent.status !== "active") continue;
16826
17643
  liveIds.add(agent.agentId);
16827
17644
  let scanner = artifactScanners.get(agent.agentId);
@@ -16997,12 +17814,12 @@ function startManager(opts) {
16997
17814
  config = opts;
16998
17815
  try {
16999
17816
  const stateFile = getStateFile();
17000
- if (existsSync12(stateFile)) {
17001
- const raw = readFileSync22(stateFile, "utf-8");
17817
+ if (existsSync14(stateFile)) {
17818
+ const raw = readFileSync26(stateFile, "utf-8");
17002
17819
  const parsed = JSON.parse(raw);
17003
17820
  if (Array.isArray(parsed.agents)) {
17004
- state6.agents = parsed.agents;
17005
- log(`[startup] rehydrated ${state6.agents.length} agent state(s) from ${stateFile}`);
17821
+ state7.agents = parsed.agents;
17822
+ log(`[startup] rehydrated ${state7.agents.length} agent state(s) from ${stateFile}`);
17006
17823
  }
17007
17824
  if (parsed.circuitBreakerTrips && typeof parsed.circuitBreakerTrips === "object") {
17008
17825
  restartBreaker.hydrate(parsed.circuitBreakerTrips);
@@ -17015,9 +17832,9 @@ function startManager(opts) {
17015
17832
  if (n > 0) log(`[startup] rehydrated ${n} auto-resume marker(s) (ENG-6088)`);
17016
17833
  }
17017
17834
  if (typeof parsed.lastUpdateRequestProcessedAt === "string" || parsed.lastUpdateRequestProcessedAt === null) {
17018
- state6.lastUpdateRequestProcessedAt = parsed.lastUpdateRequestProcessedAt;
17019
- if (state6.lastUpdateRequestProcessedAt) {
17020
- log(`[startup] rehydrated update-request ack at ${state6.lastUpdateRequestProcessedAt} (ENG-6692)`);
17835
+ state7.lastUpdateRequestProcessedAt = parsed.lastUpdateRequestProcessedAt;
17836
+ if (state7.lastUpdateRequestProcessedAt) {
17837
+ log(`[startup] rehydrated update-request ack at ${state7.lastUpdateRequestProcessedAt} (ENG-6692)`);
17021
17838
  }
17022
17839
  }
17023
17840
  }
@@ -17025,7 +17842,7 @@ function startManager(opts) {
17025
17842
  log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
17026
17843
  }
17027
17844
  log(
17028
- `[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join29(homedir12(), ".augmented", "manager.log")}`
17845
+ `[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join33(homedir15(), ".augmented", "manager.log")}`
17029
17846
  );
17030
17847
  deployMcpAssets();
17031
17848
  reapOrphanChannelMcps({ log });
@@ -17037,7 +17854,7 @@ function startManager(opts) {
17037
17854
  }
17038
17855
  try {
17039
17856
  refreshSlackRestartContextHints(
17040
- state6.agents.map((a) => a.codeName),
17857
+ state7.agents.map((a) => a.codeName),
17041
17858
  { log }
17042
17859
  );
17043
17860
  } catch (err) {
@@ -17054,7 +17871,7 @@ async function reapOrphanedClaudePids() {
17054
17871
  const looksLikeClaude = (pid) => {
17055
17872
  if (process.platform !== "linux") return true;
17056
17873
  try {
17057
- const comm = readFileSync22(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
17874
+ const comm = readFileSync26(`/proc/${pid}/comm`, "utf-8").trim().toLowerCase();
17058
17875
  return comm.includes("claude");
17059
17876
  } catch {
17060
17877
  return false;
@@ -17151,18 +17968,18 @@ function restartRunningChannelMcps(basenames) {
17151
17968
  }
17152
17969
  }
17153
17970
  function deployMcpAssets() {
17154
- const targetDir = join29(homedir12(), ".augmented", "_mcp");
17155
- mkdirSync10(targetDir, { recursive: true });
17156
- const moduleDir = dirname8(fileURLToPath(import.meta.url));
17971
+ const targetDir = join33(homedir15(), ".augmented", "_mcp");
17972
+ mkdirSync11(targetDir, { recursive: true });
17973
+ const moduleDir = dirname9(fileURLToPath(import.meta.url));
17157
17974
  let mcpSourceDir = "";
17158
17975
  let dir = moduleDir;
17159
17976
  for (let i = 0; i < 6; i++) {
17160
- const candidate = join29(dir, "dist", "mcp");
17161
- if (existsSync12(join29(candidate, "index.js"))) {
17977
+ const candidate = join33(dir, "dist", "mcp");
17978
+ if (existsSync14(join33(candidate, "index.js"))) {
17162
17979
  mcpSourceDir = candidate;
17163
17980
  break;
17164
17981
  }
17165
- const parent = dirname8(dir);
17982
+ const parent = dirname9(dir);
17166
17983
  if (parent === dir) break;
17167
17984
  dir = parent;
17168
17985
  }
@@ -17173,8 +17990,8 @@ function deployMcpAssets() {
17173
17990
  const changedBasenames = [];
17174
17991
  const fileHash = (p) => {
17175
17992
  try {
17176
- if (!existsSync12(p)) return null;
17177
- return createHash16("sha256").update(readFileSync22(p)).digest("hex");
17993
+ if (!existsSync14(p)) return null;
17994
+ return createHash17("sha256").update(readFileSync26(p)).digest("hex");
17178
17995
  } catch {
17179
17996
  return null;
17180
17997
  }
@@ -17245,9 +18062,9 @@ function deployMcpAssets() {
17245
18062
  // needs restarting to pick up a token rotation.
17246
18063
  "xero.js"
17247
18064
  ]) {
17248
- const src = join29(mcpSourceDir, file);
17249
- const dst = join29(targetDir, file);
17250
- if (!existsSync12(src)) continue;
18065
+ const src = join33(mcpSourceDir, file);
18066
+ const dst = join33(targetDir, file);
18067
+ if (!existsSync14(src)) continue;
17251
18068
  const before = fileHash(dst);
17252
18069
  try {
17253
18070
  copyFileSync(src, dst);
@@ -17264,23 +18081,23 @@ function deployMcpAssets() {
17264
18081
  log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
17265
18082
  restartRunningChannelMcps(changedBasenames);
17266
18083
  }
17267
- const localMcpPath = join29(targetDir, "index.js");
18084
+ const localMcpPath = join33(targetDir, "index.js");
17268
18085
  try {
17269
- const agentsDir = join29(homedir12(), ".augmented", "agents");
17270
- if (existsSync12(agentsDir)) {
17271
- for (const entry of readdirSync8(agentsDir, { withFileTypes: true })) {
18086
+ const agentsDir = join33(homedir15(), ".augmented", "agents");
18087
+ if (existsSync14(agentsDir)) {
18088
+ for (const entry of readdirSync9(agentsDir, { withFileTypes: true })) {
17272
18089
  if (!entry.isDirectory()) continue;
17273
18090
  for (const subdir of ["provision", "project"]) {
17274
- const mcpJsonPath = join29(agentsDir, entry.name, subdir, ".mcp.json");
18091
+ const mcpJsonPath = join33(agentsDir, entry.name, subdir, ".mcp.json");
17275
18092
  try {
17276
- const raw = readFileSync22(mcpJsonPath, "utf-8");
18093
+ const raw = readFileSync26(mcpJsonPath, "utf-8");
17277
18094
  if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
17278
18095
  const mcpConfig = JSON.parse(raw);
17279
18096
  const augServer = mcpConfig.mcpServers?.["augmented"];
17280
18097
  if (!augServer) continue;
17281
18098
  augServer.command = "node";
17282
18099
  augServer.args = [localMcpPath];
17283
- writeFileSync13(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
18100
+ writeFileSync14(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
17284
18101
  log(`[manager] Patched ${entry.name}/${subdir}/.mcp.json: npx \u2192 node`);
17285
18102
  } catch {
17286
18103
  }