gossipcat 0.4.22 → 0.4.23
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 +34 -2
- package/dist-dashboard/assets/index-C5O8BHjE.js +71 -0
- package/dist-dashboard/assets/index-DHrxKCIK.css +1 -0
- package/dist-dashboard/index.html +2 -2
- package/dist-mcp/mcp-server.js +1425 -735
- package/package.json +1 -1
- package/dist-dashboard/assets/index-Ci46EANB.css +0 -1
- package/dist-dashboard/assets/index-aXAMEMbl.js +0 -70
package/dist-mcp/mcp-server.js
CHANGED
|
@@ -3405,9 +3405,18 @@ var init_src2 = __esm({
|
|
|
3405
3405
|
});
|
|
3406
3406
|
|
|
3407
3407
|
// packages/orchestrator/src/task-stream.ts
|
|
3408
|
+
var TaskStreamEventType;
|
|
3408
3409
|
var init_task_stream = __esm({
|
|
3409
3410
|
"packages/orchestrator/src/task-stream.ts"() {
|
|
3410
3411
|
"use strict";
|
|
3412
|
+
TaskStreamEventType = /* @__PURE__ */ ((TaskStreamEventType2) => {
|
|
3413
|
+
TaskStreamEventType2["LOG"] = "log";
|
|
3414
|
+
TaskStreamEventType2["PROGRESS"] = "progress";
|
|
3415
|
+
TaskStreamEventType2["PARTIAL_RESULT"] = "partial_result";
|
|
3416
|
+
TaskStreamEventType2["FINAL_RESULT"] = "final_result";
|
|
3417
|
+
TaskStreamEventType2["ERROR"] = "error";
|
|
3418
|
+
return TaskStreamEventType2;
|
|
3419
|
+
})(TaskStreamEventType || {});
|
|
3411
3420
|
}
|
|
3412
3421
|
});
|
|
3413
3422
|
|
|
@@ -8776,7 +8785,15 @@ var init_tool_server = __esm({
|
|
|
8776
8785
|
}
|
|
8777
8786
|
assignRoot(agentId, root) {
|
|
8778
8787
|
const abs = (0, import_path8.resolve)(root);
|
|
8779
|
-
|
|
8788
|
+
const canonical = canonicalizeForBoundary(abs);
|
|
8789
|
+
const existing = this.agentRoots.get(agentId);
|
|
8790
|
+
if (existing && existing !== canonical) {
|
|
8791
|
+
process.stderr.write(
|
|
8792
|
+
`[gossipcat] assignRoot collision: agent=${agentId} replacing root ${existing} \u2192 ${canonical} (Option B last-write-wins)
|
|
8793
|
+
`
|
|
8794
|
+
);
|
|
8795
|
+
}
|
|
8796
|
+
this.agentRoots.set(agentId, canonical);
|
|
8780
8797
|
this.writeAgents.add(agentId);
|
|
8781
8798
|
}
|
|
8782
8799
|
releaseAgent(agentId) {
|
|
@@ -9447,118 +9464,6 @@ var init_types2 = __esm({
|
|
|
9447
9464
|
}
|
|
9448
9465
|
});
|
|
9449
9466
|
|
|
9450
|
-
// packages/orchestrator/src/skill-parser.ts
|
|
9451
|
-
function parseSkillFrontmatter(content) {
|
|
9452
|
-
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
9453
|
-
if (!match) return null;
|
|
9454
|
-
const lines = match[1].split("\n");
|
|
9455
|
-
const fields = {};
|
|
9456
|
-
for (const line of lines) {
|
|
9457
|
-
const colonIdx = line.indexOf(":");
|
|
9458
|
-
if (colonIdx === -1) continue;
|
|
9459
|
-
const key = line.slice(0, colonIdx).trim();
|
|
9460
|
-
let value = line.slice(colonIdx + 1).trim();
|
|
9461
|
-
if (value.length >= 2 && (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'"))) {
|
|
9462
|
-
value = value.slice(1, -1);
|
|
9463
|
-
}
|
|
9464
|
-
fields[key] = value;
|
|
9465
|
-
}
|
|
9466
|
-
if (!fields.name || !fields.description || !fields.status) return null;
|
|
9467
|
-
let keywords = [];
|
|
9468
|
-
if (fields.keywords) {
|
|
9469
|
-
const raw = fields.keywords;
|
|
9470
|
-
if (raw.startsWith("[") && raw.endsWith("]")) {
|
|
9471
|
-
keywords = raw.slice(1, -1).split(",").map((k) => k.trim().replace(/^['"]|['"]$/g, "").slice(0, 100)).filter(Boolean);
|
|
9472
|
-
} else {
|
|
9473
|
-
keywords = raw.split(",").map((k) => k.trim().slice(0, 100)).filter(Boolean);
|
|
9474
|
-
}
|
|
9475
|
-
}
|
|
9476
|
-
const rawTaskType = fields.task_type;
|
|
9477
|
-
const task_type = rawTaskType === "review" || rawTaskType === "implement" || rawTaskType === "research" || rawTaskType === "any" ? rawTaskType : "any";
|
|
9478
|
-
let scope;
|
|
9479
|
-
if (fields.scope) {
|
|
9480
|
-
const raw = fields.scope.trim();
|
|
9481
|
-
let tokens;
|
|
9482
|
-
if (raw.startsWith("[") && raw.endsWith("]")) {
|
|
9483
|
-
tokens = raw.slice(1, -1).split(",").map((t) => t.trim().replace(/^['"]|['"]$/g, ""));
|
|
9484
|
-
} else {
|
|
9485
|
-
tokens = [raw.replace(/^['"]|['"]$/g, "")];
|
|
9486
|
-
}
|
|
9487
|
-
const valid = tokens.filter(
|
|
9488
|
-
(t) => t === "review" || t === "implement" || t === "research"
|
|
9489
|
-
);
|
|
9490
|
-
if (valid.length > 0) scope = valid;
|
|
9491
|
-
}
|
|
9492
|
-
return {
|
|
9493
|
-
name: normalizeSkillName(fields.name),
|
|
9494
|
-
description: fields.description,
|
|
9495
|
-
keywords,
|
|
9496
|
-
category: fields.category || void 0,
|
|
9497
|
-
mode: fields.mode === "contextual" ? "contextual" : fields.mode === "permanent" ? "permanent" : void 0,
|
|
9498
|
-
generated_by: fields.generated_by,
|
|
9499
|
-
sources: fields.sources,
|
|
9500
|
-
status: fields.status,
|
|
9501
|
-
task_type,
|
|
9502
|
-
scope
|
|
9503
|
-
};
|
|
9504
|
-
}
|
|
9505
|
-
var init_skill_parser = __esm({
|
|
9506
|
-
"packages/orchestrator/src/skill-parser.ts"() {
|
|
9507
|
-
"use strict";
|
|
9508
|
-
init_skill_name();
|
|
9509
|
-
}
|
|
9510
|
-
});
|
|
9511
|
-
|
|
9512
|
-
// packages/orchestrator/src/memory-config.ts
|
|
9513
|
-
function loadMemoryConfig(projectRoot) {
|
|
9514
|
-
const configPath = (0, import_path9.resolve)(projectRoot, ".gossip", "memory-config.json");
|
|
9515
|
-
if (!(0, import_fs8.existsSync)(configPath)) {
|
|
9516
|
-
return { ...DEFAULTS, bundledMemories: { ...DEFAULTS.bundledMemories } };
|
|
9517
|
-
}
|
|
9518
|
-
let raw;
|
|
9519
|
-
try {
|
|
9520
|
-
raw = (0, import_fs8.readFileSync)(configPath, "utf-8");
|
|
9521
|
-
} catch (err) {
|
|
9522
|
-
log("memory-config", `WARNING: failed to read ${configPath}: ${err?.message ?? err} \u2014 using defaults`);
|
|
9523
|
-
return { ...DEFAULTS, bundledMemories: { ...DEFAULTS.bundledMemories } };
|
|
9524
|
-
}
|
|
9525
|
-
let parsed;
|
|
9526
|
-
try {
|
|
9527
|
-
parsed = JSON.parse(raw);
|
|
9528
|
-
} catch (err) {
|
|
9529
|
-
log("memory-config", `WARNING: malformed JSON in ${configPath}: ${err?.message ?? err} \u2014 using defaults`);
|
|
9530
|
-
return { ...DEFAULTS, bundledMemories: { ...DEFAULTS.bundledMemories } };
|
|
9531
|
-
}
|
|
9532
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
9533
|
-
log("memory-config", `WARNING: ${configPath} must be a JSON object \u2014 using defaults`);
|
|
9534
|
-
return { ...DEFAULTS, bundledMemories: { ...DEFAULTS.bundledMemories } };
|
|
9535
|
-
}
|
|
9536
|
-
const obj = parsed;
|
|
9537
|
-
const bm = obj.bundledMemories;
|
|
9538
|
-
if (typeof bm !== "object" || bm === null || Array.isArray(bm)) {
|
|
9539
|
-
return { ...DEFAULTS, bundledMemories: { ...DEFAULTS.bundledMemories } };
|
|
9540
|
-
}
|
|
9541
|
-
const bmObj = bm;
|
|
9542
|
-
const enabled = typeof bmObj.enabled === "boolean" ? bmObj.enabled : DEFAULTS.bundledMemories.enabled;
|
|
9543
|
-
const exclude = Array.isArray(bmObj.exclude) ? bmObj.exclude.filter((x) => typeof x === "string") : DEFAULTS.bundledMemories.exclude;
|
|
9544
|
-
return { bundledMemories: { enabled, exclude } };
|
|
9545
|
-
}
|
|
9546
|
-
var import_fs8, import_path9, DEFAULTS;
|
|
9547
|
-
var init_memory_config = __esm({
|
|
9548
|
-
"packages/orchestrator/src/memory-config.ts"() {
|
|
9549
|
-
"use strict";
|
|
9550
|
-
import_fs8 = require("fs");
|
|
9551
|
-
import_path9 = require("path");
|
|
9552
|
-
init_log();
|
|
9553
|
-
DEFAULTS = {
|
|
9554
|
-
bundledMemories: {
|
|
9555
|
-
enabled: true,
|
|
9556
|
-
exclude: []
|
|
9557
|
-
}
|
|
9558
|
-
};
|
|
9559
|
-
}
|
|
9560
|
-
});
|
|
9561
|
-
|
|
9562
9467
|
// packages/orchestrator/src/consensus-types.ts
|
|
9563
9468
|
function classifySignal(signalName) {
|
|
9564
9469
|
if (PERFORMANCE_SIGNAL_NAMES.has(signalName)) return "performance";
|
|
@@ -9593,7 +9498,8 @@ var init_consensus_types = __esm({
|
|
|
9593
9498
|
"citation_fabricated",
|
|
9594
9499
|
"finding_dropped_format",
|
|
9595
9500
|
"consensus_round_retracted",
|
|
9596
|
-
"unverified"
|
|
9501
|
+
"unverified",
|
|
9502
|
+
"transport_failure"
|
|
9597
9503
|
]);
|
|
9598
9504
|
}
|
|
9599
9505
|
});
|
|
@@ -9688,7 +9594,28 @@ function bump(projectRoot, consensusId) {
|
|
|
9688
9594
|
const next = (inMemoryFallback.get(fbk) ?? 0) + 1;
|
|
9689
9595
|
inMemoryFallback.set(fbk, next);
|
|
9690
9596
|
} else {
|
|
9691
|
-
inMemoryFallback.
|
|
9597
|
+
const priorCount = inMemoryFallback.get(fbk) ?? 0;
|
|
9598
|
+
if (priorCount > 0) {
|
|
9599
|
+
const toFlush = Math.min(priorCount, MAX_BACKFILL_PER_BUMP);
|
|
9600
|
+
let remaining = priorCount;
|
|
9601
|
+
for (let i = 0; i < toFlush; i++) {
|
|
9602
|
+
const backfillRecord = {
|
|
9603
|
+
type: "_meta",
|
|
9604
|
+
signal: "round_counter_bumped",
|
|
9605
|
+
consensusId,
|
|
9606
|
+
bumpedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9607
|
+
_emission_path: "round-counter-bump-backfill"
|
|
9608
|
+
};
|
|
9609
|
+
if (!appendMetaRecord(projectRoot, backfillRecord)) break;
|
|
9610
|
+
remaining -= 1;
|
|
9611
|
+
inMemoryFallback.set(fbk, remaining);
|
|
9612
|
+
}
|
|
9613
|
+
if (remaining === 0) {
|
|
9614
|
+
inMemoryFallback.delete(fbk);
|
|
9615
|
+
}
|
|
9616
|
+
} else {
|
|
9617
|
+
inMemoryFallback.delete(fbk);
|
|
9618
|
+
}
|
|
9692
9619
|
}
|
|
9693
9620
|
}
|
|
9694
9621
|
function get(projectRoot, consensusId) {
|
|
@@ -9730,7 +9657,7 @@ function makeBumpRecord(consensusId, emissionPath) {
|
|
|
9730
9657
|
_emission_path: emissionPath
|
|
9731
9658
|
};
|
|
9732
9659
|
}
|
|
9733
|
-
var fs, path, JSONL_FILENAME, inMemoryFallback, fallbackKey, scanCache;
|
|
9660
|
+
var fs, path, JSONL_FILENAME, inMemoryFallback, MAX_BACKFILL_PER_BUMP, fallbackKey, scanCache;
|
|
9734
9661
|
var init_round_counter = __esm({
|
|
9735
9662
|
"packages/orchestrator/src/round-counter.ts"() {
|
|
9736
9663
|
"use strict";
|
|
@@ -9738,6 +9665,7 @@ var init_round_counter = __esm({
|
|
|
9738
9665
|
path = __toESM(require("path"));
|
|
9739
9666
|
JSONL_FILENAME = "agent-performance.jsonl";
|
|
9740
9667
|
inMemoryFallback = /* @__PURE__ */ new Map();
|
|
9668
|
+
MAX_BACKFILL_PER_BUMP = 100;
|
|
9741
9669
|
fallbackKey = (projectRoot, consensusId) => `${projectRoot} ${consensusId}`;
|
|
9742
9670
|
scanCache = /* @__PURE__ */ new Map();
|
|
9743
9671
|
}
|
|
@@ -9810,8 +9738,8 @@ function escapeControlChars(s) {
|
|
|
9810
9738
|
function readTail(filePath, n) {
|
|
9811
9739
|
const lines = [];
|
|
9812
9740
|
try {
|
|
9813
|
-
if ((0,
|
|
9814
|
-
const raw = (0,
|
|
9741
|
+
if ((0, import_fs8.existsSync)(filePath)) {
|
|
9742
|
+
const raw = (0, import_fs8.readFileSync)(filePath, "utf8");
|
|
9815
9743
|
if (raw.length > 0) {
|
|
9816
9744
|
const split = raw.split("\n").filter((l) => l.length > 0);
|
|
9817
9745
|
lines.push(...split);
|
|
@@ -9822,8 +9750,8 @@ function readTail(filePath, n) {
|
|
|
9822
9750
|
if (lines.length < n) {
|
|
9823
9751
|
try {
|
|
9824
9752
|
const rotated = filePath + ".1";
|
|
9825
|
-
if ((0,
|
|
9826
|
-
const raw = (0,
|
|
9753
|
+
if ((0, import_fs8.existsSync)(rotated)) {
|
|
9754
|
+
const raw = (0, import_fs8.readFileSync)(rotated, "utf8");
|
|
9827
9755
|
const split = raw.split("\n").filter((l) => l.length > 0);
|
|
9828
9756
|
lines.unshift(...split);
|
|
9829
9757
|
}
|
|
@@ -9832,16 +9760,16 @@ function readTail(filePath, n) {
|
|
|
9832
9760
|
}
|
|
9833
9761
|
return lines.slice(-n);
|
|
9834
9762
|
}
|
|
9835
|
-
var
|
|
9763
|
+
var import_fs8, import_path9, import_crypto7, DEFAULTS, ALLOWLIST_SET, PipelineDriftDetector;
|
|
9836
9764
|
var init_pipeline_drift_detector = __esm({
|
|
9837
9765
|
"packages/orchestrator/src/pipeline-drift-detector.ts"() {
|
|
9838
9766
|
"use strict";
|
|
9839
|
-
|
|
9840
|
-
|
|
9767
|
+
import_fs8 = require("fs");
|
|
9768
|
+
import_path9 = require("path");
|
|
9841
9769
|
import_crypto7 = require("crypto");
|
|
9842
9770
|
init_completion_signals_allowlist();
|
|
9843
9771
|
init_performance_writer();
|
|
9844
|
-
|
|
9772
|
+
DEFAULTS = {
|
|
9845
9773
|
windowSize: 500,
|
|
9846
9774
|
bypassThreshold: 1,
|
|
9847
9775
|
unknownThresholdRate: 0.01,
|
|
@@ -9856,23 +9784,23 @@ var init_pipeline_drift_detector = __esm({
|
|
|
9856
9784
|
dir;
|
|
9857
9785
|
opts;
|
|
9858
9786
|
constructor(projectRoot, options = {}) {
|
|
9859
|
-
this.dir = (0,
|
|
9860
|
-
this.perfPath = (0,
|
|
9861
|
-
this.driftPath = (0,
|
|
9862
|
-
this.statePath = (0,
|
|
9787
|
+
this.dir = (0, import_path9.join)(projectRoot, ".gossip");
|
|
9788
|
+
this.perfPath = (0, import_path9.join)(this.dir, "agent-performance.jsonl");
|
|
9789
|
+
this.driftPath = (0, import_path9.join)(this.dir, "pipeline-drift.jsonl");
|
|
9790
|
+
this.statePath = (0, import_path9.join)(this.dir, "pipeline-drift.state");
|
|
9863
9791
|
this.opts = {
|
|
9864
|
-
windowSize: options.windowSize ??
|
|
9865
|
-
bypassThreshold: options.bypassThreshold ??
|
|
9866
|
-
unknownThresholdRate: options.unknownThresholdRate ??
|
|
9867
|
-
minDenominator: options.minDenominator ??
|
|
9868
|
-
enabled: options.enabled ??
|
|
9792
|
+
windowSize: options.windowSize ?? DEFAULTS.windowSize,
|
|
9793
|
+
bypassThreshold: options.bypassThreshold ?? DEFAULTS.bypassThreshold,
|
|
9794
|
+
unknownThresholdRate: options.unknownThresholdRate ?? DEFAULTS.unknownThresholdRate,
|
|
9795
|
+
minDenominator: options.minDenominator ?? DEFAULTS.minDenominator,
|
|
9796
|
+
enabled: options.enabled ?? DEFAULTS.enabled
|
|
9869
9797
|
};
|
|
9870
9798
|
}
|
|
9871
9799
|
/** Read the last detection row from `pipeline-drift.jsonl`, or null. */
|
|
9872
9800
|
readLastReport() {
|
|
9873
9801
|
try {
|
|
9874
|
-
if (!(0,
|
|
9875
|
-
const raw = (0,
|
|
9802
|
+
if (!(0, import_fs8.existsSync)(this.driftPath)) return null;
|
|
9803
|
+
const raw = (0, import_fs8.readFileSync)(this.driftPath, "utf8");
|
|
9876
9804
|
const lines = raw.split("\n").filter((l) => l.length > 0);
|
|
9877
9805
|
if (lines.length === 0) return null;
|
|
9878
9806
|
const last = lines[lines.length - 1];
|
|
@@ -9962,9 +9890,9 @@ var init_pipeline_drift_detector = __esm({
|
|
|
9962
9890
|
const detectedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
9963
9891
|
const row = { ...result, detectedAt };
|
|
9964
9892
|
try {
|
|
9965
|
-
if (!(0,
|
|
9893
|
+
if (!(0, import_fs8.existsSync)(this.dir)) (0, import_fs8.mkdirSync)(this.dir, { recursive: true });
|
|
9966
9894
|
rotateJsonlIfNeeded2(this.driftPath);
|
|
9967
|
-
(0,
|
|
9895
|
+
(0, import_fs8.appendFileSync)(this.driftPath, JSON.stringify(row) + "\n");
|
|
9968
9896
|
} catch (err) {
|
|
9969
9897
|
try {
|
|
9970
9898
|
process.stderr.write(`[gossipcat] drift jsonl write failed: ${err.message}
|
|
@@ -9977,8 +9905,8 @@ var init_pipeline_drift_detector = __esm({
|
|
|
9977
9905
|
const safeSignal = first ? escapeControlChars(first.signal) : "";
|
|
9978
9906
|
const safePath = first ? escapeControlChars(first.emissionPath) : "";
|
|
9979
9907
|
const safeTask = first ? escapeControlChars(first.taskId) : "";
|
|
9980
|
-
const mcpLog = (0,
|
|
9981
|
-
(0,
|
|
9908
|
+
const mcpLog = (0, import_path9.join)(this.dir, "mcp.log");
|
|
9909
|
+
(0, import_fs8.appendFileSync)(
|
|
9982
9910
|
mcpLog,
|
|
9983
9911
|
`[drift] bypass=${bypassCount}/${rows.length} unknown=${unknownCount}/${postEpochCount} first_offender={path=${safePath} signal=${safeSignal} task=${safeTask}}
|
|
9984
9912
|
`
|
|
@@ -9990,8 +9918,8 @@ var init_pipeline_drift_detector = __esm({
|
|
|
9990
9918
|
}
|
|
9991
9919
|
readState() {
|
|
9992
9920
|
try {
|
|
9993
|
-
if (!(0,
|
|
9994
|
-
const raw = (0,
|
|
9921
|
+
if (!(0, import_fs8.existsSync)(this.statePath)) return {};
|
|
9922
|
+
const raw = (0, import_fs8.readFileSync)(this.statePath, "utf8");
|
|
9995
9923
|
const parsed = JSON.parse(raw);
|
|
9996
9924
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
9997
9925
|
} catch {
|
|
@@ -10000,8 +9928,8 @@ var init_pipeline_drift_detector = __esm({
|
|
|
10000
9928
|
}
|
|
10001
9929
|
writeState(next) {
|
|
10002
9930
|
try {
|
|
10003
|
-
if (!(0,
|
|
10004
|
-
(0,
|
|
9931
|
+
if (!(0, import_fs8.existsSync)(this.dir)) (0, import_fs8.mkdirSync)(this.dir, { recursive: true });
|
|
9932
|
+
(0, import_fs8.writeFileSync)(this.statePath, JSON.stringify(next));
|
|
10005
9933
|
} catch {
|
|
10006
9934
|
}
|
|
10007
9935
|
}
|
|
@@ -10012,9 +9940,9 @@ var init_pipeline_drift_detector = __esm({
|
|
|
10012
9940
|
// packages/orchestrator/src/performance-writer.ts
|
|
10013
9941
|
function rotateJsonlIfNeeded2(filePath, maxBytes = MAX_TELEMETRY_BYTES) {
|
|
10014
9942
|
try {
|
|
10015
|
-
const st = (0,
|
|
9943
|
+
const st = (0, import_fs9.statSync)(filePath);
|
|
10016
9944
|
if (st.size < maxBytes) return;
|
|
10017
|
-
(0,
|
|
9945
|
+
(0, import_fs9.renameSync)(filePath, filePath + ".1");
|
|
10018
9946
|
} catch {
|
|
10019
9947
|
}
|
|
10020
9948
|
}
|
|
@@ -10077,12 +10005,12 @@ function bumpSampleCounter(projectRoot, delta) {
|
|
|
10077
10005
|
}
|
|
10078
10006
|
}
|
|
10079
10007
|
}
|
|
10080
|
-
var
|
|
10008
|
+
var import_fs9, import_path10, 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, PerformanceWriter;
|
|
10081
10009
|
var init_performance_writer = __esm({
|
|
10082
10010
|
"packages/orchestrator/src/performance-writer.ts"() {
|
|
10083
10011
|
"use strict";
|
|
10084
|
-
|
|
10085
|
-
|
|
10012
|
+
import_fs9 = require("fs");
|
|
10013
|
+
import_path10 = require("path");
|
|
10086
10014
|
init_consensus_types();
|
|
10087
10015
|
init_round_counter();
|
|
10088
10016
|
loggedCounterErrors = /* @__PURE__ */ new Set();
|
|
@@ -10109,7 +10037,12 @@ var init_performance_writer = __esm({
|
|
|
10109
10037
|
"consensus_coverage_degraded",
|
|
10110
10038
|
// Sandbox policy violation — recorded for observability, zero weight in scoring.
|
|
10111
10039
|
// Consensus round bb03845d-64264402 (7/7 confirmed).
|
|
10112
|
-
"boundary_escape"
|
|
10040
|
+
"boundary_escape",
|
|
10041
|
+
// Transport-layer failure (relay-worker resolutionRoots gap, missing/deleted
|
|
10042
|
+
// worktree, cwd misrouting). Excluded from accuracy/uniqueness arithmetic
|
|
10043
|
+
// per performance-reader.ts:950 + L75. Pre-PR #329: rejected by validateSignal
|
|
10044
|
+
// and silently dropped, masking the fail-closed signal emit added in PR #328.
|
|
10045
|
+
"transport_failure"
|
|
10113
10046
|
]);
|
|
10114
10047
|
VALID_IMPL_SIGNALS = /* @__PURE__ */ new Set([
|
|
10115
10048
|
"impl_test_pass",
|
|
@@ -10149,9 +10082,9 @@ var init_performance_writer = __esm({
|
|
|
10149
10082
|
filePath;
|
|
10150
10083
|
projectRoot;
|
|
10151
10084
|
constructor(projectRoot) {
|
|
10152
|
-
const dir = (0,
|
|
10153
|
-
if (!(0,
|
|
10154
|
-
this.filePath = (0,
|
|
10085
|
+
const dir = (0, import_path10.join)(projectRoot, ".gossip");
|
|
10086
|
+
if (!(0, import_fs9.existsSync)(dir)) (0, import_fs9.mkdirSync)(dir, { recursive: true });
|
|
10087
|
+
this.filePath = (0, import_path10.join)(dir, "agent-performance.jsonl");
|
|
10155
10088
|
this.projectRoot = projectRoot;
|
|
10156
10089
|
}
|
|
10157
10090
|
/**
|
|
@@ -10205,7 +10138,7 @@ var init_performance_writer = __esm({
|
|
|
10205
10138
|
}
|
|
10206
10139
|
}
|
|
10207
10140
|
try {
|
|
10208
|
-
(0,
|
|
10141
|
+
(0, import_fs9.appendFileSync)(this.filePath, payload);
|
|
10209
10142
|
} catch (writeErr) {
|
|
10210
10143
|
const cid = deriveConsensusId(signal);
|
|
10211
10144
|
if (cid) {
|
|
@@ -10253,7 +10186,7 @@ var init_performance_writer = __esm({
|
|
|
10253
10186
|
const data = parts.join("\n") + "\n";
|
|
10254
10187
|
rotateJsonlIfNeeded2(this.filePath);
|
|
10255
10188
|
try {
|
|
10256
|
-
(0,
|
|
10189
|
+
(0, import_fs9.appendFileSync)(this.filePath, data);
|
|
10257
10190
|
} catch (writeErr) {
|
|
10258
10191
|
for (const s of signals) {
|
|
10259
10192
|
const cid = deriveConsensusId(s);
|
|
@@ -10313,7 +10246,7 @@ var init_performance_writer = __esm({
|
|
|
10313
10246
|
validateSignal(classStamped);
|
|
10314
10247
|
const stamped = { ...classStamped, _emission_path: "mcp-server-signals" };
|
|
10315
10248
|
try {
|
|
10316
|
-
(0,
|
|
10249
|
+
(0, import_fs9.appendFileSync)(this.filePath, JSON.stringify(stamped) + "\n");
|
|
10317
10250
|
} finally {
|
|
10318
10251
|
try {
|
|
10319
10252
|
reset(this.projectRoot, consensusId);
|
|
@@ -10405,6 +10338,118 @@ var init_signal_helpers = __esm({
|
|
|
10405
10338
|
}
|
|
10406
10339
|
});
|
|
10407
10340
|
|
|
10341
|
+
// packages/orchestrator/src/skill-parser.ts
|
|
10342
|
+
function parseSkillFrontmatter(content) {
|
|
10343
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
10344
|
+
if (!match) return null;
|
|
10345
|
+
const lines = match[1].split("\n");
|
|
10346
|
+
const fields = {};
|
|
10347
|
+
for (const line of lines) {
|
|
10348
|
+
const colonIdx = line.indexOf(":");
|
|
10349
|
+
if (colonIdx === -1) continue;
|
|
10350
|
+
const key = line.slice(0, colonIdx).trim();
|
|
10351
|
+
let value = line.slice(colonIdx + 1).trim();
|
|
10352
|
+
if (value.length >= 2 && (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'"))) {
|
|
10353
|
+
value = value.slice(1, -1);
|
|
10354
|
+
}
|
|
10355
|
+
fields[key] = value;
|
|
10356
|
+
}
|
|
10357
|
+
if (!fields.name || !fields.description || !fields.status) return null;
|
|
10358
|
+
let keywords = [];
|
|
10359
|
+
if (fields.keywords) {
|
|
10360
|
+
const raw = fields.keywords;
|
|
10361
|
+
if (raw.startsWith("[") && raw.endsWith("]")) {
|
|
10362
|
+
keywords = raw.slice(1, -1).split(",").map((k) => k.trim().replace(/^['"]|['"]$/g, "").slice(0, 100)).filter(Boolean);
|
|
10363
|
+
} else {
|
|
10364
|
+
keywords = raw.split(",").map((k) => k.trim().slice(0, 100)).filter(Boolean);
|
|
10365
|
+
}
|
|
10366
|
+
}
|
|
10367
|
+
const rawTaskType = fields.task_type;
|
|
10368
|
+
const task_type = rawTaskType === "review" || rawTaskType === "implement" || rawTaskType === "research" || rawTaskType === "any" ? rawTaskType : "any";
|
|
10369
|
+
let scope;
|
|
10370
|
+
if (fields.scope) {
|
|
10371
|
+
const raw = fields.scope.trim();
|
|
10372
|
+
let tokens;
|
|
10373
|
+
if (raw.startsWith("[") && raw.endsWith("]")) {
|
|
10374
|
+
tokens = raw.slice(1, -1).split(",").map((t) => t.trim().replace(/^['"]|['"]$/g, ""));
|
|
10375
|
+
} else {
|
|
10376
|
+
tokens = [raw.replace(/^['"]|['"]$/g, "")];
|
|
10377
|
+
}
|
|
10378
|
+
const valid = tokens.filter(
|
|
10379
|
+
(t) => t === "review" || t === "implement" || t === "research"
|
|
10380
|
+
);
|
|
10381
|
+
if (valid.length > 0) scope = valid;
|
|
10382
|
+
}
|
|
10383
|
+
return {
|
|
10384
|
+
name: normalizeSkillName(fields.name),
|
|
10385
|
+
description: fields.description,
|
|
10386
|
+
keywords,
|
|
10387
|
+
category: fields.category || void 0,
|
|
10388
|
+
mode: fields.mode === "contextual" ? "contextual" : fields.mode === "permanent" ? "permanent" : void 0,
|
|
10389
|
+
generated_by: fields.generated_by,
|
|
10390
|
+
sources: fields.sources,
|
|
10391
|
+
status: fields.status,
|
|
10392
|
+
task_type,
|
|
10393
|
+
scope
|
|
10394
|
+
};
|
|
10395
|
+
}
|
|
10396
|
+
var init_skill_parser = __esm({
|
|
10397
|
+
"packages/orchestrator/src/skill-parser.ts"() {
|
|
10398
|
+
"use strict";
|
|
10399
|
+
init_skill_name();
|
|
10400
|
+
}
|
|
10401
|
+
});
|
|
10402
|
+
|
|
10403
|
+
// packages/orchestrator/src/memory-config.ts
|
|
10404
|
+
function loadMemoryConfig(projectRoot) {
|
|
10405
|
+
const configPath = (0, import_path11.resolve)(projectRoot, ".gossip", "memory-config.json");
|
|
10406
|
+
if (!(0, import_fs10.existsSync)(configPath)) {
|
|
10407
|
+
return { ...DEFAULTS2, bundledMemories: { ...DEFAULTS2.bundledMemories } };
|
|
10408
|
+
}
|
|
10409
|
+
let raw;
|
|
10410
|
+
try {
|
|
10411
|
+
raw = (0, import_fs10.readFileSync)(configPath, "utf-8");
|
|
10412
|
+
} catch (err) {
|
|
10413
|
+
log("memory-config", `WARNING: failed to read ${configPath}: ${err?.message ?? err} \u2014 using defaults`);
|
|
10414
|
+
return { ...DEFAULTS2, bundledMemories: { ...DEFAULTS2.bundledMemories } };
|
|
10415
|
+
}
|
|
10416
|
+
let parsed;
|
|
10417
|
+
try {
|
|
10418
|
+
parsed = JSON.parse(raw);
|
|
10419
|
+
} catch (err) {
|
|
10420
|
+
log("memory-config", `WARNING: malformed JSON in ${configPath}: ${err?.message ?? err} \u2014 using defaults`);
|
|
10421
|
+
return { ...DEFAULTS2, bundledMemories: { ...DEFAULTS2.bundledMemories } };
|
|
10422
|
+
}
|
|
10423
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
10424
|
+
log("memory-config", `WARNING: ${configPath} must be a JSON object \u2014 using defaults`);
|
|
10425
|
+
return { ...DEFAULTS2, bundledMemories: { ...DEFAULTS2.bundledMemories } };
|
|
10426
|
+
}
|
|
10427
|
+
const obj = parsed;
|
|
10428
|
+
const bm = obj.bundledMemories;
|
|
10429
|
+
if (typeof bm !== "object" || bm === null || Array.isArray(bm)) {
|
|
10430
|
+
return { ...DEFAULTS2, bundledMemories: { ...DEFAULTS2.bundledMemories } };
|
|
10431
|
+
}
|
|
10432
|
+
const bmObj = bm;
|
|
10433
|
+
const enabled = typeof bmObj.enabled === "boolean" ? bmObj.enabled : DEFAULTS2.bundledMemories.enabled;
|
|
10434
|
+
const exclude = Array.isArray(bmObj.exclude) ? bmObj.exclude.filter((x) => typeof x === "string") : DEFAULTS2.bundledMemories.exclude;
|
|
10435
|
+
return { bundledMemories: { enabled, exclude } };
|
|
10436
|
+
}
|
|
10437
|
+
var import_fs10, import_path11, DEFAULTS2;
|
|
10438
|
+
var init_memory_config = __esm({
|
|
10439
|
+
"packages/orchestrator/src/memory-config.ts"() {
|
|
10440
|
+
"use strict";
|
|
10441
|
+
import_fs10 = require("fs");
|
|
10442
|
+
import_path11 = require("path");
|
|
10443
|
+
init_log();
|
|
10444
|
+
DEFAULTS2 = {
|
|
10445
|
+
bundledMemories: {
|
|
10446
|
+
enabled: true,
|
|
10447
|
+
exclude: []
|
|
10448
|
+
}
|
|
10449
|
+
};
|
|
10450
|
+
}
|
|
10451
|
+
});
|
|
10452
|
+
|
|
10408
10453
|
// packages/orchestrator/src/skill-loader.ts
|
|
10409
10454
|
function categoryBoost(skillCategory, categories) {
|
|
10410
10455
|
if (!skillCategory || categories.length === 0) return 0;
|
|
@@ -11039,6 +11084,7 @@ ${content}
|
|
|
11039
11084
|
}
|
|
11040
11085
|
const confirmed = entry.confirmedBy;
|
|
11041
11086
|
if (!Array.isArray(confirmed) || confirmed.length === 0) continue;
|
|
11087
|
+
if (entry.type === "insight") continue;
|
|
11042
11088
|
const ts2 = entry.timestamp;
|
|
11043
11089
|
if (ts2) {
|
|
11044
11090
|
const ms = typeof ts2 === "number" ? ts2 : new Date(ts2).getTime();
|
|
@@ -14471,7 +14517,13 @@ var init_performance_reader = __esm({
|
|
|
14471
14517
|
boundary_escape: true,
|
|
14472
14518
|
task_timeout: true,
|
|
14473
14519
|
task_empty: true,
|
|
14474
|
-
consensus_coverage_degraded: true
|
|
14520
|
+
consensus_coverage_degraded: true,
|
|
14521
|
+
// Operational rewrite from hallucination_caught when the relay worker ran
|
|
14522
|
+
// without the dispatched resolutionRoots (Path 2, spec
|
|
14523
|
+
// docs/specs/2026-04-29-relay-worker-resolution-roots.md). Listed here so the
|
|
14524
|
+
// scoring switch's exhaustiveness check holds; it's a no-op for accuracy /
|
|
14525
|
+
// uniqueness / circuit breaker — only `transport_failure_count` is bumped.
|
|
14526
|
+
transport_failure: true
|
|
14475
14527
|
};
|
|
14476
14528
|
SEVERITY_MULTIPLIER = {
|
|
14477
14529
|
critical: 4,
|
|
@@ -14609,9 +14661,9 @@ var init_performance_reader = __esm({
|
|
|
14609
14661
|
/** Get a reliability multiplier for dispatch weighting (0.3 to 2.0) */
|
|
14610
14662
|
getDispatchWeight(agentId) {
|
|
14611
14663
|
const score = this.getAgentScore(agentId);
|
|
14612
|
-
if (!score || score.
|
|
14664
|
+
if (!score || score.scoringSignals < 3) return 1;
|
|
14613
14665
|
if (score.circuitOpen) return 0.3;
|
|
14614
|
-
const confidence = 1 - Math.exp(-score.
|
|
14666
|
+
const confidence = 1 - Math.exp(-score.scoringSignals / 10);
|
|
14615
14667
|
const consensusAdjusted = 0.5 + (score.reliability - 0.5) * confidence;
|
|
14616
14668
|
return clamp(0.3 + consensusAdjusted * 1.7, 0.3, 2);
|
|
14617
14669
|
}
|
|
@@ -14696,8 +14748,8 @@ var init_performance_reader = __esm({
|
|
|
14696
14748
|
isBenched(agentId, categories, allAgentIds) {
|
|
14697
14749
|
const score = this.getAgentScore(agentId);
|
|
14698
14750
|
if (!score) return { benched: false };
|
|
14699
|
-
const ruleA = score.accuracy < 0.3 && score.
|
|
14700
|
-
const hallRate = score.
|
|
14751
|
+
const ruleA = score.accuracy < 0.3 && score.scoringSignals >= 200;
|
|
14752
|
+
const hallRate = score.scoringSignals > 0 ? score.weightedHallucinations / score.scoringSignals : 0;
|
|
14701
14753
|
const ruleB = score.weightedHallucinations >= 5 && hallRate > 0.4;
|
|
14702
14754
|
if (!ruleA && !ruleB) return { benched: false };
|
|
14703
14755
|
const reason = ruleA ? "chronic-low-accuracy" : "burst-hallucination";
|
|
@@ -14910,10 +14962,12 @@ var init_performance_reader = __esm({
|
|
|
14910
14962
|
unverifiedsEmitted: 0,
|
|
14911
14963
|
unverifiedsReceived: 0,
|
|
14912
14964
|
totalSignals: 0,
|
|
14965
|
+
scoringSignals: 0,
|
|
14913
14966
|
lastSignalMs: 0,
|
|
14914
14967
|
categoryStrengths: {},
|
|
14915
14968
|
categoryCorrect: {},
|
|
14916
|
-
categoryHallucinated: {}
|
|
14969
|
+
categoryHallucinated: {},
|
|
14970
|
+
transportFailures: 0
|
|
14917
14971
|
});
|
|
14918
14972
|
return acc.get(id);
|
|
14919
14973
|
};
|
|
@@ -15017,6 +15071,7 @@ var init_performance_reader = __esm({
|
|
|
15017
15071
|
case "category_confirmed":
|
|
15018
15072
|
case "consensus_verified": {
|
|
15019
15073
|
const diversityMul = signal.signal === "agreement" ? peerDiversity.get(signal.agentId) ?? 1 : 1;
|
|
15074
|
+
a.scoringSignals++;
|
|
15020
15075
|
a.weightedCorrect += sevMul * decay * diversityMul;
|
|
15021
15076
|
a.weightedTotal += sevMul * decay * diversityMul;
|
|
15022
15077
|
a.agreements++;
|
|
@@ -15030,8 +15085,9 @@ var init_performance_reader = __esm({
|
|
|
15030
15085
|
}
|
|
15031
15086
|
case "disagreement": {
|
|
15032
15087
|
if (!signal.category) {
|
|
15033
|
-
|
|
15088
|
+
break;
|
|
15034
15089
|
}
|
|
15090
|
+
a.scoringSignals++;
|
|
15035
15091
|
a.weightedTotal += sevMul * decay;
|
|
15036
15092
|
a.disagreements++;
|
|
15037
15093
|
if (signal.counterpartId && signal.counterpartId.length > 0) {
|
|
@@ -15047,6 +15103,7 @@ var init_performance_reader = __esm({
|
|
|
15047
15103
|
break;
|
|
15048
15104
|
}
|
|
15049
15105
|
case "unverified": {
|
|
15106
|
+
a.scoringSignals++;
|
|
15050
15107
|
a.weightedTotal += decay * 0.02;
|
|
15051
15108
|
a.unverifiedsEmitted++;
|
|
15052
15109
|
if (signal.counterpartId && signal.counterpartId.length > 0) {
|
|
@@ -15056,6 +15113,7 @@ var init_performance_reader = __esm({
|
|
|
15056
15113
|
break;
|
|
15057
15114
|
}
|
|
15058
15115
|
case "unique_confirmed": {
|
|
15116
|
+
a.scoringSignals++;
|
|
15059
15117
|
a.weightedCorrect += sevMul * decay;
|
|
15060
15118
|
a.weightedTotal += sevMul * decay;
|
|
15061
15119
|
a.weightedUnique += 0.2 * sevMul * decay;
|
|
@@ -15068,11 +15126,13 @@ var init_performance_reader = __esm({
|
|
|
15068
15126
|
break;
|
|
15069
15127
|
}
|
|
15070
15128
|
case "unique_unconfirmed": {
|
|
15129
|
+
a.scoringSignals++;
|
|
15071
15130
|
a.weightedUnique += 0.05 * decay;
|
|
15072
15131
|
a.uniqueFindings++;
|
|
15073
15132
|
break;
|
|
15074
15133
|
}
|
|
15075
15134
|
case "new_finding": {
|
|
15135
|
+
a.scoringSignals++;
|
|
15076
15136
|
a.weightedUnique += 0.15 * decay;
|
|
15077
15137
|
a.uniqueFindings++;
|
|
15078
15138
|
break;
|
|
@@ -15099,6 +15159,7 @@ var init_performance_reader = __esm({
|
|
|
15099
15159
|
}
|
|
15100
15160
|
}
|
|
15101
15161
|
}
|
|
15162
|
+
a.scoringSignals++;
|
|
15102
15163
|
a.weightedHallucinations += severity * hallucDecay * gatedMultiplier;
|
|
15103
15164
|
a.weightedTotal += decay;
|
|
15104
15165
|
a.hallucinations++;
|
|
@@ -15110,6 +15171,9 @@ var init_performance_reader = __esm({
|
|
|
15110
15171
|
case "task_timeout":
|
|
15111
15172
|
case "task_empty":
|
|
15112
15173
|
break;
|
|
15174
|
+
case "transport_failure":
|
|
15175
|
+
a.transportFailures++;
|
|
15176
|
+
break;
|
|
15113
15177
|
case "boundary_escape":
|
|
15114
15178
|
break;
|
|
15115
15179
|
}
|
|
@@ -15118,6 +15182,7 @@ var init_performance_reader = __esm({
|
|
|
15118
15182
|
const signalsByAgent = /* @__PURE__ */ new Map();
|
|
15119
15183
|
for (const signal of consensusSignals) {
|
|
15120
15184
|
if (!KNOWN_SIGNALS[signal.signal]) continue;
|
|
15185
|
+
if (signal.signal === "transport_failure") continue;
|
|
15121
15186
|
const list = signalsByAgent.get(signal.agentId) || [];
|
|
15122
15187
|
list.push(signal);
|
|
15123
15188
|
signalsByAgent.set(signal.agentId, list);
|
|
@@ -15180,6 +15245,7 @@ var init_performance_reader = __esm({
|
|
|
15180
15245
|
reliability,
|
|
15181
15246
|
impactScore,
|
|
15182
15247
|
totalSignals: a.totalSignals,
|
|
15248
|
+
scoringSignals: a.scoringSignals,
|
|
15183
15249
|
agreements: a.agreements,
|
|
15184
15250
|
disagreements: a.disagreements,
|
|
15185
15251
|
uniqueFindings: a.uniqueFindings,
|
|
@@ -15192,7 +15258,8 @@ var init_performance_reader = __esm({
|
|
|
15192
15258
|
categoryStrengths: a.categoryStrengths,
|
|
15193
15259
|
categoryCorrect: { ...a.categoryCorrect },
|
|
15194
15260
|
categoryHallucinated: { ...a.categoryHallucinated },
|
|
15195
|
-
categoryAccuracy
|
|
15261
|
+
categoryAccuracy,
|
|
15262
|
+
transport_failure_count: a.transportFailures
|
|
15196
15263
|
});
|
|
15197
15264
|
}
|
|
15198
15265
|
for (const [agentId, consec] of consecutiveFailures) {
|
|
@@ -15204,6 +15271,7 @@ var init_performance_reader = __esm({
|
|
|
15204
15271
|
reliability: 0.5,
|
|
15205
15272
|
impactScore: 0.5,
|
|
15206
15273
|
totalSignals: 0,
|
|
15274
|
+
scoringSignals: 0,
|
|
15207
15275
|
agreements: 0,
|
|
15208
15276
|
disagreements: 0,
|
|
15209
15277
|
uniqueFindings: 0,
|
|
@@ -15216,7 +15284,8 @@ var init_performance_reader = __esm({
|
|
|
15216
15284
|
categoryStrengths: {},
|
|
15217
15285
|
categoryCorrect: {},
|
|
15218
15286
|
categoryHallucinated: {},
|
|
15219
|
-
categoryAccuracy: {}
|
|
15287
|
+
categoryAccuracy: {},
|
|
15288
|
+
transport_failure_count: 0
|
|
15220
15289
|
});
|
|
15221
15290
|
}
|
|
15222
15291
|
}
|
|
@@ -18263,6 +18332,8 @@ var init_dispatch_pipeline = __esm({
|
|
|
18263
18332
|
import_fs27 = require("fs");
|
|
18264
18333
|
import_path29 = require("path");
|
|
18265
18334
|
init_types2();
|
|
18335
|
+
init_worker_agent();
|
|
18336
|
+
init_signal_helpers();
|
|
18266
18337
|
init_skill_loader();
|
|
18267
18338
|
init_prompt_assembler();
|
|
18268
18339
|
init_agent_memory();
|
|
@@ -18493,10 +18564,14 @@ var init_dispatch_pipeline = __esm({
|
|
|
18493
18564
|
entry.scope = options?.scope;
|
|
18494
18565
|
entry.planId = options?.planId;
|
|
18495
18566
|
entry.planStep = options?.step;
|
|
18567
|
+
if (options?.resolutionRoots && options.resolutionRoots.length > 0) {
|
|
18568
|
+
entry.resolutionRoots = options.resolutionRoots;
|
|
18569
|
+
}
|
|
18496
18570
|
if (options?.writeMode === "scoped" && options.scope) {
|
|
18497
18571
|
this.scopeTracker.register(options.scope, taskId);
|
|
18498
18572
|
}
|
|
18499
18573
|
const prevSequential = options?.writeMode === "sequential" ? this.sequentialQueues.get(agentId) : void 0;
|
|
18574
|
+
let resolutionRootAssigned = false;
|
|
18500
18575
|
const runTask = async () => {
|
|
18501
18576
|
if (prevSequential) await prevSequential.catch(() => {
|
|
18502
18577
|
});
|
|
@@ -18505,6 +18580,37 @@ var init_dispatch_pipeline = __esm({
|
|
|
18505
18580
|
entry.worktreeInfo = wtInfo;
|
|
18506
18581
|
this.toolServer?.assignRoot(agentId, wtInfo.path);
|
|
18507
18582
|
}
|
|
18583
|
+
const rrCandidate = options?.resolutionRoots?.[0];
|
|
18584
|
+
if (rrCandidate && worker instanceof WorkerAgent) {
|
|
18585
|
+
let dirOk = false;
|
|
18586
|
+
try {
|
|
18587
|
+
dirOk = (0, import_fs27.existsSync)(rrCandidate) && (0, import_fs27.statSync)(rrCandidate).isDirectory();
|
|
18588
|
+
} catch {
|
|
18589
|
+
dirOk = false;
|
|
18590
|
+
}
|
|
18591
|
+
if (!dirOk) {
|
|
18592
|
+
const errMsg = `resolutionRoots[0] does not exist or is not a directory: ${rrCandidate}`;
|
|
18593
|
+
try {
|
|
18594
|
+
emitConsensusSignals(this.projectRoot, [{
|
|
18595
|
+
type: "consensus",
|
|
18596
|
+
signal: "transport_failure",
|
|
18597
|
+
agentId,
|
|
18598
|
+
taskId,
|
|
18599
|
+
evidence: `dispatch failed: ${errMsg}`,
|
|
18600
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18601
|
+
source: "auto"
|
|
18602
|
+
}]);
|
|
18603
|
+
} catch {
|
|
18604
|
+
}
|
|
18605
|
+
throw new Error(errMsg);
|
|
18606
|
+
}
|
|
18607
|
+
if (this.toolServer) {
|
|
18608
|
+
this.toolServer.assignRoot(agentId, rrCandidate);
|
|
18609
|
+
resolutionRootAssigned = true;
|
|
18610
|
+
entry.resolutionRootAssigned = true;
|
|
18611
|
+
gossipLog(`\u2192 resolutionRoots: assignRoot(${agentId}, ${rrCandidate}) [taskId=${taskId}]`);
|
|
18612
|
+
}
|
|
18613
|
+
}
|
|
18508
18614
|
const stream = worker.executeTask(task, options?.lens, promptContent, taskId);
|
|
18509
18615
|
entry.stream = stream;
|
|
18510
18616
|
for await (const event of stream) {
|
|
@@ -18523,6 +18629,10 @@ var init_dispatch_pipeline = __esm({
|
|
|
18523
18629
|
entry.completedAt = Date.now();
|
|
18524
18630
|
entry.memoryQueryCalled = event.payload.memoryQueryCalled ?? false;
|
|
18525
18631
|
if (entry.writeMode === "scoped") this.scopeTracker.release(entry.id);
|
|
18632
|
+
if (resolutionRootAssigned) {
|
|
18633
|
+
this.toolServer?.releaseAgent(agentId);
|
|
18634
|
+
resolutionRootAssigned = false;
|
|
18635
|
+
}
|
|
18526
18636
|
try {
|
|
18527
18637
|
const elapsedMs = (entry.completedAt ?? Date.now()) - entry.startedAt;
|
|
18528
18638
|
gossipLog(`\u2705 relay \u2190 ${entry.agentId} [${entry.id}] OK (${(elapsedMs / 1e3).toFixed(1)}s, ${(event.payload.result || "").length} chars)`);
|
|
@@ -18557,6 +18667,10 @@ var init_dispatch_pipeline = __esm({
|
|
|
18557
18667
|
this.worktreeManager.cleanup(entry.id, entry.worktreeInfo.path).catch(() => {
|
|
18558
18668
|
});
|
|
18559
18669
|
}
|
|
18670
|
+
if (resolutionRootAssigned) {
|
|
18671
|
+
this.toolServer?.releaseAgent(agentId);
|
|
18672
|
+
resolutionRootAssigned = false;
|
|
18673
|
+
}
|
|
18560
18674
|
try {
|
|
18561
18675
|
const elapsedMs = (entry.completedAt ?? Date.now()) - entry.startedAt;
|
|
18562
18676
|
gossipLog(`\u274C relay \u2190 ${entry.agentId} [${entry.id}] FAILED (${(elapsedMs / 1e3).toFixed(1)}s) \u2014 ${event.payload.error}`);
|
|
@@ -18603,7 +18717,8 @@ var init_dispatch_pipeline = __esm({
|
|
|
18603
18717
|
agentId: t.agentId,
|
|
18604
18718
|
task: t.task,
|
|
18605
18719
|
startedAt: t.startedAt,
|
|
18606
|
-
timeoutMs: 3e5
|
|
18720
|
+
timeoutMs: 3e5,
|
|
18721
|
+
...t.resolutionRoots && t.resolutionRoots.length > 0 ? { resolutionRoots: t.resolutionRoots } : {}
|
|
18607
18722
|
}));
|
|
18608
18723
|
}
|
|
18609
18724
|
/** Get a health summary of all active tasks — for diagnostics when user asks "is it working?" */
|
|
@@ -18655,6 +18770,10 @@ var init_dispatch_pipeline = __esm({
|
|
|
18655
18770
|
});
|
|
18656
18771
|
this.toolServer?.releaseAgent(task.agentId);
|
|
18657
18772
|
}
|
|
18773
|
+
if (task.resolutionRootAssigned) {
|
|
18774
|
+
this.toolServer?.releaseAgent(task.agentId);
|
|
18775
|
+
task.resolutionRootAssigned = false;
|
|
18776
|
+
}
|
|
18658
18777
|
cancelled++;
|
|
18659
18778
|
}
|
|
18660
18779
|
}
|
|
@@ -18826,6 +18945,10 @@ Worktree merge: CONFLICT
|
|
|
18826
18945
|
if (t.writeMode === "worktree") {
|
|
18827
18946
|
this.toolServer?.releaseAgent(t.agentId);
|
|
18828
18947
|
}
|
|
18948
|
+
if (t.resolutionRootAssigned) {
|
|
18949
|
+
this.toolServer?.releaseAgent(t.agentId);
|
|
18950
|
+
t.resolutionRootAssigned = false;
|
|
18951
|
+
}
|
|
18829
18952
|
}
|
|
18830
18953
|
}
|
|
18831
18954
|
const results = [
|
|
@@ -20143,8 +20266,8 @@ Keep it SHORT \u2014 under 30 lines. This is a working document, not a design do
|
|
|
20143
20266
|
]);
|
|
20144
20267
|
const specContent = response.text || "";
|
|
20145
20268
|
try {
|
|
20146
|
-
const { mkdirSync:
|
|
20147
|
-
|
|
20269
|
+
const { mkdirSync: mkdirSync33, writeFileSync: writeFS } = require("fs");
|
|
20270
|
+
mkdirSync33((0, import_path30.join)(this.projectRoot, ".gossip"), { recursive: true });
|
|
20148
20271
|
writeFS(specPath, specContent, "utf-8");
|
|
20149
20272
|
} catch (err) {
|
|
20150
20273
|
return { text: `Spec generated but failed to save: ${err.message}
|
|
@@ -21088,8 +21211,8 @@ message: Your question?
|
|
|
21088
21211
|
}
|
|
21089
21212
|
/** Start all worker agents (connect to relay) */
|
|
21090
21213
|
async start() {
|
|
21091
|
-
const { existsSync:
|
|
21092
|
-
const { join:
|
|
21214
|
+
const { existsSync: existsSync64, readFileSync: readFileSync61 } = await import("fs");
|
|
21215
|
+
const { join: join73 } = await import("path");
|
|
21093
21216
|
for (const config2 of this.registry.getAll()) {
|
|
21094
21217
|
if (config2.native) continue;
|
|
21095
21218
|
if (this.workers.has(config2.id)) continue;
|
|
@@ -21098,8 +21221,8 @@ message: Your question?
|
|
|
21098
21221
|
apiKey = await this.keyProviderFn(config2.provider) ?? void 0;
|
|
21099
21222
|
}
|
|
21100
21223
|
const llm = createProvider(config2.provider, config2.model, apiKey);
|
|
21101
|
-
const instructionsPath =
|
|
21102
|
-
const instructions =
|
|
21224
|
+
const instructionsPath = join73(this.projectRoot, ".gossip", "agents", config2.id, "instructions.md");
|
|
21225
|
+
const instructions = existsSync64(instructionsPath) ? readFileSync61(instructionsPath, "utf-8") : void 0;
|
|
21103
21226
|
const enableWebSearch = config2.preset === "researcher" || config2.skills.includes("research");
|
|
21104
21227
|
const worker = new WorkerAgent(config2.id, llm, this.relayUrl, ALL_TOOLS, instructions, enableWebSearch, this.relayApiKey);
|
|
21105
21228
|
await worker.start();
|
|
@@ -21292,8 +21415,8 @@ message: Your question?
|
|
|
21292
21415
|
this.registry.register(config2);
|
|
21293
21416
|
}
|
|
21294
21417
|
async syncWorkers(keyProvider) {
|
|
21295
|
-
const { existsSync:
|
|
21296
|
-
const { join:
|
|
21418
|
+
const { existsSync: existsSync64, readFileSync: readFileSync61 } = await import("fs");
|
|
21419
|
+
const { join: join73 } = await import("path");
|
|
21297
21420
|
let added = 0;
|
|
21298
21421
|
for (const ac of this.registry.getAll()) {
|
|
21299
21422
|
if (ac.native) continue;
|
|
@@ -21310,8 +21433,8 @@ message: Your question?
|
|
|
21310
21433
|
this.workers.delete(ac.id);
|
|
21311
21434
|
}
|
|
21312
21435
|
const llm = createProvider(ac.provider, ac.model, key ?? void 0, void 0, ac.base_url);
|
|
21313
|
-
const instructionsPath =
|
|
21314
|
-
const instructions =
|
|
21436
|
+
const instructionsPath = join73(this.projectRoot, ".gossip", "agents", ac.id, "instructions.md");
|
|
21437
|
+
const instructions = existsSync64(instructionsPath) ? readFileSync61(instructionsPath, "utf-8") : void 0;
|
|
21315
21438
|
const enableWebSearch = ac.preset === "researcher" || ac.skills.includes("research");
|
|
21316
21439
|
const worker = new WorkerAgent(ac.id, llm, this.relayUrl, ALL_TOOLS, instructions, enableWebSearch, this.relayApiKey);
|
|
21317
21440
|
await worker.start();
|
|
@@ -24249,6 +24372,86 @@ var init_memory_searcher = __esm({
|
|
|
24249
24372
|
}
|
|
24250
24373
|
});
|
|
24251
24374
|
|
|
24375
|
+
// packages/orchestrator/src/transport-failure-detector.ts
|
|
24376
|
+
function shouldRewriteToTransportFailure(signalName, ctx2) {
|
|
24377
|
+
if (signalName !== "hallucination_caught") return false;
|
|
24378
|
+
if (ctx2.isNativeAgent) return false;
|
|
24379
|
+
if (!ctx2.hadResolutionRoots) return false;
|
|
24380
|
+
if (!ctx2.findingText) return false;
|
|
24381
|
+
if (!TRANSPORT_FAILURE_PATTERN.test(ctx2.findingText)) return false;
|
|
24382
|
+
if (CITE_ANCHOR_PATTERN.test(ctx2.findingText)) return false;
|
|
24383
|
+
return true;
|
|
24384
|
+
}
|
|
24385
|
+
function appendTransportRewrite(projectRoot, audit) {
|
|
24386
|
+
try {
|
|
24387
|
+
const filePath = (0, import_path45.join)(projectRoot, ".gossip", "transport-rewrites.jsonl");
|
|
24388
|
+
(0, import_fs42.mkdirSync)((0, import_path45.dirname)(filePath), { recursive: true });
|
|
24389
|
+
(0, import_fs42.appendFileSync)(filePath, JSON.stringify(audit) + "\n", "utf-8");
|
|
24390
|
+
} catch (err) {
|
|
24391
|
+
process.stderr.write(
|
|
24392
|
+
`[gossipcat] appendTransportRewrite failed: ${err.message}
|
|
24393
|
+
`
|
|
24394
|
+
);
|
|
24395
|
+
}
|
|
24396
|
+
}
|
|
24397
|
+
function lookupRoundResolutionRoots(projectRoot, consensusId) {
|
|
24398
|
+
try {
|
|
24399
|
+
const reportPath = (0, import_path45.join)(
|
|
24400
|
+
projectRoot,
|
|
24401
|
+
".gossip",
|
|
24402
|
+
"consensus-reports",
|
|
24403
|
+
`${consensusId}.json`
|
|
24404
|
+
);
|
|
24405
|
+
if (!(0, import_fs42.existsSync)(reportPath)) return [];
|
|
24406
|
+
const raw = (0, import_fs42.readFileSync)(reportPath, "utf-8");
|
|
24407
|
+
const parsed = JSON.parse(raw);
|
|
24408
|
+
return Array.isArray(parsed.resolutionRoots) ? parsed.resolutionRoots : [];
|
|
24409
|
+
} catch {
|
|
24410
|
+
return [];
|
|
24411
|
+
}
|
|
24412
|
+
}
|
|
24413
|
+
function extractConsensusId(findingId) {
|
|
24414
|
+
if (!findingId) return void 0;
|
|
24415
|
+
const match = findingId.match(/^([0-9a-f]{8}-[0-9a-f]{8})(?::|$)/);
|
|
24416
|
+
return match ? match[1] : void 0;
|
|
24417
|
+
}
|
|
24418
|
+
function maybeRewriteHallucinationToTransportFailure(projectRoot, signal, isNativeAgent) {
|
|
24419
|
+
if (signal.signal !== "hallucination_caught") return signal;
|
|
24420
|
+
const consensusId = extractConsensusId(signal.findingId) ?? signal.consensusId ?? void 0;
|
|
24421
|
+
if (!consensusId) return signal;
|
|
24422
|
+
const roots = lookupRoundResolutionRoots(projectRoot, consensusId);
|
|
24423
|
+
const findingText = `${signal.evidence ?? ""} ${signal.finding ?? ""}`.trim();
|
|
24424
|
+
const ctx2 = {
|
|
24425
|
+
isNativeAgent: isNativeAgent(signal.agentId),
|
|
24426
|
+
hadResolutionRoots: roots.length > 0,
|
|
24427
|
+
findingText
|
|
24428
|
+
};
|
|
24429
|
+
if (!shouldRewriteToTransportFailure(signal.signal, ctx2)) return signal;
|
|
24430
|
+
appendTransportRewrite(projectRoot, {
|
|
24431
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24432
|
+
consensus_id: consensusId,
|
|
24433
|
+
finding_id: signal.findingId,
|
|
24434
|
+
agent_id: signal.agentId,
|
|
24435
|
+
original_signal: "hallucination_caught",
|
|
24436
|
+
rewritten_to: "transport_failure",
|
|
24437
|
+
finding_excerpt: (signal.evidence ?? "").slice(0, 200)
|
|
24438
|
+
});
|
|
24439
|
+
return {
|
|
24440
|
+
...signal,
|
|
24441
|
+
signal: "transport_failure"
|
|
24442
|
+
};
|
|
24443
|
+
}
|
|
24444
|
+
var import_fs42, import_path45, TRANSPORT_FAILURE_PATTERN, CITE_ANCHOR_PATTERN;
|
|
24445
|
+
var init_transport_failure_detector = __esm({
|
|
24446
|
+
"packages/orchestrator/src/transport-failure-detector.ts"() {
|
|
24447
|
+
"use strict";
|
|
24448
|
+
import_fs42 = require("fs");
|
|
24449
|
+
import_path45 = require("path");
|
|
24450
|
+
TRANSPORT_FAILURE_PATTERN = /files? (?:are )?(?:not present|missing)|empty diff|empty workspace|cannot be (?:read|located)|not (?:found|present) (?:on|in)(?: the)? (?:disk|filesystem|worktree)/i;
|
|
24451
|
+
CITE_ANCHOR_PATTERN = /<cite\s+tag=["']file["']\s*>[^<]+<\/cite>/i;
|
|
24452
|
+
}
|
|
24453
|
+
});
|
|
24454
|
+
|
|
24252
24455
|
// packages/orchestrator/src/_sanitize.ts
|
|
24253
24456
|
function sanitizeForLog(raw, maxChars = 200) {
|
|
24254
24457
|
let s = raw.replace(CONTROL_CHAR_RE, "\uFFFD");
|
|
@@ -24521,28 +24724,28 @@ var init_claim_types = __esm({
|
|
|
24521
24724
|
function containWithinProject(projectRoot, input) {
|
|
24522
24725
|
let resolved;
|
|
24523
24726
|
try {
|
|
24524
|
-
resolved = (0,
|
|
24727
|
+
resolved = (0, import_path46.resolve)(projectRoot, input);
|
|
24525
24728
|
} catch {
|
|
24526
24729
|
return null;
|
|
24527
24730
|
}
|
|
24528
24731
|
let finalPath = resolved;
|
|
24529
24732
|
try {
|
|
24530
|
-
if ((0,
|
|
24531
|
-
finalPath = (0,
|
|
24733
|
+
if ((0, import_fs43.existsSync)(resolved)) {
|
|
24734
|
+
finalPath = (0, import_fs43.realpathSync)(resolved);
|
|
24532
24735
|
}
|
|
24533
24736
|
} catch {
|
|
24534
24737
|
return null;
|
|
24535
24738
|
}
|
|
24536
24739
|
let rootReal = projectRoot;
|
|
24537
24740
|
try {
|
|
24538
|
-
if ((0,
|
|
24539
|
-
rootReal = (0,
|
|
24741
|
+
if ((0, import_fs43.existsSync)(projectRoot)) {
|
|
24742
|
+
rootReal = (0, import_fs43.realpathSync)(projectRoot);
|
|
24540
24743
|
}
|
|
24541
24744
|
} catch {
|
|
24542
24745
|
return null;
|
|
24543
24746
|
}
|
|
24544
24747
|
if (finalPath === rootReal) return finalPath;
|
|
24545
|
-
if (finalPath.startsWith(rootReal +
|
|
24748
|
+
if (finalPath.startsWith(rootReal + import_path46.sep)) return finalPath;
|
|
24546
24749
|
return null;
|
|
24547
24750
|
}
|
|
24548
24751
|
function getModality(claim) {
|
|
@@ -24555,7 +24758,7 @@ function runRg(symbol2, scope, projectRoot, remainingMs) {
|
|
|
24555
24758
|
return;
|
|
24556
24759
|
}
|
|
24557
24760
|
const scopePath = containWithinProject(projectRoot, scope);
|
|
24558
|
-
if (scopePath === null || !(0,
|
|
24761
|
+
if (scopePath === null || !(0, import_fs43.existsSync)(scopePath)) {
|
|
24559
24762
|
resolvePromise({ total: 0, error: "missing_path" });
|
|
24560
24763
|
return;
|
|
24561
24764
|
}
|
|
@@ -24656,12 +24859,12 @@ async function verifyCallsiteCount(claim, idx, projectRoot, remainingMs) {
|
|
|
24656
24859
|
async function verifyFileLine(claim, idx, projectRoot) {
|
|
24657
24860
|
const modality = getModality(claim);
|
|
24658
24861
|
const filePath = containWithinProject(projectRoot, claim.path);
|
|
24659
|
-
if (filePath === null || !(0,
|
|
24862
|
+
if (filePath === null || !(0, import_fs43.existsSync)(filePath)) {
|
|
24660
24863
|
return { claim_index: idx, status: "unverifiable_by_grep", reason: "file_not_found" };
|
|
24661
24864
|
}
|
|
24662
24865
|
let st;
|
|
24663
24866
|
try {
|
|
24664
|
-
st = (0,
|
|
24867
|
+
st = (0, import_fs43.statSync)(filePath);
|
|
24665
24868
|
} catch {
|
|
24666
24869
|
return { claim_index: idx, status: "unverifiable_by_grep", reason: "stat_failed" };
|
|
24667
24870
|
}
|
|
@@ -24670,7 +24873,7 @@ async function verifyFileLine(claim, idx, projectRoot) {
|
|
|
24670
24873
|
}
|
|
24671
24874
|
let text;
|
|
24672
24875
|
try {
|
|
24673
|
-
text = (0,
|
|
24876
|
+
text = (0, import_fs43.readFileSync)(filePath, "utf-8");
|
|
24674
24877
|
} catch {
|
|
24675
24878
|
return { claim_index: idx, status: "unverifiable_by_grep", reason: "read_failed" };
|
|
24676
24879
|
}
|
|
@@ -24821,13 +25024,13 @@ async function verifyClaims(block, projectRoot) {
|
|
|
24821
25024
|
}
|
|
24822
25025
|
return verdicts;
|
|
24823
25026
|
}
|
|
24824
|
-
var import_child_process6,
|
|
25027
|
+
var import_child_process6, import_fs43, import_path46, MAX_CLAIMS_PER_BLOCK, PER_BLOCK_DEADLINE_MS;
|
|
24825
25028
|
var init_claim_verifier = __esm({
|
|
24826
25029
|
"packages/orchestrator/src/claim-verifier.ts"() {
|
|
24827
25030
|
"use strict";
|
|
24828
25031
|
import_child_process6 = require("child_process");
|
|
24829
|
-
|
|
24830
|
-
|
|
25032
|
+
import_fs43 = require("fs");
|
|
25033
|
+
import_path46 = require("path");
|
|
24831
25034
|
init_sanitize();
|
|
24832
25035
|
MAX_CLAIMS_PER_BLOCK = 16;
|
|
24833
25036
|
PER_BLOCK_DEADLINE_MS = 500;
|
|
@@ -25182,42 +25385,81 @@ function runUnderLock(projectRoot, opts) {
|
|
|
25182
25385
|
if (inferred) symbolsToCheck.add(inferred);
|
|
25183
25386
|
}
|
|
25184
25387
|
if (symbolsToCheck.size === 0) continue;
|
|
25185
|
-
let
|
|
25388
|
+
let sawAbsentEverywhere = false;
|
|
25389
|
+
let sawPresentElsewhere = false;
|
|
25390
|
+
let sawPresentAtAnchor = false;
|
|
25391
|
+
let sawCiteWithoutLine = false;
|
|
25392
|
+
let readFailure = false;
|
|
25186
25393
|
for (const fc of safeFileCites) {
|
|
25187
25394
|
let body;
|
|
25188
25395
|
try {
|
|
25189
25396
|
body = fs4.readFileSync(fc.absPath, "utf8");
|
|
25190
25397
|
} catch {
|
|
25191
|
-
|
|
25398
|
+
readFailure = true;
|
|
25192
25399
|
break;
|
|
25193
25400
|
}
|
|
25194
25401
|
const stripped = stripJsTsComments(body);
|
|
25195
25402
|
for (const sym of symbolsToCheck) {
|
|
25196
|
-
|
|
25197
|
-
|
|
25198
|
-
|
|
25403
|
+
const presence = classifyPresence(
|
|
25404
|
+
body,
|
|
25405
|
+
stripped,
|
|
25406
|
+
sym,
|
|
25407
|
+
fc.line,
|
|
25408
|
+
LINE_ANCHORED_WINDOW
|
|
25409
|
+
);
|
|
25410
|
+
if (presence.kind === "absent_everywhere") {
|
|
25411
|
+
sawAbsentEverywhere = true;
|
|
25412
|
+
} else if (presence.kind === "present_at_anchor") {
|
|
25413
|
+
sawPresentAtAnchor = true;
|
|
25414
|
+
} else {
|
|
25415
|
+
sawPresentElsewhere = true;
|
|
25416
|
+
if (fc.line === void 0) sawCiteWithoutLine = true;
|
|
25199
25417
|
}
|
|
25200
25418
|
}
|
|
25201
|
-
if (!allClear) break;
|
|
25202
25419
|
}
|
|
25203
|
-
if (
|
|
25420
|
+
if (readFailure) continue;
|
|
25421
|
+
const allAbsentEverywhere = sawAbsentEverywhere && !sawPresentElsewhere && !sawPresentAtAnchor;
|
|
25422
|
+
const allPresentElsewhere = sawPresentElsewhere && !sawAbsentEverywhere && !sawPresentAtAnchor && !sawCiteWithoutLine;
|
|
25423
|
+
if (!allAbsentEverywhere && !(opts.lineAnchored && allPresentElsewhere)) {
|
|
25424
|
+
continue;
|
|
25425
|
+
}
|
|
25204
25426
|
const findingId = String(entry.taskId ?? entry.findingId ?? "");
|
|
25205
25427
|
const beforeQuote = Array.from(symbolsToCheck).slice(0, 3).join(", ");
|
|
25206
|
-
const
|
|
25428
|
+
const useStaleAnchor = !allAbsentEverywhere && allPresentElsewhere;
|
|
25429
|
+
const resolvedBy = useStaleAnchor ? "stale_anchor" : headSha ? `commit:${headSha}` : "manual";
|
|
25207
25430
|
try {
|
|
25208
25431
|
entry.status = "resolved";
|
|
25209
25432
|
entry.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
25210
25433
|
entry.resolvedBy = resolvedBy;
|
|
25211
25434
|
row.raw = JSON.stringify(entry);
|
|
25212
|
-
|
|
25213
|
-
|
|
25214
|
-
|
|
25215
|
-
|
|
25216
|
-
|
|
25217
|
-
|
|
25218
|
-
|
|
25219
|
-
|
|
25220
|
-
|
|
25435
|
+
if (useStaleAnchor) {
|
|
25436
|
+
const firstCite = safeFileCites[0];
|
|
25437
|
+
if (firstCite.line === void 0) {
|
|
25438
|
+
throw new Error("finding-resolver invariant: stale_anchor path reached with undefined cited line");
|
|
25439
|
+
}
|
|
25440
|
+
const citedLine = firstCite.line;
|
|
25441
|
+
appendChainedEntry(projectRoot, {
|
|
25442
|
+
ts: entry.resolvedAt,
|
|
25443
|
+
finding_id: findingId,
|
|
25444
|
+
action: "resolve",
|
|
25445
|
+
resolved_by: "stale_anchor",
|
|
25446
|
+
before_quote: beforeQuote,
|
|
25447
|
+
after_check: "present_elsewhere_only",
|
|
25448
|
+
operator: "auto",
|
|
25449
|
+
cited_line: citedLine,
|
|
25450
|
+
window: LINE_ANCHORED_WINDOW
|
|
25451
|
+
});
|
|
25452
|
+
} else {
|
|
25453
|
+
appendChainedEntry(projectRoot, {
|
|
25454
|
+
ts: entry.resolvedAt,
|
|
25455
|
+
finding_id: findingId,
|
|
25456
|
+
action: "resolve",
|
|
25457
|
+
resolved_by: resolvedBy,
|
|
25458
|
+
before_quote: beforeQuote,
|
|
25459
|
+
after_check: "absent",
|
|
25460
|
+
operator: "auto"
|
|
25461
|
+
});
|
|
25462
|
+
}
|
|
25221
25463
|
resolvedCount++;
|
|
25222
25464
|
resolvedFindingIds.push(findingId);
|
|
25223
25465
|
} catch (err) {
|
|
@@ -25374,6 +25616,20 @@ function containsToken(haystack, token) {
|
|
|
25374
25616
|
const re = new RegExp(`(^|[^A-Za-z0-9_$.])${escaped}(?![A-Za-z0-9_$])`);
|
|
25375
25617
|
return re.test(haystack);
|
|
25376
25618
|
}
|
|
25619
|
+
function classifyPresence(body, stripped, symbol2, citedLine, window) {
|
|
25620
|
+
const inFile = containsToken(stripped, symbol2);
|
|
25621
|
+
if (!inFile) return { kind: "absent_everywhere" };
|
|
25622
|
+
if (citedLine === void 0) {
|
|
25623
|
+
return { kind: "present_elsewhere" };
|
|
25624
|
+
}
|
|
25625
|
+
const lines = body.split("\n");
|
|
25626
|
+
if (lines.length === 0) return { kind: "present_elsewhere" };
|
|
25627
|
+
const lo = Math.max(0, citedLine - 1 - window);
|
|
25628
|
+
const hi = Math.min(lines.length - 1, citedLine - 1 + window);
|
|
25629
|
+
const windowText = lines.slice(lo, hi + 1).join("\n");
|
|
25630
|
+
const inWindow = containsToken(windowText, symbol2);
|
|
25631
|
+
return inWindow ? { kind: "present_at_anchor" } : { kind: "present_elsewhere" };
|
|
25632
|
+
}
|
|
25377
25633
|
function loadConsensusReport(projectRoot, consensusId) {
|
|
25378
25634
|
if (!/^[A-Za-z0-9_-]+$/.test(consensusId)) return null;
|
|
25379
25635
|
const reportPath = path5.join(projectRoot, ".gossip", "consensus-reports", `${consensusId}.json`);
|
|
@@ -25500,7 +25756,7 @@ function computeTouchedSet(projectRoot, opts, gitRoot) {
|
|
|
25500
25756
|
}
|
|
25501
25757
|
return set2;
|
|
25502
25758
|
}
|
|
25503
|
-
var fs4, os, path5, import_child_process7, FINDINGS_FILENAME, WATERMARK_FILENAME, COLD_START_SINCE, PATH_REJECT_REASONS, FILE_CITE_RE, FN_CITE_RE, PLAIN_FILE_CITE_RE, INFER_SKIP_LIST, SHA_RE, FINDING_RESOLVER_INTERNALS;
|
|
25759
|
+
var fs4, os, path5, import_child_process7, FINDINGS_FILENAME, WATERMARK_FILENAME, COLD_START_SINCE, LINE_ANCHORED_WINDOW, PATH_REJECT_REASONS, FILE_CITE_RE, FN_CITE_RE, PLAIN_FILE_CITE_RE, INFER_SKIP_LIST, SHA_RE, FINDING_RESOLVER_INTERNALS;
|
|
25504
25760
|
var init_finding_resolver = __esm({
|
|
25505
25761
|
"packages/orchestrator/src/finding-resolver.ts"() {
|
|
25506
25762
|
"use strict";
|
|
@@ -25513,6 +25769,7 @@ var init_finding_resolver = __esm({
|
|
|
25513
25769
|
FINDINGS_FILENAME = "implementation-findings.jsonl";
|
|
25514
25770
|
WATERMARK_FILENAME = "last-resolve-scan.sha";
|
|
25515
25771
|
COLD_START_SINCE = "90.days";
|
|
25772
|
+
LINE_ANCHORED_WINDOW = 5;
|
|
25516
25773
|
PATH_REJECT_REASONS = {
|
|
25517
25774
|
TRAVERSAL: 'path contains ".." traversal',
|
|
25518
25775
|
NUL: "path contains NUL byte",
|
|
@@ -25595,11 +25852,13 @@ __export(src_exports3, {
|
|
|
25595
25852
|
MemoryCompactor: () => MemoryCompactor,
|
|
25596
25853
|
MemorySearcher: () => MemorySearcher,
|
|
25597
25854
|
MemoryWriter: () => MemoryWriter,
|
|
25855
|
+
OPERATIONAL_SIGNAL_NAMES: () => OPERATIONAL_SIGNAL_NAMES,
|
|
25598
25856
|
OllamaProvider: () => OllamaProvider,
|
|
25599
25857
|
OpenAIProvider: () => OpenAIProvider,
|
|
25600
25858
|
OverlapDetector: () => OverlapDetector,
|
|
25601
25859
|
PARSE_FINDINGS_LIMITS: () => PARSE_FINDINGS_LIMITS,
|
|
25602
25860
|
PENDING_PLAN_CHOICES: () => PENDING_PLAN_CHOICES,
|
|
25861
|
+
PERFORMANCE_SIGNAL_NAMES: () => PERFORMANCE_SIGNAL_NAMES,
|
|
25603
25862
|
PER_BLOCK_DEADLINE_MS: () => PER_BLOCK_DEADLINE_MS,
|
|
25604
25863
|
PLAN_CHOICES: () => PLAN_CHOICES,
|
|
25605
25864
|
PerformanceReader: () => PerformanceReader,
|
|
@@ -25619,9 +25878,11 @@ __export(src_exports3, {
|
|
|
25619
25878
|
TIMEOUT_DAYS: () => TIMEOUT_DAYS,
|
|
25620
25879
|
TIMEOUT_MS: () => TIMEOUT_MS,
|
|
25621
25880
|
TOOL_SCHEMAS: () => TOOL_SCHEMAS2,
|
|
25881
|
+
TRANSPORT_FAILURE_PATTERN: () => TRANSPORT_FAILURE_PATTERN,
|
|
25622
25882
|
TaskDispatcher: () => TaskDispatcher,
|
|
25623
25883
|
TaskGraph: () => TaskGraph,
|
|
25624
25884
|
TaskGraphSync: () => TaskGraphSync,
|
|
25885
|
+
TaskStreamEventType: () => TaskStreamEventType,
|
|
25625
25886
|
TeamManager: () => TeamManager,
|
|
25626
25887
|
ToolExecutor: () => ToolExecutor,
|
|
25627
25888
|
ToolRouter: () => ToolRouter,
|
|
@@ -25631,6 +25892,7 @@ __export(src_exports3, {
|
|
|
25631
25892
|
ZERO_HASH: () => ZERO_HASH,
|
|
25632
25893
|
Z_CRITICAL: () => Z_CRITICAL,
|
|
25633
25894
|
appendChainedEntry: () => appendChainedEntry,
|
|
25895
|
+
appendTransportRewrite: () => appendTransportRewrite,
|
|
25634
25896
|
applyStatusTags: () => applyStatusTags,
|
|
25635
25897
|
assemblePrompt: () => assemblePrompt,
|
|
25636
25898
|
assembleUtilityPrompt: () => assembleUtilityPrompt,
|
|
@@ -25638,6 +25900,7 @@ __export(src_exports3, {
|
|
|
25638
25900
|
buildToolSystemPrompt: () => buildToolSystemPrompt,
|
|
25639
25901
|
buildUtilityAgentPrompt: () => buildUtilityAgentPrompt,
|
|
25640
25902
|
bumpRoundCounter: () => bump,
|
|
25903
|
+
classifyPresence: () => classifyPresence,
|
|
25641
25904
|
classifySignal: () => classifySignal,
|
|
25642
25905
|
computeCooldown: () => computeCooldown,
|
|
25643
25906
|
computeDedupeKey: () => computeDedupeKey,
|
|
@@ -25657,6 +25920,7 @@ __export(src_exports3, {
|
|
|
25657
25920
|
emitScoringAdjustmentSignals: () => emitScoringAdjustmentSignals,
|
|
25658
25921
|
ensureRulesFile: () => ensureRulesFile,
|
|
25659
25922
|
extractCategories: () => extractCategories,
|
|
25923
|
+
extractConsensusId: () => extractConsensusId,
|
|
25660
25924
|
extractSpecReferences: () => extractSpecReferences,
|
|
25661
25925
|
findBundledHook: () => findBundledHook,
|
|
25662
25926
|
findBundledRules: () => findBundledRules,
|
|
@@ -25672,6 +25936,8 @@ __export(src_exports3, {
|
|
|
25672
25936
|
loadMemoryConfig: () => loadMemoryConfig,
|
|
25673
25937
|
loadSkills: () => loadSkills,
|
|
25674
25938
|
logUncategorizedFinding: () => logUncategorizedFinding,
|
|
25939
|
+
lookupRoundResolutionRoots: () => lookupRoundResolutionRoots,
|
|
25940
|
+
maybeRewriteHallucinationToTransportFailure: () => maybeRewriteHallucinationToTransportFailure,
|
|
25675
25941
|
normalizeSkillName: () => normalizeSkillName,
|
|
25676
25942
|
oneSidedZTest: () => oneSidedZTest,
|
|
25677
25943
|
parseAgentFindingsStrict: () => parseAgentFindingsStrict,
|
|
@@ -25691,6 +25957,7 @@ __export(src_exports3, {
|
|
|
25691
25957
|
sanitizeForLog: () => sanitizeForLog,
|
|
25692
25958
|
seedMemoryHygiene: () => seedMemoryHygiene,
|
|
25693
25959
|
selectCrossReviewers: () => selectCrossReviewers,
|
|
25960
|
+
shouldRewriteToTransportFailure: () => shouldRewriteToTransportFailure,
|
|
25694
25961
|
shouldSkipConsensus: () => shouldSkipConsensus,
|
|
25695
25962
|
stableStringify: () => stableStringify,
|
|
25696
25963
|
stripJsTsComments: () => stripJsTsComments,
|
|
@@ -25761,6 +26028,7 @@ var init_src4 = __esm({
|
|
|
25761
26028
|
init_check_effectiveness();
|
|
25762
26029
|
init_completion_signals();
|
|
25763
26030
|
init_signal_helpers();
|
|
26031
|
+
init_transport_failure_detector();
|
|
25764
26032
|
init_completion_signals_allowlist();
|
|
25765
26033
|
init_pipeline_drift_detector();
|
|
25766
26034
|
init_memory_config();
|
|
@@ -25771,6 +26039,7 @@ var init_src4 = __esm({
|
|
|
25771
26039
|
init_file_lock();
|
|
25772
26040
|
init_audit_log_chain();
|
|
25773
26041
|
init_finding_resolver();
|
|
26042
|
+
init_task_stream();
|
|
25774
26043
|
}
|
|
25775
26044
|
});
|
|
25776
26045
|
|
|
@@ -26535,7 +26804,7 @@ var init_utility_agents = __esm({
|
|
|
26535
26804
|
// packages/relay/src/dashboard/api-overview.ts
|
|
26536
26805
|
function readSkillStatus(path6) {
|
|
26537
26806
|
try {
|
|
26538
|
-
const content = (0,
|
|
26807
|
+
const content = (0, import_fs44.readFileSync)(path6, "utf-8");
|
|
26539
26808
|
const m = content.match(/^---\n([\s\S]*?)\n---/);
|
|
26540
26809
|
if (!m) return null;
|
|
26541
26810
|
const block = m[1];
|
|
@@ -26549,24 +26818,24 @@ function readSkillStatus(path6) {
|
|
|
26549
26818
|
}
|
|
26550
26819
|
}
|
|
26551
26820
|
function computeSkillVerdictSummary(projectRoot) {
|
|
26552
|
-
const agentsDir = (0,
|
|
26553
|
-
if (!(0,
|
|
26821
|
+
const agentsDir = (0, import_path47.join)(projectRoot, ".gossip", "agents");
|
|
26822
|
+
if (!(0, import_fs44.existsSync)(agentsDir)) return void 0;
|
|
26554
26823
|
const summary = { pending: 0, passed: 0, failed: 0, silent_skill: 0, insufficient_evidence: 0, inconclusive: 0 };
|
|
26555
26824
|
let seen = false;
|
|
26556
26825
|
try {
|
|
26557
|
-
const agentIds = (0,
|
|
26826
|
+
const agentIds = (0, import_fs44.readdirSync)(agentsDir);
|
|
26558
26827
|
for (const agentId of agentIds) {
|
|
26559
|
-
const skillsDir = (0,
|
|
26560
|
-
if (!(0,
|
|
26828
|
+
const skillsDir = (0, import_path47.join)(agentsDir, agentId, "skills");
|
|
26829
|
+
if (!(0, import_fs44.existsSync)(skillsDir)) continue;
|
|
26561
26830
|
let entries;
|
|
26562
26831
|
try {
|
|
26563
|
-
entries = (0,
|
|
26832
|
+
entries = (0, import_fs44.readdirSync)(skillsDir);
|
|
26564
26833
|
} catch {
|
|
26565
26834
|
continue;
|
|
26566
26835
|
}
|
|
26567
26836
|
for (const entry of entries) {
|
|
26568
26837
|
if (!entry.endsWith(".md")) continue;
|
|
26569
|
-
const status = readSkillStatus((0,
|
|
26838
|
+
const status = readSkillStatus((0, import_path47.join)(skillsDir, entry));
|
|
26570
26839
|
if (!status) continue;
|
|
26571
26840
|
seen = true;
|
|
26572
26841
|
if (status === "pending") summary.pending++;
|
|
@@ -26583,13 +26852,13 @@ function computeSkillVerdictSummary(projectRoot) {
|
|
|
26583
26852
|
return seen ? summary : summary;
|
|
26584
26853
|
}
|
|
26585
26854
|
function computeDroppedFindingTypeCounts(projectRoot) {
|
|
26586
|
-
const dir = (0,
|
|
26587
|
-
if (!(0,
|
|
26855
|
+
const dir = (0, import_path47.join)(projectRoot, ".gossip", "consensus-reports");
|
|
26856
|
+
if (!(0, import_fs44.existsSync)(dir)) return void 0;
|
|
26588
26857
|
try {
|
|
26589
|
-
const files = (0,
|
|
26590
|
-
const full = (0,
|
|
26858
|
+
const files = (0, import_fs44.readdirSync)(dir).filter((f) => f.endsWith(".json")).map((f) => {
|
|
26859
|
+
const full = (0, import_path47.join)(dir, f);
|
|
26591
26860
|
try {
|
|
26592
|
-
return { full, mtime: (0,
|
|
26861
|
+
return { full, mtime: (0, import_fs44.statSync)(full).mtimeMs };
|
|
26593
26862
|
} catch {
|
|
26594
26863
|
return null;
|
|
26595
26864
|
}
|
|
@@ -26598,7 +26867,7 @@ function computeDroppedFindingTypeCounts(projectRoot) {
|
|
|
26598
26867
|
let seen = false;
|
|
26599
26868
|
for (const { full } of files) {
|
|
26600
26869
|
try {
|
|
26601
|
-
const report = JSON.parse((0,
|
|
26870
|
+
const report = JSON.parse((0, import_fs44.readFileSync)(full, "utf-8"));
|
|
26602
26871
|
const dropped = report?.droppedFindingsByType;
|
|
26603
26872
|
if (!dropped || typeof dropped !== "object") continue;
|
|
26604
26873
|
for (const [type, count] of Object.entries(dropped)) {
|
|
@@ -26627,12 +26896,12 @@ async function overviewHandler(projectRoot, ctx2) {
|
|
|
26627
26896
|
const hourlyActivity = new Array(12).fill(0);
|
|
26628
26897
|
const now = Date.now();
|
|
26629
26898
|
const hourMs = 60 * 60 * 1e3;
|
|
26630
|
-
const graphPath = (0,
|
|
26631
|
-
if ((0,
|
|
26899
|
+
const graphPath = (0, import_path47.join)(projectRoot, ".gossip", "task-graph.jsonl");
|
|
26900
|
+
if ((0, import_fs44.existsSync)(graphPath)) {
|
|
26632
26901
|
try {
|
|
26633
26902
|
const created = /* @__PURE__ */ new Map();
|
|
26634
26903
|
const finished = /* @__PURE__ */ new Set();
|
|
26635
|
-
const lines = (0,
|
|
26904
|
+
const lines = (0, import_fs44.readFileSync)(graphPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
26636
26905
|
for (const line of lines) {
|
|
26637
26906
|
try {
|
|
26638
26907
|
const ev = JSON.parse(line);
|
|
@@ -26685,10 +26954,10 @@ async function overviewHandler(projectRoot, ctx2) {
|
|
|
26685
26954
|
let lastConsensusTimestamp = "";
|
|
26686
26955
|
let actionableFindings = 0;
|
|
26687
26956
|
const runBuckets = /* @__PURE__ */ new Map();
|
|
26688
|
-
const perfPath = (0,
|
|
26689
|
-
if ((0,
|
|
26957
|
+
const perfPath = (0, import_path47.join)(projectRoot, ".gossip", "agent-performance.jsonl");
|
|
26958
|
+
if ((0, import_fs44.existsSync)(perfPath)) {
|
|
26690
26959
|
try {
|
|
26691
|
-
const lines = (0,
|
|
26960
|
+
const lines = (0, import_fs44.readFileSync)(perfPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
26692
26961
|
for (const line of lines) {
|
|
26693
26962
|
try {
|
|
26694
26963
|
const entry = JSON.parse(line);
|
|
@@ -26738,12 +27007,12 @@ async function overviewHandler(projectRoot, ctx2) {
|
|
|
26738
27007
|
const droppedFindingTypeCounts = computeDroppedFindingTypeCounts(projectRoot);
|
|
26739
27008
|
return { agentsOnline, relayCount, relayConnected, nativeCount, consensusRuns, totalFindings, confirmedFindings, totalSignals, tasksCompleted, tasksFailed, avgDurationMs, lastConsensusTimestamp, actionableFindings, hourlyActivity, skillVerdictSummary, droppedFindingTypeCounts };
|
|
26740
27009
|
}
|
|
26741
|
-
var
|
|
27010
|
+
var import_fs44, import_path47;
|
|
26742
27011
|
var init_api_overview = __esm({
|
|
26743
27012
|
"packages/relay/src/dashboard/api-overview.ts"() {
|
|
26744
27013
|
"use strict";
|
|
26745
|
-
|
|
26746
|
-
|
|
27014
|
+
import_fs44 = require("fs");
|
|
27015
|
+
import_path47 = require("path");
|
|
26747
27016
|
init_utility_agents();
|
|
26748
27017
|
}
|
|
26749
27018
|
});
|
|
@@ -26769,16 +27038,16 @@ function cacheSet(key, value) {
|
|
|
26769
27038
|
async function fleetTrendHandler(projectRoot, query) {
|
|
26770
27039
|
const rawDays = parseInt(query?.get("days") ?? "", 10);
|
|
26771
27040
|
const days = isNaN(rawDays) || rawDays < 1 ? DEFAULT_DAYS : Math.min(rawDays, MAX_DAYS);
|
|
26772
|
-
const perfPath = (0,
|
|
26773
|
-
if (!(0,
|
|
26774
|
-
const mtime = (0,
|
|
27041
|
+
const perfPath = (0, import_path48.join)(projectRoot, ".gossip", "agent-performance.jsonl");
|
|
27042
|
+
if (!(0, import_fs45.existsSync)(perfPath)) return { days, points: [] };
|
|
27043
|
+
const mtime = (0, import_fs45.statSync)(perfPath).mtimeMs;
|
|
26775
27044
|
const cacheKey = `${projectRoot}::${days}`;
|
|
26776
27045
|
const cached3 = cacheGet(cacheKey);
|
|
26777
27046
|
if (cached3 && cached3.mtime === mtime) return cached3.payload;
|
|
26778
27047
|
const cutoff = Date.now() - days * DAY_MS2;
|
|
26779
27048
|
const buckets = /* @__PURE__ */ new Map();
|
|
26780
27049
|
try {
|
|
26781
|
-
const lines = (0,
|
|
27050
|
+
const lines = (0, import_fs45.readFileSync)(perfPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
26782
27051
|
for (const line of lines) {
|
|
26783
27052
|
try {
|
|
26784
27053
|
const rec = JSON.parse(line);
|
|
@@ -26815,18 +27084,18 @@ async function fleetTrendHandler(projectRoot, query) {
|
|
|
26815
27084
|
const payload = { days, points };
|
|
26816
27085
|
let postMtime = null;
|
|
26817
27086
|
try {
|
|
26818
|
-
postMtime = (0,
|
|
27087
|
+
postMtime = (0, import_fs45.statSync)(perfPath).mtimeMs;
|
|
26819
27088
|
} catch {
|
|
26820
27089
|
}
|
|
26821
27090
|
if (postMtime === mtime) cacheSet(cacheKey, { mtime, payload });
|
|
26822
27091
|
return payload;
|
|
26823
27092
|
}
|
|
26824
|
-
var
|
|
27093
|
+
var import_fs45, import_path48, DEFAULT_DAYS, MAX_DAYS, DAY_MS2, CACHE_MAX, cache;
|
|
26825
27094
|
var init_api_fleet_trend = __esm({
|
|
26826
27095
|
"packages/relay/src/dashboard/api-fleet-trend.ts"() {
|
|
26827
27096
|
"use strict";
|
|
26828
|
-
|
|
26829
|
-
|
|
27097
|
+
import_fs45 = require("fs");
|
|
27098
|
+
import_path48 = require("path");
|
|
26830
27099
|
DEFAULT_DAYS = 30;
|
|
26831
27100
|
MAX_DAYS = 90;
|
|
26832
27101
|
DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
@@ -26838,9 +27107,9 @@ var init_api_fleet_trend = __esm({
|
|
|
26838
27107
|
// packages/relay/src/dashboard/api-agents.ts
|
|
26839
27108
|
function readSkillFrontmatter(projectRoot, agentId, skillName) {
|
|
26840
27109
|
try {
|
|
26841
|
-
const path6 = (0,
|
|
26842
|
-
if (!(0,
|
|
26843
|
-
const raw = (0,
|
|
27110
|
+
const path6 = (0, import_path49.join)(projectRoot, ".gossip", "agents", agentId, "skills", `${skillName}.md`);
|
|
27111
|
+
if (!(0, import_fs46.existsSync)(path6)) return null;
|
|
27112
|
+
const raw = (0, import_fs46.readFileSync)(path6, "utf-8");
|
|
26844
27113
|
if (!raw.startsWith("---")) return null;
|
|
26845
27114
|
const end = raw.indexOf("\n---", 3);
|
|
26846
27115
|
if (end === -1) return null;
|
|
@@ -26876,9 +27145,9 @@ function normalizeCategory(s) {
|
|
|
26876
27145
|
}
|
|
26877
27146
|
function readForcedDevelops(projectRoot, agentId, category) {
|
|
26878
27147
|
try {
|
|
26879
|
-
const path6 = (0,
|
|
26880
|
-
if (!(0,
|
|
26881
|
-
const raw = (0,
|
|
27148
|
+
const path6 = (0, import_path49.join)(projectRoot, ".gossip", "forced-skill-develops.jsonl");
|
|
27149
|
+
if (!(0, import_fs46.existsSync)(path6)) return [];
|
|
27150
|
+
const raw = (0, import_fs46.readFileSync)(path6, "utf-8");
|
|
26882
27151
|
const target = normalizeCategory(category);
|
|
26883
27152
|
const out = [];
|
|
26884
27153
|
for (const line of raw.split("\n")) {
|
|
@@ -26901,17 +27170,18 @@ function readForcedDevelops(projectRoot, agentId, category) {
|
|
|
26901
27170
|
}
|
|
26902
27171
|
}
|
|
26903
27172
|
function readTaskGraphByAgent(projectRoot) {
|
|
26904
|
-
const taskGraphPath = (0,
|
|
27173
|
+
const taskGraphPath = (0, import_path49.join)(projectRoot, ".gossip", "task-graph.jsonl");
|
|
26905
27174
|
const result = /* @__PURE__ */ new Map();
|
|
26906
|
-
if (!(0,
|
|
27175
|
+
if (!(0, import_fs46.existsSync)(taskGraphPath)) return result;
|
|
26907
27176
|
let lines;
|
|
26908
27177
|
try {
|
|
26909
|
-
lines = (0,
|
|
27178
|
+
lines = (0, import_fs46.readFileSync)(taskGraphPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
26910
27179
|
} catch {
|
|
26911
27180
|
return result;
|
|
26912
27181
|
}
|
|
26913
27182
|
const created = /* @__PURE__ */ new Map();
|
|
26914
27183
|
const completed = /* @__PURE__ */ new Map();
|
|
27184
|
+
const failed = /* @__PURE__ */ new Set();
|
|
26915
27185
|
for (const line of lines) {
|
|
26916
27186
|
let entry;
|
|
26917
27187
|
try {
|
|
@@ -26927,18 +27197,23 @@ function readTaskGraphByAgent(projectRoot) {
|
|
|
26927
27197
|
outputTokens: entry.outputTokens ?? 0,
|
|
26928
27198
|
timestamp: entry.timestamp ?? ""
|
|
26929
27199
|
});
|
|
27200
|
+
} else if (entry.type === "task.failed" && entry.taskId) {
|
|
27201
|
+
failed.add(entry.taskId);
|
|
26930
27202
|
}
|
|
26931
27203
|
}
|
|
26932
27204
|
for (const [taskId, createdData] of created) {
|
|
26933
27205
|
const { agentId, task, timestamp } = createdData;
|
|
26934
27206
|
if (isUtilityAgent(agentId)) continue;
|
|
26935
27207
|
if (!result.has(agentId)) {
|
|
26936
|
-
result.set(agentId, { totalTokens: 0, lastTask: null });
|
|
27208
|
+
result.set(agentId, { totalTokens: 0, lastTask: null, tasksCompleted: 0, tasksFailed: 0 });
|
|
26937
27209
|
}
|
|
26938
27210
|
const agentData = result.get(agentId);
|
|
26939
27211
|
const comp = completed.get(taskId);
|
|
26940
27212
|
if (comp) {
|
|
26941
27213
|
agentData.totalTokens += comp.inputTokens + comp.outputTokens;
|
|
27214
|
+
agentData.tasksCompleted++;
|
|
27215
|
+
} else if (failed.has(taskId)) {
|
|
27216
|
+
agentData.tasksFailed++;
|
|
26942
27217
|
}
|
|
26943
27218
|
if (!agentData.lastTask || timestamp > agentData.lastTask.timestamp) {
|
|
26944
27219
|
agentData.lastTask = { task, timestamp };
|
|
@@ -26963,7 +27238,7 @@ async function agentsHandler(projectRoot, configs, onlineAgents = []) {
|
|
|
26963
27238
|
const allIds = configs.map((c) => c.id);
|
|
26964
27239
|
return configs.map((config2) => {
|
|
26965
27240
|
const score = scores.get(config2.id) ?? { ...DEFAULT_SCORE, agentId: config2.id };
|
|
26966
|
-
const agentTask = taskDataByAgent.get(config2.id) ?? { totalTokens: 0, lastTask: null };
|
|
27241
|
+
const agentTask = taskDataByAgent.get(config2.id) ?? { totalTokens: 0, lastTask: null, tasksCompleted: 0, tasksFailed: 0 };
|
|
26967
27242
|
const categories = Object.keys({ ...score.categoryCorrect, ...score.categoryHallucinated });
|
|
26968
27243
|
const benchResult = reader.isBenched(config2.id, categories, allIds);
|
|
26969
27244
|
const benchState = benchResult.benched ? "benched" : benchResult.safeguardBlocked ? "kept-for-coverage" : "none";
|
|
@@ -26996,6 +27271,9 @@ async function agentsHandler(projectRoot, configs, onlineAgents = []) {
|
|
|
26996
27271
|
}
|
|
26997
27272
|
} catch {
|
|
26998
27273
|
}
|
|
27274
|
+
const { tasksCompleted, tasksFailed } = agentTask;
|
|
27275
|
+
const completionDenominator = tasksCompleted + tasksFailed;
|
|
27276
|
+
const taskCompletionRate = completionDenominator > 0 ? tasksCompleted / completionDenominator : null;
|
|
26999
27277
|
return {
|
|
27000
27278
|
id: config2.id,
|
|
27001
27279
|
provider: config2.provider,
|
|
@@ -27011,6 +27289,7 @@ async function agentsHandler(projectRoot, configs, onlineAgents = []) {
|
|
|
27011
27289
|
accuracy: score.accuracy,
|
|
27012
27290
|
uniqueness: score.uniqueness,
|
|
27013
27291
|
reliability: score.reliability,
|
|
27292
|
+
taskCompletionRate,
|
|
27014
27293
|
impactScore: score.impactScore ?? 0.5,
|
|
27015
27294
|
dispatchWeight: reader.getDispatchWeight(config2.id),
|
|
27016
27295
|
signals: score.totalSignals,
|
|
@@ -27020,6 +27299,7 @@ async function agentsHandler(projectRoot, configs, onlineAgents = []) {
|
|
|
27020
27299
|
uniqueFindings: score.uniqueFindings ?? 0,
|
|
27021
27300
|
unverifiedsEmitted: score.unverifiedsEmitted ?? 0,
|
|
27022
27301
|
unverifiedsReceived: score.unverifiedsReceived ?? 0,
|
|
27302
|
+
transportFailureCount: score.transport_failure_count ?? 0,
|
|
27023
27303
|
consecutiveFailures: score.consecutiveFailures ?? 0,
|
|
27024
27304
|
circuitOpen: score.circuitOpen ?? false,
|
|
27025
27305
|
bench,
|
|
@@ -27041,14 +27321,14 @@ async function agentsHandler(projectRoot, configs, onlineAgents = []) {
|
|
|
27041
27321
|
};
|
|
27042
27322
|
});
|
|
27043
27323
|
}
|
|
27044
|
-
var
|
|
27324
|
+
var import_fs46, import_path49, DEFAULT_SCORE;
|
|
27045
27325
|
var init_api_agents = __esm({
|
|
27046
27326
|
"packages/relay/src/dashboard/api-agents.ts"() {
|
|
27047
27327
|
"use strict";
|
|
27048
27328
|
init_performance_reader();
|
|
27049
27329
|
init_skill_index();
|
|
27050
|
-
|
|
27051
|
-
|
|
27330
|
+
import_fs46 = require("fs");
|
|
27331
|
+
import_path49 = require("path");
|
|
27052
27332
|
init_utility_agents();
|
|
27053
27333
|
DEFAULT_SCORE = {
|
|
27054
27334
|
agentId: "",
|
|
@@ -27057,6 +27337,7 @@ var init_api_agents = __esm({
|
|
|
27057
27337
|
reliability: 0.5,
|
|
27058
27338
|
impactScore: 0.5,
|
|
27059
27339
|
totalSignals: 0,
|
|
27340
|
+
scoringSignals: 0,
|
|
27060
27341
|
agreements: 0,
|
|
27061
27342
|
disagreements: 0,
|
|
27062
27343
|
uniqueFindings: 0,
|
|
@@ -27069,14 +27350,15 @@ var init_api_agents = __esm({
|
|
|
27069
27350
|
categoryStrengths: {},
|
|
27070
27351
|
categoryCorrect: {},
|
|
27071
27352
|
categoryHallucinated: {},
|
|
27072
|
-
categoryAccuracy: {}
|
|
27353
|
+
categoryAccuracy: {},
|
|
27354
|
+
transport_failure_count: 0
|
|
27073
27355
|
};
|
|
27074
27356
|
}
|
|
27075
27357
|
});
|
|
27076
27358
|
|
|
27077
27359
|
// packages/relay/src/dashboard/api-skills.ts
|
|
27078
27360
|
function isCorrupt(projectRoot, index) {
|
|
27079
|
-
return (0,
|
|
27361
|
+
return (0, import_fs47.existsSync)((0, import_path50.join)(projectRoot, ".gossip", "skill-index.json")) && !index.exists();
|
|
27080
27362
|
}
|
|
27081
27363
|
async function skillsGetHandler(projectRoot) {
|
|
27082
27364
|
try {
|
|
@@ -27105,13 +27387,13 @@ async function skillsBindHandler(projectRoot, body) {
|
|
|
27105
27387
|
return { success: false, error: err instanceof Error ? err.message : "Unknown error" };
|
|
27106
27388
|
}
|
|
27107
27389
|
}
|
|
27108
|
-
var
|
|
27390
|
+
var import_fs47, import_path50, AGENT_ID_RE2;
|
|
27109
27391
|
var init_api_skills = __esm({
|
|
27110
27392
|
"packages/relay/src/dashboard/api-skills.ts"() {
|
|
27111
27393
|
"use strict";
|
|
27112
27394
|
init_skill_index();
|
|
27113
|
-
|
|
27114
|
-
|
|
27395
|
+
import_fs47 = require("fs");
|
|
27396
|
+
import_path50 = require("path");
|
|
27115
27397
|
AGENT_ID_RE2 = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
27116
27398
|
}
|
|
27117
27399
|
});
|
|
@@ -27119,25 +27401,25 @@ var init_api_skills = __esm({
|
|
|
27119
27401
|
// packages/relay/src/dashboard/api-memory.ts
|
|
27120
27402
|
async function memoryHandler(projectRoot, agentId) {
|
|
27121
27403
|
if (!agentId || !AGENT_ID_RE3.test(agentId) || DANGEROUS_IDS.has(agentId)) throw new Error("Invalid agent ID");
|
|
27122
|
-
const memDir = (0,
|
|
27404
|
+
const memDir = (0, import_path51.join)(projectRoot, ".gossip", "agents", agentId, "memory");
|
|
27123
27405
|
let index = "";
|
|
27124
|
-
const indexPath = (0,
|
|
27125
|
-
if ((0,
|
|
27406
|
+
const indexPath = (0, import_path51.join)(memDir, "MEMORY.md");
|
|
27407
|
+
if ((0, import_fs48.existsSync)(indexPath)) {
|
|
27126
27408
|
try {
|
|
27127
|
-
index = (0,
|
|
27409
|
+
index = (0, import_fs48.readFileSync)(indexPath, "utf-8");
|
|
27128
27410
|
} catch {
|
|
27129
27411
|
}
|
|
27130
27412
|
}
|
|
27131
27413
|
const knowledge = [];
|
|
27132
|
-
const knowledgeDir = (0,
|
|
27414
|
+
const knowledgeDir = (0, import_path51.join)(memDir, "knowledge");
|
|
27133
27415
|
const knowledgeDirs = [knowledgeDir, memDir];
|
|
27134
27416
|
for (const dir of knowledgeDirs) {
|
|
27135
|
-
if (!(0,
|
|
27417
|
+
if (!(0, import_fs48.existsSync)(dir)) continue;
|
|
27136
27418
|
try {
|
|
27137
|
-
const files = (0,
|
|
27419
|
+
const files = (0, import_fs48.readdirSync)(dir).filter((f) => f.endsWith(".md") && f !== "MEMORY.md");
|
|
27138
27420
|
for (const filename of files) {
|
|
27139
27421
|
try {
|
|
27140
|
-
const raw = (0,
|
|
27422
|
+
const raw = (0, import_fs48.readFileSync)((0, import_path51.join)(dir, filename), "utf-8");
|
|
27141
27423
|
const { frontmatter, content } = parseFrontmatter(raw);
|
|
27142
27424
|
knowledge.push({ filename, frontmatter, content });
|
|
27143
27425
|
} catch {
|
|
@@ -27147,10 +27429,10 @@ async function memoryHandler(projectRoot, agentId) {
|
|
|
27147
27429
|
}
|
|
27148
27430
|
}
|
|
27149
27431
|
const tasks = [];
|
|
27150
|
-
const tasksPath = (0,
|
|
27151
|
-
if ((0,
|
|
27432
|
+
const tasksPath = (0, import_path51.join)(memDir, "tasks.jsonl");
|
|
27433
|
+
if ((0, import_fs48.existsSync)(tasksPath)) {
|
|
27152
27434
|
try {
|
|
27153
|
-
const lines = (0,
|
|
27435
|
+
const lines = (0, import_fs48.readFileSync)(tasksPath, "utf-8").trim().split("\n").filter(Boolean).slice(-200);
|
|
27154
27436
|
for (const line of lines) {
|
|
27155
27437
|
try {
|
|
27156
27438
|
tasks.push(JSON.parse(line));
|
|
@@ -27178,12 +27460,12 @@ function parseFrontmatter(raw) {
|
|
|
27178
27460
|
}
|
|
27179
27461
|
return { frontmatter: fm, content: raw.slice(end + 3).trim() };
|
|
27180
27462
|
}
|
|
27181
|
-
var
|
|
27463
|
+
var import_fs48, import_path51, AGENT_ID_RE3, DANGEROUS_IDS;
|
|
27182
27464
|
var init_api_memory = __esm({
|
|
27183
27465
|
"packages/relay/src/dashboard/api-memory.ts"() {
|
|
27184
27466
|
"use strict";
|
|
27185
|
-
|
|
27186
|
-
|
|
27467
|
+
import_fs48 = require("fs");
|
|
27468
|
+
import_path51 = require("path");
|
|
27187
27469
|
AGENT_ID_RE3 = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
27188
27470
|
DANGEROUS_IDS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
27189
27471
|
}
|
|
@@ -27192,25 +27474,25 @@ var init_api_memory = __esm({
|
|
|
27192
27474
|
// packages/relay/src/dashboard/api-native-memory.ts
|
|
27193
27475
|
function autoMemoryDir(projectRoot, home) {
|
|
27194
27476
|
const h = home ?? (0, import_os2.homedir)();
|
|
27195
|
-
return (0,
|
|
27477
|
+
return (0, import_path52.join)(h, ".claude", "projects", projectRoot.replaceAll("/", "-"), "memory");
|
|
27196
27478
|
}
|
|
27197
27479
|
async function autoMemoryHandler(projectRoot, home) {
|
|
27198
27480
|
const dir = autoMemoryDir(projectRoot, home);
|
|
27199
|
-
if (!(0,
|
|
27481
|
+
if (!(0, import_fs49.existsSync)(dir)) return { knowledge: [] };
|
|
27200
27482
|
let entries;
|
|
27201
27483
|
try {
|
|
27202
|
-
entries = (0,
|
|
27484
|
+
entries = (0, import_fs49.readdirSync)(dir);
|
|
27203
27485
|
} catch {
|
|
27204
27486
|
return { knowledge: [] };
|
|
27205
27487
|
}
|
|
27206
27488
|
const knowledge = [];
|
|
27207
27489
|
for (const filename of entries) {
|
|
27208
27490
|
if (!FILENAME_RE.test(filename)) continue;
|
|
27209
|
-
const full = (0,
|
|
27491
|
+
const full = (0, import_path52.join)(dir, filename);
|
|
27210
27492
|
try {
|
|
27211
|
-
const st = (0,
|
|
27493
|
+
const st = (0, import_fs49.statSync)(full);
|
|
27212
27494
|
if (!st.isFile()) continue;
|
|
27213
|
-
const raw = (0,
|
|
27495
|
+
const raw = (0, import_fs49.readFileSync)(full, "utf-8");
|
|
27214
27496
|
const { frontmatter, content } = parseFrontmatter2(raw);
|
|
27215
27497
|
knowledge.push({ filename, frontmatter, content, agentId: "_auto" });
|
|
27216
27498
|
} catch {
|
|
@@ -27232,12 +27514,12 @@ function parseFrontmatter2(raw) {
|
|
|
27232
27514
|
if (rest.startsWith("\n")) rest = rest.slice(1);
|
|
27233
27515
|
return { frontmatter: fm, content: rest.trim() };
|
|
27234
27516
|
}
|
|
27235
|
-
var
|
|
27517
|
+
var import_fs49, import_path52, import_os2, FILENAME_RE;
|
|
27236
27518
|
var init_api_native_memory = __esm({
|
|
27237
27519
|
"packages/relay/src/dashboard/api-native-memory.ts"() {
|
|
27238
27520
|
"use strict";
|
|
27239
|
-
|
|
27240
|
-
|
|
27521
|
+
import_fs49 = require("fs");
|
|
27522
|
+
import_path52 = require("path");
|
|
27241
27523
|
import_os2 = require("os");
|
|
27242
27524
|
FILENAME_RE = /^[A-Za-z0-9_.-]+\.md$/;
|
|
27243
27525
|
}
|
|
@@ -27245,25 +27527,25 @@ var init_api_native_memory = __esm({
|
|
|
27245
27527
|
|
|
27246
27528
|
// packages/relay/src/dashboard/api-gossip-memory.ts
|
|
27247
27529
|
function gossipMemoryDir(projectRoot) {
|
|
27248
|
-
return (0,
|
|
27530
|
+
return (0, import_path53.join)(projectRoot, ".gossip", "memory");
|
|
27249
27531
|
}
|
|
27250
27532
|
async function gossipMemoryHandler(projectRoot) {
|
|
27251
27533
|
const dir = gossipMemoryDir(projectRoot);
|
|
27252
|
-
if (!(0,
|
|
27534
|
+
if (!(0, import_fs50.existsSync)(dir)) return { knowledge: [] };
|
|
27253
27535
|
let entries;
|
|
27254
27536
|
try {
|
|
27255
|
-
entries = (0,
|
|
27537
|
+
entries = (0, import_fs50.readdirSync)(dir);
|
|
27256
27538
|
} catch {
|
|
27257
27539
|
return { knowledge: [] };
|
|
27258
27540
|
}
|
|
27259
27541
|
const knowledge = [];
|
|
27260
27542
|
for (const filename of entries) {
|
|
27261
27543
|
if (!FILENAME_RE2.test(filename)) continue;
|
|
27262
|
-
const full = (0,
|
|
27544
|
+
const full = (0, import_path53.join)(dir, filename);
|
|
27263
27545
|
try {
|
|
27264
|
-
const st = (0,
|
|
27546
|
+
const st = (0, import_fs50.statSync)(full);
|
|
27265
27547
|
if (!st.isFile()) continue;
|
|
27266
|
-
const raw = (0,
|
|
27548
|
+
const raw = (0, import_fs50.readFileSync)(full, "utf-8");
|
|
27267
27549
|
const { frontmatter, content } = parseFrontmatter2(raw);
|
|
27268
27550
|
knowledge.push({ filename, frontmatter, content, agentId: "_gossip" });
|
|
27269
27551
|
} catch {
|
|
@@ -27271,12 +27553,12 @@ async function gossipMemoryHandler(projectRoot) {
|
|
|
27271
27553
|
}
|
|
27272
27554
|
return { knowledge };
|
|
27273
27555
|
}
|
|
27274
|
-
var
|
|
27556
|
+
var import_fs50, import_path53, FILENAME_RE2;
|
|
27275
27557
|
var init_api_gossip_memory = __esm({
|
|
27276
27558
|
"packages/relay/src/dashboard/api-gossip-memory.ts"() {
|
|
27277
27559
|
"use strict";
|
|
27278
|
-
|
|
27279
|
-
|
|
27560
|
+
import_fs50 = require("fs");
|
|
27561
|
+
import_path53 = require("path");
|
|
27280
27562
|
init_api_native_memory();
|
|
27281
27563
|
FILENAME_RE2 = /^[A-Za-z0-9_.-]+\.md$/;
|
|
27282
27564
|
}
|
|
@@ -27288,7 +27570,7 @@ async function consensusHandler(projectRoot, query) {
|
|
|
27288
27570
|
const rawPageSize = parseInt(query?.get("pageSize") ?? "", 10);
|
|
27289
27571
|
const page = isNaN(rawPage) || rawPage < 1 ? 1 : rawPage;
|
|
27290
27572
|
const pageSize = isNaN(rawPageSize) || rawPageSize < 1 ? DEFAULT_PAGE_SIZE : Math.min(rawPageSize, MAX_PAGE_SIZE);
|
|
27291
|
-
const perfPath = (0,
|
|
27573
|
+
const perfPath = (0, import_path54.join)(projectRoot, ".gossip", "agent-performance.jsonl");
|
|
27292
27574
|
let retractedIds = /* @__PURE__ */ new Set();
|
|
27293
27575
|
let roundRetractions = [];
|
|
27294
27576
|
try {
|
|
@@ -27303,10 +27585,10 @@ async function consensusHandler(projectRoot, query) {
|
|
|
27303
27585
|
retractionByConsensusId.set(r.consensus_id, { reason: r.reason, retracted_at: r.retracted_at });
|
|
27304
27586
|
}
|
|
27305
27587
|
const retractedConsensusIds = Array.from(retractedIds);
|
|
27306
|
-
if (!(0,
|
|
27588
|
+
if (!(0, import_fs51.existsSync)(perfPath)) return { runs: [], totalRuns: 0, totalSignals: 0, page, pageSize, retractedConsensusIds, roundRetractions };
|
|
27307
27589
|
const signals = [];
|
|
27308
27590
|
try {
|
|
27309
|
-
const lines = (0,
|
|
27591
|
+
const lines = (0, import_fs51.readFileSync)(perfPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
27310
27592
|
for (const line of lines) {
|
|
27311
27593
|
try {
|
|
27312
27594
|
const parsed = JSON.parse(line);
|
|
@@ -27383,12 +27665,12 @@ async function consensusHandler(projectRoot, query) {
|
|
|
27383
27665
|
const paginatedRuns = runs.slice(offset, offset + pageSize);
|
|
27384
27666
|
return { runs: paginatedRuns, totalRuns, totalSignals: signals.length, page, pageSize, retractedConsensusIds, roundRetractions };
|
|
27385
27667
|
}
|
|
27386
|
-
var
|
|
27668
|
+
var import_fs51, import_path54, RESOLUTION_SIGNALS, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE;
|
|
27387
27669
|
var init_api_consensus = __esm({
|
|
27388
27670
|
"packages/relay/src/dashboard/api-consensus.ts"() {
|
|
27389
27671
|
"use strict";
|
|
27390
|
-
|
|
27391
|
-
|
|
27672
|
+
import_fs51 = require("fs");
|
|
27673
|
+
import_path54 = require("path");
|
|
27392
27674
|
RESOLUTION_SIGNALS = /* @__PURE__ */ new Set(["agreement", "unique_confirmed", "consensus_verified"]);
|
|
27393
27675
|
DEFAULT_PAGE_SIZE = 10;
|
|
27394
27676
|
MAX_PAGE_SIZE = 500;
|
|
@@ -27420,13 +27702,13 @@ async function signalsHandler(projectRoot, query) {
|
|
|
27420
27702
|
const cursor = query?.get("cursor") ?? null;
|
|
27421
27703
|
const limit = Math.min(Math.max(parseInt(query?.get("limit") ?? "", 10) || DEFAULT_LIMIT, 1), MAX_LIMIT);
|
|
27422
27704
|
const offset = Math.max(parseInt(query?.get("offset") ?? "", 10) || 0, 0);
|
|
27423
|
-
const perfPath = (0,
|
|
27424
|
-
if (!(0,
|
|
27705
|
+
const perfPath = (0, import_path55.join)(projectRoot, ".gossip", "agent-performance.jsonl");
|
|
27706
|
+
if (!(0, import_fs52.existsSync)(perfPath)) return { items: [], total: 0, offset, limit };
|
|
27425
27707
|
const all = [];
|
|
27426
27708
|
const roundRetractions = [];
|
|
27427
27709
|
const signalFilterSet = signalFilters.length ? new Set(signalFilters) : null;
|
|
27428
27710
|
try {
|
|
27429
|
-
const lines = (0,
|
|
27711
|
+
const lines = (0, import_fs52.readFileSync)(perfPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
27430
27712
|
for (const line of lines) {
|
|
27431
27713
|
try {
|
|
27432
27714
|
const entry = JSON.parse(line);
|
|
@@ -27481,12 +27763,12 @@ async function signalsHandler(projectRoot, query) {
|
|
|
27481
27763
|
if (nextCursor) response.nextCursor = nextCursor;
|
|
27482
27764
|
return response;
|
|
27483
27765
|
}
|
|
27484
|
-
var
|
|
27766
|
+
var import_fs52, import_path55, MAX_LIMIT, DEFAULT_LIMIT, META_SIGNALS;
|
|
27485
27767
|
var init_api_signals = __esm({
|
|
27486
27768
|
"packages/relay/src/dashboard/api-signals.ts"() {
|
|
27487
27769
|
"use strict";
|
|
27488
|
-
|
|
27489
|
-
|
|
27770
|
+
import_fs52 = require("fs");
|
|
27771
|
+
import_path55 = require("path");
|
|
27490
27772
|
MAX_LIMIT = 500;
|
|
27491
27773
|
DEFAULT_LIMIT = 50;
|
|
27492
27774
|
META_SIGNALS = /* @__PURE__ */ new Set(["task_completed", "tool_turns", "format_compliance"]);
|
|
@@ -27498,7 +27780,7 @@ function extractCitations(findingText, projectRoot) {
|
|
|
27498
27780
|
const out = [];
|
|
27499
27781
|
let realRoot;
|
|
27500
27782
|
try {
|
|
27501
|
-
realRoot = (0,
|
|
27783
|
+
realRoot = (0, import_fs53.realpathSync)((0, import_path56.resolve)(projectRoot));
|
|
27502
27784
|
} catch {
|
|
27503
27785
|
return out;
|
|
27504
27786
|
}
|
|
@@ -27509,23 +27791,23 @@ function extractCitations(findingText, projectRoot) {
|
|
|
27509
27791
|
const line = parseInt(m[2], 10);
|
|
27510
27792
|
if (!Number.isFinite(line) || line < 1) continue;
|
|
27511
27793
|
if (filePath.includes("\0")) continue;
|
|
27512
|
-
const abs = (0,
|
|
27513
|
-
const preRel = (0,
|
|
27794
|
+
const abs = (0, import_path56.resolve)(realRoot, filePath);
|
|
27795
|
+
const preRel = (0, import_path56.relative)(realRoot, abs);
|
|
27514
27796
|
if (preRel === "" || preRel.startsWith("..")) continue;
|
|
27515
|
-
if (!(0,
|
|
27797
|
+
if (!(0, import_fs53.existsSync)(abs)) {
|
|
27516
27798
|
out.push({ file: filePath, line, snippet: "// file not found" });
|
|
27517
27799
|
continue;
|
|
27518
27800
|
}
|
|
27519
27801
|
let realAbs;
|
|
27520
27802
|
try {
|
|
27521
|
-
realAbs = (0,
|
|
27803
|
+
realAbs = (0, import_fs53.realpathSync)(abs);
|
|
27522
27804
|
} catch {
|
|
27523
27805
|
continue;
|
|
27524
27806
|
}
|
|
27525
|
-
const rel = (0,
|
|
27807
|
+
const rel = (0, import_path56.relative)(realRoot, realAbs);
|
|
27526
27808
|
if (rel === "" || rel.startsWith("..")) continue;
|
|
27527
27809
|
try {
|
|
27528
|
-
const lines = (0,
|
|
27810
|
+
const lines = (0, import_fs53.readFileSync)(realAbs, "utf-8").split("\n");
|
|
27529
27811
|
const start = Math.max(0, line - 1 - SNIPPET_CONTEXT);
|
|
27530
27812
|
const end = Math.min(lines.length, line + SNIPPET_CONTEXT);
|
|
27531
27813
|
out.push({ file: filePath, line, snippet: lines.slice(start, end).join("\n") });
|
|
@@ -27538,9 +27820,9 @@ function extractCitations(findingText, projectRoot) {
|
|
|
27538
27820
|
async function findingHandler(projectRoot, consensusId, findingId) {
|
|
27539
27821
|
if (!SAFE_ID.test(consensusId)) throw new Error(`consensus ${consensusId} not found`);
|
|
27540
27822
|
if (!SAFE_ID.test(findingId)) throw new Error(`finding ${findingId} not found in ${consensusId}`);
|
|
27541
|
-
const reportPath = (0,
|
|
27542
|
-
if (!(0,
|
|
27543
|
-
const report = JSON.parse((0,
|
|
27823
|
+
const reportPath = (0, import_path56.join)(projectRoot, ".gossip", "consensus-reports", `${consensusId}.json`);
|
|
27824
|
+
if (!(0, import_fs53.existsSync)(reportPath)) throw new Error(`consensus ${consensusId} not found`);
|
|
27825
|
+
const report = JSON.parse((0, import_fs53.readFileSync)(reportPath, "utf-8"));
|
|
27544
27826
|
const buckets = [
|
|
27545
27827
|
["confirmed", "confirmed"],
|
|
27546
27828
|
["disputed", "disputed"],
|
|
@@ -27561,9 +27843,9 @@ async function findingHandler(projectRoot, consensusId, findingId) {
|
|
|
27561
27843
|
}
|
|
27562
27844
|
if (!found) throw new Error(`finding ${findingId} not found in ${consensusId}`);
|
|
27563
27845
|
const signals = [];
|
|
27564
|
-
const perfPath = (0,
|
|
27565
|
-
if ((0,
|
|
27566
|
-
const lines = (0,
|
|
27846
|
+
const perfPath = (0, import_path56.join)(projectRoot, ".gossip", "agent-performance.jsonl");
|
|
27847
|
+
if ((0, import_fs53.existsSync)(perfPath)) {
|
|
27848
|
+
const lines = (0, import_fs53.readFileSync)(perfPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
27567
27849
|
for (const line of lines) {
|
|
27568
27850
|
try {
|
|
27569
27851
|
const rec = JSON.parse(line);
|
|
@@ -27599,12 +27881,12 @@ async function findingHandler(projectRoot, consensusId, findingId) {
|
|
|
27599
27881
|
citations
|
|
27600
27882
|
};
|
|
27601
27883
|
}
|
|
27602
|
-
var
|
|
27884
|
+
var import_fs53, import_path56, SAFE_ID, SNIPPET_CONTEXT, CITE_PATTERN;
|
|
27603
27885
|
var init_api_finding = __esm({
|
|
27604
27886
|
"packages/relay/src/dashboard/api-finding.ts"() {
|
|
27605
27887
|
"use strict";
|
|
27606
|
-
|
|
27607
|
-
|
|
27888
|
+
import_fs53 = require("fs");
|
|
27889
|
+
import_path56 = require("path");
|
|
27608
27890
|
SAFE_ID = /^[\w:.\-]+$/;
|
|
27609
27891
|
SNIPPET_CONTEXT = 2;
|
|
27610
27892
|
CITE_PATTERN = /<cite tag="file">([^<:]+):(\d+)<\/cite>/g;
|
|
@@ -27617,13 +27899,13 @@ async function openFindingsHandler(projectRoot) {
|
|
|
27617
27899
|
let open = 0;
|
|
27618
27900
|
let resolved = 0;
|
|
27619
27901
|
let staleAnchor = 0;
|
|
27620
|
-
const findingsPath = (0,
|
|
27621
|
-
if (!(0,
|
|
27902
|
+
const findingsPath = (0, import_path57.join)(projectRoot, ".gossip", "implementation-findings.jsonl");
|
|
27903
|
+
if (!(0, import_fs54.existsSync)(findingsPath)) {
|
|
27622
27904
|
return { rows, totals: { open: 0, resolved: 0, staleAnchor: 0 } };
|
|
27623
27905
|
}
|
|
27624
27906
|
let raw;
|
|
27625
27907
|
try {
|
|
27626
|
-
raw = (0,
|
|
27908
|
+
raw = (0, import_fs54.readFileSync)(findingsPath, "utf-8");
|
|
27627
27909
|
} catch {
|
|
27628
27910
|
return { rows, totals: { open: 0, resolved: 0, staleAnchor: 0 } };
|
|
27629
27911
|
}
|
|
@@ -27637,6 +27919,7 @@ async function openFindingsHandler(projectRoot) {
|
|
|
27637
27919
|
}
|
|
27638
27920
|
const findingId = String(entry.taskId ?? entry.findingId ?? entry.id ?? "");
|
|
27639
27921
|
if (!findingId) continue;
|
|
27922
|
+
if (entry.type === "insight") continue;
|
|
27640
27923
|
let state;
|
|
27641
27924
|
if (entry.status === "resolved") {
|
|
27642
27925
|
state = entry.resolvedBy === "stale_anchor" ? "stale-anchor" : "resolved";
|
|
@@ -27660,40 +27943,40 @@ async function openFindingsHandler(projectRoot) {
|
|
|
27660
27943
|
}
|
|
27661
27944
|
return { rows, totals: { open, resolved, staleAnchor } };
|
|
27662
27945
|
}
|
|
27663
|
-
var
|
|
27946
|
+
var import_fs54, import_path57;
|
|
27664
27947
|
var init_api_open_findings = __esm({
|
|
27665
27948
|
"packages/relay/src/dashboard/api-open-findings.ts"() {
|
|
27666
27949
|
"use strict";
|
|
27667
|
-
|
|
27668
|
-
|
|
27950
|
+
import_fs54 = require("fs");
|
|
27951
|
+
import_path57 = require("path");
|
|
27669
27952
|
}
|
|
27670
27953
|
});
|
|
27671
27954
|
|
|
27672
27955
|
// packages/relay/src/dashboard/api-learnings.ts
|
|
27673
27956
|
async function learningsHandler(projectRoot) {
|
|
27674
|
-
const agentsDir = (0,
|
|
27675
|
-
if (!(0,
|
|
27957
|
+
const agentsDir = (0, import_path58.join)(projectRoot, ".gossip", "agents");
|
|
27958
|
+
if (!(0, import_fs55.existsSync)(agentsDir)) return { learnings: [] };
|
|
27676
27959
|
const all = [];
|
|
27677
27960
|
let agentIds;
|
|
27678
27961
|
try {
|
|
27679
|
-
agentIds = (0,
|
|
27962
|
+
agentIds = (0, import_fs55.readdirSync)(agentsDir).filter((f) => !f.startsWith("."));
|
|
27680
27963
|
} catch {
|
|
27681
27964
|
return { learnings: [] };
|
|
27682
27965
|
}
|
|
27683
27966
|
for (const agentId of agentIds) {
|
|
27684
|
-
const knowledgeDir = (0,
|
|
27685
|
-
if (!(0,
|
|
27967
|
+
const knowledgeDir = (0, import_path58.join)(agentsDir, agentId, "memory", "knowledge");
|
|
27968
|
+
if (!(0, import_fs55.existsSync)(knowledgeDir)) continue;
|
|
27686
27969
|
let files;
|
|
27687
27970
|
try {
|
|
27688
|
-
files = (0,
|
|
27971
|
+
files = (0, import_fs55.readdirSync)(knowledgeDir).filter((f) => f.endsWith(".md"));
|
|
27689
27972
|
} catch {
|
|
27690
27973
|
continue;
|
|
27691
27974
|
}
|
|
27692
27975
|
for (const filename of files) {
|
|
27693
|
-
const filepath = (0,
|
|
27976
|
+
const filepath = (0, import_path58.join)(knowledgeDir, filename);
|
|
27694
27977
|
try {
|
|
27695
|
-
const stat4 = (0,
|
|
27696
|
-
const raw = (0,
|
|
27978
|
+
const stat4 = (0, import_fs55.statSync)(filepath);
|
|
27979
|
+
const raw = (0, import_fs55.readFileSync)(filepath, "utf-8");
|
|
27697
27980
|
const fm = parseFrontmatter3(raw);
|
|
27698
27981
|
all.push({
|
|
27699
27982
|
agentId,
|
|
@@ -27720,12 +28003,12 @@ function parseFrontmatter3(raw) {
|
|
|
27720
28003
|
}
|
|
27721
28004
|
return fm;
|
|
27722
28005
|
}
|
|
27723
|
-
var
|
|
28006
|
+
var import_fs55, import_path58, MAX_LEARNINGS;
|
|
27724
28007
|
var init_api_learnings = __esm({
|
|
27725
28008
|
"packages/relay/src/dashboard/api-learnings.ts"() {
|
|
27726
28009
|
"use strict";
|
|
27727
|
-
|
|
27728
|
-
|
|
28010
|
+
import_fs55 = require("fs");
|
|
28011
|
+
import_path58 = require("path");
|
|
27729
28012
|
MAX_LEARNINGS = 10;
|
|
27730
28013
|
}
|
|
27731
28014
|
});
|
|
@@ -27736,12 +28019,12 @@ async function tasksHandler(projectRoot, query) {
|
|
|
27736
28019
|
const rawOffset = parseInt(query?.get("offset") ?? "0", 10);
|
|
27737
28020
|
const limit = isNaN(rawLimit) || rawLimit < 1 ? 50 : Math.min(rawLimit, 2e3);
|
|
27738
28021
|
const offset = isNaN(rawOffset) || rawOffset < 0 ? 0 : rawOffset;
|
|
27739
|
-
const graphPath = (0,
|
|
27740
|
-
if (!(0,
|
|
28022
|
+
const graphPath = (0, import_path59.join)(projectRoot, ".gossip", "task-graph.jsonl");
|
|
28023
|
+
if (!(0, import_fs56.existsSync)(graphPath)) return { items: [], total: 0, offset, limit };
|
|
27741
28024
|
const created = /* @__PURE__ */ new Map();
|
|
27742
28025
|
const completed = /* @__PURE__ */ new Map();
|
|
27743
28026
|
try {
|
|
27744
|
-
const lines = (0,
|
|
28027
|
+
const lines = (0, import_fs56.readFileSync)(graphPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
27745
28028
|
for (const line of lines) {
|
|
27746
28029
|
try {
|
|
27747
28030
|
const entry = JSON.parse(line);
|
|
@@ -27797,24 +28080,24 @@ async function tasksHandler(projectRoot, query) {
|
|
|
27797
28080
|
tasks.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
27798
28081
|
return { items: tasks.slice(offset, offset + limit), total: tasks.length, offset, limit };
|
|
27799
28082
|
}
|
|
27800
|
-
var
|
|
28083
|
+
var import_fs56, import_path59;
|
|
27801
28084
|
var init_api_tasks = __esm({
|
|
27802
28085
|
"packages/relay/src/dashboard/api-tasks.ts"() {
|
|
27803
28086
|
"use strict";
|
|
27804
|
-
|
|
27805
|
-
|
|
28087
|
+
import_fs56 = require("fs");
|
|
28088
|
+
import_path59 = require("path");
|
|
27806
28089
|
init_utility_agents();
|
|
27807
28090
|
}
|
|
27808
28091
|
});
|
|
27809
28092
|
|
|
27810
28093
|
// packages/relay/src/dashboard/api-active-tasks.ts
|
|
27811
28094
|
async function activeTasksHandler(projectRoot) {
|
|
27812
|
-
const taskGraphPath = (0,
|
|
27813
|
-
if (!(0,
|
|
28095
|
+
const taskGraphPath = (0, import_path60.join)(projectRoot, ".gossip", "task-graph.jsonl");
|
|
28096
|
+
if (!(0, import_fs57.existsSync)(taskGraphPath)) return { tasks: [] };
|
|
27814
28097
|
const created = /* @__PURE__ */ new Map();
|
|
27815
28098
|
const finished = /* @__PURE__ */ new Set();
|
|
27816
28099
|
try {
|
|
27817
|
-
const lines = (0,
|
|
28100
|
+
const lines = (0, import_fs57.readFileSync)(taskGraphPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
27818
28101
|
for (const line of lines) {
|
|
27819
28102
|
try {
|
|
27820
28103
|
const ev = JSON.parse(line);
|
|
@@ -27842,12 +28125,12 @@ async function activeTasksHandler(projectRoot) {
|
|
|
27842
28125
|
active.sort((a, b) => b.startedAt.localeCompare(a.startedAt));
|
|
27843
28126
|
return { tasks: active.slice(0, 10) };
|
|
27844
28127
|
}
|
|
27845
|
-
var
|
|
28128
|
+
var import_fs57, import_path60;
|
|
27846
28129
|
var init_api_active_tasks = __esm({
|
|
27847
28130
|
"packages/relay/src/dashboard/api-active-tasks.ts"() {
|
|
27848
28131
|
"use strict";
|
|
27849
|
-
|
|
27850
|
-
|
|
28132
|
+
import_fs57 = require("fs");
|
|
28133
|
+
import_path60 = require("path");
|
|
27851
28134
|
init_utility_agents();
|
|
27852
28135
|
}
|
|
27853
28136
|
});
|
|
@@ -27861,25 +28144,25 @@ function categorize(text) {
|
|
|
27861
28144
|
return "other";
|
|
27862
28145
|
}
|
|
27863
28146
|
function logsHandler(projectRoot, query) {
|
|
27864
|
-
const logPath = (0,
|
|
27865
|
-
if (!(0,
|
|
28147
|
+
const logPath = (0, import_path61.join)(projectRoot, ".gossip", "mcp.log");
|
|
28148
|
+
if (!(0, import_fs58.existsSync)(logPath)) {
|
|
27866
28149
|
return { entries: [], totalLines: 0, fileSize: 0 };
|
|
27867
28150
|
}
|
|
27868
28151
|
const filter = query?.get("filter") || void 0;
|
|
27869
28152
|
const tail = parseInt(query?.get("tail") || "200", 10);
|
|
27870
28153
|
const clampedTail = Math.min(Math.max(tail, 10), 2e3);
|
|
27871
|
-
const fileSize = (0,
|
|
28154
|
+
const fileSize = (0, import_fs58.statSync)(logPath).size;
|
|
27872
28155
|
const MAX_READ = 512 * 1024;
|
|
27873
28156
|
const readFrom = Math.max(0, fileSize - MAX_READ);
|
|
27874
28157
|
const readLen = fileSize - readFrom;
|
|
27875
|
-
const fd = (0,
|
|
28158
|
+
const fd = (0, import_fs58.openSync)(logPath, "r");
|
|
27876
28159
|
let buf = Buffer.alloc(0);
|
|
27877
28160
|
try {
|
|
27878
28161
|
buf = Buffer.allocUnsafe(readLen);
|
|
27879
|
-
const bytesRead = (0,
|
|
28162
|
+
const bytesRead = (0, import_fs58.readSync)(fd, buf, 0, readLen, readFrom);
|
|
27880
28163
|
buf = buf.subarray(0, bytesRead);
|
|
27881
28164
|
} finally {
|
|
27882
|
-
(0,
|
|
28165
|
+
(0, import_fs58.closeSync)(fd);
|
|
27883
28166
|
}
|
|
27884
28167
|
let raw = buf.toString("utf-8");
|
|
27885
28168
|
let lineOffset = 0;
|
|
@@ -27887,13 +28170,13 @@ function logsHandler(projectRoot, query) {
|
|
|
27887
28170
|
const nl = raw.indexOf("\n");
|
|
27888
28171
|
raw = nl >= 0 ? raw.slice(nl + 1) : raw;
|
|
27889
28172
|
const SCAN_CHUNK = 64 * 1024;
|
|
27890
|
-
const scanFd = (0,
|
|
28173
|
+
const scanFd = (0, import_fs58.openSync)(logPath, "r");
|
|
27891
28174
|
try {
|
|
27892
28175
|
let pos = 0;
|
|
27893
28176
|
const chunk = Buffer.allocUnsafe(SCAN_CHUNK);
|
|
27894
28177
|
while (pos < readFrom) {
|
|
27895
28178
|
const len = Math.min(SCAN_CHUNK, readFrom - pos);
|
|
27896
|
-
const n = (0,
|
|
28179
|
+
const n = (0, import_fs58.readSync)(scanFd, chunk, 0, len, pos);
|
|
27897
28180
|
if (n === 0) break;
|
|
27898
28181
|
for (let j = 0; j < n; j++) {
|
|
27899
28182
|
if (chunk[j] === 10) lineOffset++;
|
|
@@ -27901,7 +28184,7 @@ function logsHandler(projectRoot, query) {
|
|
|
27901
28184
|
pos += n;
|
|
27902
28185
|
}
|
|
27903
28186
|
} finally {
|
|
27904
|
-
(0,
|
|
28187
|
+
(0, import_fs58.closeSync)(scanFd);
|
|
27905
28188
|
}
|
|
27906
28189
|
}
|
|
27907
28190
|
const allLines = raw.split("\n").filter(Boolean);
|
|
@@ -27919,12 +28202,12 @@ function logsHandler(projectRoot, query) {
|
|
|
27919
28202
|
entries = entries.slice(-clampedTail);
|
|
27920
28203
|
return { entries, totalLines, fileSize, filter };
|
|
27921
28204
|
}
|
|
27922
|
-
var
|
|
28205
|
+
var import_fs58, import_path61, CATEGORY_PATTERNS2;
|
|
27923
28206
|
var init_api_logs = __esm({
|
|
27924
28207
|
"packages/relay/src/dashboard/api-logs.ts"() {
|
|
27925
28208
|
"use strict";
|
|
27926
|
-
|
|
27927
|
-
|
|
28209
|
+
import_fs58 = require("fs");
|
|
28210
|
+
import_path61 = require("path");
|
|
27928
28211
|
CATEGORY_PATTERNS2 = [
|
|
27929
28212
|
[/^\[worker:/, "worker"],
|
|
27930
28213
|
[/^\[Gemini\]/, "gemini"],
|
|
@@ -27951,18 +28234,57 @@ var init_api_logs = __esm({
|
|
|
27951
28234
|
}
|
|
27952
28235
|
});
|
|
27953
28236
|
|
|
28237
|
+
// packages/relay/src/dashboard/api-violations.ts
|
|
28238
|
+
function violationsHandler(projectRoot, query) {
|
|
28239
|
+
const page = Math.max(1, parseInt(query?.get("page") ?? "1", 10));
|
|
28240
|
+
const pageSize = Math.min(100, Math.max(1, parseInt(query?.get("pageSize") ?? "25", 10)));
|
|
28241
|
+
const agentFilter = query?.get("agentId") ?? null;
|
|
28242
|
+
const filePath = (0, import_path62.join)(projectRoot, FILE);
|
|
28243
|
+
if (!(0, import_fs59.existsSync)(filePath)) {
|
|
28244
|
+
return { items: [], total: 0, page, pageSize };
|
|
28245
|
+
}
|
|
28246
|
+
const raw = (0, import_fs59.readFileSync)(filePath, "utf-8");
|
|
28247
|
+
const lines = raw.trim().split("\n").filter(Boolean);
|
|
28248
|
+
const entries = [];
|
|
28249
|
+
for (const line of lines) {
|
|
28250
|
+
try {
|
|
28251
|
+
const entry = JSON.parse(line);
|
|
28252
|
+
if (!agentFilter || entry.agentId === agentFilter) {
|
|
28253
|
+
entries.push(entry);
|
|
28254
|
+
}
|
|
28255
|
+
} catch {
|
|
28256
|
+
continue;
|
|
28257
|
+
}
|
|
28258
|
+
}
|
|
28259
|
+
entries.sort(
|
|
28260
|
+
(a, b) => new Date(b.detectedAt).getTime() - new Date(a.detectedAt).getTime()
|
|
28261
|
+
);
|
|
28262
|
+
const total = entries.length;
|
|
28263
|
+
const start = (page - 1) * pageSize;
|
|
28264
|
+
return { items: entries.slice(start, start + pageSize), total, page, pageSize };
|
|
28265
|
+
}
|
|
28266
|
+
var import_fs59, import_path62, FILE;
|
|
28267
|
+
var init_api_violations = __esm({
|
|
28268
|
+
"packages/relay/src/dashboard/api-violations.ts"() {
|
|
28269
|
+
"use strict";
|
|
28270
|
+
import_fs59 = require("fs");
|
|
28271
|
+
import_path62 = require("path");
|
|
28272
|
+
FILE = ".gossip/process-violations.jsonl";
|
|
28273
|
+
}
|
|
28274
|
+
});
|
|
28275
|
+
|
|
27954
28276
|
// packages/relay/src/dashboard/routes.ts
|
|
27955
28277
|
function resolveDashboardRoot(projectRoot) {
|
|
27956
28278
|
const candidates = [
|
|
27957
|
-
(0,
|
|
28279
|
+
(0, import_path63.resolve)(__dirname, "..", "dist-dashboard"),
|
|
27958
28280
|
// bundled: dist-mcp/mcp-server.js → ../dist-dashboard
|
|
27959
|
-
(0,
|
|
28281
|
+
(0, import_path63.resolve)(__dirname, "..", "..", "..", "..", "dist-dashboard"),
|
|
27960
28282
|
// tsc dev: packages/relay/dist/dashboard → repo-root
|
|
27961
|
-
(0,
|
|
28283
|
+
(0, import_path63.join)(projectRoot, "dist-dashboard")
|
|
27962
28284
|
// legacy dev fallback (git-clone running from repo root)
|
|
27963
28285
|
];
|
|
27964
28286
|
for (const p of candidates) {
|
|
27965
|
-
if ((0,
|
|
28287
|
+
if ((0, import_fs60.existsSync)(p)) return p;
|
|
27966
28288
|
}
|
|
27967
28289
|
return null;
|
|
27968
28290
|
}
|
|
@@ -27989,7 +28311,7 @@ function readBody(req) {
|
|
|
27989
28311
|
});
|
|
27990
28312
|
});
|
|
27991
28313
|
}
|
|
27992
|
-
var
|
|
28314
|
+
var import_fs60, import_path63, import_crypto21, AUTH_MAX_ATTEMPTS, AUTH_LOCKOUT_MS, DashboardRouter, MAX_BODY_SIZE;
|
|
27993
28315
|
var init_routes = __esm({
|
|
27994
28316
|
"packages/relay/src/dashboard/routes.ts"() {
|
|
27995
28317
|
"use strict";
|
|
@@ -28008,8 +28330,9 @@ var init_routes = __esm({
|
|
|
28008
28330
|
init_api_tasks();
|
|
28009
28331
|
init_api_active_tasks();
|
|
28010
28332
|
init_api_logs();
|
|
28011
|
-
|
|
28012
|
-
|
|
28333
|
+
init_api_violations();
|
|
28334
|
+
import_fs60 = require("fs");
|
|
28335
|
+
import_path63 = require("path");
|
|
28013
28336
|
import_crypto21 = require("crypto");
|
|
28014
28337
|
AUTH_MAX_ATTEMPTS = 10;
|
|
28015
28338
|
AUTH_LOCKOUT_MS = 6e4;
|
|
@@ -28249,6 +28572,11 @@ var init_routes = __esm({
|
|
|
28249
28572
|
this.json(res, 200, data);
|
|
28250
28573
|
return true;
|
|
28251
28574
|
}
|
|
28575
|
+
if (url2 === "/dashboard/api/violations" && req.method === "GET") {
|
|
28576
|
+
const data = violationsHandler(this.projectRoot, query ?? void 0);
|
|
28577
|
+
this.json(res, 200, data);
|
|
28578
|
+
return true;
|
|
28579
|
+
}
|
|
28252
28580
|
if ((url2 === "/dashboard/api/native-memory" || url2 === "/dashboard/api/auto-memory") && req.method === "GET") {
|
|
28253
28581
|
const data = await autoMemoryHandler(this.projectRoot);
|
|
28254
28582
|
this.json(res, 200, data);
|
|
@@ -28281,13 +28609,13 @@ var init_routes = __esm({
|
|
|
28281
28609
|
res.end("Dashboard assets not found. Reinstall gossipcat or rebuild from source.");
|
|
28282
28610
|
return true;
|
|
28283
28611
|
}
|
|
28284
|
-
const htmlPath = (0,
|
|
28285
|
-
if (!(0,
|
|
28612
|
+
const htmlPath = (0, import_path63.join)(this.dashboardRoot, "index.html");
|
|
28613
|
+
if (!(0, import_fs60.existsSync)(htmlPath)) {
|
|
28286
28614
|
res.writeHead(503, { "Content-Type": "text/plain" });
|
|
28287
28615
|
res.end(`Dashboard index.html missing at ${this.dashboardRoot}. Reinstall gossipcat.`);
|
|
28288
28616
|
return true;
|
|
28289
28617
|
}
|
|
28290
|
-
const html = (0,
|
|
28618
|
+
const html = (0, import_fs60.readFileSync)(htmlPath, "utf-8");
|
|
28291
28619
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
28292
28620
|
res.end(html);
|
|
28293
28621
|
return true;
|
|
@@ -28313,16 +28641,16 @@ var init_routes = __esm({
|
|
|
28313
28641
|
const ext = "." + (relativePath.split(".").pop() || "");
|
|
28314
28642
|
const mime = MIME[ext];
|
|
28315
28643
|
if (!mime) return false;
|
|
28316
|
-
const filePath = (0,
|
|
28644
|
+
const filePath = (0, import_path63.join)(this.dashboardRoot, relativePath);
|
|
28317
28645
|
try {
|
|
28318
|
-
const realFile = (0,
|
|
28319
|
-
const realBase = (0,
|
|
28646
|
+
const realFile = (0, import_fs60.realpathSync)(filePath);
|
|
28647
|
+
const realBase = (0, import_fs60.realpathSync)(this.dashboardRoot);
|
|
28320
28648
|
if (!realFile.startsWith(realBase + "/")) {
|
|
28321
28649
|
res.writeHead(404);
|
|
28322
28650
|
res.end();
|
|
28323
28651
|
return true;
|
|
28324
28652
|
}
|
|
28325
|
-
const data = (0,
|
|
28653
|
+
const data = (0, import_fs60.readFileSync)(realFile);
|
|
28326
28654
|
res.writeHead(200, { "Content-Type": mime, "Cache-Control": "public, max-age=86400" });
|
|
28327
28655
|
res.end(data);
|
|
28328
28656
|
return true;
|
|
@@ -28337,8 +28665,8 @@ var init_routes = __esm({
|
|
|
28337
28665
|
return match ? match[1] : null;
|
|
28338
28666
|
}
|
|
28339
28667
|
getConsensusReports(page = 1, pageSize = 5) {
|
|
28340
|
-
const { readdirSync: readdirSync18, readFileSync:
|
|
28341
|
-
const reportsDir = (0,
|
|
28668
|
+
const { readdirSync: readdirSync18, readFileSync: readFileSync61, existsSync: existsSync64 } = require("fs");
|
|
28669
|
+
const reportsDir = (0, import_path63.join)(this.projectRoot, ".gossip", "consensus-reports");
|
|
28342
28670
|
let retractedConsensusIds = [];
|
|
28343
28671
|
let roundRetractions = [];
|
|
28344
28672
|
try {
|
|
@@ -28348,13 +28676,13 @@ var init_routes = __esm({
|
|
|
28348
28676
|
roundRetractions = reader.getRoundRetractions();
|
|
28349
28677
|
} catch {
|
|
28350
28678
|
}
|
|
28351
|
-
if (!
|
|
28679
|
+
if (!existsSync64(reportsDir)) return { reports: [], totalReports: 0, page, pageSize, retractedConsensusIds, roundRetractions };
|
|
28352
28680
|
try {
|
|
28353
|
-
const { statSync:
|
|
28681
|
+
const { statSync: statSync24 } = require("fs");
|
|
28354
28682
|
const allFiles = readdirSync18(reportsDir).filter((f) => f.endsWith(".json")).sort((a, b) => {
|
|
28355
28683
|
try {
|
|
28356
|
-
const aTime =
|
|
28357
|
-
const bTime =
|
|
28684
|
+
const aTime = statSync24((0, import_path63.join)(reportsDir, a)).mtimeMs;
|
|
28685
|
+
const bTime = statSync24((0, import_path63.join)(reportsDir, b)).mtimeMs;
|
|
28358
28686
|
return bTime - aTime;
|
|
28359
28687
|
} catch {
|
|
28360
28688
|
return 0;
|
|
@@ -28365,13 +28693,13 @@ var init_routes = __esm({
|
|
|
28365
28693
|
const clampedPage = Math.max(page, 1);
|
|
28366
28694
|
const start = (clampedPage - 1) * clampedPageSize;
|
|
28367
28695
|
const files = allFiles.slice(start, start + clampedPageSize);
|
|
28368
|
-
const realReportsDir = (0,
|
|
28696
|
+
const realReportsDir = (0, import_fs60.realpathSync)(reportsDir);
|
|
28369
28697
|
const reports = files.map((f) => {
|
|
28370
28698
|
try {
|
|
28371
|
-
const filePath = (0,
|
|
28372
|
-
const realFile = (0,
|
|
28699
|
+
const filePath = (0, import_path63.join)(reportsDir, f);
|
|
28700
|
+
const realFile = (0, import_fs60.realpathSync)(filePath);
|
|
28373
28701
|
if (!realFile.startsWith(realReportsDir + "/")) return null;
|
|
28374
|
-
return JSON.parse(
|
|
28702
|
+
return JSON.parse(readFileSync61(realFile, "utf-8"));
|
|
28375
28703
|
} catch {
|
|
28376
28704
|
return null;
|
|
28377
28705
|
}
|
|
@@ -28382,29 +28710,29 @@ var init_routes = __esm({
|
|
|
28382
28710
|
}
|
|
28383
28711
|
}
|
|
28384
28712
|
archiveFindings() {
|
|
28385
|
-
const { readdirSync: readdirSync18, readFileSync:
|
|
28386
|
-
const reportsDir = (0,
|
|
28387
|
-
const archiveDir = (0,
|
|
28713
|
+
const { readdirSync: readdirSync18, readFileSync: readFileSync61, renameSync: renameSync9, writeFileSync: writeFileSync26, mkdirSync: mkdirSync33, existsSync: existsSync64 } = require("fs");
|
|
28714
|
+
const reportsDir = (0, import_path63.join)(this.projectRoot, ".gossip", "consensus-reports");
|
|
28715
|
+
const archiveDir = (0, import_path63.join)(this.projectRoot, ".gossip", "consensus-reports-archive");
|
|
28388
28716
|
let archived = 0;
|
|
28389
|
-
if (
|
|
28717
|
+
if (existsSync64(reportsDir)) {
|
|
28390
28718
|
const files = readdirSync18(reportsDir).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
28391
28719
|
if (files.length > 5) {
|
|
28392
|
-
|
|
28720
|
+
mkdirSync33(archiveDir, { recursive: true });
|
|
28393
28721
|
const toArchive = files.slice(5);
|
|
28394
28722
|
for (const f of toArchive) {
|
|
28395
28723
|
try {
|
|
28396
|
-
|
|
28724
|
+
renameSync9((0, import_path63.join)(reportsDir, f), (0, import_path63.join)(archiveDir, f));
|
|
28397
28725
|
archived++;
|
|
28398
28726
|
} catch {
|
|
28399
28727
|
}
|
|
28400
28728
|
}
|
|
28401
28729
|
}
|
|
28402
28730
|
}
|
|
28403
|
-
const findingsPath = (0,
|
|
28731
|
+
const findingsPath = (0, import_path63.join)(this.projectRoot, ".gossip", "implementation-findings.jsonl");
|
|
28404
28732
|
let findingsCleared = 0;
|
|
28405
|
-
if (
|
|
28733
|
+
if (existsSync64(findingsPath)) {
|
|
28406
28734
|
try {
|
|
28407
|
-
const lines =
|
|
28735
|
+
const lines = readFileSync61(findingsPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
28408
28736
|
const kept = lines.filter((line) => {
|
|
28409
28737
|
try {
|
|
28410
28738
|
const entry = JSON.parse(line);
|
|
@@ -28417,11 +28745,11 @@ var init_routes = __esm({
|
|
|
28417
28745
|
return true;
|
|
28418
28746
|
}
|
|
28419
28747
|
});
|
|
28420
|
-
|
|
28748
|
+
writeFileSync26(findingsPath, kept.join("\n") + (kept.length > 0 ? "\n" : ""));
|
|
28421
28749
|
} catch {
|
|
28422
28750
|
}
|
|
28423
28751
|
}
|
|
28424
|
-
const remaining =
|
|
28752
|
+
const remaining = existsSync64(reportsDir) ? readdirSync18(reportsDir).filter((f) => f.endsWith(".json")).length : 0;
|
|
28425
28753
|
return { archived, remaining, findingsCleared };
|
|
28426
28754
|
}
|
|
28427
28755
|
json(res, status, data) {
|
|
@@ -28434,14 +28762,14 @@ var init_routes = __esm({
|
|
|
28434
28762
|
});
|
|
28435
28763
|
|
|
28436
28764
|
// packages/relay/src/dashboard/ws.ts
|
|
28437
|
-
var import_ws3,
|
|
28765
|
+
var import_ws3, import_fs61, import_fs62, import_path64, DashboardWs;
|
|
28438
28766
|
var init_ws = __esm({
|
|
28439
28767
|
"packages/relay/src/dashboard/ws.ts"() {
|
|
28440
28768
|
"use strict";
|
|
28441
28769
|
import_ws3 = require("ws");
|
|
28442
|
-
|
|
28443
|
-
|
|
28444
|
-
|
|
28770
|
+
import_fs61 = require("fs");
|
|
28771
|
+
import_fs62 = require("fs");
|
|
28772
|
+
import_path64 = require("path");
|
|
28445
28773
|
DashboardWs = class {
|
|
28446
28774
|
clients = /* @__PURE__ */ new Set();
|
|
28447
28775
|
logWatcher = null;
|
|
@@ -28466,15 +28794,15 @@ var init_ws = __esm({
|
|
|
28466
28794
|
/** Start watching mcp.log for new lines and broadcasting them to connected clients. */
|
|
28467
28795
|
startLogWatcher(projectRoot) {
|
|
28468
28796
|
this.stopLogWatcher();
|
|
28469
|
-
this.logPath = (0,
|
|
28470
|
-
if (!(0,
|
|
28797
|
+
this.logPath = (0, import_path64.join)(projectRoot, ".gossip", "mcp.log");
|
|
28798
|
+
if (!(0, import_fs61.existsSync)(this.logPath)) return;
|
|
28471
28799
|
try {
|
|
28472
|
-
this.logOffset = (0,
|
|
28800
|
+
this.logOffset = (0, import_fs61.statSync)(this.logPath).size;
|
|
28473
28801
|
} catch {
|
|
28474
28802
|
this.logOffset = 0;
|
|
28475
28803
|
}
|
|
28476
28804
|
try {
|
|
28477
|
-
this.logWatcher = (0,
|
|
28805
|
+
this.logWatcher = (0, import_fs62.watch)(this.logPath, () => {
|
|
28478
28806
|
if (this.clients.size === 0) return;
|
|
28479
28807
|
this.readNewLines();
|
|
28480
28808
|
});
|
|
@@ -28491,7 +28819,7 @@ var init_ws = __esm({
|
|
|
28491
28819
|
if (this.logReading) return;
|
|
28492
28820
|
this.logReading = true;
|
|
28493
28821
|
try {
|
|
28494
|
-
const currentSize = (0,
|
|
28822
|
+
const currentSize = (0, import_fs61.statSync)(this.logPath).size;
|
|
28495
28823
|
if (currentSize < this.logOffset) {
|
|
28496
28824
|
this.logOffset = 0;
|
|
28497
28825
|
this.logCarry = "";
|
|
@@ -28504,7 +28832,7 @@ var init_ws = __esm({
|
|
|
28504
28832
|
const readFrom = capped ? (this.logCarry = "", this.logCapped = true, currentSize - 65536) : (this.logCapped = false, this.logOffset);
|
|
28505
28833
|
let stream;
|
|
28506
28834
|
try {
|
|
28507
|
-
stream = (0,
|
|
28835
|
+
stream = (0, import_fs61.createReadStream)(this.logPath, { start: readFrom, end: currentSize - 1 });
|
|
28508
28836
|
} catch {
|
|
28509
28837
|
this.logReading = false;
|
|
28510
28838
|
return;
|
|
@@ -29013,14 +29341,14 @@ __export(sandbox_exports, {
|
|
|
29013
29341
|
});
|
|
29014
29342
|
function rotateIfNeeded2(filePath, maxBytes) {
|
|
29015
29343
|
try {
|
|
29016
|
-
const st = (0,
|
|
29344
|
+
const st = (0, import_fs63.statSync)(filePath);
|
|
29017
29345
|
if (st.size < maxBytes) return;
|
|
29018
29346
|
const rotated = filePath + ".1";
|
|
29019
29347
|
try {
|
|
29020
|
-
if ((0,
|
|
29348
|
+
if ((0, import_fs63.existsSync)(rotated)) (0, import_fs63.unlinkSync)(rotated);
|
|
29021
29349
|
} catch {
|
|
29022
29350
|
}
|
|
29023
|
-
(0,
|
|
29351
|
+
(0, import_fs63.renameSync)(filePath, rotated);
|
|
29024
29352
|
} catch {
|
|
29025
29353
|
}
|
|
29026
29354
|
}
|
|
@@ -29093,9 +29421,9 @@ Tests passing is NOT sufficient verification \u2014 the 2026-04-22 incident had
|
|
|
29093
29421
|
}
|
|
29094
29422
|
function readSandboxMode(projectRoot) {
|
|
29095
29423
|
try {
|
|
29096
|
-
const p = (0,
|
|
29097
|
-
if (!(0,
|
|
29098
|
-
const raw = JSON.parse((0,
|
|
29424
|
+
const p = (0, import_path65.join)(projectRoot, ".gossip", "config.json");
|
|
29425
|
+
if (!(0, import_fs63.existsSync)(p)) return "warn";
|
|
29426
|
+
const raw = JSON.parse((0, import_fs63.readFileSync)(p, "utf-8"));
|
|
29099
29427
|
const mode = raw?.sandboxEnforcement;
|
|
29100
29428
|
if (mode === "off" || mode === "warn" || mode === "block") return mode;
|
|
29101
29429
|
return "warn";
|
|
@@ -29105,8 +29433,8 @@ function readSandboxMode(projectRoot) {
|
|
|
29105
29433
|
}
|
|
29106
29434
|
function recordDispatchMetadata(projectRoot, meta3) {
|
|
29107
29435
|
try {
|
|
29108
|
-
const dir = (0,
|
|
29109
|
-
(0,
|
|
29436
|
+
const dir = (0, import_path65.join)(projectRoot, ".gossip");
|
|
29437
|
+
(0, import_fs63.mkdirSync)(dir, { recursive: true });
|
|
29110
29438
|
const snapshotted = { ...meta3 };
|
|
29111
29439
|
if (meta3.writeMode === "scoped" || meta3.writeMode === "worktree") {
|
|
29112
29440
|
try {
|
|
@@ -29124,15 +29452,15 @@ function recordDispatchMetadata(projectRoot, meta3) {
|
|
|
29124
29452
|
} catch {
|
|
29125
29453
|
}
|
|
29126
29454
|
}
|
|
29127
|
-
(0,
|
|
29455
|
+
(0, import_fs63.appendFileSync)((0, import_path65.join)(dir, METADATA_FILE), JSON.stringify(snapshotted) + "\n");
|
|
29128
29456
|
} catch {
|
|
29129
29457
|
}
|
|
29130
29458
|
}
|
|
29131
29459
|
function updateDispatchMetadata(projectRoot, taskId, patch) {
|
|
29132
29460
|
try {
|
|
29133
|
-
const p = (0,
|
|
29134
|
-
if (!(0,
|
|
29135
|
-
const raw = (0,
|
|
29461
|
+
const p = (0, import_path65.join)(projectRoot, ".gossip", METADATA_FILE);
|
|
29462
|
+
if (!(0, import_fs63.existsSync)(p)) return false;
|
|
29463
|
+
const raw = (0, import_fs63.readFileSync)(p, "utf-8");
|
|
29136
29464
|
const lines = raw.split("\n");
|
|
29137
29465
|
let patched = false;
|
|
29138
29466
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -29150,7 +29478,7 @@ function updateDispatchMetadata(projectRoot, taskId, patch) {
|
|
|
29150
29478
|
}
|
|
29151
29479
|
}
|
|
29152
29480
|
if (!patched) return false;
|
|
29153
|
-
(0,
|
|
29481
|
+
(0, import_fs63.writeFileSync)(p, lines.join("\n"));
|
|
29154
29482
|
return true;
|
|
29155
29483
|
} catch {
|
|
29156
29484
|
return false;
|
|
@@ -29159,14 +29487,14 @@ function updateDispatchMetadata(projectRoot, taskId, patch) {
|
|
|
29159
29487
|
function stampTaskSentinel(projectRoot, taskId) {
|
|
29160
29488
|
if (!taskId) return null;
|
|
29161
29489
|
try {
|
|
29162
|
-
const dir = (0,
|
|
29163
|
-
(0,
|
|
29490
|
+
const dir = (0, import_path65.join)(projectRoot, ".gossip", SENTINEL_DIR);
|
|
29491
|
+
(0, import_fs63.mkdirSync)(dir, { recursive: true });
|
|
29164
29492
|
const slug = taskId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
29165
|
-
const path6 = (0,
|
|
29166
|
-
const fd = (0,
|
|
29167
|
-
(0,
|
|
29493
|
+
const path6 = (0, import_path65.join)(dir, `${slug}.sentinel`);
|
|
29494
|
+
const fd = (0, import_fs63.openSync)(path6, "w");
|
|
29495
|
+
(0, import_fs63.closeSync)(fd);
|
|
29168
29496
|
const stampTime = new Date(Date.now() - 2e3);
|
|
29169
|
-
(0,
|
|
29497
|
+
(0, import_fs63.utimesSync)(path6, stampTime, stampTime);
|
|
29170
29498
|
return path6;
|
|
29171
29499
|
} catch {
|
|
29172
29500
|
return null;
|
|
@@ -29175,15 +29503,15 @@ function stampTaskSentinel(projectRoot, taskId) {
|
|
|
29175
29503
|
function cleanupTaskSentinel(sentinelPath) {
|
|
29176
29504
|
if (!sentinelPath) return;
|
|
29177
29505
|
try {
|
|
29178
|
-
(0,
|
|
29506
|
+
(0, import_fs63.unlinkSync)(sentinelPath);
|
|
29179
29507
|
} catch {
|
|
29180
29508
|
}
|
|
29181
29509
|
}
|
|
29182
29510
|
function lookupDispatchMetadata(projectRoot, taskId) {
|
|
29183
29511
|
try {
|
|
29184
|
-
const p = (0,
|
|
29185
|
-
if (!(0,
|
|
29186
|
-
const raw = (0,
|
|
29512
|
+
const p = (0, import_path65.join)(projectRoot, ".gossip", METADATA_FILE);
|
|
29513
|
+
if (!(0, import_fs63.existsSync)(p)) return null;
|
|
29514
|
+
const raw = (0, import_fs63.readFileSync)(p, "utf-8");
|
|
29187
29515
|
const lines = raw.split("\n").filter(Boolean);
|
|
29188
29516
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
29189
29517
|
try {
|
|
@@ -29215,21 +29543,21 @@ function parseGitStatus(porcelain) {
|
|
|
29215
29543
|
function normalizeScope(scope, projectRoot) {
|
|
29216
29544
|
let s = scope.trim();
|
|
29217
29545
|
if (!s) return "";
|
|
29218
|
-
if ((0,
|
|
29219
|
-
s = (0,
|
|
29546
|
+
if ((0, import_path65.isAbsolute)(s)) {
|
|
29547
|
+
s = (0, import_path65.relative)(projectRoot, s);
|
|
29220
29548
|
} else if (s.startsWith("./")) {
|
|
29221
29549
|
s = s.slice(2);
|
|
29222
29550
|
}
|
|
29223
|
-
s = (0,
|
|
29551
|
+
s = (0, import_path65.normalize)(s).replace(/\/+$/, "");
|
|
29224
29552
|
if (s === "." || s === "") return "";
|
|
29225
29553
|
return s;
|
|
29226
29554
|
}
|
|
29227
29555
|
function isInsideScope(filePath, scope) {
|
|
29228
29556
|
if (!scope) return true;
|
|
29229
|
-
const f = (0,
|
|
29557
|
+
const f = (0, import_path65.normalize)(filePath).replace(/^\.\//, "");
|
|
29230
29558
|
const s = scope.replace(/^\.\//, "").replace(/\/+$/, "");
|
|
29231
29559
|
if (f === s) return true;
|
|
29232
|
-
return f.startsWith(s + "/") || f.startsWith(s +
|
|
29560
|
+
return f.startsWith(s + "/") || f.startsWith(s + import_path65.sep);
|
|
29233
29561
|
}
|
|
29234
29562
|
function detectBoundaryEscapes(meta3, modifiedFiles, projectRoot) {
|
|
29235
29563
|
const mode = meta3.writeMode;
|
|
@@ -29290,8 +29618,8 @@ function recordBoundaryEscape(projectRoot, meta3, violations, mode) {
|
|
|
29290
29618
|
} catch {
|
|
29291
29619
|
}
|
|
29292
29620
|
try {
|
|
29293
|
-
const dir = (0,
|
|
29294
|
-
(0,
|
|
29621
|
+
const dir = (0, import_path65.join)(projectRoot, ".gossip");
|
|
29622
|
+
(0, import_fs63.mkdirSync)(dir, { recursive: true });
|
|
29295
29623
|
const line = {
|
|
29296
29624
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29297
29625
|
taskId: meta3.taskId,
|
|
@@ -29302,15 +29630,15 @@ function recordBoundaryEscape(projectRoot, meta3, violations, mode) {
|
|
|
29302
29630
|
action: mode
|
|
29303
29631
|
// "warn" or "block"
|
|
29304
29632
|
};
|
|
29305
|
-
const escapeFile = (0,
|
|
29633
|
+
const escapeFile = (0, import_path65.join)(dir, BOUNDARY_ESCAPE_FILE);
|
|
29306
29634
|
rotateIfNeeded2(escapeFile, MAX_BOUNDARY_ESCAPE_BYTES);
|
|
29307
|
-
(0,
|
|
29635
|
+
(0, import_fs63.appendFileSync)(escapeFile, JSON.stringify(line) + "\n");
|
|
29308
29636
|
} catch {
|
|
29309
29637
|
}
|
|
29310
29638
|
}
|
|
29311
29639
|
function canonicalize(p) {
|
|
29312
29640
|
try {
|
|
29313
|
-
return (0,
|
|
29641
|
+
return (0, import_path65.resolve)(p).replace(/\/+$/, "") || "/";
|
|
29314
29642
|
} catch {
|
|
29315
29643
|
return p.replace(/\/+$/, "") || "/";
|
|
29316
29644
|
}
|
|
@@ -29521,7 +29849,7 @@ function buildAuditExclusions(projectRoot, ownWorktree, scope) {
|
|
|
29521
29849
|
for (const v of expandTmpVariants(wt)) excl.add(v);
|
|
29522
29850
|
}
|
|
29523
29851
|
if (scope) {
|
|
29524
|
-
const s = canonicalize((0,
|
|
29852
|
+
const s = canonicalize((0, import_path65.join)(projectRoot, scope));
|
|
29525
29853
|
for (const v of expandTmpVariants(s)) excl.add(v);
|
|
29526
29854
|
}
|
|
29527
29855
|
return Array.from(excl);
|
|
@@ -29575,12 +29903,12 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
|
|
|
29575
29903
|
return { violations: [], skipped: "win32" };
|
|
29576
29904
|
}
|
|
29577
29905
|
const sentinel = meta3.sentinelPath;
|
|
29578
|
-
if (!sentinel || !(0,
|
|
29906
|
+
if (!sentinel || !(0, import_fs63.existsSync)(sentinel)) {
|
|
29579
29907
|
return { violations: [], skipped: "sentinel missing" };
|
|
29580
29908
|
}
|
|
29581
29909
|
let sentinelMtimeMs = 0;
|
|
29582
29910
|
try {
|
|
29583
|
-
sentinelMtimeMs = (0,
|
|
29911
|
+
sentinelMtimeMs = (0, import_fs63.statSync)(sentinel).mtimeMs;
|
|
29584
29912
|
} catch {
|
|
29585
29913
|
}
|
|
29586
29914
|
if (sentinelMtimeMs === 0) {
|
|
@@ -29592,11 +29920,11 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
|
|
|
29592
29920
|
);
|
|
29593
29921
|
const exclusions = buildAuditExclusions(projectRoot, meta3.worktreePath, options.scope);
|
|
29594
29922
|
const findBin = options.findBinary ?? "find";
|
|
29595
|
-
const sentinelDir = canonicalize((0,
|
|
29923
|
+
const sentinelDir = canonicalize((0, import_path65.join)(projectRoot, ".gossip", SENTINEL_DIR));
|
|
29596
29924
|
const mainSet = /* @__PURE__ */ new Set();
|
|
29597
29925
|
const sensitiveSet = /* @__PURE__ */ new Set();
|
|
29598
29926
|
for (const root of scanRoots) {
|
|
29599
|
-
if (!(0,
|
|
29927
|
+
if (!(0, import_fs63.existsSync)(root)) continue;
|
|
29600
29928
|
const canonRoot = canonicalize(root);
|
|
29601
29929
|
const allExcl = [...exclusions, ...expandTmpVariants(sentinelDir)];
|
|
29602
29930
|
const args = buildFindPruneArgs(canonRoot, allExcl, sentinel);
|
|
@@ -29632,7 +29960,7 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
|
|
|
29632
29960
|
}
|
|
29633
29961
|
const sensitiveTargets = buildSensitiveTargets(platform2);
|
|
29634
29962
|
for (const target of sensitiveTargets) {
|
|
29635
|
-
if (!(0,
|
|
29963
|
+
if (!(0, import_fs63.existsSync)(target.path)) continue;
|
|
29636
29964
|
const canonTarget = canonicalize(target.path);
|
|
29637
29965
|
const args = buildSensitiveFindArgs(
|
|
29638
29966
|
canonTarget,
|
|
@@ -29688,8 +30016,8 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
|
|
|
29688
30016
|
}
|
|
29689
30017
|
function recordLayer3Violations(projectRoot, meta3, violations, source) {
|
|
29690
30018
|
try {
|
|
29691
|
-
const dir = (0,
|
|
29692
|
-
(0,
|
|
30019
|
+
const dir = (0, import_path65.join)(projectRoot, ".gossip");
|
|
30020
|
+
(0, import_fs63.mkdirSync)(dir, { recursive: true });
|
|
29693
30021
|
const ts2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
29694
30022
|
const lines = violations.map(
|
|
29695
30023
|
(path6) => JSON.stringify({
|
|
@@ -29700,9 +30028,9 @@ function recordLayer3Violations(projectRoot, meta3, violations, source) {
|
|
|
29700
30028
|
source
|
|
29701
30029
|
})
|
|
29702
30030
|
);
|
|
29703
|
-
const escapeFile = (0,
|
|
30031
|
+
const escapeFile = (0, import_path65.join)(dir, BOUNDARY_ESCAPE_FILE);
|
|
29704
30032
|
rotateIfNeeded2(escapeFile, MAX_BOUNDARY_ESCAPE_BYTES);
|
|
29705
|
-
(0,
|
|
30033
|
+
(0, import_fs63.appendFileSync)(escapeFile, lines.join("\n") + "\n");
|
|
29706
30034
|
} catch {
|
|
29707
30035
|
}
|
|
29708
30036
|
if (source === "layer3-sensitive" && violations.length > 0) {
|
|
@@ -29759,14 +30087,14 @@ function runLayer3Audit(projectRoot, taskId) {
|
|
|
29759
30087
|
}
|
|
29760
30088
|
return { blockError, warnPrefix };
|
|
29761
30089
|
}
|
|
29762
|
-
var import_child_process8,
|
|
30090
|
+
var import_child_process8, import_fs63, import_os3, import_path65, 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__;
|
|
29763
30091
|
var init_sandbox2 = __esm({
|
|
29764
30092
|
"apps/cli/src/sandbox.ts"() {
|
|
29765
30093
|
"use strict";
|
|
29766
30094
|
import_child_process8 = require("child_process");
|
|
29767
|
-
|
|
30095
|
+
import_fs63 = require("fs");
|
|
29768
30096
|
import_os3 = require("os");
|
|
29769
|
-
|
|
30097
|
+
import_path65 = require("path");
|
|
29770
30098
|
METADATA_FILE = "dispatch-metadata.jsonl";
|
|
29771
30099
|
BOUNDARY_ESCAPE_FILE = "boundary-escapes.jsonl";
|
|
29772
30100
|
SENTINEL_DIR = "sentinels";
|
|
@@ -29825,6 +30153,114 @@ var init_sandbox2 = __esm({
|
|
|
29825
30153
|
}
|
|
29826
30154
|
});
|
|
29827
30155
|
|
|
30156
|
+
// apps/cli/src/handlers/ref-allowlist-detection.ts
|
|
30157
|
+
var ref_allowlist_detection_exports = {};
|
|
30158
|
+
__export(ref_allowlist_detection_exports, {
|
|
30159
|
+
capturePreDispatchSha: () => capturePreDispatchSha,
|
|
30160
|
+
checkRefAllowlistViolation: () => checkRefAllowlistViolation
|
|
30161
|
+
});
|
|
30162
|
+
function capturePreDispatchSha() {
|
|
30163
|
+
try {
|
|
30164
|
+
const sha = (0, import_child_process9.execFileSync)("git", ["rev-parse", "origin/master"], {
|
|
30165
|
+
cwd: process.cwd(),
|
|
30166
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
30167
|
+
}).toString().trim();
|
|
30168
|
+
return sha || null;
|
|
30169
|
+
} catch {
|
|
30170
|
+
process.stderr.write("[gossipcat] ref-allowlist: could not read origin/master SHA (offline or no remote) \u2014 skipping pre-dispatch snapshot\n");
|
|
30171
|
+
return null;
|
|
30172
|
+
}
|
|
30173
|
+
}
|
|
30174
|
+
function getPrMergeCommits(preSha, postSha) {
|
|
30175
|
+
try {
|
|
30176
|
+
const out = (0, import_child_process9.execFileSync)(
|
|
30177
|
+
"git",
|
|
30178
|
+
["log", `${preSha}..${postSha}`, `--grep=(#[0-9]`, "--format=%H %s"],
|
|
30179
|
+
{ cwd: process.cwd(), stdio: ["ignore", "pipe", "ignore"] }
|
|
30180
|
+
).toString().trim();
|
|
30181
|
+
return out ? out.split("\n").filter(Boolean) : [];
|
|
30182
|
+
} catch {
|
|
30183
|
+
return [];
|
|
30184
|
+
}
|
|
30185
|
+
}
|
|
30186
|
+
function getCommitRange(preSha, postSha) {
|
|
30187
|
+
try {
|
|
30188
|
+
const out = (0, import_child_process9.execFileSync)(
|
|
30189
|
+
"git",
|
|
30190
|
+
["log", `${preSha}..${postSha}`, "--format=%H %s"],
|
|
30191
|
+
{ cwd: process.cwd(), stdio: ["ignore", "pipe", "ignore"] }
|
|
30192
|
+
).toString().trim();
|
|
30193
|
+
return out ? out.split("\n").filter(Boolean) : [];
|
|
30194
|
+
} catch {
|
|
30195
|
+
return [];
|
|
30196
|
+
}
|
|
30197
|
+
}
|
|
30198
|
+
function appendViolationRecord(record2) {
|
|
30199
|
+
try {
|
|
30200
|
+
const projectRoot = process.cwd();
|
|
30201
|
+
(0, import_fs64.mkdirSync)((0, import_path66.join)(projectRoot, ".gossip"), { recursive: true });
|
|
30202
|
+
const logPath = (0, import_path66.join)(projectRoot, PROCESS_VIOLATIONS_FILE);
|
|
30203
|
+
(0, import_fs64.appendFileSync)(logPath, JSON.stringify(record2) + "\n", "utf8");
|
|
30204
|
+
} catch (err) {
|
|
30205
|
+
process.stderr.write(`[gossipcat] ref-allowlist: failed to append violation record: ${err.message}
|
|
30206
|
+
`);
|
|
30207
|
+
}
|
|
30208
|
+
}
|
|
30209
|
+
function checkRefAllowlistViolation(taskId, agentId, preSha) {
|
|
30210
|
+
let postSha;
|
|
30211
|
+
try {
|
|
30212
|
+
postSha = (0, import_child_process9.execFileSync)("git", ["rev-parse", "origin/master"], {
|
|
30213
|
+
cwd: process.cwd(),
|
|
30214
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
30215
|
+
}).toString().trim();
|
|
30216
|
+
} catch {
|
|
30217
|
+
return;
|
|
30218
|
+
}
|
|
30219
|
+
if (!postSha || postSha === preSha) return;
|
|
30220
|
+
const mergeCommits = getPrMergeCommits(preSha, postSha);
|
|
30221
|
+
if (mergeCommits.length > 0) return;
|
|
30222
|
+
const allCommits = getCommitRange(preSha, postSha);
|
|
30223
|
+
const detectedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
30224
|
+
appendViolationRecord({ taskId, agentId, preSha, postSha, detectedAt, commits: allCommits });
|
|
30225
|
+
try {
|
|
30226
|
+
const { emitConsensusSignals: emitConsensusSignals2 } = (init_src4(), __toCommonJS(src_exports3));
|
|
30227
|
+
emitConsensusSignals2(process.cwd(), [
|
|
30228
|
+
{
|
|
30229
|
+
type: "consensus",
|
|
30230
|
+
signal: "boundary_escape",
|
|
30231
|
+
agentId,
|
|
30232
|
+
taskId,
|
|
30233
|
+
findingId: `proc:${taskId}:master_push`,
|
|
30234
|
+
category: "process_discipline",
|
|
30235
|
+
severity: "high",
|
|
30236
|
+
evidence: `origin/master moved from ${preSha} to ${postSha} during task ${taskId} without a PR-merge entry \u2014 direct push detected. Commits: ${allCommits.slice(0, 5).join("; ")}`,
|
|
30237
|
+
timestamp: detectedAt
|
|
30238
|
+
}
|
|
30239
|
+
]);
|
|
30240
|
+
} catch (err) {
|
|
30241
|
+
process.stderr.write(`[gossipcat] ref-allowlist: failed to emit boundary_escape signal: ${err.message}
|
|
30242
|
+
`);
|
|
30243
|
+
}
|
|
30244
|
+
process.stderr.write(
|
|
30245
|
+
`
|
|
30246
|
+
REF-ALLOWLIST VIOLATION: ${taskId} agent=${agentId} origin/master moved ${preSha.slice(0, 8)}\u2192${postSha.slice(0, 8)} with no PR merge.
|
|
30247
|
+
Operator confirmation required for revert or retroactive PR.
|
|
30248
|
+
Full audit trail at .gossip/process-violations.jsonl
|
|
30249
|
+
|
|
30250
|
+
`
|
|
30251
|
+
);
|
|
30252
|
+
}
|
|
30253
|
+
var import_fs64, import_path66, import_child_process9, PROCESS_VIOLATIONS_FILE;
|
|
30254
|
+
var init_ref_allowlist_detection = __esm({
|
|
30255
|
+
"apps/cli/src/handlers/ref-allowlist-detection.ts"() {
|
|
30256
|
+
"use strict";
|
|
30257
|
+
import_fs64 = require("fs");
|
|
30258
|
+
import_path66 = require("path");
|
|
30259
|
+
import_child_process9 = require("child_process");
|
|
30260
|
+
PROCESS_VIOLATIONS_FILE = ".gossip/process-violations.jsonl";
|
|
30261
|
+
}
|
|
30262
|
+
});
|
|
30263
|
+
|
|
29828
30264
|
// apps/cli/src/handlers/native-tasks.ts
|
|
29829
30265
|
function pruneExpiredRecentConsensusTaskIds(now = Date.now()) {
|
|
29830
30266
|
try {
|
|
@@ -29904,11 +30340,11 @@ function taskWasInConsensusRound(taskId, agentId, rounds, recentTaskIds, recentA
|
|
|
29904
30340
|
}
|
|
29905
30341
|
function appendRelayWarning(projectRoot, entry) {
|
|
29906
30342
|
try {
|
|
29907
|
-
const { appendFileSync:
|
|
29908
|
-
const { join:
|
|
29909
|
-
const dir =
|
|
29910
|
-
|
|
29911
|
-
|
|
30343
|
+
const { appendFileSync: appendFileSync18, mkdirSync: mkdirSync33 } = require("fs");
|
|
30344
|
+
const { join: join73 } = require("path");
|
|
30345
|
+
const dir = join73(projectRoot, ".gossip");
|
|
30346
|
+
mkdirSync33(dir, { recursive: true });
|
|
30347
|
+
appendFileSync18(join73(dir, RELAY_WARNINGS_FILE), JSON.stringify(entry) + "\n", "utf8");
|
|
29912
30348
|
} catch (err) {
|
|
29913
30349
|
process.stderr.write(`[gossipcat] append relay-warning failed: ${err.message}
|
|
29914
30350
|
`);
|
|
@@ -30224,6 +30660,13 @@ async function handleNativeRelay(task_id, result, error48, agentStartedAt, relay
|
|
|
30224
30660
|
ctx.mainAgent.scopeTracker.release(task_id);
|
|
30225
30661
|
} catch {
|
|
30226
30662
|
}
|
|
30663
|
+
if (taskInfo.writeMode && taskInfo.preDispatchSha) {
|
|
30664
|
+
try {
|
|
30665
|
+
const { checkRefAllowlistViolation: checkRefAllowlistViolation2 } = (init_ref_allowlist_detection(), __toCommonJS(ref_allowlist_detection_exports));
|
|
30666
|
+
checkRefAllowlistViolation2(task_id, taskInfo.agentId, taskInfo.preDispatchSha);
|
|
30667
|
+
} catch {
|
|
30668
|
+
}
|
|
30669
|
+
}
|
|
30227
30670
|
if (error48 && taskInfo.writeMode === "worktree") {
|
|
30228
30671
|
try {
|
|
30229
30672
|
ctx.mainAgent.getWorktreeManager()?.pruneOrphans().catch(() => {
|
|
@@ -30575,12 +31018,12 @@ function startConsensusTimeout(consensusId) {
|
|
|
30575
31018
|
const allEntries = [...snapshot.relayCrossReviewEntries, ...snapshot.nativeCrossReviewEntries];
|
|
30576
31019
|
const report = await engine.synthesizeWithCrossReview(snapshot.allResults, allEntries, consensusId, snapshot.relayCrossReviewSkipped);
|
|
30577
31020
|
try {
|
|
30578
|
-
const { writeFileSync:
|
|
30579
|
-
const { join:
|
|
30580
|
-
const reportsDir =
|
|
30581
|
-
|
|
31021
|
+
const { writeFileSync: writeFileSync26, mkdirSync: mkdirSync33 } = require("fs");
|
|
31022
|
+
const { join: join73 } = require("path");
|
|
31023
|
+
const reportsDir = join73(process.cwd(), ".gossip", "consensus-reports");
|
|
31024
|
+
mkdirSync33(reportsDir, { recursive: true });
|
|
30582
31025
|
const topic = snapshot.allResults?.find((r) => r.task)?.task?.slice(0, 500) || "";
|
|
30583
|
-
|
|
31026
|
+
writeFileSync26(join73(reportsDir, `${consensusId}.json`), JSON.stringify({
|
|
30584
31027
|
id: consensusId,
|
|
30585
31028
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30586
31029
|
topic,
|
|
@@ -30747,13 +31190,13 @@ async function handleRelayCrossReview(consensus_id, agent_id, result) {
|
|
|
30747
31190
|
synthSnapshot.relayCrossReviewSkipped
|
|
30748
31191
|
);
|
|
30749
31192
|
try {
|
|
30750
|
-
const { writeFileSync:
|
|
30751
|
-
const { join:
|
|
30752
|
-
const reportsDir =
|
|
30753
|
-
|
|
30754
|
-
const reportPath =
|
|
31193
|
+
const { writeFileSync: writeFileSync26, mkdirSync: mkdirSync33 } = require("fs");
|
|
31194
|
+
const { join: join73 } = require("path");
|
|
31195
|
+
const reportsDir = join73(process.cwd(), ".gossip", "consensus-reports");
|
|
31196
|
+
mkdirSync33(reportsDir, { recursive: true });
|
|
31197
|
+
const reportPath = join73(reportsDir, `${consensus_id}.json`);
|
|
30755
31198
|
const topic = synthSnapshot.allResults?.find((r) => r.task)?.task?.slice(0, 500) || "";
|
|
30756
|
-
|
|
31199
|
+
writeFileSync26(reportPath, JSON.stringify({
|
|
30757
31200
|
id: consensus_id,
|
|
30758
31201
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30759
31202
|
topic,
|
|
@@ -30796,10 +31239,10 @@ function persistPendingConsensus() {
|
|
|
30796
31239
|
try {
|
|
30797
31240
|
const projectRoot = ctx.mainAgent?.projectRoot;
|
|
30798
31241
|
if (!projectRoot) return;
|
|
30799
|
-
const { writeFileSync:
|
|
30800
|
-
const { join:
|
|
30801
|
-
const dir =
|
|
30802
|
-
|
|
31242
|
+
const { writeFileSync: writeFileSync26, mkdirSync: mkdirSync33 } = require("fs");
|
|
31243
|
+
const { join: join73 } = require("path");
|
|
31244
|
+
const dir = join73(projectRoot, ".gossip");
|
|
31245
|
+
mkdirSync33(dir, { recursive: true });
|
|
30803
31246
|
const rounds = {};
|
|
30804
31247
|
for (const [id, round] of ctx.pendingConsensusRounds) {
|
|
30805
31248
|
rounds[id] = {
|
|
@@ -30824,7 +31267,7 @@ function persistPendingConsensus() {
|
|
|
30824
31267
|
resolutionRoots: round.resolutionRoots ? [...round.resolutionRoots] : void 0
|
|
30825
31268
|
};
|
|
30826
31269
|
}
|
|
30827
|
-
|
|
31270
|
+
writeFileSync26(join73(dir, CONSENSUS_FILE), JSON.stringify(rounds));
|
|
30828
31271
|
} catch (err) {
|
|
30829
31272
|
process.stderr.write(`[gossipcat] persistPendingConsensus failed: ${err.message}
|
|
30830
31273
|
`);
|
|
@@ -30832,11 +31275,11 @@ function persistPendingConsensus() {
|
|
|
30832
31275
|
}
|
|
30833
31276
|
function restorePendingConsensus(projectRoot) {
|
|
30834
31277
|
try {
|
|
30835
|
-
const { existsSync:
|
|
30836
|
-
const { join:
|
|
30837
|
-
const filePath =
|
|
30838
|
-
if (!
|
|
30839
|
-
const raw = JSON.parse(
|
|
31278
|
+
const { existsSync: existsSync64, readFileSync: readFileSync61, unlinkSync: unlinkSync8 } = require("fs");
|
|
31279
|
+
const { join: join73 } = require("path");
|
|
31280
|
+
const filePath = join73(projectRoot, ".gossip", CONSENSUS_FILE);
|
|
31281
|
+
if (!existsSync64(filePath)) return;
|
|
31282
|
+
const raw = JSON.parse(readFileSync61(filePath, "utf-8"));
|
|
30840
31283
|
const now = Date.now();
|
|
30841
31284
|
for (const [id, data] of Object.entries(raw)) {
|
|
30842
31285
|
if (now > data.deadline + 3e5) {
|
|
@@ -30867,7 +31310,7 @@ function restorePendingConsensus(projectRoot) {
|
|
|
30867
31310
|
process.stderr.write(`[gossipcat] Restored consensus round ${id} \u2014 ${data.pendingNativeAgents?.length ?? 0} agents pending
|
|
30868
31311
|
`);
|
|
30869
31312
|
}
|
|
30870
|
-
|
|
31313
|
+
unlinkSync8(filePath);
|
|
30871
31314
|
} catch {
|
|
30872
31315
|
}
|
|
30873
31316
|
}
|
|
@@ -30881,6 +31324,178 @@ var init_relay_cross_review = __esm({
|
|
|
30881
31324
|
}
|
|
30882
31325
|
});
|
|
30883
31326
|
|
|
31327
|
+
// apps/cli/src/lifecycle-tasks.ts
|
|
31328
|
+
var lifecycle_tasks_exports = {};
|
|
31329
|
+
__export(lifecycle_tasks_exports, {
|
|
31330
|
+
__resetLifecycleTasksForTests: () => __resetLifecycleTasksForTests,
|
|
31331
|
+
drainLifecycleTasks: () => drainLifecycleTasks,
|
|
31332
|
+
installLifecycleDrainHandlers: () => installLifecycleDrainHandlers,
|
|
31333
|
+
trackLifecycleTask: () => trackLifecycleTask
|
|
31334
|
+
});
|
|
31335
|
+
function trackLifecycleTask(p) {
|
|
31336
|
+
inFlight.add(p);
|
|
31337
|
+
p.finally(() => {
|
|
31338
|
+
inFlight.delete(p);
|
|
31339
|
+
}).catch(() => {
|
|
31340
|
+
});
|
|
31341
|
+
}
|
|
31342
|
+
function drainLifecycleTasks(maxMs = 8e3) {
|
|
31343
|
+
if (inFlight.size === 0) return Promise.resolve();
|
|
31344
|
+
const snapshot = [...inFlight];
|
|
31345
|
+
return Promise.race([
|
|
31346
|
+
Promise.allSettled(snapshot).then(() => void 0),
|
|
31347
|
+
new Promise((resolve28) => setTimeout(resolve28, maxMs).unref?.())
|
|
31348
|
+
]).then(() => void 0);
|
|
31349
|
+
}
|
|
31350
|
+
function installLifecycleDrainHandlers() {
|
|
31351
|
+
if (__installed) return;
|
|
31352
|
+
__installed = true;
|
|
31353
|
+
const drainAndContinue = async (signal) => {
|
|
31354
|
+
try {
|
|
31355
|
+
const pending = inFlight.size;
|
|
31356
|
+
if (pending > 0) {
|
|
31357
|
+
process.stderr.write(`[gossipcat] ${signal}: draining ${pending} lifecycle task(s)
|
|
31358
|
+
`);
|
|
31359
|
+
}
|
|
31360
|
+
await drainLifecycleTasks();
|
|
31361
|
+
} catch {
|
|
31362
|
+
}
|
|
31363
|
+
};
|
|
31364
|
+
process.on("beforeExit", () => {
|
|
31365
|
+
void drainAndContinue("beforeExit");
|
|
31366
|
+
});
|
|
31367
|
+
}
|
|
31368
|
+
function __resetLifecycleTasksForTests() {
|
|
31369
|
+
if (process.env.NODE_ENV !== "test") {
|
|
31370
|
+
throw new Error("__resetLifecycleTasksForTests is test-only \u2014 refusing to run outside NODE_ENV=test");
|
|
31371
|
+
}
|
|
31372
|
+
inFlight.clear();
|
|
31373
|
+
__installed = false;
|
|
31374
|
+
}
|
|
31375
|
+
var inFlight, __installed;
|
|
31376
|
+
var init_lifecycle_tasks = __esm({
|
|
31377
|
+
"apps/cli/src/lifecycle-tasks.ts"() {
|
|
31378
|
+
"use strict";
|
|
31379
|
+
inFlight = /* @__PURE__ */ new Set();
|
|
31380
|
+
__installed = false;
|
|
31381
|
+
}
|
|
31382
|
+
});
|
|
31383
|
+
|
|
31384
|
+
// apps/cli/src/handlers/check-effectiveness-runner.ts
|
|
31385
|
+
var check_effectiveness_runner_exports = {};
|
|
31386
|
+
__export(check_effectiveness_runner_exports, {
|
|
31387
|
+
runCheckEffectivenessForAllSkills: () => runCheckEffectivenessForAllSkills
|
|
31388
|
+
});
|
|
31389
|
+
function writeHealthAtomic(projectRoot, record2) {
|
|
31390
|
+
const dir = (0, import_path68.join)(projectRoot, ".gossip");
|
|
31391
|
+
const finalPath = (0, import_path68.join)(dir, "skill-runner-health.json");
|
|
31392
|
+
const tmpPath = finalPath + ".tmp";
|
|
31393
|
+
try {
|
|
31394
|
+
(0, import_fs66.mkdirSync)(dir, { recursive: true });
|
|
31395
|
+
(0, import_fs66.writeFileSync)(tmpPath, JSON.stringify(record2, null, 2));
|
|
31396
|
+
(0, import_fs66.renameSync)(tmpPath, finalPath);
|
|
31397
|
+
} catch (e) {
|
|
31398
|
+
process.stderr.write(`[gossipcat] checkEffectiveness: health write failed: ${e.message}
|
|
31399
|
+
`);
|
|
31400
|
+
try {
|
|
31401
|
+
if ((0, import_fs66.existsSync)(tmpPath)) (0, import_fs66.unlinkSync)(tmpPath);
|
|
31402
|
+
} catch {
|
|
31403
|
+
}
|
|
31404
|
+
}
|
|
31405
|
+
}
|
|
31406
|
+
async function runCheckEffectivenessForAllSkills(opts) {
|
|
31407
|
+
const startedAt = Date.now();
|
|
31408
|
+
const baseDir = (0, import_path68.join)(opts.projectRoot, ".gossip", "agents");
|
|
31409
|
+
let agentDirs = [];
|
|
31410
|
+
let canonicalBaseDir;
|
|
31411
|
+
if ((0, import_fs66.existsSync)(baseDir)) {
|
|
31412
|
+
try {
|
|
31413
|
+
canonicalBaseDir = (0, import_fs66.realpathSync)(baseDir);
|
|
31414
|
+
agentDirs = (0, import_fs66.readdirSync)(canonicalBaseDir);
|
|
31415
|
+
} catch {
|
|
31416
|
+
}
|
|
31417
|
+
}
|
|
31418
|
+
process.stderr.write(`[gossipcat] checkEffectiveness: scanning across ${agentDirs.length} agents
|
|
31419
|
+
`);
|
|
31420
|
+
let skillsChecked = 0;
|
|
31421
|
+
const transitions = {
|
|
31422
|
+
passed: 0,
|
|
31423
|
+
failed: 0,
|
|
31424
|
+
flagged_for_manual_review: 0,
|
|
31425
|
+
inconclusive: 0,
|
|
31426
|
+
pending: 0
|
|
31427
|
+
};
|
|
31428
|
+
let lastError = null;
|
|
31429
|
+
if (canonicalBaseDir && agentDirs.length > 0) {
|
|
31430
|
+
for (const agentId of agentDirs) {
|
|
31431
|
+
if (agentId.startsWith("_")) continue;
|
|
31432
|
+
if (!SAFE_NAME2.test(agentId)) continue;
|
|
31433
|
+
const skillsDir = (0, import_path68.join)(canonicalBaseDir, agentId, "skills");
|
|
31434
|
+
if (!(0, import_fs66.existsSync)(skillsDir)) continue;
|
|
31435
|
+
let canonicalSkillsDir;
|
|
31436
|
+
try {
|
|
31437
|
+
canonicalSkillsDir = (0, import_fs66.realpathSync)(skillsDir);
|
|
31438
|
+
} catch {
|
|
31439
|
+
continue;
|
|
31440
|
+
}
|
|
31441
|
+
if (!canonicalSkillsDir.startsWith(canonicalBaseDir + "/")) {
|
|
31442
|
+
process.stderr.write(`[gossipcat] checkEffectiveness: skipping ${agentId} \u2014 skillsDir resolved outside agents tree (canonical=${canonicalSkillsDir})
|
|
31443
|
+
`);
|
|
31444
|
+
continue;
|
|
31445
|
+
}
|
|
31446
|
+
const role = opts.registryGet(agentId)?.role;
|
|
31447
|
+
if (role === "implementer") continue;
|
|
31448
|
+
const files = (0, import_fs66.readdirSync)(canonicalSkillsDir).filter((f) => f.endsWith(".md"));
|
|
31449
|
+
for (const file2 of files) {
|
|
31450
|
+
const category = file2.replace(/\.md$/, "");
|
|
31451
|
+
if (!SAFE_NAME2.test(category)) continue;
|
|
31452
|
+
skillsChecked++;
|
|
31453
|
+
try {
|
|
31454
|
+
const verdict = await opts.skillEngine.checkEffectiveness(agentId, category, { role });
|
|
31455
|
+
if (verdict.shouldUpdate) {
|
|
31456
|
+
const loggedStates = /* @__PURE__ */ new Set(["passed", "failed", "flagged_for_manual_review"]);
|
|
31457
|
+
if (loggedStates.has(verdict.status)) {
|
|
31458
|
+
process.stderr.write(
|
|
31459
|
+
`[gossipcat] checkEffectiveness ${agentId}/${category}: ${verdict.status}` + (verdict.effectiveness !== void 0 ? ` (\u0394=${verdict.effectiveness.toFixed(3)})` : "") + `
|
|
31460
|
+
`
|
|
31461
|
+
);
|
|
31462
|
+
}
|
|
31463
|
+
if (transitions[verdict.status] != null) {
|
|
31464
|
+
transitions[verdict.status]++;
|
|
31465
|
+
}
|
|
31466
|
+
}
|
|
31467
|
+
} catch (e) {
|
|
31468
|
+
lastError = e.message;
|
|
31469
|
+
process.stderr.write(`[gossipcat] checkEffectiveness ${agentId}/${category} threw: ${lastError}
|
|
31470
|
+
`);
|
|
31471
|
+
}
|
|
31472
|
+
}
|
|
31473
|
+
}
|
|
31474
|
+
}
|
|
31475
|
+
const totalTransitions = transitions.passed + transitions.failed + transitions.flagged_for_manual_review + transitions.inconclusive + transitions.pending;
|
|
31476
|
+
const durationMs = Date.now() - startedAt;
|
|
31477
|
+
process.stderr.write(
|
|
31478
|
+
`[gossipcat] checkEffectiveness: done in ${durationMs}ms (skills: ${skillsChecked}, transitions: ${totalTransitions})
|
|
31479
|
+
`
|
|
31480
|
+
);
|
|
31481
|
+
writeHealthAtomic(opts.projectRoot, {
|
|
31482
|
+
last_run_at: new Date(startedAt).toISOString(),
|
|
31483
|
+
last_run_duration_ms: durationMs,
|
|
31484
|
+
skills_evaluated: skillsChecked,
|
|
31485
|
+
transitions,
|
|
31486
|
+
last_error: lastError
|
|
31487
|
+
});
|
|
31488
|
+
}
|
|
31489
|
+
var import_fs66, import_path68, SAFE_NAME2;
|
|
31490
|
+
var init_check_effectiveness_runner = __esm({
|
|
31491
|
+
"apps/cli/src/handlers/check-effectiveness-runner.ts"() {
|
|
31492
|
+
"use strict";
|
|
31493
|
+
import_fs66 = require("fs");
|
|
31494
|
+
import_path68 = require("path");
|
|
31495
|
+
SAFE_NAME2 = /^(?!.*\.\.)[a-zA-Z0-9._-]+$/;
|
|
31496
|
+
}
|
|
31497
|
+
});
|
|
31498
|
+
|
|
30884
31499
|
// apps/cli/src/config.ts
|
|
30885
31500
|
var config_exports = {};
|
|
30886
31501
|
__export(config_exports, {
|
|
@@ -30897,18 +31512,18 @@ __export(config_exports, {
|
|
|
30897
31512
|
function findConfigPath(projectRoot) {
|
|
30898
31513
|
const root = projectRoot || process.cwd();
|
|
30899
31514
|
const candidates = [
|
|
30900
|
-
(0,
|
|
30901
|
-
(0,
|
|
30902
|
-
(0,
|
|
30903
|
-
(0,
|
|
31515
|
+
(0, import_path69.resolve)(root, ".gossip", "config.json"),
|
|
31516
|
+
(0, import_path69.resolve)(root, "gossip.agents.json"),
|
|
31517
|
+
(0, import_path69.resolve)(root, "gossip.agents.yaml"),
|
|
31518
|
+
(0, import_path69.resolve)(root, "gossip.agents.yml")
|
|
30904
31519
|
];
|
|
30905
31520
|
for (const p of candidates) {
|
|
30906
|
-
if ((0,
|
|
31521
|
+
if ((0, import_fs67.existsSync)(p)) return p;
|
|
30907
31522
|
}
|
|
30908
31523
|
return null;
|
|
30909
31524
|
}
|
|
30910
31525
|
function loadConfig(configPath) {
|
|
30911
|
-
const raw = (0,
|
|
31526
|
+
const raw = (0, import_fs67.readFileSync)(configPath, "utf-8");
|
|
30912
31527
|
let parsed;
|
|
30913
31528
|
try {
|
|
30914
31529
|
parsed = JSON.parse(raw);
|
|
@@ -30998,19 +31613,19 @@ function configToAgentConfigs(config2) {
|
|
|
30998
31613
|
}
|
|
30999
31614
|
function loadClaudeSubagents(projectRoot, existingIds) {
|
|
31000
31615
|
const root = projectRoot || process.cwd();
|
|
31001
|
-
const agentsDir = (0,
|
|
31002
|
-
if (!(0,
|
|
31616
|
+
const agentsDir = (0, import_path69.join)(root, ".claude", "agents");
|
|
31617
|
+
if (!(0, import_fs67.existsSync)(agentsDir)) return [];
|
|
31003
31618
|
let files;
|
|
31004
31619
|
try {
|
|
31005
|
-
files = (0,
|
|
31620
|
+
files = (0, import_fs67.readdirSync)(agentsDir).filter((f) => f.endsWith(".md"));
|
|
31006
31621
|
} catch {
|
|
31007
31622
|
return [];
|
|
31008
31623
|
}
|
|
31009
31624
|
const agents = [];
|
|
31010
31625
|
for (const file2 of files) {
|
|
31011
|
-
const filePath = (0,
|
|
31626
|
+
const filePath = (0, import_path69.join)(agentsDir, file2);
|
|
31012
31627
|
try {
|
|
31013
|
-
const content = (0,
|
|
31628
|
+
const content = (0, import_fs67.readFileSync)(filePath, "utf-8");
|
|
31014
31629
|
const frontmatter = content.match(/^---\n([\s\S]*?)\n---/);
|
|
31015
31630
|
if (!frontmatter) continue;
|
|
31016
31631
|
const fm = frontmatter[1];
|
|
@@ -31065,12 +31680,12 @@ function inferSkills(description, name) {
|
|
|
31065
31680
|
if (skills.length === 0) skills.push("general");
|
|
31066
31681
|
return skills;
|
|
31067
31682
|
}
|
|
31068
|
-
var
|
|
31683
|
+
var import_fs67, import_path69, VALID_PROVIDERS, VALID_MAIN_PROVIDERS, CLAUDE_MODEL_MAP;
|
|
31069
31684
|
var init_config = __esm({
|
|
31070
31685
|
"apps/cli/src/config.ts"() {
|
|
31071
31686
|
"use strict";
|
|
31072
|
-
|
|
31073
|
-
|
|
31687
|
+
import_fs67 = require("fs");
|
|
31688
|
+
import_path69 = require("path");
|
|
31074
31689
|
VALID_PROVIDERS = ["anthropic", "openai", "openclaw", "google", "local", "native", "none"];
|
|
31075
31690
|
VALID_MAIN_PROVIDERS = VALID_PROVIDERS.filter((p) => p !== "native");
|
|
31076
31691
|
CLAUDE_MODEL_MAP = {
|
|
@@ -31088,86 +31703,38 @@ __export(skill_develop_audit_exports, {
|
|
|
31088
31703
|
});
|
|
31089
31704
|
function appendSkillDevelopAudit(entry) {
|
|
31090
31705
|
try {
|
|
31091
|
-
const gossipDir2 = (0,
|
|
31092
|
-
(0,
|
|
31706
|
+
const gossipDir2 = (0, import_path70.join)(process.cwd(), ".gossip");
|
|
31707
|
+
(0, import_fs68.mkdirSync)(gossipDir2, { recursive: true });
|
|
31093
31708
|
const line = JSON.stringify(entry) + "\n";
|
|
31094
|
-
(0,
|
|
31095
|
-
(0,
|
|
31709
|
+
(0, import_fs68.appendFileSync)((0, import_path70.join)(gossipDir2, AUDIT_FILE), line);
|
|
31710
|
+
(0, import_fs68.appendFileSync)((0, import_path70.join)(gossipDir2, LEGACY_FILE), line);
|
|
31096
31711
|
} catch {
|
|
31097
31712
|
}
|
|
31098
31713
|
}
|
|
31099
|
-
var
|
|
31714
|
+
var import_fs68, import_path70, AUDIT_FILE, LEGACY_FILE;
|
|
31100
31715
|
var init_skill_develop_audit = __esm({
|
|
31101
31716
|
"apps/cli/src/handlers/skill-develop-audit.ts"() {
|
|
31102
31717
|
"use strict";
|
|
31103
|
-
|
|
31104
|
-
|
|
31718
|
+
import_fs68 = require("fs");
|
|
31719
|
+
import_path70 = require("path");
|
|
31105
31720
|
AUDIT_FILE = "skill-develop-audit.jsonl";
|
|
31106
31721
|
LEGACY_FILE = "forced-skill-develops.jsonl";
|
|
31107
31722
|
}
|
|
31108
31723
|
});
|
|
31109
31724
|
|
|
31110
|
-
// apps/cli/src/handlers/check-effectiveness-runner.ts
|
|
31111
|
-
var check_effectiveness_runner_exports = {};
|
|
31112
|
-
__export(check_effectiveness_runner_exports, {
|
|
31113
|
-
runCheckEffectivenessForAllSkills: () => runCheckEffectivenessForAllSkills
|
|
31114
|
-
});
|
|
31115
|
-
async function runCheckEffectivenessForAllSkills(opts) {
|
|
31116
|
-
const baseDir = (0, import_path67.join)(opts.projectRoot, ".gossip", "agents");
|
|
31117
|
-
if (!(0, import_fs65.existsSync)(baseDir)) return;
|
|
31118
|
-
const agentDirs = (0, import_fs65.readdirSync)(baseDir);
|
|
31119
|
-
for (const agentId of agentDirs) {
|
|
31120
|
-
if (agentId.startsWith("_")) continue;
|
|
31121
|
-
if (!SAFE_NAME2.test(agentId)) continue;
|
|
31122
|
-
const skillsDir = (0, import_path67.join)(baseDir, agentId, "skills");
|
|
31123
|
-
if (!(0, import_fs65.existsSync)(skillsDir)) continue;
|
|
31124
|
-
const role = opts.registryGet(agentId)?.role;
|
|
31125
|
-
if (role === "implementer") continue;
|
|
31126
|
-
const files = (0, import_fs65.readdirSync)(skillsDir).filter((f) => f.endsWith(".md"));
|
|
31127
|
-
for (const file2 of files) {
|
|
31128
|
-
const category = file2.replace(/\.md$/, "");
|
|
31129
|
-
if (!SAFE_NAME2.test(category)) continue;
|
|
31130
|
-
try {
|
|
31131
|
-
const verdict = await opts.skillEngine.checkEffectiveness(agentId, category, { role });
|
|
31132
|
-
if (verdict.shouldUpdate) {
|
|
31133
|
-
const loggedStates = /* @__PURE__ */ new Set(["passed", "failed", "flagged_for_manual_review"]);
|
|
31134
|
-
if (loggedStates.has(verdict.status)) {
|
|
31135
|
-
process.stderr.write(
|
|
31136
|
-
`[gossipcat] checkEffectiveness ${agentId}/${category}: ${verdict.status}` + (verdict.effectiveness !== void 0 ? ` (\u0394=${verdict.effectiveness.toFixed(3)})` : "") + `
|
|
31137
|
-
`
|
|
31138
|
-
);
|
|
31139
|
-
}
|
|
31140
|
-
}
|
|
31141
|
-
} catch (e) {
|
|
31142
|
-
process.stderr.write(`[gossipcat] checkEffectiveness ${agentId}/${category} threw: ${e.message}
|
|
31143
|
-
`);
|
|
31144
|
-
}
|
|
31145
|
-
}
|
|
31146
|
-
}
|
|
31147
|
-
}
|
|
31148
|
-
var import_fs65, import_path67, SAFE_NAME2;
|
|
31149
|
-
var init_check_effectiveness_runner = __esm({
|
|
31150
|
-
"apps/cli/src/handlers/check-effectiveness-runner.ts"() {
|
|
31151
|
-
"use strict";
|
|
31152
|
-
import_fs65 = require("fs");
|
|
31153
|
-
import_path67 = require("path");
|
|
31154
|
-
SAFE_NAME2 = /^(?!.*\.\.)[a-zA-Z0-9._-]+$/;
|
|
31155
|
-
}
|
|
31156
|
-
});
|
|
31157
|
-
|
|
31158
31725
|
// apps/cli/src/keychain.ts
|
|
31159
31726
|
var keychain_exports = {};
|
|
31160
31727
|
__export(keychain_exports, {
|
|
31161
31728
|
Keychain: () => Keychain
|
|
31162
31729
|
});
|
|
31163
|
-
var
|
|
31730
|
+
var import_child_process10, import_os4, import_fs72, import_path74, import_crypto25, DEFAULT_SERVICE_NAME, VALID_PROVIDERS2, ENCRYPTED_FILE, ALGO, Keychain;
|
|
31164
31731
|
var init_keychain = __esm({
|
|
31165
31732
|
"apps/cli/src/keychain.ts"() {
|
|
31166
31733
|
"use strict";
|
|
31167
|
-
|
|
31734
|
+
import_child_process10 = require("child_process");
|
|
31168
31735
|
import_os4 = require("os");
|
|
31169
|
-
|
|
31170
|
-
|
|
31736
|
+
import_fs72 = require("fs");
|
|
31737
|
+
import_path74 = require("path");
|
|
31171
31738
|
import_crypto25 = require("crypto");
|
|
31172
31739
|
DEFAULT_SERVICE_NAME = "gossip-mesh";
|
|
31173
31740
|
VALID_PROVIDERS2 = /^[a-zA-Z0-9_-]{1,32}$/;
|
|
@@ -31211,10 +31778,10 @@ var init_keychain = __esm({
|
|
|
31211
31778
|
return (0, import_crypto25.pbkdf2Sync)(seed, salt, 6e5, 32, "sha256");
|
|
31212
31779
|
}
|
|
31213
31780
|
loadEncryptedFile() {
|
|
31214
|
-
const filePath = (0,
|
|
31215
|
-
if (!(0,
|
|
31781
|
+
const filePath = (0, import_path74.join)(process.cwd(), ENCRYPTED_FILE);
|
|
31782
|
+
if (!(0, import_fs72.existsSync)(filePath)) return;
|
|
31216
31783
|
try {
|
|
31217
|
-
const raw = (0,
|
|
31784
|
+
const raw = (0, import_fs72.readFileSync)(filePath);
|
|
31218
31785
|
if (raw.length < 61) return;
|
|
31219
31786
|
const salt = raw.subarray(0, 32);
|
|
31220
31787
|
const iv = raw.subarray(32, 44);
|
|
@@ -31232,9 +31799,9 @@ var init_keychain = __esm({
|
|
|
31232
31799
|
}
|
|
31233
31800
|
}
|
|
31234
31801
|
saveEncryptedFile() {
|
|
31235
|
-
const filePath = (0,
|
|
31236
|
-
const dir = (0,
|
|
31237
|
-
if (!(0,
|
|
31802
|
+
const filePath = (0, import_path74.join)(process.cwd(), ENCRYPTED_FILE);
|
|
31803
|
+
const dir = (0, import_path74.join)(process.cwd(), ".gossip");
|
|
31804
|
+
if (!(0, import_fs72.existsSync)(dir)) (0, import_fs72.mkdirSync)(dir, { recursive: true });
|
|
31238
31805
|
const data = JSON.stringify(Object.fromEntries(this.inMemoryStore));
|
|
31239
31806
|
const salt = (0, import_crypto25.randomBytes)(32);
|
|
31240
31807
|
const iv = (0, import_crypto25.randomBytes)(12);
|
|
@@ -31242,12 +31809,12 @@ var init_keychain = __esm({
|
|
|
31242
31809
|
const cipher = (0, import_crypto25.createCipheriv)(ALGO, key, iv);
|
|
31243
31810
|
const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
|
|
31244
31811
|
const tag = cipher.getAuthTag();
|
|
31245
|
-
(0,
|
|
31812
|
+
(0, import_fs72.writeFileSync)(filePath, Buffer.concat([salt, iv, tag, encrypted]), { mode: 384 });
|
|
31246
31813
|
}
|
|
31247
31814
|
isKeychainAvailable() {
|
|
31248
31815
|
if ((0, import_os4.platform)() === "darwin") {
|
|
31249
31816
|
try {
|
|
31250
|
-
(0,
|
|
31817
|
+
(0, import_child_process10.execFileSync)("security", ["help"], { stdio: "pipe" });
|
|
31251
31818
|
return true;
|
|
31252
31819
|
} catch {
|
|
31253
31820
|
return false;
|
|
@@ -31255,7 +31822,7 @@ var init_keychain = __esm({
|
|
|
31255
31822
|
}
|
|
31256
31823
|
if ((0, import_os4.platform)() === "linux") {
|
|
31257
31824
|
try {
|
|
31258
|
-
(0,
|
|
31825
|
+
(0, import_child_process10.execFileSync)("which", ["secret-tool"], { stdio: "pipe" });
|
|
31259
31826
|
return true;
|
|
31260
31827
|
} catch {
|
|
31261
31828
|
return false;
|
|
@@ -31271,7 +31838,7 @@ var init_keychain = __esm({
|
|
|
31271
31838
|
readFromKeychain(provider) {
|
|
31272
31839
|
this.validateProvider(provider);
|
|
31273
31840
|
if ((0, import_os4.platform)() === "darwin") {
|
|
31274
|
-
return (0,
|
|
31841
|
+
return (0, import_child_process10.execFileSync)("security", [
|
|
31275
31842
|
"find-generic-password",
|
|
31276
31843
|
"-s",
|
|
31277
31844
|
this.serviceName,
|
|
@@ -31281,7 +31848,7 @@ var init_keychain = __esm({
|
|
|
31281
31848
|
], { stdio: "pipe" }).toString().trim();
|
|
31282
31849
|
}
|
|
31283
31850
|
if ((0, import_os4.platform)() === "linux") {
|
|
31284
|
-
return (0,
|
|
31851
|
+
return (0, import_child_process10.execFileSync)("secret-tool", [
|
|
31285
31852
|
"lookup",
|
|
31286
31853
|
"service",
|
|
31287
31854
|
this.serviceName,
|
|
@@ -31295,7 +31862,7 @@ var init_keychain = __esm({
|
|
|
31295
31862
|
this.validateProvider(provider);
|
|
31296
31863
|
if ((0, import_os4.platform)() === "darwin") {
|
|
31297
31864
|
try {
|
|
31298
|
-
(0,
|
|
31865
|
+
(0, import_child_process10.execFileSync)("security", [
|
|
31299
31866
|
"delete-generic-password",
|
|
31300
31867
|
"-s",
|
|
31301
31868
|
this.serviceName,
|
|
@@ -31304,7 +31871,7 @@ var init_keychain = __esm({
|
|
|
31304
31871
|
], { stdio: "pipe" });
|
|
31305
31872
|
} catch {
|
|
31306
31873
|
}
|
|
31307
|
-
(0,
|
|
31874
|
+
(0, import_child_process10.execFileSync)("security", [
|
|
31308
31875
|
"add-generic-password",
|
|
31309
31876
|
"-s",
|
|
31310
31877
|
this.serviceName,
|
|
@@ -31316,7 +31883,7 @@ var init_keychain = __esm({
|
|
|
31316
31883
|
return;
|
|
31317
31884
|
}
|
|
31318
31885
|
if ((0, import_os4.platform)() === "linux") {
|
|
31319
|
-
(0,
|
|
31886
|
+
(0, import_child_process10.execFileSync)("secret-tool", [
|
|
31320
31887
|
"store",
|
|
31321
31888
|
"--label",
|
|
31322
31889
|
`Gossip Mesh ${provider}`,
|
|
@@ -31342,23 +31909,23 @@ __export(identity_exports, {
|
|
|
31342
31909
|
normalizeGitUrl: () => normalizeGitUrl
|
|
31343
31910
|
});
|
|
31344
31911
|
function getOrCreateSalt(projectRoot) {
|
|
31345
|
-
const saltPath = (0,
|
|
31912
|
+
const saltPath = (0, import_path75.join)(projectRoot, ".gossip", "local-salt");
|
|
31346
31913
|
try {
|
|
31347
|
-
return (0,
|
|
31914
|
+
return (0, import_fs73.readFileSync)(saltPath, "utf-8").trim();
|
|
31348
31915
|
} catch {
|
|
31349
31916
|
const salt = (0, import_crypto26.randomBytes)(16).toString("hex");
|
|
31350
|
-
(0,
|
|
31917
|
+
(0, import_fs73.mkdirSync)((0, import_path75.join)(projectRoot, ".gossip"), { recursive: true });
|
|
31351
31918
|
try {
|
|
31352
|
-
(0,
|
|
31919
|
+
(0, import_fs73.writeFileSync)(saltPath, salt, { flag: "wx" });
|
|
31353
31920
|
return salt;
|
|
31354
31921
|
} catch {
|
|
31355
|
-
return (0,
|
|
31922
|
+
return (0, import_fs73.readFileSync)(saltPath, "utf-8").trim();
|
|
31356
31923
|
}
|
|
31357
31924
|
}
|
|
31358
31925
|
}
|
|
31359
31926
|
function getUserId(projectRoot) {
|
|
31360
31927
|
try {
|
|
31361
|
-
const email3 = (0,
|
|
31928
|
+
const email3 = (0, import_child_process11.execFileSync)("git", ["config", "user.email"], { stdio: "pipe" }).toString().trim();
|
|
31362
31929
|
const salt = getOrCreateSalt(projectRoot);
|
|
31363
31930
|
return (0, import_crypto26.createHash)("sha256").update(email3 + projectRoot + salt).digest("hex").slice(0, 16);
|
|
31364
31931
|
} catch {
|
|
@@ -31381,7 +31948,7 @@ function getTeamUserId(email3, teamSalt) {
|
|
|
31381
31948
|
}
|
|
31382
31949
|
function getGitEmail() {
|
|
31383
31950
|
try {
|
|
31384
|
-
const email3 = (0,
|
|
31951
|
+
const email3 = (0, import_child_process11.execFileSync)("git", ["config", "user.email"], { stdio: "pipe" }).toString().trim();
|
|
31385
31952
|
return email3 || null;
|
|
31386
31953
|
} catch {
|
|
31387
31954
|
return null;
|
|
@@ -31389,7 +31956,7 @@ function getGitEmail() {
|
|
|
31389
31956
|
}
|
|
31390
31957
|
function getProjectId(projectRoot) {
|
|
31391
31958
|
try {
|
|
31392
|
-
const remoteUrl = (0,
|
|
31959
|
+
const remoteUrl = (0, import_child_process11.execFileSync)(
|
|
31393
31960
|
"git",
|
|
31394
31961
|
["config", "--get", "remote.origin.url"],
|
|
31395
31962
|
{ cwd: projectRoot, stdio: "pipe" }
|
|
@@ -31402,14 +31969,14 @@ function getProjectId(projectRoot) {
|
|
|
31402
31969
|
}
|
|
31403
31970
|
return (0, import_crypto26.createHash)("sha256").update(projectRoot).digest("hex").slice(0, 16);
|
|
31404
31971
|
}
|
|
31405
|
-
var
|
|
31972
|
+
var import_fs73, import_path75, import_crypto26, import_child_process11;
|
|
31406
31973
|
var init_identity = __esm({
|
|
31407
31974
|
"apps/cli/src/identity.ts"() {
|
|
31408
31975
|
"use strict";
|
|
31409
|
-
|
|
31410
|
-
|
|
31976
|
+
import_fs73 = require("fs");
|
|
31977
|
+
import_path75 = require("path");
|
|
31411
31978
|
import_crypto26 = require("crypto");
|
|
31412
|
-
|
|
31979
|
+
import_child_process11 = require("child_process");
|
|
31413
31980
|
}
|
|
31414
31981
|
});
|
|
31415
31982
|
|
|
@@ -31429,9 +31996,9 @@ async function getLatestVersion() {
|
|
|
31429
31996
|
return data.version;
|
|
31430
31997
|
}
|
|
31431
31998
|
function detectInstallMethod() {
|
|
31432
|
-
const packageRoot = (0,
|
|
31999
|
+
const packageRoot = (0, import_path76.resolve)(__dirname, "..", "..", "..", "..");
|
|
31433
32000
|
if (process.env.npm_config_global === "true") return "global";
|
|
31434
|
-
if ((0,
|
|
32001
|
+
if ((0, import_fs74.existsSync)((0, import_path76.join)(packageRoot, ".git"))) return "git-clone";
|
|
31435
32002
|
return "local";
|
|
31436
32003
|
}
|
|
31437
32004
|
function updateCommand(method, version2) {
|
|
@@ -31479,10 +32046,15 @@ Check your internet connection or visit https://www.npmjs.com/package/gossipcat
|
|
|
31479
32046
|
}]
|
|
31480
32047
|
};
|
|
31481
32048
|
}
|
|
32049
|
+
const scrubbedEnv = { ...process.env };
|
|
32050
|
+
for (const key of Object.keys(scrubbedEnv)) {
|
|
32051
|
+
if (/^GOSSIPCAT_/i.test(key)) delete scrubbedEnv[key];
|
|
32052
|
+
}
|
|
31482
32053
|
try {
|
|
31483
|
-
(0,
|
|
32054
|
+
(0, import_child_process12.execSync)(command, {
|
|
31484
32055
|
stdio: "inherit",
|
|
31485
|
-
cwd: method === "git-clone" ? (0,
|
|
32056
|
+
cwd: method === "git-clone" ? (0, import_path76.resolve)(__dirname, "..", "..", "..", "..") : process.cwd(),
|
|
32057
|
+
env: scrubbedEnv
|
|
31486
32058
|
});
|
|
31487
32059
|
} catch (err) {
|
|
31488
32060
|
return {
|
|
@@ -31504,13 +32076,13 @@ Run /mcp reconnect in Claude Code to load the new version.`
|
|
|
31504
32076
|
}]
|
|
31505
32077
|
};
|
|
31506
32078
|
}
|
|
31507
|
-
var
|
|
32079
|
+
var import_child_process12, import_fs74, import_path76;
|
|
31508
32080
|
var init_gossip_update = __esm({
|
|
31509
32081
|
"apps/cli/src/handlers/gossip-update.ts"() {
|
|
31510
32082
|
"use strict";
|
|
31511
|
-
|
|
31512
|
-
|
|
31513
|
-
|
|
32083
|
+
import_child_process12 = require("child_process");
|
|
32084
|
+
import_fs74 = require("fs");
|
|
32085
|
+
import_path76 = require("path");
|
|
31514
32086
|
init_version();
|
|
31515
32087
|
}
|
|
31516
32088
|
});
|
|
@@ -31716,8 +32288,8 @@ var init_verify_memory = __esm({
|
|
|
31716
32288
|
});
|
|
31717
32289
|
|
|
31718
32290
|
// apps/cli/src/mcp-server-sdk.ts
|
|
31719
|
-
var
|
|
31720
|
-
var
|
|
32291
|
+
var import_fs75 = require("fs");
|
|
32292
|
+
var import_path77 = require("path");
|
|
31721
32293
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
31722
32294
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
31723
32295
|
var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
@@ -45544,8 +46116,8 @@ init_native_tasks();
|
|
|
45544
46116
|
|
|
45545
46117
|
// apps/cli/src/handlers/dispatch.ts
|
|
45546
46118
|
var import_crypto24 = require("crypto");
|
|
45547
|
-
var
|
|
45548
|
-
var
|
|
46119
|
+
var import_fs65 = require("fs");
|
|
46120
|
+
var import_path67 = require("path");
|
|
45549
46121
|
init_src4();
|
|
45550
46122
|
init_src3();
|
|
45551
46123
|
init_mcp_context();
|
|
@@ -45572,7 +46144,11 @@ function persistRelayTasks() {
|
|
|
45572
46144
|
agentId: task.agentId,
|
|
45573
46145
|
task: task.task.slice(0, 5e3),
|
|
45574
46146
|
startedAt: task.startedAt,
|
|
45575
|
-
timeoutMs: task.timeoutMs
|
|
46147
|
+
timeoutMs: task.timeoutMs,
|
|
46148
|
+
// Persist the dispatched resolutionRoots so post-reconnect audit /
|
|
46149
|
+
// dashboard rendering can show the worktree binding even after the
|
|
46150
|
+
// websocket-bound runtime task is marked timed_out.
|
|
46151
|
+
...task.resolutionRoots && task.resolutionRoots.length > 0 ? { resolutionRoots: [...task.resolutionRoots] } : {}
|
|
45576
46152
|
});
|
|
45577
46153
|
}
|
|
45578
46154
|
wf(j(dir, RELAY_TASK_FILE), JSON.stringify({ tasks: records }));
|
|
@@ -45683,9 +46259,9 @@ function formatFalsifiedNote(block, verdicts) {
|
|
|
45683
46259
|
}
|
|
45684
46260
|
function writePremiseVerificationLog(projectRoot, taskId, result, opts) {
|
|
45685
46261
|
try {
|
|
45686
|
-
const logPath = (0,
|
|
46262
|
+
const logPath = (0, import_path67.join)(projectRoot, PREMISE_VERIFICATION_LOG);
|
|
45687
46263
|
rotateIfNeeded2(logPath, MAX_PREMISE_VERIFICATION_BYTES);
|
|
45688
|
-
(0,
|
|
46264
|
+
(0, import_fs65.mkdirSync)((0, import_path67.join)(projectRoot, ".gossip"), { recursive: true });
|
|
45689
46265
|
const row = {
|
|
45690
46266
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
45691
46267
|
consensus_id: null,
|
|
@@ -45699,7 +46275,7 @@ function writePremiseVerificationLog(projectRoot, taskId, result, opts) {
|
|
|
45699
46275
|
skill_bound: opts.skill_bound
|
|
45700
46276
|
};
|
|
45701
46277
|
if (opts.schema_lint) row.schema_lint = opts.schema_lint;
|
|
45702
|
-
(0,
|
|
46278
|
+
(0, import_fs65.appendFileSync)(logPath, JSON.stringify(row) + "\n");
|
|
45703
46279
|
} catch {
|
|
45704
46280
|
}
|
|
45705
46281
|
}
|
|
@@ -45811,7 +46387,7 @@ var AGENT_PROVIDER_MAP = {
|
|
|
45811
46387
|
};
|
|
45812
46388
|
function readQuotaState() {
|
|
45813
46389
|
try {
|
|
45814
|
-
const raw = (0,
|
|
46390
|
+
const raw = (0, import_fs65.readFileSync)((0, import_path67.join)(process.cwd(), ".gossip", "quota-state.json"), "utf8");
|
|
45815
46391
|
return JSON.parse(raw);
|
|
45816
46392
|
} catch {
|
|
45817
46393
|
return {};
|
|
@@ -45835,7 +46411,7 @@ function reroutableAgent(agentId) {
|
|
|
45835
46411
|
}
|
|
45836
46412
|
return agentId;
|
|
45837
46413
|
}
|
|
45838
|
-
async function handleDispatchSingle(agent_id, task, write_mode, scope, timeout_ms, plan_id, step) {
|
|
46414
|
+
async function handleDispatchSingle(agent_id, task, write_mode, scope, timeout_ms, plan_id, step, resolutionRoots) {
|
|
45839
46415
|
await ctx.boot();
|
|
45840
46416
|
await ctx.syncWorkersViaKeychain();
|
|
45841
46417
|
if (!/^[a-zA-Z0-9_-]+$/.test(agent_id)) {
|
|
@@ -45857,6 +46433,9 @@ async function handleDispatchSingle(agent_id, task, write_mode, scope, timeout_m
|
|
|
45857
46433
|
options.planId = plan_id;
|
|
45858
46434
|
options.step = step;
|
|
45859
46435
|
}
|
|
46436
|
+
if (resolutionRoots && resolutionRoots.length > 0) {
|
|
46437
|
+
options.resolutionRoots = resolutionRoots;
|
|
46438
|
+
}
|
|
45860
46439
|
const dispatchOptions = Object.keys(options).length > 0 ? options : void 0;
|
|
45861
46440
|
const nativeConfig = ctx.nativeAgentConfigs.get(agent_id);
|
|
45862
46441
|
if (nativeConfig) {
|
|
@@ -45878,7 +46457,12 @@ async function handleDispatchSingle(agent_id, task, write_mode, scope, timeout_m
|
|
|
45878
46457
|
if (premiseResult.signals.length > 0) {
|
|
45879
46458
|
emitConsensusSignals(process.cwd(), premiseResult.signals);
|
|
45880
46459
|
}
|
|
45881
|
-
|
|
46460
|
+
let preDispatchSha = null;
|
|
46461
|
+
if (write_mode) {
|
|
46462
|
+
const { capturePreDispatchSha: capturePreDispatchSha2 } = (init_ref_allowlist_detection(), __toCommonJS(ref_allowlist_detection_exports));
|
|
46463
|
+
preDispatchSha = capturePreDispatchSha2();
|
|
46464
|
+
}
|
|
46465
|
+
ctx.nativeTaskMap.set(taskId, { agentId: agent_id, task, startedAt: Date.now(), timeoutMs, planId: plan_id, step, writeMode: write_mode, relayToken, preDispatchSha });
|
|
45882
46466
|
spawnTimeoutWatcher(taskId, ctx.nativeTaskMap.get(taskId));
|
|
45883
46467
|
persistNativeTaskMap();
|
|
45884
46468
|
process.stderr.write(`[gossipcat] \u2192 dispatch \u2192 ${agent_id} (${nativeConfig.model}) [${taskId}]
|
|
@@ -45975,7 +46559,7 @@ ${agentPrompt}` }
|
|
|
45975
46559
|
return { content: [{ type: "text", text: err.message }] };
|
|
45976
46560
|
}
|
|
45977
46561
|
}
|
|
45978
|
-
async function handleDispatchParallel(taskDefs, consensus) {
|
|
46562
|
+
async function handleDispatchParallel(taskDefs, consensus, resolutionRoots) {
|
|
45979
46563
|
await ctx.boot();
|
|
45980
46564
|
await ctx.syncWorkersViaKeychain();
|
|
45981
46565
|
for (const def of taskDefs) {
|
|
@@ -46000,11 +46584,21 @@ async function handleDispatchParallel(taskDefs, consensus) {
|
|
|
46000
46584
|
const lines = [];
|
|
46001
46585
|
if (relayTasks.length > 0) {
|
|
46002
46586
|
const { taskIds, errors } = await ctx.mainAgent.dispatchParallel(
|
|
46003
|
-
relayTasks.map((d) =>
|
|
46004
|
-
|
|
46005
|
-
|
|
46006
|
-
|
|
46007
|
-
|
|
46587
|
+
relayTasks.map((d) => {
|
|
46588
|
+
const opts = {};
|
|
46589
|
+
if (d.write_mode) {
|
|
46590
|
+
opts.writeMode = d.write_mode;
|
|
46591
|
+
if (d.scope) opts.scope = d.scope;
|
|
46592
|
+
}
|
|
46593
|
+
if (resolutionRoots && resolutionRoots.length > 0) {
|
|
46594
|
+
opts.resolutionRoots = resolutionRoots;
|
|
46595
|
+
}
|
|
46596
|
+
return {
|
|
46597
|
+
agentId: d.agent_id,
|
|
46598
|
+
task: d.task,
|
|
46599
|
+
options: Object.keys(opts).length > 0 ? opts : void 0
|
|
46600
|
+
};
|
|
46601
|
+
}),
|
|
46008
46602
|
consensus ? { consensus: true } : void 0
|
|
46009
46603
|
);
|
|
46010
46604
|
persistRelayTasks();
|
|
@@ -46197,12 +46791,13 @@ async function handleDispatchConsensus(taskDefs, _utility_task_id, dispatchResol
|
|
|
46197
46791
|
const lines = [];
|
|
46198
46792
|
const allTaskIds = [];
|
|
46199
46793
|
if (relayTasks.length > 0) {
|
|
46794
|
+
const relayOptions = dispatchResolutionRoots && dispatchResolutionRoots.length > 0 ? { resolutionRoots: dispatchResolutionRoots } : void 0;
|
|
46200
46795
|
const { taskIds, errors } = precomputedLenses ? await ctx.mainAgent.dispatchParallelWithLenses(
|
|
46201
|
-
relayTasks.map((d) => ({ agentId: d.agent_id, task: d.task })),
|
|
46796
|
+
relayTasks.map((d) => ({ agentId: d.agent_id, task: d.task, options: relayOptions })),
|
|
46202
46797
|
{ consensus: true },
|
|
46203
46798
|
precomputedLenses
|
|
46204
46799
|
) : await ctx.mainAgent.dispatchParallel(
|
|
46205
|
-
relayTasks.map((d) => ({ agentId: d.agent_id, task: d.task })),
|
|
46800
|
+
relayTasks.map((d) => ({ agentId: d.agent_id, task: d.task, options: relayOptions })),
|
|
46206
46801
|
{ consensus: true }
|
|
46207
46802
|
);
|
|
46208
46803
|
persistRelayTasks();
|
|
@@ -46319,8 +46914,29 @@ ${p.prompt}` });
|
|
|
46319
46914
|
init_mcp_context();
|
|
46320
46915
|
init_relay_cross_review();
|
|
46321
46916
|
init_native_tasks();
|
|
46917
|
+
init_lifecycle_tasks();
|
|
46322
46918
|
init_src3();
|
|
46323
46919
|
init_src4();
|
|
46920
|
+
function scheduleSkillRunner(c, mainAgent) {
|
|
46921
|
+
if (!c.skillEngine) return;
|
|
46922
|
+
const skillEngine = c.skillEngine;
|
|
46923
|
+
const registryGet = (id) => mainAgent.getAgentConfig(id);
|
|
46924
|
+
const projectRoot = process.cwd();
|
|
46925
|
+
const runRunner = async () => {
|
|
46926
|
+
try {
|
|
46927
|
+
const { runCheckEffectivenessForAllSkills: runCheckEffectivenessForAllSkills2 } = await Promise.resolve().then(() => (init_check_effectiveness_runner(), check_effectiveness_runner_exports));
|
|
46928
|
+
await runCheckEffectivenessForAllSkills2({
|
|
46929
|
+
skillEngine,
|
|
46930
|
+
registryGet,
|
|
46931
|
+
projectRoot
|
|
46932
|
+
});
|
|
46933
|
+
} catch (e) {
|
|
46934
|
+
process.stderr.write(`[gossipcat] checkEffectiveness post-collect run failed: ${e.message}
|
|
46935
|
+
`);
|
|
46936
|
+
}
|
|
46937
|
+
};
|
|
46938
|
+
trackLifecycleTask(Promise.resolve().then(runRunner));
|
|
46939
|
+
}
|
|
46324
46940
|
var _autoResolverErrors = /* @__PURE__ */ new Set();
|
|
46325
46941
|
var _autoResolverLockWarned = false;
|
|
46326
46942
|
var CONSENSUS_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{8}$/;
|
|
@@ -46509,6 +47125,7 @@ ${t.skillWarnings.map((w) => ` - ${w}`).join("\n")}`;
|
|
|
46509
47125
|
});
|
|
46510
47126
|
let consensusReport = void 0;
|
|
46511
47127
|
let provisionalSignalCount = 0;
|
|
47128
|
+
let outerEffectiveRoots = resolutionRoots ?? [];
|
|
46512
47129
|
const CONSENSUS_TIMEOUT_MS = 18e5;
|
|
46513
47130
|
if (consensus && allResults.filter((r) => r.status === "completed").length >= 2) {
|
|
46514
47131
|
const nativeAgentIds = /* @__PURE__ */ new Set();
|
|
@@ -46559,6 +47176,7 @@ ${t.skillWarnings.map((w) => ` - ${w}`).join("\n")}`;
|
|
|
46559
47176
|
process.stderr.write(`[consensus] auto-discovery failed: ${err.message}
|
|
46560
47177
|
`);
|
|
46561
47178
|
}
|
|
47179
|
+
outerEffectiveRoots = effectiveRoots;
|
|
46562
47180
|
const verifierFs = new FileTools(new Sandbox(process.cwd()));
|
|
46563
47181
|
const verifierGit = new GitTools(process.cwd());
|
|
46564
47182
|
const verifierMemory = new MemorySearcher(process.cwd());
|
|
@@ -46831,6 +47449,7 @@ ${np.user}
|
|
|
46831
47449
|
ctx.nativeTaskMap.delete(id);
|
|
46832
47450
|
}
|
|
46833
47451
|
}
|
|
47452
|
+
scheduleSkillRunner(ctx, ctx.mainAgent);
|
|
46834
47453
|
return { content: [{ type: "text", text: partialOutput }] };
|
|
46835
47454
|
}
|
|
46836
47455
|
}
|
|
@@ -46846,9 +47465,10 @@ ${np.user}
|
|
|
46846
47465
|
try {
|
|
46847
47466
|
const { writeFileSync: wfr, mkdirSync: mdr } = require("fs");
|
|
46848
47467
|
const { join: jr } = require("path");
|
|
47468
|
+
const { randomBytes: rb } = require("crypto");
|
|
46849
47469
|
const reportsDir = jr(process.cwd(), ".gossip", "consensus-reports");
|
|
46850
47470
|
mdr(reportsDir, { recursive: true });
|
|
46851
|
-
const reportId = consensusReport.signals?.[0]?.consensusId ||
|
|
47471
|
+
const reportId = consensusReport.signals?.[0]?.consensusId || `${rb(4).toString("hex")}-${rb(4).toString("hex")}`;
|
|
46852
47472
|
const reportPath = jr(reportsDir, `${reportId}.json`);
|
|
46853
47473
|
const topic = allResults?.find((r) => r.task)?.task?.slice(0, 500) || "";
|
|
46854
47474
|
wfr(reportPath, JSON.stringify({
|
|
@@ -46857,6 +47477,13 @@ ${np.user}
|
|
|
46857
47477
|
topic,
|
|
46858
47478
|
agentCount: consensusReport.agentCount,
|
|
46859
47479
|
rounds: consensusReport.rounds,
|
|
47480
|
+
// Persist resolutionRoots so the transport-failure detector
|
|
47481
|
+
// (Path 2, spec docs/specs/2026-04-29-relay-worker-resolution-roots.md)
|
|
47482
|
+
// can look up "did this round dispatch with resolutionRoots?" from a
|
|
47483
|
+
// bare `consensus_id` derived from a `finding_id`. Empty array when
|
|
47484
|
+
// none was passed — preserving the explicit "no roots" signal in the
|
|
47485
|
+
// record.
|
|
47486
|
+
resolutionRoots: outerEffectiveRoots.length > 0 ? [...outerEffectiveRoots] : [],
|
|
46860
47487
|
confirmed: consensusReport.confirmed || [],
|
|
46861
47488
|
disputed: consensusReport.disputed || [],
|
|
46862
47489
|
unverified: consensusReport.unverified || [],
|
|
@@ -46870,7 +47497,12 @@ ${np.user}
|
|
|
46870
47497
|
// round-trip through the JSON payload or the feature is invisible.
|
|
46871
47498
|
...consensusReport.authorDiagnostics ? { authorDiagnostics: consensusReport.authorDiagnostics } : {}
|
|
46872
47499
|
}, null, 2));
|
|
46873
|
-
} catch {
|
|
47500
|
+
} catch (e) {
|
|
47501
|
+
const reportIdForLog = consensusReport.signals?.[0]?.consensusId || "<unknown>";
|
|
47502
|
+
process.stderr.write(
|
|
47503
|
+
`[gossipcat] consensus-report write failed for ${reportIdForLog}: ${e.message ?? e}
|
|
47504
|
+
`
|
|
47505
|
+
);
|
|
46874
47506
|
}
|
|
46875
47507
|
}
|
|
46876
47508
|
if (consensusReport) {
|
|
@@ -47132,25 +47764,7 @@ ${gaps.map((g) => ` - ${g.agentId} needs "${g.category}" (score: ${g.score.toFi
|
|
|
47132
47764
|
}
|
|
47133
47765
|
} catch {
|
|
47134
47766
|
}
|
|
47135
|
-
|
|
47136
|
-
const skillEngine = ctx.skillEngine;
|
|
47137
|
-
const mainAgent = ctx.mainAgent;
|
|
47138
|
-
const registryGet = (id) => mainAgent.getAgentConfig(id);
|
|
47139
|
-
const projectRoot = process.cwd();
|
|
47140
|
-
setImmediate(async () => {
|
|
47141
|
-
try {
|
|
47142
|
-
const { runCheckEffectivenessForAllSkills: runCheckEffectivenessForAllSkills2 } = await Promise.resolve().then(() => (init_check_effectiveness_runner(), check_effectiveness_runner_exports));
|
|
47143
|
-
await runCheckEffectivenessForAllSkills2({
|
|
47144
|
-
skillEngine,
|
|
47145
|
-
registryGet,
|
|
47146
|
-
projectRoot
|
|
47147
|
-
});
|
|
47148
|
-
} catch (e) {
|
|
47149
|
-
process.stderr.write(`[gossipcat] checkEffectiveness post-collect run failed: ${e.message}
|
|
47150
|
-
`);
|
|
47151
|
-
}
|
|
47152
|
-
});
|
|
47153
|
-
}
|
|
47767
|
+
scheduleSkillRunner(ctx, ctx.mainAgent);
|
|
47154
47768
|
try {
|
|
47155
47769
|
const taskCount = ctx.mainAgent.getSessionGossip().length;
|
|
47156
47770
|
const consensusCount = ctx.mainAgent.getSessionConsensusHistory().length;
|
|
@@ -47168,19 +47782,19 @@ REQUIRED_BEFORE_END: gossip_session_save() \u2014 ${taskCount} tasks, ${consensu
|
|
|
47168
47782
|
init_relay_cross_review();
|
|
47169
47783
|
|
|
47170
47784
|
// apps/cli/src/stickyPort.ts
|
|
47171
|
-
var
|
|
47172
|
-
var
|
|
47785
|
+
var import_fs69 = require("fs");
|
|
47786
|
+
var import_path71 = require("path");
|
|
47173
47787
|
var import_net = require("net");
|
|
47174
|
-
var RELAY_STICKY_FILE = (0,
|
|
47175
|
-
var HTTP_MCP_STICKY_FILE = (0,
|
|
47788
|
+
var RELAY_STICKY_FILE = (0, import_path71.join)(".gossip", "relay.port");
|
|
47789
|
+
var HTTP_MCP_STICKY_FILE = (0, import_path71.join)(".gossip", "http-mcp.port");
|
|
47176
47790
|
function stickyPath(filename) {
|
|
47177
|
-
return (0,
|
|
47791
|
+
return (0, import_path71.join)(process.cwd(), filename);
|
|
47178
47792
|
}
|
|
47179
47793
|
function readStickyPort(filename) {
|
|
47180
47794
|
const p = stickyPath(filename);
|
|
47181
|
-
if (!(0,
|
|
47795
|
+
if (!(0, import_fs69.existsSync)(p)) return null;
|
|
47182
47796
|
try {
|
|
47183
|
-
const raw = (0,
|
|
47797
|
+
const raw = (0, import_fs69.readFileSync)(p, "utf-8").trim();
|
|
47184
47798
|
const n = parseInt(raw, 10);
|
|
47185
47799
|
if (!Number.isFinite(n) || n < 1 || n > 65535) return null;
|
|
47186
47800
|
return n;
|
|
@@ -47192,8 +47806,8 @@ function writeStickyPort(filename, port) {
|
|
|
47192
47806
|
if (!Number.isFinite(port) || port < 1 || port > 65535) return;
|
|
47193
47807
|
const p = stickyPath(filename);
|
|
47194
47808
|
try {
|
|
47195
|
-
(0,
|
|
47196
|
-
(0,
|
|
47809
|
+
(0, import_fs69.mkdirSync)((0, import_path71.dirname)(p), { recursive: true });
|
|
47810
|
+
(0, import_fs69.writeFileSync)(p, String(port), "utf-8");
|
|
47197
47811
|
} catch {
|
|
47198
47812
|
}
|
|
47199
47813
|
}
|
|
@@ -47257,12 +47871,12 @@ function buildDashboardAdvisory(input) {
|
|
|
47257
47871
|
}
|
|
47258
47872
|
|
|
47259
47873
|
// apps/cli/src/native-agent-cache.ts
|
|
47260
|
-
var
|
|
47261
|
-
var
|
|
47874
|
+
var import_fs70 = require("fs");
|
|
47875
|
+
var import_path72 = require("path");
|
|
47262
47876
|
var realFs = {
|
|
47263
|
-
existsSync:
|
|
47264
|
-
readFileSync:
|
|
47265
|
-
statSync: (p) => ({ mtimeMs: (0,
|
|
47877
|
+
existsSync: import_fs70.existsSync,
|
|
47878
|
+
readFileSync: import_fs70.readFileSync,
|
|
47879
|
+
statSync: (p) => ({ mtimeMs: (0, import_fs70.statSync)(p).mtimeMs })
|
|
47266
47880
|
};
|
|
47267
47881
|
function modelTierFromId(modelId) {
|
|
47268
47882
|
if (modelId.includes("opus")) return "opus";
|
|
@@ -47270,8 +47884,8 @@ function modelTierFromId(modelId) {
|
|
|
47270
47884
|
return "sonnet";
|
|
47271
47885
|
}
|
|
47272
47886
|
function refreshNativeAgentFromDisk(ac, cache2, projectRoot, fs5 = realFs) {
|
|
47273
|
-
const claudeAgentPath = (0,
|
|
47274
|
-
const instrPath = (0,
|
|
47887
|
+
const claudeAgentPath = (0, import_path72.join)(projectRoot, ".claude", "agents", `${ac.id}.md`);
|
|
47888
|
+
const instrPath = (0, import_path72.join)(projectRoot, ".gossip", "agents", ac.id, "instructions.md");
|
|
47275
47889
|
const prev = cache2.get(ac.id);
|
|
47276
47890
|
let sourcePath = null;
|
|
47277
47891
|
let stripFrontmatter = false;
|
|
@@ -47330,16 +47944,16 @@ function refreshNativeAgentFromDisk(ac, cache2, projectRoot, fs5 = realFs) {
|
|
|
47330
47944
|
}
|
|
47331
47945
|
|
|
47332
47946
|
// apps/cli/src/rules-content.ts
|
|
47333
|
-
var
|
|
47334
|
-
var
|
|
47947
|
+
var import_fs71 = require("fs");
|
|
47948
|
+
var import_path73 = require("path");
|
|
47335
47949
|
var AGENT_LIST_PLACEHOLDER = "{{AGENT_LIST}}";
|
|
47336
47950
|
function resolveRulesPath() {
|
|
47337
47951
|
const candidates = [
|
|
47338
|
-
(0,
|
|
47339
|
-
(0,
|
|
47340
|
-
(0,
|
|
47952
|
+
(0, import_path73.join)(process.cwd(), "docs", "RULES.md"),
|
|
47953
|
+
(0, import_path73.join)(__dirname, "..", "docs", "RULES.md"),
|
|
47954
|
+
(0, import_path73.join)(__dirname, "docs", "RULES.md")
|
|
47341
47955
|
];
|
|
47342
|
-
return candidates.find((p) => (0,
|
|
47956
|
+
return candidates.find((p) => (0, import_fs71.existsSync)(p)) ?? null;
|
|
47343
47957
|
}
|
|
47344
47958
|
function generateRulesContent(agentList) {
|
|
47345
47959
|
const rulesPath = resolveRulesPath();
|
|
@@ -47348,7 +47962,7 @@ function generateRulesContent(agentList) {
|
|
|
47348
47962
|
`[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/.`
|
|
47349
47963
|
);
|
|
47350
47964
|
}
|
|
47351
|
-
const template = (0,
|
|
47965
|
+
const template = (0, import_fs71.readFileSync)(rulesPath, "utf-8");
|
|
47352
47966
|
return template.split(AGENT_LIST_PLACEHOLDER).join(agentList);
|
|
47353
47967
|
}
|
|
47354
47968
|
|
|
@@ -47364,6 +47978,23 @@ function formatDropReceipt(drops) {
|
|
|
47364
47978
|
${lines.join("\n")}`;
|
|
47365
47979
|
}
|
|
47366
47980
|
|
|
47981
|
+
// apps/cli/src/shutdown.ts
|
|
47982
|
+
async function shutdownOnSignal(signal, deps) {
|
|
47983
|
+
try {
|
|
47984
|
+
await deps.drainLifecycleTasks();
|
|
47985
|
+
} catch {
|
|
47986
|
+
}
|
|
47987
|
+
deps.eviction.stop();
|
|
47988
|
+
process.stderr.write(`[relay] shutdown reason=${signal} pid=${deps.pid}
|
|
47989
|
+
`);
|
|
47990
|
+
try {
|
|
47991
|
+
await deps.relayStop();
|
|
47992
|
+
} catch {
|
|
47993
|
+
}
|
|
47994
|
+
deps.cleanupPid();
|
|
47995
|
+
deps.exit(0);
|
|
47996
|
+
}
|
|
47997
|
+
|
|
47367
47998
|
// apps/cli/src/mcp-server-sdk.ts
|
|
47368
47999
|
var import_os5 = require("os");
|
|
47369
48000
|
|
|
@@ -47419,17 +48050,17 @@ function filterWatchEvents(rawJsonl, opts) {
|
|
|
47419
48050
|
}
|
|
47420
48051
|
|
|
47421
48052
|
// apps/cli/src/mcp-server-sdk.ts
|
|
47422
|
-
var gossipDir = (0,
|
|
48053
|
+
var gossipDir = (0, import_path77.join)(process.cwd(), ".gossip");
|
|
47423
48054
|
try {
|
|
47424
|
-
(0,
|
|
48055
|
+
(0, import_fs75.mkdirSync)(gossipDir, { recursive: true });
|
|
47425
48056
|
} catch {
|
|
47426
48057
|
}
|
|
47427
|
-
var logStream = (0,
|
|
48058
|
+
var logStream = (0, import_fs75.createWriteStream)((0, import_path77.join)(gossipDir, "mcp.log"), { flags: "a" });
|
|
47428
48059
|
process.stderr.write = ((chunk, ...args) => {
|
|
47429
48060
|
return logStream.write(chunk, ...args);
|
|
47430
48061
|
});
|
|
47431
48062
|
function memoryDirForProject(cwd) {
|
|
47432
|
-
return (0,
|
|
48063
|
+
return (0, import_path77.join)((0, import_os5.homedir)(), ".claude", "projects", cwd.replaceAll("/", "-"), "memory");
|
|
47433
48064
|
}
|
|
47434
48065
|
function detectEnvironment() {
|
|
47435
48066
|
if (process.env.CLAUDECODE === "1" || process.env.CLAUDE_CODE_ENTRYPOINT) {
|
|
@@ -47453,9 +48084,9 @@ var planExecutionDepth = 0;
|
|
|
47453
48084
|
var _pendingSessionData = /* @__PURE__ */ new Map();
|
|
47454
48085
|
async function writeArtifactsInOrder(a) {
|
|
47455
48086
|
const { writeFileSync: wf, mkdirSync: md } = await import("fs");
|
|
47456
|
-
const { dirname:
|
|
48087
|
+
const { dirname: dirname17 } = await import("path");
|
|
47457
48088
|
try {
|
|
47458
|
-
md(
|
|
48089
|
+
md(dirname17(a.nextSessionPath), { recursive: true });
|
|
47459
48090
|
wf(a.nextSessionPath, a.nextSessionContent);
|
|
47460
48091
|
} catch (err) {
|
|
47461
48092
|
process.stderr.write(`[gossipcat] next-session.md write FAILED: ${err.message}
|
|
@@ -47463,7 +48094,7 @@ async function writeArtifactsInOrder(a) {
|
|
|
47463
48094
|
throw err;
|
|
47464
48095
|
}
|
|
47465
48096
|
try {
|
|
47466
|
-
md(
|
|
48097
|
+
md(dirname17(a.knowledgePath), { recursive: true });
|
|
47467
48098
|
wf(a.knowledgePath, a.knowledgeContent);
|
|
47468
48099
|
} catch (err) {
|
|
47469
48100
|
process.stderr.write(`[gossipcat] cognitive knowledge write failed: ${err.message}
|
|
@@ -47484,14 +48115,14 @@ var _pendingPlanData = /* @__PURE__ */ new Map();
|
|
|
47484
48115
|
var _utilityGuardSnapshots = /* @__PURE__ */ new Map();
|
|
47485
48116
|
var _modules = null;
|
|
47486
48117
|
function lookupFindingSeverity(findingId, projectRoot) {
|
|
47487
|
-
const { existsSync:
|
|
47488
|
-
const { join:
|
|
47489
|
-
const reportsDir =
|
|
47490
|
-
if (!
|
|
48118
|
+
const { existsSync: existsSync64, readdirSync: readdirSync18, readFileSync: readFileSync61 } = require("fs");
|
|
48119
|
+
const { join: join73 } = require("path");
|
|
48120
|
+
const reportsDir = join73(projectRoot, ".gossip", "consensus-reports");
|
|
48121
|
+
if (!existsSync64(reportsDir)) return null;
|
|
47491
48122
|
try {
|
|
47492
48123
|
const files = readdirSync18(reportsDir).filter((f) => f.endsWith(".json"));
|
|
47493
48124
|
for (const file2 of files) {
|
|
47494
|
-
const report = JSON.parse(
|
|
48125
|
+
const report = JSON.parse(readFileSync61(join73(reportsDir, file2), "utf-8"));
|
|
47495
48126
|
for (const bucket of ["confirmed", "disputed", "unverified", "unique"]) {
|
|
47496
48127
|
for (const finding of report[bucket] || []) {
|
|
47497
48128
|
if (finding.id === findingId && finding.severity) {
|
|
@@ -47569,7 +48200,7 @@ async function doBoot() {
|
|
|
47569
48200
|
const agentConfigs = m.configToAgentConfigs(config2);
|
|
47570
48201
|
ctx.keychain = new m.Keychain();
|
|
47571
48202
|
const { existsSync: pidExists, readFileSync: readPid, writeFileSync: writePid, unlinkSync: delPid } = require("fs");
|
|
47572
|
-
const pidFile = (0,
|
|
48203
|
+
const pidFile = (0, import_path77.join)(process.cwd(), ".gossip", "relay.pid");
|
|
47573
48204
|
if (pidExists(pidFile)) {
|
|
47574
48205
|
const oldPid = parseInt(readPid(pidFile, "utf-8").trim(), 10);
|
|
47575
48206
|
if (!isNaN(oldPid) && oldPid !== process.pid) {
|
|
@@ -47613,31 +48244,25 @@ async function doBoot() {
|
|
|
47613
48244
|
process.once("exit", cleanupPid);
|
|
47614
48245
|
let shuttingDown = false;
|
|
47615
48246
|
const eviction = scheduleNativeTaskEviction();
|
|
48247
|
+
const { installLifecycleDrainHandlers: installLifecycleDrainHandlers2, drainLifecycleTasks: drainLifecycleTasks2 } = await Promise.resolve().then(() => (init_lifecycle_tasks(), lifecycle_tasks_exports));
|
|
48248
|
+
installLifecycleDrainHandlers2();
|
|
48249
|
+
const shutdownDeps = {
|
|
48250
|
+
eviction,
|
|
48251
|
+
relayStop: () => ctx.relay.stop(),
|
|
48252
|
+
cleanupPid,
|
|
48253
|
+
drainLifecycleTasks: () => drainLifecycleTasks2(),
|
|
48254
|
+
exit: (code) => process.exit(code),
|
|
48255
|
+
pid: process.pid
|
|
48256
|
+
};
|
|
47616
48257
|
process.once("SIGTERM", async () => {
|
|
47617
48258
|
if (shuttingDown) return;
|
|
47618
48259
|
shuttingDown = true;
|
|
47619
|
-
|
|
47620
|
-
process.stderr.write(`[relay] shutdown reason=SIGTERM pid=${process.pid}
|
|
47621
|
-
`);
|
|
47622
|
-
try {
|
|
47623
|
-
await ctx.relay.stop();
|
|
47624
|
-
} catch {
|
|
47625
|
-
}
|
|
47626
|
-
cleanupPid();
|
|
47627
|
-
process.exit(0);
|
|
48260
|
+
await shutdownOnSignal("SIGTERM", shutdownDeps);
|
|
47628
48261
|
});
|
|
47629
48262
|
process.once("SIGINT", async () => {
|
|
47630
48263
|
if (shuttingDown) return;
|
|
47631
48264
|
shuttingDown = true;
|
|
47632
|
-
|
|
47633
|
-
process.stderr.write(`[relay] shutdown reason=SIGINT pid=${process.pid}
|
|
47634
|
-
`);
|
|
47635
|
-
try {
|
|
47636
|
-
await ctx.relay.stop();
|
|
47637
|
-
} catch {
|
|
47638
|
-
}
|
|
47639
|
-
cleanupPid();
|
|
47640
|
-
process.exit(0);
|
|
48265
|
+
await shutdownOnSignal("SIGINT", shutdownDeps);
|
|
47641
48266
|
});
|
|
47642
48267
|
if (ctx.relay.dashboardUrl) {
|
|
47643
48268
|
process.stderr.write(`[gossipcat] \u{1F310} Dashboard: ${ctx.relay.dashboardUrl} (key: ${ctx.relay.dashboardKey})
|
|
@@ -47685,10 +48310,10 @@ async function doBoot() {
|
|
|
47685
48310
|
}
|
|
47686
48311
|
const key = await ctx.keychain.getKey(ac.provider);
|
|
47687
48312
|
const llm = m.createProvider(ac.provider, ac.model, key ?? void 0, void 0, ac.base_url);
|
|
47688
|
-
const { existsSync:
|
|
47689
|
-
const { join:
|
|
47690
|
-
const instructionsPath =
|
|
47691
|
-
const baseInstructions =
|
|
48313
|
+
const { existsSync: existsSync64, readFileSync: readFileSync61 } = require("fs");
|
|
48314
|
+
const { join: join73 } = require("path");
|
|
48315
|
+
const instructionsPath = join73(process.cwd(), ".gossip", "agents", ac.id, "instructions.md");
|
|
48316
|
+
const baseInstructions = existsSync64(instructionsPath) ? readFileSync61(instructionsPath, "utf-8") : "";
|
|
47692
48317
|
const identity = ctx.identityRegistry.get(ac.id);
|
|
47693
48318
|
const identityBlock = identity ? m.formatIdentityBlock(identity) + "\n" : "";
|
|
47694
48319
|
const instructions = (identityBlock + baseInstructions).trim() || void 0;
|
|
@@ -48360,13 +48985,26 @@ server.tool(
|
|
|
48360
48985
|
if (!agent_id || !task) {
|
|
48361
48986
|
return { content: [{ type: "text", text: 'Error: mode:"single" requires agent_id and task.' }] };
|
|
48362
48987
|
}
|
|
48363
|
-
return handleDispatchSingle(
|
|
48988
|
+
return handleDispatchSingle(
|
|
48989
|
+
agent_id,
|
|
48990
|
+
task,
|
|
48991
|
+
write_mode,
|
|
48992
|
+
scope,
|
|
48993
|
+
timeout_ms,
|
|
48994
|
+
plan_id,
|
|
48995
|
+
step,
|
|
48996
|
+
validatedDispatchRoots.length > 0 ? validatedDispatchRoots : void 0
|
|
48997
|
+
);
|
|
48364
48998
|
}
|
|
48365
48999
|
if (mode === "parallel") {
|
|
48366
49000
|
if (!tasks || tasks.length === 0) {
|
|
48367
49001
|
return { content: [{ type: "text", text: 'Error: mode:"parallel" requires a non-empty tasks array.' }] };
|
|
48368
49002
|
}
|
|
48369
|
-
return handleDispatchParallel(
|
|
49003
|
+
return handleDispatchParallel(
|
|
49004
|
+
tasks,
|
|
49005
|
+
false,
|
|
49006
|
+
validatedDispatchRoots.length > 0 ? validatedDispatchRoots : void 0
|
|
49007
|
+
);
|
|
48370
49008
|
}
|
|
48371
49009
|
if (mode === "consensus") {
|
|
48372
49010
|
if (!tasks || tasks.length === 0) {
|
|
@@ -48484,9 +49122,26 @@ server.tool(
|
|
|
48484
49122
|
lines.push(` HTTP MCP: :${ctx.httpMcpPort}/mcp${ctx.httpMcpPortSource === "sticky" ? " (sticky)" : ""}`);
|
|
48485
49123
|
}
|
|
48486
49124
|
try {
|
|
48487
|
-
const { readFileSync:
|
|
48488
|
-
const
|
|
48489
|
-
const
|
|
49125
|
+
const { readFileSync: rfHealth } = await import("fs");
|
|
49126
|
+
const healthPath = (0, import_path77.join)(process.cwd(), ".gossip", "skill-runner-health.json");
|
|
49127
|
+
const raw = rfHealth(healthPath, "utf8");
|
|
49128
|
+
const h = JSON.parse(raw);
|
|
49129
|
+
const lastMs = h.last_run_at ? new Date(h.last_run_at).getTime() : NaN;
|
|
49130
|
+
if (Number.isFinite(lastMs)) {
|
|
49131
|
+
const ago = Date.now() - lastMs;
|
|
49132
|
+
const sec = Math.round(ago / 1e3);
|
|
49133
|
+
const rel = sec < 60 ? `${sec}s` : sec < 3600 ? `${Math.round(sec / 60)}m` : `${Math.round(sec / 3600)}h`;
|
|
49134
|
+
const t = h.transitions || {};
|
|
49135
|
+
const totalT = (t.passed ?? 0) + (t.failed ?? 0) + (t.flagged_for_manual_review ?? 0) + (t.inconclusive ?? 0) + (t.pending ?? 0);
|
|
49136
|
+
lines.push(` Skill graduation: last run ${rel} ago (${h.skills_evaluated ?? 0} skills, ${totalT} transitions)`);
|
|
49137
|
+
}
|
|
49138
|
+
} catch {
|
|
49139
|
+
lines.push(" Skill graduation: never run since session start (expected after first gossip_collect)");
|
|
49140
|
+
}
|
|
49141
|
+
try {
|
|
49142
|
+
const { readFileSync: readFileSync61 } = await import("fs");
|
|
49143
|
+
const quotaPath = (0, import_path77.join)(process.cwd(), ".gossip", "quota-state.json");
|
|
49144
|
+
const quotaRaw = readFileSync61(quotaPath, "utf8");
|
|
48490
49145
|
const quotaState = JSON.parse(quotaRaw);
|
|
48491
49146
|
for (const [provider, state] of Object.entries(quotaState)) {
|
|
48492
49147
|
const now = Date.now();
|
|
@@ -48500,17 +49155,17 @@ server.tool(
|
|
|
48500
49155
|
} catch {
|
|
48501
49156
|
}
|
|
48502
49157
|
try {
|
|
48503
|
-
const { readFileSync:
|
|
48504
|
-
const reportsDir = (0,
|
|
48505
|
-
const perfPath = (0,
|
|
49158
|
+
const { readFileSync: readFileSync61, readdirSync: readdirSync18, statSync: statSync24 } = await import("fs");
|
|
49159
|
+
const reportsDir = (0, import_path77.join)(process.cwd(), ".gossip", "consensus-reports");
|
|
49160
|
+
const perfPath = (0, import_path77.join)(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
48506
49161
|
const WINDOW_MS2 = 24 * 60 * 60 * 1e3;
|
|
48507
49162
|
const now = Date.now();
|
|
48508
49163
|
const recentReports = [];
|
|
48509
49164
|
try {
|
|
48510
49165
|
for (const fname of readdirSync18(reportsDir)) {
|
|
48511
49166
|
if (!fname.endsWith(".json")) continue;
|
|
48512
|
-
const fpath = (0,
|
|
48513
|
-
const st =
|
|
49167
|
+
const fpath = (0, import_path77.join)(reportsDir, fname);
|
|
49168
|
+
const st = statSync24(fpath);
|
|
48514
49169
|
if (now - st.mtimeMs > WINDOW_MS2) continue;
|
|
48515
49170
|
recentReports.push({ id: fname.replace(/\.json$/, ""), mtimeMs: st.mtimeMs });
|
|
48516
49171
|
}
|
|
@@ -48519,7 +49174,7 @@ server.tool(
|
|
|
48519
49174
|
if (recentReports.length > 0) {
|
|
48520
49175
|
const covered = /* @__PURE__ */ new Set();
|
|
48521
49176
|
try {
|
|
48522
|
-
const perfRaw =
|
|
49177
|
+
const perfRaw = readFileSync61(perfPath, "utf8");
|
|
48523
49178
|
for (const line of perfRaw.split("\n")) {
|
|
48524
49179
|
if (!line) continue;
|
|
48525
49180
|
try {
|
|
@@ -48869,8 +49524,8 @@ server.tool(
|
|
|
48869
49524
|
}
|
|
48870
49525
|
return { content: [{ type: "text", text: results.join("\n") }] };
|
|
48871
49526
|
}
|
|
48872
|
-
const { writeFileSync:
|
|
48873
|
-
const { join:
|
|
49527
|
+
const { writeFileSync: writeFileSync26, mkdirSync: mkdirSync33, existsSync: existsSync64 } = require("fs");
|
|
49528
|
+
const { join: join73 } = require("path");
|
|
48874
49529
|
const root = process.cwd();
|
|
48875
49530
|
const CLAUDE_MODEL_MAP2 = {
|
|
48876
49531
|
opus: { provider: "anthropic", model: "claude-opus-4-6" },
|
|
@@ -48884,8 +49539,8 @@ server.tool(
|
|
|
48884
49539
|
let existingAgents = {};
|
|
48885
49540
|
if (mode === "merge") {
|
|
48886
49541
|
try {
|
|
48887
|
-
const { readFileSync:
|
|
48888
|
-
const existing = JSON.parse(
|
|
49542
|
+
const { readFileSync: readFileSync61 } = require("fs");
|
|
49543
|
+
const existing = JSON.parse(readFileSync61(join73(root, ".gossip", "config.json"), "utf-8"));
|
|
48889
49544
|
existingAgents = existing.agents || {};
|
|
48890
49545
|
} catch {
|
|
48891
49546
|
}
|
|
@@ -48916,9 +49571,9 @@ server.tool(
|
|
|
48916
49571
|
"",
|
|
48917
49572
|
body
|
|
48918
49573
|
].join("\n");
|
|
48919
|
-
const agentsDir =
|
|
48920
|
-
|
|
48921
|
-
|
|
49574
|
+
const agentsDir = join73(root, ".claude", "agents");
|
|
49575
|
+
mkdirSync33(agentsDir, { recursive: true });
|
|
49576
|
+
writeFileSync26(join73(agentsDir, `${agent.id}.md`), md, "utf-8");
|
|
48922
49577
|
nativeCreated.push(agent.id);
|
|
48923
49578
|
configAgents[agent.id] = {
|
|
48924
49579
|
provider: mapped.provider,
|
|
@@ -48936,8 +49591,8 @@ server.tool(
|
|
|
48936
49591
|
errors.push(`${agent.id}: custom agent requires "custom_model" field`);
|
|
48937
49592
|
continue;
|
|
48938
49593
|
}
|
|
48939
|
-
const nativeFile =
|
|
48940
|
-
const wasNative = existingAgents[agent.id]?.native ||
|
|
49594
|
+
const nativeFile = join73(root, ".claude", "agents", `${agent.id}.md`);
|
|
49595
|
+
const wasNative = existingAgents[agent.id]?.native || existsSync64(nativeFile);
|
|
48941
49596
|
if (wasNative) {
|
|
48942
49597
|
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.`);
|
|
48943
49598
|
continue;
|
|
@@ -48951,9 +49606,9 @@ server.tool(
|
|
|
48951
49606
|
};
|
|
48952
49607
|
customCreated.push(agent.id);
|
|
48953
49608
|
if (agent.instructions) {
|
|
48954
|
-
const instrDir =
|
|
48955
|
-
|
|
48956
|
-
|
|
49609
|
+
const instrDir = join73(root, ".gossip", "agents", agent.id);
|
|
49610
|
+
mkdirSync33(instrDir, { recursive: true });
|
|
49611
|
+
writeFileSync26(join73(instrDir, "instructions.md"), agent.instructions, "utf-8");
|
|
48957
49612
|
}
|
|
48958
49613
|
}
|
|
48959
49614
|
}
|
|
@@ -48967,8 +49622,8 @@ server.tool(
|
|
|
48967
49622
|
} catch (err) {
|
|
48968
49623
|
return { content: [{ type: "text", text: `Invalid config: ${err.message}` }] };
|
|
48969
49624
|
}
|
|
48970
|
-
|
|
48971
|
-
|
|
49625
|
+
mkdirSync33(join73(root, ".gossip"), { recursive: true });
|
|
49626
|
+
writeFileSync26(join73(root, ".gossip", "config.json"), JSON.stringify(config2, null, 2));
|
|
48972
49627
|
let hookSummary = "";
|
|
48973
49628
|
try {
|
|
48974
49629
|
const { installWorktreeSandboxHook: installWorktreeSandboxHook2, writeOrchestratorRoleMarker: writeOrchestratorRoleMarker2 } = (init_src4(), __toCommonJS(src_exports3));
|
|
@@ -49007,10 +49662,10 @@ server.tool(
|
|
|
49007
49662
|
}
|
|
49008
49663
|
}
|
|
49009
49664
|
const agentList = Object.entries(config2.agents).map(([id, a]) => `- ${id}: ${a.provider}/${a.model} (${a.preset || "custom"})${a.native ? " \u2014 native" : ""}`).join("\n");
|
|
49010
|
-
const rulesDir =
|
|
49011
|
-
const rulesFile =
|
|
49012
|
-
|
|
49013
|
-
|
|
49665
|
+
const rulesDir = join73(root, env.rulesDir);
|
|
49666
|
+
const rulesFile = join73(root, env.rulesFile);
|
|
49667
|
+
mkdirSync33(rulesDir, { recursive: true });
|
|
49668
|
+
writeFileSync26(rulesFile, generateRulesContent(agentList));
|
|
49014
49669
|
const lines = [`Host: ${env.host}`, ""];
|
|
49015
49670
|
if (nativeCreated.length > 0) {
|
|
49016
49671
|
lines.push(`Native agents created (${nativeCreated.length}):`);
|
|
@@ -49297,11 +49952,11 @@ The original signal remains in the audit log but will be excluded from scoring.`
|
|
|
49297
49952
|
const fid = finding_id.trim();
|
|
49298
49953
|
const cwd = process.cwd();
|
|
49299
49954
|
const findingsPath = require("path").join(cwd, ".gossip", "implementation-findings.jsonl");
|
|
49300
|
-
const { readFileSync:
|
|
49301
|
-
if (!
|
|
49955
|
+
const { readFileSync: readFileSync61, existsSync: existsSync64, writeFileSync: writeFileSync26, renameSync: renameSync9 } = require("fs");
|
|
49956
|
+
if (!existsSync64(findingsPath)) {
|
|
49302
49957
|
return { content: [{ type: "text", text: `No implementation-findings.jsonl found at ${findingsPath}` }] };
|
|
49303
49958
|
}
|
|
49304
|
-
const lines =
|
|
49959
|
+
const lines = readFileSync61(findingsPath, "utf-8").split("\n");
|
|
49305
49960
|
let matched = false;
|
|
49306
49961
|
let alreadyTarget = false;
|
|
49307
49962
|
let matchedEntry = null;
|
|
@@ -49357,8 +50012,8 @@ The original signal remains in the audit log but will be excluded from scoring.`
|
|
|
49357
50012
|
}
|
|
49358
50013
|
try {
|
|
49359
50014
|
const tmp = findingsPath + ".tmp." + Date.now();
|
|
49360
|
-
|
|
49361
|
-
|
|
50015
|
+
writeFileSync26(tmp, newLines.join("\n"));
|
|
50016
|
+
renameSync9(tmp, findingsPath);
|
|
49362
50017
|
} catch (err) {
|
|
49363
50018
|
return { content: [{ type: "text", text: `Failed to write findings: ${err.message}` }] };
|
|
49364
50019
|
}
|
|
@@ -49389,19 +50044,19 @@ The original signal remains in the audit log but will be excluded from scoring.`
|
|
|
49389
50044
|
return { content: [{ type: "text", text: "Error: consensus_id is required for bulk_from_consensus." }] };
|
|
49390
50045
|
}
|
|
49391
50046
|
try {
|
|
49392
|
-
const { readFileSync:
|
|
49393
|
-
const { join:
|
|
49394
|
-
const reportPath =
|
|
50047
|
+
const { readFileSync: readFileSync61 } = await import("fs");
|
|
50048
|
+
const { join: join73 } = await import("path");
|
|
50049
|
+
const reportPath = join73(process.cwd(), ".gossip", "consensus-reports", `${consensus_id}.json`);
|
|
49395
50050
|
let report;
|
|
49396
50051
|
try {
|
|
49397
|
-
report = JSON.parse(
|
|
50052
|
+
report = JSON.parse(readFileSync61(reportPath, "utf-8"));
|
|
49398
50053
|
} catch {
|
|
49399
50054
|
return { content: [{ type: "text", text: `Error: consensus report not found: ${consensus_id}` }] };
|
|
49400
50055
|
}
|
|
49401
50056
|
const existingFindingIds = /* @__PURE__ */ new Set();
|
|
49402
50057
|
try {
|
|
49403
|
-
const perfPath =
|
|
49404
|
-
const lines =
|
|
50058
|
+
const perfPath = join73(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
50059
|
+
const lines = readFileSync61(perfPath, "utf-8").split("\n").filter(Boolean);
|
|
49405
50060
|
for (const line of lines) {
|
|
49406
50061
|
try {
|
|
49407
50062
|
const rec = JSON.parse(line);
|
|
@@ -49569,6 +50224,41 @@ Uncategorized finding_ids: ${uncategorized.join(", ")}`;
|
|
|
49569
50224
|
timestamp: ts2
|
|
49570
50225
|
};
|
|
49571
50226
|
});
|
|
50227
|
+
try {
|
|
50228
|
+
const { maybeRewriteHallucinationToTransportFailure: maybeRewriteHallucinationToTransportFailure2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
50229
|
+
const { existsSync: nativeExists } = require("fs");
|
|
50230
|
+
const { join: nativeJoin } = require("path");
|
|
50231
|
+
const nativeFileCache = /* @__PURE__ */ new Map();
|
|
50232
|
+
const isNativeAgent = (agentId) => {
|
|
50233
|
+
if (ctx.nativeAgentConfigs.has(agentId)) return true;
|
|
50234
|
+
const cached3 = nativeFileCache.get(agentId);
|
|
50235
|
+
if (cached3 !== void 0) return cached3;
|
|
50236
|
+
let onDisk = false;
|
|
50237
|
+
try {
|
|
50238
|
+
onDisk = nativeExists(nativeJoin(process.cwd(), ".claude", "agents", `${agentId}.md`));
|
|
50239
|
+
} catch {
|
|
50240
|
+
onDisk = false;
|
|
50241
|
+
}
|
|
50242
|
+
nativeFileCache.set(agentId, onDisk);
|
|
50243
|
+
return onDisk;
|
|
50244
|
+
};
|
|
50245
|
+
for (let i = 0; i < formatted.length; i++) {
|
|
50246
|
+
const s = formatted[i];
|
|
50247
|
+
if (s.type !== "consensus") continue;
|
|
50248
|
+
if (s.signal !== "hallucination_caught") continue;
|
|
50249
|
+
const rewritten = maybeRewriteHallucinationToTransportFailure2(
|
|
50250
|
+
process.cwd(),
|
|
50251
|
+
s,
|
|
50252
|
+
isNativeAgent
|
|
50253
|
+
);
|
|
50254
|
+
if (rewritten !== s) {
|
|
50255
|
+
formatted[i] = rewritten;
|
|
50256
|
+
}
|
|
50257
|
+
}
|
|
50258
|
+
} catch (err) {
|
|
50259
|
+
process.stderr.write(`[gossip_signals] transport-failure detector failed: ${err.message}
|
|
50260
|
+
`);
|
|
50261
|
+
}
|
|
49572
50262
|
const { extractCategories: extractCategories2, logUncategorizedFinding: logUncategorizedFinding2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
49573
50263
|
const droppedNoCategory = [];
|
|
49574
50264
|
const categoryEnforced = formatted.filter((s, i) => {
|
|
@@ -49602,9 +50292,9 @@ Uncategorized finding_ids: ${uncategorized.join(", ")}`;
|
|
|
49602
50292
|
const existingFindingIds = /* @__PURE__ */ new Set();
|
|
49603
50293
|
const existingKeyToFindingId = /* @__PURE__ */ new Map();
|
|
49604
50294
|
try {
|
|
49605
|
-
const { readFileSync:
|
|
50295
|
+
const { readFileSync: readFileSync61 } = await import("fs");
|
|
49606
50296
|
const perfPath = require("path").join(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
49607
|
-
const lines =
|
|
50297
|
+
const lines = readFileSync61(perfPath, "utf-8").split("\n").filter(Boolean);
|
|
49608
50298
|
for (const line of lines) {
|
|
49609
50299
|
try {
|
|
49610
50300
|
const rec = JSON.parse(line);
|
|
@@ -50361,16 +51051,16 @@ ${preview}` }]
|
|
|
50361
51051
|
const { SkillGapTracker: SkillGapTracker2, parseSkillFrontmatter: parseSkillFrontmatter2, normalizeSkillName: normalizeSkillName2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
50362
51052
|
const tracker = new SkillGapTracker2(process.cwd());
|
|
50363
51053
|
if (skills && skills.length > 0) {
|
|
50364
|
-
const { writeFileSync:
|
|
50365
|
-
const { join:
|
|
50366
|
-
const dir =
|
|
50367
|
-
|
|
51054
|
+
const { writeFileSync: writeFileSync26, mkdirSync: mkdirSync33, existsSync: existsSync64, readFileSync: readFileSync61 } = require("fs");
|
|
51055
|
+
const { join: join73 } = require("path");
|
|
51056
|
+
const dir = join73(process.cwd(), ".gossip", "skills");
|
|
51057
|
+
mkdirSync33(dir, { recursive: true });
|
|
50368
51058
|
const results = [];
|
|
50369
51059
|
for (const sk of skills) {
|
|
50370
51060
|
const name = normalizeSkillName2(sk.name);
|
|
50371
|
-
const filePath =
|
|
50372
|
-
if (
|
|
50373
|
-
const existing =
|
|
51061
|
+
const filePath = join73(dir, `${name}.md`);
|
|
51062
|
+
if (existsSync64(filePath)) {
|
|
51063
|
+
const existing = readFileSync61(filePath, "utf-8");
|
|
50374
51064
|
const fm = parseSkillFrontmatter2(existing);
|
|
50375
51065
|
if (fm) {
|
|
50376
51066
|
if (fm.generated_by === "manual") {
|
|
@@ -50387,7 +51077,7 @@ ${preview}` }]
|
|
|
50387
51077
|
}
|
|
50388
51078
|
}
|
|
50389
51079
|
}
|
|
50390
|
-
|
|
51080
|
+
writeFileSync26(filePath, sk.content);
|
|
50391
51081
|
tracker.recordResolution(name);
|
|
50392
51082
|
results.push(`Created .gossip/skills/${name}.md`);
|
|
50393
51083
|
}
|
|
@@ -51100,10 +51790,10 @@ server.tool(
|
|
|
51100
51790
|
max_events: external_exports.number().int().positive().max(WATCH_MAX_EVENTS).optional().describe(`Cap events returned (default ${WATCH_MAX_EVENTS}).`)
|
|
51101
51791
|
},
|
|
51102
51792
|
async ({ cursor, max_events }) => {
|
|
51103
|
-
const { readFileSync:
|
|
51104
|
-
const { join:
|
|
51105
|
-
const perfPath =
|
|
51106
|
-
const raw =
|
|
51793
|
+
const { readFileSync: readFileSync61, existsSync: existsSync64 } = await import("node:fs");
|
|
51794
|
+
const { join: join73 } = await import("node:path");
|
|
51795
|
+
const perfPath = join73(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
51796
|
+
const raw = existsSync64(perfPath) ? readFileSync61(perfPath, "utf-8") : "";
|
|
51107
51797
|
const result = filterWatchEvents(raw, { cursor, maxEvents: max_events });
|
|
51108
51798
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
51109
51799
|
}
|