gossipcat 0.4.31 → 0.5.2

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.
@@ -734,8 +734,8 @@ var init_agent_registry = __esm({
734
734
  setPerformanceReader(reader) {
735
735
  this.perfReader = reader;
736
736
  }
737
- setSuggesterCache(cache2) {
738
- this.suggesterCache = cache2;
737
+ setSuggesterCache(cache3) {
738
+ this.suggesterCache = cache3;
739
739
  }
740
740
  getDispatchWeight(agentId) {
741
741
  if (this.perfReader?.isCircuitOpen(agentId)) return 0.3;
@@ -11407,11 +11407,11 @@ var init_performance_reader = __esm({
11407
11407
  * Returns false on any IO/parse error — recovery defaults to "no relief"
11408
11408
  * when we can't prove a skill is bound.
11409
11409
  */
11410
- hasSkillForCategory(agentId, category, cache2) {
11410
+ hasSkillForCategory(agentId, category, cache3) {
11411
11411
  if (!agentId || !category) return false;
11412
11412
  const normalizedTarget = normalizeSkillName(category);
11413
11413
  const cacheKey = agentId + "\0" + normalizedTarget;
11414
- const cached4 = cache2.get(cacheKey);
11414
+ const cached4 = cache3.get(cacheKey);
11415
11415
  if (cached4 !== void 0) return cached4;
11416
11416
  const indexMap = this.getSkillIndexEnabledMap();
11417
11417
  const agentIndex = indexMap?.[agentId];
@@ -11443,7 +11443,7 @@ var init_performance_reader = __esm({
11443
11443
  }
11444
11444
  } catch {
11445
11445
  }
11446
- cache2.set(cacheKey, result);
11446
+ cache3.set(cacheKey, result);
11447
11447
  return result;
11448
11448
  }
11449
11449
  /**
@@ -12776,9 +12776,9 @@ function deriveAggregateKey(signal, projectRoot, boundAtCache) {
12776
12776
  timestampMs: ts2
12777
12777
  };
12778
12778
  }
12779
- function resolveBoundAtMs(agentId, category, projectRoot, cache2, fallbackMs) {
12779
+ function resolveBoundAtMs(agentId, category, projectRoot, cache3, fallbackMs) {
12780
12780
  const key = agentId + "\0" + category;
12781
- const cached4 = cache2.get(key);
12781
+ const cached4 = cache3.get(key);
12782
12782
  if (cached4 !== void 0) {
12783
12783
  return cached4 === boundAtMissSentinel ? fallbackMs : cached4;
12784
12784
  }
@@ -12787,13 +12787,13 @@ function resolveBoundAtMs(agentId, category, projectRoot, cache2, fallbackMs) {
12787
12787
  if (typeof boundAt === "string" && boundAt.length > 0) {
12788
12788
  const ms = new Date(boundAt).getTime();
12789
12789
  if (isFinite(ms) && ms > 0) {
12790
- cache2.set(key, ms);
12790
+ cache3.set(key, ms);
12791
12791
  return ms;
12792
12792
  }
12793
12793
  }
12794
12794
  } catch {
12795
12795
  }
12796
- cache2.set(key, boundAtMissSentinel);
12796
+ cache3.set(key, boundAtMissSentinel);
12797
12797
  return fallbackMs;
12798
12798
  }
12799
12799
  var import_fs14, import_path15, loggedCounterErrors, MAX_TELEMETRY_BYTES, VALID_CONSENSUS_SIGNALS, VALID_IMPL_SIGNALS, VALID_META_SIGNALS, VALID_PIPELINE_SIGNALS, SYSTEM_SENTINEL_AGENT_ID, rowsWrittenSinceCheck, DRIFT_SAMPLE_INTERVAL, INTERNAL, boundAtMissSentinel, PerformanceWriter;
@@ -17366,9 +17366,9 @@ function getRuntimeFlag(key, defaultValue, registry2 = RUNTIME_FLAG_REGISTRY) {
17366
17366
  if (envVal !== void 0 && envVal !== "") {
17367
17367
  return envVal;
17368
17368
  }
17369
- const cache2 = ensureLoaded(registry2);
17370
- if (Object.prototype.hasOwnProperty.call(cache2, key)) {
17371
- return cache2[key];
17369
+ const cache3 = ensureLoaded(registry2);
17370
+ if (Object.prototype.hasOwnProperty.call(cache3, key)) {
17371
+ return cache3[key];
17372
17372
  }
17373
17373
  if (defaultValue !== void 0) {
17374
17374
  return defaultValue;
@@ -17568,10 +17568,10 @@ async function unsetRuntimeFlag(key, source, reason, registry2 = RUNTIME_FLAG_RE
17568
17568
  }
17569
17569
  }
17570
17570
  function listRuntimeFlags(registry2 = RUNTIME_FLAG_REGISTRY) {
17571
- const cache2 = ensureLoaded(registry2);
17571
+ const cache3 = ensureLoaded(registry2);
17572
17572
  return Object.entries(registry2).map(([key, spec]) => {
17573
17573
  const envVal = process.env[key];
17574
- const fileVal = Object.prototype.hasOwnProperty.call(cache2, key) ? cache2[key] : void 0;
17574
+ const fileVal = Object.prototype.hasOwnProperty.call(cache3, key) ? cache3[key] : void 0;
17575
17575
  let value;
17576
17576
  let from;
17577
17577
  if (envVal !== void 0 && envVal !== "") {
@@ -23823,8 +23823,8 @@ message: Your question?
23823
23823
  }
23824
23824
  /** Start all worker agents (connect to relay) */
23825
23825
  async start() {
23826
- const { existsSync: existsSync69, readFileSync: readFileSync62 } = await import("fs");
23827
- const { join: join82 } = await import("path");
23826
+ const { existsSync: existsSync70, readFileSync: readFileSync64 } = await import("fs");
23827
+ const { join: join83 } = await import("path");
23828
23828
  for (const config2 of this.registry.getAll()) {
23829
23829
  if (config2.native) continue;
23830
23830
  if (this.workers.has(config2.id)) continue;
@@ -23833,8 +23833,8 @@ message: Your question?
23833
23833
  apiKey = await this.keyProviderFn(config2.provider) ?? void 0;
23834
23834
  }
23835
23835
  const llm = createProvider(config2.provider, config2.model, apiKey);
23836
- const instructionsPath = join82(this.projectRoot, ".gossip", "agents", config2.id, "instructions.md");
23837
- const instructions = existsSync69(instructionsPath) ? readFileSync62(instructionsPath, "utf-8") : void 0;
23836
+ const instructionsPath = join83(this.projectRoot, ".gossip", "agents", config2.id, "instructions.md");
23837
+ const instructions = existsSync70(instructionsPath) ? readFileSync64(instructionsPath, "utf-8") : void 0;
23838
23838
  const enableWebSearch = config2.preset === "researcher" || config2.skills.includes("research");
23839
23839
  const worker = new WorkerAgent(config2.id, llm, this.relayUrl, ALL_TOOLS, instructions, enableWebSearch, this.relayApiKey);
23840
23840
  await worker.start();
@@ -24031,8 +24031,8 @@ message: Your question?
24031
24031
  this.registry.register(config2);
24032
24032
  }
24033
24033
  async syncWorkers(keyProvider) {
24034
- const { existsSync: existsSync69, readFileSync: readFileSync62 } = await import("fs");
24035
- const { join: join82 } = await import("path");
24034
+ const { existsSync: existsSync70, readFileSync: readFileSync64 } = await import("fs");
24035
+ const { join: join83 } = await import("path");
24036
24036
  let added = 0;
24037
24037
  for (const ac of this.registry.getAll()) {
24038
24038
  if (ac.native) continue;
@@ -24049,8 +24049,8 @@ message: Your question?
24049
24049
  this.workers.delete(ac.id);
24050
24050
  }
24051
24051
  const llm = createProvider(ac.provider, ac.model, key ?? void 0, void 0, ac.base_url);
24052
- const instructionsPath = join82(this.projectRoot, ".gossip", "agents", ac.id, "instructions.md");
24053
- const instructions = existsSync69(instructionsPath) ? readFileSync62(instructionsPath, "utf-8") : void 0;
24052
+ const instructionsPath = join83(this.projectRoot, ".gossip", "agents", ac.id, "instructions.md");
24053
+ const instructions = existsSync70(instructionsPath) ? readFileSync64(instructionsPath, "utf-8") : void 0;
24054
24054
  const enableWebSearch = ac.preset === "researcher" || ac.skills.includes("research");
24055
24055
  const worker = new WorkerAgent(ac.id, llm, this.relayUrl, ALL_TOOLS, instructions, enableWebSearch, this.relayApiKey);
24056
24056
  await worker.start();
@@ -30051,11 +30051,18 @@ async function overviewHandler(projectRoot, ctx2) {
30051
30051
  const now = Date.now();
30052
30052
  const hourMs = 60 * 60 * 1e3;
30053
30053
  const graphPath = (0, import_path53.join)(projectRoot, ".gossip", "task-graph.jsonl");
30054
- if ((0, import_fs49.existsSync)(graphPath)) {
30054
+ const archivePath = graphPath + ".1";
30055
+ if ((0, import_fs49.existsSync)(graphPath) || (0, import_fs49.existsSync)(archivePath)) {
30055
30056
  try {
30056
30057
  const created = /* @__PURE__ */ new Map();
30057
30058
  const finished = /* @__PURE__ */ new Set();
30058
- const lines = (0, import_fs49.readFileSync)(graphPath, "utf-8").trim().split("\n").filter(Boolean);
30059
+ const lines = [];
30060
+ if ((0, import_fs49.existsSync)(archivePath)) {
30061
+ lines.push(...(0, import_fs49.readFileSync)(archivePath, "utf-8").split("\n").filter(Boolean));
30062
+ }
30063
+ if ((0, import_fs49.existsSync)(graphPath)) {
30064
+ lines.push(...(0, import_fs49.readFileSync)(graphPath, "utf-8").split("\n").filter(Boolean));
30065
+ }
30059
30066
  for (const line of lines) {
30060
30067
  try {
30061
30068
  const ev = JSON.parse(line);
@@ -30332,11 +30339,17 @@ function readForcedDevelops(projectRoot, agentId, category) {
30332
30339
  }
30333
30340
  function readTaskGraphByAgent(projectRoot) {
30334
30341
  const taskGraphPath = (0, import_path55.join)(projectRoot, ".gossip", "task-graph.jsonl");
30342
+ const archivePath = taskGraphPath + ".1";
30335
30343
  const result = /* @__PURE__ */ new Map();
30336
- if (!(0, import_fs51.existsSync)(taskGraphPath)) return result;
30337
- let lines;
30344
+ if (!(0, import_fs51.existsSync)(taskGraphPath) && !(0, import_fs51.existsSync)(archivePath)) return result;
30345
+ let lines = [];
30338
30346
  try {
30339
- lines = (0, import_fs51.readFileSync)(taskGraphPath, "utf-8").trim().split("\n").filter(Boolean);
30347
+ if ((0, import_fs51.existsSync)(archivePath)) {
30348
+ lines.push(...(0, import_fs51.readFileSync)(archivePath, "utf-8").split("\n").filter(Boolean));
30349
+ }
30350
+ if ((0, import_fs51.existsSync)(taskGraphPath)) {
30351
+ lines.push(...(0, import_fs51.readFileSync)(taskGraphPath, "utf-8").split("\n").filter(Boolean));
30352
+ }
30340
30353
  } catch {
30341
30354
  return result;
30342
30355
  }
@@ -30531,12 +30544,206 @@ var init_api_agents = __esm({
30531
30544
  function isCorrupt(projectRoot, index) {
30532
30545
  return (0, import_fs52.existsSync)((0, import_path56.join)(projectRoot, ".gossip", "skill-index.json")) && !index.exists();
30533
30546
  }
30547
+ function readSkillFrontmatter2(projectRoot, agentId, skillName) {
30548
+ try {
30549
+ const path7 = (0, import_path56.join)(projectRoot, ".gossip", "agents", agentId, "skills", `${skillName}.md`);
30550
+ if (!(0, import_fs52.existsSync)(path7)) return null;
30551
+ const raw = (0, import_fs52.readFileSync)(path7, "utf-8");
30552
+ if (!raw.startsWith("---")) return null;
30553
+ const end = raw.indexOf("\n---", 3);
30554
+ if (end === -1) return null;
30555
+ const block = raw.slice(3, end);
30556
+ const out = {};
30557
+ for (const line of block.split("\n")) {
30558
+ const m = line.match(/^\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:\s*(.+?)\s*$/);
30559
+ if (!m) continue;
30560
+ const key = m[1];
30561
+ let value = m[2];
30562
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
30563
+ value = value.slice(1, -1);
30564
+ }
30565
+ if (key === "status") out.status = value;
30566
+ else if (key === "bound_at") out.bound_at = value;
30567
+ else if (key === "passed_baseline_rate") {
30568
+ const n = Number(value);
30569
+ if (Number.isFinite(n)) out.passed_baseline_rate = n;
30570
+ }
30571
+ }
30572
+ return out;
30573
+ } catch {
30574
+ return null;
30575
+ }
30576
+ }
30577
+ function buildSignalIndex(projectRoot) {
30578
+ const idx = { byAgentSkill: /* @__PURE__ */ new Map() };
30579
+ const perfPath = (0, import_path56.join)(projectRoot, ".gossip", "agent-performance.jsonl");
30580
+ if (!(0, import_fs52.existsSync)(perfPath)) return idx;
30581
+ let raw;
30582
+ try {
30583
+ raw = readJsonlWithRotated(perfPath);
30584
+ } catch {
30585
+ return idx;
30586
+ }
30587
+ if (!raw) return idx;
30588
+ const retracted = /* @__PURE__ */ new Set();
30589
+ const retractedConsensusIds = /* @__PURE__ */ new Set();
30590
+ const rows = [];
30591
+ for (const line of raw.split("\n")) {
30592
+ if (!line.trim()) continue;
30593
+ try {
30594
+ rows.push(JSON.parse(line));
30595
+ } catch {
30596
+ }
30597
+ }
30598
+ for (const r of rows) {
30599
+ if (r.signal === "consensus_round_retracted") {
30600
+ const cid = r.consensus_id;
30601
+ if (typeof cid === "string" && cid.length > 0) retractedConsensusIds.add(cid);
30602
+ continue;
30603
+ }
30604
+ if (r.signal === "signal_retracted") {
30605
+ const agentId = r.agentId;
30606
+ const taskKey = r.taskId ?? r.timestamp;
30607
+ const retractedSignal = r.retractedSignal;
30608
+ if (!agentId || !taskKey) continue;
30609
+ if (typeof retractedSignal === "string") {
30610
+ retracted.add(`${agentId}:${taskKey}:${retractedSignal}`);
30611
+ } else {
30612
+ retracted.add(`${agentId}:${taskKey}:*`);
30613
+ }
30614
+ }
30615
+ }
30616
+ for (const r of rows) {
30617
+ if (r.type !== "consensus") continue;
30618
+ const signal = r.signal;
30619
+ if (!signal) continue;
30620
+ if (!CORRECT_SIGNALS.has(signal) && !HALLUC_SIGNALS.has(signal)) continue;
30621
+ const agentId = r.agentId;
30622
+ const category = r.category;
30623
+ const tsStr = r.timestamp;
30624
+ if (!agentId || !category || !tsStr) continue;
30625
+ const ts2 = new Date(tsStr).getTime();
30626
+ if (!Number.isFinite(ts2) || ts2 === 0) continue;
30627
+ const taskKey = r.taskId ?? tsStr;
30628
+ if (retracted.has(`${agentId}:${taskKey}:${signal}`)) continue;
30629
+ if (retracted.has(`${agentId}:${taskKey}:*`)) continue;
30630
+ const findingId = r.findingId;
30631
+ if (typeof findingId === "string") {
30632
+ let drop = false;
30633
+ for (const cid of retractedConsensusIds) {
30634
+ if (findingId.startsWith(cid + ":")) {
30635
+ drop = true;
30636
+ break;
30637
+ }
30638
+ }
30639
+ if (drop) continue;
30640
+ }
30641
+ const skillKey = normalizeSkillName(category);
30642
+ if (!skillKey) continue;
30643
+ let perAgent = idx.byAgentSkill.get(agentId);
30644
+ if (!perAgent) {
30645
+ perAgent = /* @__PURE__ */ new Map();
30646
+ idx.byAgentSkill.set(agentId, perAgent);
30647
+ }
30648
+ let arr = perAgent.get(skillKey);
30649
+ if (!arr) {
30650
+ arr = [];
30651
+ perAgent.set(skillKey, arr);
30652
+ }
30653
+ arr.push({ ts: ts2, signal });
30654
+ }
30655
+ for (const perAgent of idx.byAgentSkill.values()) {
30656
+ for (const arr of perAgent.values()) arr.sort((a, b) => a.ts - b.ts);
30657
+ }
30658
+ return idx;
30659
+ }
30660
+ function deriveEffectiveness(projectRoot, index, signalIdx, nowMs) {
30661
+ const out = [];
30662
+ for (const agentId of index.getAgentIds()) {
30663
+ for (const slot of index.getAgentSlots(agentId)) {
30664
+ if (!slot.enabled) continue;
30665
+ const fm = readSkillFrontmatter2(projectRoot, agentId, slot.skill);
30666
+ const boundAtIso = fm?.bound_at ?? slot.boundAt;
30667
+ const boundAtMs = new Date(boundAtIso).getTime();
30668
+ if (!Number.isFinite(boundAtMs) || boundAtMs <= 0) continue;
30669
+ const windowStartMs = Math.max(boundAtMs, nowMs - WINDOW_MS2);
30670
+ const totalSpan = Math.max(nowMs - windowStartMs, NUM_BUCKETS);
30671
+ const bucketMs = totalSpan / NUM_BUCKETS;
30672
+ const events = signalIdx.byAgentSkill.get(agentId)?.get(normalizeSkillName(slot.skill)) ?? [];
30673
+ const buckets = Array.from(
30674
+ { length: NUM_BUCKETS },
30675
+ () => ({ c: 0, h: 0 })
30676
+ );
30677
+ let n = 0;
30678
+ for (const ev of events) {
30679
+ if (ev.ts < windowStartMs) continue;
30680
+ const rel = ev.ts - windowStartMs;
30681
+ let i = Math.floor(rel / bucketMs);
30682
+ if (i < 0) i = 0;
30683
+ if (i >= NUM_BUCKETS) i = NUM_BUCKETS - 1;
30684
+ if (CORRECT_SIGNALS.has(ev.signal)) buckets[i].c++;
30685
+ else if (HALLUC_SIGNALS.has(ev.signal)) buckets[i].h++;
30686
+ n++;
30687
+ }
30688
+ const curve = buckets.map((b, i) => {
30689
+ const total = b.c + b.h;
30690
+ const t = windowStartMs + (i + 1) * bucketMs;
30691
+ return { t, value: total > 0 ? b.c / total : null };
30692
+ });
30693
+ const threshold = fm?.passed_baseline_rate ?? DEFAULT_THRESHOLD;
30694
+ const status = fm?.status ?? null;
30695
+ out.push({
30696
+ agentId,
30697
+ skill: slot.skill,
30698
+ status,
30699
+ curve,
30700
+ threshold,
30701
+ n,
30702
+ boundAt: boundAtIso
30703
+ });
30704
+ }
30705
+ }
30706
+ return out;
30707
+ }
30708
+ function jsonlMtime(projectRoot) {
30709
+ try {
30710
+ return (0, import_fs52.statSync)((0, import_path56.join)(projectRoot, ".gossip", "agent-performance.jsonl")).mtimeMs;
30711
+ } catch {
30712
+ return 0;
30713
+ }
30714
+ }
30715
+ function cacheHit(projectRoot, nowMs) {
30716
+ const entry = cache2.get(projectRoot);
30717
+ if (!entry) return null;
30718
+ if (nowMs - entry.builtAtMs > CACHE_TTL_MS) return null;
30719
+ if (entry.jsonlMtimeMs !== jsonlMtime(projectRoot)) return null;
30720
+ return entry.payload;
30721
+ }
30534
30722
  async function skillsGetHandler(projectRoot) {
30723
+ const nowMs = Date.now();
30724
+ const cached4 = cacheHit(projectRoot, nowMs);
30725
+ if (cached4) return cached4;
30535
30726
  try {
30536
30727
  const index = new SkillIndex(projectRoot);
30537
- return { index: index.getIndex(), suggestions: [] };
30728
+ let effectiveness = [];
30729
+ try {
30730
+ const signalIdx = buildSignalIndex(projectRoot);
30731
+ effectiveness = deriveEffectiveness(projectRoot, index, signalIdx, nowMs);
30732
+ } catch {
30733
+ }
30734
+ const payload = {
30735
+ index: index.getIndex(),
30736
+ suggestions: [],
30737
+ effectiveness
30738
+ };
30739
+ cache2.set(projectRoot, {
30740
+ payload,
30741
+ builtAtMs: nowMs,
30742
+ jsonlMtimeMs: jsonlMtime(projectRoot)
30743
+ });
30744
+ return payload;
30538
30745
  } catch {
30539
- return { index: {}, suggestions: [] };
30746
+ return { index: {}, suggestions: [], effectiveness: [] };
30540
30747
  }
30541
30748
  }
30542
30749
  async function skillsBindHandler(projectRoot, body) {
@@ -30553,19 +30760,33 @@ async function skillsBindHandler(projectRoot, body) {
30553
30760
  const changed = index.disable(body.agent_id, body.skill);
30554
30761
  if (!changed) return { success: false, error: "Skill not bound to agent" };
30555
30762
  }
30763
+ cache2.delete(projectRoot);
30556
30764
  return { success: true };
30557
30765
  } catch (err) {
30558
30766
  return { success: false, error: err instanceof Error ? err.message : "Unknown error" };
30559
30767
  }
30560
30768
  }
30561
- var import_fs52, import_path56, AGENT_ID_RE2;
30769
+ var import_fs52, import_path56, AGENT_ID_RE2, NUM_BUCKETS, WINDOW_MS2, DEFAULT_THRESHOLD, CACHE_TTL_MS, CORRECT_SIGNALS, HALLUC_SIGNALS, cache2;
30562
30770
  var init_api_skills = __esm({
30563
30771
  "packages/relay/src/dashboard/api-skills.ts"() {
30564
30772
  "use strict";
30565
30773
  init_skill_index();
30774
+ init_src4();
30566
30775
  import_fs52 = require("fs");
30567
30776
  import_path56 = require("path");
30568
30777
  AGENT_ID_RE2 = /^[a-zA-Z0-9_-]{1,64}$/;
30778
+ NUM_BUCKETS = 10;
30779
+ WINDOW_MS2 = 7 * 24 * 60 * 60 * 1e3;
30780
+ DEFAULT_THRESHOLD = 0.7;
30781
+ CACHE_TTL_MS = 6e4;
30782
+ CORRECT_SIGNALS = /* @__PURE__ */ new Set([
30783
+ "agreement",
30784
+ "category_confirmed",
30785
+ "consensus_verified",
30786
+ "unique_confirmed"
30787
+ ]);
30788
+ HALLUC_SIGNALS = /* @__PURE__ */ new Set(["disagreement", "hallucination_caught"]);
30789
+ cache2 = /* @__PURE__ */ new Map();
30569
30790
  }
30570
30791
  });
30571
30792
 
@@ -30849,6 +31070,123 @@ var init_api_consensus = __esm({
30849
31070
  }
30850
31071
  });
30851
31072
 
31073
+ // packages/relay/src/dashboard/api-consensus-flow.ts
31074
+ function isValidConsensusId(id) {
31075
+ return SAFE_CONSENSUS_ID.test(id);
31076
+ }
31077
+ function familyOf(agentId) {
31078
+ if (agentId.startsWith("sonnet-")) return "sonnet";
31079
+ if (agentId.startsWith("gemini-")) return "gemini";
31080
+ if (agentId.startsWith("opus-")) return "opus";
31081
+ if (agentId.startsWith("haiku-")) return "haiku";
31082
+ return "other";
31083
+ }
31084
+ function tally(report, bucket) {
31085
+ const arr = report?.[bucket];
31086
+ return Array.isArray(arr) ? arr : [];
31087
+ }
31088
+ function consensusFlowHandler(projectRoot, query) {
31089
+ const consensusId = query?.get("consensusId")?.trim() ?? "";
31090
+ if (!consensusId) {
31091
+ return { error: "consensusId query parameter is required" };
31092
+ }
31093
+ if (!isValidConsensusId(consensusId)) {
31094
+ return { error: `invalid consensusId shape (expected xxxxxxxx-xxxxxxxx hex)` };
31095
+ }
31096
+ const reportPath = (0, import_path61.join)(projectRoot, ".gossip", "consensus-reports", `${consensusId}.json`);
31097
+ if (!(0, import_fs56.existsSync)(reportPath)) {
31098
+ return { error: `consensus ${consensusId} not found` };
31099
+ }
31100
+ let report;
31101
+ try {
31102
+ report = JSON.parse((0, import_fs56.readFileSync)(reportPath, "utf-8"));
31103
+ } catch (e) {
31104
+ return { error: `failed to parse consensus report: ${e?.message ?? "unknown error"}` };
31105
+ }
31106
+ const buckets = {
31107
+ confirmed: tally(report, "confirmed"),
31108
+ disputed: tally(report, "disputed"),
31109
+ unverified: tally(report, "unverified"),
31110
+ unique: tally(report, "unique")
31111
+ };
31112
+ const newFindings = Array.isArray(report?.newFindings) ? report.newFindings : [];
31113
+ const totalFindings = buckets.confirmed.length + buckets.disputed.length + buckets.unverified.length + buckets.unique.length + newFindings.length;
31114
+ const familyAgents = /* @__PURE__ */ new Map();
31115
+ for (const verdict of ["confirmed", "disputed", "unverified", "unique"]) {
31116
+ for (const f of buckets[verdict]) {
31117
+ const agent = f.originalAgentId;
31118
+ if (!agent) continue;
31119
+ const fam = familyOf(agent);
31120
+ if (!familyAgents.has(fam)) familyAgents.set(fam, /* @__PURE__ */ new Set());
31121
+ familyAgents.get(fam).add(agent);
31122
+ }
31123
+ }
31124
+ const modelFamilyToFindings = Array.from(familyAgents.entries()).map(([family, ids]) => ({
31125
+ family,
31126
+ agentIds: Array.from(ids).sort(),
31127
+ agentCount: ids.size
31128
+ })).sort((a, b) => a.family.localeCompare(b.family));
31129
+ const edgeCounts = /* @__PURE__ */ new Map();
31130
+ for (const verdict of ["confirmed", "disputed", "unverified", "unique"]) {
31131
+ for (const f of buckets[verdict]) {
31132
+ const agent = f.originalAgentId;
31133
+ if (!agent) continue;
31134
+ const fam = familyOf(agent);
31135
+ const key = `${fam}::${verdict}`;
31136
+ edgeCounts.set(key, (edgeCounts.get(key) ?? 0) + 1);
31137
+ }
31138
+ }
31139
+ const familyToOutcome = [];
31140
+ for (const [key, count] of edgeCounts) {
31141
+ const [fam, verdict] = key.split("::");
31142
+ const agentCount = familyAgents.get(fam)?.size ?? 0;
31143
+ familyToOutcome.push({
31144
+ from: { family: fam, agentCount },
31145
+ to: { verdict, count },
31146
+ weight: totalFindings > 0 ? count / totalFindings : 0
31147
+ });
31148
+ }
31149
+ familyToOutcome.sort((a, b) => {
31150
+ if (a.from.family !== b.from.family) return a.from.family.localeCompare(b.from.family);
31151
+ return a.to.verdict.localeCompare(b.to.verdict);
31152
+ });
31153
+ const out = {
31154
+ consensusId,
31155
+ timestamp: typeof report?.timestamp === "string" ? report.timestamp : "",
31156
+ agentCount: typeof report?.agentCount === "number" ? report.agentCount : 0,
31157
+ modelFamilyToFindings,
31158
+ familyToOutcome,
31159
+ summary: {
31160
+ totalFindings,
31161
+ confirmed: buckets.confirmed.length,
31162
+ disputed: buckets.disputed.length,
31163
+ unverified: buckets.unverified.length,
31164
+ unique: buckets.unique.length,
31165
+ newFindings: newFindings.length
31166
+ }
31167
+ };
31168
+ if (report?.crossReviewAssignments && typeof report.crossReviewAssignments === "object") {
31169
+ out.crossReviewAssignments = report.crossReviewAssignments;
31170
+ }
31171
+ if (Array.isArray(report?.crossReviewCoverage)) {
31172
+ out.crossReviewCoverage = report.crossReviewCoverage;
31173
+ }
31174
+ if (report?.partialReview === true) out.partialReview = true;
31175
+ if (report?.coverageDegraded && typeof report.coverageDegraded === "object") {
31176
+ out.coverageDegraded = report.coverageDegraded;
31177
+ }
31178
+ return out;
31179
+ }
31180
+ var import_fs56, import_path61, SAFE_CONSENSUS_ID;
31181
+ var init_api_consensus_flow = __esm({
31182
+ "packages/relay/src/dashboard/api-consensus-flow.ts"() {
31183
+ "use strict";
31184
+ import_fs56 = require("fs");
31185
+ import_path61 = require("path");
31186
+ SAFE_CONSENSUS_ID = /^[0-9a-f]{8}-[0-9a-f]{8}$/;
31187
+ }
31188
+ });
31189
+
30852
31190
  // packages/relay/src/dashboard/api-signals.ts
30853
31191
  function inferSource(entry) {
30854
31192
  const raw = typeof entry.source === "string" ? entry.source.toLowerCase() : "";
@@ -30874,7 +31212,7 @@ async function signalsHandler(projectRoot, query) {
30874
31212
  const cursor = query?.get("cursor") ?? null;
30875
31213
  const limit = Math.min(Math.max(parseInt(query?.get("limit") ?? "", 10) || DEFAULT_LIMIT, 1), MAX_LIMIT);
30876
31214
  const offset = Math.max(parseInt(query?.get("offset") ?? "", 10) || 0, 0);
30877
- const perfPath = (0, import_path61.join)(projectRoot, ".gossip", "agent-performance.jsonl");
31215
+ const perfPath = (0, import_path62.join)(projectRoot, ".gossip", "agent-performance.jsonl");
30878
31216
  const all = [];
30879
31217
  const roundRetractions = [];
30880
31218
  const signalFilterSet = signalFilters.length ? new Set(signalFilters) : null;
@@ -30936,11 +31274,11 @@ async function signalsHandler(projectRoot, query) {
30936
31274
  if (nextCursor) response.nextCursor = nextCursor;
30937
31275
  return response;
30938
31276
  }
30939
- var import_path61, MAX_LIMIT, DEFAULT_LIMIT, META_SIGNALS;
31277
+ var import_path62, MAX_LIMIT, DEFAULT_LIMIT, META_SIGNALS;
30940
31278
  var init_api_signals = __esm({
30941
31279
  "packages/relay/src/dashboard/api-signals.ts"() {
30942
31280
  "use strict";
30943
- import_path61 = require("path");
31281
+ import_path62 = require("path");
30944
31282
  init_src4();
30945
31283
  MAX_LIMIT = 500;
30946
31284
  DEFAULT_LIMIT = 50;
@@ -30953,7 +31291,7 @@ function extractCitations(findingText, projectRoot) {
30953
31291
  const out = [];
30954
31292
  let realRoot;
30955
31293
  try {
30956
- realRoot = (0, import_fs56.realpathSync)((0, import_path62.resolve)(projectRoot));
31294
+ realRoot = (0, import_fs57.realpathSync)((0, import_path63.resolve)(projectRoot));
30957
31295
  } catch {
30958
31296
  return out;
30959
31297
  }
@@ -30964,23 +31302,23 @@ function extractCitations(findingText, projectRoot) {
30964
31302
  const line = parseInt(m[2], 10);
30965
31303
  if (!Number.isFinite(line) || line < 1) continue;
30966
31304
  if (filePath.includes("\0")) continue;
30967
- const abs = (0, import_path62.resolve)(realRoot, filePath);
30968
- const preRel = (0, import_path62.relative)(realRoot, abs);
31305
+ const abs = (0, import_path63.resolve)(realRoot, filePath);
31306
+ const preRel = (0, import_path63.relative)(realRoot, abs);
30969
31307
  if (preRel === "" || preRel.startsWith("..")) continue;
30970
- if (!(0, import_fs56.existsSync)(abs)) {
31308
+ if (!(0, import_fs57.existsSync)(abs)) {
30971
31309
  out.push({ file: filePath, line, snippet: "// file not found" });
30972
31310
  continue;
30973
31311
  }
30974
31312
  let realAbs;
30975
31313
  try {
30976
- realAbs = (0, import_fs56.realpathSync)(abs);
31314
+ realAbs = (0, import_fs57.realpathSync)(abs);
30977
31315
  } catch {
30978
31316
  continue;
30979
31317
  }
30980
- const rel = (0, import_path62.relative)(realRoot, realAbs);
31318
+ const rel = (0, import_path63.relative)(realRoot, realAbs);
30981
31319
  if (rel === "" || rel.startsWith("..")) continue;
30982
31320
  try {
30983
- const lines = (0, import_fs56.readFileSync)(realAbs, "utf-8").split("\n");
31321
+ const lines = (0, import_fs57.readFileSync)(realAbs, "utf-8").split("\n");
30984
31322
  const start = Math.max(0, line - 1 - SNIPPET_CONTEXT);
30985
31323
  const end = Math.min(lines.length, line + SNIPPET_CONTEXT);
30986
31324
  out.push({ file: filePath, line, snippet: lines.slice(start, end).join("\n") });
@@ -30993,9 +31331,9 @@ function extractCitations(findingText, projectRoot) {
30993
31331
  async function findingHandler(projectRoot, consensusId, findingId) {
30994
31332
  if (!SAFE_ID.test(consensusId)) throw new Error(`consensus ${consensusId} not found`);
30995
31333
  if (!SAFE_ID.test(findingId)) throw new Error(`finding ${findingId} not found in ${consensusId}`);
30996
- const reportPath = (0, import_path62.join)(projectRoot, ".gossip", "consensus-reports", `${consensusId}.json`);
30997
- if (!(0, import_fs56.existsSync)(reportPath)) throw new Error(`consensus ${consensusId} not found`);
30998
- const report = JSON.parse((0, import_fs56.readFileSync)(reportPath, "utf-8"));
31334
+ const reportPath = (0, import_path63.join)(projectRoot, ".gossip", "consensus-reports", `${consensusId}.json`);
31335
+ if (!(0, import_fs57.existsSync)(reportPath)) throw new Error(`consensus ${consensusId} not found`);
31336
+ const report = JSON.parse((0, import_fs57.readFileSync)(reportPath, "utf-8"));
30999
31337
  const buckets = [
31000
31338
  ["confirmed", "confirmed"],
31001
31339
  ["disputed", "disputed"],
@@ -31016,7 +31354,7 @@ async function findingHandler(projectRoot, consensusId, findingId) {
31016
31354
  }
31017
31355
  if (!found) throw new Error(`finding ${findingId} not found in ${consensusId}`);
31018
31356
  const signals = [];
31019
- const perfPath = (0, import_path62.join)(projectRoot, ".gossip", "agent-performance.jsonl");
31357
+ const perfPath = (0, import_path63.join)(projectRoot, ".gossip", "agent-performance.jsonl");
31020
31358
  try {
31021
31359
  const raw = readJsonlWithRotated(perfPath);
31022
31360
  if (raw) {
@@ -31058,13 +31396,13 @@ async function findingHandler(projectRoot, consensusId, findingId) {
31058
31396
  citations
31059
31397
  };
31060
31398
  }
31061
- var import_fs56, import_path62, SAFE_ID, SNIPPET_CONTEXT, CITE_PATTERN;
31399
+ var import_fs57, import_path63, SAFE_ID, SNIPPET_CONTEXT, CITE_PATTERN;
31062
31400
  var init_api_finding = __esm({
31063
31401
  "packages/relay/src/dashboard/api-finding.ts"() {
31064
31402
  "use strict";
31065
- import_fs56 = require("fs");
31403
+ import_fs57 = require("fs");
31066
31404
  init_src4();
31067
- import_path62 = require("path");
31405
+ import_path63 = require("path");
31068
31406
  SAFE_ID = /^[\w:.\-]+$/;
31069
31407
  SNIPPET_CONTEXT = 2;
31070
31408
  CITE_PATTERN = /<cite tag="file">([^<:]+):(\d+)<\/cite>/g;
@@ -31077,13 +31415,13 @@ async function openFindingsHandler(projectRoot) {
31077
31415
  let open = 0;
31078
31416
  let resolved = 0;
31079
31417
  let staleAnchor = 0;
31080
- const findingsPath = (0, import_path63.join)(projectRoot, ".gossip", "implementation-findings.jsonl");
31081
- if (!(0, import_fs57.existsSync)(findingsPath)) {
31418
+ const findingsPath = (0, import_path64.join)(projectRoot, ".gossip", "implementation-findings.jsonl");
31419
+ if (!(0, import_fs58.existsSync)(findingsPath)) {
31082
31420
  return { rows, totals: { open: 0, resolved: 0, staleAnchor: 0 } };
31083
31421
  }
31084
31422
  let raw;
31085
31423
  try {
31086
- raw = (0, import_fs57.readFileSync)(findingsPath, "utf-8");
31424
+ raw = (0, import_fs58.readFileSync)(findingsPath, "utf-8");
31087
31425
  } catch {
31088
31426
  return { rows, totals: { open: 0, resolved: 0, staleAnchor: 0 } };
31089
31427
  }
@@ -31121,40 +31459,40 @@ async function openFindingsHandler(projectRoot) {
31121
31459
  }
31122
31460
  return { rows, totals: { open, resolved, staleAnchor } };
31123
31461
  }
31124
- var import_fs57, import_path63;
31462
+ var import_fs58, import_path64;
31125
31463
  var init_api_open_findings = __esm({
31126
31464
  "packages/relay/src/dashboard/api-open-findings.ts"() {
31127
31465
  "use strict";
31128
- import_fs57 = require("fs");
31129
- import_path63 = require("path");
31466
+ import_fs58 = require("fs");
31467
+ import_path64 = require("path");
31130
31468
  }
31131
31469
  });
31132
31470
 
31133
31471
  // packages/relay/src/dashboard/api-learnings.ts
31134
31472
  async function learningsHandler(projectRoot) {
31135
- const agentsDir = (0, import_path64.join)(projectRoot, ".gossip", "agents");
31136
- if (!(0, import_fs58.existsSync)(agentsDir)) return { learnings: [] };
31473
+ const agentsDir = (0, import_path65.join)(projectRoot, ".gossip", "agents");
31474
+ if (!(0, import_fs59.existsSync)(agentsDir)) return { learnings: [] };
31137
31475
  const all = [];
31138
31476
  let agentIds;
31139
31477
  try {
31140
- agentIds = (0, import_fs58.readdirSync)(agentsDir).filter((f) => !f.startsWith("."));
31478
+ agentIds = (0, import_fs59.readdirSync)(agentsDir).filter((f) => !f.startsWith("."));
31141
31479
  } catch {
31142
31480
  return { learnings: [] };
31143
31481
  }
31144
31482
  for (const agentId of agentIds) {
31145
- const knowledgeDir = (0, import_path64.join)(agentsDir, agentId, "memory", "knowledge");
31146
- if (!(0, import_fs58.existsSync)(knowledgeDir)) continue;
31483
+ const knowledgeDir = (0, import_path65.join)(agentsDir, agentId, "memory", "knowledge");
31484
+ if (!(0, import_fs59.existsSync)(knowledgeDir)) continue;
31147
31485
  let files;
31148
31486
  try {
31149
- files = (0, import_fs58.readdirSync)(knowledgeDir).filter((f) => f.endsWith(".md"));
31487
+ files = (0, import_fs59.readdirSync)(knowledgeDir).filter((f) => f.endsWith(".md"));
31150
31488
  } catch {
31151
31489
  continue;
31152
31490
  }
31153
31491
  for (const filename of files) {
31154
- const filepath = (0, import_path64.join)(knowledgeDir, filename);
31492
+ const filepath = (0, import_path65.join)(knowledgeDir, filename);
31155
31493
  try {
31156
- const stat4 = (0, import_fs58.statSync)(filepath);
31157
- const raw = (0, import_fs58.readFileSync)(filepath, "utf-8");
31494
+ const stat4 = (0, import_fs59.statSync)(filepath);
31495
+ const raw = (0, import_fs59.readFileSync)(filepath, "utf-8");
31158
31496
  const fm = parseFrontmatter3(raw);
31159
31497
  all.push({
31160
31498
  agentId,
@@ -31181,28 +31519,41 @@ function parseFrontmatter3(raw) {
31181
31519
  }
31182
31520
  return fm;
31183
31521
  }
31184
- var import_fs58, import_path64, MAX_LEARNINGS;
31522
+ var import_fs59, import_path65, MAX_LEARNINGS;
31185
31523
  var init_api_learnings = __esm({
31186
31524
  "packages/relay/src/dashboard/api-learnings.ts"() {
31187
31525
  "use strict";
31188
- import_fs58 = require("fs");
31189
- import_path64 = require("path");
31526
+ import_fs59 = require("fs");
31527
+ import_path65 = require("path");
31190
31528
  MAX_LEARNINGS = 10;
31191
31529
  }
31192
31530
  });
31193
31531
 
31194
31532
  // packages/relay/src/dashboard/api-tasks.ts
31533
+ function readTaskGraphLines(graphPath) {
31534
+ const out = [];
31535
+ const archive = graphPath + ".1";
31536
+ if ((0, import_fs60.existsSync)(archive)) {
31537
+ out.push(...(0, import_fs60.readFileSync)(archive, "utf-8").split("\n").filter(Boolean));
31538
+ }
31539
+ if ((0, import_fs60.existsSync)(graphPath)) {
31540
+ out.push(...(0, import_fs60.readFileSync)(graphPath, "utf-8").split("\n").filter(Boolean));
31541
+ }
31542
+ return out;
31543
+ }
31195
31544
  async function tasksHandler(projectRoot, query) {
31196
31545
  const rawLimit = parseInt(query?.get("limit") ?? "50", 10);
31197
31546
  const rawOffset = parseInt(query?.get("offset") ?? "0", 10);
31198
31547
  const limit = isNaN(rawLimit) || rawLimit < 1 ? 50 : Math.min(rawLimit, 2e3);
31199
31548
  const offset = isNaN(rawOffset) || rawOffset < 0 ? 0 : rawOffset;
31200
- const graphPath = (0, import_path65.join)(projectRoot, ".gossip", "task-graph.jsonl");
31201
- if (!(0, import_fs59.existsSync)(graphPath)) return { items: [], total: 0, offset, limit };
31549
+ const graphPath = (0, import_path66.join)(projectRoot, ".gossip", "task-graph.jsonl");
31550
+ if (!(0, import_fs60.existsSync)(graphPath) && !(0, import_fs60.existsSync)(graphPath + ".1")) {
31551
+ return { items: [], total: 0, offset, limit };
31552
+ }
31202
31553
  const created = /* @__PURE__ */ new Map();
31203
31554
  const completed = /* @__PURE__ */ new Map();
31204
31555
  try {
31205
- const lines = (0, import_fs59.readFileSync)(graphPath, "utf-8").trim().split("\n").filter(Boolean);
31556
+ const lines = readTaskGraphLines(graphPath);
31206
31557
  for (const line of lines) {
31207
31558
  try {
31208
31559
  const entry = JSON.parse(line);
@@ -31258,24 +31609,24 @@ async function tasksHandler(projectRoot, query) {
31258
31609
  tasks.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
31259
31610
  return { items: tasks.slice(offset, offset + limit), total: tasks.length, offset, limit };
31260
31611
  }
31261
- var import_fs59, import_path65;
31612
+ var import_fs60, import_path66;
31262
31613
  var init_api_tasks = __esm({
31263
31614
  "packages/relay/src/dashboard/api-tasks.ts"() {
31264
31615
  "use strict";
31265
- import_fs59 = require("fs");
31266
- import_path65 = require("path");
31616
+ import_fs60 = require("fs");
31617
+ import_path66 = require("path");
31267
31618
  init_utility_agents();
31268
31619
  }
31269
31620
  });
31270
31621
 
31271
31622
  // packages/relay/src/dashboard/api-active-tasks.ts
31272
31623
  async function activeTasksHandler(projectRoot) {
31273
- const taskGraphPath = (0, import_path66.join)(projectRoot, ".gossip", "task-graph.jsonl");
31274
- if (!(0, import_fs60.existsSync)(taskGraphPath)) return { tasks: [] };
31624
+ const taskGraphPath = (0, import_path67.join)(projectRoot, ".gossip", "task-graph.jsonl");
31625
+ if (!(0, import_fs61.existsSync)(taskGraphPath)) return { tasks: [] };
31275
31626
  const created = /* @__PURE__ */ new Map();
31276
31627
  const finished = /* @__PURE__ */ new Set();
31277
31628
  try {
31278
- const lines = (0, import_fs60.readFileSync)(taskGraphPath, "utf-8").trim().split("\n").filter(Boolean);
31629
+ const lines = (0, import_fs61.readFileSync)(taskGraphPath, "utf-8").trim().split("\n").filter(Boolean);
31279
31630
  for (const line of lines) {
31280
31631
  try {
31281
31632
  const ev = JSON.parse(line);
@@ -31303,12 +31654,12 @@ async function activeTasksHandler(projectRoot) {
31303
31654
  active.sort((a, b) => b.startedAt.localeCompare(a.startedAt));
31304
31655
  return { tasks: active.slice(0, 10) };
31305
31656
  }
31306
- var import_fs60, import_path66;
31657
+ var import_fs61, import_path67;
31307
31658
  var init_api_active_tasks = __esm({
31308
31659
  "packages/relay/src/dashboard/api-active-tasks.ts"() {
31309
31660
  "use strict";
31310
- import_fs60 = require("fs");
31311
- import_path66 = require("path");
31661
+ import_fs61 = require("fs");
31662
+ import_path67 = require("path");
31312
31663
  init_utility_agents();
31313
31664
  }
31314
31665
  });
@@ -31322,25 +31673,25 @@ function categorize(text) {
31322
31673
  return "other";
31323
31674
  }
31324
31675
  function logsHandler(projectRoot, query) {
31325
- const logPath = (0, import_path67.join)(projectRoot, ".gossip", "mcp.log");
31326
- if (!(0, import_fs61.existsSync)(logPath)) {
31676
+ const logPath = (0, import_path68.join)(projectRoot, ".gossip", "mcp.log");
31677
+ if (!(0, import_fs62.existsSync)(logPath)) {
31327
31678
  return { entries: [], totalLines: 0, fileSize: 0 };
31328
31679
  }
31329
31680
  const filter = query?.get("filter") || void 0;
31330
31681
  const tail = parseInt(query?.get("tail") || "200", 10);
31331
31682
  const clampedTail = Math.min(Math.max(tail, 10), 2e3);
31332
- const fileSize = (0, import_fs61.statSync)(logPath).size;
31683
+ const fileSize = (0, import_fs62.statSync)(logPath).size;
31333
31684
  const MAX_READ = 512 * 1024;
31334
31685
  const readFrom = Math.max(0, fileSize - MAX_READ);
31335
31686
  const readLen = fileSize - readFrom;
31336
- const fd = (0, import_fs61.openSync)(logPath, "r");
31687
+ const fd = (0, import_fs62.openSync)(logPath, "r");
31337
31688
  let buf = Buffer.alloc(0);
31338
31689
  try {
31339
31690
  buf = Buffer.allocUnsafe(readLen);
31340
- const bytesRead = (0, import_fs61.readSync)(fd, buf, 0, readLen, readFrom);
31691
+ const bytesRead = (0, import_fs62.readSync)(fd, buf, 0, readLen, readFrom);
31341
31692
  buf = buf.subarray(0, bytesRead);
31342
31693
  } finally {
31343
- (0, import_fs61.closeSync)(fd);
31694
+ (0, import_fs62.closeSync)(fd);
31344
31695
  }
31345
31696
  let raw = buf.toString("utf-8");
31346
31697
  let lineOffset = 0;
@@ -31348,13 +31699,13 @@ function logsHandler(projectRoot, query) {
31348
31699
  const nl = raw.indexOf("\n");
31349
31700
  raw = nl >= 0 ? raw.slice(nl + 1) : raw;
31350
31701
  const SCAN_CHUNK = 64 * 1024;
31351
- const scanFd = (0, import_fs61.openSync)(logPath, "r");
31702
+ const scanFd = (0, import_fs62.openSync)(logPath, "r");
31352
31703
  try {
31353
31704
  let pos = 0;
31354
31705
  const chunk = Buffer.allocUnsafe(SCAN_CHUNK);
31355
31706
  while (pos < readFrom) {
31356
31707
  const len = Math.min(SCAN_CHUNK, readFrom - pos);
31357
- const n = (0, import_fs61.readSync)(scanFd, chunk, 0, len, pos);
31708
+ const n = (0, import_fs62.readSync)(scanFd, chunk, 0, len, pos);
31358
31709
  if (n === 0) break;
31359
31710
  for (let j = 0; j < n; j++) {
31360
31711
  if (chunk[j] === 10) lineOffset++;
@@ -31362,7 +31713,7 @@ function logsHandler(projectRoot, query) {
31362
31713
  pos += n;
31363
31714
  }
31364
31715
  } finally {
31365
- (0, import_fs61.closeSync)(scanFd);
31716
+ (0, import_fs62.closeSync)(scanFd);
31366
31717
  }
31367
31718
  }
31368
31719
  const allLines = raw.split("\n").filter(Boolean);
@@ -31380,12 +31731,12 @@ function logsHandler(projectRoot, query) {
31380
31731
  entries = entries.slice(-clampedTail);
31381
31732
  return { entries, totalLines, fileSize, filter };
31382
31733
  }
31383
- var import_fs61, import_path67, CATEGORY_PATTERNS2;
31734
+ var import_fs62, import_path68, CATEGORY_PATTERNS2;
31384
31735
  var init_api_logs = __esm({
31385
31736
  "packages/relay/src/dashboard/api-logs.ts"() {
31386
31737
  "use strict";
31387
- import_fs61 = require("fs");
31388
- import_path67 = require("path");
31738
+ import_fs62 = require("fs");
31739
+ import_path68 = require("path");
31389
31740
  CATEGORY_PATTERNS2 = [
31390
31741
  [/^\[worker:/, "worker"],
31391
31742
  [/^\[Gemini\]/, "gemini"],
@@ -31417,11 +31768,11 @@ function violationsHandler(projectRoot, query) {
31417
31768
  const page = Math.max(1, parseInt(query?.get("page") ?? "1", 10));
31418
31769
  const pageSize = Math.min(100, Math.max(1, parseInt(query?.get("pageSize") ?? "25", 10)));
31419
31770
  const agentFilter = query?.get("agentId") ?? null;
31420
- const filePath = (0, import_path68.join)(projectRoot, FILE);
31421
- if (!(0, import_fs62.existsSync)(filePath)) {
31771
+ const filePath = (0, import_path69.join)(projectRoot, FILE);
31772
+ if (!(0, import_fs63.existsSync)(filePath)) {
31422
31773
  return { items: [], total: 0, page, pageSize };
31423
31774
  }
31424
- const raw = (0, import_fs62.readFileSync)(filePath, "utf-8");
31775
+ const raw = (0, import_fs63.readFileSync)(filePath, "utf-8");
31425
31776
  const lines = raw.trim().split("\n").filter(Boolean);
31426
31777
  const entries = [];
31427
31778
  for (const line of lines) {
@@ -31441,12 +31792,12 @@ function violationsHandler(projectRoot, query) {
31441
31792
  const start = (page - 1) * pageSize;
31442
31793
  return { items: entries.slice(start, start + pageSize), total, page, pageSize };
31443
31794
  }
31444
- var import_fs62, import_path68, FILE;
31795
+ var import_fs63, import_path69, FILE;
31445
31796
  var init_api_violations = __esm({
31446
31797
  "packages/relay/src/dashboard/api-violations.ts"() {
31447
31798
  "use strict";
31448
- import_fs62 = require("fs");
31449
- import_path68 = require("path");
31799
+ import_fs63 = require("fs");
31800
+ import_path69 = require("path");
31450
31801
  FILE = ".gossip/process-violations.jsonl";
31451
31802
  }
31452
31803
  });
@@ -31454,15 +31805,15 @@ var init_api_violations = __esm({
31454
31805
  // packages/relay/src/dashboard/routes.ts
31455
31806
  function resolveDashboardRoot(projectRoot) {
31456
31807
  const candidates = [
31457
- (0, import_path69.resolve)(__dirname, "..", "dist-dashboard"),
31808
+ (0, import_path70.resolve)(__dirname, "..", "dist-dashboard"),
31458
31809
  // bundled: dist-mcp/mcp-server.js → ../dist-dashboard
31459
- (0, import_path69.resolve)(__dirname, "..", "..", "..", "..", "dist-dashboard"),
31810
+ (0, import_path70.resolve)(__dirname, "..", "..", "..", "..", "dist-dashboard"),
31460
31811
  // tsc dev: packages/relay/dist/dashboard → repo-root
31461
- (0, import_path69.join)(projectRoot, "dist-dashboard")
31812
+ (0, import_path70.join)(projectRoot, "dist-dashboard")
31462
31813
  // legacy dev fallback (git-clone running from repo root)
31463
31814
  ];
31464
31815
  for (const p of candidates) {
31465
- if ((0, import_fs63.existsSync)(p)) return p;
31816
+ if ((0, import_fs64.existsSync)(p)) return p;
31466
31817
  }
31467
31818
  return null;
31468
31819
  }
@@ -31489,7 +31840,7 @@ function readBody(req) {
31489
31840
  });
31490
31841
  });
31491
31842
  }
31492
- var import_fs63, import_path69, import_crypto25, AUTH_MAX_ATTEMPTS, AUTH_LOCKOUT_MS, DashboardRouter, MAX_BODY_SIZE;
31843
+ var import_fs64, import_path70, import_crypto25, AUTH_MAX_ATTEMPTS, AUTH_LOCKOUT_MS, DashboardRouter, MAX_BODY_SIZE;
31493
31844
  var init_routes = __esm({
31494
31845
  "packages/relay/src/dashboard/routes.ts"() {
31495
31846
  "use strict";
@@ -31502,6 +31853,7 @@ var init_routes = __esm({
31502
31853
  init_api_native_memory();
31503
31854
  init_api_gossip_memory();
31504
31855
  init_api_consensus();
31856
+ init_api_consensus_flow();
31505
31857
  init_api_signals();
31506
31858
  init_api_finding();
31507
31859
  init_api_open_findings();
@@ -31510,8 +31862,8 @@ var init_routes = __esm({
31510
31862
  init_api_active_tasks();
31511
31863
  init_api_logs();
31512
31864
  init_api_violations();
31513
- import_fs63 = require("fs");
31514
- import_path69 = require("path");
31865
+ import_fs64 = require("fs");
31866
+ import_path70 = require("path");
31515
31867
  import_crypto25 = require("crypto");
31516
31868
  AUTH_MAX_ATTEMPTS = 10;
31517
31869
  AUTH_LOCKOUT_MS = 6e4;
@@ -31574,6 +31926,11 @@ var init_routes = __esm({
31574
31926
  if (url2 === "/dashboard") {
31575
31927
  return this.serveDashboard(res);
31576
31928
  }
31929
+ if (url2 === "/" || url2 === "") {
31930
+ res.writeHead(302, { Location: "/dashboard" });
31931
+ res.end();
31932
+ return true;
31933
+ }
31577
31934
  this.json(res, 404, { error: "Not found" });
31578
31935
  return true;
31579
31936
  }
@@ -31690,6 +32047,24 @@ var init_routes = __esm({
31690
32047
  this.json(res, 200, data);
31691
32048
  return true;
31692
32049
  }
32050
+ if (url2 === "/dashboard/api/consensus-flow" && req.method === "GET") {
32051
+ const consensusId = query?.get("consensusId")?.trim() ?? "";
32052
+ if (!consensusId) {
32053
+ this.json(res, 400, { error: "consensusId query parameter is required" });
32054
+ return true;
32055
+ }
32056
+ if (!isValidConsensusId(consensusId)) {
32057
+ this.json(res, 400, { error: "invalid consensusId shape (expected xxxxxxxx-xxxxxxxx hex)" });
32058
+ return true;
32059
+ }
32060
+ const data = consensusFlowHandler(this.projectRoot, query ?? void 0);
32061
+ if ("error" in data) {
32062
+ this.json(res, 404, data);
32063
+ return true;
32064
+ }
32065
+ this.json(res, 200, data);
32066
+ return true;
32067
+ }
31693
32068
  if (url2 === "/dashboard/api/consensus-reports" && req.method === "GET") {
31694
32069
  const page = parseInt(query?.get("page") || "1", 10);
31695
32070
  const pageSize = parseInt(query?.get("pageSize") || "5", 10);
@@ -31792,13 +32167,13 @@ var init_routes = __esm({
31792
32167
  res.end("Dashboard assets not found. Reinstall gossipcat or rebuild from source.");
31793
32168
  return true;
31794
32169
  }
31795
- const htmlPath = (0, import_path69.join)(this.dashboardRoot, "index.html");
31796
- if (!(0, import_fs63.existsSync)(htmlPath)) {
32170
+ const htmlPath = (0, import_path70.join)(this.dashboardRoot, "index.html");
32171
+ if (!(0, import_fs64.existsSync)(htmlPath)) {
31797
32172
  res.writeHead(503, { "Content-Type": "text/plain" });
31798
32173
  res.end(`Dashboard index.html missing at ${this.dashboardRoot}. Reinstall gossipcat.`);
31799
32174
  return true;
31800
32175
  }
31801
- const html = (0, import_fs63.readFileSync)(htmlPath, "utf-8");
32176
+ const html = (0, import_fs64.readFileSync)(htmlPath, "utf-8");
31802
32177
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
31803
32178
  res.end(html);
31804
32179
  return true;
@@ -31824,16 +32199,16 @@ var init_routes = __esm({
31824
32199
  const ext = "." + (relativePath.split(".").pop() || "");
31825
32200
  const mime = MIME[ext];
31826
32201
  if (!mime) return false;
31827
- const filePath = (0, import_path69.join)(this.dashboardRoot, relativePath);
32202
+ const filePath = (0, import_path70.join)(this.dashboardRoot, relativePath);
31828
32203
  try {
31829
- const realFile = (0, import_fs63.realpathSync)(filePath);
31830
- const realBase = (0, import_fs63.realpathSync)(this.dashboardRoot);
32204
+ const realFile = (0, import_fs64.realpathSync)(filePath);
32205
+ const realBase = (0, import_fs64.realpathSync)(this.dashboardRoot);
31831
32206
  if (!realFile.startsWith(realBase + "/")) {
31832
32207
  res.writeHead(404);
31833
32208
  res.end();
31834
32209
  return true;
31835
32210
  }
31836
- const data = (0, import_fs63.readFileSync)(realFile);
32211
+ const data = (0, import_fs64.readFileSync)(realFile);
31837
32212
  res.writeHead(200, { "Content-Type": mime, "Cache-Control": "public, max-age=86400" });
31838
32213
  res.end(data);
31839
32214
  return true;
@@ -31848,8 +32223,8 @@ var init_routes = __esm({
31848
32223
  return match ? match[1] : null;
31849
32224
  }
31850
32225
  getConsensusReports(page = 1, pageSize = 5) {
31851
- const { readdirSync: readdirSync22, readFileSync: readFileSync62, existsSync: existsSync69 } = require("fs");
31852
- const reportsDir = (0, import_path69.join)(this.projectRoot, ".gossip", "consensus-reports");
32226
+ const { readdirSync: readdirSync22, readFileSync: readFileSync64, existsSync: existsSync70 } = require("fs");
32227
+ const reportsDir = (0, import_path70.join)(this.projectRoot, ".gossip", "consensus-reports");
31853
32228
  let retractedConsensusIds = [];
31854
32229
  let roundRetractions = [];
31855
32230
  try {
@@ -31859,13 +32234,13 @@ var init_routes = __esm({
31859
32234
  roundRetractions = reader.getRoundRetractions();
31860
32235
  } catch {
31861
32236
  }
31862
- if (!existsSync69(reportsDir)) return { reports: [], totalReports: 0, page, pageSize, retractedConsensusIds, roundRetractions };
32237
+ if (!existsSync70(reportsDir)) return { reports: [], totalReports: 0, page, pageSize, retractedConsensusIds, roundRetractions };
31863
32238
  try {
31864
- const { statSync: statSync34 } = require("fs");
32239
+ const { statSync: statSync35 } = require("fs");
31865
32240
  const allFiles = readdirSync22(reportsDir).filter((f) => f.endsWith(".json")).sort((a, b) => {
31866
32241
  try {
31867
- const aTime = statSync34((0, import_path69.join)(reportsDir, a)).mtimeMs;
31868
- const bTime = statSync34((0, import_path69.join)(reportsDir, b)).mtimeMs;
32242
+ const aTime = statSync35((0, import_path70.join)(reportsDir, a)).mtimeMs;
32243
+ const bTime = statSync35((0, import_path70.join)(reportsDir, b)).mtimeMs;
31869
32244
  return bTime - aTime;
31870
32245
  } catch {
31871
32246
  return 0;
@@ -31876,13 +32251,13 @@ var init_routes = __esm({
31876
32251
  const clampedPage = Math.max(page, 1);
31877
32252
  const start = (clampedPage - 1) * clampedPageSize;
31878
32253
  const files = allFiles.slice(start, start + clampedPageSize);
31879
- const realReportsDir = (0, import_fs63.realpathSync)(reportsDir);
32254
+ const realReportsDir = (0, import_fs64.realpathSync)(reportsDir);
31880
32255
  const reports = files.map((f) => {
31881
32256
  try {
31882
- const filePath = (0, import_path69.join)(reportsDir, f);
31883
- const realFile = (0, import_fs63.realpathSync)(filePath);
32257
+ const filePath = (0, import_path70.join)(reportsDir, f);
32258
+ const realFile = (0, import_fs64.realpathSync)(filePath);
31884
32259
  if (!realFile.startsWith(realReportsDir + "/")) return null;
31885
- return JSON.parse(readFileSync62(realFile, "utf-8"));
32260
+ return JSON.parse(readFileSync64(realFile, "utf-8"));
31886
32261
  } catch {
31887
32262
  return null;
31888
32263
  }
@@ -31893,29 +32268,29 @@ var init_routes = __esm({
31893
32268
  }
31894
32269
  }
31895
32270
  archiveFindings() {
31896
- const { readdirSync: readdirSync22, readFileSync: readFileSync62, renameSync: renameSync15, writeFileSync: writeFileSync34, mkdirSync: mkdirSync41, existsSync: existsSync69 } = require("fs");
31897
- const reportsDir = (0, import_path69.join)(this.projectRoot, ".gossip", "consensus-reports");
31898
- const archiveDir = (0, import_path69.join)(this.projectRoot, ".gossip", "consensus-reports-archive");
32271
+ const { readdirSync: readdirSync22, readFileSync: readFileSync64, renameSync: renameSync15, writeFileSync: writeFileSync34, mkdirSync: mkdirSync41, existsSync: existsSync70 } = require("fs");
32272
+ const reportsDir = (0, import_path70.join)(this.projectRoot, ".gossip", "consensus-reports");
32273
+ const archiveDir = (0, import_path70.join)(this.projectRoot, ".gossip", "consensus-reports-archive");
31899
32274
  let archived = 0;
31900
- if (existsSync69(reportsDir)) {
32275
+ if (existsSync70(reportsDir)) {
31901
32276
  const files = readdirSync22(reportsDir).filter((f) => f.endsWith(".json")).sort().reverse();
31902
32277
  if (files.length > 5) {
31903
32278
  mkdirSync41(archiveDir, { recursive: true });
31904
32279
  const toArchive = files.slice(5);
31905
32280
  for (const f of toArchive) {
31906
32281
  try {
31907
- renameSync15((0, import_path69.join)(reportsDir, f), (0, import_path69.join)(archiveDir, f));
32282
+ renameSync15((0, import_path70.join)(reportsDir, f), (0, import_path70.join)(archiveDir, f));
31908
32283
  archived++;
31909
32284
  } catch {
31910
32285
  }
31911
32286
  }
31912
32287
  }
31913
32288
  }
31914
- const findingsPath = (0, import_path69.join)(this.projectRoot, ".gossip", "implementation-findings.jsonl");
32289
+ const findingsPath = (0, import_path70.join)(this.projectRoot, ".gossip", "implementation-findings.jsonl");
31915
32290
  let findingsCleared = 0;
31916
- if (existsSync69(findingsPath)) {
32291
+ if (existsSync70(findingsPath)) {
31917
32292
  try {
31918
- const lines = readFileSync62(findingsPath, "utf-8").trim().split("\n").filter(Boolean);
32293
+ const lines = readFileSync64(findingsPath, "utf-8").trim().split("\n").filter(Boolean);
31919
32294
  const kept = lines.filter((line) => {
31920
32295
  try {
31921
32296
  const entry = JSON.parse(line);
@@ -31932,7 +32307,7 @@ var init_routes = __esm({
31932
32307
  } catch {
31933
32308
  }
31934
32309
  }
31935
- const remaining = existsSync69(reportsDir) ? readdirSync22(reportsDir).filter((f) => f.endsWith(".json")).length : 0;
32310
+ const remaining = existsSync70(reportsDir) ? readdirSync22(reportsDir).filter((f) => f.endsWith(".json")).length : 0;
31936
32311
  return { archived, remaining, findingsCleared };
31937
32312
  }
31938
32313
  json(res, status, data) {
@@ -31945,14 +32320,14 @@ var init_routes = __esm({
31945
32320
  });
31946
32321
 
31947
32322
  // packages/relay/src/dashboard/ws.ts
31948
- var import_ws3, import_fs64, import_fs65, import_path70, DashboardWs;
32323
+ var import_ws3, import_fs65, import_fs66, import_path71, DashboardWs;
31949
32324
  var init_ws = __esm({
31950
32325
  "packages/relay/src/dashboard/ws.ts"() {
31951
32326
  "use strict";
31952
32327
  import_ws3 = require("ws");
31953
- import_fs64 = require("fs");
31954
32328
  import_fs65 = require("fs");
31955
- import_path70 = require("path");
32329
+ import_fs66 = require("fs");
32330
+ import_path71 = require("path");
31956
32331
  DashboardWs = class {
31957
32332
  clients = /* @__PURE__ */ new Set();
31958
32333
  logWatcher = null;
@@ -31977,15 +32352,15 @@ var init_ws = __esm({
31977
32352
  /** Start watching mcp.log for new lines and broadcasting them to connected clients. */
31978
32353
  startLogWatcher(projectRoot) {
31979
32354
  this.stopLogWatcher();
31980
- this.logPath = (0, import_path70.join)(projectRoot, ".gossip", "mcp.log");
31981
- if (!(0, import_fs64.existsSync)(this.logPath)) return;
32355
+ this.logPath = (0, import_path71.join)(projectRoot, ".gossip", "mcp.log");
32356
+ if (!(0, import_fs65.existsSync)(this.logPath)) return;
31982
32357
  try {
31983
- this.logOffset = (0, import_fs64.statSync)(this.logPath).size;
32358
+ this.logOffset = (0, import_fs65.statSync)(this.logPath).size;
31984
32359
  } catch {
31985
32360
  this.logOffset = 0;
31986
32361
  }
31987
32362
  try {
31988
- this.logWatcher = (0, import_fs65.watch)(this.logPath, () => {
32363
+ this.logWatcher = (0, import_fs66.watch)(this.logPath, () => {
31989
32364
  if (this.clients.size === 0) return;
31990
32365
  this.readNewLines();
31991
32366
  });
@@ -32002,7 +32377,7 @@ var init_ws = __esm({
32002
32377
  if (this.logReading) return;
32003
32378
  this.logReading = true;
32004
32379
  try {
32005
- const currentSize = (0, import_fs64.statSync)(this.logPath).size;
32380
+ const currentSize = (0, import_fs65.statSync)(this.logPath).size;
32006
32381
  if (currentSize < this.logOffset) {
32007
32382
  this.logOffset = 0;
32008
32383
  this.logCarry = "";
@@ -32015,7 +32390,7 @@ var init_ws = __esm({
32015
32390
  const readFrom = capped ? (this.logCarry = "", this.logCapped = true, currentSize - 65536) : (this.logCapped = false, this.logOffset);
32016
32391
  let stream;
32017
32392
  try {
32018
- stream = (0, import_fs64.createReadStream)(this.logPath, { start: readFrom, end: currentSize - 1 });
32393
+ stream = (0, import_fs65.createReadStream)(this.logPath, { start: readFrom, end: currentSize - 1 });
32019
32394
  } catch {
32020
32395
  this.logReading = false;
32021
32396
  return;
@@ -32678,14 +33053,14 @@ __export(sandbox_exports, {
32678
33053
  });
32679
33054
  function rotateIfNeeded2(filePath, maxBytes) {
32680
33055
  try {
32681
- const st = (0, import_fs66.statSync)(filePath);
33056
+ const st = (0, import_fs67.statSync)(filePath);
32682
33057
  if (st.size < maxBytes) return;
32683
33058
  const rotated = filePath + ".1";
32684
33059
  try {
32685
- if ((0, import_fs66.existsSync)(rotated)) (0, import_fs66.unlinkSync)(rotated);
33060
+ if ((0, import_fs67.existsSync)(rotated)) (0, import_fs67.unlinkSync)(rotated);
32686
33061
  } catch {
32687
33062
  }
32688
- (0, import_fs66.renameSync)(filePath, rotated);
33063
+ (0, import_fs67.renameSync)(filePath, rotated);
32689
33064
  } catch {
32690
33065
  }
32691
33066
  }
@@ -32758,9 +33133,9 @@ Tests passing is NOT sufficient verification \u2014 the 2026-04-22 incident had
32758
33133
  }
32759
33134
  function readSandboxMode(projectRoot) {
32760
33135
  try {
32761
- const p = (0, import_path71.join)(projectRoot, ".gossip", "config.json");
32762
- if (!(0, import_fs66.existsSync)(p)) return "warn";
32763
- const raw = JSON.parse((0, import_fs66.readFileSync)(p, "utf-8"));
33136
+ const p = (0, import_path72.join)(projectRoot, ".gossip", "config.json");
33137
+ if (!(0, import_fs67.existsSync)(p)) return "warn";
33138
+ const raw = JSON.parse((0, import_fs67.readFileSync)(p, "utf-8"));
32764
33139
  const mode = raw?.sandboxEnforcement;
32765
33140
  if (mode === "off" || mode === "warn" || mode === "block") return mode;
32766
33141
  return "warn";
@@ -32770,8 +33145,8 @@ function readSandboxMode(projectRoot) {
32770
33145
  }
32771
33146
  function recordDispatchMetadata(projectRoot, meta3) {
32772
33147
  try {
32773
- const dir = (0, import_path71.join)(projectRoot, ".gossip");
32774
- (0, import_fs66.mkdirSync)(dir, { recursive: true });
33148
+ const dir = (0, import_path72.join)(projectRoot, ".gossip");
33149
+ (0, import_fs67.mkdirSync)(dir, { recursive: true });
32775
33150
  const snapshotted = { ...meta3 };
32776
33151
  if (meta3.writeMode === "scoped" || meta3.writeMode === "worktree") {
32777
33152
  try {
@@ -32789,15 +33164,15 @@ function recordDispatchMetadata(projectRoot, meta3) {
32789
33164
  } catch {
32790
33165
  }
32791
33166
  }
32792
- (0, import_fs66.appendFileSync)((0, import_path71.join)(dir, METADATA_FILE), JSON.stringify(snapshotted) + "\n");
33167
+ (0, import_fs67.appendFileSync)((0, import_path72.join)(dir, METADATA_FILE), JSON.stringify(snapshotted) + "\n");
32793
33168
  } catch {
32794
33169
  }
32795
33170
  }
32796
33171
  function updateDispatchMetadata(projectRoot, taskId, patch) {
32797
33172
  try {
32798
- const p = (0, import_path71.join)(projectRoot, ".gossip", METADATA_FILE);
32799
- if (!(0, import_fs66.existsSync)(p)) return false;
32800
- const raw = (0, import_fs66.readFileSync)(p, "utf-8");
33173
+ const p = (0, import_path72.join)(projectRoot, ".gossip", METADATA_FILE);
33174
+ if (!(0, import_fs67.existsSync)(p)) return false;
33175
+ const raw = (0, import_fs67.readFileSync)(p, "utf-8");
32801
33176
  const lines = raw.split("\n");
32802
33177
  let patched = false;
32803
33178
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -32815,7 +33190,7 @@ function updateDispatchMetadata(projectRoot, taskId, patch) {
32815
33190
  }
32816
33191
  }
32817
33192
  if (!patched) return false;
32818
- (0, import_fs66.writeFileSync)(p, lines.join("\n"));
33193
+ (0, import_fs67.writeFileSync)(p, lines.join("\n"));
32819
33194
  return true;
32820
33195
  } catch {
32821
33196
  return false;
@@ -32824,14 +33199,14 @@ function updateDispatchMetadata(projectRoot, taskId, patch) {
32824
33199
  function stampTaskSentinel(projectRoot, taskId) {
32825
33200
  if (!taskId) return null;
32826
33201
  try {
32827
- const dir = (0, import_path71.join)(projectRoot, ".gossip", SENTINEL_DIR);
32828
- (0, import_fs66.mkdirSync)(dir, { recursive: true });
33202
+ const dir = (0, import_path72.join)(projectRoot, ".gossip", SENTINEL_DIR);
33203
+ (0, import_fs67.mkdirSync)(dir, { recursive: true });
32829
33204
  const slug = taskId.replace(/[^a-zA-Z0-9_-]/g, "_");
32830
- const path7 = (0, import_path71.join)(dir, `${slug}.sentinel`);
32831
- const fd = (0, import_fs66.openSync)(path7, "w");
32832
- (0, import_fs66.closeSync)(fd);
33205
+ const path7 = (0, import_path72.join)(dir, `${slug}.sentinel`);
33206
+ const fd = (0, import_fs67.openSync)(path7, "w");
33207
+ (0, import_fs67.closeSync)(fd);
32833
33208
  const stampTime = new Date(Date.now() - 2e3);
32834
- (0, import_fs66.utimesSync)(path7, stampTime, stampTime);
33209
+ (0, import_fs67.utimesSync)(path7, stampTime, stampTime);
32835
33210
  return path7;
32836
33211
  } catch {
32837
33212
  return null;
@@ -32840,15 +33215,15 @@ function stampTaskSentinel(projectRoot, taskId) {
32840
33215
  function cleanupTaskSentinel(sentinelPath) {
32841
33216
  if (!sentinelPath) return;
32842
33217
  try {
32843
- (0, import_fs66.unlinkSync)(sentinelPath);
33218
+ (0, import_fs67.unlinkSync)(sentinelPath);
32844
33219
  } catch {
32845
33220
  }
32846
33221
  }
32847
33222
  function lookupDispatchMetadata(projectRoot, taskId) {
32848
33223
  try {
32849
- const p = (0, import_path71.join)(projectRoot, ".gossip", METADATA_FILE);
32850
- if (!(0, import_fs66.existsSync)(p)) return null;
32851
- const raw = (0, import_fs66.readFileSync)(p, "utf-8");
33224
+ const p = (0, import_path72.join)(projectRoot, ".gossip", METADATA_FILE);
33225
+ if (!(0, import_fs67.existsSync)(p)) return null;
33226
+ const raw = (0, import_fs67.readFileSync)(p, "utf-8");
32852
33227
  const lines = raw.split("\n").filter(Boolean);
32853
33228
  for (let i = lines.length - 1; i >= 0; i--) {
32854
33229
  try {
@@ -32880,21 +33255,21 @@ function parseGitStatus(porcelain) {
32880
33255
  function normalizeScope(scope, projectRoot) {
32881
33256
  let s = scope.trim();
32882
33257
  if (!s) return "";
32883
- if ((0, import_path71.isAbsolute)(s)) {
32884
- s = (0, import_path71.relative)(projectRoot, s);
33258
+ if ((0, import_path72.isAbsolute)(s)) {
33259
+ s = (0, import_path72.relative)(projectRoot, s);
32885
33260
  } else if (s.startsWith("./")) {
32886
33261
  s = s.slice(2);
32887
33262
  }
32888
- s = (0, import_path71.normalize)(s).replace(/\/+$/, "");
33263
+ s = (0, import_path72.normalize)(s).replace(/\/+$/, "");
32889
33264
  if (s === "." || s === "") return "";
32890
33265
  return s;
32891
33266
  }
32892
33267
  function isInsideScope(filePath, scope) {
32893
33268
  if (!scope) return true;
32894
- const f = (0, import_path71.normalize)(filePath).replace(/^\.\//, "");
33269
+ const f = (0, import_path72.normalize)(filePath).replace(/^\.\//, "");
32895
33270
  const s = scope.replace(/^\.\//, "").replace(/\/+$/, "");
32896
33271
  if (f === s) return true;
32897
- return f.startsWith(s + "/") || f.startsWith(s + import_path71.sep);
33272
+ return f.startsWith(s + "/") || f.startsWith(s + import_path72.sep);
32898
33273
  }
32899
33274
  function detectBoundaryEscapes(meta3, modifiedFiles, projectRoot) {
32900
33275
  const mode = meta3.writeMode;
@@ -32955,8 +33330,8 @@ function recordBoundaryEscape(projectRoot, meta3, violations, mode) {
32955
33330
  } catch {
32956
33331
  }
32957
33332
  try {
32958
- const dir = (0, import_path71.join)(projectRoot, ".gossip");
32959
- (0, import_fs66.mkdirSync)(dir, { recursive: true });
33333
+ const dir = (0, import_path72.join)(projectRoot, ".gossip");
33334
+ (0, import_fs67.mkdirSync)(dir, { recursive: true });
32960
33335
  const line = {
32961
33336
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
32962
33337
  taskId: meta3.taskId,
@@ -32967,15 +33342,15 @@ function recordBoundaryEscape(projectRoot, meta3, violations, mode) {
32967
33342
  action: mode
32968
33343
  // "warn" or "block"
32969
33344
  };
32970
- const escapeFile = (0, import_path71.join)(dir, BOUNDARY_ESCAPE_FILE);
33345
+ const escapeFile = (0, import_path72.join)(dir, BOUNDARY_ESCAPE_FILE);
32971
33346
  rotateIfNeeded2(escapeFile, MAX_BOUNDARY_ESCAPE_BYTES);
32972
- (0, import_fs66.appendFileSync)(escapeFile, JSON.stringify(line) + "\n");
33347
+ (0, import_fs67.appendFileSync)(escapeFile, JSON.stringify(line) + "\n");
32973
33348
  } catch {
32974
33349
  }
32975
33350
  }
32976
33351
  function canonicalize(p) {
32977
33352
  try {
32978
- return (0, import_path71.resolve)(p).replace(/\/+$/, "") || "/";
33353
+ return (0, import_path72.resolve)(p).replace(/\/+$/, "") || "/";
32979
33354
  } catch {
32980
33355
  return p.replace(/\/+$/, "") || "/";
32981
33356
  }
@@ -33186,7 +33561,7 @@ function buildAuditExclusions(projectRoot, ownWorktree, scope) {
33186
33561
  for (const v of expandTmpVariants(wt)) excl.add(v);
33187
33562
  }
33188
33563
  if (scope) {
33189
- const s = canonicalize((0, import_path71.join)(projectRoot, scope));
33564
+ const s = canonicalize((0, import_path72.join)(projectRoot, scope));
33190
33565
  for (const v of expandTmpVariants(s)) excl.add(v);
33191
33566
  }
33192
33567
  return Array.from(excl);
@@ -33240,12 +33615,12 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
33240
33615
  return { violations: [], skipped: "win32" };
33241
33616
  }
33242
33617
  const sentinel = meta3.sentinelPath;
33243
- if (!sentinel || !(0, import_fs66.existsSync)(sentinel)) {
33618
+ if (!sentinel || !(0, import_fs67.existsSync)(sentinel)) {
33244
33619
  return { violations: [], skipped: "sentinel missing" };
33245
33620
  }
33246
33621
  let sentinelMtimeMs = 0;
33247
33622
  try {
33248
- sentinelMtimeMs = (0, import_fs66.statSync)(sentinel).mtimeMs;
33623
+ sentinelMtimeMs = (0, import_fs67.statSync)(sentinel).mtimeMs;
33249
33624
  } catch {
33250
33625
  }
33251
33626
  if (sentinelMtimeMs === 0) {
@@ -33257,11 +33632,11 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
33257
33632
  );
33258
33633
  const exclusions = buildAuditExclusions(projectRoot, meta3.worktreePath, options.scope);
33259
33634
  const findBin = options.findBinary ?? "find";
33260
- const sentinelDir = canonicalize((0, import_path71.join)(projectRoot, ".gossip", SENTINEL_DIR));
33635
+ const sentinelDir = canonicalize((0, import_path72.join)(projectRoot, ".gossip", SENTINEL_DIR));
33261
33636
  const mainSet = /* @__PURE__ */ new Set();
33262
33637
  const sensitiveSet = /* @__PURE__ */ new Set();
33263
33638
  for (const root of scanRoots) {
33264
- if (!(0, import_fs66.existsSync)(root)) continue;
33639
+ if (!(0, import_fs67.existsSync)(root)) continue;
33265
33640
  const canonRoot = canonicalize(root);
33266
33641
  const allExcl = [...exclusions, ...expandTmpVariants(sentinelDir)];
33267
33642
  const args = buildFindPruneArgs(canonRoot, allExcl, sentinel);
@@ -33297,7 +33672,7 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
33297
33672
  }
33298
33673
  const sensitiveTargets = buildSensitiveTargets(platform2);
33299
33674
  for (const target of sensitiveTargets) {
33300
- if (!(0, import_fs66.existsSync)(target.path)) continue;
33675
+ if (!(0, import_fs67.existsSync)(target.path)) continue;
33301
33676
  const canonTarget = canonicalize(target.path);
33302
33677
  const args = buildSensitiveFindArgs(
33303
33678
  canonTarget,
@@ -33353,8 +33728,8 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
33353
33728
  }
33354
33729
  function recordLayer3Violations(projectRoot, meta3, violations, source) {
33355
33730
  try {
33356
- const dir = (0, import_path71.join)(projectRoot, ".gossip");
33357
- (0, import_fs66.mkdirSync)(dir, { recursive: true });
33731
+ const dir = (0, import_path72.join)(projectRoot, ".gossip");
33732
+ (0, import_fs67.mkdirSync)(dir, { recursive: true });
33358
33733
  const ts2 = (/* @__PURE__ */ new Date()).toISOString();
33359
33734
  const lines = violations.map(
33360
33735
  (path7) => JSON.stringify({
@@ -33365,9 +33740,9 @@ function recordLayer3Violations(projectRoot, meta3, violations, source) {
33365
33740
  source
33366
33741
  })
33367
33742
  );
33368
- const escapeFile = (0, import_path71.join)(dir, BOUNDARY_ESCAPE_FILE);
33743
+ const escapeFile = (0, import_path72.join)(dir, BOUNDARY_ESCAPE_FILE);
33369
33744
  rotateIfNeeded2(escapeFile, MAX_BOUNDARY_ESCAPE_BYTES);
33370
- (0, import_fs66.appendFileSync)(escapeFile, lines.join("\n") + "\n");
33745
+ (0, import_fs67.appendFileSync)(escapeFile, lines.join("\n") + "\n");
33371
33746
  } catch {
33372
33747
  }
33373
33748
  if (source === "layer3-sensitive" && violations.length > 0) {
@@ -33424,14 +33799,14 @@ function runLayer3Audit(projectRoot, taskId) {
33424
33799
  }
33425
33800
  return { blockError, warnPrefix };
33426
33801
  }
33427
- var import_child_process10, import_fs66, import_os5, import_path71, METADATA_FILE, BOUNDARY_ESCAPE_FILE, SENTINEL_DIR, MAX_BOUNDARY_ESCAPE_BYTES, MAX_PREMISE_VERIFICATION_BYTES, BOUNDARY_ALLOWLIST, SYSTEM_PREFIXES, SCOPE_NOTE, NUMERAL, TARGETS, MODIFIER, CLAIM_PATTERNS, UNVERIFIED_NOTE_SENTINEL, __test__;
33802
+ var import_child_process10, import_fs67, import_os5, import_path72, METADATA_FILE, BOUNDARY_ESCAPE_FILE, SENTINEL_DIR, MAX_BOUNDARY_ESCAPE_BYTES, MAX_PREMISE_VERIFICATION_BYTES, BOUNDARY_ALLOWLIST, SYSTEM_PREFIXES, SCOPE_NOTE, NUMERAL, TARGETS, MODIFIER, CLAIM_PATTERNS, UNVERIFIED_NOTE_SENTINEL, __test__;
33428
33803
  var init_sandbox2 = __esm({
33429
33804
  "apps/cli/src/sandbox.ts"() {
33430
33805
  "use strict";
33431
33806
  import_child_process10 = require("child_process");
33432
- import_fs66 = require("fs");
33807
+ import_fs67 = require("fs");
33433
33808
  import_os5 = require("os");
33434
- import_path71 = require("path");
33809
+ import_path72 = require("path");
33435
33810
  METADATA_FILE = "dispatch-metadata.jsonl";
33436
33811
  BOUNDARY_ESCAPE_FILE = "boundary-escapes.jsonl";
33437
33812
  SENTINEL_DIR = "sentinels";
@@ -33502,7 +33877,7 @@ __export(dispatch_prompt_storage_exports, {
33502
33877
  writeDispatchPrompt: () => writeDispatchPrompt
33503
33878
  });
33504
33879
  function dispatchPromptsDir(projectRoot) {
33505
- return (0, import_path72.join)(projectRoot, ".gossip", DISPATCH_PROMPTS_SUBDIR);
33880
+ return (0, import_path73.join)(projectRoot, ".gossip", DISPATCH_PROMPTS_SUBDIR);
33506
33881
  }
33507
33882
  function assertSafeTaskId(taskId) {
33508
33883
  if (typeof taskId !== "string" || taskId.length === 0) {
@@ -33515,35 +33890,35 @@ function assertSafeTaskId(taskId) {
33515
33890
  function writeDispatchPrompt(projectRoot, taskId, body) {
33516
33891
  assertSafeTaskId(taskId);
33517
33892
  const dir = dispatchPromptsDir(projectRoot);
33518
- (0, import_fs67.mkdirSync)(dir, { recursive: true });
33519
- const finalPath = (0, import_path72.join)(dir, `${taskId}.txt`);
33520
- const tmpPath = (0, import_path72.join)(dir, `${taskId}.txt.${(0, import_crypto27.randomUUID)().slice(0, 8)}.tmp`);
33893
+ (0, import_fs68.mkdirSync)(dir, { recursive: true });
33894
+ const finalPath = (0, import_path73.join)(dir, `${taskId}.txt`);
33895
+ const tmpPath = (0, import_path73.join)(dir, `${taskId}.txt.${(0, import_crypto27.randomUUID)().slice(0, 8)}.tmp`);
33521
33896
  try {
33522
- (0, import_fs67.writeFileSync)(tmpPath, body, "utf8");
33523
- (0, import_fs67.renameSync)(tmpPath, finalPath);
33897
+ (0, import_fs68.writeFileSync)(tmpPath, body, "utf8");
33898
+ (0, import_fs68.renameSync)(tmpPath, finalPath);
33524
33899
  } catch (err) {
33525
33900
  try {
33526
- (0, import_fs67.unlinkSync)(tmpPath);
33901
+ (0, import_fs68.unlinkSync)(tmpPath);
33527
33902
  } catch {
33528
33903
  }
33529
33904
  throw err;
33530
33905
  }
33531
- return (0, import_path72.resolve)(finalPath);
33906
+ return (0, import_path73.resolve)(finalPath);
33532
33907
  }
33533
33908
  function cleanupExpiredDispatchPrompts(projectRoot, maxAgeMs = DEFAULT_PROMPT_TTL_MS, capBytes = DISPATCH_PROMPT_CAP_BYTES) {
33534
33909
  const dir = dispatchPromptsDir(projectRoot);
33535
- if (!(0, import_fs67.existsSync)(dir)) return { evictedAge: 0, evictedCap: 0 };
33910
+ if (!(0, import_fs68.existsSync)(dir)) return { evictedAge: 0, evictedCap: 0 };
33536
33911
  const now = Date.now();
33537
33912
  let entries = [];
33538
33913
  try {
33539
- for (const name of (0, import_fs67.readdirSync)(dir)) {
33540
- const path7 = (0, import_path72.join)(dir, name);
33914
+ for (const name of (0, import_fs68.readdirSync)(dir)) {
33915
+ const path7 = (0, import_path73.join)(dir, name);
33541
33916
  try {
33542
- const st = (0, import_fs67.statSync)(path7);
33917
+ const st = (0, import_fs68.statSync)(path7);
33543
33918
  if (!st.isFile()) continue;
33544
33919
  entries.push({ name, path: path7, mtimeMs: st.mtimeMs, size: st.size });
33545
33920
  } catch (err) {
33546
- process.stderr.write(`[gossipcat] dispatch-prompt stat failed for ${(0, import_path72.basename)(path7)}: ${err.message}
33921
+ process.stderr.write(`[gossipcat] dispatch-prompt stat failed for ${(0, import_path73.basename)(path7)}: ${err.message}
33547
33922
  `);
33548
33923
  }
33549
33924
  }
@@ -33557,7 +33932,7 @@ function cleanupExpiredDispatchPrompts(projectRoot, maxAgeMs = DEFAULT_PROMPT_TT
33557
33932
  for (const e of entries) {
33558
33933
  if (now - e.mtimeMs > maxAgeMs) {
33559
33934
  try {
33560
- (0, import_fs67.unlinkSync)(e.path);
33935
+ (0, import_fs68.unlinkSync)(e.path);
33561
33936
  evictedAge++;
33562
33937
  } catch (err) {
33563
33938
  process.stderr.write(`[gossipcat] dispatch-prompt unlink failed for ${e.name}: ${err.message}
@@ -33574,7 +33949,7 @@ function cleanupExpiredDispatchPrompts(projectRoot, maxAgeMs = DEFAULT_PROMPT_TT
33574
33949
  for (const e of survivors) {
33575
33950
  if (totalBytes <= capBytes) break;
33576
33951
  try {
33577
- (0, import_fs67.unlinkSync)(e.path);
33952
+ (0, import_fs68.unlinkSync)(e.path);
33578
33953
  totalBytes -= e.size;
33579
33954
  evictedCap++;
33580
33955
  } catch (err) {
@@ -33587,18 +33962,18 @@ function cleanupExpiredDispatchPrompts(projectRoot, maxAgeMs = DEFAULT_PROMPT_TT
33587
33962
  }
33588
33963
  function pruneOrphanDispatchPrompts(projectRoot, knownTaskIds, maxAgeMs = DEFAULT_PROMPT_TTL_MS) {
33589
33964
  const dir = dispatchPromptsDir(projectRoot);
33590
- if (!(0, import_fs67.existsSync)(dir)) return { orphans: 0, aged: 0 };
33965
+ if (!(0, import_fs68.existsSync)(dir)) return { orphans: 0, aged: 0 };
33591
33966
  const now = Date.now();
33592
33967
  let orphans = 0;
33593
33968
  let aged = 0;
33594
33969
  try {
33595
- for (const name of (0, import_fs67.readdirSync)(dir)) {
33970
+ for (const name of (0, import_fs68.readdirSync)(dir)) {
33596
33971
  if (!name.endsWith(".txt")) continue;
33597
33972
  const taskId = name.slice(0, -4);
33598
- const path7 = (0, import_path72.join)(dir, name);
33973
+ const path7 = (0, import_path73.join)(dir, name);
33599
33974
  let mtimeMs = 0;
33600
33975
  try {
33601
- mtimeMs = (0, import_fs67.statSync)(path7).mtimeMs;
33976
+ mtimeMs = (0, import_fs68.statSync)(path7).mtimeMs;
33602
33977
  } catch {
33603
33978
  continue;
33604
33979
  }
@@ -33606,7 +33981,7 @@ function pruneOrphanDispatchPrompts(projectRoot, knownTaskIds, maxAgeMs = DEFAUL
33606
33981
  const orphaned = !knownTaskIds.has(taskId);
33607
33982
  if (tooOld || orphaned) {
33608
33983
  try {
33609
- (0, import_fs67.unlinkSync)(path7);
33984
+ (0, import_fs68.unlinkSync)(path7);
33610
33985
  if (orphaned) orphans++;
33611
33986
  if (tooOld) aged++;
33612
33987
  } catch (err) {
@@ -33623,14 +33998,14 @@ function pruneOrphanDispatchPrompts(projectRoot, knownTaskIds, maxAgeMs = DEFAUL
33623
33998
  }
33624
33999
  function dispatchPromptPath(projectRoot, taskId) {
33625
34000
  assertSafeTaskId(taskId);
33626
- return (0, import_path72.resolve)((0, import_path72.join)(dispatchPromptsDir(projectRoot), `${taskId}.txt`));
34001
+ return (0, import_path73.resolve)((0, import_path73.join)(dispatchPromptsDir(projectRoot), `${taskId}.txt`));
33627
34002
  }
33628
- var import_fs67, import_path72, import_crypto27, SAFE_TASK_ID, DISPATCH_PROMPT_CAP_BYTES, DEFAULT_PROMPT_TTL_MS, DISPATCH_PROMPTS_SUBDIR;
34003
+ var import_fs68, import_path73, import_crypto27, SAFE_TASK_ID, DISPATCH_PROMPT_CAP_BYTES, DEFAULT_PROMPT_TTL_MS, DISPATCH_PROMPTS_SUBDIR;
33629
34004
  var init_dispatch_prompt_storage = __esm({
33630
34005
  "apps/cli/src/handlers/dispatch-prompt-storage.ts"() {
33631
34006
  "use strict";
33632
- import_fs67 = require("fs");
33633
- import_path72 = require("path");
34007
+ import_fs68 = require("fs");
34008
+ import_path73 = require("path");
33634
34009
  import_crypto27 = require("crypto");
33635
34010
  SAFE_TASK_ID = /^(?!.*\.\.)[A-Za-z0-9._-]{1,64}$/;
33636
34011
  DISPATCH_PROMPT_CAP_BYTES = 100 * 1024 * 1024;
@@ -33684,9 +34059,9 @@ function getCommitRange(preSha, postSha) {
33684
34059
  function appendViolationRecord(record2) {
33685
34060
  try {
33686
34061
  const projectRoot = process.cwd();
33687
- (0, import_fs68.mkdirSync)((0, import_path73.join)(projectRoot, ".gossip"), { recursive: true });
33688
- const logPath = (0, import_path73.join)(projectRoot, PROCESS_VIOLATIONS_FILE);
33689
- (0, import_fs68.appendFileSync)(logPath, JSON.stringify(record2) + "\n", "utf8");
34062
+ (0, import_fs69.mkdirSync)((0, import_path74.join)(projectRoot, ".gossip"), { recursive: true });
34063
+ const logPath = (0, import_path74.join)(projectRoot, PROCESS_VIOLATIONS_FILE);
34064
+ (0, import_fs69.appendFileSync)(logPath, JSON.stringify(record2) + "\n", "utf8");
33690
34065
  } catch (err) {
33691
34066
  process.stderr.write(`[gossipcat] ref-allowlist: failed to append violation record: ${err.message}
33692
34067
  `);
@@ -33736,12 +34111,12 @@ Full audit trail at .gossip/process-violations.jsonl
33736
34111
  `
33737
34112
  );
33738
34113
  }
33739
- var import_fs68, import_path73, import_child_process11, PROCESS_VIOLATIONS_FILE;
34114
+ var import_fs69, import_path74, import_child_process11, PROCESS_VIOLATIONS_FILE;
33740
34115
  var init_ref_allowlist_detection = __esm({
33741
34116
  "apps/cli/src/handlers/ref-allowlist-detection.ts"() {
33742
34117
  "use strict";
33743
- import_fs68 = require("fs");
33744
- import_path73 = require("path");
34118
+ import_fs69 = require("fs");
34119
+ import_path74 = require("path");
33745
34120
  import_child_process11 = require("child_process");
33746
34121
  PROCESS_VIOLATIONS_FILE = ".gossip/process-violations.jsonl";
33747
34122
  }
@@ -33827,10 +34202,10 @@ function taskWasInConsensusRound(taskId, agentId, rounds, recentTaskIds, recentA
33827
34202
  function appendRelayWarning(projectRoot, entry) {
33828
34203
  try {
33829
34204
  const { appendFileSync: appendFileSync21, mkdirSync: mkdirSync41 } = require("fs");
33830
- const { join: join82 } = require("path");
33831
- const dir = join82(projectRoot, ".gossip");
34205
+ const { join: join83 } = require("path");
34206
+ const dir = join83(projectRoot, ".gossip");
33832
34207
  mkdirSync41(dir, { recursive: true });
33833
- appendFileSync21(join82(dir, RELAY_WARNINGS_FILE), JSON.stringify(entry) + "\n", "utf8");
34208
+ appendFileSync21(join83(dir, RELAY_WARNINGS_FILE), JSON.stringify(entry) + "\n", "utf8");
33834
34209
  } catch (err) {
33835
34210
  process.stderr.write(`[gossipcat] append relay-warning failed: ${err.message}
33836
34211
  `);
@@ -34557,7 +34932,7 @@ function computeSkillFingerprint(paths) {
34557
34932
  const pairs = [];
34558
34933
  for (const p of paths) {
34559
34934
  try {
34560
- const st = (0, import_fs69.statSync)(p);
34935
+ const st = (0, import_fs70.statSync)(p);
34561
34936
  pairs.push(`${p}:${st.mtimeMs}`);
34562
34937
  } catch {
34563
34938
  }
@@ -34592,7 +34967,7 @@ function setCachedPrompt(k, e) {
34592
34967
  const evicted = promptCache.get(oldestKey);
34593
34968
  promptCache.delete(oldestKey);
34594
34969
  try {
34595
- (0, import_fs69.unlinkSync)(evicted.skillsSectionPath);
34970
+ (0, import_fs70.unlinkSync)(evicted.skillsSectionPath);
34596
34971
  } catch {
34597
34972
  }
34598
34973
  const evictedAgentId = oldestKey.split("|")[0] ?? "_system";
@@ -34606,7 +34981,7 @@ function invalidateAgent(agentId) {
34606
34981
  if (k.startsWith(`${agentId}|`)) {
34607
34982
  promptCache.delete(k);
34608
34983
  try {
34609
- (0, import_fs69.unlinkSync)(v.skillsSectionPath);
34984
+ (0, import_fs70.unlinkSync)(v.skillsSectionPath);
34610
34985
  } catch {
34611
34986
  }
34612
34987
  emitCacheEvictedSignal(agentId, "invalidation");
@@ -34619,7 +34994,7 @@ function invalidateAll() {
34619
34994
  const n = promptCache.size;
34620
34995
  for (const v of promptCache.values()) {
34621
34996
  try {
34622
- (0, import_fs69.unlinkSync)(v.skillsSectionPath);
34997
+ (0, import_fs70.unlinkSync)(v.skillsSectionPath);
34623
34998
  } catch {
34624
34999
  }
34625
35000
  }
@@ -34666,29 +35041,29 @@ function writeCachedSkillsSection(projectRoot, fingerprint2, skillsSection) {
34666
35041
  if (!/^[a-f0-9]{64}$/.test(fingerprint2)) {
34667
35042
  throw new Error(`writeCachedSkillsSection: invalid fingerprint ${JSON.stringify(fingerprint2).slice(0, 32)}`);
34668
35043
  }
34669
- const dir = (0, import_path74.join)(projectRoot, ".gossip", "dispatch-prompts", "cache");
34670
- (0, import_fs69.mkdirSync)(dir, { recursive: true });
34671
- const finalPath = (0, import_path74.join)(dir, `skills-${fingerprint2}.txt`);
34672
- const tmpPath = (0, import_path74.join)(dir, `skills-${fingerprint2}.txt.${(0, import_crypto30.randomUUID)().slice(0, 8)}.tmp`);
35044
+ const dir = (0, import_path75.join)(projectRoot, ".gossip", "dispatch-prompts", "cache");
35045
+ (0, import_fs70.mkdirSync)(dir, { recursive: true });
35046
+ const finalPath = (0, import_path75.join)(dir, `skills-${fingerprint2}.txt`);
35047
+ const tmpPath = (0, import_path75.join)(dir, `skills-${fingerprint2}.txt.${(0, import_crypto30.randomUUID)().slice(0, 8)}.tmp`);
34673
35048
  try {
34674
- (0, import_fs69.writeFileSync)(tmpPath, skillsSection, "utf8");
34675
- (0, import_fs69.renameSync)(tmpPath, finalPath);
35049
+ (0, import_fs70.writeFileSync)(tmpPath, skillsSection, "utf8");
35050
+ (0, import_fs70.renameSync)(tmpPath, finalPath);
34676
35051
  } catch (err) {
34677
35052
  try {
34678
- (0, import_fs69.unlinkSync)(tmpPath);
35053
+ (0, import_fs70.unlinkSync)(tmpPath);
34679
35054
  } catch {
34680
35055
  }
34681
35056
  throw err;
34682
35057
  }
34683
- return (0, import_path74.resolve)(finalPath);
35058
+ return (0, import_path75.resolve)(finalPath);
34684
35059
  }
34685
- var import_crypto29, import_fs69, import_path74, import_crypto30, DISPATCH_PROMPT_CACHE_MAX_ENTRIES, promptCache;
35060
+ var import_crypto29, import_fs70, import_path75, import_crypto30, DISPATCH_PROMPT_CACHE_MAX_ENTRIES, promptCache;
34686
35061
  var init_dispatch_prompt_cache = __esm({
34687
35062
  "apps/cli/src/handlers/dispatch-prompt-cache.ts"() {
34688
35063
  "use strict";
34689
35064
  import_crypto29 = require("crypto");
34690
- import_fs69 = require("fs");
34691
- import_path74 = require("path");
35065
+ import_fs70 = require("fs");
35066
+ import_path75 = require("path");
34692
35067
  import_crypto30 = require("crypto");
34693
35068
  DISPATCH_PROMPT_CACHE_MAX_ENTRIES = 64;
34694
35069
  promptCache = /* @__PURE__ */ new Map();
@@ -34711,18 +35086,18 @@ __export(config_exports, {
34711
35086
  function findConfigPath(projectRoot) {
34712
35087
  const root = projectRoot || process.cwd();
34713
35088
  const candidates = [
34714
- (0, import_path75.resolve)(root, ".gossip", "config.json"),
34715
- (0, import_path75.resolve)(root, "gossip.agents.json"),
34716
- (0, import_path75.resolve)(root, "gossip.agents.yaml"),
34717
- (0, import_path75.resolve)(root, "gossip.agents.yml")
35089
+ (0, import_path76.resolve)(root, ".gossip", "config.json"),
35090
+ (0, import_path76.resolve)(root, "gossip.agents.json"),
35091
+ (0, import_path76.resolve)(root, "gossip.agents.yaml"),
35092
+ (0, import_path76.resolve)(root, "gossip.agents.yml")
34718
35093
  ];
34719
35094
  for (const p of candidates) {
34720
- if ((0, import_fs70.existsSync)(p)) return p;
35095
+ if ((0, import_fs71.existsSync)(p)) return p;
34721
35096
  }
34722
35097
  return null;
34723
35098
  }
34724
35099
  function loadConfig(configPath) {
34725
- const raw = (0, import_fs70.readFileSync)(configPath, "utf-8");
35100
+ const raw = (0, import_fs71.readFileSync)(configPath, "utf-8");
34726
35101
  let parsed;
34727
35102
  try {
34728
35103
  parsed = JSON.parse(raw);
@@ -34812,19 +35187,19 @@ function configToAgentConfigs(config2) {
34812
35187
  }
34813
35188
  function loadClaudeSubagents(projectRoot, existingIds) {
34814
35189
  const root = projectRoot || process.cwd();
34815
- const agentsDir = (0, import_path75.join)(root, ".claude", "agents");
34816
- if (!(0, import_fs70.existsSync)(agentsDir)) return [];
35190
+ const agentsDir = (0, import_path76.join)(root, ".claude", "agents");
35191
+ if (!(0, import_fs71.existsSync)(agentsDir)) return [];
34817
35192
  let files;
34818
35193
  try {
34819
- files = (0, import_fs70.readdirSync)(agentsDir).filter((f) => f.endsWith(".md"));
35194
+ files = (0, import_fs71.readdirSync)(agentsDir).filter((f) => f.endsWith(".md"));
34820
35195
  } catch {
34821
35196
  return [];
34822
35197
  }
34823
35198
  const agents = [];
34824
35199
  for (const file2 of files) {
34825
- const filePath = (0, import_path75.join)(agentsDir, file2);
35200
+ const filePath = (0, import_path76.join)(agentsDir, file2);
34826
35201
  try {
34827
- const content = (0, import_fs70.readFileSync)(filePath, "utf-8");
35202
+ const content = (0, import_fs71.readFileSync)(filePath, "utf-8");
34828
35203
  const frontmatter = content.match(/^---\n([\s\S]*?)\n---/);
34829
35204
  if (!frontmatter) continue;
34830
35205
  const fm = frontmatter[1];
@@ -34879,12 +35254,12 @@ function inferSkills(description, name) {
34879
35254
  if (skills.length === 0) skills.push("general");
34880
35255
  return skills;
34881
35256
  }
34882
- var import_fs70, import_path75, VALID_PROVIDERS, VALID_MAIN_PROVIDERS, CLAUDE_MODEL_MAP;
35257
+ var import_fs71, import_path76, VALID_PROVIDERS, VALID_MAIN_PROVIDERS, CLAUDE_MODEL_MAP;
34883
35258
  var init_config = __esm({
34884
35259
  "apps/cli/src/config.ts"() {
34885
35260
  "use strict";
34886
- import_fs70 = require("fs");
34887
- import_path75 = require("path");
35261
+ import_fs71 = require("fs");
35262
+ import_path76 = require("path");
34888
35263
  VALID_PROVIDERS = ["anthropic", "openai", "openclaw", "google", "local", "native", "none"];
34889
35264
  VALID_MAIN_PROVIDERS = VALID_PROVIDERS.filter((p) => p !== "native");
34890
35265
  CLAUDE_MODEL_MAP = {
@@ -34954,11 +35329,11 @@ function startConsensusTimeout(consensusId) {
34954
35329
  const report = await engine.synthesizeWithCrossReview(snapshot.allResults, allEntries, consensusId, snapshot.relayCrossReviewSkipped);
34955
35330
  try {
34956
35331
  const { writeFileSync: writeFileSync34, mkdirSync: mkdirSync41 } = require("fs");
34957
- const { join: join82 } = require("path");
34958
- const reportsDir = join82(process.cwd(), ".gossip", "consensus-reports");
35332
+ const { join: join83 } = require("path");
35333
+ const reportsDir = join83(process.cwd(), ".gossip", "consensus-reports");
34959
35334
  mkdirSync41(reportsDir, { recursive: true });
34960
35335
  const topic = snapshot.allResults?.find((r) => r.task)?.task?.slice(0, 500) || "";
34961
- writeFileSync34(join82(reportsDir, `${consensusId}.json`), JSON.stringify({
35336
+ writeFileSync34(join83(reportsDir, `${consensusId}.json`), JSON.stringify({
34962
35337
  id: consensusId,
34963
35338
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
34964
35339
  topic,
@@ -35126,10 +35501,10 @@ async function handleRelayCrossReview(consensus_id, agent_id, result) {
35126
35501
  );
35127
35502
  try {
35128
35503
  const { writeFileSync: writeFileSync34, mkdirSync: mkdirSync41 } = require("fs");
35129
- const { join: join82 } = require("path");
35130
- const reportsDir = join82(process.cwd(), ".gossip", "consensus-reports");
35504
+ const { join: join83 } = require("path");
35505
+ const reportsDir = join83(process.cwd(), ".gossip", "consensus-reports");
35131
35506
  mkdirSync41(reportsDir, { recursive: true });
35132
- const reportPath = join82(reportsDir, `${consensus_id}.json`);
35507
+ const reportPath = join83(reportsDir, `${consensus_id}.json`);
35133
35508
  const topic = synthSnapshot.allResults?.find((r) => r.task)?.task?.slice(0, 500) || "";
35134
35509
  writeFileSync34(reportPath, JSON.stringify({
35135
35510
  id: consensus_id,
@@ -35175,8 +35550,8 @@ function persistPendingConsensus() {
35175
35550
  const projectRoot = ctx.mainAgent?.projectRoot;
35176
35551
  if (!projectRoot) return;
35177
35552
  const { writeFileSync: writeFileSync34, mkdirSync: mkdirSync41 } = require("fs");
35178
- const { join: join82 } = require("path");
35179
- const dir = join82(projectRoot, ".gossip");
35553
+ const { join: join83 } = require("path");
35554
+ const dir = join83(projectRoot, ".gossip");
35180
35555
  mkdirSync41(dir, { recursive: true });
35181
35556
  const rounds = {};
35182
35557
  for (const [id, round] of ctx.pendingConsensusRounds) {
@@ -35202,7 +35577,7 @@ function persistPendingConsensus() {
35202
35577
  resolutionRoots: round.resolutionRoots ? [...round.resolutionRoots] : void 0
35203
35578
  };
35204
35579
  }
35205
- writeFileSync34(join82(dir, CONSENSUS_FILE), JSON.stringify(rounds));
35580
+ writeFileSync34(join83(dir, CONSENSUS_FILE), JSON.stringify(rounds));
35206
35581
  } catch (err) {
35207
35582
  process.stderr.write(`[gossipcat] persistPendingConsensus failed: ${err.message}
35208
35583
  `);
@@ -35210,11 +35585,11 @@ function persistPendingConsensus() {
35210
35585
  }
35211
35586
  function restorePendingConsensus(projectRoot) {
35212
35587
  try {
35213
- const { existsSync: existsSync69, readFileSync: readFileSync62, unlinkSync: unlinkSync13 } = require("fs");
35214
- const { join: join82 } = require("path");
35215
- const filePath = join82(projectRoot, ".gossip", CONSENSUS_FILE);
35216
- if (!existsSync69(filePath)) return;
35217
- const raw = JSON.parse(readFileSync62(filePath, "utf-8"));
35588
+ const { existsSync: existsSync70, readFileSync: readFileSync64, unlinkSync: unlinkSync13 } = require("fs");
35589
+ const { join: join83 } = require("path");
35590
+ const filePath = join83(projectRoot, ".gossip", CONSENSUS_FILE);
35591
+ if (!existsSync70(filePath)) return;
35592
+ const raw = JSON.parse(readFileSync64(filePath, "utf-8"));
35218
35593
  const now = Date.now();
35219
35594
  for (const [id, data] of Object.entries(raw)) {
35220
35595
  if (now > data.deadline + 3e5) {
@@ -35322,31 +35697,31 @@ __export(check_effectiveness_runner_exports, {
35322
35697
  runCheckEffectivenessForAllSkills: () => runCheckEffectivenessForAllSkills
35323
35698
  });
35324
35699
  function writeHealthAtomic(projectRoot, record2) {
35325
- const dir = (0, import_path77.join)(projectRoot, ".gossip");
35326
- const finalPath = (0, import_path77.join)(dir, "skill-runner-health.json");
35700
+ const dir = (0, import_path78.join)(projectRoot, ".gossip");
35701
+ const finalPath = (0, import_path78.join)(dir, "skill-runner-health.json");
35327
35702
  const tmpPath = finalPath + ".tmp";
35328
35703
  try {
35329
- (0, import_fs73.mkdirSync)(dir, { recursive: true });
35330
- (0, import_fs73.writeFileSync)(tmpPath, JSON.stringify(record2, null, 2));
35331
- (0, import_fs73.renameSync)(tmpPath, finalPath);
35704
+ (0, import_fs74.mkdirSync)(dir, { recursive: true });
35705
+ (0, import_fs74.writeFileSync)(tmpPath, JSON.stringify(record2, null, 2));
35706
+ (0, import_fs74.renameSync)(tmpPath, finalPath);
35332
35707
  } catch (e) {
35333
35708
  process.stderr.write(`[gossipcat] checkEffectiveness: health write failed: ${e.message}
35334
35709
  `);
35335
35710
  try {
35336
- if ((0, import_fs73.existsSync)(tmpPath)) (0, import_fs73.unlinkSync)(tmpPath);
35711
+ if ((0, import_fs74.existsSync)(tmpPath)) (0, import_fs74.unlinkSync)(tmpPath);
35337
35712
  } catch {
35338
35713
  }
35339
35714
  }
35340
35715
  }
35341
35716
  async function runCheckEffectivenessForAllSkills(opts) {
35342
35717
  const startedAt = Date.now();
35343
- const baseDir = (0, import_path77.join)(opts.projectRoot, ".gossip", "agents");
35718
+ const baseDir = (0, import_path78.join)(opts.projectRoot, ".gossip", "agents");
35344
35719
  let agentDirs = [];
35345
35720
  let canonicalBaseDir;
35346
- if ((0, import_fs73.existsSync)(baseDir)) {
35721
+ if ((0, import_fs74.existsSync)(baseDir)) {
35347
35722
  try {
35348
- canonicalBaseDir = (0, import_fs73.realpathSync)(baseDir);
35349
- agentDirs = (0, import_fs73.readdirSync)(canonicalBaseDir);
35723
+ canonicalBaseDir = (0, import_fs74.realpathSync)(baseDir);
35724
+ agentDirs = (0, import_fs74.readdirSync)(canonicalBaseDir);
35350
35725
  } catch {
35351
35726
  }
35352
35727
  }
@@ -35365,11 +35740,11 @@ async function runCheckEffectivenessForAllSkills(opts) {
35365
35740
  for (const agentId of agentDirs) {
35366
35741
  if (agentId.startsWith("_")) continue;
35367
35742
  if (!SAFE_NAME2.test(agentId)) continue;
35368
- const skillsDir = (0, import_path77.join)(canonicalBaseDir, agentId, "skills");
35369
- if (!(0, import_fs73.existsSync)(skillsDir)) continue;
35743
+ const skillsDir = (0, import_path78.join)(canonicalBaseDir, agentId, "skills");
35744
+ if (!(0, import_fs74.existsSync)(skillsDir)) continue;
35370
35745
  let canonicalSkillsDir;
35371
35746
  try {
35372
- canonicalSkillsDir = (0, import_fs73.realpathSync)(skillsDir);
35747
+ canonicalSkillsDir = (0, import_fs74.realpathSync)(skillsDir);
35373
35748
  } catch {
35374
35749
  continue;
35375
35750
  }
@@ -35380,7 +35755,7 @@ async function runCheckEffectivenessForAllSkills(opts) {
35380
35755
  }
35381
35756
  const role = opts.registryGet(agentId)?.role;
35382
35757
  if (role === "implementer") continue;
35383
- const files = (0, import_fs73.readdirSync)(canonicalSkillsDir).filter((f) => f.endsWith(".md"));
35758
+ const files = (0, import_fs74.readdirSync)(canonicalSkillsDir).filter((f) => f.endsWith(".md"));
35384
35759
  for (const file2 of files) {
35385
35760
  const category = file2.replace(/\.md$/, "");
35386
35761
  if (!SAFE_NAME2.test(category)) continue;
@@ -35427,12 +35802,12 @@ async function runCheckEffectivenessForAllSkills(opts) {
35427
35802
  last_error: lastError
35428
35803
  });
35429
35804
  }
35430
- var import_fs73, import_path77, SAFE_NAME2;
35805
+ var import_fs74, import_path78, SAFE_NAME2;
35431
35806
  var init_check_effectiveness_runner = __esm({
35432
35807
  "apps/cli/src/handlers/check-effectiveness-runner.ts"() {
35433
35808
  "use strict";
35434
- import_fs73 = require("fs");
35435
- import_path77 = require("path");
35809
+ import_fs74 = require("fs");
35810
+ import_path78 = require("path");
35436
35811
  init_dispatch_prompt_cache();
35437
35812
  SAFE_NAME2 = /^(?!.*\.\.)[a-zA-Z0-9._-]+$/;
35438
35813
  }
@@ -35445,20 +35820,20 @@ __export(skill_develop_audit_exports, {
35445
35820
  });
35446
35821
  function appendSkillDevelopAudit(entry) {
35447
35822
  try {
35448
- const gossipDir = (0, import_path78.join)(process.cwd(), ".gossip");
35449
- (0, import_fs74.mkdirSync)(gossipDir, { recursive: true });
35823
+ const gossipDir = (0, import_path79.join)(process.cwd(), ".gossip");
35824
+ (0, import_fs75.mkdirSync)(gossipDir, { recursive: true });
35450
35825
  const line = JSON.stringify(entry) + "\n";
35451
- (0, import_fs74.appendFileSync)((0, import_path78.join)(gossipDir, AUDIT_FILE2), line);
35452
- (0, import_fs74.appendFileSync)((0, import_path78.join)(gossipDir, LEGACY_FILE), line);
35826
+ (0, import_fs75.appendFileSync)((0, import_path79.join)(gossipDir, AUDIT_FILE2), line);
35827
+ (0, import_fs75.appendFileSync)((0, import_path79.join)(gossipDir, LEGACY_FILE), line);
35453
35828
  } catch {
35454
35829
  }
35455
35830
  }
35456
- var import_fs74, import_path78, AUDIT_FILE2, LEGACY_FILE;
35831
+ var import_fs75, import_path79, AUDIT_FILE2, LEGACY_FILE;
35457
35832
  var init_skill_develop_audit = __esm({
35458
35833
  "apps/cli/src/handlers/skill-develop-audit.ts"() {
35459
35834
  "use strict";
35460
- import_fs74 = require("fs");
35461
- import_path78 = require("path");
35835
+ import_fs75 = require("fs");
35836
+ import_path79 = require("path");
35462
35837
  AUDIT_FILE2 = "skill-develop-audit.jsonl";
35463
35838
  LEGACY_FILE = "forced-skill-develops.jsonl";
35464
35839
  }
@@ -35469,14 +35844,14 @@ var keychain_exports = {};
35469
35844
  __export(keychain_exports, {
35470
35845
  Keychain: () => Keychain
35471
35846
  });
35472
- var import_child_process12, import_os6, import_fs78, import_path82, import_crypto32, DEFAULT_SERVICE_NAME, VALID_PROVIDERS2, ENCRYPTED_FILE, ALGO, Keychain;
35847
+ var import_child_process12, import_os6, import_fs79, import_path83, import_crypto32, DEFAULT_SERVICE_NAME, VALID_PROVIDERS2, ENCRYPTED_FILE, ALGO, Keychain;
35473
35848
  var init_keychain = __esm({
35474
35849
  "apps/cli/src/keychain.ts"() {
35475
35850
  "use strict";
35476
35851
  import_child_process12 = require("child_process");
35477
35852
  import_os6 = require("os");
35478
- import_fs78 = require("fs");
35479
- import_path82 = require("path");
35853
+ import_fs79 = require("fs");
35854
+ import_path83 = require("path");
35480
35855
  import_crypto32 = require("crypto");
35481
35856
  DEFAULT_SERVICE_NAME = "gossip-mesh";
35482
35857
  VALID_PROVIDERS2 = /^[a-zA-Z0-9_-]{1,32}$/;
@@ -35520,10 +35895,10 @@ var init_keychain = __esm({
35520
35895
  return (0, import_crypto32.pbkdf2Sync)(seed, salt, 6e5, 32, "sha256");
35521
35896
  }
35522
35897
  loadEncryptedFile() {
35523
- const filePath = (0, import_path82.join)(process.cwd(), ENCRYPTED_FILE);
35524
- if (!(0, import_fs78.existsSync)(filePath)) return;
35898
+ const filePath = (0, import_path83.join)(process.cwd(), ENCRYPTED_FILE);
35899
+ if (!(0, import_fs79.existsSync)(filePath)) return;
35525
35900
  try {
35526
- const raw = (0, import_fs78.readFileSync)(filePath);
35901
+ const raw = (0, import_fs79.readFileSync)(filePath);
35527
35902
  if (raw.length < 61) return;
35528
35903
  const salt = raw.subarray(0, 32);
35529
35904
  const iv = raw.subarray(32, 44);
@@ -35541,9 +35916,9 @@ var init_keychain = __esm({
35541
35916
  }
35542
35917
  }
35543
35918
  saveEncryptedFile() {
35544
- const filePath = (0, import_path82.join)(process.cwd(), ENCRYPTED_FILE);
35545
- const dir = (0, import_path82.join)(process.cwd(), ".gossip");
35546
- if (!(0, import_fs78.existsSync)(dir)) (0, import_fs78.mkdirSync)(dir, { recursive: true });
35919
+ const filePath = (0, import_path83.join)(process.cwd(), ENCRYPTED_FILE);
35920
+ const dir = (0, import_path83.join)(process.cwd(), ".gossip");
35921
+ if (!(0, import_fs79.existsSync)(dir)) (0, import_fs79.mkdirSync)(dir, { recursive: true });
35547
35922
  const data = JSON.stringify(Object.fromEntries(this.inMemoryStore));
35548
35923
  const salt = (0, import_crypto32.randomBytes)(32);
35549
35924
  const iv = (0, import_crypto32.randomBytes)(12);
@@ -35551,7 +35926,7 @@ var init_keychain = __esm({
35551
35926
  const cipher = (0, import_crypto32.createCipheriv)(ALGO, key, iv);
35552
35927
  const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
35553
35928
  const tag = cipher.getAuthTag();
35554
- (0, import_fs78.writeFileSync)(filePath, Buffer.concat([salt, iv, tag, encrypted]), { mode: 384 });
35929
+ (0, import_fs79.writeFileSync)(filePath, Buffer.concat([salt, iv, tag, encrypted]), { mode: 384 });
35555
35930
  }
35556
35931
  isKeychainAvailable() {
35557
35932
  if ((0, import_os6.platform)() === "darwin") {
@@ -35651,17 +36026,17 @@ __export(identity_exports, {
35651
36026
  normalizeGitUrl: () => normalizeGitUrl
35652
36027
  });
35653
36028
  function getOrCreateSalt(projectRoot) {
35654
- const saltPath = (0, import_path83.join)(projectRoot, ".gossip", "local-salt");
36029
+ const saltPath = (0, import_path84.join)(projectRoot, ".gossip", "local-salt");
35655
36030
  try {
35656
- return (0, import_fs79.readFileSync)(saltPath, "utf-8").trim();
36031
+ return (0, import_fs80.readFileSync)(saltPath, "utf-8").trim();
35657
36032
  } catch {
35658
36033
  const salt = (0, import_crypto33.randomBytes)(16).toString("hex");
35659
- (0, import_fs79.mkdirSync)((0, import_path83.join)(projectRoot, ".gossip"), { recursive: true });
36034
+ (0, import_fs80.mkdirSync)((0, import_path84.join)(projectRoot, ".gossip"), { recursive: true });
35660
36035
  try {
35661
- (0, import_fs79.writeFileSync)(saltPath, salt, { flag: "wx" });
36036
+ (0, import_fs80.writeFileSync)(saltPath, salt, { flag: "wx" });
35662
36037
  return salt;
35663
36038
  } catch {
35664
- return (0, import_fs79.readFileSync)(saltPath, "utf-8").trim();
36039
+ return (0, import_fs80.readFileSync)(saltPath, "utf-8").trim();
35665
36040
  }
35666
36041
  }
35667
36042
  }
@@ -35711,12 +36086,12 @@ function getProjectId(projectRoot) {
35711
36086
  }
35712
36087
  return (0, import_crypto33.createHash)("sha256").update(projectRoot).digest("hex").slice(0, 16);
35713
36088
  }
35714
- var import_fs79, import_path83, import_crypto33, import_child_process13;
36089
+ var import_fs80, import_path84, import_crypto33, import_child_process13;
35715
36090
  var init_identity = __esm({
35716
36091
  "apps/cli/src/identity.ts"() {
35717
36092
  "use strict";
35718
- import_fs79 = require("fs");
35719
- import_path83 = require("path");
36093
+ import_fs80 = require("fs");
36094
+ import_path84 = require("path");
35720
36095
  import_crypto33 = require("crypto");
35721
36096
  import_child_process13 = require("child_process");
35722
36097
  }
@@ -35738,9 +36113,9 @@ async function getLatestVersion() {
35738
36113
  return data.version;
35739
36114
  }
35740
36115
  function detectInstallMethod() {
35741
- const packageRoot = (0, import_path84.resolve)(__dirname, "..", "..", "..", "..");
36116
+ const packageRoot = (0, import_path85.resolve)(__dirname, "..", "..", "..", "..");
35742
36117
  if (process.env.npm_config_global === "true") return "global";
35743
- if ((0, import_fs80.existsSync)((0, import_path84.join)(packageRoot, ".git"))) return "git-clone";
36118
+ if ((0, import_fs81.existsSync)((0, import_path85.join)(packageRoot, ".git"))) return "git-clone";
35744
36119
  return "local";
35745
36120
  }
35746
36121
  function updateCommand(method, version2) {
@@ -35795,7 +36170,7 @@ Check your internet connection or visit https://www.npmjs.com/package/gossipcat
35795
36170
  try {
35796
36171
  (0, import_child_process14.execSync)(command, {
35797
36172
  stdio: "inherit",
35798
- cwd: method === "git-clone" ? (0, import_path84.resolve)(__dirname, "..", "..", "..", "..") : process.cwd(),
36173
+ cwd: method === "git-clone" ? (0, import_path85.resolve)(__dirname, "..", "..", "..", "..") : process.cwd(),
35799
36174
  env: scrubbedEnv
35800
36175
  });
35801
36176
  } catch (err) {
@@ -35818,13 +36193,13 @@ Run /mcp reconnect in Claude Code to load the new version.`
35818
36193
  }]
35819
36194
  };
35820
36195
  }
35821
- var import_child_process14, import_fs80, import_path84;
36196
+ var import_child_process14, import_fs81, import_path85;
35822
36197
  var init_gossip_update = __esm({
35823
36198
  "apps/cli/src/handlers/gossip-update.ts"() {
35824
36199
  "use strict";
35825
36200
  import_child_process14 = require("child_process");
35826
- import_fs80 = require("fs");
35827
- import_path84 = require("path");
36201
+ import_fs81 = require("fs");
36202
+ import_path85 = require("path");
35828
36203
  init_version();
35829
36204
  }
35830
36205
  });
@@ -36035,8 +36410,8 @@ __export(mcp_server_sdk_exports, {
36035
36410
  createMcpServer: () => createMcpServer
36036
36411
  });
36037
36412
  module.exports = __toCommonJS(mcp_server_sdk_exports);
36038
- var import_fs81 = require("fs");
36039
- var import_path85 = require("path");
36413
+ var import_fs82 = require("fs");
36414
+ var import_path86 = require("path");
36040
36415
 
36041
36416
  // apps/cli/src/hook-run.ts
36042
36417
  var import_fs = require("fs");
@@ -49939,15 +50314,15 @@ init_native_tasks();
49939
50314
 
49940
50315
  // apps/cli/src/handlers/dispatch.ts
49941
50316
  var import_crypto31 = require("crypto");
49942
- var import_fs71 = require("fs");
49943
- var import_path76 = require("path");
50317
+ var import_fs72 = require("fs");
50318
+ var import_path77 = require("path");
49944
50319
  init_src4();
49945
50320
  init_src3();
49946
50321
  init_mcp_context();
49947
50322
  init_native_tasks();
49948
50323
  init_dispatch_prompt_storage();
49949
50324
  init_dispatch_prompt_cache();
49950
- var import_fs72 = require("fs");
50325
+ var import_fs73 = require("fs");
49951
50326
 
49952
50327
  // apps/cli/src/handlers/relay-tasks.ts
49953
50328
  init_mcp_context();
@@ -50060,7 +50435,7 @@ function tryWarmCacheHit(liveTaskBlock, cacheKey, promptFormat) {
50060
50435
  const cached4 = getCachedPrompt(cacheKey);
50061
50436
  if (!cached4) return null;
50062
50437
  if (cached4.skillFingerprint !== cacheKey.skillFingerprint) return null;
50063
- if (!(0, import_fs72.existsSync)(cached4.skillsSectionPath)) return null;
50438
+ if (!(0, import_fs73.existsSync)(cached4.skillsSectionPath)) return null;
50064
50439
  try {
50065
50440
  const skillsSection = require("fs").readFileSync(cached4.skillsSectionPath, "utf8");
50066
50441
  return skillsSection + liveTaskBlock;
@@ -50137,9 +50512,9 @@ function formatFalsifiedNote(block, verdicts) {
50137
50512
  }
50138
50513
  function writePremiseVerificationLog(projectRoot, taskId, result, opts) {
50139
50514
  try {
50140
- const logPath = (0, import_path76.join)(projectRoot, PREMISE_VERIFICATION_LOG);
50515
+ const logPath = (0, import_path77.join)(projectRoot, PREMISE_VERIFICATION_LOG);
50141
50516
  rotateIfNeeded2(logPath, MAX_PREMISE_VERIFICATION_BYTES);
50142
- (0, import_fs71.mkdirSync)((0, import_path76.join)(projectRoot, ".gossip"), { recursive: true });
50517
+ (0, import_fs72.mkdirSync)((0, import_path77.join)(projectRoot, ".gossip"), { recursive: true });
50143
50518
  const row = {
50144
50519
  ts: (/* @__PURE__ */ new Date()).toISOString(),
50145
50520
  consensus_id: null,
@@ -50153,7 +50528,7 @@ function writePremiseVerificationLog(projectRoot, taskId, result, opts) {
50153
50528
  skill_bound: opts.skill_bound
50154
50529
  };
50155
50530
  if (opts.schema_lint) row.schema_lint = opts.schema_lint;
50156
- (0, import_fs71.appendFileSync)(logPath, JSON.stringify(row) + "\n");
50531
+ (0, import_fs72.appendFileSync)(logPath, JSON.stringify(row) + "\n");
50157
50532
  } catch {
50158
50533
  }
50159
50534
  }
@@ -50265,7 +50640,7 @@ var AGENT_PROVIDER_MAP = {
50265
50640
  };
50266
50641
  function readQuotaState() {
50267
50642
  try {
50268
- const raw = (0, import_fs71.readFileSync)((0, import_path76.join)(process.cwd(), ".gossip", "quota-state.json"), "utf8");
50643
+ const raw = (0, import_fs72.readFileSync)((0, import_path77.join)(process.cwd(), ".gossip", "quota-state.json"), "utf8");
50269
50644
  return JSON.parse(raw);
50270
50645
  } catch {
50271
50646
  return {};
@@ -51093,13 +51468,13 @@ function buildAutoVerifyDispatch(binding) {
51093
51468
  var _autoResolverErrors = /* @__PURE__ */ new Set();
51094
51469
  var _autoResolverLockWarned = false;
51095
51470
  var CONSENSUS_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{8}$/;
51096
- function isValidConsensusId(id) {
51471
+ function isValidConsensusId2(id) {
51097
51472
  return typeof id === "string" && CONSENSUS_ID_RE.test(id);
51098
51473
  }
51099
51474
  function extractConsensusIdFromFindingId(findingId) {
51100
51475
  if (typeof findingId !== "string") return void 0;
51101
51476
  const first = findingId.split(":")[0];
51102
- return isValidConsensusId(first) ? first : void 0;
51477
+ return isValidConsensusId2(first) ? first : void 0;
51103
51478
  }
51104
51479
  function reconcilerFindingsAll(consensusReport) {
51105
51480
  return [
@@ -51801,7 +52176,7 @@ ${np.user}
51801
52176
  ...consensusReport.unique || []
51802
52177
  ];
51803
52178
  const authoritativeId = consensusReport?.signals?.[0]?.consensusId;
51804
- const provisionalConsensusId = (isValidConsensusId(authoritativeId) ? authoritativeId : void 0) ?? (allFindings.length > 0 ? extractConsensusIdFromFindingId(allFindings[0].id) : void 0);
52179
+ const provisionalConsensusId = (isValidConsensusId2(authoritativeId) ? authoritativeId : void 0) ?? (allFindings.length > 0 ? extractConsensusIdFromFindingId(allFindings[0].id) : void 0);
51805
52180
  const provisionalSignals = allFindings.filter((f) => !isFindingAlreadySignaled(alreadySignaled, f)).map((f) => {
51806
52181
  const extracted = extractCategories2(f.finding || "");
51807
52182
  const category = f.category || extracted[0] || void 0;
@@ -52049,19 +52424,19 @@ function filterWatchEvents(rawJsonl, opts) {
52049
52424
  }
52050
52425
 
52051
52426
  // apps/cli/src/stickyPort.ts
52052
- var import_fs75 = require("fs");
52053
- var import_path79 = require("path");
52427
+ var import_fs76 = require("fs");
52428
+ var import_path80 = require("path");
52054
52429
  var import_net = require("net");
52055
- var RELAY_STICKY_FILE = (0, import_path79.join)(".gossip", "relay.port");
52056
- var HTTP_MCP_STICKY_FILE = (0, import_path79.join)(".gossip", "http-mcp.port");
52430
+ var RELAY_STICKY_FILE = (0, import_path80.join)(".gossip", "relay.port");
52431
+ var HTTP_MCP_STICKY_FILE = (0, import_path80.join)(".gossip", "http-mcp.port");
52057
52432
  function stickyPath(filename) {
52058
- return (0, import_path79.join)(process.cwd(), filename);
52433
+ return (0, import_path80.join)(process.cwd(), filename);
52059
52434
  }
52060
52435
  function readStickyPort(filename) {
52061
52436
  const p = stickyPath(filename);
52062
- if (!(0, import_fs75.existsSync)(p)) return null;
52437
+ if (!(0, import_fs76.existsSync)(p)) return null;
52063
52438
  try {
52064
- const raw = (0, import_fs75.readFileSync)(p, "utf-8").trim();
52439
+ const raw = (0, import_fs76.readFileSync)(p, "utf-8").trim();
52065
52440
  const n = parseInt(raw, 10);
52066
52441
  if (!Number.isFinite(n) || n < 1 || n > 65535) return null;
52067
52442
  return n;
@@ -52073,8 +52448,8 @@ function writeStickyPort(filename, port) {
52073
52448
  if (!Number.isFinite(port) || port < 1 || port > 65535) return;
52074
52449
  const p = stickyPath(filename);
52075
52450
  try {
52076
- (0, import_fs75.mkdirSync)((0, import_path79.dirname)(p), { recursive: true });
52077
- (0, import_fs75.writeFileSync)(p, String(port), "utf-8");
52451
+ (0, import_fs76.mkdirSync)((0, import_path80.dirname)(p), { recursive: true });
52452
+ (0, import_fs76.writeFileSync)(p, String(port), "utf-8");
52078
52453
  } catch {
52079
52454
  }
52080
52455
  }
@@ -52138,22 +52513,22 @@ function buildDashboardAdvisory(input) {
52138
52513
  }
52139
52514
 
52140
52515
  // apps/cli/src/native-agent-cache.ts
52141
- var import_fs76 = require("fs");
52142
- var import_path80 = require("path");
52516
+ var import_fs77 = require("fs");
52517
+ var import_path81 = require("path");
52143
52518
  var realFs = {
52144
- existsSync: import_fs76.existsSync,
52145
- readFileSync: import_fs76.readFileSync,
52146
- statSync: (p) => ({ mtimeMs: (0, import_fs76.statSync)(p).mtimeMs })
52519
+ existsSync: import_fs77.existsSync,
52520
+ readFileSync: import_fs77.readFileSync,
52521
+ statSync: (p) => ({ mtimeMs: (0, import_fs77.statSync)(p).mtimeMs })
52147
52522
  };
52148
52523
  function modelTierFromId(modelId) {
52149
52524
  if (modelId.includes("opus")) return "opus";
52150
52525
  if (modelId.includes("haiku")) return "haiku";
52151
52526
  return "sonnet";
52152
52527
  }
52153
- function refreshNativeAgentFromDisk(ac, cache2, projectRoot, fs6 = realFs) {
52154
- const claudeAgentPath = (0, import_path80.join)(projectRoot, ".claude", "agents", `${ac.id}.md`);
52155
- const instrPath = (0, import_path80.join)(projectRoot, ".gossip", "agents", ac.id, "instructions.md");
52156
- const prev = cache2.get(ac.id);
52528
+ function refreshNativeAgentFromDisk(ac, cache3, projectRoot, fs6 = realFs) {
52529
+ const claudeAgentPath = (0, import_path81.join)(projectRoot, ".claude", "agents", `${ac.id}.md`);
52530
+ const instrPath = (0, import_path81.join)(projectRoot, ".gossip", "agents", ac.id, "instructions.md");
52531
+ const prev = cache3.get(ac.id);
52157
52532
  let sourcePath = null;
52158
52533
  let stripFrontmatter = false;
52159
52534
  if (fs6.existsSync(claudeAgentPath)) {
@@ -52167,7 +52542,7 @@ function refreshNativeAgentFromDisk(ac, cache2, projectRoot, fs6 = realFs) {
52167
52542
  if (prev && prev.instructions.length > 0) {
52168
52543
  return;
52169
52544
  }
52170
- cache2.set(ac.id, {
52545
+ cache3.set(ac.id, {
52171
52546
  model: modelTierFromId(ac.model),
52172
52547
  instructions: "",
52173
52548
  description: ac.role || ac.preset || "",
@@ -52183,7 +52558,7 @@ function refreshNativeAgentFromDisk(ac, cache2, projectRoot, fs6 = realFs) {
52183
52558
  if (prev && prev.instructions.length > 0) {
52184
52559
  return;
52185
52560
  }
52186
- cache2.set(ac.id, {
52561
+ cache3.set(ac.id, {
52187
52562
  model: modelTierFromId(ac.model),
52188
52563
  instructions: "",
52189
52564
  description: ac.role || ac.preset || "",
@@ -52201,7 +52576,7 @@ function refreshNativeAgentFromDisk(ac, cache2, projectRoot, fs6 = realFs) {
52201
52576
  if (instructions.length === 0 && prev && prev.instructions.length > 0) {
52202
52577
  return;
52203
52578
  }
52204
- cache2.set(ac.id, {
52579
+ cache3.set(ac.id, {
52205
52580
  model: modelTierFromId(ac.model),
52206
52581
  instructions,
52207
52582
  description: ac.role || ac.preset || "",
@@ -52211,16 +52586,16 @@ function refreshNativeAgentFromDisk(ac, cache2, projectRoot, fs6 = realFs) {
52211
52586
  }
52212
52587
 
52213
52588
  // apps/cli/src/rules-content.ts
52214
- var import_fs77 = require("fs");
52215
- var import_path81 = require("path");
52589
+ var import_fs78 = require("fs");
52590
+ var import_path82 = require("path");
52216
52591
  var AGENT_LIST_PLACEHOLDER = "{{AGENT_LIST}}";
52217
52592
  function resolveRulesPath() {
52218
52593
  const candidates = [
52219
- (0, import_path81.join)(process.cwd(), "docs", "RULES.md"),
52220
- (0, import_path81.join)(__dirname, "..", "docs", "RULES.md"),
52221
- (0, import_path81.join)(__dirname, "docs", "RULES.md")
52594
+ (0, import_path82.join)(process.cwd(), "docs", "RULES.md"),
52595
+ (0, import_path82.join)(__dirname, "..", "docs", "RULES.md"),
52596
+ (0, import_path82.join)(__dirname, "docs", "RULES.md")
52222
52597
  ];
52223
- return candidates.find((p) => (0, import_fs77.existsSync)(p)) ?? null;
52598
+ return candidates.find((p) => (0, import_fs78.existsSync)(p)) ?? null;
52224
52599
  }
52225
52600
  function generateRulesContent(agentList) {
52226
52601
  const rulesPath = resolveRulesPath();
@@ -52229,7 +52604,7 @@ function generateRulesContent(agentList) {
52229
52604
  `[gossipcat] generateRulesContent: docs/RULES.md not found in any fallback path (cwd=${process.cwd()}, dirname=${__dirname}). Expected docs/RULES.md tracked in the gossipcat repo or shipped alongside the MCP bundle. If running from a fresh install, re-run \`npm run build:mcp\` to copy docs/RULES.md into dist-mcp/docs/.`
52230
52605
  );
52231
52606
  }
52232
- const template = (0, import_fs77.readFileSync)(rulesPath, "utf-8");
52607
+ const template = (0, import_fs78.readFileSync)(rulesPath, "utf-8");
52233
52608
  return template.split(AGENT_LIST_PLACEHOLDER).join(agentList);
52234
52609
  }
52235
52610
 
@@ -52299,12 +52674,12 @@ function isReservedAgentId(id) {
52299
52674
  }
52300
52675
  }
52301
52676
  if (process.env.GOSSIPCAT_MCP_NO_MAIN !== "1") {
52302
- const gossipDir = (0, import_path85.join)(process.cwd(), ".gossip");
52677
+ const gossipDir = (0, import_path86.join)(process.cwd(), ".gossip");
52303
52678
  try {
52304
- (0, import_fs81.mkdirSync)(gossipDir, { recursive: true });
52679
+ (0, import_fs82.mkdirSync)(gossipDir, { recursive: true });
52305
52680
  } catch {
52306
52681
  }
52307
- const logStream = (0, import_fs81.createWriteStream)((0, import_path85.join)(gossipDir, "mcp.log"), { flags: "a" });
52682
+ const logStream = (0, import_fs82.createWriteStream)((0, import_path86.join)(gossipDir, "mcp.log"), { flags: "a" });
52308
52683
  process.stderr.write = ((chunk, ...args) => {
52309
52684
  return logStream.write(chunk, ...args);
52310
52685
  });
@@ -52315,7 +52690,7 @@ try {
52315
52690
  } catch {
52316
52691
  }
52317
52692
  function memoryDirForProject(cwd) {
52318
- return (0, import_path85.join)((0, import_os7.homedir)(), ".claude", "projects", cwd.replaceAll("/", "-"), "memory");
52693
+ return (0, import_path86.join)((0, import_os7.homedir)(), ".claude", "projects", cwd.replaceAll("/", "-"), "memory");
52319
52694
  }
52320
52695
  function detectEnvironment() {
52321
52696
  if (process.env.CLAUDECODE === "1" || process.env.CLAUDE_CODE_ENTRYPOINT) {
@@ -52370,14 +52745,14 @@ var _pendingPlanData = /* @__PURE__ */ new Map();
52370
52745
  var _utilityGuardSnapshots = /* @__PURE__ */ new Map();
52371
52746
  var _modules = null;
52372
52747
  function lookupFindingSeverity(findingId, projectRoot) {
52373
- const { existsSync: existsSync69, readdirSync: readdirSync22, readFileSync: readFileSync62 } = require("fs");
52374
- const { join: join82 } = require("path");
52375
- const reportsDir = join82(projectRoot, ".gossip", "consensus-reports");
52376
- if (!existsSync69(reportsDir)) return null;
52748
+ const { existsSync: existsSync70, readdirSync: readdirSync22, readFileSync: readFileSync64 } = require("fs");
52749
+ const { join: join83 } = require("path");
52750
+ const reportsDir = join83(projectRoot, ".gossip", "consensus-reports");
52751
+ if (!existsSync70(reportsDir)) return null;
52377
52752
  try {
52378
52753
  const files = readdirSync22(reportsDir).filter((f) => f.endsWith(".json"));
52379
52754
  for (const file2 of files) {
52380
- const report = JSON.parse(readFileSync62(join82(reportsDir, file2), "utf-8"));
52755
+ const report = JSON.parse(readFileSync64(join83(reportsDir, file2), "utf-8"));
52381
52756
  for (const bucket of ["confirmed", "disputed", "unverified", "unique"]) {
52382
52757
  for (const finding of report[bucket] || []) {
52383
52758
  if (finding.id === findingId && finding.severity) {
@@ -52455,7 +52830,7 @@ async function doBoot() {
52455
52830
  const agentConfigs = m.configToAgentConfigs(config2);
52456
52831
  ctx.keychain = new m.Keychain();
52457
52832
  const { existsSync: pidExists, readFileSync: readPid, writeFileSync: writePid, unlinkSync: delPid } = require("fs");
52458
- const pidFile = (0, import_path85.join)(process.cwd(), ".gossip", "relay.pid");
52833
+ const pidFile = (0, import_path86.join)(process.cwd(), ".gossip", "relay.pid");
52459
52834
  if (pidExists(pidFile)) {
52460
52835
  const oldPid = parseInt(readPid(pidFile, "utf-8").trim(), 10);
52461
52836
  if (!isNaN(oldPid) && oldPid !== process.pid) {
@@ -52565,10 +52940,10 @@ async function doBoot() {
52565
52940
  }
52566
52941
  const key = await ctx.keychain.getKey(ac.provider);
52567
52942
  const llm = m.createProvider(ac.provider, ac.model, key ?? void 0, void 0, ac.base_url);
52568
- const { existsSync: existsSync69, readFileSync: readFileSync62 } = require("fs");
52569
- const { join: join82 } = require("path");
52570
- const instructionsPath = join82(process.cwd(), ".gossip", "agents", ac.id, "instructions.md");
52571
- const baseInstructions = existsSync69(instructionsPath) ? readFileSync62(instructionsPath, "utf-8") : "";
52943
+ const { existsSync: existsSync70, readFileSync: readFileSync64 } = require("fs");
52944
+ const { join: join83 } = require("path");
52945
+ const instructionsPath = join83(process.cwd(), ".gossip", "agents", ac.id, "instructions.md");
52946
+ const baseInstructions = existsSync70(instructionsPath) ? readFileSync64(instructionsPath, "utf-8") : "";
52572
52947
  const identity = ctx.identityRegistry.get(ac.id);
52573
52948
  const identityBlock = identity ? m.formatIdentityBlock(identity) + "\n" : "";
52574
52949
  const instructions = (identityBlock + baseInstructions).trim() || void 0;
@@ -53403,7 +53778,7 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
53403
53778
  }
53404
53779
  try {
53405
53780
  const { readFileSync: rfHealth } = await import("fs");
53406
- const healthPath = (0, import_path85.join)(process.cwd(), ".gossip", "skill-runner-health.json");
53781
+ const healthPath = (0, import_path86.join)(process.cwd(), ".gossip", "skill-runner-health.json");
53407
53782
  const raw = rfHealth(healthPath, "utf8");
53408
53783
  const h = JSON.parse(raw);
53409
53784
  const lastMs = h.last_run_at ? new Date(h.last_run_at).getTime() : NaN;
@@ -53419,9 +53794,9 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
53419
53794
  lines.push(" Skill graduation: never run since session start (expected after first gossip_collect)");
53420
53795
  }
53421
53796
  try {
53422
- const { readFileSync: readFileSync62 } = await import("fs");
53423
- const quotaPath = (0, import_path85.join)(process.cwd(), ".gossip", "quota-state.json");
53424
- const quotaRaw = readFileSync62(quotaPath, "utf8");
53797
+ const { readFileSync: readFileSync64 } = await import("fs");
53798
+ const quotaPath = (0, import_path86.join)(process.cwd(), ".gossip", "quota-state.json");
53799
+ const quotaRaw = readFileSync64(quotaPath, "utf8");
53425
53800
  const quotaState = JSON.parse(quotaRaw);
53426
53801
  for (const [provider, state] of Object.entries(quotaState)) {
53427
53802
  const now = Date.now();
@@ -53435,19 +53810,19 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
53435
53810
  } catch {
53436
53811
  }
53437
53812
  try {
53438
- const { readdirSync: readdirSync22, statSync: statSync34 } = await import("fs");
53813
+ const { readdirSync: readdirSync22, statSync: statSync35 } = await import("fs");
53439
53814
  const { readJsonlWithRotated: readJsonlRotated1506 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
53440
- const reportsDir = (0, import_path85.join)(process.cwd(), ".gossip", "consensus-reports");
53441
- const perfPath = (0, import_path85.join)(process.cwd(), ".gossip", "agent-performance.jsonl");
53442
- const WINDOW_MS2 = 24 * 60 * 60 * 1e3;
53815
+ const reportsDir = (0, import_path86.join)(process.cwd(), ".gossip", "consensus-reports");
53816
+ const perfPath = (0, import_path86.join)(process.cwd(), ".gossip", "agent-performance.jsonl");
53817
+ const WINDOW_MS3 = 24 * 60 * 60 * 1e3;
53443
53818
  const now = Date.now();
53444
53819
  const recentReports = [];
53445
53820
  try {
53446
53821
  for (const fname of readdirSync22(reportsDir)) {
53447
53822
  if (!fname.endsWith(".json")) continue;
53448
- const fpath = (0, import_path85.join)(reportsDir, fname);
53449
- const st = statSync34(fpath);
53450
- if (now - st.mtimeMs > WINDOW_MS2) continue;
53823
+ const fpath = (0, import_path86.join)(reportsDir, fname);
53824
+ const st = statSync35(fpath);
53825
+ if (now - st.mtimeMs > WINDOW_MS3) continue;
53451
53826
  recentReports.push({ id: fname.replace(/\.json$/, ""), mtimeMs: st.mtimeMs });
53452
53827
  }
53453
53828
  } catch {
@@ -53811,8 +54186,8 @@ ${body}`
53811
54186
  }
53812
54187
  return { content: [{ type: "text", text: results.join("\n") }] };
53813
54188
  }
53814
- const { writeFileSync: writeFileSync34, mkdirSync: mkdirSync41, existsSync: existsSync69 } = require("fs");
53815
- const { join: join82 } = require("path");
54189
+ const { writeFileSync: writeFileSync34, mkdirSync: mkdirSync41, existsSync: existsSync70 } = require("fs");
54190
+ const { join: join83 } = require("path");
53816
54191
  const root = process.cwd();
53817
54192
  const CLAUDE_MODEL_MAP2 = {
53818
54193
  opus: { provider: "anthropic", model: "claude-opus-4-6" },
@@ -53826,8 +54201,8 @@ ${body}`
53826
54201
  let existingAgents = {};
53827
54202
  if (mode === "merge") {
53828
54203
  try {
53829
- const { readFileSync: readFileSync62 } = require("fs");
53830
- const existing = JSON.parse(readFileSync62(join82(root, ".gossip", "config.json"), "utf-8"));
54204
+ const { readFileSync: readFileSync64 } = require("fs");
54205
+ const existing = JSON.parse(readFileSync64(join83(root, ".gossip", "config.json"), "utf-8"));
53831
54206
  existingAgents = existing.agents || {};
53832
54207
  } catch {
53833
54208
  }
@@ -53858,9 +54233,9 @@ ${body}`
53858
54233
  "",
53859
54234
  body
53860
54235
  ].join("\n");
53861
- const agentsDir = join82(root, ".claude", "agents");
54236
+ const agentsDir = join83(root, ".claude", "agents");
53862
54237
  mkdirSync41(agentsDir, { recursive: true });
53863
- writeFileSync34(join82(agentsDir, `${agent.id}.md`), md, "utf-8");
54238
+ writeFileSync34(join83(agentsDir, `${agent.id}.md`), md, "utf-8");
53864
54239
  nativeCreated.push(agent.id);
53865
54240
  configAgents[agent.id] = {
53866
54241
  provider: mapped.provider,
@@ -53878,8 +54253,8 @@ ${body}`
53878
54253
  errors.push(`${agent.id}: custom agent requires "custom_model" field`);
53879
54254
  continue;
53880
54255
  }
53881
- const nativeFile = join82(root, ".claude", "agents", `${agent.id}.md`);
53882
- const wasNative = existingAgents[agent.id]?.native || existsSync69(nativeFile);
54256
+ const nativeFile = join83(root, ".claude", "agents", `${agent.id}.md`);
54257
+ const wasNative = existingAgents[agent.id]?.native || existsSync70(nativeFile);
53883
54258
  if (wasNative) {
53884
54259
  errors.push(`${agent.id}: cannot re-register native agent as custom \u2014 .claude/agents/${agent.id}.md exists. Remove the file first or keep it as native.`);
53885
54260
  continue;
@@ -53893,9 +54268,9 @@ ${body}`
53893
54268
  };
53894
54269
  customCreated.push(agent.id);
53895
54270
  if (agent.instructions) {
53896
- const instrDir = join82(root, ".gossip", "agents", agent.id);
54271
+ const instrDir = join83(root, ".gossip", "agents", agent.id);
53897
54272
  mkdirSync41(instrDir, { recursive: true });
53898
- writeFileSync34(join82(instrDir, "instructions.md"), agent.instructions, "utf-8");
54273
+ writeFileSync34(join83(instrDir, "instructions.md"), agent.instructions, "utf-8");
53899
54274
  }
53900
54275
  }
53901
54276
  }
@@ -53909,8 +54284,8 @@ ${body}`
53909
54284
  } catch (err) {
53910
54285
  return { content: [{ type: "text", text: `Invalid config: ${err.message}` }] };
53911
54286
  }
53912
- mkdirSync41(join82(root, ".gossip"), { recursive: true });
53913
- writeFileSync34(join82(root, ".gossip", "config.json"), JSON.stringify(config2, null, 2));
54287
+ mkdirSync41(join83(root, ".gossip"), { recursive: true });
54288
+ writeFileSync34(join83(root, ".gossip", "config.json"), JSON.stringify(config2, null, 2));
53914
54289
  let hookSummary = "";
53915
54290
  try {
53916
54291
  const { installWorktreeSandboxHook: installWorktreeSandboxHook2, writeOrchestratorRoleMarker: writeOrchestratorRoleMarker2 } = (init_src4(), __toCommonJS(src_exports3));
@@ -53987,8 +54362,8 @@ ${body}`
53987
54362
  }
53988
54363
  }
53989
54364
  const agentList = Object.entries(config2.agents).map(([id, a]) => `- ${id}: ${a.provider}/${a.model} (${a.preset || "custom"})${a.native ? " \u2014 native" : ""}`).join("\n");
53990
- const rulesDir = join82(root, env.rulesDir);
53991
- const rulesFile = join82(root, env.rulesFile);
54365
+ const rulesDir = join83(root, env.rulesDir);
54366
+ const rulesFile = join83(root, env.rulesFile);
53992
54367
  mkdirSync41(rulesDir, { recursive: true });
53993
54368
  writeFileSync34(rulesFile, generateRulesContent(agentList));
53994
54369
  const lines = [`Host: ${env.host}`, ""];
@@ -54285,11 +54660,11 @@ The original signal remains in the audit log but will be excluded from scoring.`
54285
54660
  const fid = finding_id.trim();
54286
54661
  const cwd = process.cwd();
54287
54662
  const findingsPath = require("path").join(cwd, ".gossip", "implementation-findings.jsonl");
54288
- const { readFileSync: readFileSync62, existsSync: existsSync69, writeFileSync: writeFileSync34, renameSync: renameSync15 } = require("fs");
54289
- if (!existsSync69(findingsPath)) {
54663
+ const { readFileSync: readFileSync64, existsSync: existsSync70, writeFileSync: writeFileSync34, renameSync: renameSync15 } = require("fs");
54664
+ if (!existsSync70(findingsPath)) {
54290
54665
  return { content: [{ type: "text", text: `No implementation-findings.jsonl found at ${findingsPath}` }] };
54291
54666
  }
54292
- const lines = readFileSync62(findingsPath, "utf-8").split("\n");
54667
+ const lines = readFileSync64(findingsPath, "utf-8").split("\n");
54293
54668
  let matched = false;
54294
54669
  let alreadyTarget = false;
54295
54670
  let matchedEntry = null;
@@ -54377,18 +54752,18 @@ The original signal remains in the audit log but will be excluded from scoring.`
54377
54752
  return { content: [{ type: "text", text: "Error: consensus_id is required for bulk_from_consensus." }] };
54378
54753
  }
54379
54754
  try {
54380
- const { readFileSync: readFileSync62 } = await import("fs");
54381
- const { join: join82 } = await import("path");
54382
- const reportPath = join82(process.cwd(), ".gossip", "consensus-reports", `${consensus_id}.json`);
54755
+ const { readFileSync: readFileSync64 } = await import("fs");
54756
+ const { join: join83 } = await import("path");
54757
+ const reportPath = join83(process.cwd(), ".gossip", "consensus-reports", `${consensus_id}.json`);
54383
54758
  let report;
54384
54759
  try {
54385
- report = JSON.parse(readFileSync62(reportPath, "utf-8"));
54760
+ report = JSON.parse(readFileSync64(reportPath, "utf-8"));
54386
54761
  } catch {
54387
54762
  return { content: [{ type: "text", text: `Error: consensus report not found: ${consensus_id}` }] };
54388
54763
  }
54389
54764
  const existingFindingIds = /* @__PURE__ */ new Set();
54390
54765
  try {
54391
- const perfPath = join82(process.cwd(), ".gossip", "agent-performance.jsonl");
54766
+ const perfPath = join83(process.cwd(), ".gossip", "agent-performance.jsonl");
54392
54767
  const { readJsonlWithRotated: readJsonlRotated2570 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
54393
54768
  const lines = readJsonlRotated2570(perfPath).split("\n").filter(Boolean);
54394
54769
  for (const line of lines) {
@@ -55404,16 +55779,16 @@ ${preview}` }]
55404
55779
  const { SkillGapTracker: SkillGapTracker2, parseSkillFrontmatter: parseSkillFrontmatter2, normalizeSkillName: normalizeSkillName2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
55405
55780
  const tracker = new SkillGapTracker2(process.cwd());
55406
55781
  if (skills && skills.length > 0) {
55407
- const { writeFileSync: writeFileSync34, mkdirSync: mkdirSync41, existsSync: existsSync69, readFileSync: readFileSync62 } = require("fs");
55408
- const { join: join82 } = require("path");
55409
- const dir = join82(process.cwd(), ".gossip", "skills");
55782
+ const { writeFileSync: writeFileSync34, mkdirSync: mkdirSync41, existsSync: existsSync70, readFileSync: readFileSync64 } = require("fs");
55783
+ const { join: join83 } = require("path");
55784
+ const dir = join83(process.cwd(), ".gossip", "skills");
55410
55785
  mkdirSync41(dir, { recursive: true });
55411
55786
  const results = [];
55412
55787
  for (const sk of skills) {
55413
55788
  const name = normalizeSkillName2(sk.name);
55414
- const filePath = join82(dir, `${name}.md`);
55415
- if (existsSync69(filePath)) {
55416
- const existing = readFileSync62(filePath, "utf-8");
55789
+ const filePath = join83(dir, `${name}.md`);
55790
+ if (existsSync70(filePath)) {
55791
+ const existing = readFileSync64(filePath, "utf-8");
55417
55792
  const fm = parseSkillFrontmatter2(existing);
55418
55793
  if (fm) {
55419
55794
  if (fm.generated_by === "manual") {
@@ -56249,9 +56624,9 @@ ${p.user}
56249
56624
  max_events: external_exports.number().int().positive().max(WATCH_MAX_EVENTS).optional().describe(`Cap events returned (default ${WATCH_MAX_EVENTS}).`)
56250
56625
  },
56251
56626
  async ({ cursor, max_events }) => {
56252
- const { join: join82 } = await import("node:path");
56627
+ const { join: join83 } = await import("node:path");
56253
56628
  const { readJsonlWithRotated: readJsonlWithRotated2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
56254
- const perfPath = join82(process.cwd(), ".gossip", "agent-performance.jsonl");
56629
+ const perfPath = join83(process.cwd(), ".gossip", "agent-performance.jsonl");
56255
56630
  const raw = readJsonlWithRotated2(perfPath);
56256
56631
  const result = filterWatchEvents(raw, { cursor, maxEvents: max_events });
56257
56632
  return { content: [{ type: "text", text: JSON.stringify(result) }] };