gossipcat 0.4.30 → 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.
- package/README.md +41 -8
- package/dist-dashboard/assets/Geist-Variable-jflMhO5d.woff2 +0 -0
- package/dist-dashboard/assets/dashboard-overview.png +0 -0
- package/dist-dashboard/assets/dashboard-skills.png +0 -0
- package/dist-dashboard/assets/dashboard-team.png +0 -0
- package/dist-dashboard/assets/index-BggwL1Da.css +1 -0
- package/dist-dashboard/assets/index-BxhrNkau.js +78 -0
- package/dist-dashboard/index.html +16 -8
- package/dist-mcp/mcp-server.js +829 -414
- package/package.json +1 -1
- package/dist-dashboard/assets/index-CC9eddQj.css +0 -1
- package/dist-dashboard/assets/index-CLlV_738.js +0 -71
package/dist-mcp/mcp-server.js
CHANGED
|
@@ -734,8 +734,8 @@ var init_agent_registry = __esm({
|
|
|
734
734
|
setPerformanceReader(reader) {
|
|
735
735
|
this.perfReader = reader;
|
|
736
736
|
}
|
|
737
|
-
setSuggesterCache(
|
|
738
|
-
this.suggesterCache =
|
|
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,
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
12779
|
+
function resolveBoundAtMs(agentId, category, projectRoot, cache3, fallbackMs) {
|
|
12780
12780
|
const key = agentId + "\0" + category;
|
|
12781
|
-
const cached4 =
|
|
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
|
-
|
|
12790
|
+
cache3.set(key, ms);
|
|
12791
12791
|
return ms;
|
|
12792
12792
|
}
|
|
12793
12793
|
}
|
|
12794
12794
|
} catch {
|
|
12795
12795
|
}
|
|
12796
|
-
|
|
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
|
|
17370
|
-
if (Object.prototype.hasOwnProperty.call(
|
|
17371
|
-
return
|
|
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
|
|
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(
|
|
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:
|
|
23827
|
-
const { join:
|
|
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 =
|
|
23837
|
-
const instructions =
|
|
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:
|
|
24035
|
-
const { join:
|
|
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 =
|
|
24053
|
-
const instructions =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
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
|
-
|
|
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,
|
|
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,
|
|
30968
|
-
const preRel = (0,
|
|
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,
|
|
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,
|
|
31314
|
+
realAbs = (0, import_fs57.realpathSync)(abs);
|
|
30977
31315
|
} catch {
|
|
30978
31316
|
continue;
|
|
30979
31317
|
}
|
|
30980
|
-
const rel = (0,
|
|
31318
|
+
const rel = (0, import_path63.relative)(realRoot, realAbs);
|
|
30981
31319
|
if (rel === "" || rel.startsWith("..")) continue;
|
|
30982
31320
|
try {
|
|
30983
|
-
const lines = (0,
|
|
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,
|
|
30997
|
-
if (!(0,
|
|
30998
|
-
const report = JSON.parse((0,
|
|
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,
|
|
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
|
|
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
|
-
|
|
31403
|
+
import_fs57 = require("fs");
|
|
31066
31404
|
init_src4();
|
|
31067
|
-
|
|
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,
|
|
31081
|
-
if (!(0,
|
|
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,
|
|
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
|
|
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
|
-
|
|
31129
|
-
|
|
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,
|
|
31136
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
31146
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
31492
|
+
const filepath = (0, import_path65.join)(knowledgeDir, filename);
|
|
31155
31493
|
try {
|
|
31156
|
-
const stat4 = (0,
|
|
31157
|
-
const raw = (0,
|
|
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
|
|
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
|
-
|
|
31189
|
-
|
|
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,
|
|
31201
|
-
if (!(0,
|
|
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 = (
|
|
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
|
|
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
|
-
|
|
31266
|
-
|
|
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,
|
|
31274
|
-
if (!(0,
|
|
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,
|
|
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
|
|
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
|
-
|
|
31311
|
-
|
|
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,
|
|
31326
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
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,
|
|
31691
|
+
const bytesRead = (0, import_fs62.readSync)(fd, buf, 0, readLen, readFrom);
|
|
31341
31692
|
buf = buf.subarray(0, bytesRead);
|
|
31342
31693
|
} finally {
|
|
31343
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
31388
|
-
|
|
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,
|
|
31421
|
-
if (!(0,
|
|
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,
|
|
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
|
|
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
|
-
|
|
31449
|
-
|
|
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,
|
|
31808
|
+
(0, import_path70.resolve)(__dirname, "..", "dist-dashboard"),
|
|
31458
31809
|
// bundled: dist-mcp/mcp-server.js → ../dist-dashboard
|
|
31459
|
-
(0,
|
|
31810
|
+
(0, import_path70.resolve)(__dirname, "..", "..", "..", "..", "dist-dashboard"),
|
|
31460
31811
|
// tsc dev: packages/relay/dist/dashboard → repo-root
|
|
31461
|
-
(0,
|
|
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,
|
|
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
|
|
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
|
-
|
|
31514
|
-
|
|
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,
|
|
31796
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
32202
|
+
const filePath = (0, import_path70.join)(this.dashboardRoot, relativePath);
|
|
31828
32203
|
try {
|
|
31829
|
-
const realFile = (0,
|
|
31830
|
-
const realBase = (0,
|
|
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,
|
|
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:
|
|
31852
|
-
const reportsDir = (0,
|
|
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 (!
|
|
32237
|
+
if (!existsSync70(reportsDir)) return { reports: [], totalReports: 0, page, pageSize, retractedConsensusIds, roundRetractions };
|
|
31863
32238
|
try {
|
|
31864
|
-
const { statSync:
|
|
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 =
|
|
31868
|
-
const bTime =
|
|
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,
|
|
32254
|
+
const realReportsDir = (0, import_fs64.realpathSync)(reportsDir);
|
|
31880
32255
|
const reports = files.map((f) => {
|
|
31881
32256
|
try {
|
|
31882
|
-
const filePath = (0,
|
|
31883
|
-
const realFile = (0,
|
|
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(
|
|
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:
|
|
31897
|
-
const reportsDir = (0,
|
|
31898
|
-
const archiveDir = (0,
|
|
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 (
|
|
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,
|
|
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,
|
|
32289
|
+
const findingsPath = (0, import_path70.join)(this.projectRoot, ".gossip", "implementation-findings.jsonl");
|
|
31915
32290
|
let findingsCleared = 0;
|
|
31916
|
-
if (
|
|
32291
|
+
if (existsSync70(findingsPath)) {
|
|
31917
32292
|
try {
|
|
31918
|
-
const lines =
|
|
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 =
|
|
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,
|
|
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
|
-
|
|
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,
|
|
31981
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
33060
|
+
if ((0, import_fs67.existsSync)(rotated)) (0, import_fs67.unlinkSync)(rotated);
|
|
32686
33061
|
} catch {
|
|
32687
33062
|
}
|
|
32688
|
-
(0,
|
|
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,
|
|
32762
|
-
if (!(0,
|
|
32763
|
-
const raw = JSON.parse((0,
|
|
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,
|
|
32774
|
-
(0,
|
|
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,
|
|
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,
|
|
32799
|
-
if (!(0,
|
|
32800
|
-
const raw = (0,
|
|
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,
|
|
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,
|
|
32828
|
-
(0,
|
|
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,
|
|
32831
|
-
const fd = (0,
|
|
32832
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
32850
|
-
if (!(0,
|
|
32851
|
-
const raw = (0,
|
|
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,
|
|
32884
|
-
s = (0,
|
|
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,
|
|
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,
|
|
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 +
|
|
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,
|
|
32959
|
-
(0,
|
|
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,
|
|
33345
|
+
const escapeFile = (0, import_path72.join)(dir, BOUNDARY_ESCAPE_FILE);
|
|
32971
33346
|
rotateIfNeeded2(escapeFile, MAX_BOUNDARY_ESCAPE_BYTES);
|
|
32972
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
33357
|
-
(0,
|
|
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,
|
|
33743
|
+
const escapeFile = (0, import_path72.join)(dir, BOUNDARY_ESCAPE_FILE);
|
|
33369
33744
|
rotateIfNeeded2(escapeFile, MAX_BOUNDARY_ESCAPE_BYTES);
|
|
33370
|
-
(0,
|
|
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,
|
|
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
|
-
|
|
33807
|
+
import_fs67 = require("fs");
|
|
33433
33808
|
import_os5 = require("os");
|
|
33434
|
-
|
|
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,
|
|
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,
|
|
33519
|
-
const finalPath = (0,
|
|
33520
|
-
const tmpPath = (0,
|
|
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,
|
|
33523
|
-
(0,
|
|
33897
|
+
(0, import_fs68.writeFileSync)(tmpPath, body, "utf8");
|
|
33898
|
+
(0, import_fs68.renameSync)(tmpPath, finalPath);
|
|
33524
33899
|
} catch (err) {
|
|
33525
33900
|
try {
|
|
33526
|
-
(0,
|
|
33901
|
+
(0, import_fs68.unlinkSync)(tmpPath);
|
|
33527
33902
|
} catch {
|
|
33528
33903
|
}
|
|
33529
33904
|
throw err;
|
|
33530
33905
|
}
|
|
33531
|
-
return (0,
|
|
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,
|
|
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,
|
|
33540
|
-
const path7 = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
33973
|
+
const path7 = (0, import_path73.join)(dir, name);
|
|
33599
33974
|
let mtimeMs = 0;
|
|
33600
33975
|
try {
|
|
33601
|
-
mtimeMs = (0,
|
|
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,
|
|
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,
|
|
34001
|
+
return (0, import_path73.resolve)((0, import_path73.join)(dispatchPromptsDir(projectRoot), `${taskId}.txt`));
|
|
33627
34002
|
}
|
|
33628
|
-
var
|
|
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
|
-
|
|
33633
|
-
|
|
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,
|
|
33688
|
-
const logPath = (0,
|
|
33689
|
-
(0,
|
|
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
|
|
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
|
-
|
|
33744
|
-
|
|
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:
|
|
33831
|
-
const dir =
|
|
34205
|
+
const { join: join83 } = require("path");
|
|
34206
|
+
const dir = join83(projectRoot, ".gossip");
|
|
33832
34207
|
mkdirSync41(dir, { recursive: true });
|
|
33833
|
-
appendFileSync21(
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
34670
|
-
(0,
|
|
34671
|
-
const finalPath = (0,
|
|
34672
|
-
const tmpPath = (0,
|
|
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,
|
|
34675
|
-
(0,
|
|
35049
|
+
(0, import_fs70.writeFileSync)(tmpPath, skillsSection, "utf8");
|
|
35050
|
+
(0, import_fs70.renameSync)(tmpPath, finalPath);
|
|
34676
35051
|
} catch (err) {
|
|
34677
35052
|
try {
|
|
34678
|
-
(0,
|
|
35053
|
+
(0, import_fs70.unlinkSync)(tmpPath);
|
|
34679
35054
|
} catch {
|
|
34680
35055
|
}
|
|
34681
35056
|
throw err;
|
|
34682
35057
|
}
|
|
34683
|
-
return (0,
|
|
35058
|
+
return (0, import_path75.resolve)(finalPath);
|
|
34684
35059
|
}
|
|
34685
|
-
var import_crypto29,
|
|
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
|
-
|
|
34691
|
-
|
|
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,
|
|
34715
|
-
(0,
|
|
34716
|
-
(0,
|
|
34717
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
34816
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
35200
|
+
const filePath = (0, import_path76.join)(agentsDir, file2);
|
|
34826
35201
|
try {
|
|
34827
|
-
const content = (0,
|
|
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
|
|
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
|
-
|
|
34887
|
-
|
|
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:
|
|
34958
|
-
const reportsDir =
|
|
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(
|
|
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:
|
|
35130
|
-
const reportsDir =
|
|
35504
|
+
const { join: join83 } = require("path");
|
|
35505
|
+
const reportsDir = join83(process.cwd(), ".gossip", "consensus-reports");
|
|
35131
35506
|
mkdirSync41(reportsDir, { recursive: true });
|
|
35132
|
-
const reportPath =
|
|
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:
|
|
35179
|
-
const dir =
|
|
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(
|
|
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:
|
|
35214
|
-
const { join:
|
|
35215
|
-
const filePath =
|
|
35216
|
-
if (!
|
|
35217
|
-
const raw = JSON.parse(
|
|
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,
|
|
35326
|
-
const finalPath = (0,
|
|
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,
|
|
35330
|
-
(0,
|
|
35331
|
-
(0,
|
|
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,
|
|
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,
|
|
35718
|
+
const baseDir = (0, import_path78.join)(opts.projectRoot, ".gossip", "agents");
|
|
35344
35719
|
let agentDirs = [];
|
|
35345
35720
|
let canonicalBaseDir;
|
|
35346
|
-
if ((0,
|
|
35721
|
+
if ((0, import_fs74.existsSync)(baseDir)) {
|
|
35347
35722
|
try {
|
|
35348
|
-
canonicalBaseDir = (0,
|
|
35349
|
-
agentDirs = (0,
|
|
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,
|
|
35369
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
35435
|
-
|
|
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,
|
|
35449
|
-
(0,
|
|
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,
|
|
35452
|
-
(0,
|
|
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
|
|
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
|
-
|
|
35461
|
-
|
|
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,
|
|
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
|
-
|
|
35479
|
-
|
|
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,
|
|
35524
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
35545
|
-
const dir = (0,
|
|
35546
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
36029
|
+
const saltPath = (0, import_path84.join)(projectRoot, ".gossip", "local-salt");
|
|
35655
36030
|
try {
|
|
35656
|
-
return (0,
|
|
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,
|
|
36034
|
+
(0, import_fs80.mkdirSync)((0, import_path84.join)(projectRoot, ".gossip"), { recursive: true });
|
|
35660
36035
|
try {
|
|
35661
|
-
(0,
|
|
36036
|
+
(0, import_fs80.writeFileSync)(saltPath, salt, { flag: "wx" });
|
|
35662
36037
|
return salt;
|
|
35663
36038
|
} catch {
|
|
35664
|
-
return (0,
|
|
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
|
|
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
|
-
|
|
35719
|
-
|
|
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,
|
|
36116
|
+
const packageRoot = (0, import_path85.resolve)(__dirname, "..", "..", "..", "..");
|
|
35742
36117
|
if (process.env.npm_config_global === "true") return "global";
|
|
35743
|
-
if ((0,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
35827
|
-
|
|
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
|
|
36039
|
-
var
|
|
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
|
|
49943
|
-
var
|
|
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
|
|
50325
|
+
var import_fs73 = require("fs");
|
|
49951
50326
|
|
|
49952
50327
|
// apps/cli/src/handlers/relay-tasks.ts
|
|
49953
50328
|
init_mcp_context();
|
|
@@ -50040,10 +50415,16 @@ function stampConcurrencyTaint(map2) {
|
|
|
50040
50415
|
}
|
|
50041
50416
|
return true;
|
|
50042
50417
|
}
|
|
50043
|
-
function elidePromptIfRequested(projectRoot, taskId, agentPrompt, promptFormat, warmCached = false) {
|
|
50418
|
+
function elidePromptIfRequested(projectRoot, taskId, agentPrompt, promptFormat, warmCached = false, writeMode) {
|
|
50044
50419
|
if (promptFormat !== "elided") return { elided: false };
|
|
50045
|
-
const
|
|
50046
|
-
|
|
50420
|
+
const body = writeMode === "worktree" ? `// GOSSIP_ISOLATION: worktree
|
|
50421
|
+
// This task was dispatched with write_mode: "worktree".
|
|
50422
|
+
// The orchestrator MUST invoke Agent() with isolation: "worktree".
|
|
50423
|
+
// Do not paraphrase this requirement.
|
|
50424
|
+
|
|
50425
|
+
` + agentPrompt : agentPrompt;
|
|
50426
|
+
const bytes = Buffer.byteLength(body, "utf8");
|
|
50427
|
+
const promptPath = writeDispatchPrompt(projectRoot, taskId, body);
|
|
50047
50428
|
const warmSuffix = warmCached ? " \u2014 warm-cached (skills) + live task" : "";
|
|
50048
50429
|
const marker = `[skills section elided: see ${promptPath}, ${bytes} bytes${warmSuffix} \u2014 READ this file and pass its CONTENTS verbatim as the Agent(prompt: ...) value. Do NOT pass the path string.]`;
|
|
50049
50430
|
return { elided: true, promptPath, marker, bytes };
|
|
@@ -50054,7 +50435,7 @@ function tryWarmCacheHit(liveTaskBlock, cacheKey, promptFormat) {
|
|
|
50054
50435
|
const cached4 = getCachedPrompt(cacheKey);
|
|
50055
50436
|
if (!cached4) return null;
|
|
50056
50437
|
if (cached4.skillFingerprint !== cacheKey.skillFingerprint) return null;
|
|
50057
|
-
if (!(0,
|
|
50438
|
+
if (!(0, import_fs73.existsSync)(cached4.skillsSectionPath)) return null;
|
|
50058
50439
|
try {
|
|
50059
50440
|
const skillsSection = require("fs").readFileSync(cached4.skillsSectionPath, "utf8");
|
|
50060
50441
|
return skillsSection + liveTaskBlock;
|
|
@@ -50131,9 +50512,9 @@ function formatFalsifiedNote(block, verdicts) {
|
|
|
50131
50512
|
}
|
|
50132
50513
|
function writePremiseVerificationLog(projectRoot, taskId, result, opts) {
|
|
50133
50514
|
try {
|
|
50134
|
-
const logPath = (0,
|
|
50515
|
+
const logPath = (0, import_path77.join)(projectRoot, PREMISE_VERIFICATION_LOG);
|
|
50135
50516
|
rotateIfNeeded2(logPath, MAX_PREMISE_VERIFICATION_BYTES);
|
|
50136
|
-
(0,
|
|
50517
|
+
(0, import_fs72.mkdirSync)((0, import_path77.join)(projectRoot, ".gossip"), { recursive: true });
|
|
50137
50518
|
const row = {
|
|
50138
50519
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
50139
50520
|
consensus_id: null,
|
|
@@ -50147,7 +50528,7 @@ function writePremiseVerificationLog(projectRoot, taskId, result, opts) {
|
|
|
50147
50528
|
skill_bound: opts.skill_bound
|
|
50148
50529
|
};
|
|
50149
50530
|
if (opts.schema_lint) row.schema_lint = opts.schema_lint;
|
|
50150
|
-
(0,
|
|
50531
|
+
(0, import_fs72.appendFileSync)(logPath, JSON.stringify(row) + "\n");
|
|
50151
50532
|
} catch {
|
|
50152
50533
|
}
|
|
50153
50534
|
}
|
|
@@ -50259,7 +50640,7 @@ var AGENT_PROVIDER_MAP = {
|
|
|
50259
50640
|
};
|
|
50260
50641
|
function readQuotaState() {
|
|
50261
50642
|
try {
|
|
50262
|
-
const raw = (0,
|
|
50643
|
+
const raw = (0, import_fs72.readFileSync)((0, import_path77.join)(process.cwd(), ".gossip", "quota-state.json"), "utf8");
|
|
50263
50644
|
return JSON.parse(raw);
|
|
50264
50645
|
} catch {
|
|
50265
50646
|
return {};
|
|
@@ -50415,17 +50796,31 @@ Task: ${task}`;
|
|
|
50415
50796
|
worktreePath: void 0,
|
|
50416
50797
|
timestamp: Date.now()
|
|
50417
50798
|
});
|
|
50418
|
-
const elision = elidePromptIfRequested(
|
|
50799
|
+
const elision = elidePromptIfRequested(
|
|
50800
|
+
process.cwd(),
|
|
50801
|
+
taskId,
|
|
50802
|
+
agentPrompt,
|
|
50803
|
+
prompt_format,
|
|
50804
|
+
singleWarm,
|
|
50805
|
+
useWorktree ? "worktree" : void 0
|
|
50806
|
+
);
|
|
50419
50807
|
if (elision.elided) {
|
|
50420
50808
|
const info = ctx.nativeTaskMap.get(taskId);
|
|
50421
50809
|
if (info) info.promptPath = elision.promptPath;
|
|
50422
50810
|
}
|
|
50423
50811
|
persistNativeTaskMap();
|
|
50812
|
+
const promptRef = elision.elided ? "<file contents>" : `<AGENT_PROMPT:${taskId} below>`;
|
|
50813
|
+
const agentCall = useWorktree ? `Agent(
|
|
50814
|
+
model: "${nativeConfig.model}",
|
|
50815
|
+
prompt: ${promptRef},
|
|
50816
|
+
isolation: "worktree", // REQUIRED \u2014 do not omit
|
|
50817
|
+
run_in_background: true
|
|
50818
|
+
)` : `Agent(model: "${nativeConfig.model}", prompt: ${promptRef}, run_in_background: true)`;
|
|
50424
50819
|
const promptInstruction = elision.elided ? `Step 1 \u2014 ${elision.marker}
|
|
50425
|
-
|
|
50820
|
+
${agentCall}
|
|
50426
50821
|
|
|
50427
50822
|
` : `Step 1 \u2014 Pass the AGENT_PROMPT:${taskId} content item below verbatim to Agent(prompt: ...):
|
|
50428
|
-
|
|
50823
|
+
${agentCall}
|
|
50429
50824
|
|
|
50430
50825
|
`;
|
|
50431
50826
|
return { content: [
|
|
@@ -50437,8 +50832,10 @@ NATIVE_DISPATCH: Execute this via Claude Code Agent tool, then relay the result.
|
|
|
50437
50832
|
Task ID: ${taskId}
|
|
50438
50833
|
Agent: ${agent_id}
|
|
50439
50834
|
Model: ${nativeConfig.model}
|
|
50835
|
+
` + (useWorktree ? `Worktree isolation: REQUIRED \u2014 Agent() MUST be invoked with isolation: "worktree"
|
|
50440
50836
|
|
|
50441
|
-
`
|
|
50837
|
+
` : `
|
|
50838
|
+
`) + promptInstruction + `Step 2 \u2014 REQUIRED after agent completes:
|
|
50442
50839
|
gossip_relay(task_id: "${taskId}", relay_token: "${relayToken}", result: "<agent output>")
|
|
50443
50840
|
(VERBATIM \u2014 pass the agent's raw output; do NOT paraphrase or summarize, or <agent_finding> tags will be lost)
|
|
50444
50841
|
|
|
@@ -50680,15 +51077,24 @@ Task: ${def.task}`;
|
|
|
50680
51077
|
worktreePath: void 0,
|
|
50681
51078
|
timestamp: Date.now()
|
|
50682
51079
|
});
|
|
50683
|
-
const parallelElision = elidePromptIfRequested(process.cwd(), taskId, agentPrompt, prompt_format, parallelWarm);
|
|
51080
|
+
const parallelElision = elidePromptIfRequested(process.cwd(), taskId, agentPrompt, prompt_format, parallelWarm, def.write_mode);
|
|
50684
51081
|
if (parallelElision.elided) {
|
|
50685
51082
|
const info = ctx.nativeTaskMap.get(taskId);
|
|
50686
51083
|
if (info) info.promptPath = parallelElision.promptPath;
|
|
50687
51084
|
}
|
|
50688
51085
|
const parallelPromptRef = parallelElision.elided ? parallelElision.marker : `<AGENT_PROMPT:${taskId} below>`;
|
|
51086
|
+
const parallelUseWorktree = def.write_mode === "worktree";
|
|
51087
|
+
const parallelWorktreeBanner = parallelUseWorktree ? `
|
|
51088
|
+
Worktree isolation: REQUIRED \u2014 Agent() MUST be invoked with isolation: "worktree"` : "";
|
|
51089
|
+
const parallelAgentCall = parallelUseWorktree ? `Agent(
|
|
51090
|
+
model: "${nativeConfig.model}",
|
|
51091
|
+
prompt: ${parallelPromptRef},
|
|
51092
|
+
isolation: "worktree", // REQUIRED \u2014 do not omit
|
|
51093
|
+
run_in_background: true
|
|
51094
|
+
)` : `Agent(model: "${nativeConfig.model}", prompt: ${parallelPromptRef}, run_in_background: true)`;
|
|
50689
51095
|
lines.push(` ${taskId} \u2192 ${def.agent_id} (native \u2014 dispatch via Agent tool)`);
|
|
50690
51096
|
nativeInstructions.push(
|
|
50691
|
-
`[${taskId}]
|
|
51097
|
+
`[${taskId}] ${parallelAgentCall}${parallelWorktreeBanner}
|
|
50692
51098
|
\u2192 then: gossip_relay(task_id: "${taskId}", relay_token: "${relayToken}", result: "<output>")`
|
|
50693
51099
|
);
|
|
50694
51100
|
if (!parallelElision.elided) {
|
|
@@ -50898,16 +51304,25 @@ Task: ${def.task}`;
|
|
|
50898
51304
|
}
|
|
50899
51305
|
}
|
|
50900
51306
|
agentPrompt = maybeApplyUnverifiedNote(agentPrompt, def.task, def.agent_id);
|
|
50901
|
-
const consensusElision = elidePromptIfRequested(process.cwd(), taskId, agentPrompt, prompt_format, consensusWarm);
|
|
51307
|
+
const consensusElision = elidePromptIfRequested(process.cwd(), taskId, agentPrompt, prompt_format, consensusWarm, def.write_mode);
|
|
50902
51308
|
if (consensusElision.elided) {
|
|
50903
51309
|
const info = ctx.nativeTaskMap.get(taskId);
|
|
50904
51310
|
if (info) info.promptPath = consensusElision.promptPath;
|
|
50905
51311
|
persistNativeTaskMap();
|
|
50906
51312
|
}
|
|
50907
51313
|
const consensusPromptRef = consensusElision.elided ? consensusElision.marker : `<AGENT_PROMPT:${taskId} below>`;
|
|
51314
|
+
const consensusUseWorktree = def.write_mode === "worktree";
|
|
51315
|
+
const consensusWorktreeBanner = consensusUseWorktree ? `
|
|
51316
|
+
Worktree isolation: REQUIRED \u2014 Agent() MUST be invoked with isolation: "worktree"` : "";
|
|
51317
|
+
const consensusAgentCall = consensusUseWorktree ? `Agent(
|
|
51318
|
+
model: "${nativeConfig.model}",
|
|
51319
|
+
prompt: ${consensusPromptRef},
|
|
51320
|
+
isolation: "worktree", // REQUIRED \u2014 do not omit
|
|
51321
|
+
run_in_background: true
|
|
51322
|
+
)` : `Agent(model: "${nativeConfig.model}", prompt: ${consensusPromptRef}, run_in_background: true)`;
|
|
50908
51323
|
lines.push(` ${taskId} \u2192 ${def.agent_id} (native \u2014 dispatch via Agent tool)`);
|
|
50909
51324
|
nativeInstructions.push(
|
|
50910
|
-
`[${taskId}]
|
|
51325
|
+
`[${taskId}] ${consensusAgentCall}${consensusWorktreeBanner}
|
|
50911
51326
|
\u2192 then: gossip_relay(task_id: "${taskId}", relay_token: "${relayToken}", result: "<output>")`
|
|
50912
51327
|
);
|
|
50913
51328
|
if (!consensusElision.elided) {
|
|
@@ -51053,13 +51468,13 @@ function buildAutoVerifyDispatch(binding) {
|
|
|
51053
51468
|
var _autoResolverErrors = /* @__PURE__ */ new Set();
|
|
51054
51469
|
var _autoResolverLockWarned = false;
|
|
51055
51470
|
var CONSENSUS_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{8}$/;
|
|
51056
|
-
function
|
|
51471
|
+
function isValidConsensusId2(id) {
|
|
51057
51472
|
return typeof id === "string" && CONSENSUS_ID_RE.test(id);
|
|
51058
51473
|
}
|
|
51059
51474
|
function extractConsensusIdFromFindingId(findingId) {
|
|
51060
51475
|
if (typeof findingId !== "string") return void 0;
|
|
51061
51476
|
const first = findingId.split(":")[0];
|
|
51062
|
-
return
|
|
51477
|
+
return isValidConsensusId2(first) ? first : void 0;
|
|
51063
51478
|
}
|
|
51064
51479
|
function reconcilerFindingsAll(consensusReport) {
|
|
51065
51480
|
return [
|
|
@@ -51761,7 +52176,7 @@ ${np.user}
|
|
|
51761
52176
|
...consensusReport.unique || []
|
|
51762
52177
|
];
|
|
51763
52178
|
const authoritativeId = consensusReport?.signals?.[0]?.consensusId;
|
|
51764
|
-
const provisionalConsensusId = (
|
|
52179
|
+
const provisionalConsensusId = (isValidConsensusId2(authoritativeId) ? authoritativeId : void 0) ?? (allFindings.length > 0 ? extractConsensusIdFromFindingId(allFindings[0].id) : void 0);
|
|
51765
52180
|
const provisionalSignals = allFindings.filter((f) => !isFindingAlreadySignaled(alreadySignaled, f)).map((f) => {
|
|
51766
52181
|
const extracted = extractCategories2(f.finding || "");
|
|
51767
52182
|
const category = f.category || extracted[0] || void 0;
|
|
@@ -52009,19 +52424,19 @@ function filterWatchEvents(rawJsonl, opts) {
|
|
|
52009
52424
|
}
|
|
52010
52425
|
|
|
52011
52426
|
// apps/cli/src/stickyPort.ts
|
|
52012
|
-
var
|
|
52013
|
-
var
|
|
52427
|
+
var import_fs76 = require("fs");
|
|
52428
|
+
var import_path80 = require("path");
|
|
52014
52429
|
var import_net = require("net");
|
|
52015
|
-
var RELAY_STICKY_FILE = (0,
|
|
52016
|
-
var HTTP_MCP_STICKY_FILE = (0,
|
|
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");
|
|
52017
52432
|
function stickyPath(filename) {
|
|
52018
|
-
return (0,
|
|
52433
|
+
return (0, import_path80.join)(process.cwd(), filename);
|
|
52019
52434
|
}
|
|
52020
52435
|
function readStickyPort(filename) {
|
|
52021
52436
|
const p = stickyPath(filename);
|
|
52022
|
-
if (!(0,
|
|
52437
|
+
if (!(0, import_fs76.existsSync)(p)) return null;
|
|
52023
52438
|
try {
|
|
52024
|
-
const raw = (0,
|
|
52439
|
+
const raw = (0, import_fs76.readFileSync)(p, "utf-8").trim();
|
|
52025
52440
|
const n = parseInt(raw, 10);
|
|
52026
52441
|
if (!Number.isFinite(n) || n < 1 || n > 65535) return null;
|
|
52027
52442
|
return n;
|
|
@@ -52033,8 +52448,8 @@ function writeStickyPort(filename, port) {
|
|
|
52033
52448
|
if (!Number.isFinite(port) || port < 1 || port > 65535) return;
|
|
52034
52449
|
const p = stickyPath(filename);
|
|
52035
52450
|
try {
|
|
52036
|
-
(0,
|
|
52037
|
-
(0,
|
|
52451
|
+
(0, import_fs76.mkdirSync)((0, import_path80.dirname)(p), { recursive: true });
|
|
52452
|
+
(0, import_fs76.writeFileSync)(p, String(port), "utf-8");
|
|
52038
52453
|
} catch {
|
|
52039
52454
|
}
|
|
52040
52455
|
}
|
|
@@ -52098,22 +52513,22 @@ function buildDashboardAdvisory(input) {
|
|
|
52098
52513
|
}
|
|
52099
52514
|
|
|
52100
52515
|
// apps/cli/src/native-agent-cache.ts
|
|
52101
|
-
var
|
|
52102
|
-
var
|
|
52516
|
+
var import_fs77 = require("fs");
|
|
52517
|
+
var import_path81 = require("path");
|
|
52103
52518
|
var realFs = {
|
|
52104
|
-
existsSync:
|
|
52105
|
-
readFileSync:
|
|
52106
|
-
statSync: (p) => ({ mtimeMs: (0,
|
|
52519
|
+
existsSync: import_fs77.existsSync,
|
|
52520
|
+
readFileSync: import_fs77.readFileSync,
|
|
52521
|
+
statSync: (p) => ({ mtimeMs: (0, import_fs77.statSync)(p).mtimeMs })
|
|
52107
52522
|
};
|
|
52108
52523
|
function modelTierFromId(modelId) {
|
|
52109
52524
|
if (modelId.includes("opus")) return "opus";
|
|
52110
52525
|
if (modelId.includes("haiku")) return "haiku";
|
|
52111
52526
|
return "sonnet";
|
|
52112
52527
|
}
|
|
52113
|
-
function refreshNativeAgentFromDisk(ac,
|
|
52114
|
-
const claudeAgentPath = (0,
|
|
52115
|
-
const instrPath = (0,
|
|
52116
|
-
const prev =
|
|
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);
|
|
52117
52532
|
let sourcePath = null;
|
|
52118
52533
|
let stripFrontmatter = false;
|
|
52119
52534
|
if (fs6.existsSync(claudeAgentPath)) {
|
|
@@ -52127,7 +52542,7 @@ function refreshNativeAgentFromDisk(ac, cache2, projectRoot, fs6 = realFs) {
|
|
|
52127
52542
|
if (prev && prev.instructions.length > 0) {
|
|
52128
52543
|
return;
|
|
52129
52544
|
}
|
|
52130
|
-
|
|
52545
|
+
cache3.set(ac.id, {
|
|
52131
52546
|
model: modelTierFromId(ac.model),
|
|
52132
52547
|
instructions: "",
|
|
52133
52548
|
description: ac.role || ac.preset || "",
|
|
@@ -52143,7 +52558,7 @@ function refreshNativeAgentFromDisk(ac, cache2, projectRoot, fs6 = realFs) {
|
|
|
52143
52558
|
if (prev && prev.instructions.length > 0) {
|
|
52144
52559
|
return;
|
|
52145
52560
|
}
|
|
52146
|
-
|
|
52561
|
+
cache3.set(ac.id, {
|
|
52147
52562
|
model: modelTierFromId(ac.model),
|
|
52148
52563
|
instructions: "",
|
|
52149
52564
|
description: ac.role || ac.preset || "",
|
|
@@ -52161,7 +52576,7 @@ function refreshNativeAgentFromDisk(ac, cache2, projectRoot, fs6 = realFs) {
|
|
|
52161
52576
|
if (instructions.length === 0 && prev && prev.instructions.length > 0) {
|
|
52162
52577
|
return;
|
|
52163
52578
|
}
|
|
52164
|
-
|
|
52579
|
+
cache3.set(ac.id, {
|
|
52165
52580
|
model: modelTierFromId(ac.model),
|
|
52166
52581
|
instructions,
|
|
52167
52582
|
description: ac.role || ac.preset || "",
|
|
@@ -52171,16 +52586,16 @@ function refreshNativeAgentFromDisk(ac, cache2, projectRoot, fs6 = realFs) {
|
|
|
52171
52586
|
}
|
|
52172
52587
|
|
|
52173
52588
|
// apps/cli/src/rules-content.ts
|
|
52174
|
-
var
|
|
52175
|
-
var
|
|
52589
|
+
var import_fs78 = require("fs");
|
|
52590
|
+
var import_path82 = require("path");
|
|
52176
52591
|
var AGENT_LIST_PLACEHOLDER = "{{AGENT_LIST}}";
|
|
52177
52592
|
function resolveRulesPath() {
|
|
52178
52593
|
const candidates = [
|
|
52179
|
-
(0,
|
|
52180
|
-
(0,
|
|
52181
|
-
(0,
|
|
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")
|
|
52182
52597
|
];
|
|
52183
|
-
return candidates.find((p) => (0,
|
|
52598
|
+
return candidates.find((p) => (0, import_fs78.existsSync)(p)) ?? null;
|
|
52184
52599
|
}
|
|
52185
52600
|
function generateRulesContent(agentList) {
|
|
52186
52601
|
const rulesPath = resolveRulesPath();
|
|
@@ -52189,7 +52604,7 @@ function generateRulesContent(agentList) {
|
|
|
52189
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/.`
|
|
52190
52605
|
);
|
|
52191
52606
|
}
|
|
52192
|
-
const template = (0,
|
|
52607
|
+
const template = (0, import_fs78.readFileSync)(rulesPath, "utf-8");
|
|
52193
52608
|
return template.split(AGENT_LIST_PLACEHOLDER).join(agentList);
|
|
52194
52609
|
}
|
|
52195
52610
|
|
|
@@ -52259,12 +52674,12 @@ function isReservedAgentId(id) {
|
|
|
52259
52674
|
}
|
|
52260
52675
|
}
|
|
52261
52676
|
if (process.env.GOSSIPCAT_MCP_NO_MAIN !== "1") {
|
|
52262
|
-
const gossipDir = (0,
|
|
52677
|
+
const gossipDir = (0, import_path86.join)(process.cwd(), ".gossip");
|
|
52263
52678
|
try {
|
|
52264
|
-
(0,
|
|
52679
|
+
(0, import_fs82.mkdirSync)(gossipDir, { recursive: true });
|
|
52265
52680
|
} catch {
|
|
52266
52681
|
}
|
|
52267
|
-
const logStream = (0,
|
|
52682
|
+
const logStream = (0, import_fs82.createWriteStream)((0, import_path86.join)(gossipDir, "mcp.log"), { flags: "a" });
|
|
52268
52683
|
process.stderr.write = ((chunk, ...args) => {
|
|
52269
52684
|
return logStream.write(chunk, ...args);
|
|
52270
52685
|
});
|
|
@@ -52275,7 +52690,7 @@ try {
|
|
|
52275
52690
|
} catch {
|
|
52276
52691
|
}
|
|
52277
52692
|
function memoryDirForProject(cwd) {
|
|
52278
|
-
return (0,
|
|
52693
|
+
return (0, import_path86.join)((0, import_os7.homedir)(), ".claude", "projects", cwd.replaceAll("/", "-"), "memory");
|
|
52279
52694
|
}
|
|
52280
52695
|
function detectEnvironment() {
|
|
52281
52696
|
if (process.env.CLAUDECODE === "1" || process.env.CLAUDE_CODE_ENTRYPOINT) {
|
|
@@ -52330,14 +52745,14 @@ var _pendingPlanData = /* @__PURE__ */ new Map();
|
|
|
52330
52745
|
var _utilityGuardSnapshots = /* @__PURE__ */ new Map();
|
|
52331
52746
|
var _modules = null;
|
|
52332
52747
|
function lookupFindingSeverity(findingId, projectRoot) {
|
|
52333
|
-
const { existsSync:
|
|
52334
|
-
const { join:
|
|
52335
|
-
const reportsDir =
|
|
52336
|
-
if (!
|
|
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;
|
|
52337
52752
|
try {
|
|
52338
52753
|
const files = readdirSync22(reportsDir).filter((f) => f.endsWith(".json"));
|
|
52339
52754
|
for (const file2 of files) {
|
|
52340
|
-
const report = JSON.parse(
|
|
52755
|
+
const report = JSON.parse(readFileSync64(join83(reportsDir, file2), "utf-8"));
|
|
52341
52756
|
for (const bucket of ["confirmed", "disputed", "unverified", "unique"]) {
|
|
52342
52757
|
for (const finding of report[bucket] || []) {
|
|
52343
52758
|
if (finding.id === findingId && finding.severity) {
|
|
@@ -52415,7 +52830,7 @@ async function doBoot() {
|
|
|
52415
52830
|
const agentConfigs = m.configToAgentConfigs(config2);
|
|
52416
52831
|
ctx.keychain = new m.Keychain();
|
|
52417
52832
|
const { existsSync: pidExists, readFileSync: readPid, writeFileSync: writePid, unlinkSync: delPid } = require("fs");
|
|
52418
|
-
const pidFile = (0,
|
|
52833
|
+
const pidFile = (0, import_path86.join)(process.cwd(), ".gossip", "relay.pid");
|
|
52419
52834
|
if (pidExists(pidFile)) {
|
|
52420
52835
|
const oldPid = parseInt(readPid(pidFile, "utf-8").trim(), 10);
|
|
52421
52836
|
if (!isNaN(oldPid) && oldPid !== process.pid) {
|
|
@@ -52525,10 +52940,10 @@ async function doBoot() {
|
|
|
52525
52940
|
}
|
|
52526
52941
|
const key = await ctx.keychain.getKey(ac.provider);
|
|
52527
52942
|
const llm = m.createProvider(ac.provider, ac.model, key ?? void 0, void 0, ac.base_url);
|
|
52528
|
-
const { existsSync:
|
|
52529
|
-
const { join:
|
|
52530
|
-
const instructionsPath =
|
|
52531
|
-
const baseInstructions =
|
|
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") : "";
|
|
52532
52947
|
const identity = ctx.identityRegistry.get(ac.id);
|
|
52533
52948
|
const identityBlock = identity ? m.formatIdentityBlock(identity) + "\n" : "";
|
|
52534
52949
|
const instructions = (identityBlock + baseInstructions).trim() || void 0;
|
|
@@ -53363,7 +53778,7 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
53363
53778
|
}
|
|
53364
53779
|
try {
|
|
53365
53780
|
const { readFileSync: rfHealth } = await import("fs");
|
|
53366
|
-
const healthPath = (0,
|
|
53781
|
+
const healthPath = (0, import_path86.join)(process.cwd(), ".gossip", "skill-runner-health.json");
|
|
53367
53782
|
const raw = rfHealth(healthPath, "utf8");
|
|
53368
53783
|
const h = JSON.parse(raw);
|
|
53369
53784
|
const lastMs = h.last_run_at ? new Date(h.last_run_at).getTime() : NaN;
|
|
@@ -53379,9 +53794,9 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
53379
53794
|
lines.push(" Skill graduation: never run since session start (expected after first gossip_collect)");
|
|
53380
53795
|
}
|
|
53381
53796
|
try {
|
|
53382
|
-
const { readFileSync:
|
|
53383
|
-
const quotaPath = (0,
|
|
53384
|
-
const quotaRaw =
|
|
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");
|
|
53385
53800
|
const quotaState = JSON.parse(quotaRaw);
|
|
53386
53801
|
for (const [provider, state] of Object.entries(quotaState)) {
|
|
53387
53802
|
const now = Date.now();
|
|
@@ -53395,19 +53810,19 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
53395
53810
|
} catch {
|
|
53396
53811
|
}
|
|
53397
53812
|
try {
|
|
53398
|
-
const { readdirSync: readdirSync22, statSync:
|
|
53813
|
+
const { readdirSync: readdirSync22, statSync: statSync35 } = await import("fs");
|
|
53399
53814
|
const { readJsonlWithRotated: readJsonlRotated1506 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
53400
|
-
const reportsDir = (0,
|
|
53401
|
-
const perfPath = (0,
|
|
53402
|
-
const
|
|
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;
|
|
53403
53818
|
const now = Date.now();
|
|
53404
53819
|
const recentReports = [];
|
|
53405
53820
|
try {
|
|
53406
53821
|
for (const fname of readdirSync22(reportsDir)) {
|
|
53407
53822
|
if (!fname.endsWith(".json")) continue;
|
|
53408
|
-
const fpath = (0,
|
|
53409
|
-
const st =
|
|
53410
|
-
if (now - st.mtimeMs >
|
|
53823
|
+
const fpath = (0, import_path86.join)(reportsDir, fname);
|
|
53824
|
+
const st = statSync35(fpath);
|
|
53825
|
+
if (now - st.mtimeMs > WINDOW_MS3) continue;
|
|
53411
53826
|
recentReports.push({ id: fname.replace(/\.json$/, ""), mtimeMs: st.mtimeMs });
|
|
53412
53827
|
}
|
|
53413
53828
|
} catch {
|
|
@@ -53771,8 +54186,8 @@ ${body}`
|
|
|
53771
54186
|
}
|
|
53772
54187
|
return { content: [{ type: "text", text: results.join("\n") }] };
|
|
53773
54188
|
}
|
|
53774
|
-
const { writeFileSync: writeFileSync34, mkdirSync: mkdirSync41, existsSync:
|
|
53775
|
-
const { join:
|
|
54189
|
+
const { writeFileSync: writeFileSync34, mkdirSync: mkdirSync41, existsSync: existsSync70 } = require("fs");
|
|
54190
|
+
const { join: join83 } = require("path");
|
|
53776
54191
|
const root = process.cwd();
|
|
53777
54192
|
const CLAUDE_MODEL_MAP2 = {
|
|
53778
54193
|
opus: { provider: "anthropic", model: "claude-opus-4-6" },
|
|
@@ -53786,8 +54201,8 @@ ${body}`
|
|
|
53786
54201
|
let existingAgents = {};
|
|
53787
54202
|
if (mode === "merge") {
|
|
53788
54203
|
try {
|
|
53789
|
-
const { readFileSync:
|
|
53790
|
-
const existing = JSON.parse(
|
|
54204
|
+
const { readFileSync: readFileSync64 } = require("fs");
|
|
54205
|
+
const existing = JSON.parse(readFileSync64(join83(root, ".gossip", "config.json"), "utf-8"));
|
|
53791
54206
|
existingAgents = existing.agents || {};
|
|
53792
54207
|
} catch {
|
|
53793
54208
|
}
|
|
@@ -53818,9 +54233,9 @@ ${body}`
|
|
|
53818
54233
|
"",
|
|
53819
54234
|
body
|
|
53820
54235
|
].join("\n");
|
|
53821
|
-
const agentsDir =
|
|
54236
|
+
const agentsDir = join83(root, ".claude", "agents");
|
|
53822
54237
|
mkdirSync41(agentsDir, { recursive: true });
|
|
53823
|
-
writeFileSync34(
|
|
54238
|
+
writeFileSync34(join83(agentsDir, `${agent.id}.md`), md, "utf-8");
|
|
53824
54239
|
nativeCreated.push(agent.id);
|
|
53825
54240
|
configAgents[agent.id] = {
|
|
53826
54241
|
provider: mapped.provider,
|
|
@@ -53838,8 +54253,8 @@ ${body}`
|
|
|
53838
54253
|
errors.push(`${agent.id}: custom agent requires "custom_model" field`);
|
|
53839
54254
|
continue;
|
|
53840
54255
|
}
|
|
53841
|
-
const nativeFile =
|
|
53842
|
-
const wasNative = existingAgents[agent.id]?.native ||
|
|
54256
|
+
const nativeFile = join83(root, ".claude", "agents", `${agent.id}.md`);
|
|
54257
|
+
const wasNative = existingAgents[agent.id]?.native || existsSync70(nativeFile);
|
|
53843
54258
|
if (wasNative) {
|
|
53844
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.`);
|
|
53845
54260
|
continue;
|
|
@@ -53853,9 +54268,9 @@ ${body}`
|
|
|
53853
54268
|
};
|
|
53854
54269
|
customCreated.push(agent.id);
|
|
53855
54270
|
if (agent.instructions) {
|
|
53856
|
-
const instrDir =
|
|
54271
|
+
const instrDir = join83(root, ".gossip", "agents", agent.id);
|
|
53857
54272
|
mkdirSync41(instrDir, { recursive: true });
|
|
53858
|
-
writeFileSync34(
|
|
54273
|
+
writeFileSync34(join83(instrDir, "instructions.md"), agent.instructions, "utf-8");
|
|
53859
54274
|
}
|
|
53860
54275
|
}
|
|
53861
54276
|
}
|
|
@@ -53869,8 +54284,8 @@ ${body}`
|
|
|
53869
54284
|
} catch (err) {
|
|
53870
54285
|
return { content: [{ type: "text", text: `Invalid config: ${err.message}` }] };
|
|
53871
54286
|
}
|
|
53872
|
-
mkdirSync41(
|
|
53873
|
-
writeFileSync34(
|
|
54287
|
+
mkdirSync41(join83(root, ".gossip"), { recursive: true });
|
|
54288
|
+
writeFileSync34(join83(root, ".gossip", "config.json"), JSON.stringify(config2, null, 2));
|
|
53874
54289
|
let hookSummary = "";
|
|
53875
54290
|
try {
|
|
53876
54291
|
const { installWorktreeSandboxHook: installWorktreeSandboxHook2, writeOrchestratorRoleMarker: writeOrchestratorRoleMarker2 } = (init_src4(), __toCommonJS(src_exports3));
|
|
@@ -53947,8 +54362,8 @@ ${body}`
|
|
|
53947
54362
|
}
|
|
53948
54363
|
}
|
|
53949
54364
|
const agentList = Object.entries(config2.agents).map(([id, a]) => `- ${id}: ${a.provider}/${a.model} (${a.preset || "custom"})${a.native ? " \u2014 native" : ""}`).join("\n");
|
|
53950
|
-
const rulesDir =
|
|
53951
|
-
const rulesFile =
|
|
54365
|
+
const rulesDir = join83(root, env.rulesDir);
|
|
54366
|
+
const rulesFile = join83(root, env.rulesFile);
|
|
53952
54367
|
mkdirSync41(rulesDir, { recursive: true });
|
|
53953
54368
|
writeFileSync34(rulesFile, generateRulesContent(agentList));
|
|
53954
54369
|
const lines = [`Host: ${env.host}`, ""];
|
|
@@ -54245,11 +54660,11 @@ The original signal remains in the audit log but will be excluded from scoring.`
|
|
|
54245
54660
|
const fid = finding_id.trim();
|
|
54246
54661
|
const cwd = process.cwd();
|
|
54247
54662
|
const findingsPath = require("path").join(cwd, ".gossip", "implementation-findings.jsonl");
|
|
54248
|
-
const { readFileSync:
|
|
54249
|
-
if (!
|
|
54663
|
+
const { readFileSync: readFileSync64, existsSync: existsSync70, writeFileSync: writeFileSync34, renameSync: renameSync15 } = require("fs");
|
|
54664
|
+
if (!existsSync70(findingsPath)) {
|
|
54250
54665
|
return { content: [{ type: "text", text: `No implementation-findings.jsonl found at ${findingsPath}` }] };
|
|
54251
54666
|
}
|
|
54252
|
-
const lines =
|
|
54667
|
+
const lines = readFileSync64(findingsPath, "utf-8").split("\n");
|
|
54253
54668
|
let matched = false;
|
|
54254
54669
|
let alreadyTarget = false;
|
|
54255
54670
|
let matchedEntry = null;
|
|
@@ -54337,18 +54752,18 @@ The original signal remains in the audit log but will be excluded from scoring.`
|
|
|
54337
54752
|
return { content: [{ type: "text", text: "Error: consensus_id is required for bulk_from_consensus." }] };
|
|
54338
54753
|
}
|
|
54339
54754
|
try {
|
|
54340
|
-
const { readFileSync:
|
|
54341
|
-
const { join:
|
|
54342
|
-
const reportPath =
|
|
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`);
|
|
54343
54758
|
let report;
|
|
54344
54759
|
try {
|
|
54345
|
-
report = JSON.parse(
|
|
54760
|
+
report = JSON.parse(readFileSync64(reportPath, "utf-8"));
|
|
54346
54761
|
} catch {
|
|
54347
54762
|
return { content: [{ type: "text", text: `Error: consensus report not found: ${consensus_id}` }] };
|
|
54348
54763
|
}
|
|
54349
54764
|
const existingFindingIds = /* @__PURE__ */ new Set();
|
|
54350
54765
|
try {
|
|
54351
|
-
const perfPath =
|
|
54766
|
+
const perfPath = join83(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
54352
54767
|
const { readJsonlWithRotated: readJsonlRotated2570 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
54353
54768
|
const lines = readJsonlRotated2570(perfPath).split("\n").filter(Boolean);
|
|
54354
54769
|
for (const line of lines) {
|
|
@@ -55364,16 +55779,16 @@ ${preview}` }]
|
|
|
55364
55779
|
const { SkillGapTracker: SkillGapTracker2, parseSkillFrontmatter: parseSkillFrontmatter2, normalizeSkillName: normalizeSkillName2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
55365
55780
|
const tracker = new SkillGapTracker2(process.cwd());
|
|
55366
55781
|
if (skills && skills.length > 0) {
|
|
55367
|
-
const { writeFileSync: writeFileSync34, mkdirSync: mkdirSync41, existsSync:
|
|
55368
|
-
const { join:
|
|
55369
|
-
const dir =
|
|
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");
|
|
55370
55785
|
mkdirSync41(dir, { recursive: true });
|
|
55371
55786
|
const results = [];
|
|
55372
55787
|
for (const sk of skills) {
|
|
55373
55788
|
const name = normalizeSkillName2(sk.name);
|
|
55374
|
-
const filePath =
|
|
55375
|
-
if (
|
|
55376
|
-
const existing =
|
|
55789
|
+
const filePath = join83(dir, `${name}.md`);
|
|
55790
|
+
if (existsSync70(filePath)) {
|
|
55791
|
+
const existing = readFileSync64(filePath, "utf-8");
|
|
55377
55792
|
const fm = parseSkillFrontmatter2(existing);
|
|
55378
55793
|
if (fm) {
|
|
55379
55794
|
if (fm.generated_by === "manual") {
|
|
@@ -56209,9 +56624,9 @@ ${p.user}
|
|
|
56209
56624
|
max_events: external_exports.number().int().positive().max(WATCH_MAX_EVENTS).optional().describe(`Cap events returned (default ${WATCH_MAX_EVENTS}).`)
|
|
56210
56625
|
},
|
|
56211
56626
|
async ({ cursor, max_events }) => {
|
|
56212
|
-
const { join:
|
|
56627
|
+
const { join: join83 } = await import("node:path");
|
|
56213
56628
|
const { readJsonlWithRotated: readJsonlWithRotated2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
56214
|
-
const perfPath =
|
|
56629
|
+
const perfPath = join83(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
56215
56630
|
const raw = readJsonlWithRotated2(perfPath);
|
|
56216
56631
|
const result = filterWatchEvents(raw, { cursor, maxEvents: max_events });
|
|
56217
56632
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|