gossipcat 0.6.6 → 0.6.8
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 +8 -0
- package/dist-dashboard/assets/index-BrM1EvA1.css +1 -0
- package/dist-dashboard/assets/index-CqSX6axm.js +81 -0
- package/dist-dashboard/index.html +2 -2
- package/dist-mcp/mcp-server.js +1498 -677
- package/docs/HANDBOOK.md +11 -3
- package/package.json +3 -2
- package/dist-dashboard/assets/index-BEKs0u32.js +0 -81
- package/dist-dashboard/assets/index-CxBsFpD6.css +0 -1
package/dist-mcp/mcp-server.js
CHANGED
|
@@ -420,11 +420,11 @@ var require_codegen = __commonJS({
|
|
|
420
420
|
const rhs = this.rhs === void 0 ? "" : ` = ${this.rhs}`;
|
|
421
421
|
return `${varKind} ${this.name}${rhs};` + _n;
|
|
422
422
|
}
|
|
423
|
-
optimizeNames(names,
|
|
423
|
+
optimizeNames(names, constants4) {
|
|
424
424
|
if (!names[this.name.str])
|
|
425
425
|
return;
|
|
426
426
|
if (this.rhs)
|
|
427
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
427
|
+
this.rhs = optimizeExpr(this.rhs, names, constants4);
|
|
428
428
|
return this;
|
|
429
429
|
}
|
|
430
430
|
get names() {
|
|
@@ -441,10 +441,10 @@ var require_codegen = __commonJS({
|
|
|
441
441
|
render({ _n }) {
|
|
442
442
|
return `${this.lhs} = ${this.rhs};` + _n;
|
|
443
443
|
}
|
|
444
|
-
optimizeNames(names,
|
|
444
|
+
optimizeNames(names, constants4) {
|
|
445
445
|
if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
|
|
446
446
|
return;
|
|
447
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
447
|
+
this.rhs = optimizeExpr(this.rhs, names, constants4);
|
|
448
448
|
return this;
|
|
449
449
|
}
|
|
450
450
|
get names() {
|
|
@@ -505,8 +505,8 @@ var require_codegen = __commonJS({
|
|
|
505
505
|
optimizeNodes() {
|
|
506
506
|
return `${this.code}` ? this : void 0;
|
|
507
507
|
}
|
|
508
|
-
optimizeNames(names,
|
|
509
|
-
this.code = optimizeExpr(this.code, names,
|
|
508
|
+
optimizeNames(names, constants4) {
|
|
509
|
+
this.code = optimizeExpr(this.code, names, constants4);
|
|
510
510
|
return this;
|
|
511
511
|
}
|
|
512
512
|
get names() {
|
|
@@ -535,12 +535,12 @@ var require_codegen = __commonJS({
|
|
|
535
535
|
}
|
|
536
536
|
return nodes.length > 0 ? this : void 0;
|
|
537
537
|
}
|
|
538
|
-
optimizeNames(names,
|
|
538
|
+
optimizeNames(names, constants4) {
|
|
539
539
|
const { nodes } = this;
|
|
540
540
|
let i = nodes.length;
|
|
541
541
|
while (i--) {
|
|
542
542
|
const n = nodes[i];
|
|
543
|
-
if (n.optimizeNames(names,
|
|
543
|
+
if (n.optimizeNames(names, constants4))
|
|
544
544
|
continue;
|
|
545
545
|
subtractNames(names, n.names);
|
|
546
546
|
nodes.splice(i, 1);
|
|
@@ -593,12 +593,12 @@ var require_codegen = __commonJS({
|
|
|
593
593
|
return void 0;
|
|
594
594
|
return this;
|
|
595
595
|
}
|
|
596
|
-
optimizeNames(names,
|
|
596
|
+
optimizeNames(names, constants4) {
|
|
597
597
|
var _a3;
|
|
598
|
-
this.else = (_a3 = this.else) === null || _a3 === void 0 ? void 0 : _a3.optimizeNames(names,
|
|
599
|
-
if (!(super.optimizeNames(names,
|
|
598
|
+
this.else = (_a3 = this.else) === null || _a3 === void 0 ? void 0 : _a3.optimizeNames(names, constants4);
|
|
599
|
+
if (!(super.optimizeNames(names, constants4) || this.else))
|
|
600
600
|
return;
|
|
601
|
-
this.condition = optimizeExpr(this.condition, names,
|
|
601
|
+
this.condition = optimizeExpr(this.condition, names, constants4);
|
|
602
602
|
return this;
|
|
603
603
|
}
|
|
604
604
|
get names() {
|
|
@@ -621,10 +621,10 @@ var require_codegen = __commonJS({
|
|
|
621
621
|
render(opts) {
|
|
622
622
|
return `for(${this.iteration})` + super.render(opts);
|
|
623
623
|
}
|
|
624
|
-
optimizeNames(names,
|
|
625
|
-
if (!super.optimizeNames(names,
|
|
624
|
+
optimizeNames(names, constants4) {
|
|
625
|
+
if (!super.optimizeNames(names, constants4))
|
|
626
626
|
return;
|
|
627
|
-
this.iteration = optimizeExpr(this.iteration, names,
|
|
627
|
+
this.iteration = optimizeExpr(this.iteration, names, constants4);
|
|
628
628
|
return this;
|
|
629
629
|
}
|
|
630
630
|
get names() {
|
|
@@ -660,10 +660,10 @@ var require_codegen = __commonJS({
|
|
|
660
660
|
render(opts) {
|
|
661
661
|
return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
|
|
662
662
|
}
|
|
663
|
-
optimizeNames(names,
|
|
664
|
-
if (!super.optimizeNames(names,
|
|
663
|
+
optimizeNames(names, constants4) {
|
|
664
|
+
if (!super.optimizeNames(names, constants4))
|
|
665
665
|
return;
|
|
666
|
-
this.iterable = optimizeExpr(this.iterable, names,
|
|
666
|
+
this.iterable = optimizeExpr(this.iterable, names, constants4);
|
|
667
667
|
return this;
|
|
668
668
|
}
|
|
669
669
|
get names() {
|
|
@@ -705,11 +705,11 @@ var require_codegen = __commonJS({
|
|
|
705
705
|
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNodes();
|
|
706
706
|
return this;
|
|
707
707
|
}
|
|
708
|
-
optimizeNames(names,
|
|
708
|
+
optimizeNames(names, constants4) {
|
|
709
709
|
var _a3, _b;
|
|
710
|
-
super.optimizeNames(names,
|
|
711
|
-
(_a3 = this.catch) === null || _a3 === void 0 ? void 0 : _a3.optimizeNames(names,
|
|
712
|
-
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names,
|
|
710
|
+
super.optimizeNames(names, constants4);
|
|
711
|
+
(_a3 = this.catch) === null || _a3 === void 0 ? void 0 : _a3.optimizeNames(names, constants4);
|
|
712
|
+
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants4);
|
|
713
713
|
return this;
|
|
714
714
|
}
|
|
715
715
|
get names() {
|
|
@@ -1010,7 +1010,7 @@ var require_codegen = __commonJS({
|
|
|
1010
1010
|
function addExprNames(names, from) {
|
|
1011
1011
|
return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
|
|
1012
1012
|
}
|
|
1013
|
-
function optimizeExpr(expr, names,
|
|
1013
|
+
function optimizeExpr(expr, names, constants4) {
|
|
1014
1014
|
if (expr instanceof code_1.Name)
|
|
1015
1015
|
return replaceName(expr);
|
|
1016
1016
|
if (!canOptimize(expr))
|
|
@@ -1025,14 +1025,14 @@ var require_codegen = __commonJS({
|
|
|
1025
1025
|
return items;
|
|
1026
1026
|
}, []));
|
|
1027
1027
|
function replaceName(n) {
|
|
1028
|
-
const c =
|
|
1028
|
+
const c = constants4[n.str];
|
|
1029
1029
|
if (c === void 0 || names[n.str] !== 1)
|
|
1030
1030
|
return n;
|
|
1031
1031
|
delete names[n.str];
|
|
1032
1032
|
return c;
|
|
1033
1033
|
}
|
|
1034
1034
|
function canOptimize(e) {
|
|
1035
|
-
return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 &&
|
|
1035
|
+
return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants4[c.str] !== void 0);
|
|
1036
1036
|
}
|
|
1037
1037
|
}
|
|
1038
1038
|
function subtractNames(names, from) {
|
|
@@ -2994,7 +2994,7 @@ var require_compile = __commonJS({
|
|
|
2994
2994
|
const schOrFunc = root.refs[ref];
|
|
2995
2995
|
if (schOrFunc)
|
|
2996
2996
|
return schOrFunc;
|
|
2997
|
-
let _sch =
|
|
2997
|
+
let _sch = resolve33.call(this, root, ref);
|
|
2998
2998
|
if (_sch === void 0) {
|
|
2999
2999
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
3000
3000
|
const { schemaId } = this.opts;
|
|
@@ -3021,7 +3021,7 @@ var require_compile = __commonJS({
|
|
|
3021
3021
|
function sameSchemaEnv(s1, s2) {
|
|
3022
3022
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3023
3023
|
}
|
|
3024
|
-
function
|
|
3024
|
+
function resolve33(root, ref) {
|
|
3025
3025
|
let sch;
|
|
3026
3026
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3027
3027
|
ref = sch;
|
|
@@ -3239,8 +3239,8 @@ var require_utils = __commonJS({
|
|
|
3239
3239
|
}
|
|
3240
3240
|
return ind;
|
|
3241
3241
|
}
|
|
3242
|
-
function removeDotSegments(
|
|
3243
|
-
let input =
|
|
3242
|
+
function removeDotSegments(path8) {
|
|
3243
|
+
let input = path8;
|
|
3244
3244
|
const output = [];
|
|
3245
3245
|
let nextSlash = -1;
|
|
3246
3246
|
let len = 0;
|
|
@@ -3492,8 +3492,8 @@ var require_schemes = __commonJS({
|
|
|
3492
3492
|
wsComponent.secure = void 0;
|
|
3493
3493
|
}
|
|
3494
3494
|
if (wsComponent.resourceName) {
|
|
3495
|
-
const [
|
|
3496
|
-
wsComponent.path =
|
|
3495
|
+
const [path8, query] = wsComponent.resourceName.split("?");
|
|
3496
|
+
wsComponent.path = path8 && path8 !== "/" ? path8 : void 0;
|
|
3497
3497
|
wsComponent.query = query;
|
|
3498
3498
|
wsComponent.resourceName = void 0;
|
|
3499
3499
|
}
|
|
@@ -3652,7 +3652,7 @@ var require_fast_uri = __commonJS({
|
|
|
3652
3652
|
}
|
|
3653
3653
|
return uri;
|
|
3654
3654
|
}
|
|
3655
|
-
function
|
|
3655
|
+
function resolve33(baseURI, relativeURI, options) {
|
|
3656
3656
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3657
3657
|
const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3658
3658
|
schemelessOptions.skipEscape = true;
|
|
@@ -3910,7 +3910,7 @@ var require_fast_uri = __commonJS({
|
|
|
3910
3910
|
var fastUri = {
|
|
3911
3911
|
SCHEMES,
|
|
3912
3912
|
normalize: normalize3,
|
|
3913
|
-
resolve:
|
|
3913
|
+
resolve: resolve33,
|
|
3914
3914
|
resolveComponent,
|
|
3915
3915
|
equal,
|
|
3916
3916
|
serialize,
|
|
@@ -6886,12 +6886,12 @@ var require_dist = __commonJS({
|
|
|
6886
6886
|
throw new Error(`Unknown format "${name}"`);
|
|
6887
6887
|
return f;
|
|
6888
6888
|
};
|
|
6889
|
-
function addFormats(ajv, list,
|
|
6889
|
+
function addFormats(ajv, list, fs7, exportName) {
|
|
6890
6890
|
var _a3;
|
|
6891
6891
|
var _b;
|
|
6892
6892
|
(_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
6893
6893
|
for (const f of list)
|
|
6894
|
-
ajv.addFormat(f,
|
|
6894
|
+
ajv.addFormat(f, fs7[f]);
|
|
6895
6895
|
}
|
|
6896
6896
|
module2.exports = exports2 = formatsPlugin;
|
|
6897
6897
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -6967,11 +6967,14 @@ var init_mcp_context = __esm({
|
|
|
6967
6967
|
// packages/orchestrator/src/log.ts
|
|
6968
6968
|
function ts() {
|
|
6969
6969
|
const d = /* @__PURE__ */ new Date();
|
|
6970
|
+
const yyyy = d.getUTCFullYear();
|
|
6971
|
+
const mo = String(d.getUTCMonth() + 1).padStart(2, "0");
|
|
6972
|
+
const dd = String(d.getUTCDate()).padStart(2, "0");
|
|
6970
6973
|
const hh = String(d.getUTCHours()).padStart(2, "0");
|
|
6971
6974
|
const mm = String(d.getUTCMinutes()).padStart(2, "0");
|
|
6972
6975
|
const ss = String(d.getUTCSeconds()).padStart(2, "0");
|
|
6973
6976
|
const ms = String(d.getUTCMilliseconds()).padStart(3, "0");
|
|
6974
|
-
return `${hh}:${mm}:${ss}.${ms}`;
|
|
6977
|
+
return `${yyyy}-${mo}-${dd} ${hh}:${mm}:${ss}.${ms}Z`;
|
|
6975
6978
|
}
|
|
6976
6979
|
function emojiFor(tag) {
|
|
6977
6980
|
if (TAG_EMOJI[tag]) return TAG_EMOJI[tag];
|
|
@@ -7009,9 +7012,9 @@ var init_log = __esm({
|
|
|
7009
7012
|
function statePath(projectRoot) {
|
|
7010
7013
|
return (0, import_path4.join)(projectRoot, ".gossip", "auth-state.json");
|
|
7011
7014
|
}
|
|
7012
|
-
function readState(
|
|
7015
|
+
function readState(path8) {
|
|
7013
7016
|
try {
|
|
7014
|
-
return JSON.parse((0, import_fs5.readFileSync)(
|
|
7017
|
+
return JSON.parse((0, import_fs5.readFileSync)(path8, "utf-8"));
|
|
7015
7018
|
} catch {
|
|
7016
7019
|
return {};
|
|
7017
7020
|
}
|
|
@@ -7020,33 +7023,33 @@ function recordAuthFailure(projectRoot, provider, status) {
|
|
|
7020
7023
|
if (!projectRoot) return;
|
|
7021
7024
|
if (!PROVIDER_RE.test(provider)) return;
|
|
7022
7025
|
try {
|
|
7023
|
-
const
|
|
7024
|
-
const dir = (0, import_path4.join)(
|
|
7026
|
+
const path8 = statePath(projectRoot);
|
|
7027
|
+
const dir = (0, import_path4.join)(path8, "..");
|
|
7025
7028
|
if (!(0, import_fs5.existsSync)(dir)) (0, import_fs5.mkdirSync)(dir, { recursive: true });
|
|
7026
|
-
const existing = readState(
|
|
7029
|
+
const existing = readState(path8);
|
|
7027
7030
|
existing[provider] = { status, at: Date.now() };
|
|
7028
|
-
(0, import_fs5.writeFileSync)(
|
|
7031
|
+
(0, import_fs5.writeFileSync)(path8, JSON.stringify(existing, null, 2));
|
|
7029
7032
|
} catch {
|
|
7030
7033
|
}
|
|
7031
7034
|
}
|
|
7032
7035
|
function clearAuthFailure(projectRoot, provider) {
|
|
7033
7036
|
if (!projectRoot) return;
|
|
7034
7037
|
try {
|
|
7035
|
-
const
|
|
7036
|
-
if (!(0, import_fs5.existsSync)(
|
|
7037
|
-
const existing = readState(
|
|
7038
|
+
const path8 = statePath(projectRoot);
|
|
7039
|
+
if (!(0, import_fs5.existsSync)(path8)) return;
|
|
7040
|
+
const existing = readState(path8);
|
|
7038
7041
|
if (!(provider in existing)) return;
|
|
7039
7042
|
delete existing[provider];
|
|
7040
|
-
(0, import_fs5.writeFileSync)(
|
|
7043
|
+
(0, import_fs5.writeFileSync)(path8, JSON.stringify(existing, null, 2));
|
|
7041
7044
|
} catch {
|
|
7042
7045
|
}
|
|
7043
7046
|
}
|
|
7044
7047
|
function readRecentAuthFailures(projectRoot, ttlMs = 6 * 60 * 60 * 1e3) {
|
|
7045
7048
|
if (!projectRoot) return [];
|
|
7046
7049
|
try {
|
|
7047
|
-
const
|
|
7048
|
-
if (!(0, import_fs5.existsSync)(
|
|
7049
|
-
const state = readState(
|
|
7050
|
+
const path8 = statePath(projectRoot);
|
|
7051
|
+
if (!(0, import_fs5.existsSync)(path8)) return [];
|
|
7052
|
+
const state = readState(path8);
|
|
7050
7053
|
const now = Date.now();
|
|
7051
7054
|
const out = [];
|
|
7052
7055
|
for (const [provider, entry] of Object.entries(state)) {
|
|
@@ -13951,7 +13954,7 @@ var init_gossip_agent = __esm({
|
|
|
13951
13954
|
}
|
|
13952
13955
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
13953
13956
|
connect() {
|
|
13954
|
-
return new Promise((
|
|
13957
|
+
return new Promise((resolve33, reject) => {
|
|
13955
13958
|
const ws = new wrapper_default(this.config.relayUrl);
|
|
13956
13959
|
const timeout = setTimeout(() => {
|
|
13957
13960
|
ws.removeAllListeners();
|
|
@@ -13984,7 +13987,7 @@ var init_gossip_agent = __esm({
|
|
|
13984
13987
|
ws.on("error", (err) => this.emit("error", err));
|
|
13985
13988
|
this.startKeepAlive();
|
|
13986
13989
|
this.emit("connect", msg.sessionId);
|
|
13987
|
-
|
|
13990
|
+
resolve33();
|
|
13988
13991
|
} else if (msg.type === "error") {
|
|
13989
13992
|
clearTimeout(timeout);
|
|
13990
13993
|
ws.removeAllListeners();
|
|
@@ -14010,7 +14013,7 @@ var init_gossip_agent = __esm({
|
|
|
14010
14013
|
this.reconnectTimer = null;
|
|
14011
14014
|
}
|
|
14012
14015
|
if (!this.ws) return;
|
|
14013
|
-
return new Promise((
|
|
14016
|
+
return new Promise((resolve33) => {
|
|
14014
14017
|
this.intentionalDisconnect = true;
|
|
14015
14018
|
this._connected = false;
|
|
14016
14019
|
const ws = this.ws;
|
|
@@ -14021,7 +14024,7 @@ var init_gossip_agent = __esm({
|
|
|
14021
14024
|
settled = true;
|
|
14022
14025
|
this.intentionalDisconnect = false;
|
|
14023
14026
|
this.emit("disconnect", code);
|
|
14024
|
-
|
|
14027
|
+
resolve33();
|
|
14025
14028
|
};
|
|
14026
14029
|
const timer = setTimeout(() => done(1e3), 2e3);
|
|
14027
14030
|
ws.once("close", (code) => {
|
|
@@ -14060,8 +14063,8 @@ var init_gossip_agent = __esm({
|
|
|
14060
14063
|
throw new Error("Not connected to relay");
|
|
14061
14064
|
}
|
|
14062
14065
|
const encoded = Buffer.from(this.codec.encode(envelope));
|
|
14063
|
-
return new Promise((
|
|
14064
|
-
this.ws.send(encoded, (err) => err ? reject(err) :
|
|
14066
|
+
return new Promise((resolve33, reject) => {
|
|
14067
|
+
this.ws.send(encoded, (err) => err ? reject(err) : resolve33());
|
|
14065
14068
|
});
|
|
14066
14069
|
}
|
|
14067
14070
|
// ─── Internal ────────────────────────────────────────────────────────────────
|
|
@@ -14541,7 +14544,7 @@ ${context}` : ""}
|
|
|
14541
14544
|
this.memoryQueryCalled = true;
|
|
14542
14545
|
}
|
|
14543
14546
|
const requestId = (0, import_crypto6.randomUUID)();
|
|
14544
|
-
const resultPromise = new Promise((
|
|
14547
|
+
const resultPromise = new Promise((resolve33, reject) => {
|
|
14545
14548
|
const timer = setTimeout(() => {
|
|
14546
14549
|
if (this.pendingToolCalls.has(requestId)) {
|
|
14547
14550
|
this.pendingToolCalls.delete(requestId);
|
|
@@ -14552,7 +14555,7 @@ ${context}` : ""}
|
|
|
14552
14555
|
this.pendingToolCalls.set(requestId, {
|
|
14553
14556
|
resolve: (r) => {
|
|
14554
14557
|
clearTimeout(timer);
|
|
14555
|
-
|
|
14558
|
+
resolve33(r);
|
|
14556
14559
|
},
|
|
14557
14560
|
reject: (e) => {
|
|
14558
14561
|
clearTimeout(timer);
|
|
@@ -14617,13 +14620,17 @@ ${context}` : ""}
|
|
|
14617
14620
|
});
|
|
14618
14621
|
|
|
14619
14622
|
// packages/tools/src/file-tools.ts
|
|
14620
|
-
var import_promises, import_path6, import_fs7, FileTools;
|
|
14623
|
+
var import_promises, import_path6, import_fs7, import_re2, MAX_GREP_FILE_BYTES, MAX_GREP_MATCHES, MAX_GREP_FILES, FileTools;
|
|
14621
14624
|
var init_file_tools = __esm({
|
|
14622
14625
|
"packages/tools/src/file-tools.ts"() {
|
|
14623
14626
|
"use strict";
|
|
14624
14627
|
import_promises = require("fs/promises");
|
|
14625
14628
|
import_path6 = require("path");
|
|
14626
14629
|
import_fs7 = require("fs");
|
|
14630
|
+
import_re2 = __toESM(require("re2"));
|
|
14631
|
+
MAX_GREP_FILE_BYTES = 2 * 1024 * 1024;
|
|
14632
|
+
MAX_GREP_MATCHES = 2e3;
|
|
14633
|
+
MAX_GREP_FILES = 5e3;
|
|
14627
14634
|
FileTools = class {
|
|
14628
14635
|
constructor(sandbox) {
|
|
14629
14636
|
this.sandbox = sandbox;
|
|
@@ -14709,13 +14716,17 @@ var init_file_tools = __esm({
|
|
|
14709
14716
|
const searchRoot = args.path ? this.sandbox.validatePath(args.path, allowed) : agentRoot || this.sandbox.projectRoot;
|
|
14710
14717
|
let regex;
|
|
14711
14718
|
try {
|
|
14712
|
-
regex = new
|
|
14719
|
+
regex = new import_re2.default(args.pattern);
|
|
14713
14720
|
} catch (error51) {
|
|
14714
14721
|
return `Invalid regex pattern: ${error51 instanceof Error ? error51.message : "Unknown error"}`;
|
|
14715
14722
|
}
|
|
14716
|
-
const
|
|
14717
|
-
await this.grepDir(searchRoot, regex,
|
|
14718
|
-
|
|
14723
|
+
const state = { matches: [], filesScanned: 0, truncated: false };
|
|
14724
|
+
await this.grepDir(searchRoot, regex, state, 0, 10);
|
|
14725
|
+
let output = state.matches.join("\n") || "No matches found";
|
|
14726
|
+
if (state.truncated) {
|
|
14727
|
+
output += "\n... (truncated \u2014 result or scan limit reached; narrow your pattern/path)";
|
|
14728
|
+
}
|
|
14729
|
+
return output;
|
|
14719
14730
|
}
|
|
14720
14731
|
async fileTree(args, agentRoot) {
|
|
14721
14732
|
const allowed = agentRoot ? [agentRoot] : [];
|
|
@@ -14735,7 +14746,7 @@ var init_file_tools = __esm({
|
|
|
14735
14746
|
return;
|
|
14736
14747
|
}
|
|
14737
14748
|
const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
14738
|
-
const regex = new
|
|
14749
|
+
const regex = new import_re2.default(regexStr);
|
|
14739
14750
|
for (const entry of entries) {
|
|
14740
14751
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
14741
14752
|
const fullPath = (0, import_path6.join)(dir, entry);
|
|
@@ -14755,8 +14766,9 @@ var init_file_tools = __esm({
|
|
|
14755
14766
|
}
|
|
14756
14767
|
}
|
|
14757
14768
|
}
|
|
14758
|
-
async grepDir(dir, regex,
|
|
14769
|
+
async grepDir(dir, regex, state, depth = 0, maxDepth = 10) {
|
|
14759
14770
|
if (depth >= maxDepth) return;
|
|
14771
|
+
if (state.truncated) return;
|
|
14760
14772
|
let entries;
|
|
14761
14773
|
try {
|
|
14762
14774
|
entries = await (0, import_promises.readdir)(dir);
|
|
@@ -14764,6 +14776,7 @@ var init_file_tools = __esm({
|
|
|
14764
14776
|
return;
|
|
14765
14777
|
}
|
|
14766
14778
|
for (const entry of entries) {
|
|
14779
|
+
if (state.truncated) return;
|
|
14767
14780
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
14768
14781
|
const fullPath = (0, import_path6.join)(dir, entry);
|
|
14769
14782
|
let info;
|
|
@@ -14773,17 +14786,29 @@ var init_file_tools = __esm({
|
|
|
14773
14786
|
continue;
|
|
14774
14787
|
}
|
|
14775
14788
|
if (info.isDirectory()) {
|
|
14776
|
-
await this.grepDir(fullPath, regex,
|
|
14789
|
+
await this.grepDir(fullPath, regex, state, depth + 1, maxDepth);
|
|
14777
14790
|
} else {
|
|
14791
|
+
if (info.size > MAX_GREP_FILE_BYTES) {
|
|
14792
|
+
continue;
|
|
14793
|
+
}
|
|
14794
|
+
state.filesScanned++;
|
|
14795
|
+
if (state.filesScanned > MAX_GREP_FILES) {
|
|
14796
|
+
state.truncated = true;
|
|
14797
|
+
return;
|
|
14798
|
+
}
|
|
14778
14799
|
try {
|
|
14779
14800
|
const content = await (0, import_promises.readFile)(fullPath, "utf-8");
|
|
14780
14801
|
const lines = content.split("\n");
|
|
14781
14802
|
const relPath = (0, import_path6.relative)(this.sandbox.projectRoot, fullPath);
|
|
14782
|
-
lines.
|
|
14783
|
-
if (
|
|
14784
|
-
|
|
14803
|
+
for (let idx = 0; idx < lines.length; idx++) {
|
|
14804
|
+
if (state.matches.length >= MAX_GREP_MATCHES) {
|
|
14805
|
+
state.truncated = true;
|
|
14806
|
+
break;
|
|
14785
14807
|
}
|
|
14786
|
-
|
|
14808
|
+
if (regex.test(lines[idx])) {
|
|
14809
|
+
state.matches.push(`${relPath}:${idx + 1}: ${lines[idx]}`);
|
|
14810
|
+
}
|
|
14811
|
+
}
|
|
14787
14812
|
} catch {
|
|
14788
14813
|
}
|
|
14789
14814
|
}
|
|
@@ -15566,8 +15591,8 @@ var init_parseUtil = __esm({
|
|
|
15566
15591
|
init_errors2();
|
|
15567
15592
|
init_en();
|
|
15568
15593
|
makeIssue2 = (params) => {
|
|
15569
|
-
const { data, path:
|
|
15570
|
-
const fullPath = [...
|
|
15594
|
+
const { data, path: path8, errorMaps, issueData } = params;
|
|
15595
|
+
const fullPath = [...path8, ...issueData.path || []];
|
|
15571
15596
|
const fullIssue = {
|
|
15572
15597
|
...issueData,
|
|
15573
15598
|
path: fullPath
|
|
@@ -15878,11 +15903,11 @@ var init_types = __esm({
|
|
|
15878
15903
|
init_parseUtil();
|
|
15879
15904
|
init_util();
|
|
15880
15905
|
ParseInputLazyPath2 = class {
|
|
15881
|
-
constructor(parent, value,
|
|
15906
|
+
constructor(parent, value, path8, key) {
|
|
15882
15907
|
this._cachedPath = [];
|
|
15883
15908
|
this.parent = parent;
|
|
15884
15909
|
this.data = value;
|
|
15885
|
-
this._path =
|
|
15910
|
+
this._path = path8;
|
|
15886
15911
|
this._key = key;
|
|
15887
15912
|
}
|
|
15888
15913
|
get path() {
|
|
@@ -19916,7 +19941,7 @@ ${truncateAtLine(fullDiff, 3e3)}`;
|
|
|
19916
19941
|
}
|
|
19917
19942
|
async requestPeerReview(callerId, diff, testResult) {
|
|
19918
19943
|
const requestId = (0, import_crypto8.randomUUID)();
|
|
19919
|
-
const reviewPromise = new Promise((
|
|
19944
|
+
const reviewPromise = new Promise((resolve33, reject) => {
|
|
19920
19945
|
const timer = setTimeout(() => {
|
|
19921
19946
|
this.pendingReviews.delete(requestId);
|
|
19922
19947
|
reject(new Error("Review timed out"));
|
|
@@ -19925,7 +19950,7 @@ ${truncateAtLine(fullDiff, 3e3)}`;
|
|
|
19925
19950
|
this.pendingReviews.set(requestId, {
|
|
19926
19951
|
resolve: (r) => {
|
|
19927
19952
|
clearTimeout(timer);
|
|
19928
|
-
|
|
19953
|
+
resolve33(r);
|
|
19929
19954
|
},
|
|
19930
19955
|
reject: (e) => {
|
|
19931
19956
|
clearTimeout(timer);
|
|
@@ -20216,6 +20241,9 @@ __export(src_exports2, {
|
|
|
20216
20241
|
GIT_TOOLS: () => GIT_TOOLS,
|
|
20217
20242
|
GitTools: () => GitTools,
|
|
20218
20243
|
IDENTITY_TOOLS: () => IDENTITY_TOOLS,
|
|
20244
|
+
MAX_GREP_FILES: () => MAX_GREP_FILES,
|
|
20245
|
+
MAX_GREP_FILE_BYTES: () => MAX_GREP_FILE_BYTES,
|
|
20246
|
+
MAX_GREP_MATCHES: () => MAX_GREP_MATCHES,
|
|
20219
20247
|
MAX_MEMORY_QUERY_LOG_BYTES: () => MAX_MEMORY_QUERY_LOG_BYTES,
|
|
20220
20248
|
MEMORY_QUERY_LOG: () => MEMORY_QUERY_LOG,
|
|
20221
20249
|
MEMORY_TOOLS: () => MEMORY_TOOLS,
|
|
@@ -20296,7 +20324,14 @@ var init_consensus_types = __esm({
|
|
|
20296
20324
|
"transport_failure",
|
|
20297
20325
|
"worktree_isolation_failed",
|
|
20298
20326
|
"auto_verify_attempted",
|
|
20299
|
-
"auto_verify_skipped_misconfigured"
|
|
20327
|
+
"auto_verify_skipped_misconfigured",
|
|
20328
|
+
/**
|
|
20329
|
+
* Orchestrator dispatch-hygiene signals (UNIT 1 — orchestrator signal pipeline).
|
|
20330
|
+
* Tallied as operational; never affect agent accuracy scoring.
|
|
20331
|
+
*/
|
|
20332
|
+
"dispatched_stale_base",
|
|
20333
|
+
"referenced_unreadable_path",
|
|
20334
|
+
"mid_flight_fixup"
|
|
20300
20335
|
]);
|
|
20301
20336
|
}
|
|
20302
20337
|
});
|
|
@@ -20324,21 +20359,21 @@ function extractFrontmatterField(content, field) {
|
|
|
20324
20359
|
return null;
|
|
20325
20360
|
}
|
|
20326
20361
|
function readSkillFreshness(agentId, category, skillRoot) {
|
|
20327
|
-
const
|
|
20328
|
-
if (!(0, import_fs12.existsSync)(
|
|
20329
|
-
return { boundAt: null, status: null, path:
|
|
20362
|
+
const path8 = resolveSkillFilePath(agentId, category, skillRoot);
|
|
20363
|
+
if (!(0, import_fs12.existsSync)(path8)) {
|
|
20364
|
+
return { boundAt: null, status: null, path: path8, regressedFromPassedAt: null };
|
|
20330
20365
|
}
|
|
20331
20366
|
let content;
|
|
20332
20367
|
try {
|
|
20333
|
-
content = (0, import_fs12.readFileSync)(
|
|
20368
|
+
content = (0, import_fs12.readFileSync)(path8, "utf-8");
|
|
20334
20369
|
} catch {
|
|
20335
|
-
return { boundAt: null, status: null, path:
|
|
20370
|
+
return { boundAt: null, status: null, path: path8, regressedFromPassedAt: null };
|
|
20336
20371
|
}
|
|
20337
20372
|
const boundAt = extractFrontmatterField(content, "bound_at");
|
|
20338
20373
|
const rawStatus = extractFrontmatterField(content, "status");
|
|
20339
20374
|
const status = rawStatus === null ? null : coerceStatus(rawStatus);
|
|
20340
20375
|
const regressedFromPassedAt = extractFrontmatterField(content, "regressed_from_passed_at");
|
|
20341
|
-
return { boundAt, status, path:
|
|
20376
|
+
return { boundAt, status, path: path8, regressedFromPassedAt };
|
|
20342
20377
|
}
|
|
20343
20378
|
function computeCooldown(input) {
|
|
20344
20379
|
let status;
|
|
@@ -21928,15 +21963,15 @@ function classifyForAggregate(signal) {
|
|
|
21928
21963
|
}
|
|
21929
21964
|
}
|
|
21930
21965
|
function readAggregateIndex(projectRoot) {
|
|
21931
|
-
const
|
|
21932
|
-
if (!(0, import_fs14.existsSync)(
|
|
21966
|
+
const path8 = (0, import_path14.join)(projectRoot, ".gossip", SIDECAR_FILENAME);
|
|
21967
|
+
if (!(0, import_fs14.existsSync)(path8)) {
|
|
21933
21968
|
cachedAggregateData = null;
|
|
21934
21969
|
cachedAggregateMtimeMs = 0;
|
|
21935
21970
|
return null;
|
|
21936
21971
|
}
|
|
21937
21972
|
let mtimeMs = 0;
|
|
21938
21973
|
try {
|
|
21939
|
-
mtimeMs = (0, import_fs14.statSync)(
|
|
21974
|
+
mtimeMs = (0, import_fs14.statSync)(path8).mtimeMs;
|
|
21940
21975
|
} catch (err) {
|
|
21941
21976
|
logSidecarError("stat", err);
|
|
21942
21977
|
return null;
|
|
@@ -21946,7 +21981,7 @@ function readAggregateIndex(projectRoot) {
|
|
|
21946
21981
|
}
|
|
21947
21982
|
let raw;
|
|
21948
21983
|
try {
|
|
21949
|
-
raw = (0, import_fs14.readFileSync)(
|
|
21984
|
+
raw = (0, import_fs14.readFileSync)(path8, "utf-8");
|
|
21950
21985
|
} catch (err) {
|
|
21951
21986
|
logSidecarError("read", err);
|
|
21952
21987
|
return null;
|
|
@@ -21982,14 +22017,14 @@ function readAggregateIndex(projectRoot) {
|
|
|
21982
22017
|
return result;
|
|
21983
22018
|
}
|
|
21984
22019
|
function writeAggregateIndex(projectRoot, data) {
|
|
21985
|
-
const
|
|
22020
|
+
const path8 = (0, import_path14.join)(projectRoot, ".gossip", SIDECAR_FILENAME);
|
|
21986
22021
|
try {
|
|
21987
|
-
(0, import_fs14.mkdirSync)((0, import_path14.dirname)(
|
|
21988
|
-
const tmp =
|
|
22022
|
+
(0, import_fs14.mkdirSync)((0, import_path14.dirname)(path8), { recursive: true });
|
|
22023
|
+
const tmp = path8 + ".tmp";
|
|
21989
22024
|
(0, import_fs14.writeFileSync)(tmp, JSON.stringify(data, null, 2) + "\n");
|
|
21990
|
-
(0, import_fs14.renameSync)(tmp,
|
|
22025
|
+
(0, import_fs14.renameSync)(tmp, path8);
|
|
21991
22026
|
cachedAggregateData = data;
|
|
21992
|
-
cachedAggregateMtimeMs = (0, import_fs14.statSync)(
|
|
22027
|
+
cachedAggregateMtimeMs = (0, import_fs14.statSync)(path8).mtimeMs;
|
|
21993
22028
|
} catch (err) {
|
|
21994
22029
|
logSidecarError("write", err);
|
|
21995
22030
|
}
|
|
@@ -22375,14 +22410,14 @@ var init_performance_reader = __esm({
|
|
|
22375
22410
|
*/
|
|
22376
22411
|
getSkillIndexEnabledMap() {
|
|
22377
22412
|
if (this.skillIndexCache !== void 0) return this.skillIndexCache;
|
|
22378
|
-
const
|
|
22413
|
+
const path8 = (0, import_path15.join)(this.projectRoot, ".gossip", "skill-index.json");
|
|
22379
22414
|
let parsed;
|
|
22380
22415
|
try {
|
|
22381
|
-
if (!(0, import_fs15.existsSync)(
|
|
22416
|
+
if (!(0, import_fs15.existsSync)(path8)) {
|
|
22382
22417
|
this.skillIndexCache = null;
|
|
22383
22418
|
return null;
|
|
22384
22419
|
}
|
|
22385
|
-
parsed = JSON.parse((0, import_fs15.readFileSync)(
|
|
22420
|
+
parsed = JSON.parse((0, import_fs15.readFileSync)(path8, "utf-8"));
|
|
22386
22421
|
} catch {
|
|
22387
22422
|
this.skillIndexCache = null;
|
|
22388
22423
|
return null;
|
|
@@ -23776,7 +23811,14 @@ var init_performance_writer = __esm({
|
|
|
23776
23811
|
"relay_findings_dropped",
|
|
23777
23812
|
// Phase A self-telemetry: collect-end reconciliation detected fewer signals
|
|
23778
23813
|
// written than findings in the consensus report. Observability-only.
|
|
23779
|
-
"signal_loss_suspected"
|
|
23814
|
+
"signal_loss_suspected",
|
|
23815
|
+
// UNIT 1 orchestrator signal pipeline: dispatch-hygiene precondition signals.
|
|
23816
|
+
// Operational-only (tallied, never scored). Emitted by orchestrator-preconditions.ts
|
|
23817
|
+
// when a dispatch-hygiene failure is detected (stale base, unreadable reference
|
|
23818
|
+
// paths, mid-flight commits during a consensus round).
|
|
23819
|
+
"dispatched_stale_base",
|
|
23820
|
+
"referenced_unreadable_path",
|
|
23821
|
+
"mid_flight_fixup"
|
|
23780
23822
|
]);
|
|
23781
23823
|
SYSTEM_SENTINEL_AGENT_ID = "_system";
|
|
23782
23824
|
rowsWrittenSinceCheck = 0;
|
|
@@ -24489,13 +24531,13 @@ function resolveSkill(agentId, skill, projectRoot) {
|
|
|
24489
24531
|
if ((0, import_fs19.existsSync)(candidate)) {
|
|
24490
24532
|
try {
|
|
24491
24533
|
const content = (0, import_fs19.readFileSync)(candidate, "utf-8");
|
|
24492
|
-
let
|
|
24534
|
+
let path8;
|
|
24493
24535
|
try {
|
|
24494
|
-
|
|
24536
|
+
path8 = (0, import_fs19.realpathSync)(candidate);
|
|
24495
24537
|
} catch {
|
|
24496
|
-
|
|
24538
|
+
path8 = candidate;
|
|
24497
24539
|
}
|
|
24498
|
-
return { content, path:
|
|
24540
|
+
return { content, path: path8 };
|
|
24499
24541
|
} catch (err) {
|
|
24500
24542
|
log("skill-loader", `Failed to read skill file ${candidate}: ${err?.message ?? err}`);
|
|
24501
24543
|
continue;
|
|
@@ -25599,14 +25641,14 @@ ${cleanSummary}` : cleanSummary;
|
|
|
25599
25641
|
const citations = [];
|
|
25600
25642
|
let m;
|
|
25601
25643
|
while ((m = fileRegex.exec(body)) !== null) {
|
|
25602
|
-
const
|
|
25644
|
+
const path8 = m[1];
|
|
25603
25645
|
const before = body.slice(Math.max(0, m.index - 8), m.index + 1);
|
|
25604
|
-
if (/https?:\/\//.test(before) || /https?:\/\//.test(
|
|
25646
|
+
if (/https?:\/\//.test(before) || /https?:\/\//.test(path8)) continue;
|
|
25605
25647
|
const line = m[2] ? parseInt(m[2], 10) : void 0;
|
|
25606
|
-
const key = line !== void 0 ? `${
|
|
25648
|
+
const key = line !== void 0 ? `${path8}:${line}` : path8;
|
|
25607
25649
|
if (seen.has(key)) continue;
|
|
25608
25650
|
seen.add(key);
|
|
25609
|
-
citations.push({ path:
|
|
25651
|
+
citations.push({ path: path8, line, key });
|
|
25610
25652
|
}
|
|
25611
25653
|
const roots = [this.projectRoot, ...resolutionRoots ?? []];
|
|
25612
25654
|
const unverified = [];
|
|
@@ -29268,12 +29310,12 @@ async function getUncategorizedStatusLine(projectRoot, opts) {
|
|
|
29268
29310
|
let mostRecentText = "";
|
|
29269
29311
|
let mostRecentTs = 0;
|
|
29270
29312
|
const uncatPath = (0, import_path31.join)(projectRoot, ".gossip", "uncategorized-findings.jsonl");
|
|
29271
|
-
const scanFile = (filePath) => new Promise((
|
|
29313
|
+
const scanFile = (filePath) => new Promise((resolve33) => {
|
|
29272
29314
|
if (!(0, import_fs29.existsSync)(filePath)) {
|
|
29273
|
-
return
|
|
29315
|
+
return resolve33();
|
|
29274
29316
|
}
|
|
29275
29317
|
const stream = (0, import_fs29.createReadStream)(filePath, { encoding: "utf8" });
|
|
29276
|
-
stream.on("error", () =>
|
|
29318
|
+
stream.on("error", () => resolve33());
|
|
29277
29319
|
const rl = (0, import_readline.createInterface)({ input: stream, crlfDelay: Infinity });
|
|
29278
29320
|
rl.on("line", (line) => {
|
|
29279
29321
|
if (!line) return;
|
|
@@ -29290,8 +29332,8 @@ async function getUncategorizedStatusLine(projectRoot, opts) {
|
|
|
29290
29332
|
} catch {
|
|
29291
29333
|
}
|
|
29292
29334
|
});
|
|
29293
|
-
rl.on("close",
|
|
29294
|
-
rl.on("error", () =>
|
|
29335
|
+
rl.on("close", resolve33);
|
|
29336
|
+
rl.on("error", () => resolve33());
|
|
29295
29337
|
});
|
|
29296
29338
|
await scanFile(uncatPath);
|
|
29297
29339
|
if ((0, import_fs29.existsSync)(uncatPath + ".1")) {
|
|
@@ -29480,6 +29522,26 @@ var init_consensus_engine = __esm({
|
|
|
29480
29522
|
if (!report.warnings) report.warnings = [];
|
|
29481
29523
|
report.warnings.push(entry);
|
|
29482
29524
|
}
|
|
29525
|
+
/**
|
|
29526
|
+
* Idempotent helper: appends the UNSCORED ROUND banner to report.summary and
|
|
29527
|
+
* records a zero_tags warning when any agents emitted zero <agent_finding> tags.
|
|
29528
|
+
* Safe to call multiple times — skips if the banner is already present or if
|
|
29529
|
+
* zeroTagAgents is empty/absent.
|
|
29530
|
+
* Called at each finalization point: run(), runSelectedCrossReview(), and
|
|
29531
|
+
* synthesizeWithCrossReview() — so ALL synthesize paths surface the banner.
|
|
29532
|
+
*/
|
|
29533
|
+
surfaceZeroTagBanner(report) {
|
|
29534
|
+
if (!report.zeroTagAgents?.length) return;
|
|
29535
|
+
if (report.summary.includes("UNSCORED ROUND")) return;
|
|
29536
|
+
const n = report.zeroTagAgents.length;
|
|
29537
|
+
const overflow = report.zeroTagOverflow ?? 0;
|
|
29538
|
+
const list = report.zeroTagAgents.join(", ");
|
|
29539
|
+
const evidence = `UNSCORED ROUND \u2014 ${n}${overflow > 0 ? "+" + overflow : ""} agent(s) emitted zero <agent_finding> tags; their output was bullet-parsed and CONFIRMED/DISPUTED scoring was NOT computed for them (agents: ${list})`;
|
|
29540
|
+
report.summary += `
|
|
29541
|
+
\u26A0\uFE0F ${evidence}
|
|
29542
|
+
`;
|
|
29543
|
+
this.appendReportWarning(report, "zero_tags", evidence);
|
|
29544
|
+
}
|
|
29483
29545
|
/** True when a PerformanceReader is available for orchestrator-selected cross-review (Step 3). */
|
|
29484
29546
|
get hasPerformanceReader() {
|
|
29485
29547
|
return this.config.performanceReader !== void 0;
|
|
@@ -29730,6 +29792,7 @@ var init_consensus_engine = __esm({
|
|
|
29730
29792
|
);
|
|
29731
29793
|
report.unverified = enriched;
|
|
29732
29794
|
report.summary = this.formatReport(report.confirmed, report.disputed, report.unverified, report.unique, report.newFindings, successful.length, report.rounds, timing, report.insights);
|
|
29795
|
+
this.surfaceZeroTagBanner(report);
|
|
29733
29796
|
return report;
|
|
29734
29797
|
}
|
|
29735
29798
|
/**
|
|
@@ -30107,7 +30170,7 @@ Return only valid JSON.${skillsBlock}`;
|
|
|
30107
30170
|
}
|
|
30108
30171
|
log(
|
|
30109
30172
|
"consensus",
|
|
30110
|
-
`\u26A0 agent "${r.agentId}" emitted ZERO tags \u2014 falling back to bullet parsing.
|
|
30173
|
+
`\u26A0 agent "${r.agentId}" emitted ZERO tags \u2014 falling back to bullet parsing. Common causes: the dispatch/cross-review prompt instructed plain prose (no <agent_finding> tags), a design/research task where the agent emitted none, or a skill Output Format conflicting with the FINDING TAG SCHEMA. Verify the dispatch prompt keeps the schema in force.`
|
|
30111
30174
|
);
|
|
30112
30175
|
} else {
|
|
30113
30176
|
const offending = Object.entries(parseResult.droppedUnknownType).map(([t, n]) => `${t}:${n}`).join(",") || "(missing type attribute)";
|
|
@@ -31547,7 +31610,9 @@ ${safeSnippet}
|
|
|
31547
31610
|
}
|
|
31548
31611
|
if (findingSeq === 0) {
|
|
31549
31612
|
log("consensus", "runSelectedCrossReview: no structured findings extracted; synthesizing without cross-review");
|
|
31550
|
-
|
|
31613
|
+
const report2 = await this.synthesize(results, [], consensusId);
|
|
31614
|
+
this.surfaceZeroTagBanner(report2);
|
|
31615
|
+
return report2;
|
|
31551
31616
|
}
|
|
31552
31617
|
const agentCandidates = successful.map((r) => ({ agentId: r.agentId }));
|
|
31553
31618
|
const assignments = selectCrossReviewers(findingsForSelection, agentCandidates, performanceReader);
|
|
@@ -31555,6 +31620,7 @@ ${safeSnippet}
|
|
|
31555
31620
|
log("consensus", "runSelectedCrossReview: no reviewers selected; synthesizing without cross-review");
|
|
31556
31621
|
const report2 = await this.synthesize(results, [], consensusId);
|
|
31557
31622
|
this.appendReportWarning(report2, "partial_review", "no cross-reviewers selected \u2014 every finding is under-reviewed (0 of target K)");
|
|
31623
|
+
this.surfaceZeroTagBanner(report2);
|
|
31558
31624
|
return report2;
|
|
31559
31625
|
}
|
|
31560
31626
|
const reviewerCountPerFinding = /* @__PURE__ */ new Map();
|
|
@@ -31609,6 +31675,7 @@ ${safeSnippet}
|
|
|
31609
31675
|
assigned: reviewerCountPerFinding.get(f.id) ?? 0,
|
|
31610
31676
|
targetK: findingKMap.get(f.id) ?? 2
|
|
31611
31677
|
}));
|
|
31678
|
+
this.surfaceZeroTagBanner(report);
|
|
31612
31679
|
return report;
|
|
31613
31680
|
}
|
|
31614
31681
|
/**
|
|
@@ -31654,6 +31721,7 @@ ${safeSnippet}
|
|
|
31654
31721
|
`;
|
|
31655
31722
|
this.appendReportWarning(report, "coverage_degraded", evidence);
|
|
31656
31723
|
}
|
|
31724
|
+
this.surfaceZeroTagBanner(report);
|
|
31657
31725
|
if (relayCrossReviewSkipped && relayCrossReviewSkipped.length > 0) {
|
|
31658
31726
|
const lines = ["", "\u26A0\uFE0F Relay cross-review skipped:"];
|
|
31659
31727
|
for (const s of relayCrossReviewSkipped) {
|
|
@@ -34212,11 +34280,11 @@ var init_archetype_catalog = __esm({
|
|
|
34212
34280
|
ArchetypeCatalog = class {
|
|
34213
34281
|
archetypes;
|
|
34214
34282
|
constructor(catalogPath) {
|
|
34215
|
-
const
|
|
34216
|
-
if (!
|
|
34283
|
+
const path8 = catalogPath ?? findArchetypeCatalog();
|
|
34284
|
+
if (!path8) {
|
|
34217
34285
|
throw new Error("archetypes.json not found \u2014 tried bundled dist-mcp/data/, dev ts-node path, and cwd/data/. Reinstall gossipcat.");
|
|
34218
34286
|
}
|
|
34219
|
-
const raw = (0, import_fs34.readFileSync)(
|
|
34287
|
+
const raw = (0, import_fs34.readFileSync)(path8, "utf-8");
|
|
34220
34288
|
this.archetypes = JSON.parse(raw);
|
|
34221
34289
|
}
|
|
34222
34290
|
/** Return all archetype IDs */
|
|
@@ -34270,8 +34338,7 @@ function findBundledHook() {
|
|
|
34270
34338
|
const candidates = [
|
|
34271
34339
|
(0, import_path37.resolve)(__dirname, "assets", "hooks", HOOK_FILENAME),
|
|
34272
34340
|
(0, import_path37.resolve)(__dirname, "..", "..", "..", "assets", "hooks", HOOK_FILENAME),
|
|
34273
|
-
(0, import_path37.resolve)(__dirname, "..", "assets", "hooks", HOOK_FILENAME)
|
|
34274
|
-
(0, import_path37.resolve)(process.cwd(), "assets", "hooks", HOOK_FILENAME)
|
|
34341
|
+
(0, import_path37.resolve)(__dirname, "..", "assets", "hooks", HOOK_FILENAME)
|
|
34275
34342
|
];
|
|
34276
34343
|
for (const p of candidates) {
|
|
34277
34344
|
if ((0, import_fs35.existsSync)(p)) return p;
|
|
@@ -34331,11 +34398,6 @@ function installWorktreeSandboxHook(projectRoot) {
|
|
|
34331
34398
|
try {
|
|
34332
34399
|
const bundled = findBundledHook();
|
|
34333
34400
|
if (!bundled) return { installed: false, reason: "bundled hook asset not found" };
|
|
34334
|
-
const targetDir = (0, import_path37.join)(projectRoot, ".claude", "hooks");
|
|
34335
|
-
const target = (0, import_path37.join)(targetDir, HOOK_FILENAME);
|
|
34336
|
-
(0, import_fs35.mkdirSync)(targetDir, { recursive: true });
|
|
34337
|
-
(0, import_fs35.copyFileSync)(bundled, target);
|
|
34338
|
-
(0, import_fs35.chmodSync)(target, 493);
|
|
34339
34401
|
const settingsPath = (0, import_path37.join)(projectRoot, ".claude", "settings.json");
|
|
34340
34402
|
(0, import_fs35.mkdirSync)((0, import_path37.dirname)(settingsPath), { recursive: true });
|
|
34341
34403
|
let settings;
|
|
@@ -34348,6 +34410,11 @@ function installWorktreeSandboxHook(projectRoot) {
|
|
|
34348
34410
|
);
|
|
34349
34411
|
return { installed: false, reason: err.message };
|
|
34350
34412
|
}
|
|
34413
|
+
const targetDir = (0, import_path37.join)(projectRoot, ".claude", "hooks");
|
|
34414
|
+
const target = (0, import_path37.join)(targetDir, HOOK_FILENAME);
|
|
34415
|
+
(0, import_fs35.mkdirSync)(targetDir, { recursive: true });
|
|
34416
|
+
(0, import_fs35.copyFileSync)(bundled, target);
|
|
34417
|
+
(0, import_fs35.chmodSync)(target, 493);
|
|
34351
34418
|
const mutated = mergePreToolUseEntry(settings);
|
|
34352
34419
|
if (mutated) {
|
|
34353
34420
|
(0, import_fs35.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
@@ -34381,8 +34448,7 @@ function findDisciplineHook(filename) {
|
|
|
34381
34448
|
const candidates = [
|
|
34382
34449
|
(0, import_path37.resolve)(__dirname, "assets", "hooks", DISCIPLINE_HOOK_DIR, filename),
|
|
34383
34450
|
(0, import_path37.resolve)(__dirname, "..", "..", "..", "assets", "hooks", DISCIPLINE_HOOK_DIR, filename),
|
|
34384
|
-
(0, import_path37.resolve)(__dirname, "..", "assets", "hooks", DISCIPLINE_HOOK_DIR, filename)
|
|
34385
|
-
(0, import_path37.resolve)(process.cwd(), "assets", "hooks", DISCIPLINE_HOOK_DIR, filename)
|
|
34451
|
+
(0, import_path37.resolve)(__dirname, "..", "assets", "hooks", DISCIPLINE_HOOK_DIR, filename)
|
|
34386
34452
|
];
|
|
34387
34453
|
for (const p of candidates) {
|
|
34388
34454
|
if ((0, import_fs35.existsSync)(p)) return p;
|
|
@@ -34563,18 +34629,6 @@ function installDisciplineHooks(projectRoot) {
|
|
|
34563
34629
|
const installed = [];
|
|
34564
34630
|
const skipped = [];
|
|
34565
34631
|
try {
|
|
34566
|
-
const targetDir = (0, import_path37.join)(projectRoot, ".claude", "hooks", DISCIPLINE_HOOK_DIR);
|
|
34567
|
-
(0, import_fs35.mkdirSync)(targetDir, { recursive: true });
|
|
34568
|
-
for (const hook of DISCIPLINE_HOOKS) {
|
|
34569
|
-
const bundled = findDisciplineHook(hook.filename);
|
|
34570
|
-
if (!bundled) {
|
|
34571
|
-
skipped.push(hook.name);
|
|
34572
|
-
continue;
|
|
34573
|
-
}
|
|
34574
|
-
const target = (0, import_path37.join)(targetDir, hook.filename);
|
|
34575
|
-
(0, import_fs35.copyFileSync)(bundled, target);
|
|
34576
|
-
(0, import_fs35.chmodSync)(target, 493);
|
|
34577
|
-
}
|
|
34578
34632
|
const settingsPath = (0, import_path37.join)(projectRoot, ".claude", "settings.local.json");
|
|
34579
34633
|
(0, import_fs35.mkdirSync)((0, import_path37.dirname)(settingsPath), { recursive: true });
|
|
34580
34634
|
let settings;
|
|
@@ -34587,6 +34641,18 @@ function installDisciplineHooks(projectRoot) {
|
|
|
34587
34641
|
);
|
|
34588
34642
|
return { installed, skipped, reason: err.message };
|
|
34589
34643
|
}
|
|
34644
|
+
const targetDir = (0, import_path37.join)(projectRoot, ".claude", "hooks", DISCIPLINE_HOOK_DIR);
|
|
34645
|
+
(0, import_fs35.mkdirSync)(targetDir, { recursive: true });
|
|
34646
|
+
for (const hook of DISCIPLINE_HOOKS) {
|
|
34647
|
+
const bundled = findDisciplineHook(hook.filename);
|
|
34648
|
+
if (!bundled) {
|
|
34649
|
+
skipped.push(hook.name);
|
|
34650
|
+
continue;
|
|
34651
|
+
}
|
|
34652
|
+
const target = (0, import_path37.join)(targetDir, hook.filename);
|
|
34653
|
+
(0, import_fs35.copyFileSync)(bundled, target);
|
|
34654
|
+
(0, import_fs35.chmodSync)(target, 493);
|
|
34655
|
+
}
|
|
34590
34656
|
let anyMutated = false;
|
|
34591
34657
|
for (const hook of DISCIPLINE_HOOKS) {
|
|
34592
34658
|
const bundled = findDisciplineHook(hook.filename);
|
|
@@ -35274,8 +35340,8 @@ message: Your question?
|
|
|
35274
35340
|
}
|
|
35275
35341
|
/** Start all worker agents (connect to relay) */
|
|
35276
35342
|
async start() {
|
|
35277
|
-
const { existsSync:
|
|
35278
|
-
const { join:
|
|
35343
|
+
const { existsSync: existsSync74, readFileSync: readFileSync70 } = await import("fs");
|
|
35344
|
+
const { join: join93 } = await import("path");
|
|
35279
35345
|
for (const config2 of this.registry.getAll()) {
|
|
35280
35346
|
if (config2.native) continue;
|
|
35281
35347
|
if (this.workers.has(config2.id)) continue;
|
|
@@ -35293,8 +35359,8 @@ message: Your question?
|
|
|
35293
35359
|
void 0,
|
|
35294
35360
|
config2.key_ref
|
|
35295
35361
|
);
|
|
35296
|
-
const instructionsPath =
|
|
35297
|
-
const instructions =
|
|
35362
|
+
const instructionsPath = join93(this.projectRoot, ".gossip", "agents", config2.id, "instructions.md");
|
|
35363
|
+
const instructions = existsSync74(instructionsPath) ? readFileSync70(instructionsPath, "utf-8") : void 0;
|
|
35298
35364
|
const enableWebSearch = config2.preset === "researcher" || config2.skills.includes("research");
|
|
35299
35365
|
const worker = new WorkerAgent(config2.id, llm, this.relayUrl, ALL_TOOLS, instructions, enableWebSearch, this.relayApiKey, config2.maxToolTurns);
|
|
35300
35366
|
await worker.start();
|
|
@@ -35491,8 +35557,8 @@ message: Your question?
|
|
|
35491
35557
|
this.registry.register(config2);
|
|
35492
35558
|
}
|
|
35493
35559
|
async syncWorkers(keyProvider) {
|
|
35494
|
-
const { existsSync:
|
|
35495
|
-
const { join:
|
|
35560
|
+
const { existsSync: existsSync74, readFileSync: readFileSync70 } = await import("fs");
|
|
35561
|
+
const { join: join93 } = await import("path");
|
|
35496
35562
|
let added = 0;
|
|
35497
35563
|
for (const ac of this.registry.getAll()) {
|
|
35498
35564
|
if (ac.native) continue;
|
|
@@ -35509,8 +35575,8 @@ message: Your question?
|
|
|
35509
35575
|
this.workers.delete(ac.id);
|
|
35510
35576
|
}
|
|
35511
35577
|
const llm = createProviderForAgent(ac.id, ac.provider, ac.model, key ?? void 0, ac.base_url, void 0, ac.key_ref);
|
|
35512
|
-
const instructionsPath =
|
|
35513
|
-
const instructions =
|
|
35578
|
+
const instructionsPath = join93(this.projectRoot, ".gossip", "agents", ac.id, "instructions.md");
|
|
35579
|
+
const instructions = existsSync74(instructionsPath) ? readFileSync70(instructionsPath, "utf-8") : void 0;
|
|
35514
35580
|
const enableWebSearch = ac.preset === "researcher" || ac.skills.includes("research");
|
|
35515
35581
|
const worker = new WorkerAgent(ac.id, llm, this.relayUrl, ALL_TOOLS, instructions, enableWebSearch, this.relayApiKey, ac.maxToolTurns);
|
|
35516
35582
|
await worker.start();
|
|
@@ -36487,8 +36553,8 @@ function applyStatusTags(input, statusMap) {
|
|
|
36487
36553
|
}
|
|
36488
36554
|
return { output: lines.join("\n"), changed };
|
|
36489
36555
|
}
|
|
36490
|
-
function atomicWrite(
|
|
36491
|
-
const tmp = `${
|
|
36556
|
+
function atomicWrite(path8, content) {
|
|
36557
|
+
const tmp = `${path8}.tmp`;
|
|
36492
36558
|
let fd;
|
|
36493
36559
|
try {
|
|
36494
36560
|
(0, import_fs40.writeFileSync)(tmp, content, "utf-8");
|
|
@@ -36496,7 +36562,7 @@ function atomicWrite(path7, content) {
|
|
|
36496
36562
|
(0, import_fs40.fsyncSync)(fd);
|
|
36497
36563
|
(0, import_fs40.closeSync)(fd);
|
|
36498
36564
|
fd = void 0;
|
|
36499
|
-
(0, import_fs40.renameSync)(tmp,
|
|
36565
|
+
(0, import_fs40.renameSync)(tmp, path8);
|
|
36500
36566
|
} catch (err) {
|
|
36501
36567
|
if (fd !== void 0) {
|
|
36502
36568
|
try {
|
|
@@ -36637,8 +36703,8 @@ function corpusDir(projectRoot) {
|
|
|
36637
36703
|
const encoded = projectRoot.replace(/\//g, "-");
|
|
36638
36704
|
return (0, import_path43.join)((0, import_os3.homedir)(), ".claude", "projects", encoded, "memory");
|
|
36639
36705
|
}
|
|
36640
|
-
function atomicWriteJson(
|
|
36641
|
-
const tmp = `${
|
|
36706
|
+
function atomicWriteJson(path8, data) {
|
|
36707
|
+
const tmp = `${path8}.tmp`;
|
|
36642
36708
|
let fd;
|
|
36643
36709
|
try {
|
|
36644
36710
|
(0, import_fs41.writeFileSync)(tmp, JSON.stringify(data, null, 2), "utf-8");
|
|
@@ -36646,7 +36712,7 @@ function atomicWriteJson(path7, data) {
|
|
|
36646
36712
|
(0, import_fs41.fsyncSync)(fd);
|
|
36647
36713
|
(0, import_fs41.closeSync)(fd);
|
|
36648
36714
|
fd = void 0;
|
|
36649
|
-
(0, import_fs41.renameSync)(tmp,
|
|
36715
|
+
(0, import_fs41.renameSync)(tmp, path8);
|
|
36650
36716
|
} catch (err) {
|
|
36651
36717
|
if (fd !== void 0) {
|
|
36652
36718
|
try {
|
|
@@ -36856,8 +36922,8 @@ function rebuildIndex(projectRoot) {
|
|
|
36856
36922
|
atomicWriteJson(idxPath, index);
|
|
36857
36923
|
return index;
|
|
36858
36924
|
}
|
|
36859
|
-
function atomicWriteText(
|
|
36860
|
-
const tmp = `${
|
|
36925
|
+
function atomicWriteText(path8, content) {
|
|
36926
|
+
const tmp = `${path8}.tmp`;
|
|
36861
36927
|
let fd;
|
|
36862
36928
|
try {
|
|
36863
36929
|
(0, import_fs41.writeFileSync)(tmp, content, "utf-8");
|
|
@@ -36865,7 +36931,7 @@ function atomicWriteText(path7, content) {
|
|
|
36865
36931
|
(0, import_fs41.fsyncSync)(fd);
|
|
36866
36932
|
(0, import_fs41.closeSync)(fd);
|
|
36867
36933
|
fd = void 0;
|
|
36868
|
-
(0, import_fs41.renameSync)(tmp,
|
|
36934
|
+
(0, import_fs41.renameSync)(tmp, path8);
|
|
36869
36935
|
} catch (err) {
|
|
36870
36936
|
if (fd !== void 0) {
|
|
36871
36937
|
try {
|
|
@@ -37259,29 +37325,29 @@ var init_task_graph_sync = __esm({
|
|
|
37259
37325
|
);
|
|
37260
37326
|
}
|
|
37261
37327
|
}
|
|
37262
|
-
async patch(
|
|
37263
|
-
const res = await fetch(`${this.supabaseUrl}${
|
|
37328
|
+
async patch(path8, body) {
|
|
37329
|
+
const res = await fetch(`${this.supabaseUrl}${path8}`, {
|
|
37264
37330
|
method: "PATCH",
|
|
37265
37331
|
headers: this.headers(),
|
|
37266
37332
|
body: JSON.stringify(body)
|
|
37267
37333
|
});
|
|
37268
|
-
if (!res.ok) throw new Error(`PATCH ${
|
|
37334
|
+
if (!res.ok) throw new Error(`PATCH ${path8} failed: ${res.status} ${await res.text()}`);
|
|
37269
37335
|
}
|
|
37270
|
-
async post(
|
|
37271
|
-
const res = await fetch(`${this.supabaseUrl}${
|
|
37336
|
+
async post(path8, body) {
|
|
37337
|
+
const res = await fetch(`${this.supabaseUrl}${path8}`, {
|
|
37272
37338
|
method: "POST",
|
|
37273
37339
|
headers: { ...this.headers(), "Prefer": "return=representation" },
|
|
37274
37340
|
body: JSON.stringify(body)
|
|
37275
37341
|
});
|
|
37276
|
-
if (!res.ok) throw new Error(`POST ${
|
|
37342
|
+
if (!res.ok) throw new Error(`POST ${path8} failed: ${res.status} ${await res.text()}`);
|
|
37277
37343
|
}
|
|
37278
|
-
async upsert(
|
|
37279
|
-
const res = await fetch(`${this.supabaseUrl}${
|
|
37344
|
+
async upsert(path8, body) {
|
|
37345
|
+
const res = await fetch(`${this.supabaseUrl}${path8}`, {
|
|
37280
37346
|
method: "POST",
|
|
37281
37347
|
headers: { ...this.headers(), "Prefer": "resolution=merge-duplicates,return=representation" },
|
|
37282
37348
|
body: JSON.stringify(body)
|
|
37283
37349
|
});
|
|
37284
|
-
if (!res.ok) throw new Error(`UPSERT ${
|
|
37350
|
+
if (!res.ok) throw new Error(`UPSERT ${path8} failed: ${res.status} ${await res.text()}`);
|
|
37285
37351
|
}
|
|
37286
37352
|
headers() {
|
|
37287
37353
|
return {
|
|
@@ -37478,22 +37544,22 @@ async function readJsonBody(req, cap) {
|
|
|
37478
37544
|
return { err: "invalid_json", msg: err instanceof Error ? err.message : "parse error" };
|
|
37479
37545
|
}
|
|
37480
37546
|
}
|
|
37481
|
-
function replyBodyErr(ctx2, req, res, rec, started,
|
|
37547
|
+
function replyBodyErr(ctx2, req, res, rec, started, path8, body) {
|
|
37482
37548
|
if (body.err === "too_large") {
|
|
37483
37549
|
ctx2.sendJson(res, 413, ctx2.errBody("payload_too_large", "payload_too_large", body.msg));
|
|
37484
|
-
ctx2.logEvent({ started, req, status: 413, path:
|
|
37550
|
+
ctx2.logEvent({ started, req, status: 413, path: path8, bytesRead: 0, bytesWritten: 0, token: rec.token });
|
|
37485
37551
|
} else {
|
|
37486
37552
|
ctx2.sendJson(res, 400, ctx2.errBody("bad_request", "bad_request", body.msg));
|
|
37487
|
-
ctx2.logEvent({ started, req, status: 400, path:
|
|
37553
|
+
ctx2.logEvent({ started, req, status: 400, path: path8, bytesRead: 0, bytesWritten: 0, token: rec.token });
|
|
37488
37554
|
}
|
|
37489
37555
|
}
|
|
37490
|
-
function reply403(ctx2, req, res, rec, started,
|
|
37556
|
+
function reply403(ctx2, req, res, rec, started, path8, msg) {
|
|
37491
37557
|
ctx2.sendJson(res, 403, ctx2.errBody("forbidden", "scope_violation", msg));
|
|
37492
|
-
ctx2.logEvent({ started, req, status: 403, path:
|
|
37558
|
+
ctx2.logEvent({ started, req, status: 403, path: path8, bytesRead: 0, bytesWritten: 0, token: rec.token });
|
|
37493
37559
|
}
|
|
37494
|
-
function reply429(ctx2, req, res, rec, started,
|
|
37560
|
+
function reply429(ctx2, req, res, rec, started, path8) {
|
|
37495
37561
|
ctx2.send429(res);
|
|
37496
|
-
ctx2.logEvent({ started, req, status: 429, path:
|
|
37562
|
+
ctx2.logEvent({ started, req, status: 429, path: path8, bytesRead: 0, bytesWritten: 0, token: rec.token });
|
|
37497
37563
|
}
|
|
37498
37564
|
async function handleBridgeInfo(ctx2, req, res, started, ip) {
|
|
37499
37565
|
if (!ctx2.limBridgeInfo.record(ip)) {
|
|
@@ -37532,12 +37598,12 @@ async function handleFileRead(ctx2, req, res, rec, started) {
|
|
|
37532
37598
|
if (!ctx2.limRead.record(`read:${rec.token}`)) return reply429(ctx2, req, res, rec, started, "/file-read");
|
|
37533
37599
|
const body = await readJsonBody(req, MAX_FILE_BYTES);
|
|
37534
37600
|
if ("err" in body) return replyBodyErr(ctx2, req, res, rec, started, "/file-read", body);
|
|
37535
|
-
const
|
|
37536
|
-
if (!
|
|
37601
|
+
const path8 = typeof body.value?.path === "string" ? body.value.path : "";
|
|
37602
|
+
if (!path8) {
|
|
37537
37603
|
ctx2.sendJson(res, 400, ctx2.errBody("bad_request", "bad_request", "path is required"));
|
|
37538
37604
|
return ctx2.logEvent({ started, req, status: 400, path: "/file-read", bytesRead: 0, bytesWritten: 0, token: rec.token });
|
|
37539
37605
|
}
|
|
37540
|
-
const abs = resolveInScope(rec,
|
|
37606
|
+
const abs = resolveInScope(rec, path8);
|
|
37541
37607
|
if (!abs.ok) return reply403(ctx2, req, res, rec, started, "/file-read", abs.msg);
|
|
37542
37608
|
let fileSize;
|
|
37543
37609
|
let mtime;
|
|
@@ -37578,14 +37644,14 @@ async function handleFileWrite(ctx2, req, res, rec, started) {
|
|
|
37578
37644
|
if (!ctx2.limWrite.record(`write:${rec.token}`)) return reply429(ctx2, req, res, rec, started, "/file-write");
|
|
37579
37645
|
const body = await readJsonBody(req, MAX_FILE_BYTES);
|
|
37580
37646
|
if ("err" in body) return replyBodyErr(ctx2, req, res, rec, started, "/file-write", body);
|
|
37581
|
-
const
|
|
37647
|
+
const path8 = typeof body.value?.path === "string" ? body.value.path : "";
|
|
37582
37648
|
const content = typeof body.value?.content === "string" ? body.value.content : "";
|
|
37583
37649
|
const ifMatch = typeof body.value?.if_match === "string" ? body.value.if_match : void 0;
|
|
37584
|
-
if (!
|
|
37650
|
+
if (!path8) {
|
|
37585
37651
|
ctx2.sendJson(res, 400, ctx2.errBody("bad_request", "bad_request", "path is required"));
|
|
37586
37652
|
return ctx2.logEvent({ started, req, status: 400, path: "/file-write", bytesRead: 0, bytesWritten: 0, token: rec.token });
|
|
37587
37653
|
}
|
|
37588
|
-
const abs = resolveInScope(rec,
|
|
37654
|
+
const abs = resolveInScope(rec, path8);
|
|
37589
37655
|
if (!abs.ok) return reply403(ctx2, req, res, rec, started, "/file-write", abs.msg);
|
|
37590
37656
|
const buf = Buffer.from(content, "utf-8");
|
|
37591
37657
|
if (buf.byteLength > MAX_FILE_BYTES) {
|
|
@@ -38234,12 +38300,12 @@ function buildIndexFromDisk(memoryDir, agentIds) {
|
|
|
38234
38300
|
};
|
|
38235
38301
|
}
|
|
38236
38302
|
function readValidSidecar(projectRoot, memoryDir) {
|
|
38237
|
-
const
|
|
38238
|
-
if (!(0, import_fs44.existsSync)(
|
|
38303
|
+
const path8 = proseResolverPath(projectRoot);
|
|
38304
|
+
if (!(0, import_fs44.existsSync)(path8)) return null;
|
|
38239
38305
|
let parsed;
|
|
38240
38306
|
try {
|
|
38241
|
-
if ((0, import_fs44.statSync)(
|
|
38242
|
-
parsed = JSON.parse((0, import_fs44.readFileSync)(
|
|
38307
|
+
if ((0, import_fs44.statSync)(path8).size > SIDECAR_READ_LIMIT) return null;
|
|
38308
|
+
parsed = JSON.parse((0, import_fs44.readFileSync)(path8, "utf-8"));
|
|
38243
38309
|
} catch {
|
|
38244
38310
|
return null;
|
|
38245
38311
|
}
|
|
@@ -38259,10 +38325,10 @@ function readValidSidecar(projectRoot, memoryDir) {
|
|
|
38259
38325
|
return idx;
|
|
38260
38326
|
}
|
|
38261
38327
|
function writeSidecar(projectRoot, idx) {
|
|
38262
|
-
const
|
|
38328
|
+
const path8 = proseResolverPath(projectRoot);
|
|
38263
38329
|
try {
|
|
38264
|
-
(0, import_fs44.mkdirSync)((0, import_path48.dirname)(
|
|
38265
|
-
(0, import_fs44.writeFileSync)(
|
|
38330
|
+
(0, import_fs44.mkdirSync)((0, import_path48.dirname)(path8), { recursive: true });
|
|
38331
|
+
(0, import_fs44.writeFileSync)(path8, JSON.stringify(idx));
|
|
38266
38332
|
} catch {
|
|
38267
38333
|
}
|
|
38268
38334
|
}
|
|
@@ -38427,11 +38493,11 @@ function isLedgerIndex(x) {
|
|
|
38427
38493
|
return typeof o.ledgerMtime === "number" && typeof o.ledgerContentHash === "string" && Array.isArray(o.entries) && o.entries.every((e) => e !== null && typeof e === "object" && typeof e.bulletHash === "string" && typeof e.verdict === "string" && typeof e.details === "string" && typeof e.checkedAt === "string");
|
|
38428
38494
|
}
|
|
38429
38495
|
function readLedgerIndex(projectRoot, liveLedgerContent, liveLedgerMtime) {
|
|
38430
|
-
const
|
|
38431
|
-
if (!(0, import_fs45.existsSync)(
|
|
38496
|
+
const path8 = ledgerIndexPath(projectRoot);
|
|
38497
|
+
if (!(0, import_fs45.existsSync)(path8)) return null;
|
|
38432
38498
|
let parsed;
|
|
38433
38499
|
try {
|
|
38434
|
-
parsed = JSON.parse((0, import_fs45.readFileSync)(
|
|
38500
|
+
parsed = JSON.parse((0, import_fs45.readFileSync)(path8, "utf-8"));
|
|
38435
38501
|
} catch {
|
|
38436
38502
|
return null;
|
|
38437
38503
|
}
|
|
@@ -38441,10 +38507,10 @@ function readLedgerIndex(projectRoot, liveLedgerContent, liveLedgerMtime) {
|
|
|
38441
38507
|
return parsed;
|
|
38442
38508
|
}
|
|
38443
38509
|
function writeLedgerIndex(projectRoot, index) {
|
|
38444
|
-
const
|
|
38510
|
+
const path8 = ledgerIndexPath(projectRoot);
|
|
38445
38511
|
try {
|
|
38446
|
-
(0, import_fs45.mkdirSync)((0, import_path49.dirname)(
|
|
38447
|
-
(0, import_fs45.writeFileSync)(
|
|
38512
|
+
(0, import_fs45.mkdirSync)((0, import_path49.dirname)(path8), { recursive: true });
|
|
38513
|
+
(0, import_fs45.writeFileSync)(path8, JSON.stringify(index, null, 2));
|
|
38448
38514
|
} catch {
|
|
38449
38515
|
}
|
|
38450
38516
|
}
|
|
@@ -38552,9 +38618,9 @@ function annotateLedgerText(raw, bullets, entriesByHash) {
|
|
|
38552
38618
|
}
|
|
38553
38619
|
return lines.join("\n");
|
|
38554
38620
|
}
|
|
38555
|
-
function ledgerMtime(
|
|
38621
|
+
function ledgerMtime(ledgerPath2) {
|
|
38556
38622
|
try {
|
|
38557
|
-
return (0, import_fs45.statSync)(
|
|
38623
|
+
return (0, import_fs45.statSync)(ledgerPath2).mtimeMs;
|
|
38558
38624
|
} catch {
|
|
38559
38625
|
return 0;
|
|
38560
38626
|
}
|
|
@@ -38616,10 +38682,10 @@ function checkDistMcpStaleness(bundlePath) {
|
|
|
38616
38682
|
let newestMtime = 0;
|
|
38617
38683
|
let newestPath;
|
|
38618
38684
|
for (const root of SRC_ROOTS) {
|
|
38619
|
-
walk((0, import_path50.join)(repoRoot, root), (
|
|
38685
|
+
walk((0, import_path50.join)(repoRoot, root), (path8, mtimeMs) => {
|
|
38620
38686
|
if (mtimeMs > newestMtime) {
|
|
38621
38687
|
newestMtime = mtimeMs;
|
|
38622
|
-
newestPath =
|
|
38688
|
+
newestPath = path8;
|
|
38623
38689
|
}
|
|
38624
38690
|
});
|
|
38625
38691
|
}
|
|
@@ -39089,13 +39155,13 @@ Skills are auto-injected from agent config. Project-wide skills in .gossip/skill
|
|
|
39089
39155
|
*
|
|
39090
39156
|
* Bootstrap critical path stays synchronous and fast.
|
|
39091
39157
|
*/
|
|
39092
|
-
applyLedgerAnnotations(content,
|
|
39158
|
+
applyLedgerAnnotations(content, ledgerPath2) {
|
|
39093
39159
|
try {
|
|
39094
39160
|
const bullets = parseNextSessionBullets(content);
|
|
39095
39161
|
if (bullets.length === 0) return content;
|
|
39096
39162
|
let mtime = 0;
|
|
39097
39163
|
try {
|
|
39098
|
-
mtime = (0, import_fs47.statSync)(
|
|
39164
|
+
mtime = (0, import_fs47.statSync)(ledgerPath2).mtimeMs;
|
|
39099
39165
|
} catch {
|
|
39100
39166
|
}
|
|
39101
39167
|
const index = readLedgerIndex(this.projectRoot, content, mtime);
|
|
@@ -39241,19 +39307,19 @@ function hasControlChars(s) {
|
|
|
39241
39307
|
}
|
|
39242
39308
|
return false;
|
|
39243
39309
|
}
|
|
39244
|
-
async function gitCommonDir(
|
|
39310
|
+
async function gitCommonDir(path8) {
|
|
39245
39311
|
try {
|
|
39246
39312
|
const { stdout } = await execFileP(
|
|
39247
39313
|
"git",
|
|
39248
|
-
["-C",
|
|
39314
|
+
["-C", path8, "rev-parse", "--git-common-dir"],
|
|
39249
39315
|
GIT_EXEC_OPTS
|
|
39250
39316
|
);
|
|
39251
39317
|
const out = stdout.trim();
|
|
39252
39318
|
if (!out) return null;
|
|
39253
39319
|
try {
|
|
39254
|
-
return (0, import_fs48.realpathSync)((0, import_path52.resolve)(
|
|
39320
|
+
return (0, import_fs48.realpathSync)((0, import_path52.resolve)(path8, out));
|
|
39255
39321
|
} catch {
|
|
39256
|
-
return (0, import_path52.resolve)(
|
|
39322
|
+
return (0, import_path52.resolve)(path8, out);
|
|
39257
39323
|
}
|
|
39258
39324
|
} catch {
|
|
39259
39325
|
return null;
|
|
@@ -39279,17 +39345,17 @@ function parseWorktreePorcelain(stdout, { includeLocked = false } = {}) {
|
|
|
39279
39345
|
const fields = rec.split("\0").filter(Boolean);
|
|
39280
39346
|
const worktreeField = fields.find((f) => f.startsWith("worktree "));
|
|
39281
39347
|
if (!worktreeField) continue;
|
|
39282
|
-
const
|
|
39348
|
+
const path8 = worktreeField.slice("worktree ".length);
|
|
39283
39349
|
if (fields.some(
|
|
39284
39350
|
(f) => f === "bare" || !includeLocked && f.startsWith("locked") || f.startsWith("prunable")
|
|
39285
39351
|
)) {
|
|
39286
39352
|
continue;
|
|
39287
39353
|
}
|
|
39288
|
-
let canonical =
|
|
39354
|
+
let canonical = path8;
|
|
39289
39355
|
try {
|
|
39290
|
-
canonical = (0, import_fs48.realpathSync)((0, import_path52.resolve)(
|
|
39356
|
+
canonical = (0, import_fs48.realpathSync)((0, import_path52.resolve)(path8));
|
|
39291
39357
|
} catch {
|
|
39292
|
-
canonical = (0, import_path52.resolve)(
|
|
39358
|
+
canonical = (0, import_path52.resolve)(path8);
|
|
39293
39359
|
}
|
|
39294
39360
|
out.push(canonical);
|
|
39295
39361
|
if (out.length >= 100) break;
|
|
@@ -40415,6 +40481,89 @@ var init_chatbot_agent = __esm({
|
|
|
40415
40481
|
}
|
|
40416
40482
|
});
|
|
40417
40483
|
|
|
40484
|
+
// packages/orchestrator/src/orchestrator-preconditions.ts
|
|
40485
|
+
function detectStaleBase(dispatchSha, originMasterSha, mergeBaseSha) {
|
|
40486
|
+
if (dispatchSha === originMasterSha) {
|
|
40487
|
+
return { stale: false, reason: null };
|
|
40488
|
+
}
|
|
40489
|
+
if (mergeBaseSha === dispatchSha) {
|
|
40490
|
+
return { stale: true, reason: "behind_origin" };
|
|
40491
|
+
}
|
|
40492
|
+
if (mergeBaseSha === originMasterSha) {
|
|
40493
|
+
return { stale: false, reason: "ahead_of_origin" };
|
|
40494
|
+
}
|
|
40495
|
+
return { stale: true, reason: "branched_pre_merge" };
|
|
40496
|
+
}
|
|
40497
|
+
function findUnreadablePaths(paths, canRead) {
|
|
40498
|
+
return paths.filter((p) => !canRead(p));
|
|
40499
|
+
}
|
|
40500
|
+
function extractReferencedPathsWithMeta(taskText) {
|
|
40501
|
+
if (!taskText) {
|
|
40502
|
+
return { paths: [], droppedOverCap: 0 };
|
|
40503
|
+
}
|
|
40504
|
+
const rawTokens = taskText.split(/[\s`]+/);
|
|
40505
|
+
const seen = /* @__PURE__ */ new Set();
|
|
40506
|
+
const out = [];
|
|
40507
|
+
let droppedOverCap = 0;
|
|
40508
|
+
for (const raw of rawTokens) {
|
|
40509
|
+
const trimmed = raw.replace(/^[([{<"']+/, "").replace(/[)\]}>"',.;:]+$/, "");
|
|
40510
|
+
const token = trimmed.replace(/:\d+(?::\d+)?$/, "");
|
|
40511
|
+
if (token.length === 0) {
|
|
40512
|
+
continue;
|
|
40513
|
+
}
|
|
40514
|
+
if (token.startsWith("/") || token.includes("..")) {
|
|
40515
|
+
continue;
|
|
40516
|
+
}
|
|
40517
|
+
if (!REPO_PATH_SHAPE.test(token)) {
|
|
40518
|
+
continue;
|
|
40519
|
+
}
|
|
40520
|
+
if (seen.has(token)) {
|
|
40521
|
+
continue;
|
|
40522
|
+
}
|
|
40523
|
+
seen.add(token);
|
|
40524
|
+
if (out.length >= MAX_REFERENCED_PATHS) {
|
|
40525
|
+
droppedOverCap += 1;
|
|
40526
|
+
continue;
|
|
40527
|
+
}
|
|
40528
|
+
out.push(token);
|
|
40529
|
+
}
|
|
40530
|
+
return { paths: out, droppedOverCap };
|
|
40531
|
+
}
|
|
40532
|
+
function extractReferencedPaths(taskText) {
|
|
40533
|
+
return extractReferencedPathsWithMeta(taskText).paths;
|
|
40534
|
+
}
|
|
40535
|
+
function findUnreadableReferencedPaths(taskText, opts) {
|
|
40536
|
+
return findUnreadableReferencedPathsWithMeta(taskText, opts).unreadable;
|
|
40537
|
+
}
|
|
40538
|
+
function findUnreadableReferencedPathsWithMeta(taskText, opts) {
|
|
40539
|
+
const { paths, droppedOverCap } = extractReferencedPathsWithMeta(taskText);
|
|
40540
|
+
const out = [];
|
|
40541
|
+
const isWorktree = opts.writeMode === "worktree";
|
|
40542
|
+
for (const path8 of paths) {
|
|
40543
|
+
const exists = opts.pathExists(path8);
|
|
40544
|
+
if (!exists) {
|
|
40545
|
+
out.push({ path: path8, reason: "missing" });
|
|
40546
|
+
continue;
|
|
40547
|
+
}
|
|
40548
|
+
if (isWorktree && opts.isGitignoredOrUntracked(path8)) {
|
|
40549
|
+
out.push({ path: path8, reason: "gitignored_in_worktree" });
|
|
40550
|
+
}
|
|
40551
|
+
}
|
|
40552
|
+
return { unreadable: out, droppedOverCap };
|
|
40553
|
+
}
|
|
40554
|
+
function detectMidFlightCommits(commitsBetween) {
|
|
40555
|
+
const count = commitsBetween.length;
|
|
40556
|
+
return { detected: count > 0, count };
|
|
40557
|
+
}
|
|
40558
|
+
var REPO_PATH_SHAPE, MAX_REFERENCED_PATHS;
|
|
40559
|
+
var init_orchestrator_preconditions = __esm({
|
|
40560
|
+
"packages/orchestrator/src/orchestrator-preconditions.ts"() {
|
|
40561
|
+
"use strict";
|
|
40562
|
+
REPO_PATH_SHAPE = /^(?:\.\/)?[\w./-]+\.(?:md|ts|tsx|js|json|txt|ya?ml)$/;
|
|
40563
|
+
MAX_REFERENCED_PATHS = 20;
|
|
40564
|
+
}
|
|
40565
|
+
});
|
|
40566
|
+
|
|
40418
40567
|
// packages/orchestrator/src/index.ts
|
|
40419
40568
|
var src_exports3 = {};
|
|
40420
40569
|
__export(src_exports3, {
|
|
@@ -40540,6 +40689,8 @@ __export(src_exports3, {
|
|
|
40540
40689
|
defaultVerifierFactory: () => defaultVerifierFactory,
|
|
40541
40690
|
deriveConsensusId: () => deriveConsensusId,
|
|
40542
40691
|
detectFormatCompliance: () => detectFormatCompliance,
|
|
40692
|
+
detectMidFlightCommits: () => detectMidFlightCommits,
|
|
40693
|
+
detectStaleBase: () => detectStaleBase,
|
|
40543
40694
|
discoverAgentIdsForRoot: () => discoverAgentIdsForRoot,
|
|
40544
40695
|
discoverGitWorktrees: () => discoverGitWorktrees,
|
|
40545
40696
|
emitCitationFabricatedSignal: () => emitCitationFabricatedSignal,
|
|
@@ -40552,11 +40703,16 @@ __export(src_exports3, {
|
|
|
40552
40703
|
ensureRulesFile: () => ensureRulesFile,
|
|
40553
40704
|
extractCategories: () => extractCategories,
|
|
40554
40705
|
extractConsensusId: () => extractConsensusId,
|
|
40706
|
+
extractReferencedPaths: () => extractReferencedPaths,
|
|
40707
|
+
extractReferencedPathsWithMeta: () => extractReferencedPathsWithMeta,
|
|
40555
40708
|
extractSpecReferences: () => extractSpecReferences,
|
|
40556
40709
|
extractTokens: () => extractTokens,
|
|
40557
40710
|
findBundledHook: () => findBundledHook,
|
|
40558
40711
|
findBundledRules: () => findBundledRules,
|
|
40559
40712
|
findOpenSectionLine: () => findOpenSectionLine,
|
|
40713
|
+
findUnreadablePaths: () => findUnreadablePaths,
|
|
40714
|
+
findUnreadableReferencedPaths: () => findUnreadableReferencedPaths,
|
|
40715
|
+
findUnreadableReferencedPathsWithMeta: () => findUnreadableReferencedPathsWithMeta,
|
|
40560
40716
|
formatCooldownMessage: () => formatCooldownMessage,
|
|
40561
40717
|
formatStalenessWarning: () => formatStalenessWarning,
|
|
40562
40718
|
getRoundCounter: () => get,
|
|
@@ -40739,6 +40895,7 @@ var init_src4 = __esm({
|
|
|
40739
40895
|
init_runtime_config();
|
|
40740
40896
|
init_runtime_config_schema();
|
|
40741
40897
|
init_chatbot_agent();
|
|
40898
|
+
init_orchestrator_preconditions();
|
|
40742
40899
|
}
|
|
40743
40900
|
});
|
|
40744
40901
|
|
|
@@ -41958,10 +42115,10 @@ var init_auth = __esm({
|
|
|
41958
42115
|
* left half-written by a crash. Validate the shape before trusting it and
|
|
41959
42116
|
* fail closed (regenerate) on anything unexpected — never throw.
|
|
41960
42117
|
*/
|
|
41961
|
-
loadPersisted(
|
|
42118
|
+
loadPersisted(path8) {
|
|
41962
42119
|
try {
|
|
41963
|
-
if (!(0, import_fs54.existsSync)(
|
|
41964
|
-
const parsed = JSON.parse((0, import_fs54.readFileSync)(
|
|
42120
|
+
if (!(0, import_fs54.existsSync)(path8)) return false;
|
|
42121
|
+
const parsed = JSON.parse((0, import_fs54.readFileSync)(path8, "utf8"));
|
|
41965
42122
|
if (!isPersistedAuth(parsed)) return false;
|
|
41966
42123
|
this.key = parsed.key;
|
|
41967
42124
|
this.sessions.clear();
|
|
@@ -42197,9 +42354,9 @@ var init_api_open_findings = __esm({
|
|
|
42197
42354
|
});
|
|
42198
42355
|
|
|
42199
42356
|
// packages/relay/src/dashboard/api-overview.ts
|
|
42200
|
-
function readSkillStatus(
|
|
42357
|
+
function readSkillStatus(path8) {
|
|
42201
42358
|
try {
|
|
42202
|
-
const content = (0, import_fs56.readFileSync)(
|
|
42359
|
+
const content = (0, import_fs56.readFileSync)(path8, "utf-8");
|
|
42203
42360
|
const m = content.match(/^---\n([\s\S]*?)\n---/);
|
|
42204
42361
|
if (!m) return null;
|
|
42205
42362
|
const block = m[1];
|
|
@@ -42513,9 +42670,9 @@ var init_api_fleet_trend = __esm({
|
|
|
42513
42670
|
// packages/relay/src/dashboard/api-agents.ts
|
|
42514
42671
|
function readSkillFrontmatter(projectRoot, agentId, skillName) {
|
|
42515
42672
|
try {
|
|
42516
|
-
const
|
|
42517
|
-
if (!(0, import_fs58.existsSync)(
|
|
42518
|
-
const raw = (0, import_fs58.readFileSync)(
|
|
42673
|
+
const path8 = (0, import_path62.join)(projectRoot, ".gossip", "agents", agentId, "skills", `${skillName}.md`);
|
|
42674
|
+
if (!(0, import_fs58.existsSync)(path8)) return null;
|
|
42675
|
+
const raw = (0, import_fs58.readFileSync)(path8, "utf-8");
|
|
42519
42676
|
if (!raw.startsWith("---")) return null;
|
|
42520
42677
|
const end = raw.indexOf("\n---", 3);
|
|
42521
42678
|
if (end === -1) return null;
|
|
@@ -42553,9 +42710,9 @@ function normalizeCategory(s) {
|
|
|
42553
42710
|
}
|
|
42554
42711
|
function readForcedDevelops(projectRoot, agentId, category) {
|
|
42555
42712
|
try {
|
|
42556
|
-
const
|
|
42557
|
-
if (!(0, import_fs58.existsSync)(
|
|
42558
|
-
const raw = (0, import_fs58.readFileSync)(
|
|
42713
|
+
const path8 = (0, import_path62.join)(projectRoot, ".gossip", "forced-skill-develops.jsonl");
|
|
42714
|
+
if (!(0, import_fs58.existsSync)(path8)) return [];
|
|
42715
|
+
const raw = (0, import_fs58.readFileSync)(path8, "utf-8");
|
|
42559
42716
|
const target = normalizeCategory(category);
|
|
42560
42717
|
const out = [];
|
|
42561
42718
|
for (const line of raw.split("\n")) {
|
|
@@ -43837,7 +43994,9 @@ async function tasksHandler(projectRoot, query) {
|
|
|
43837
43994
|
});
|
|
43838
43995
|
} else if (entry.type === "task.completed") {
|
|
43839
43996
|
completed.set(entry.taskId, {
|
|
43840
|
-
|
|
43997
|
+
// On-disk field is "durationMs"; "entry.duration" was previously
|
|
43998
|
+
// undefined, silently dropping all task durations from the response.
|
|
43999
|
+
duration: entry.durationMs ?? entry.duration,
|
|
43841
44000
|
timestamp: entry.timestamp,
|
|
43842
44001
|
failed: false,
|
|
43843
44002
|
inputTokens: entry.inputTokens,
|
|
@@ -43873,7 +44032,11 @@ async function tasksHandler(projectRoot, query) {
|
|
|
43873
44032
|
result: result?.result,
|
|
43874
44033
|
status: result ? result.cancelled ? "cancelled" : result.failed ? "failed" : "completed" : "running",
|
|
43875
44034
|
duration: result?.duration,
|
|
44035
|
+
// timestamp = completion time for terminal tasks (used as "Completed" node in timeline).
|
|
44036
|
+
// For running tasks, falls back to createdAt.
|
|
43876
44037
|
timestamp: result?.timestamp || info.timestamp,
|
|
44038
|
+
// createdAt = always the dispatch time (task.created event timestamp).
|
|
44039
|
+
createdAt: info.timestamp,
|
|
43877
44040
|
inputTokens: result?.inputTokens,
|
|
43878
44041
|
outputTokens: result?.outputTokens
|
|
43879
44042
|
});
|
|
@@ -43891,14 +44054,149 @@ var init_api_tasks = __esm({
|
|
|
43891
44054
|
}
|
|
43892
44055
|
});
|
|
43893
44056
|
|
|
44057
|
+
// packages/relay/src/dashboard/api-task-detail.ts
|
|
44058
|
+
function readJsonlLines(filePath) {
|
|
44059
|
+
const out = [];
|
|
44060
|
+
const archive = filePath + ".1";
|
|
44061
|
+
if ((0, import_fs67.existsSync)(archive)) {
|
|
44062
|
+
out.push(...(0, import_fs67.readFileSync)(archive, "utf-8").split("\n").filter(Boolean));
|
|
44063
|
+
}
|
|
44064
|
+
if ((0, import_fs67.existsSync)(filePath)) {
|
|
44065
|
+
out.push(...(0, import_fs67.readFileSync)(filePath, "utf-8").split("\n").filter(Boolean));
|
|
44066
|
+
}
|
|
44067
|
+
return out;
|
|
44068
|
+
}
|
|
44069
|
+
async function taskDetailHandler(projectRoot, taskId) {
|
|
44070
|
+
const graphPath = (0, import_path74.join)(projectRoot, ".gossip", "task-graph.jsonl");
|
|
44071
|
+
if (!(0, import_fs67.existsSync)(graphPath) && !(0, import_fs67.existsSync)(graphPath + ".1")) {
|
|
44072
|
+
return null;
|
|
44073
|
+
}
|
|
44074
|
+
const created = /* @__PURE__ */ new Map();
|
|
44075
|
+
const completed = /* @__PURE__ */ new Map();
|
|
44076
|
+
try {
|
|
44077
|
+
const lines = readJsonlLines(graphPath);
|
|
44078
|
+
for (const line of lines) {
|
|
44079
|
+
try {
|
|
44080
|
+
const entry = JSON.parse(line);
|
|
44081
|
+
if (entry.type === "task.created") {
|
|
44082
|
+
created.set(entry.taskId, {
|
|
44083
|
+
agentId: entry.agentId || "?",
|
|
44084
|
+
task: entry.task || "",
|
|
44085
|
+
timestamp: entry.timestamp
|
|
44086
|
+
});
|
|
44087
|
+
} else if (entry.type === "task.completed") {
|
|
44088
|
+
completed.set(entry.taskId, {
|
|
44089
|
+
duration: entry.durationMs ?? entry.duration,
|
|
44090
|
+
timestamp: entry.timestamp,
|
|
44091
|
+
failed: false,
|
|
44092
|
+
inputTokens: entry.inputTokens,
|
|
44093
|
+
outputTokens: entry.outputTokens,
|
|
44094
|
+
result: typeof entry.result === "string" ? entry.result : void 0
|
|
44095
|
+
});
|
|
44096
|
+
} else if (entry.type === "task.failed") {
|
|
44097
|
+
completed.set(entry.taskId, { timestamp: entry.timestamp, failed: true });
|
|
44098
|
+
} else if (entry.type === "task.cancelled") {
|
|
44099
|
+
completed.set(entry.taskId, { timestamp: entry.timestamp, failed: false, cancelled: true });
|
|
44100
|
+
}
|
|
44101
|
+
} catch {
|
|
44102
|
+
}
|
|
44103
|
+
}
|
|
44104
|
+
} catch {
|
|
44105
|
+
return null;
|
|
44106
|
+
}
|
|
44107
|
+
const info = created.get(taskId);
|
|
44108
|
+
if (!info) return null;
|
|
44109
|
+
const result = completed.get(taskId);
|
|
44110
|
+
const base = {
|
|
44111
|
+
taskId,
|
|
44112
|
+
agentId: info.agentId,
|
|
44113
|
+
task: info.task,
|
|
44114
|
+
result: result?.result,
|
|
44115
|
+
status: result ? result.cancelled ? "cancelled" : result.failed ? "failed" : "completed" : "running",
|
|
44116
|
+
duration: result?.duration,
|
|
44117
|
+
timestamp: result?.timestamp || info.timestamp,
|
|
44118
|
+
createdAt: info.timestamp,
|
|
44119
|
+
inputTokens: result?.inputTokens,
|
|
44120
|
+
outputTokens: result?.outputTokens
|
|
44121
|
+
};
|
|
44122
|
+
let consensusId;
|
|
44123
|
+
let signalCount = 0;
|
|
44124
|
+
const siblingSet = /* @__PURE__ */ new Set();
|
|
44125
|
+
const perfPath = (0, import_path74.join)(projectRoot, ".gossip", "agent-performance.jsonl");
|
|
44126
|
+
try {
|
|
44127
|
+
const lines = readJsonlLines(perfPath);
|
|
44128
|
+
const allEntries = [];
|
|
44129
|
+
for (const line of lines) {
|
|
44130
|
+
try {
|
|
44131
|
+
const entry = JSON.parse(line);
|
|
44132
|
+
if (typeof entry.taskId !== "string") continue;
|
|
44133
|
+
allEntries.push(entry);
|
|
44134
|
+
if (entry.taskId === taskId) {
|
|
44135
|
+
signalCount++;
|
|
44136
|
+
if (!consensusId && typeof entry.consensusId === "string" && entry.consensusId) {
|
|
44137
|
+
consensusId = entry.consensusId;
|
|
44138
|
+
}
|
|
44139
|
+
}
|
|
44140
|
+
} catch {
|
|
44141
|
+
}
|
|
44142
|
+
}
|
|
44143
|
+
if (consensusId) {
|
|
44144
|
+
for (const entry of allEntries) {
|
|
44145
|
+
if (siblingSet.size >= SIBLING_CAP) break;
|
|
44146
|
+
if (entry.consensusId === consensusId && typeof entry.taskId === "string" && entry.taskId && entry.taskId !== taskId) {
|
|
44147
|
+
siblingSet.add(entry.taskId);
|
|
44148
|
+
}
|
|
44149
|
+
}
|
|
44150
|
+
}
|
|
44151
|
+
} catch {
|
|
44152
|
+
}
|
|
44153
|
+
let findingCount = 0;
|
|
44154
|
+
if (consensusId) {
|
|
44155
|
+
const prefix = `${consensusId}:`;
|
|
44156
|
+
const findingsPath = (0, import_path74.join)(projectRoot, ".gossip", "implementation-findings.jsonl");
|
|
44157
|
+
try {
|
|
44158
|
+
const lines = readJsonlLines(findingsPath);
|
|
44159
|
+
for (const line of lines) {
|
|
44160
|
+
try {
|
|
44161
|
+
const entry = JSON.parse(line);
|
|
44162
|
+
if (typeof entry.taskId === "string" && entry.taskId.startsWith(prefix)) {
|
|
44163
|
+
findingCount++;
|
|
44164
|
+
}
|
|
44165
|
+
} catch {
|
|
44166
|
+
}
|
|
44167
|
+
}
|
|
44168
|
+
} catch {
|
|
44169
|
+
}
|
|
44170
|
+
}
|
|
44171
|
+
const siblingTaskIds = siblingSet.size > 0 ? [...siblingSet] : void 0;
|
|
44172
|
+
const siblingsTruncated = siblingSet.size >= SIBLING_CAP;
|
|
44173
|
+
return {
|
|
44174
|
+
...base,
|
|
44175
|
+
...consensusId !== void 0 && { consensusId },
|
|
44176
|
+
...siblingTaskIds !== void 0 && { siblingTaskIds },
|
|
44177
|
+
...siblingsTruncated && { siblingsTruncated },
|
|
44178
|
+
signalCount,
|
|
44179
|
+
findingCount
|
|
44180
|
+
};
|
|
44181
|
+
}
|
|
44182
|
+
var import_fs67, import_path74, SIBLING_CAP;
|
|
44183
|
+
var init_api_task_detail = __esm({
|
|
44184
|
+
"packages/relay/src/dashboard/api-task-detail.ts"() {
|
|
44185
|
+
"use strict";
|
|
44186
|
+
import_fs67 = require("fs");
|
|
44187
|
+
import_path74 = require("path");
|
|
44188
|
+
SIBLING_CAP = 25;
|
|
44189
|
+
}
|
|
44190
|
+
});
|
|
44191
|
+
|
|
43894
44192
|
// packages/relay/src/dashboard/api-active-tasks.ts
|
|
43895
44193
|
async function activeTasksHandler(projectRoot) {
|
|
43896
|
-
const taskGraphPath = (0,
|
|
43897
|
-
if (!(0,
|
|
44194
|
+
const taskGraphPath = (0, import_path75.join)(projectRoot, ".gossip", "task-graph.jsonl");
|
|
44195
|
+
if (!(0, import_fs68.existsSync)(taskGraphPath)) return { tasks: [] };
|
|
43898
44196
|
const created = /* @__PURE__ */ new Map();
|
|
43899
44197
|
const finished = /* @__PURE__ */ new Set();
|
|
43900
44198
|
try {
|
|
43901
|
-
const lines = (0,
|
|
44199
|
+
const lines = (0, import_fs68.readFileSync)(taskGraphPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
43902
44200
|
for (const line of lines) {
|
|
43903
44201
|
try {
|
|
43904
44202
|
const ev = JSON.parse(line);
|
|
@@ -43926,19 +44224,19 @@ async function activeTasksHandler(projectRoot) {
|
|
|
43926
44224
|
active.sort((a, b) => b.startedAt.localeCompare(a.startedAt));
|
|
43927
44225
|
return { tasks: active.slice(0, 10) };
|
|
43928
44226
|
}
|
|
43929
|
-
var
|
|
44227
|
+
var import_fs68, import_path75;
|
|
43930
44228
|
var init_api_active_tasks = __esm({
|
|
43931
44229
|
"packages/relay/src/dashboard/api-active-tasks.ts"() {
|
|
43932
44230
|
"use strict";
|
|
43933
|
-
|
|
43934
|
-
|
|
44231
|
+
import_fs68 = require("fs");
|
|
44232
|
+
import_path75 = require("path");
|
|
43935
44233
|
init_utility_agents();
|
|
43936
44234
|
}
|
|
43937
44235
|
});
|
|
43938
44236
|
|
|
43939
44237
|
// packages/relay/src/dashboard/api-session.ts
|
|
43940
44238
|
function resolveGitBranch(cwd) {
|
|
43941
|
-
return new Promise((
|
|
44239
|
+
return new Promise((resolve33) => {
|
|
43942
44240
|
let done = false;
|
|
43943
44241
|
const child = (0, import_node_child_process2.execFile)(
|
|
43944
44242
|
"git",
|
|
@@ -43948,21 +44246,21 @@ function resolveGitBranch(cwd) {
|
|
|
43948
44246
|
if (done) return;
|
|
43949
44247
|
done = true;
|
|
43950
44248
|
if (err) {
|
|
43951
|
-
|
|
44249
|
+
resolve33(null);
|
|
43952
44250
|
return;
|
|
43953
44251
|
}
|
|
43954
44252
|
const branch = stdout.trim();
|
|
43955
44253
|
if (!branch || branch === "HEAD") {
|
|
43956
|
-
|
|
44254
|
+
resolve33(null);
|
|
43957
44255
|
return;
|
|
43958
44256
|
}
|
|
43959
|
-
|
|
44257
|
+
resolve33(branch);
|
|
43960
44258
|
}
|
|
43961
44259
|
);
|
|
43962
44260
|
child.on("error", () => {
|
|
43963
44261
|
if (!done) {
|
|
43964
44262
|
done = true;
|
|
43965
|
-
|
|
44263
|
+
resolve33(null);
|
|
43966
44264
|
}
|
|
43967
44265
|
});
|
|
43968
44266
|
});
|
|
@@ -43974,16 +44272,16 @@ async function sessionHandler(projectRoot) {
|
|
|
43974
44272
|
]);
|
|
43975
44273
|
return {
|
|
43976
44274
|
gitBranch,
|
|
43977
|
-
projectName: (0,
|
|
44275
|
+
projectName: (0, import_path76.basename)(projectRoot),
|
|
43978
44276
|
activeTasks
|
|
43979
44277
|
};
|
|
43980
44278
|
}
|
|
43981
|
-
var import_node_child_process2,
|
|
44279
|
+
var import_node_child_process2, import_path76;
|
|
43982
44280
|
var init_api_session = __esm({
|
|
43983
44281
|
"packages/relay/src/dashboard/api-session.ts"() {
|
|
43984
44282
|
"use strict";
|
|
43985
44283
|
import_node_child_process2 = require("node:child_process");
|
|
43986
|
-
|
|
44284
|
+
import_path76 = require("path");
|
|
43987
44285
|
init_api_active_tasks();
|
|
43988
44286
|
}
|
|
43989
44287
|
});
|
|
@@ -43997,25 +44295,25 @@ function categorize(text) {
|
|
|
43997
44295
|
return "other";
|
|
43998
44296
|
}
|
|
43999
44297
|
function logsHandler(projectRoot, query) {
|
|
44000
|
-
const logPath = (0,
|
|
44001
|
-
if (!(0,
|
|
44298
|
+
const logPath = (0, import_path77.join)(projectRoot, ".gossip", "mcp.log");
|
|
44299
|
+
if (!(0, import_fs69.existsSync)(logPath)) {
|
|
44002
44300
|
return { entries: [], totalLines: 0, fileSize: 0 };
|
|
44003
44301
|
}
|
|
44004
44302
|
const filter = query?.get("filter") || void 0;
|
|
44005
44303
|
const tail = parseInt(query?.get("tail") || "200", 10);
|
|
44006
44304
|
const clampedTail = Math.min(Math.max(tail, 10), 2e3);
|
|
44007
|
-
const fileSize = (0,
|
|
44305
|
+
const fileSize = (0, import_fs69.statSync)(logPath).size;
|
|
44008
44306
|
const MAX_READ = 512 * 1024;
|
|
44009
44307
|
const readFrom = Math.max(0, fileSize - MAX_READ);
|
|
44010
44308
|
const readLen = fileSize - readFrom;
|
|
44011
|
-
const fd = (0,
|
|
44309
|
+
const fd = (0, import_fs69.openSync)(logPath, "r");
|
|
44012
44310
|
let buf = Buffer.alloc(0);
|
|
44013
44311
|
try {
|
|
44014
44312
|
buf = Buffer.allocUnsafe(readLen);
|
|
44015
|
-
const bytesRead = (0,
|
|
44313
|
+
const bytesRead = (0, import_fs69.readSync)(fd, buf, 0, readLen, readFrom);
|
|
44016
44314
|
buf = buf.subarray(0, bytesRead);
|
|
44017
44315
|
} finally {
|
|
44018
|
-
(0,
|
|
44316
|
+
(0, import_fs69.closeSync)(fd);
|
|
44019
44317
|
}
|
|
44020
44318
|
let raw = buf.toString("utf-8");
|
|
44021
44319
|
let lineOffset = 0;
|
|
@@ -44023,13 +44321,13 @@ function logsHandler(projectRoot, query) {
|
|
|
44023
44321
|
const nl = raw.indexOf("\n");
|
|
44024
44322
|
raw = nl >= 0 ? raw.slice(nl + 1) : raw;
|
|
44025
44323
|
const SCAN_CHUNK = 64 * 1024;
|
|
44026
|
-
const scanFd = (0,
|
|
44324
|
+
const scanFd = (0, import_fs69.openSync)(logPath, "r");
|
|
44027
44325
|
try {
|
|
44028
44326
|
let pos = 0;
|
|
44029
44327
|
const chunk = Buffer.allocUnsafe(SCAN_CHUNK);
|
|
44030
44328
|
while (pos < readFrom) {
|
|
44031
44329
|
const len = Math.min(SCAN_CHUNK, readFrom - pos);
|
|
44032
|
-
const n = (0,
|
|
44330
|
+
const n = (0, import_fs69.readSync)(scanFd, chunk, 0, len, pos);
|
|
44033
44331
|
if (n === 0) break;
|
|
44034
44332
|
for (let j = 0; j < n; j++) {
|
|
44035
44333
|
if (chunk[j] === 10) lineOffset++;
|
|
@@ -44037,7 +44335,7 @@ function logsHandler(projectRoot, query) {
|
|
|
44037
44335
|
pos += n;
|
|
44038
44336
|
}
|
|
44039
44337
|
} finally {
|
|
44040
|
-
(0,
|
|
44338
|
+
(0, import_fs69.closeSync)(scanFd);
|
|
44041
44339
|
}
|
|
44042
44340
|
}
|
|
44043
44341
|
const allLines = raw.split("\n").filter(Boolean);
|
|
@@ -44055,12 +44353,12 @@ function logsHandler(projectRoot, query) {
|
|
|
44055
44353
|
entries = entries.slice(-clampedTail);
|
|
44056
44354
|
return { entries, totalLines, fileSize, filter };
|
|
44057
44355
|
}
|
|
44058
|
-
var
|
|
44356
|
+
var import_fs69, import_path77, CATEGORY_PATTERNS2;
|
|
44059
44357
|
var init_api_logs = __esm({
|
|
44060
44358
|
"packages/relay/src/dashboard/api-logs.ts"() {
|
|
44061
44359
|
"use strict";
|
|
44062
|
-
|
|
44063
|
-
|
|
44360
|
+
import_fs69 = require("fs");
|
|
44361
|
+
import_path77 = require("path");
|
|
44064
44362
|
CATEGORY_PATTERNS2 = [
|
|
44065
44363
|
[/^\[worker:/, "worker"],
|
|
44066
44364
|
[/^\[Gemini\]/, "gemini"],
|
|
@@ -44092,11 +44390,11 @@ function violationsHandler(projectRoot, query) {
|
|
|
44092
44390
|
const page = Math.max(1, parseInt(query?.get("page") ?? "1", 10));
|
|
44093
44391
|
const pageSize = Math.min(100, Math.max(1, parseInt(query?.get("pageSize") ?? "25", 10)));
|
|
44094
44392
|
const agentFilter = query?.get("agentId") ?? null;
|
|
44095
|
-
const filePath = (0,
|
|
44096
|
-
if (!(0,
|
|
44393
|
+
const filePath = (0, import_path78.join)(projectRoot, FILE);
|
|
44394
|
+
if (!(0, import_fs70.existsSync)(filePath)) {
|
|
44097
44395
|
return { items: [], total: 0, page, pageSize };
|
|
44098
44396
|
}
|
|
44099
|
-
const raw = (0,
|
|
44397
|
+
const raw = (0, import_fs70.readFileSync)(filePath, "utf-8");
|
|
44100
44398
|
const lines = raw.trim().split("\n").filter(Boolean);
|
|
44101
44399
|
const entries = [];
|
|
44102
44400
|
for (const line of lines) {
|
|
@@ -44116,12 +44414,12 @@ function violationsHandler(projectRoot, query) {
|
|
|
44116
44414
|
const start = (page - 1) * pageSize;
|
|
44117
44415
|
return { items: entries.slice(start, start + pageSize), total, page, pageSize };
|
|
44118
44416
|
}
|
|
44119
|
-
var
|
|
44417
|
+
var import_fs70, import_path78, FILE;
|
|
44120
44418
|
var init_api_violations = __esm({
|
|
44121
44419
|
"packages/relay/src/dashboard/api-violations.ts"() {
|
|
44122
44420
|
"use strict";
|
|
44123
|
-
|
|
44124
|
-
|
|
44421
|
+
import_fs70 = require("fs");
|
|
44422
|
+
import_path78 = require("path");
|
|
44125
44423
|
FILE = ".gossip/process-violations.jsonl";
|
|
44126
44424
|
}
|
|
44127
44425
|
});
|
|
@@ -44217,12 +44515,12 @@ function isMirrorFrameShaped(obj) {
|
|
|
44217
44515
|
const f = obj;
|
|
44218
44516
|
return f.type === "mirror" && typeof f.chat_id === "string" && typeof f.role === "string" && typeof f.text === "string" && typeof f.ts === "string" && typeof f.id === "number";
|
|
44219
44517
|
}
|
|
44220
|
-
var
|
|
44518
|
+
var import_fs71, import_path79, CHAT_ID_RE, PERSIST_CAP, MAX_LINE_BYTES, NullChatStore, FileChatStore;
|
|
44221
44519
|
var init_chat_store = __esm({
|
|
44222
44520
|
"packages/relay/src/dashboard/chat-store.ts"() {
|
|
44223
44521
|
"use strict";
|
|
44224
|
-
|
|
44225
|
-
|
|
44522
|
+
import_fs71 = require("fs");
|
|
44523
|
+
import_path79 = require("path");
|
|
44226
44524
|
CHAT_ID_RE = /^[a-zA-Z0-9_-]{1,128}$/;
|
|
44227
44525
|
PERSIST_CAP = 1e3;
|
|
44228
44526
|
MAX_LINE_BYTES = 256 * 1024;
|
|
@@ -44254,15 +44552,15 @@ var init_chat_store = __esm({
|
|
|
44254
44552
|
return CHAT_ID_RE.test(chatId);
|
|
44255
44553
|
}
|
|
44256
44554
|
filePath(chatId) {
|
|
44257
|
-
return (0,
|
|
44555
|
+
return (0, import_path79.join)(this.chatDir, `${chatId}.jsonl`);
|
|
44258
44556
|
}
|
|
44259
44557
|
append(chatId, frame) {
|
|
44260
44558
|
if (!this.isValidChatId(chatId)) return;
|
|
44261
44559
|
if (chatId.startsWith("_")) return;
|
|
44262
44560
|
try {
|
|
44263
|
-
(0,
|
|
44561
|
+
(0, import_fs71.mkdirSync)(this.chatDir, { recursive: true });
|
|
44264
44562
|
const line = JSON.stringify(frame) + "\n";
|
|
44265
|
-
(0,
|
|
44563
|
+
(0, import_fs71.appendFileSync)(this.filePath(chatId), line, "utf8");
|
|
44266
44564
|
const prev = this.appendCounters.get(chatId);
|
|
44267
44565
|
const count = (prev ?? 0) + 1;
|
|
44268
44566
|
this.appendCounters.set(chatId, count);
|
|
@@ -44278,13 +44576,13 @@ var init_chat_store = __esm({
|
|
|
44278
44576
|
if (chatId.startsWith("_")) return;
|
|
44279
44577
|
try {
|
|
44280
44578
|
const fp = this.filePath(chatId);
|
|
44281
|
-
const content = (0,
|
|
44579
|
+
const content = (0, import_fs71.readFileSync)(fp, "utf8");
|
|
44282
44580
|
const lines = content.split("\n").filter((l) => l.length > 0);
|
|
44283
44581
|
if (lines.length < 2 * PERSIST_CAP) return;
|
|
44284
44582
|
const kept = lines.slice(lines.length - PERSIST_CAP);
|
|
44285
44583
|
const tmp = fp + ".tmp";
|
|
44286
|
-
(0,
|
|
44287
|
-
(0,
|
|
44584
|
+
(0, import_fs71.writeFileSync)(tmp, kept.join("\n") + "\n", "utf8");
|
|
44585
|
+
(0, import_fs71.renameSync)(tmp, fp);
|
|
44288
44586
|
} catch (err) {
|
|
44289
44587
|
this.cleanupStaleTmp(chatId);
|
|
44290
44588
|
console.warn(`[chat-store] retain failed for chatId=${chatId}`, err);
|
|
@@ -44299,7 +44597,7 @@ var init_chat_store = __esm({
|
|
|
44299
44597
|
*/
|
|
44300
44598
|
cleanupStaleTmp(chatId) {
|
|
44301
44599
|
try {
|
|
44302
|
-
(0,
|
|
44600
|
+
(0, import_fs71.unlinkSync)(this.filePath(chatId) + ".tmp");
|
|
44303
44601
|
} catch (err) {
|
|
44304
44602
|
if (err?.code !== "ENOENT") {
|
|
44305
44603
|
console.warn(`[chat-store] stale .tmp cleanup failed for chatId=${chatId}:`, err);
|
|
@@ -44311,7 +44609,7 @@ var init_chat_store = __esm({
|
|
|
44311
44609
|
this.cleanupStaleTmp(chatId);
|
|
44312
44610
|
let content;
|
|
44313
44611
|
try {
|
|
44314
|
-
content = (0,
|
|
44612
|
+
content = (0, import_fs71.readFileSync)(this.filePath(chatId), "utf8");
|
|
44315
44613
|
} catch (err) {
|
|
44316
44614
|
if (err?.code === "ENOENT") return [];
|
|
44317
44615
|
console.warn(`[chat-store] load failed for chatId=${chatId}:`, err);
|
|
@@ -44341,7 +44639,7 @@ var init_chat_store = __esm({
|
|
|
44341
44639
|
drop(chatId) {
|
|
44342
44640
|
if (!this.isValidChatId(chatId)) return;
|
|
44343
44641
|
try {
|
|
44344
|
-
(0,
|
|
44642
|
+
(0, import_fs71.unlinkSync)(this.filePath(chatId));
|
|
44345
44643
|
} catch (err) {
|
|
44346
44644
|
if (err?.code !== "ENOENT") {
|
|
44347
44645
|
console.warn(`[chat-store] drop failed for chatId=${chatId}:`, err);
|
|
@@ -45552,20 +45850,20 @@ function normalizeLegacyDegradedFields(report) {
|
|
|
45552
45850
|
}
|
|
45553
45851
|
function resolveDashboardRoot(projectRoot) {
|
|
45554
45852
|
const candidates = [
|
|
45555
|
-
(0,
|
|
45853
|
+
(0, import_path80.resolve)(__dirname, "..", "dist-dashboard"),
|
|
45556
45854
|
// bundled: dist-mcp/mcp-server.js → ../dist-dashboard
|
|
45557
|
-
(0,
|
|
45855
|
+
(0, import_path80.resolve)(__dirname, "..", "..", "..", "..", "dist-dashboard"),
|
|
45558
45856
|
// tsc dev: packages/relay/dist/dashboard → repo-root
|
|
45559
|
-
(0,
|
|
45857
|
+
(0, import_path80.join)(projectRoot, "dist-dashboard")
|
|
45560
45858
|
// legacy dev fallback (git-clone running from repo root)
|
|
45561
45859
|
];
|
|
45562
45860
|
for (const p of candidates) {
|
|
45563
|
-
if ((0,
|
|
45861
|
+
if ((0, import_fs72.existsSync)(p)) return p;
|
|
45564
45862
|
}
|
|
45565
45863
|
return null;
|
|
45566
45864
|
}
|
|
45567
45865
|
function readBody(req, maxBytes = MAX_BODY_SIZE) {
|
|
45568
|
-
return new Promise((
|
|
45866
|
+
return new Promise((resolve33, reject) => {
|
|
45569
45867
|
const chunks = [];
|
|
45570
45868
|
let size = 0;
|
|
45571
45869
|
let tooLarge = false;
|
|
@@ -45580,14 +45878,14 @@ function readBody(req, maxBytes = MAX_BODY_SIZE) {
|
|
|
45580
45878
|
chunks.push(chunk);
|
|
45581
45879
|
});
|
|
45582
45880
|
req.on("end", () => {
|
|
45583
|
-
if (!tooLarge)
|
|
45881
|
+
if (!tooLarge) resolve33(Buffer.concat(chunks).toString("utf-8"));
|
|
45584
45882
|
});
|
|
45585
45883
|
req.on("error", (err) => {
|
|
45586
45884
|
if (!tooLarge) reject(err);
|
|
45587
45885
|
});
|
|
45588
45886
|
});
|
|
45589
45887
|
}
|
|
45590
|
-
var
|
|
45888
|
+
var import_fs72, import_path80, import_crypto28, AUTH_MAX_ATTEMPTS, AUTH_LOCKOUT_MS, AUTH_ATTEMPT_TTL_MS, AUTH_ATTEMPTS_HARD_CAP, CHAT_MAX_BODY, BRIDGE_MAX_BODY, MIRROR_MAX_BODY, MIRROR_MIN_INTERVAL_MS, MIRROR_LAST_TURN_HARD_CAP, CHAT_MIN_INTERVAL_MS, DashboardRouter, MAX_BODY_SIZE;
|
|
45591
45889
|
var init_routes = __esm({
|
|
45592
45890
|
"packages/relay/src/dashboard/routes.ts"() {
|
|
45593
45891
|
"use strict";
|
|
@@ -45607,6 +45905,7 @@ var init_routes = __esm({
|
|
|
45607
45905
|
init_api_open_findings();
|
|
45608
45906
|
init_api_learnings();
|
|
45609
45907
|
init_api_tasks();
|
|
45908
|
+
init_api_task_detail();
|
|
45610
45909
|
init_api_active_tasks();
|
|
45611
45910
|
init_api_session();
|
|
45612
45911
|
init_api_logs();
|
|
@@ -45615,8 +45914,8 @@ var init_routes = __esm({
|
|
|
45615
45914
|
init_api_bridge();
|
|
45616
45915
|
init_chat_session_store();
|
|
45617
45916
|
init_src4();
|
|
45618
|
-
|
|
45619
|
-
|
|
45917
|
+
import_fs72 = require("fs");
|
|
45918
|
+
import_path80 = require("path");
|
|
45620
45919
|
import_crypto28 = require("crypto");
|
|
45621
45920
|
AUTH_MAX_ATTEMPTS = 10;
|
|
45622
45921
|
AUTH_LOCKOUT_MS = 6e4;
|
|
@@ -45634,7 +45933,7 @@ var init_routes = __esm({
|
|
|
45634
45933
|
this.projectRoot = projectRoot;
|
|
45635
45934
|
this.ctx = ctx2;
|
|
45636
45935
|
this.dashboardRoot = resolveDashboardRoot(projectRoot);
|
|
45637
|
-
this.bridge = new BridgeHub({ chatDir: (0,
|
|
45936
|
+
this.bridge = new BridgeHub({ chatDir: (0, import_path80.join)(projectRoot, ".gossip", "chat") });
|
|
45638
45937
|
}
|
|
45639
45938
|
auth;
|
|
45640
45939
|
projectRoot;
|
|
@@ -45935,6 +46234,19 @@ var init_routes = __esm({
|
|
|
45935
46234
|
this.json(res, 200, data);
|
|
45936
46235
|
return true;
|
|
45937
46236
|
}
|
|
46237
|
+
{
|
|
46238
|
+
const m = url2.match(/^\/dashboard\/api\/tasks\/([^/]+)$/);
|
|
46239
|
+
if (m && req.method === "GET") {
|
|
46240
|
+
const taskId = decodeURIComponent(m[1]);
|
|
46241
|
+
const data = await taskDetailHandler(this.projectRoot, taskId);
|
|
46242
|
+
if (data === null) {
|
|
46243
|
+
this.json(res, 404, { error: `Task not found: ${taskId}` });
|
|
46244
|
+
} else {
|
|
46245
|
+
this.json(res, 200, data);
|
|
46246
|
+
}
|
|
46247
|
+
return true;
|
|
46248
|
+
}
|
|
46249
|
+
}
|
|
45938
46250
|
if (url2 === "/dashboard/api/active-tasks" && req.method === "GET") {
|
|
45939
46251
|
const data = await activeTasksHandler(this.projectRoot);
|
|
45940
46252
|
this.json(res, 200, data);
|
|
@@ -46147,13 +46459,13 @@ var init_routes = __esm({
|
|
|
46147
46459
|
res.end("Dashboard assets not found. Reinstall gossipcat or rebuild from source.");
|
|
46148
46460
|
return true;
|
|
46149
46461
|
}
|
|
46150
|
-
const htmlPath = (0,
|
|
46151
|
-
if (!(0,
|
|
46462
|
+
const htmlPath = (0, import_path80.join)(this.dashboardRoot, "index.html");
|
|
46463
|
+
if (!(0, import_fs72.existsSync)(htmlPath)) {
|
|
46152
46464
|
res.writeHead(503, { "Content-Type": "text/plain" });
|
|
46153
46465
|
res.end(`Dashboard index.html missing at ${this.dashboardRoot}. Reinstall gossipcat.`);
|
|
46154
46466
|
return true;
|
|
46155
46467
|
}
|
|
46156
|
-
const html = (0,
|
|
46468
|
+
const html = (0, import_fs72.readFileSync)(htmlPath, "utf-8");
|
|
46157
46469
|
res.writeHead(200, {
|
|
46158
46470
|
"Content-Type": "text/html; charset=utf-8",
|
|
46159
46471
|
"Cache-Control": "no-cache"
|
|
@@ -46182,16 +46494,16 @@ var init_routes = __esm({
|
|
|
46182
46494
|
const ext = "." + (relativePath.split(".").pop() || "");
|
|
46183
46495
|
const mime = MIME[ext];
|
|
46184
46496
|
if (!mime) return false;
|
|
46185
|
-
const filePath = (0,
|
|
46497
|
+
const filePath = (0, import_path80.join)(this.dashboardRoot, relativePath);
|
|
46186
46498
|
try {
|
|
46187
|
-
const realFile = (0,
|
|
46188
|
-
const realBase = (0,
|
|
46499
|
+
const realFile = (0, import_fs72.realpathSync)(filePath);
|
|
46500
|
+
const realBase = (0, import_fs72.realpathSync)(this.dashboardRoot);
|
|
46189
46501
|
if (!realFile.startsWith(realBase + "/")) {
|
|
46190
46502
|
res.writeHead(404);
|
|
46191
46503
|
res.end();
|
|
46192
46504
|
return true;
|
|
46193
46505
|
}
|
|
46194
|
-
const data = (0,
|
|
46506
|
+
const data = (0, import_fs72.readFileSync)(realFile);
|
|
46195
46507
|
res.writeHead(200, { "Content-Type": mime, "Cache-Control": "public, max-age=86400" });
|
|
46196
46508
|
res.end(data);
|
|
46197
46509
|
return true;
|
|
@@ -46206,8 +46518,8 @@ var init_routes = __esm({
|
|
|
46206
46518
|
return match ? match[1] : null;
|
|
46207
46519
|
}
|
|
46208
46520
|
getConsensusReports(page = 1, pageSize = 5) {
|
|
46209
|
-
const { readdirSync: readdirSync22, readFileSync:
|
|
46210
|
-
const reportsDir = (0,
|
|
46521
|
+
const { readdirSync: readdirSync22, readFileSync: readFileSync70, existsSync: existsSync74 } = require("fs");
|
|
46522
|
+
const reportsDir = (0, import_path80.join)(this.projectRoot, ".gossip", "consensus-reports");
|
|
46211
46523
|
let retractedConsensusIds = [];
|
|
46212
46524
|
let roundRetractions = [];
|
|
46213
46525
|
try {
|
|
@@ -46217,13 +46529,13 @@ var init_routes = __esm({
|
|
|
46217
46529
|
roundRetractions = reader.getRoundRetractions();
|
|
46218
46530
|
} catch {
|
|
46219
46531
|
}
|
|
46220
|
-
if (!
|
|
46532
|
+
if (!existsSync74(reportsDir)) return { reports: [], totalReports: 0, page, pageSize, retractedConsensusIds, roundRetractions };
|
|
46221
46533
|
try {
|
|
46222
46534
|
const { statSync: statSync36 } = require("fs");
|
|
46223
46535
|
const allFiles = readdirSync22(reportsDir).filter((f) => f.endsWith(".json")).sort((a, b) => {
|
|
46224
46536
|
try {
|
|
46225
|
-
const aTime = statSync36((0,
|
|
46226
|
-
const bTime = statSync36((0,
|
|
46537
|
+
const aTime = statSync36((0, import_path80.join)(reportsDir, a)).mtimeMs;
|
|
46538
|
+
const bTime = statSync36((0, import_path80.join)(reportsDir, b)).mtimeMs;
|
|
46227
46539
|
return bTime - aTime;
|
|
46228
46540
|
} catch {
|
|
46229
46541
|
return 0;
|
|
@@ -46234,13 +46546,13 @@ var init_routes = __esm({
|
|
|
46234
46546
|
const clampedPage = Math.max(page, 1);
|
|
46235
46547
|
const start = (clampedPage - 1) * clampedPageSize;
|
|
46236
46548
|
const files = allFiles.slice(start, start + clampedPageSize);
|
|
46237
|
-
const realReportsDir = (0,
|
|
46549
|
+
const realReportsDir = (0, import_fs72.realpathSync)(reportsDir);
|
|
46238
46550
|
const reports = files.map((f) => {
|
|
46239
46551
|
try {
|
|
46240
|
-
const filePath = (0,
|
|
46241
|
-
const realFile = (0,
|
|
46552
|
+
const filePath = (0, import_path80.join)(reportsDir, f);
|
|
46553
|
+
const realFile = (0, import_fs72.realpathSync)(filePath);
|
|
46242
46554
|
if (!realFile.startsWith(realReportsDir + "/")) return null;
|
|
46243
|
-
return normalizeLegacyDegradedFields(JSON.parse(
|
|
46555
|
+
return normalizeLegacyDegradedFields(JSON.parse(readFileSync70(realFile, "utf-8")));
|
|
46244
46556
|
} catch {
|
|
46245
46557
|
return null;
|
|
46246
46558
|
}
|
|
@@ -46251,29 +46563,29 @@ var init_routes = __esm({
|
|
|
46251
46563
|
}
|
|
46252
46564
|
}
|
|
46253
46565
|
archiveFindings() {
|
|
46254
|
-
const { readdirSync: readdirSync22, readFileSync:
|
|
46255
|
-
const reportsDir = (0,
|
|
46256
|
-
const archiveDir = (0,
|
|
46566
|
+
const { readdirSync: readdirSync22, readFileSync: readFileSync70, renameSync: renameSync18, writeFileSync: writeFileSync38, mkdirSync: mkdirSync45, existsSync: existsSync74 } = require("fs");
|
|
46567
|
+
const reportsDir = (0, import_path80.join)(this.projectRoot, ".gossip", "consensus-reports");
|
|
46568
|
+
const archiveDir = (0, import_path80.join)(this.projectRoot, ".gossip", "consensus-reports-archive");
|
|
46257
46569
|
let archived = 0;
|
|
46258
|
-
if (
|
|
46570
|
+
if (existsSync74(reportsDir)) {
|
|
46259
46571
|
const files = readdirSync22(reportsDir).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
46260
46572
|
if (files.length > 5) {
|
|
46261
46573
|
mkdirSync45(archiveDir, { recursive: true });
|
|
46262
46574
|
const toArchive = files.slice(5);
|
|
46263
46575
|
for (const f of toArchive) {
|
|
46264
46576
|
try {
|
|
46265
|
-
renameSync18((0,
|
|
46577
|
+
renameSync18((0, import_path80.join)(reportsDir, f), (0, import_path80.join)(archiveDir, f));
|
|
46266
46578
|
archived++;
|
|
46267
46579
|
} catch {
|
|
46268
46580
|
}
|
|
46269
46581
|
}
|
|
46270
46582
|
}
|
|
46271
46583
|
}
|
|
46272
|
-
const findingsPath = (0,
|
|
46584
|
+
const findingsPath = (0, import_path80.join)(this.projectRoot, ".gossip", "implementation-findings.jsonl");
|
|
46273
46585
|
let findingsCleared = 0;
|
|
46274
|
-
if (
|
|
46586
|
+
if (existsSync74(findingsPath)) {
|
|
46275
46587
|
try {
|
|
46276
|
-
const lines =
|
|
46588
|
+
const lines = readFileSync70(findingsPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
46277
46589
|
const kept = lines.filter((line) => {
|
|
46278
46590
|
try {
|
|
46279
46591
|
const entry = JSON.parse(line);
|
|
@@ -46290,7 +46602,7 @@ var init_routes = __esm({
|
|
|
46290
46602
|
} catch {
|
|
46291
46603
|
}
|
|
46292
46604
|
}
|
|
46293
|
-
const remaining =
|
|
46605
|
+
const remaining = existsSync74(reportsDir) ? readdirSync22(reportsDir).filter((f) => f.endsWith(".json")).length : 0;
|
|
46294
46606
|
return { archived, remaining, findingsCleared };
|
|
46295
46607
|
}
|
|
46296
46608
|
json(res, status, data) {
|
|
@@ -46303,14 +46615,14 @@ var init_routes = __esm({
|
|
|
46303
46615
|
});
|
|
46304
46616
|
|
|
46305
46617
|
// packages/relay/src/dashboard/ws.ts
|
|
46306
|
-
var
|
|
46618
|
+
var import_fs73, import_fs74, import_path81, DashboardWs;
|
|
46307
46619
|
var init_ws = __esm({
|
|
46308
46620
|
"packages/relay/src/dashboard/ws.ts"() {
|
|
46309
46621
|
"use strict";
|
|
46310
46622
|
init_wrapper();
|
|
46311
|
-
import_fs72 = require("fs");
|
|
46312
46623
|
import_fs73 = require("fs");
|
|
46313
|
-
|
|
46624
|
+
import_fs74 = require("fs");
|
|
46625
|
+
import_path81 = require("path");
|
|
46314
46626
|
DashboardWs = class {
|
|
46315
46627
|
clients = /* @__PURE__ */ new Set();
|
|
46316
46628
|
logWatcher = null;
|
|
@@ -46335,15 +46647,15 @@ var init_ws = __esm({
|
|
|
46335
46647
|
/** Start watching mcp.log for new lines and broadcasting them to connected clients. */
|
|
46336
46648
|
startLogWatcher(projectRoot) {
|
|
46337
46649
|
this.stopLogWatcher();
|
|
46338
|
-
this.logPath = (0,
|
|
46339
|
-
if (!(0,
|
|
46650
|
+
this.logPath = (0, import_path81.join)(projectRoot, ".gossip", "mcp.log");
|
|
46651
|
+
if (!(0, import_fs73.existsSync)(this.logPath)) return;
|
|
46340
46652
|
try {
|
|
46341
|
-
this.logOffset = (0,
|
|
46653
|
+
this.logOffset = (0, import_fs73.statSync)(this.logPath).size;
|
|
46342
46654
|
} catch {
|
|
46343
46655
|
this.logOffset = 0;
|
|
46344
46656
|
}
|
|
46345
46657
|
try {
|
|
46346
|
-
this.logWatcher = (0,
|
|
46658
|
+
this.logWatcher = (0, import_fs74.watch)(this.logPath, () => {
|
|
46347
46659
|
if (this.clients.size === 0) return;
|
|
46348
46660
|
this.readNewLines();
|
|
46349
46661
|
});
|
|
@@ -46360,7 +46672,7 @@ var init_ws = __esm({
|
|
|
46360
46672
|
if (this.logReading) return;
|
|
46361
46673
|
this.logReading = true;
|
|
46362
46674
|
try {
|
|
46363
|
-
const currentSize = (0,
|
|
46675
|
+
const currentSize = (0, import_fs73.statSync)(this.logPath).size;
|
|
46364
46676
|
if (currentSize < this.logOffset) {
|
|
46365
46677
|
this.logOffset = 0;
|
|
46366
46678
|
this.logCarry = "";
|
|
@@ -46373,7 +46685,7 @@ var init_ws = __esm({
|
|
|
46373
46685
|
const readFrom = capped ? (this.logCarry = "", this.logCapped = true, currentSize - 65536) : (this.logCapped = false, this.logOffset);
|
|
46374
46686
|
let stream;
|
|
46375
46687
|
try {
|
|
46376
|
-
stream = (0,
|
|
46688
|
+
stream = (0, import_fs73.createReadStream)(this.logPath, { start: readFrom, end: currentSize - 1 });
|
|
46377
46689
|
} catch {
|
|
46378
46690
|
this.logReading = false;
|
|
46379
46691
|
return;
|
|
@@ -46487,7 +46799,7 @@ var init_server = __esm({
|
|
|
46487
46799
|
return this.heartbeatRunning;
|
|
46488
46800
|
}
|
|
46489
46801
|
async start() {
|
|
46490
|
-
return new Promise((
|
|
46802
|
+
return new Promise((resolve33) => {
|
|
46491
46803
|
this.httpServer = (0, import_http.createServer)(this.handleHttp.bind(this));
|
|
46492
46804
|
if (this.config.dashboard) {
|
|
46493
46805
|
this.dashboardAuth = new DashboardAuth();
|
|
@@ -46533,7 +46845,7 @@ var init_server = __esm({
|
|
|
46533
46845
|
this.httpServer.listen(this.config.port, this.config.host ?? "127.0.0.1", () => {
|
|
46534
46846
|
const addr = this.httpServer.address();
|
|
46535
46847
|
this._port = addr.port;
|
|
46536
|
-
|
|
46848
|
+
resolve33();
|
|
46537
46849
|
});
|
|
46538
46850
|
});
|
|
46539
46851
|
}
|
|
@@ -46553,9 +46865,9 @@ var init_server = __esm({
|
|
|
46553
46865
|
for (const client of this.wss.clients) {
|
|
46554
46866
|
client.close(1001, "Server shutting down");
|
|
46555
46867
|
}
|
|
46556
|
-
return new Promise((
|
|
46868
|
+
return new Promise((resolve33) => {
|
|
46557
46869
|
this.wss.close(() => {
|
|
46558
|
-
this.httpServer.close(() =>
|
|
46870
|
+
this.httpServer.close(() => resolve33());
|
|
46559
46871
|
});
|
|
46560
46872
|
});
|
|
46561
46873
|
}
|
|
@@ -46969,8 +47281,8 @@ function parsePorcelain(output) {
|
|
|
46969
47281
|
const paths = [];
|
|
46970
47282
|
for (const line of lines) {
|
|
46971
47283
|
if (line.length < 4) continue;
|
|
46972
|
-
const
|
|
46973
|
-
if (
|
|
47284
|
+
const path8 = line.slice(3);
|
|
47285
|
+
if (path8) paths.push(path8);
|
|
46974
47286
|
}
|
|
46975
47287
|
return paths.sort();
|
|
46976
47288
|
}
|
|
@@ -46993,12 +47305,12 @@ function revertLeakedPaths(cwd, paths) {
|
|
|
46993
47305
|
if (!paths || paths.length === 0) return result;
|
|
46994
47306
|
const { safe: safePaths, rejected } = filterSafePaths(paths);
|
|
46995
47307
|
result.rejected = rejected;
|
|
46996
|
-
const
|
|
46997
|
-
const
|
|
47308
|
+
const fs7 = require("fs");
|
|
47309
|
+
const path8 = require("path");
|
|
46998
47310
|
const present = [];
|
|
46999
47311
|
for (const p of safePaths) {
|
|
47000
|
-
const abs =
|
|
47001
|
-
if (
|
|
47312
|
+
const abs = path8.join(cwd, p);
|
|
47313
|
+
if (fs7.existsSync(abs)) {
|
|
47002
47314
|
present.push(p);
|
|
47003
47315
|
} else {
|
|
47004
47316
|
result.skipped.push(p);
|
|
@@ -47028,12 +47340,12 @@ function preserveLeakedPaths(cwd, paths, taskId) {
|
|
|
47028
47340
|
}
|
|
47029
47341
|
const { safe: safePaths, rejected } = filterSafePaths(paths);
|
|
47030
47342
|
result.rejected = rejected;
|
|
47031
|
-
const
|
|
47032
|
-
const
|
|
47343
|
+
const fs7 = require("fs");
|
|
47344
|
+
const path8 = require("path");
|
|
47033
47345
|
const crypto3 = require("crypto");
|
|
47034
47346
|
const present = [];
|
|
47035
47347
|
for (const p of safePaths) {
|
|
47036
|
-
if (
|
|
47348
|
+
if (fs7.existsSync(path8.join(cwd, p))) {
|
|
47037
47349
|
present.push(p);
|
|
47038
47350
|
} else {
|
|
47039
47351
|
result.skipped.push(p);
|
|
@@ -47068,16 +47380,16 @@ function preserveLeakedPaths(cwd, paths, taskId) {
|
|
|
47068
47380
|
result.emptyDiff = true;
|
|
47069
47381
|
return result;
|
|
47070
47382
|
}
|
|
47071
|
-
const recoveryDir =
|
|
47072
|
-
|
|
47073
|
-
const finalPath =
|
|
47074
|
-
const tmpPath =
|
|
47383
|
+
const recoveryDir = path8.join(cwd, ".gossip", "recovery");
|
|
47384
|
+
fs7.mkdirSync(recoveryDir, { recursive: true });
|
|
47385
|
+
const finalPath = path8.join(recoveryDir, `${taskId}.patch`);
|
|
47386
|
+
const tmpPath = path8.join(recoveryDir, `${taskId}.patch.${crypto3.randomUUID().slice(0, 8)}.tmp`);
|
|
47075
47387
|
try {
|
|
47076
|
-
|
|
47077
|
-
|
|
47388
|
+
fs7.writeFileSync(tmpPath, diff);
|
|
47389
|
+
fs7.renameSync(tmpPath, finalPath);
|
|
47078
47390
|
} catch (err) {
|
|
47079
47391
|
try {
|
|
47080
|
-
|
|
47392
|
+
fs7.unlinkSync(tmpPath);
|
|
47081
47393
|
} catch {
|
|
47082
47394
|
}
|
|
47083
47395
|
throw err;
|
|
@@ -47221,14 +47533,14 @@ __export(sandbox_exports, {
|
|
|
47221
47533
|
});
|
|
47222
47534
|
function rotateIfNeeded2(filePath, maxBytes) {
|
|
47223
47535
|
try {
|
|
47224
|
-
const st = (0,
|
|
47536
|
+
const st = (0, import_fs75.statSync)(filePath);
|
|
47225
47537
|
if (st.size < maxBytes) return;
|
|
47226
47538
|
const rotated = filePath + ".1";
|
|
47227
47539
|
try {
|
|
47228
|
-
if ((0,
|
|
47540
|
+
if ((0, import_fs75.existsSync)(rotated)) (0, import_fs75.unlinkSync)(rotated);
|
|
47229
47541
|
} catch {
|
|
47230
47542
|
}
|
|
47231
|
-
(0,
|
|
47543
|
+
(0, import_fs75.renameSync)(filePath, rotated);
|
|
47232
47544
|
} catch {
|
|
47233
47545
|
}
|
|
47234
47546
|
}
|
|
@@ -47301,9 +47613,9 @@ Tests passing is NOT sufficient verification \u2014 the 2026-04-22 incident had
|
|
|
47301
47613
|
}
|
|
47302
47614
|
function readSandboxMode(projectRoot) {
|
|
47303
47615
|
try {
|
|
47304
|
-
const p = (0,
|
|
47305
|
-
if (!(0,
|
|
47306
|
-
const raw = JSON.parse((0,
|
|
47616
|
+
const p = (0, import_path82.join)(projectRoot, ".gossip", "config.json");
|
|
47617
|
+
if (!(0, import_fs75.existsSync)(p)) return "warn";
|
|
47618
|
+
const raw = JSON.parse((0, import_fs75.readFileSync)(p, "utf-8"));
|
|
47307
47619
|
const mode = raw?.sandboxEnforcement;
|
|
47308
47620
|
if (mode === "off" || mode === "warn" || mode === "block") return mode;
|
|
47309
47621
|
return "warn";
|
|
@@ -47313,8 +47625,8 @@ function readSandboxMode(projectRoot) {
|
|
|
47313
47625
|
}
|
|
47314
47626
|
function recordDispatchMetadata(projectRoot, meta3) {
|
|
47315
47627
|
try {
|
|
47316
|
-
const dir = (0,
|
|
47317
|
-
(0,
|
|
47628
|
+
const dir = (0, import_path82.join)(projectRoot, ".gossip");
|
|
47629
|
+
(0, import_fs75.mkdirSync)(dir, { recursive: true });
|
|
47318
47630
|
const snapshotted = { ...meta3 };
|
|
47319
47631
|
if (meta3.writeMode === "scoped" || meta3.writeMode === "worktree") {
|
|
47320
47632
|
try {
|
|
@@ -47332,15 +47644,15 @@ function recordDispatchMetadata(projectRoot, meta3) {
|
|
|
47332
47644
|
} catch {
|
|
47333
47645
|
}
|
|
47334
47646
|
}
|
|
47335
|
-
(0,
|
|
47647
|
+
(0, import_fs75.appendFileSync)((0, import_path82.join)(dir, METADATA_FILE), JSON.stringify(snapshotted) + "\n");
|
|
47336
47648
|
} catch {
|
|
47337
47649
|
}
|
|
47338
47650
|
}
|
|
47339
47651
|
function updateDispatchMetadata(projectRoot, taskId, patch) {
|
|
47340
47652
|
try {
|
|
47341
|
-
const p = (0,
|
|
47342
|
-
if (!(0,
|
|
47343
|
-
const raw = (0,
|
|
47653
|
+
const p = (0, import_path82.join)(projectRoot, ".gossip", METADATA_FILE);
|
|
47654
|
+
if (!(0, import_fs75.existsSync)(p)) return false;
|
|
47655
|
+
const raw = (0, import_fs75.readFileSync)(p, "utf-8");
|
|
47344
47656
|
const lines = raw.split("\n");
|
|
47345
47657
|
let patched = false;
|
|
47346
47658
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -47358,7 +47670,7 @@ function updateDispatchMetadata(projectRoot, taskId, patch) {
|
|
|
47358
47670
|
}
|
|
47359
47671
|
}
|
|
47360
47672
|
if (!patched) return false;
|
|
47361
|
-
(0,
|
|
47673
|
+
(0, import_fs75.writeFileSync)(p, lines.join("\n"));
|
|
47362
47674
|
return true;
|
|
47363
47675
|
} catch {
|
|
47364
47676
|
return false;
|
|
@@ -47367,15 +47679,15 @@ function updateDispatchMetadata(projectRoot, taskId, patch) {
|
|
|
47367
47679
|
function stampTaskSentinel(projectRoot, taskId) {
|
|
47368
47680
|
if (!taskId) return null;
|
|
47369
47681
|
try {
|
|
47370
|
-
const dir = (0,
|
|
47371
|
-
(0,
|
|
47682
|
+
const dir = (0, import_path82.join)(projectRoot, ".gossip", SENTINEL_DIR);
|
|
47683
|
+
(0, import_fs75.mkdirSync)(dir, { recursive: true });
|
|
47372
47684
|
const slug = taskId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
47373
|
-
const
|
|
47374
|
-
const fd = (0,
|
|
47375
|
-
(0,
|
|
47685
|
+
const path8 = (0, import_path82.join)(dir, `${slug}.sentinel`);
|
|
47686
|
+
const fd = (0, import_fs75.openSync)(path8, "w");
|
|
47687
|
+
(0, import_fs75.closeSync)(fd);
|
|
47376
47688
|
const stampTime = new Date(Date.now() - 2e3);
|
|
47377
|
-
(0,
|
|
47378
|
-
return
|
|
47689
|
+
(0, import_fs75.utimesSync)(path8, stampTime, stampTime);
|
|
47690
|
+
return path8;
|
|
47379
47691
|
} catch {
|
|
47380
47692
|
return null;
|
|
47381
47693
|
}
|
|
@@ -47383,15 +47695,15 @@ function stampTaskSentinel(projectRoot, taskId) {
|
|
|
47383
47695
|
function cleanupTaskSentinel(sentinelPath) {
|
|
47384
47696
|
if (!sentinelPath) return;
|
|
47385
47697
|
try {
|
|
47386
|
-
(0,
|
|
47698
|
+
(0, import_fs75.unlinkSync)(sentinelPath);
|
|
47387
47699
|
} catch {
|
|
47388
47700
|
}
|
|
47389
47701
|
}
|
|
47390
47702
|
function lookupDispatchMetadata(projectRoot, taskId) {
|
|
47391
47703
|
try {
|
|
47392
|
-
const p = (0,
|
|
47393
|
-
if (!(0,
|
|
47394
|
-
const raw = (0,
|
|
47704
|
+
const p = (0, import_path82.join)(projectRoot, ".gossip", METADATA_FILE);
|
|
47705
|
+
if (!(0, import_fs75.existsSync)(p)) return null;
|
|
47706
|
+
const raw = (0, import_fs75.readFileSync)(p, "utf-8");
|
|
47395
47707
|
const lines = raw.split("\n").filter(Boolean);
|
|
47396
47708
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
47397
47709
|
try {
|
|
@@ -47423,21 +47735,21 @@ function parseGitStatus(porcelain) {
|
|
|
47423
47735
|
function normalizeScope(scope, projectRoot) {
|
|
47424
47736
|
let s = scope.trim();
|
|
47425
47737
|
if (!s) return "";
|
|
47426
|
-
if ((0,
|
|
47427
|
-
s = (0,
|
|
47738
|
+
if ((0, import_path82.isAbsolute)(s)) {
|
|
47739
|
+
s = (0, import_path82.relative)(projectRoot, s);
|
|
47428
47740
|
} else if (s.startsWith("./")) {
|
|
47429
47741
|
s = s.slice(2);
|
|
47430
47742
|
}
|
|
47431
|
-
s = (0,
|
|
47743
|
+
s = (0, import_path82.normalize)(s).replace(/\/+$/, "");
|
|
47432
47744
|
if (s === "." || s === "") return "";
|
|
47433
47745
|
return s;
|
|
47434
47746
|
}
|
|
47435
47747
|
function isInsideScope(filePath, scope) {
|
|
47436
47748
|
if (!scope) return true;
|
|
47437
|
-
const f = (0,
|
|
47749
|
+
const f = (0, import_path82.normalize)(filePath).replace(/^\.\//, "");
|
|
47438
47750
|
const s = scope.replace(/^\.\//, "").replace(/\/+$/, "");
|
|
47439
47751
|
if (f === s) return true;
|
|
47440
|
-
return f.startsWith(s + "/") || f.startsWith(s +
|
|
47752
|
+
return f.startsWith(s + "/") || f.startsWith(s + import_path82.sep);
|
|
47441
47753
|
}
|
|
47442
47754
|
function detectBoundaryEscapes(meta3, modifiedFiles, projectRoot) {
|
|
47443
47755
|
const mode = meta3.writeMode;
|
|
@@ -47498,8 +47810,8 @@ function recordBoundaryEscape(projectRoot, meta3, violations, mode) {
|
|
|
47498
47810
|
} catch {
|
|
47499
47811
|
}
|
|
47500
47812
|
try {
|
|
47501
|
-
const dir = (0,
|
|
47502
|
-
(0,
|
|
47813
|
+
const dir = (0, import_path82.join)(projectRoot, ".gossip");
|
|
47814
|
+
(0, import_fs75.mkdirSync)(dir, { recursive: true });
|
|
47503
47815
|
const line = {
|
|
47504
47816
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
47505
47817
|
taskId: meta3.taskId,
|
|
@@ -47510,15 +47822,15 @@ function recordBoundaryEscape(projectRoot, meta3, violations, mode) {
|
|
|
47510
47822
|
action: mode
|
|
47511
47823
|
// "warn" or "block"
|
|
47512
47824
|
};
|
|
47513
|
-
const escapeFile = (0,
|
|
47825
|
+
const escapeFile = (0, import_path82.join)(dir, BOUNDARY_ESCAPE_FILE);
|
|
47514
47826
|
rotateIfNeeded2(escapeFile, MAX_BOUNDARY_ESCAPE_BYTES);
|
|
47515
|
-
(0,
|
|
47827
|
+
(0, import_fs75.appendFileSync)(escapeFile, JSON.stringify(line) + "\n");
|
|
47516
47828
|
} catch {
|
|
47517
47829
|
}
|
|
47518
47830
|
}
|
|
47519
47831
|
function canonicalize(p) {
|
|
47520
47832
|
try {
|
|
47521
|
-
return (0,
|
|
47833
|
+
return (0, import_path82.resolve)(p).replace(/\/+$/, "") || "/";
|
|
47522
47834
|
} catch {
|
|
47523
47835
|
return p.replace(/\/+$/, "") || "/";
|
|
47524
47836
|
}
|
|
@@ -47544,8 +47856,8 @@ function defaultScanRoots(writeMode, projectRoot) {
|
|
|
47544
47856
|
out.add("/private/tmp");
|
|
47545
47857
|
return Array.from(out);
|
|
47546
47858
|
}
|
|
47547
|
-
function expandTmpVariants(
|
|
47548
|
-
const p =
|
|
47859
|
+
function expandTmpVariants(path8) {
|
|
47860
|
+
const p = path8.replace(/\/+$/, "") || "/";
|
|
47549
47861
|
for (const root of ["/tmp", "/etc", "/var"]) {
|
|
47550
47862
|
if (p === root || p.startsWith(root + "/")) {
|
|
47551
47863
|
return [p, "/private" + p];
|
|
@@ -47629,7 +47941,7 @@ function buildAuditExclusions(projectRoot, ownWorktree, scope) {
|
|
|
47629
47941
|
for (const v of expandTmpVariants(wt)) excl.add(v);
|
|
47630
47942
|
}
|
|
47631
47943
|
if (scope) {
|
|
47632
|
-
const s = canonicalize((0,
|
|
47944
|
+
const s = canonicalize((0, import_path82.join)(projectRoot, scope));
|
|
47633
47945
|
for (const v of expandTmpVariants(s)) excl.add(v);
|
|
47634
47946
|
}
|
|
47635
47947
|
return Array.from(excl);
|
|
@@ -47718,12 +48030,12 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
|
|
|
47718
48030
|
return { violations: [], skipped: "win32" };
|
|
47719
48031
|
}
|
|
47720
48032
|
const sentinel = meta3.sentinelPath;
|
|
47721
|
-
if (!sentinel || !(0,
|
|
48033
|
+
if (!sentinel || !(0, import_fs75.existsSync)(sentinel)) {
|
|
47722
48034
|
return { violations: [], skipped: "sentinel missing" };
|
|
47723
48035
|
}
|
|
47724
48036
|
let sentinelMtimeMs = 0;
|
|
47725
48037
|
try {
|
|
47726
|
-
sentinelMtimeMs = (0,
|
|
48038
|
+
sentinelMtimeMs = (0, import_fs75.statSync)(sentinel).mtimeMs;
|
|
47727
48039
|
} catch {
|
|
47728
48040
|
}
|
|
47729
48041
|
if (sentinelMtimeMs === 0) {
|
|
@@ -47735,11 +48047,11 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
|
|
|
47735
48047
|
);
|
|
47736
48048
|
const exclusions = buildAuditExclusions(projectRoot, meta3.worktreePath, options.scope);
|
|
47737
48049
|
const findBin = options.findBinary ?? "find";
|
|
47738
|
-
const sentinelDir = canonicalize((0,
|
|
48050
|
+
const sentinelDir = canonicalize((0, import_path82.join)(projectRoot, ".gossip", SENTINEL_DIR));
|
|
47739
48051
|
const mainSet = /* @__PURE__ */ new Set();
|
|
47740
48052
|
const sensitiveSet = /* @__PURE__ */ new Set();
|
|
47741
48053
|
for (const root of scanRoots) {
|
|
47742
|
-
if (!(0,
|
|
48054
|
+
if (!(0, import_fs75.existsSync)(root)) continue;
|
|
47743
48055
|
const canonRoot = canonicalize(root);
|
|
47744
48056
|
const allExcl = [...exclusions, ...expandTmpVariants(sentinelDir)];
|
|
47745
48057
|
const args = buildFindPruneArgs(canonRoot, allExcl, sentinel);
|
|
@@ -47775,7 +48087,7 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
|
|
|
47775
48087
|
}
|
|
47776
48088
|
const sensitiveTargets = buildSensitiveTargets(platform2);
|
|
47777
48089
|
for (const target of sensitiveTargets) {
|
|
47778
|
-
if (!(0,
|
|
48090
|
+
if (!(0, import_fs75.existsSync)(target.path)) continue;
|
|
47779
48091
|
const canonTarget = canonicalize(target.path);
|
|
47780
48092
|
const args = buildSensitiveFindArgs(
|
|
47781
48093
|
canonTarget,
|
|
@@ -47849,21 +48161,21 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
|
|
|
47849
48161
|
}
|
|
47850
48162
|
function recordLayer3Violations(projectRoot, meta3, violations, source) {
|
|
47851
48163
|
try {
|
|
47852
|
-
const dir = (0,
|
|
47853
|
-
(0,
|
|
48164
|
+
const dir = (0, import_path82.join)(projectRoot, ".gossip");
|
|
48165
|
+
(0, import_fs75.mkdirSync)(dir, { recursive: true });
|
|
47854
48166
|
const ts2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
47855
48167
|
const lines = violations.map(
|
|
47856
|
-
(
|
|
48168
|
+
(path8) => JSON.stringify({
|
|
47857
48169
|
timestamp: ts2,
|
|
47858
48170
|
taskId: meta3.taskId,
|
|
47859
48171
|
agentId: meta3.agentId,
|
|
47860
|
-
violatingPaths: [
|
|
48172
|
+
violatingPaths: [path8],
|
|
47861
48173
|
source
|
|
47862
48174
|
})
|
|
47863
48175
|
);
|
|
47864
|
-
const escapeFile = (0,
|
|
48176
|
+
const escapeFile = (0, import_path82.join)(dir, BOUNDARY_ESCAPE_FILE);
|
|
47865
48177
|
rotateIfNeeded2(escapeFile, MAX_BOUNDARY_ESCAPE_BYTES);
|
|
47866
|
-
(0,
|
|
48178
|
+
(0, import_fs75.appendFileSync)(escapeFile, lines.join("\n") + "\n");
|
|
47867
48179
|
} catch {
|
|
47868
48180
|
}
|
|
47869
48181
|
if (source === "layer3-sensitive" && violations.length > 0) {
|
|
@@ -47920,14 +48232,14 @@ function runLayer3Audit(projectRoot, taskId) {
|
|
|
47920
48232
|
}
|
|
47921
48233
|
return { blockError, warnPrefix };
|
|
47922
48234
|
}
|
|
47923
|
-
var import_child_process12,
|
|
48235
|
+
var import_child_process12, import_fs75, import_os5, import_path82, 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, LAYER3_KEEP_TMPDIR_PREFIXES, __test__;
|
|
47924
48236
|
var init_sandbox2 = __esm({
|
|
47925
48237
|
"apps/cli/src/sandbox.ts"() {
|
|
47926
48238
|
"use strict";
|
|
47927
48239
|
import_child_process12 = require("child_process");
|
|
47928
|
-
|
|
48240
|
+
import_fs75 = require("fs");
|
|
47929
48241
|
import_os5 = require("os");
|
|
47930
|
-
|
|
48242
|
+
import_path82 = require("path");
|
|
47931
48243
|
METADATA_FILE = "dispatch-metadata.jsonl";
|
|
47932
48244
|
BOUNDARY_ESCAPE_FILE = "boundary-escapes.jsonl";
|
|
47933
48245
|
SENTINEL_DIR = "sentinels";
|
|
@@ -47999,7 +48311,7 @@ __export(dispatch_prompt_storage_exports, {
|
|
|
47999
48311
|
writeDispatchPrompt: () => writeDispatchPrompt
|
|
48000
48312
|
});
|
|
48001
48313
|
function dispatchPromptsDir(projectRoot) {
|
|
48002
|
-
return (0,
|
|
48314
|
+
return (0, import_path83.join)(projectRoot, ".gossip", DISPATCH_PROMPTS_SUBDIR);
|
|
48003
48315
|
}
|
|
48004
48316
|
function assertSafeTaskId(taskId) {
|
|
48005
48317
|
if (typeof taskId !== "string" || taskId.length === 0) {
|
|
@@ -48012,35 +48324,35 @@ function assertSafeTaskId(taskId) {
|
|
|
48012
48324
|
function writeDispatchPrompt(projectRoot, taskId, body) {
|
|
48013
48325
|
assertSafeTaskId(taskId);
|
|
48014
48326
|
const dir = dispatchPromptsDir(projectRoot);
|
|
48015
|
-
(0,
|
|
48016
|
-
const finalPath = (0,
|
|
48017
|
-
const tmpPath = (0,
|
|
48327
|
+
(0, import_fs76.mkdirSync)(dir, { recursive: true });
|
|
48328
|
+
const finalPath = (0, import_path83.join)(dir, `${taskId}.txt`);
|
|
48329
|
+
const tmpPath = (0, import_path83.join)(dir, `${taskId}.txt.${(0, import_crypto30.randomUUID)().slice(0, 8)}.tmp`);
|
|
48018
48330
|
try {
|
|
48019
|
-
(0,
|
|
48020
|
-
(0,
|
|
48331
|
+
(0, import_fs76.writeFileSync)(tmpPath, body, "utf8");
|
|
48332
|
+
(0, import_fs76.renameSync)(tmpPath, finalPath);
|
|
48021
48333
|
} catch (err) {
|
|
48022
48334
|
try {
|
|
48023
|
-
(0,
|
|
48335
|
+
(0, import_fs76.unlinkSync)(tmpPath);
|
|
48024
48336
|
} catch {
|
|
48025
48337
|
}
|
|
48026
48338
|
throw err;
|
|
48027
48339
|
}
|
|
48028
|
-
return (0,
|
|
48340
|
+
return (0, import_path83.resolve)(finalPath);
|
|
48029
48341
|
}
|
|
48030
48342
|
function cleanupExpiredDispatchPrompts(projectRoot, maxAgeMs = DEFAULT_PROMPT_TTL_MS, capBytes = DISPATCH_PROMPT_CAP_BYTES) {
|
|
48031
48343
|
const dir = dispatchPromptsDir(projectRoot);
|
|
48032
|
-
if (!(0,
|
|
48344
|
+
if (!(0, import_fs76.existsSync)(dir)) return { evictedAge: 0, evictedCap: 0 };
|
|
48033
48345
|
const now = Date.now();
|
|
48034
48346
|
let entries = [];
|
|
48035
48347
|
try {
|
|
48036
|
-
for (const name of (0,
|
|
48037
|
-
const
|
|
48348
|
+
for (const name of (0, import_fs76.readdirSync)(dir)) {
|
|
48349
|
+
const path8 = (0, import_path83.join)(dir, name);
|
|
48038
48350
|
try {
|
|
48039
|
-
const st = (0,
|
|
48351
|
+
const st = (0, import_fs76.statSync)(path8);
|
|
48040
48352
|
if (!st.isFile()) continue;
|
|
48041
|
-
entries.push({ name, path:
|
|
48353
|
+
entries.push({ name, path: path8, mtimeMs: st.mtimeMs, size: st.size });
|
|
48042
48354
|
} catch (err) {
|
|
48043
|
-
process.stderr.write(`[gossipcat] dispatch-prompt stat failed for ${(0,
|
|
48355
|
+
process.stderr.write(`[gossipcat] dispatch-prompt stat failed for ${(0, import_path83.basename)(path8)}: ${err.message}
|
|
48044
48356
|
`);
|
|
48045
48357
|
}
|
|
48046
48358
|
}
|
|
@@ -48054,7 +48366,7 @@ function cleanupExpiredDispatchPrompts(projectRoot, maxAgeMs = DEFAULT_PROMPT_TT
|
|
|
48054
48366
|
for (const e of entries) {
|
|
48055
48367
|
if (now - e.mtimeMs > maxAgeMs) {
|
|
48056
48368
|
try {
|
|
48057
|
-
(0,
|
|
48369
|
+
(0, import_fs76.unlinkSync)(e.path);
|
|
48058
48370
|
evictedAge++;
|
|
48059
48371
|
} catch (err) {
|
|
48060
48372
|
process.stderr.write(`[gossipcat] dispatch-prompt unlink failed for ${e.name}: ${err.message}
|
|
@@ -48071,7 +48383,7 @@ function cleanupExpiredDispatchPrompts(projectRoot, maxAgeMs = DEFAULT_PROMPT_TT
|
|
|
48071
48383
|
for (const e of survivors) {
|
|
48072
48384
|
if (totalBytes <= capBytes) break;
|
|
48073
48385
|
try {
|
|
48074
|
-
(0,
|
|
48386
|
+
(0, import_fs76.unlinkSync)(e.path);
|
|
48075
48387
|
totalBytes -= e.size;
|
|
48076
48388
|
evictedCap++;
|
|
48077
48389
|
} catch (err) {
|
|
@@ -48084,18 +48396,18 @@ function cleanupExpiredDispatchPrompts(projectRoot, maxAgeMs = DEFAULT_PROMPT_TT
|
|
|
48084
48396
|
}
|
|
48085
48397
|
function pruneOrphanDispatchPrompts(projectRoot, knownTaskIds, maxAgeMs = DEFAULT_PROMPT_TTL_MS) {
|
|
48086
48398
|
const dir = dispatchPromptsDir(projectRoot);
|
|
48087
|
-
if (!(0,
|
|
48399
|
+
if (!(0, import_fs76.existsSync)(dir)) return { orphans: 0, aged: 0 };
|
|
48088
48400
|
const now = Date.now();
|
|
48089
48401
|
let orphans = 0;
|
|
48090
48402
|
let aged = 0;
|
|
48091
48403
|
try {
|
|
48092
|
-
for (const name of (0,
|
|
48404
|
+
for (const name of (0, import_fs76.readdirSync)(dir)) {
|
|
48093
48405
|
if (!name.endsWith(".txt")) continue;
|
|
48094
48406
|
const taskId = name.slice(0, -4);
|
|
48095
|
-
const
|
|
48407
|
+
const path8 = (0, import_path83.join)(dir, name);
|
|
48096
48408
|
let mtimeMs = 0;
|
|
48097
48409
|
try {
|
|
48098
|
-
mtimeMs = (0,
|
|
48410
|
+
mtimeMs = (0, import_fs76.statSync)(path8).mtimeMs;
|
|
48099
48411
|
} catch {
|
|
48100
48412
|
continue;
|
|
48101
48413
|
}
|
|
@@ -48103,7 +48415,7 @@ function pruneOrphanDispatchPrompts(projectRoot, knownTaskIds, maxAgeMs = DEFAUL
|
|
|
48103
48415
|
const orphaned = !knownTaskIds.has(taskId);
|
|
48104
48416
|
if (tooOld || orphaned) {
|
|
48105
48417
|
try {
|
|
48106
|
-
(0,
|
|
48418
|
+
(0, import_fs76.unlinkSync)(path8);
|
|
48107
48419
|
if (orphaned) orphans++;
|
|
48108
48420
|
if (tooOld) aged++;
|
|
48109
48421
|
} catch (err) {
|
|
@@ -48120,14 +48432,14 @@ function pruneOrphanDispatchPrompts(projectRoot, knownTaskIds, maxAgeMs = DEFAUL
|
|
|
48120
48432
|
}
|
|
48121
48433
|
function dispatchPromptPath(projectRoot, taskId) {
|
|
48122
48434
|
assertSafeTaskId(taskId);
|
|
48123
|
-
return (0,
|
|
48435
|
+
return (0, import_path83.resolve)((0, import_path83.join)(dispatchPromptsDir(projectRoot), `${taskId}.txt`));
|
|
48124
48436
|
}
|
|
48125
|
-
var
|
|
48437
|
+
var import_fs76, import_path83, import_crypto30, SAFE_TASK_ID2, DISPATCH_PROMPT_CAP_BYTES, DEFAULT_PROMPT_TTL_MS, DISPATCH_PROMPTS_SUBDIR;
|
|
48126
48438
|
var init_dispatch_prompt_storage = __esm({
|
|
48127
48439
|
"apps/cli/src/handlers/dispatch-prompt-storage.ts"() {
|
|
48128
48440
|
"use strict";
|
|
48129
|
-
|
|
48130
|
-
|
|
48441
|
+
import_fs76 = require("fs");
|
|
48442
|
+
import_path83 = require("path");
|
|
48131
48443
|
import_crypto30 = require("crypto");
|
|
48132
48444
|
SAFE_TASK_ID2 = /^(?!.*\.\.)[A-Za-z0-9._-]{1,64}$/;
|
|
48133
48445
|
DISPATCH_PROMPT_CAP_BYTES = 100 * 1024 * 1024;
|
|
@@ -48181,9 +48493,9 @@ function getCommitRange(preSha, postSha) {
|
|
|
48181
48493
|
function appendViolationRecord(record2) {
|
|
48182
48494
|
try {
|
|
48183
48495
|
const projectRoot = process.cwd();
|
|
48184
|
-
(0,
|
|
48185
|
-
const logPath = (0,
|
|
48186
|
-
(0,
|
|
48496
|
+
(0, import_fs77.mkdirSync)((0, import_path84.join)(projectRoot, ".gossip"), { recursive: true });
|
|
48497
|
+
const logPath = (0, import_path84.join)(projectRoot, PROCESS_VIOLATIONS_FILE);
|
|
48498
|
+
(0, import_fs77.appendFileSync)(logPath, JSON.stringify(record2) + "\n", "utf8");
|
|
48187
48499
|
} catch (err) {
|
|
48188
48500
|
process.stderr.write(`[gossipcat] ref-allowlist: failed to append violation record: ${err.message}
|
|
48189
48501
|
`);
|
|
@@ -48233,17 +48545,289 @@ Full audit trail at .gossip/process-violations.jsonl
|
|
|
48233
48545
|
`
|
|
48234
48546
|
);
|
|
48235
48547
|
}
|
|
48236
|
-
var
|
|
48548
|
+
var import_fs77, import_path84, import_child_process13, PROCESS_VIOLATIONS_FILE;
|
|
48237
48549
|
var init_ref_allowlist_detection = __esm({
|
|
48238
48550
|
"apps/cli/src/handlers/ref-allowlist-detection.ts"() {
|
|
48239
48551
|
"use strict";
|
|
48240
|
-
|
|
48241
|
-
|
|
48552
|
+
import_fs77 = require("fs");
|
|
48553
|
+
import_path84 = require("path");
|
|
48242
48554
|
import_child_process13 = require("child_process");
|
|
48243
48555
|
PROCESS_VIOLATIONS_FILE = ".gossip/process-violations.jsonl";
|
|
48244
48556
|
}
|
|
48245
48557
|
});
|
|
48246
48558
|
|
|
48559
|
+
// apps/cli/src/handlers/orchestrator-precondition-runner.ts
|
|
48560
|
+
function captureHeadSha(projectRoot, execFile6 = defaultExecFile) {
|
|
48561
|
+
try {
|
|
48562
|
+
const cwd = projectRoot || process.cwd();
|
|
48563
|
+
const sha = execFile6("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8" }).trim();
|
|
48564
|
+
return sha || void 0;
|
|
48565
|
+
} catch {
|
|
48566
|
+
return void 0;
|
|
48567
|
+
}
|
|
48568
|
+
}
|
|
48569
|
+
function getCommitsSince(sinceSha, projectRoot, execFile6 = defaultExecFile) {
|
|
48570
|
+
try {
|
|
48571
|
+
const output = execFile6("git", ["log", `${sinceSha}..HEAD`, "--format=%H"], {
|
|
48572
|
+
cwd: projectRoot,
|
|
48573
|
+
encoding: "utf8"
|
|
48574
|
+
});
|
|
48575
|
+
return output.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
48576
|
+
} catch {
|
|
48577
|
+
return [];
|
|
48578
|
+
}
|
|
48579
|
+
}
|
|
48580
|
+
async function runMidFlightCheck(input, deps = {}) {
|
|
48581
|
+
const warnings = [];
|
|
48582
|
+
if (!input.roundStartSha) {
|
|
48583
|
+
return { warnings };
|
|
48584
|
+
}
|
|
48585
|
+
const execFile6 = deps.execFile ?? defaultExecFile;
|
|
48586
|
+
const emitSignals = deps.emitSignals ?? defaultEmitSignals;
|
|
48587
|
+
try {
|
|
48588
|
+
const { projectRoot, consensusId, roundStartSha } = input;
|
|
48589
|
+
const commits = getCommitsSince(roundStartSha, projectRoot, execFile6);
|
|
48590
|
+
const { detected, count } = detectMidFlightCommits(commits);
|
|
48591
|
+
if (!detected) {
|
|
48592
|
+
return { warnings };
|
|
48593
|
+
}
|
|
48594
|
+
warnings.push(
|
|
48595
|
+
`[mid-flight-fixup] ${count} commit(s) landed during Phase 2 cross-review (since ${roundStartSha.slice(0, 8)}). Reviewers may have seen post-fix code and marked legitimate Phase 1 findings DISAGREE. Consensus round: ${consensusId}.`
|
|
48596
|
+
);
|
|
48597
|
+
try {
|
|
48598
|
+
emitSignals(projectRoot, [{
|
|
48599
|
+
type: "pipeline",
|
|
48600
|
+
signal: "mid_flight_fixup",
|
|
48601
|
+
agentId: "orchestrator",
|
|
48602
|
+
taskId: consensusId,
|
|
48603
|
+
consensusId,
|
|
48604
|
+
metadata: {
|
|
48605
|
+
count,
|
|
48606
|
+
roundStartSha,
|
|
48607
|
+
commits
|
|
48608
|
+
},
|
|
48609
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
48610
|
+
}]);
|
|
48611
|
+
} catch {
|
|
48612
|
+
}
|
|
48613
|
+
} catch {
|
|
48614
|
+
}
|
|
48615
|
+
return { warnings };
|
|
48616
|
+
}
|
|
48617
|
+
function defaultExecFile(cmd, args, opts) {
|
|
48618
|
+
return (0, import_child_process14.execFileSync)(cmd, args, opts);
|
|
48619
|
+
}
|
|
48620
|
+
function defaultCanRead(p) {
|
|
48621
|
+
try {
|
|
48622
|
+
fs6.accessSync(p, fs6.constants.R_OK);
|
|
48623
|
+
return true;
|
|
48624
|
+
} catch {
|
|
48625
|
+
return false;
|
|
48626
|
+
}
|
|
48627
|
+
}
|
|
48628
|
+
function defaultPathExists(projectRoot, p) {
|
|
48629
|
+
try {
|
|
48630
|
+
const resolved = path7.resolve(projectRoot, p);
|
|
48631
|
+
fs6.accessSync(resolved, fs6.constants.R_OK);
|
|
48632
|
+
return true;
|
|
48633
|
+
} catch {
|
|
48634
|
+
return false;
|
|
48635
|
+
}
|
|
48636
|
+
}
|
|
48637
|
+
function defaultIsGitignoredOrUntracked(projectRoot, p, execFile6) {
|
|
48638
|
+
try {
|
|
48639
|
+
execFile6("git", ["check-ignore", "-q", p], { cwd: projectRoot, encoding: "utf8" });
|
|
48640
|
+
return true;
|
|
48641
|
+
} catch {
|
|
48642
|
+
}
|
|
48643
|
+
try {
|
|
48644
|
+
execFile6("git", ["ls-files", "--error-unmatch", p], { cwd: projectRoot, encoding: "utf8" });
|
|
48645
|
+
return false;
|
|
48646
|
+
} catch {
|
|
48647
|
+
return true;
|
|
48648
|
+
}
|
|
48649
|
+
}
|
|
48650
|
+
function defaultEmitSignals(projectRoot, signals) {
|
|
48651
|
+
try {
|
|
48652
|
+
emitPipelineSignals(projectRoot, signals);
|
|
48653
|
+
} catch {
|
|
48654
|
+
}
|
|
48655
|
+
}
|
|
48656
|
+
async function gatherStaleBaseInputs(projectRoot, execFile6 = defaultExecFile) {
|
|
48657
|
+
try {
|
|
48658
|
+
const dispatchSha = execFile6("git", ["rev-parse", "HEAD"], {
|
|
48659
|
+
cwd: projectRoot,
|
|
48660
|
+
encoding: "utf8"
|
|
48661
|
+
}).trim();
|
|
48662
|
+
const originMasterSha = execFile6("git", ["rev-parse", "origin/master"], {
|
|
48663
|
+
cwd: projectRoot,
|
|
48664
|
+
encoding: "utf8"
|
|
48665
|
+
}).trim();
|
|
48666
|
+
const mergeBaseSha = execFile6("git", ["merge-base", "HEAD", "origin/master"], {
|
|
48667
|
+
cwd: projectRoot,
|
|
48668
|
+
encoding: "utf8"
|
|
48669
|
+
}).trim();
|
|
48670
|
+
return { dispatchSha, originMasterSha, mergeBaseSha };
|
|
48671
|
+
} catch {
|
|
48672
|
+
return null;
|
|
48673
|
+
}
|
|
48674
|
+
}
|
|
48675
|
+
async function runDispatchPreconditionGuard(input, deps = {}) {
|
|
48676
|
+
const warnings = [];
|
|
48677
|
+
const execFile6 = deps.execFile ?? defaultExecFile;
|
|
48678
|
+
const canRead = deps.canRead ?? defaultCanRead;
|
|
48679
|
+
const pathExists = deps.pathExists ?? defaultPathExists;
|
|
48680
|
+
const isGitignoredOrUntracked = deps.isGitignoredOrUntracked ?? defaultIsGitignoredOrUntracked;
|
|
48681
|
+
const emitSignals = deps.emitSignals ?? defaultEmitSignals;
|
|
48682
|
+
const { projectRoot, taskId, resolutionRoots, taskText, writeMode, additionalTasks } = input;
|
|
48683
|
+
try {
|
|
48684
|
+
const gitInputs = await gatherStaleBaseInputs(projectRoot, execFile6);
|
|
48685
|
+
if (gitInputs !== null) {
|
|
48686
|
+
const staleResult = detectStaleBase(
|
|
48687
|
+
gitInputs.dispatchSha,
|
|
48688
|
+
gitInputs.originMasterSha,
|
|
48689
|
+
gitInputs.mergeBaseSha
|
|
48690
|
+
);
|
|
48691
|
+
if (staleResult.stale && staleResult.reason !== null) {
|
|
48692
|
+
const reason = staleResult.reason;
|
|
48693
|
+
warnings.push(
|
|
48694
|
+
`[dispatch-hygiene] stale base detected (${reason}): dispatch SHA ${gitInputs.dispatchSha} is behind origin/master ${gitInputs.originMasterSha}. Pull and rebase before dispatching.`
|
|
48695
|
+
);
|
|
48696
|
+
try {
|
|
48697
|
+
emitSignals(projectRoot, [{
|
|
48698
|
+
type: "pipeline",
|
|
48699
|
+
signal: "dispatched_stale_base",
|
|
48700
|
+
agentId: "orchestrator",
|
|
48701
|
+
taskId,
|
|
48702
|
+
metadata: {
|
|
48703
|
+
reason,
|
|
48704
|
+
dispatchSha: gitInputs.dispatchSha
|
|
48705
|
+
},
|
|
48706
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
48707
|
+
}]);
|
|
48708
|
+
} catch {
|
|
48709
|
+
}
|
|
48710
|
+
}
|
|
48711
|
+
}
|
|
48712
|
+
const roots = resolutionRoots ?? [];
|
|
48713
|
+
if (roots.length > 0) {
|
|
48714
|
+
let unreadable;
|
|
48715
|
+
try {
|
|
48716
|
+
unreadable = findUnreadablePaths(roots, canRead);
|
|
48717
|
+
} catch {
|
|
48718
|
+
unreadable = [];
|
|
48719
|
+
}
|
|
48720
|
+
if (unreadable.length > 0) {
|
|
48721
|
+
warnings.push(
|
|
48722
|
+
`[dispatch-hygiene] ${unreadable.length} resolutionRoot(s) are unreadable: ${unreadable.join(", ")}. Cross-reviewers will fall back to project root.`
|
|
48723
|
+
);
|
|
48724
|
+
try {
|
|
48725
|
+
emitSignals(projectRoot, [{
|
|
48726
|
+
type: "pipeline",
|
|
48727
|
+
signal: "referenced_unreadable_path",
|
|
48728
|
+
agentId: "orchestrator",
|
|
48729
|
+
taskId,
|
|
48730
|
+
metadata: {
|
|
48731
|
+
unreadable
|
|
48732
|
+
},
|
|
48733
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
48734
|
+
}]);
|
|
48735
|
+
} catch {
|
|
48736
|
+
}
|
|
48737
|
+
}
|
|
48738
|
+
}
|
|
48739
|
+
const scanTasks = [];
|
|
48740
|
+
if (taskText) {
|
|
48741
|
+
scanTasks.push({ taskText, writeMode });
|
|
48742
|
+
}
|
|
48743
|
+
if (additionalTasks) {
|
|
48744
|
+
for (const t of additionalTasks) {
|
|
48745
|
+
if (t && t.taskText) {
|
|
48746
|
+
scanTasks.push({ taskText: t.taskText, writeMode: t.writeMode });
|
|
48747
|
+
}
|
|
48748
|
+
}
|
|
48749
|
+
}
|
|
48750
|
+
if (scanTasks.length > 0) {
|
|
48751
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
48752
|
+
let droppedOverCap = 0;
|
|
48753
|
+
for (const t of scanTasks) {
|
|
48754
|
+
let result = {
|
|
48755
|
+
unreadable: [],
|
|
48756
|
+
droppedOverCap: 0
|
|
48757
|
+
};
|
|
48758
|
+
try {
|
|
48759
|
+
result = findUnreadableReferencedPathsWithMeta(t.taskText, {
|
|
48760
|
+
writeMode: t.writeMode,
|
|
48761
|
+
pathExists: (p) => {
|
|
48762
|
+
try {
|
|
48763
|
+
return pathExists(projectRoot, p);
|
|
48764
|
+
} catch {
|
|
48765
|
+
return true;
|
|
48766
|
+
}
|
|
48767
|
+
},
|
|
48768
|
+
isGitignoredOrUntracked: (p) => {
|
|
48769
|
+
try {
|
|
48770
|
+
return isGitignoredOrUntracked(projectRoot, p, execFile6);
|
|
48771
|
+
} catch {
|
|
48772
|
+
return false;
|
|
48773
|
+
}
|
|
48774
|
+
}
|
|
48775
|
+
});
|
|
48776
|
+
} catch {
|
|
48777
|
+
result = { unreadable: [], droppedOverCap: 0 };
|
|
48778
|
+
}
|
|
48779
|
+
droppedOverCap += result.droppedOverCap;
|
|
48780
|
+
for (const entry of result.unreadable) {
|
|
48781
|
+
const existing = byPath.get(entry.path);
|
|
48782
|
+
if (!existing) {
|
|
48783
|
+
byPath.set(entry.path, entry);
|
|
48784
|
+
} else if (existing.reason !== "gitignored_in_worktree" && entry.reason === "gitignored_in_worktree") {
|
|
48785
|
+
byPath.set(entry.path, entry);
|
|
48786
|
+
}
|
|
48787
|
+
}
|
|
48788
|
+
}
|
|
48789
|
+
const referenced = [...byPath.values()];
|
|
48790
|
+
if (referenced.length > 0) {
|
|
48791
|
+
const detail = referenced.map((r) => `${r.path} (${r.reason})`).join(", ");
|
|
48792
|
+
warnings.push(
|
|
48793
|
+
`[dispatch-hygiene] ${referenced.length} referenced path(s) the dispatched agent cannot read: ${detail}. The agent may fail mid-task \u2014 inline the file contents or copy it into the worktree.`
|
|
48794
|
+
);
|
|
48795
|
+
try {
|
|
48796
|
+
emitSignals(projectRoot, [{
|
|
48797
|
+
type: "pipeline",
|
|
48798
|
+
signal: "referenced_unreadable_path",
|
|
48799
|
+
agentId: "orchestrator",
|
|
48800
|
+
taskId,
|
|
48801
|
+
metadata: {
|
|
48802
|
+
referenced
|
|
48803
|
+
},
|
|
48804
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
48805
|
+
}]);
|
|
48806
|
+
} catch {
|
|
48807
|
+
}
|
|
48808
|
+
}
|
|
48809
|
+
if (droppedOverCap > 0) {
|
|
48810
|
+
warnings.push(
|
|
48811
|
+
`[dispatch-hygiene] ${droppedOverCap} referenced path(s) beyond the 20-path cap were not checked.`
|
|
48812
|
+
);
|
|
48813
|
+
}
|
|
48814
|
+
}
|
|
48815
|
+
} catch {
|
|
48816
|
+
}
|
|
48817
|
+
return { warnings };
|
|
48818
|
+
}
|
|
48819
|
+
var fs6, path7, import_child_process14;
|
|
48820
|
+
var init_orchestrator_precondition_runner = __esm({
|
|
48821
|
+
"apps/cli/src/handlers/orchestrator-precondition-runner.ts"() {
|
|
48822
|
+
"use strict";
|
|
48823
|
+
fs6 = __toESM(require("fs"));
|
|
48824
|
+
path7 = __toESM(require("path"));
|
|
48825
|
+
import_child_process14 = require("child_process");
|
|
48826
|
+
init_src4();
|
|
48827
|
+
init_src4();
|
|
48828
|
+
}
|
|
48829
|
+
});
|
|
48830
|
+
|
|
48247
48831
|
// apps/cli/src/handlers/relay-cross-review.ts
|
|
48248
48832
|
var relay_cross_review_exports = {};
|
|
48249
48833
|
__export(relay_cross_review_exports, {
|
|
@@ -48274,11 +48858,11 @@ async function synthesizeTimeoutRound(snapshot, consensusId, missingAgents, llm,
|
|
|
48274
48858
|
);
|
|
48275
48859
|
try {
|
|
48276
48860
|
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45 } = require("fs");
|
|
48277
|
-
const { join:
|
|
48278
|
-
const reportsDir =
|
|
48861
|
+
const { join: join93 } = require("path");
|
|
48862
|
+
const reportsDir = join93(projectRoot, ".gossip", "consensus-reports");
|
|
48279
48863
|
mkdirSync45(reportsDir, { recursive: true });
|
|
48280
48864
|
const topic = snapshot.allResults?.find((r) => r.task)?.task?.slice(0, 500) || "";
|
|
48281
|
-
writeFileSync38(
|
|
48865
|
+
writeFileSync38(join93(reportsDir, `${consensusId}.json`), JSON.stringify({
|
|
48282
48866
|
id: consensusId,
|
|
48283
48867
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
48284
48868
|
topic,
|
|
@@ -48313,6 +48897,7 @@ function startConsensusTimeout(consensusId) {
|
|
|
48313
48897
|
return;
|
|
48314
48898
|
}
|
|
48315
48899
|
const missingAgents = [...current.pendingNativeAgents];
|
|
48900
|
+
const roundStartShaForMidFlight = current.roundStartSha;
|
|
48316
48901
|
const snapshot = { allResults: current.allResults, relayCrossReviewEntries: current.relayCrossReviewEntries, relayCrossReviewSkipped: current.relayCrossReviewSkipped, nativeCrossReviewEntries: [...current.nativeCrossReviewEntries], resolutionRoots: current.resolutionRoots, roundContext: current.roundContext };
|
|
48317
48902
|
seedRecentConsensusAgentIds(Array.from(current.participatingNativeAgents), RECENT_CONSENSUS_TASK_TTL_MS);
|
|
48318
48903
|
ctx.pendingConsensusRounds.delete(consensusId);
|
|
@@ -48342,6 +48927,18 @@ function startConsensusTimeout(consensusId) {
|
|
|
48342
48927
|
const { report } = await synthesizeTimeoutRound(snapshot, consensusId, missingAgents, timeoutLlm);
|
|
48343
48928
|
process.stderr.write(`[gossipcat] \u{1F52E} Timeout synthesis complete: ${report.confirmed.length} confirmed, ${report.disputed.length} disputed
|
|
48344
48929
|
`);
|
|
48930
|
+
try {
|
|
48931
|
+
const midFlightResult = await runMidFlightCheck({
|
|
48932
|
+
projectRoot: process.cwd(),
|
|
48933
|
+
consensusId,
|
|
48934
|
+
roundStartSha: roundStartShaForMidFlight
|
|
48935
|
+
});
|
|
48936
|
+
for (const warn of midFlightResult.warnings) {
|
|
48937
|
+
process.stderr.write(`[gossipcat] ${warn}
|
|
48938
|
+
`);
|
|
48939
|
+
}
|
|
48940
|
+
} catch {
|
|
48941
|
+
}
|
|
48345
48942
|
} catch (err) {
|
|
48346
48943
|
process.stderr.write(`[gossipcat] \u274C Timeout synthesis failed: ${err.message}
|
|
48347
48944
|
`);
|
|
@@ -48452,6 +49049,7 @@ async function handleRelayCrossReview(consensus_id, agent_id, result) {
|
|
|
48452
49049
|
}]
|
|
48453
49050
|
};
|
|
48454
49051
|
}
|
|
49052
|
+
const completionRoundStartSha = round.roundStartSha;
|
|
48455
49053
|
const synthSnapshot = {
|
|
48456
49054
|
allResults: round.allResults,
|
|
48457
49055
|
relayCrossReviewEntries: round.relayCrossReviewEntries,
|
|
@@ -48497,10 +49095,10 @@ async function handleRelayCrossReview(consensus_id, agent_id, result) {
|
|
|
48497
49095
|
);
|
|
48498
49096
|
try {
|
|
48499
49097
|
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45 } = require("fs");
|
|
48500
|
-
const { join:
|
|
48501
|
-
const reportsDir =
|
|
49098
|
+
const { join: join93 } = require("path");
|
|
49099
|
+
const reportsDir = join93(process.cwd(), ".gossip", "consensus-reports");
|
|
48502
49100
|
mkdirSync45(reportsDir, { recursive: true });
|
|
48503
|
-
const reportPath =
|
|
49101
|
+
const reportPath = join93(reportsDir, `${consensus_id}.json`);
|
|
48504
49102
|
const topic = synthSnapshot.allResults?.find((r) => r.task)?.task?.slice(0, 500) || "";
|
|
48505
49103
|
writeFileSync38(reportPath, JSON.stringify({
|
|
48506
49104
|
id: consensus_id,
|
|
@@ -48527,6 +49125,18 @@ async function handleRelayCrossReview(consensus_id, agent_id, result) {
|
|
|
48527
49125
|
}
|
|
48528
49126
|
} catch {
|
|
48529
49127
|
}
|
|
49128
|
+
try {
|
|
49129
|
+
const midFlightResult = await runMidFlightCheck({
|
|
49130
|
+
projectRoot: process.cwd(),
|
|
49131
|
+
consensusId: synthSnapshot.consensusId,
|
|
49132
|
+
roundStartSha: completionRoundStartSha
|
|
49133
|
+
});
|
|
49134
|
+
for (const warn of midFlightResult.warnings) {
|
|
49135
|
+
process.stderr.write(`[gossipcat] ${warn}
|
|
49136
|
+
`);
|
|
49137
|
+
}
|
|
49138
|
+
} catch {
|
|
49139
|
+
}
|
|
48530
49140
|
return {
|
|
48531
49141
|
content: [{
|
|
48532
49142
|
type: "text",
|
|
@@ -48600,8 +49210,8 @@ function persistPendingConsensus() {
|
|
|
48600
49210
|
const projectRoot = ctx.mainAgent?.projectRoot;
|
|
48601
49211
|
if (!projectRoot) return;
|
|
48602
49212
|
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45 } = require("fs");
|
|
48603
|
-
const { join:
|
|
48604
|
-
const dir =
|
|
49213
|
+
const { join: join93 } = require("path");
|
|
49214
|
+
const dir = join93(projectRoot, ".gossip");
|
|
48605
49215
|
mkdirSync45(dir, { recursive: true });
|
|
48606
49216
|
const rounds = {};
|
|
48607
49217
|
for (const [id, round] of ctx.pendingConsensusRounds) {
|
|
@@ -48636,7 +49246,7 @@ function persistPendingConsensus() {
|
|
|
48636
49246
|
} : void 0
|
|
48637
49247
|
};
|
|
48638
49248
|
}
|
|
48639
|
-
writeFileSync38(
|
|
49249
|
+
writeFileSync38(join93(dir, CONSENSUS_FILE), JSON.stringify(rounds));
|
|
48640
49250
|
} catch (err) {
|
|
48641
49251
|
process.stderr.write(`[gossipcat] persistPendingConsensus failed: ${err.message}
|
|
48642
49252
|
`);
|
|
@@ -48644,11 +49254,11 @@ function persistPendingConsensus() {
|
|
|
48644
49254
|
}
|
|
48645
49255
|
function restorePendingConsensus(projectRoot) {
|
|
48646
49256
|
try {
|
|
48647
|
-
const { existsSync:
|
|
48648
|
-
const { join:
|
|
48649
|
-
const filePath =
|
|
48650
|
-
if (!
|
|
48651
|
-
const raw = JSON.parse(
|
|
49257
|
+
const { existsSync: existsSync74, readFileSync: readFileSync70, unlinkSync: unlinkSync16 } = require("fs");
|
|
49258
|
+
const { join: join93 } = require("path");
|
|
49259
|
+
const filePath = join93(projectRoot, ".gossip", CONSENSUS_FILE);
|
|
49260
|
+
if (!existsSync74(filePath)) return;
|
|
49261
|
+
const raw = JSON.parse(readFileSync70(filePath, "utf-8"));
|
|
48652
49262
|
const now = Date.now();
|
|
48653
49263
|
for (const [id, data] of Object.entries(raw)) {
|
|
48654
49264
|
if (now > data.deadline + 3e5) {
|
|
@@ -48674,6 +49284,8 @@ function restorePendingConsensus(projectRoot) {
|
|
|
48674
49284
|
createdAt: data.createdAt,
|
|
48675
49285
|
nativePrompts: data.nativePrompts || [],
|
|
48676
49286
|
resolutionRoots: Array.isArray(data.resolutionRoots) && data.resolutionRoots.length > 0 ? data.resolutionRoots : void 0,
|
|
49287
|
+
// UNIT 3: restore roundStartSha from persisted data (back-compat: undefined for old rounds).
|
|
49288
|
+
roundStartSha: typeof data.roundStartSha === "string" ? data.roundStartSha : void 0,
|
|
48677
49289
|
// Spec §3.2 disk back-compat: prefer the embedded roundContext; fall
|
|
48678
49290
|
// back per-field to the old flat shape (mirrors the
|
|
48679
49291
|
// participatingNativeAgents back-compat pattern above). Old pre-PR-A
|
|
@@ -48695,6 +49307,7 @@ var init_relay_cross_review = __esm({
|
|
|
48695
49307
|
"use strict";
|
|
48696
49308
|
init_mcp_context();
|
|
48697
49309
|
init_native_tasks();
|
|
49310
|
+
init_orchestrator_precondition_runner();
|
|
48698
49311
|
CONSENSUS_FILE = "pending-consensus.json";
|
|
48699
49312
|
}
|
|
48700
49313
|
});
|
|
@@ -48779,10 +49392,10 @@ function taskWasInConsensusRound(taskId, agentId, rounds, recentTaskIds, recentA
|
|
|
48779
49392
|
function appendRelayWarning(projectRoot, entry) {
|
|
48780
49393
|
try {
|
|
48781
49394
|
const { appendFileSync: appendFileSync22, mkdirSync: mkdirSync45 } = require("fs");
|
|
48782
|
-
const { join:
|
|
48783
|
-
const dir =
|
|
49395
|
+
const { join: join93 } = require("path");
|
|
49396
|
+
const dir = join93(projectRoot, ".gossip");
|
|
48784
49397
|
mkdirSync45(dir, { recursive: true });
|
|
48785
|
-
appendFileSync22(
|
|
49398
|
+
appendFileSync22(join93(dir, RELAY_WARNINGS_FILE), JSON.stringify(entry) + "\n", "utf8");
|
|
48786
49399
|
} catch (err) {
|
|
48787
49400
|
process.stderr.write(`[gossipcat] append relay-warning failed: ${err.message}
|
|
48788
49401
|
`);
|
|
@@ -48791,8 +49404,8 @@ function appendRelayWarning(projectRoot, entry) {
|
|
|
48791
49404
|
function checkWorktreeEngaged(startedAt, projectRoot = process.cwd()) {
|
|
48792
49405
|
try {
|
|
48793
49406
|
const { readdirSync: readdirSync22, statSync: statSync36 } = require("fs");
|
|
48794
|
-
const { join:
|
|
48795
|
-
const wtDir =
|
|
49407
|
+
const { join: join93 } = require("path");
|
|
49408
|
+
const wtDir = join93(projectRoot, ".claude", "worktrees");
|
|
48796
49409
|
let entries;
|
|
48797
49410
|
try {
|
|
48798
49411
|
entries = readdirSync22(wtDir);
|
|
@@ -48803,7 +49416,7 @@ function checkWorktreeEngaged(startedAt, projectRoot = process.cwd()) {
|
|
|
48803
49416
|
for (const entry of entries) {
|
|
48804
49417
|
if (!entry.startsWith("agent-")) continue;
|
|
48805
49418
|
try {
|
|
48806
|
-
const st = statSync36(
|
|
49419
|
+
const st = statSync36(join93(wtDir, entry));
|
|
48807
49420
|
if (st.isDirectory() && st.mtimeMs >= startedAt - 2e3) return true;
|
|
48808
49421
|
} catch {
|
|
48809
49422
|
}
|
|
@@ -49684,7 +50297,7 @@ function computeSkillFingerprint(paths) {
|
|
|
49684
50297
|
const pairs = [];
|
|
49685
50298
|
for (const p of paths) {
|
|
49686
50299
|
try {
|
|
49687
|
-
const st = (0,
|
|
50300
|
+
const st = (0, import_fs78.statSync)(p);
|
|
49688
50301
|
pairs.push(`${p}:${st.mtimeMs}`);
|
|
49689
50302
|
} catch {
|
|
49690
50303
|
}
|
|
@@ -49719,7 +50332,7 @@ function setCachedPrompt(k, e) {
|
|
|
49719
50332
|
const evicted = promptCache.get(oldestKey);
|
|
49720
50333
|
promptCache.delete(oldestKey);
|
|
49721
50334
|
try {
|
|
49722
|
-
(0,
|
|
50335
|
+
(0, import_fs78.unlinkSync)(evicted.skillsSectionPath);
|
|
49723
50336
|
} catch {
|
|
49724
50337
|
}
|
|
49725
50338
|
const evictedAgentId = oldestKey.split("|")[0] ?? "_system";
|
|
@@ -49733,7 +50346,7 @@ function invalidateAgent(agentId) {
|
|
|
49733
50346
|
if (k.startsWith(`${agentId}|`)) {
|
|
49734
50347
|
promptCache.delete(k);
|
|
49735
50348
|
try {
|
|
49736
|
-
(0,
|
|
50349
|
+
(0, import_fs78.unlinkSync)(v.skillsSectionPath);
|
|
49737
50350
|
} catch {
|
|
49738
50351
|
}
|
|
49739
50352
|
emitCacheEvictedSignal(agentId, "invalidation");
|
|
@@ -49746,7 +50359,7 @@ function invalidateAll() {
|
|
|
49746
50359
|
const n = promptCache.size;
|
|
49747
50360
|
for (const v of promptCache.values()) {
|
|
49748
50361
|
try {
|
|
49749
|
-
(0,
|
|
50362
|
+
(0, import_fs78.unlinkSync)(v.skillsSectionPath);
|
|
49750
50363
|
} catch {
|
|
49751
50364
|
}
|
|
49752
50365
|
}
|
|
@@ -49793,29 +50406,29 @@ function writeCachedSkillsSection(projectRoot, fingerprint2, skillsSection) {
|
|
|
49793
50406
|
if (!/^[a-f0-9]{64}$/.test(fingerprint2)) {
|
|
49794
50407
|
throw new Error(`writeCachedSkillsSection: invalid fingerprint ${JSON.stringify(fingerprint2).slice(0, 32)}`);
|
|
49795
50408
|
}
|
|
49796
|
-
const dir = (0,
|
|
49797
|
-
(0,
|
|
49798
|
-
const finalPath = (0,
|
|
49799
|
-
const tmpPath = (0,
|
|
50409
|
+
const dir = (0, import_path85.join)(projectRoot, ".gossip", "dispatch-prompts", "cache");
|
|
50410
|
+
(0, import_fs78.mkdirSync)(dir, { recursive: true });
|
|
50411
|
+
const finalPath = (0, import_path85.join)(dir, `skills-${fingerprint2}.txt`);
|
|
50412
|
+
const tmpPath = (0, import_path85.join)(dir, `skills-${fingerprint2}.txt.${(0, import_crypto33.randomUUID)().slice(0, 8)}.tmp`);
|
|
49800
50413
|
try {
|
|
49801
|
-
(0,
|
|
49802
|
-
(0,
|
|
50414
|
+
(0, import_fs78.writeFileSync)(tmpPath, skillsSection, "utf8");
|
|
50415
|
+
(0, import_fs78.renameSync)(tmpPath, finalPath);
|
|
49803
50416
|
} catch (err) {
|
|
49804
50417
|
try {
|
|
49805
|
-
(0,
|
|
50418
|
+
(0, import_fs78.unlinkSync)(tmpPath);
|
|
49806
50419
|
} catch {
|
|
49807
50420
|
}
|
|
49808
50421
|
throw err;
|
|
49809
50422
|
}
|
|
49810
|
-
return (0,
|
|
50423
|
+
return (0, import_path85.resolve)(finalPath);
|
|
49811
50424
|
}
|
|
49812
|
-
var import_crypto32,
|
|
50425
|
+
var import_crypto32, import_fs78, import_path85, import_crypto33, DISPATCH_PROMPT_CACHE_MAX_ENTRIES, promptCache;
|
|
49813
50426
|
var init_dispatch_prompt_cache = __esm({
|
|
49814
50427
|
"apps/cli/src/handlers/dispatch-prompt-cache.ts"() {
|
|
49815
50428
|
"use strict";
|
|
49816
50429
|
import_crypto32 = require("crypto");
|
|
49817
|
-
|
|
49818
|
-
|
|
50430
|
+
import_fs78 = require("fs");
|
|
50431
|
+
import_path85 = require("path");
|
|
49819
50432
|
import_crypto33 = require("crypto");
|
|
49820
50433
|
DISPATCH_PROMPT_CACHE_MAX_ENTRIES = 64;
|
|
49821
50434
|
promptCache = /* @__PURE__ */ new Map();
|
|
@@ -49842,7 +50455,7 @@ function drainLifecycleTasks(maxMs = 8e3) {
|
|
|
49842
50455
|
const snapshot = [...inFlight];
|
|
49843
50456
|
return Promise.race([
|
|
49844
50457
|
Promise.allSettled(snapshot).then(() => void 0),
|
|
49845
|
-
new Promise((
|
|
50458
|
+
new Promise((resolve33) => setTimeout(resolve33, maxMs).unref?.())
|
|
49846
50459
|
]).then(() => void 0);
|
|
49847
50460
|
}
|
|
49848
50461
|
function installLifecycleDrainHandlers() {
|
|
@@ -49885,31 +50498,31 @@ __export(check_effectiveness_runner_exports, {
|
|
|
49885
50498
|
runCheckEffectivenessForAllSkills: () => runCheckEffectivenessForAllSkills
|
|
49886
50499
|
});
|
|
49887
50500
|
function writeHealthAtomic(projectRoot, record2) {
|
|
49888
|
-
const dir = (0,
|
|
49889
|
-
const finalPath = (0,
|
|
50501
|
+
const dir = (0, import_path88.join)(projectRoot, ".gossip");
|
|
50502
|
+
const finalPath = (0, import_path88.join)(dir, "skill-runner-health.json");
|
|
49890
50503
|
const tmpPath = finalPath + ".tmp";
|
|
49891
50504
|
try {
|
|
49892
|
-
(0,
|
|
49893
|
-
(0,
|
|
49894
|
-
(0,
|
|
50505
|
+
(0, import_fs82.mkdirSync)(dir, { recursive: true });
|
|
50506
|
+
(0, import_fs82.writeFileSync)(tmpPath, JSON.stringify(record2, null, 2));
|
|
50507
|
+
(0, import_fs82.renameSync)(tmpPath, finalPath);
|
|
49895
50508
|
} catch (e) {
|
|
49896
50509
|
process.stderr.write(`[gossipcat] checkEffectiveness: health write failed: ${e.message}
|
|
49897
50510
|
`);
|
|
49898
50511
|
try {
|
|
49899
|
-
if ((0,
|
|
50512
|
+
if ((0, import_fs82.existsSync)(tmpPath)) (0, import_fs82.unlinkSync)(tmpPath);
|
|
49900
50513
|
} catch {
|
|
49901
50514
|
}
|
|
49902
50515
|
}
|
|
49903
50516
|
}
|
|
49904
50517
|
async function runCheckEffectivenessForAllSkills(opts) {
|
|
49905
50518
|
const startedAt = Date.now();
|
|
49906
|
-
const baseDir = (0,
|
|
50519
|
+
const baseDir = (0, import_path88.join)(opts.projectRoot, ".gossip", "agents");
|
|
49907
50520
|
let agentDirs = [];
|
|
49908
50521
|
let canonicalBaseDir;
|
|
49909
|
-
if ((0,
|
|
50522
|
+
if ((0, import_fs82.existsSync)(baseDir)) {
|
|
49910
50523
|
try {
|
|
49911
|
-
canonicalBaseDir = (0,
|
|
49912
|
-
agentDirs = (0,
|
|
50524
|
+
canonicalBaseDir = (0, import_fs82.realpathSync)(baseDir);
|
|
50525
|
+
agentDirs = (0, import_fs82.readdirSync)(canonicalBaseDir);
|
|
49913
50526
|
} catch {
|
|
49914
50527
|
}
|
|
49915
50528
|
}
|
|
@@ -49928,11 +50541,11 @@ async function runCheckEffectivenessForAllSkills(opts) {
|
|
|
49928
50541
|
for (const agentId of agentDirs) {
|
|
49929
50542
|
if (agentId.startsWith("_")) continue;
|
|
49930
50543
|
if (!SAFE_NAME2.test(agentId)) continue;
|
|
49931
|
-
const skillsDir = (0,
|
|
49932
|
-
if (!(0,
|
|
50544
|
+
const skillsDir = (0, import_path88.join)(canonicalBaseDir, agentId, "skills");
|
|
50545
|
+
if (!(0, import_fs82.existsSync)(skillsDir)) continue;
|
|
49933
50546
|
let canonicalSkillsDir;
|
|
49934
50547
|
try {
|
|
49935
|
-
canonicalSkillsDir = (0,
|
|
50548
|
+
canonicalSkillsDir = (0, import_fs82.realpathSync)(skillsDir);
|
|
49936
50549
|
} catch {
|
|
49937
50550
|
continue;
|
|
49938
50551
|
}
|
|
@@ -49943,7 +50556,7 @@ async function runCheckEffectivenessForAllSkills(opts) {
|
|
|
49943
50556
|
}
|
|
49944
50557
|
const role = opts.registryGet(agentId)?.role;
|
|
49945
50558
|
if (role === "implementer") continue;
|
|
49946
|
-
const files = (0,
|
|
50559
|
+
const files = (0, import_fs82.readdirSync)(canonicalSkillsDir).filter((f) => f.endsWith(".md"));
|
|
49947
50560
|
for (const file2 of files) {
|
|
49948
50561
|
const category = file2.replace(/\.md$/, "");
|
|
49949
50562
|
if (!SAFE_NAME2.test(category)) continue;
|
|
@@ -49990,12 +50603,12 @@ async function runCheckEffectivenessForAllSkills(opts) {
|
|
|
49990
50603
|
last_error: lastError
|
|
49991
50604
|
});
|
|
49992
50605
|
}
|
|
49993
|
-
var
|
|
50606
|
+
var import_fs82, import_path88, SAFE_NAME2;
|
|
49994
50607
|
var init_check_effectiveness_runner = __esm({
|
|
49995
50608
|
"apps/cli/src/handlers/check-effectiveness-runner.ts"() {
|
|
49996
50609
|
"use strict";
|
|
49997
|
-
|
|
49998
|
-
|
|
50610
|
+
import_fs82 = require("fs");
|
|
50611
|
+
import_path88 = require("path");
|
|
49999
50612
|
init_dispatch_prompt_cache();
|
|
50000
50613
|
SAFE_NAME2 = /^(?!.*\.\.)[a-zA-Z0-9._-]+$/;
|
|
50001
50614
|
}
|
|
@@ -50008,20 +50621,20 @@ __export(skill_develop_audit_exports, {
|
|
|
50008
50621
|
});
|
|
50009
50622
|
function appendSkillDevelopAudit(entry) {
|
|
50010
50623
|
try {
|
|
50011
|
-
const gossipDir = (0,
|
|
50012
|
-
(0,
|
|
50624
|
+
const gossipDir = (0, import_path89.join)(process.cwd(), ".gossip");
|
|
50625
|
+
(0, import_fs83.mkdirSync)(gossipDir, { recursive: true });
|
|
50013
50626
|
const line = JSON.stringify(entry) + "\n";
|
|
50014
|
-
(0,
|
|
50015
|
-
(0,
|
|
50627
|
+
(0, import_fs83.appendFileSync)((0, import_path89.join)(gossipDir, AUDIT_FILE2), line);
|
|
50628
|
+
(0, import_fs83.appendFileSync)((0, import_path89.join)(gossipDir, LEGACY_FILE), line);
|
|
50016
50629
|
} catch {
|
|
50017
50630
|
}
|
|
50018
50631
|
}
|
|
50019
|
-
var
|
|
50632
|
+
var import_fs83, import_path89, AUDIT_FILE2, LEGACY_FILE;
|
|
50020
50633
|
var init_skill_develop_audit = __esm({
|
|
50021
50634
|
"apps/cli/src/handlers/skill-develop-audit.ts"() {
|
|
50022
50635
|
"use strict";
|
|
50023
|
-
|
|
50024
|
-
|
|
50636
|
+
import_fs83 = require("fs");
|
|
50637
|
+
import_path89 = require("path");
|
|
50025
50638
|
AUDIT_FILE2 = "skill-develop-audit.jsonl";
|
|
50026
50639
|
LEGACY_FILE = "forced-skill-develops.jsonl";
|
|
50027
50640
|
}
|
|
@@ -50079,14 +50692,14 @@ var keychain_exports = {};
|
|
|
50079
50692
|
__export(keychain_exports, {
|
|
50080
50693
|
Keychain: () => Keychain
|
|
50081
50694
|
});
|
|
50082
|
-
var
|
|
50695
|
+
var import_child_process15, import_os6, import_fs87, import_path93, import_crypto35, DEFAULT_SERVICE_NAME, VALID_PROVIDERS3, ENCRYPTED_FILE, ALGO, Keychain;
|
|
50083
50696
|
var init_keychain = __esm({
|
|
50084
50697
|
"apps/cli/src/keychain.ts"() {
|
|
50085
50698
|
"use strict";
|
|
50086
|
-
|
|
50699
|
+
import_child_process15 = require("child_process");
|
|
50087
50700
|
import_os6 = require("os");
|
|
50088
|
-
|
|
50089
|
-
|
|
50701
|
+
import_fs87 = require("fs");
|
|
50702
|
+
import_path93 = require("path");
|
|
50090
50703
|
import_crypto35 = require("crypto");
|
|
50091
50704
|
DEFAULT_SERVICE_NAME = "gossip-mesh";
|
|
50092
50705
|
VALID_PROVIDERS3 = /^[a-zA-Z0-9_-]{1,32}$/;
|
|
@@ -50130,10 +50743,10 @@ var init_keychain = __esm({
|
|
|
50130
50743
|
return (0, import_crypto35.pbkdf2Sync)(seed, salt, 6e5, 32, "sha256");
|
|
50131
50744
|
}
|
|
50132
50745
|
loadEncryptedFile() {
|
|
50133
|
-
const filePath = (0,
|
|
50134
|
-
if (!(0,
|
|
50746
|
+
const filePath = (0, import_path93.join)(process.cwd(), ENCRYPTED_FILE);
|
|
50747
|
+
if (!(0, import_fs87.existsSync)(filePath)) return;
|
|
50135
50748
|
try {
|
|
50136
|
-
const raw = (0,
|
|
50749
|
+
const raw = (0, import_fs87.readFileSync)(filePath);
|
|
50137
50750
|
if (raw.length < 61) return;
|
|
50138
50751
|
const salt = raw.subarray(0, 32);
|
|
50139
50752
|
const iv = raw.subarray(32, 44);
|
|
@@ -50151,9 +50764,9 @@ var init_keychain = __esm({
|
|
|
50151
50764
|
}
|
|
50152
50765
|
}
|
|
50153
50766
|
saveEncryptedFile() {
|
|
50154
|
-
const filePath = (0,
|
|
50155
|
-
const dir = (0,
|
|
50156
|
-
if (!(0,
|
|
50767
|
+
const filePath = (0, import_path93.join)(process.cwd(), ENCRYPTED_FILE);
|
|
50768
|
+
const dir = (0, import_path93.join)(process.cwd(), ".gossip");
|
|
50769
|
+
if (!(0, import_fs87.existsSync)(dir)) (0, import_fs87.mkdirSync)(dir, { recursive: true });
|
|
50157
50770
|
const data = JSON.stringify(Object.fromEntries(this.inMemoryStore));
|
|
50158
50771
|
const salt = (0, import_crypto35.randomBytes)(32);
|
|
50159
50772
|
const iv = (0, import_crypto35.randomBytes)(12);
|
|
@@ -50161,12 +50774,12 @@ var init_keychain = __esm({
|
|
|
50161
50774
|
const cipher = (0, import_crypto35.createCipheriv)(ALGO, key, iv);
|
|
50162
50775
|
const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
|
|
50163
50776
|
const tag = cipher.getAuthTag();
|
|
50164
|
-
(0,
|
|
50777
|
+
(0, import_fs87.writeFileSync)(filePath, Buffer.concat([salt, iv, tag, encrypted]), { mode: 384 });
|
|
50165
50778
|
}
|
|
50166
50779
|
isKeychainAvailable() {
|
|
50167
50780
|
if ((0, import_os6.platform)() === "darwin") {
|
|
50168
50781
|
try {
|
|
50169
|
-
(0,
|
|
50782
|
+
(0, import_child_process15.execFileSync)("security", ["help"], { stdio: "pipe" });
|
|
50170
50783
|
return true;
|
|
50171
50784
|
} catch {
|
|
50172
50785
|
return false;
|
|
@@ -50174,7 +50787,7 @@ var init_keychain = __esm({
|
|
|
50174
50787
|
}
|
|
50175
50788
|
if ((0, import_os6.platform)() === "linux") {
|
|
50176
50789
|
try {
|
|
50177
|
-
(0,
|
|
50790
|
+
(0, import_child_process15.execFileSync)("which", ["secret-tool"], { stdio: "pipe" });
|
|
50178
50791
|
return true;
|
|
50179
50792
|
} catch {
|
|
50180
50793
|
return false;
|
|
@@ -50190,7 +50803,7 @@ var init_keychain = __esm({
|
|
|
50190
50803
|
readFromKeychain(provider) {
|
|
50191
50804
|
this.validateProvider(provider);
|
|
50192
50805
|
if ((0, import_os6.platform)() === "darwin") {
|
|
50193
|
-
return (0,
|
|
50806
|
+
return (0, import_child_process15.execFileSync)("security", [
|
|
50194
50807
|
"find-generic-password",
|
|
50195
50808
|
"-s",
|
|
50196
50809
|
this.serviceName,
|
|
@@ -50200,7 +50813,7 @@ var init_keychain = __esm({
|
|
|
50200
50813
|
], { stdio: "pipe" }).toString().trim();
|
|
50201
50814
|
}
|
|
50202
50815
|
if ((0, import_os6.platform)() === "linux") {
|
|
50203
|
-
return (0,
|
|
50816
|
+
return (0, import_child_process15.execFileSync)("secret-tool", [
|
|
50204
50817
|
"lookup",
|
|
50205
50818
|
"service",
|
|
50206
50819
|
this.serviceName,
|
|
@@ -50214,7 +50827,7 @@ var init_keychain = __esm({
|
|
|
50214
50827
|
this.validateProvider(provider);
|
|
50215
50828
|
if ((0, import_os6.platform)() === "darwin") {
|
|
50216
50829
|
try {
|
|
50217
|
-
(0,
|
|
50830
|
+
(0, import_child_process15.execFileSync)("security", [
|
|
50218
50831
|
"delete-generic-password",
|
|
50219
50832
|
"-s",
|
|
50220
50833
|
this.serviceName,
|
|
@@ -50223,7 +50836,7 @@ var init_keychain = __esm({
|
|
|
50223
50836
|
], { stdio: "pipe" });
|
|
50224
50837
|
} catch {
|
|
50225
50838
|
}
|
|
50226
|
-
(0,
|
|
50839
|
+
(0, import_child_process15.execFileSync)("security", [
|
|
50227
50840
|
"add-generic-password",
|
|
50228
50841
|
"-s",
|
|
50229
50842
|
this.serviceName,
|
|
@@ -50235,7 +50848,7 @@ var init_keychain = __esm({
|
|
|
50235
50848
|
return;
|
|
50236
50849
|
}
|
|
50237
50850
|
if ((0, import_os6.platform)() === "linux") {
|
|
50238
|
-
(0,
|
|
50851
|
+
(0, import_child_process15.execFileSync)("secret-tool", [
|
|
50239
50852
|
"store",
|
|
50240
50853
|
"--label",
|
|
50241
50854
|
`Gossip Mesh ${provider}`,
|
|
@@ -50254,12 +50867,13 @@ var init_keychain = __esm({
|
|
|
50254
50867
|
// apps/cli/src/code-launch.ts
|
|
50255
50868
|
var code_launch_exports = {};
|
|
50256
50869
|
__export(code_launch_exports, {
|
|
50870
|
+
detectServerName: () => detectServerName,
|
|
50257
50871
|
runCodeCommand: () => runCodeCommand
|
|
50258
50872
|
});
|
|
50259
50873
|
function safeReadJson(filePath) {
|
|
50260
50874
|
try {
|
|
50261
|
-
if (!(0,
|
|
50262
|
-
const raw = (0,
|
|
50875
|
+
if (!(0, import_fs88.existsSync)(filePath)) return null;
|
|
50876
|
+
const raw = (0, import_fs88.readFileSync)(filePath, "utf-8");
|
|
50263
50877
|
return JSON.parse(raw);
|
|
50264
50878
|
} catch {
|
|
50265
50879
|
return null;
|
|
@@ -50276,21 +50890,23 @@ function isGossipMcpEntry(entry) {
|
|
|
50276
50890
|
return false;
|
|
50277
50891
|
}
|
|
50278
50892
|
function detectServerName(cwd) {
|
|
50893
|
+
const cwdPath = (0, import_path94.join)(cwd, ".mcp.json");
|
|
50894
|
+
const homePath = (0, import_path94.join)((0, import_os7.homedir)(), ".claude.json");
|
|
50279
50895
|
const candidates = [
|
|
50280
|
-
[
|
|
50281
|
-
[
|
|
50896
|
+
[cwdPath, safeReadJson(cwdPath)],
|
|
50897
|
+
[homePath, safeReadJson(homePath)]
|
|
50282
50898
|
];
|
|
50283
|
-
|
|
50284
|
-
if (!data || typeof data !== "object")
|
|
50899
|
+
function extractName(data, filePath) {
|
|
50900
|
+
if (!data || typeof data !== "object") return null;
|
|
50285
50901
|
const root = data;
|
|
50286
50902
|
const mcpServers = root["mcpServers"];
|
|
50287
|
-
if (!mcpServers || typeof mcpServers !== "object")
|
|
50903
|
+
if (!mcpServers || typeof mcpServers !== "object") return null;
|
|
50288
50904
|
const servers = mcpServers;
|
|
50289
50905
|
for (const [name, entry] of Object.entries(servers)) {
|
|
50290
50906
|
if (!entry || typeof entry !== "object") continue;
|
|
50291
50907
|
if (isGossipMcpEntry(entry)) {
|
|
50292
50908
|
if (SAFE_SERVER_NAME_RE.test(name)) {
|
|
50293
|
-
return
|
|
50909
|
+
return name;
|
|
50294
50910
|
}
|
|
50295
50911
|
process.stderr.write(
|
|
50296
50912
|
`[gossipcat code] Warning: found gossipcat MCP entry in ${filePath} but server name "${name}" contains unsafe characters; falling back to "gossipcat".
|
|
@@ -50298,11 +50914,30 @@ function detectServerName(cwd) {
|
|
|
50298
50914
|
);
|
|
50299
50915
|
}
|
|
50300
50916
|
}
|
|
50917
|
+
return null;
|
|
50918
|
+
}
|
|
50919
|
+
const cwdName = extractName(candidates[0][1], cwdPath);
|
|
50920
|
+
const homeName = extractName(candidates[1][1], homePath);
|
|
50921
|
+
if (cwdName !== null) {
|
|
50922
|
+
process.stderr.write(
|
|
50923
|
+
`[gossipcat code] Using channel server "${cwdName}" from ${cwdPath} (cwd-local config \u2014 only run this in repos you trust).
|
|
50924
|
+
`
|
|
50925
|
+
);
|
|
50926
|
+
if (homeName !== null && homeName !== cwdName) {
|
|
50927
|
+
process.stderr.write(
|
|
50928
|
+
`[gossipcat code] Warning: gossipcat server name differs between ${cwdPath} ("${cwdName}") and ${homePath} ("${homeName}"); using "${cwdName}" (cwd takes precedence).
|
|
50929
|
+
`
|
|
50930
|
+
);
|
|
50931
|
+
}
|
|
50932
|
+
return [cwdName, false];
|
|
50933
|
+
}
|
|
50934
|
+
if (homeName !== null) {
|
|
50935
|
+
return [homeName, false];
|
|
50301
50936
|
}
|
|
50302
50937
|
return ["gossipcat", true];
|
|
50303
50938
|
}
|
|
50304
50939
|
function isChannelAllowlisted(cwd) {
|
|
50305
|
-
const configPath = (0,
|
|
50940
|
+
const configPath = (0, import_path94.join)(cwd, ".gossip", "config.json");
|
|
50306
50941
|
try {
|
|
50307
50942
|
const data = safeReadJson(configPath);
|
|
50308
50943
|
if (!data || typeof data !== "object") return false;
|
|
@@ -50334,7 +50969,7 @@ function runCodeCommand(argv) {
|
|
|
50334
50969
|
);
|
|
50335
50970
|
claudeArgs = ["--dangerously-load-development-channels", `server:${serverName}`, ...argv];
|
|
50336
50971
|
}
|
|
50337
|
-
const child = (0,
|
|
50972
|
+
const child = (0, import_child_process16.spawn)("claude", claudeArgs, { stdio: "inherit" });
|
|
50338
50973
|
child.on("error", (err) => {
|
|
50339
50974
|
if (err.code === "ENOENT") {
|
|
50340
50975
|
process.stderr.write(
|
|
@@ -50355,14 +50990,14 @@ function runCodeCommand(argv) {
|
|
|
50355
50990
|
}
|
|
50356
50991
|
});
|
|
50357
50992
|
}
|
|
50358
|
-
var
|
|
50993
|
+
var import_fs88, import_path94, import_os7, import_child_process16, SAFE_SERVER_NAME_RE;
|
|
50359
50994
|
var init_code_launch = __esm({
|
|
50360
50995
|
"apps/cli/src/code-launch.ts"() {
|
|
50361
50996
|
"use strict";
|
|
50362
|
-
|
|
50363
|
-
|
|
50997
|
+
import_fs88 = require("fs");
|
|
50998
|
+
import_path94 = require("path");
|
|
50364
50999
|
import_os7 = require("os");
|
|
50365
|
-
|
|
51000
|
+
import_child_process16 = require("child_process");
|
|
50366
51001
|
SAFE_SERVER_NAME_RE = /^[a-zA-Z0-9._-]{1,64}$/;
|
|
50367
51002
|
}
|
|
50368
51003
|
});
|
|
@@ -50377,23 +51012,23 @@ __export(identity_exports, {
|
|
|
50377
51012
|
normalizeGitUrl: () => normalizeGitUrl
|
|
50378
51013
|
});
|
|
50379
51014
|
function getOrCreateSalt(projectRoot) {
|
|
50380
|
-
const saltPath = (0,
|
|
51015
|
+
const saltPath = (0, import_path95.join)(projectRoot, ".gossip", "local-salt");
|
|
50381
51016
|
try {
|
|
50382
|
-
return (0,
|
|
51017
|
+
return (0, import_fs89.readFileSync)(saltPath, "utf-8").trim();
|
|
50383
51018
|
} catch {
|
|
50384
51019
|
const salt = (0, import_crypto36.randomBytes)(16).toString("hex");
|
|
50385
|
-
(0,
|
|
51020
|
+
(0, import_fs89.mkdirSync)((0, import_path95.join)(projectRoot, ".gossip"), { recursive: true });
|
|
50386
51021
|
try {
|
|
50387
|
-
(0,
|
|
51022
|
+
(0, import_fs89.writeFileSync)(saltPath, salt, { flag: "wx" });
|
|
50388
51023
|
return salt;
|
|
50389
51024
|
} catch {
|
|
50390
|
-
return (0,
|
|
51025
|
+
return (0, import_fs89.readFileSync)(saltPath, "utf-8").trim();
|
|
50391
51026
|
}
|
|
50392
51027
|
}
|
|
50393
51028
|
}
|
|
50394
51029
|
function getUserId(projectRoot) {
|
|
50395
51030
|
try {
|
|
50396
|
-
const email3 = (0,
|
|
51031
|
+
const email3 = (0, import_child_process17.execFileSync)("git", ["config", "user.email"], { stdio: "pipe" }).toString().trim();
|
|
50397
51032
|
const salt = getOrCreateSalt(projectRoot);
|
|
50398
51033
|
return (0, import_crypto36.createHash)("sha256").update(email3 + projectRoot + salt).digest("hex").slice(0, 16);
|
|
50399
51034
|
} catch {
|
|
@@ -50416,7 +51051,7 @@ function getTeamUserId(email3, teamSalt) {
|
|
|
50416
51051
|
}
|
|
50417
51052
|
function getGitEmail() {
|
|
50418
51053
|
try {
|
|
50419
|
-
const email3 = (0,
|
|
51054
|
+
const email3 = (0, import_child_process17.execFileSync)("git", ["config", "user.email"], { stdio: "pipe" }).toString().trim();
|
|
50420
51055
|
return email3 || null;
|
|
50421
51056
|
} catch {
|
|
50422
51057
|
return null;
|
|
@@ -50424,7 +51059,7 @@ function getGitEmail() {
|
|
|
50424
51059
|
}
|
|
50425
51060
|
function getProjectId(projectRoot) {
|
|
50426
51061
|
try {
|
|
50427
|
-
const remoteUrl = (0,
|
|
51062
|
+
const remoteUrl = (0, import_child_process17.execFileSync)(
|
|
50428
51063
|
"git",
|
|
50429
51064
|
["config", "--get", "remote.origin.url"],
|
|
50430
51065
|
{ cwd: projectRoot, stdio: "pipe" }
|
|
@@ -50437,14 +51072,14 @@ function getProjectId(projectRoot) {
|
|
|
50437
51072
|
}
|
|
50438
51073
|
return (0, import_crypto36.createHash)("sha256").update(projectRoot).digest("hex").slice(0, 16);
|
|
50439
51074
|
}
|
|
50440
|
-
var
|
|
51075
|
+
var import_fs89, import_path95, import_crypto36, import_child_process17;
|
|
50441
51076
|
var init_identity = __esm({
|
|
50442
51077
|
"apps/cli/src/identity.ts"() {
|
|
50443
51078
|
"use strict";
|
|
50444
|
-
|
|
50445
|
-
|
|
51079
|
+
import_fs89 = require("fs");
|
|
51080
|
+
import_path95 = require("path");
|
|
50446
51081
|
import_crypto36 = require("crypto");
|
|
50447
|
-
|
|
51082
|
+
import_child_process17 = require("child_process");
|
|
50448
51083
|
}
|
|
50449
51084
|
});
|
|
50450
51085
|
|
|
@@ -50511,9 +51146,9 @@ async function getLatestVersion() {
|
|
|
50511
51146
|
return data.version;
|
|
50512
51147
|
}
|
|
50513
51148
|
function detectInstallMethod() {
|
|
50514
|
-
const packageRoot = (0,
|
|
51149
|
+
const packageRoot = (0, import_path96.resolve)(__dirname, "..", "..", "..", "..");
|
|
50515
51150
|
if (process.env.npm_config_global === "true") return "global";
|
|
50516
|
-
if ((0,
|
|
51151
|
+
if ((0, import_fs90.existsSync)((0, import_path96.join)(packageRoot, ".git"))) return "git-clone";
|
|
50517
51152
|
return "local";
|
|
50518
51153
|
}
|
|
50519
51154
|
function updateCommand(method, version2) {
|
|
@@ -50566,9 +51201,9 @@ Check your internet connection or visit https://www.npmjs.com/package/gossipcat
|
|
|
50566
51201
|
if (/^GOSSIPCAT_/i.test(key)) delete scrubbedEnv[key];
|
|
50567
51202
|
}
|
|
50568
51203
|
try {
|
|
50569
|
-
(0,
|
|
51204
|
+
(0, import_child_process18.execSync)(command, {
|
|
50570
51205
|
stdio: "inherit",
|
|
50571
|
-
cwd: method === "git-clone" ? (0,
|
|
51206
|
+
cwd: method === "git-clone" ? (0, import_path96.resolve)(__dirname, "..", "..", "..", "..") : process.cwd(),
|
|
50572
51207
|
env: scrubbedEnv
|
|
50573
51208
|
});
|
|
50574
51209
|
} catch (err) {
|
|
@@ -50591,13 +51226,13 @@ Run /mcp reconnect in Claude Code to load the new version.`
|
|
|
50591
51226
|
}]
|
|
50592
51227
|
};
|
|
50593
51228
|
}
|
|
50594
|
-
var
|
|
51229
|
+
var import_child_process18, import_fs90, import_path96;
|
|
50595
51230
|
var init_gossip_update = __esm({
|
|
50596
51231
|
"apps/cli/src/handlers/gossip-update.ts"() {
|
|
50597
51232
|
"use strict";
|
|
50598
|
-
|
|
50599
|
-
|
|
50600
|
-
|
|
51233
|
+
import_child_process18 = require("child_process");
|
|
51234
|
+
import_fs90 = require("fs");
|
|
51235
|
+
import_path96 = require("path");
|
|
50601
51236
|
init_version();
|
|
50602
51237
|
}
|
|
50603
51238
|
});
|
|
@@ -50810,8 +51445,8 @@ __export(mcp_server_sdk_exports, {
|
|
|
50810
51445
|
resolveHookAction: () => resolveHookAction
|
|
50811
51446
|
});
|
|
50812
51447
|
module.exports = __toCommonJS(mcp_server_sdk_exports);
|
|
50813
|
-
var
|
|
50814
|
-
var
|
|
51448
|
+
var import_fs91 = require("fs");
|
|
51449
|
+
var import_path97 = require("path");
|
|
50815
51450
|
|
|
50816
51451
|
// apps/cli/src/hook-run.ts
|
|
50817
51452
|
var import_fs = require("fs");
|
|
@@ -50894,10 +51529,10 @@ var RELAY_PORT_FILE = "relay.port";
|
|
|
50894
51529
|
var AUTH_MAX_READ = 64 * 1024;
|
|
50895
51530
|
var CURL_MAX_TIME = "2";
|
|
50896
51531
|
function readDashboardKey(cwd) {
|
|
50897
|
-
const
|
|
51532
|
+
const path8 = (0, import_path2.join)(cwd, ".gossip", AUTH_FILE_NAME);
|
|
50898
51533
|
let fd = null;
|
|
50899
51534
|
try {
|
|
50900
|
-
fd = (0, import_fs2.openSync)(
|
|
51535
|
+
fd = (0, import_fs2.openSync)(path8, "r");
|
|
50901
51536
|
const st = (0, import_fs2.fstatSync)(fd);
|
|
50902
51537
|
if (!st.isFile()) return null;
|
|
50903
51538
|
if ((st.mode & 63) !== 0) return null;
|
|
@@ -50994,7 +51629,7 @@ function resolveCwd(payloadCwd) {
|
|
|
50994
51629
|
return process.cwd();
|
|
50995
51630
|
}
|
|
50996
51631
|
function readStdin() {
|
|
50997
|
-
return new Promise((
|
|
51632
|
+
return new Promise((resolve33) => {
|
|
50998
51633
|
let data = "";
|
|
50999
51634
|
try {
|
|
51000
51635
|
const stdin = process.stdin;
|
|
@@ -51002,11 +51637,11 @@ function readStdin() {
|
|
|
51002
51637
|
stdin.on("data", (chunk) => {
|
|
51003
51638
|
data += chunk;
|
|
51004
51639
|
});
|
|
51005
|
-
stdin.on("end", () =>
|
|
51006
|
-
stdin.on("error", () =>
|
|
51007
|
-
if (stdin.isTTY)
|
|
51640
|
+
stdin.on("end", () => resolve33(data));
|
|
51641
|
+
stdin.on("error", () => resolve33(data));
|
|
51642
|
+
if (stdin.isTTY) resolve33("");
|
|
51008
51643
|
} catch {
|
|
51009
|
-
|
|
51644
|
+
resolve33("");
|
|
51010
51645
|
}
|
|
51011
51646
|
});
|
|
51012
51647
|
}
|
|
@@ -51243,9 +51878,9 @@ function getLastKnownLatest(cwd = process.cwd()) {
|
|
|
51243
51878
|
async function checkForUpgrade(cwd = process.cwd()) {
|
|
51244
51879
|
try {
|
|
51245
51880
|
if (process.env.GOSSIP_DISABLE_UPGRADE_CHECK === "1") return;
|
|
51246
|
-
const
|
|
51881
|
+
const path8 = cachePath(cwd);
|
|
51247
51882
|
try {
|
|
51248
|
-
const raw = (0, import_fs4.readFileSync)(
|
|
51883
|
+
const raw = (0, import_fs4.readFileSync)(path8, "utf8");
|
|
51249
51884
|
const data = JSON.parse(raw);
|
|
51250
51885
|
if (typeof data.checkedAt === "string") {
|
|
51251
51886
|
const checkedMs = new Date(data.checkedAt).getTime();
|
|
@@ -51262,13 +51897,13 @@ async function checkForUpgrade(cwd = process.cwd()) {
|
|
|
51262
51897
|
latestVersion: json2.version
|
|
51263
51898
|
};
|
|
51264
51899
|
try {
|
|
51265
|
-
(0, import_fs4.mkdirSync)((0, import_path3.dirname)(
|
|
51900
|
+
(0, import_fs4.mkdirSync)((0, import_path3.dirname)(path8), { recursive: true });
|
|
51266
51901
|
} catch {
|
|
51267
51902
|
}
|
|
51268
|
-
const tmp = `${
|
|
51903
|
+
const tmp = `${path8}.${process.pid}.tmp`;
|
|
51269
51904
|
(0, import_fs4.writeFileSync)(tmp, JSON.stringify(cache3), "utf8");
|
|
51270
51905
|
try {
|
|
51271
|
-
(0, import_fs4.renameSync)(tmp,
|
|
51906
|
+
(0, import_fs4.renameSync)(tmp, path8);
|
|
51272
51907
|
} catch (err) {
|
|
51273
51908
|
try {
|
|
51274
51909
|
(0, import_fs4.unlinkSync)(tmp);
|
|
@@ -51659,8 +52294,8 @@ function getErrorMap() {
|
|
|
51659
52294
|
|
|
51660
52295
|
// node_modules/zod/v3/helpers/parseUtil.js
|
|
51661
52296
|
var makeIssue = (params) => {
|
|
51662
|
-
const { data, path:
|
|
51663
|
-
const fullPath = [...
|
|
52297
|
+
const { data, path: path8, errorMaps, issueData } = params;
|
|
52298
|
+
const fullPath = [...path8, ...issueData.path || []];
|
|
51664
52299
|
const fullIssue = {
|
|
51665
52300
|
...issueData,
|
|
51666
52301
|
path: fullPath
|
|
@@ -51775,11 +52410,11 @@ var errorUtil;
|
|
|
51775
52410
|
|
|
51776
52411
|
// node_modules/zod/v3/types.js
|
|
51777
52412
|
var ParseInputLazyPath = class {
|
|
51778
|
-
constructor(parent, value,
|
|
52413
|
+
constructor(parent, value, path8, key) {
|
|
51779
52414
|
this._cachedPath = [];
|
|
51780
52415
|
this.parent = parent;
|
|
51781
52416
|
this.data = value;
|
|
51782
|
-
this._path =
|
|
52417
|
+
this._path = path8;
|
|
51783
52418
|
this._key = key;
|
|
51784
52419
|
}
|
|
51785
52420
|
get path() {
|
|
@@ -55699,10 +56334,10 @@ function mergeDefs(...defs) {
|
|
|
55699
56334
|
function cloneDef(schema) {
|
|
55700
56335
|
return mergeDefs(schema._zod.def);
|
|
55701
56336
|
}
|
|
55702
|
-
function getElementAtPath(obj,
|
|
55703
|
-
if (!
|
|
56337
|
+
function getElementAtPath(obj, path8) {
|
|
56338
|
+
if (!path8)
|
|
55704
56339
|
return obj;
|
|
55705
|
-
return
|
|
56340
|
+
return path8.reduce((acc, key) => acc?.[key], obj);
|
|
55706
56341
|
}
|
|
55707
56342
|
function promiseAllObject(promisesObj) {
|
|
55708
56343
|
const keys = Object.keys(promisesObj);
|
|
@@ -56111,11 +56746,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
56111
56746
|
}
|
|
56112
56747
|
return false;
|
|
56113
56748
|
}
|
|
56114
|
-
function prefixIssues(
|
|
56749
|
+
function prefixIssues(path8, issues) {
|
|
56115
56750
|
return issues.map((iss) => {
|
|
56116
56751
|
var _a3;
|
|
56117
56752
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
56118
|
-
iss.path.unshift(
|
|
56753
|
+
iss.path.unshift(path8);
|
|
56119
56754
|
return iss;
|
|
56120
56755
|
});
|
|
56121
56756
|
}
|
|
@@ -56262,16 +56897,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
56262
56897
|
}
|
|
56263
56898
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
56264
56899
|
const fieldErrors = { _errors: [] };
|
|
56265
|
-
const processError = (error52,
|
|
56900
|
+
const processError = (error52, path8 = []) => {
|
|
56266
56901
|
for (const issue2 of error52.issues) {
|
|
56267
56902
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
56268
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
56903
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
56269
56904
|
} else if (issue2.code === "invalid_key") {
|
|
56270
|
-
processError({ issues: issue2.issues }, [...
|
|
56905
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
56271
56906
|
} else if (issue2.code === "invalid_element") {
|
|
56272
|
-
processError({ issues: issue2.issues }, [...
|
|
56907
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
56273
56908
|
} else {
|
|
56274
|
-
const fullpath = [...
|
|
56909
|
+
const fullpath = [...path8, ...issue2.path];
|
|
56275
56910
|
if (fullpath.length === 0) {
|
|
56276
56911
|
fieldErrors._errors.push(mapper(issue2));
|
|
56277
56912
|
} else {
|
|
@@ -56298,17 +56933,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
56298
56933
|
}
|
|
56299
56934
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
56300
56935
|
const result = { errors: [] };
|
|
56301
|
-
const processError = (error52,
|
|
56936
|
+
const processError = (error52, path8 = []) => {
|
|
56302
56937
|
var _a3, _b;
|
|
56303
56938
|
for (const issue2 of error52.issues) {
|
|
56304
56939
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
56305
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
56940
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
56306
56941
|
} else if (issue2.code === "invalid_key") {
|
|
56307
|
-
processError({ issues: issue2.issues }, [...
|
|
56942
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
56308
56943
|
} else if (issue2.code === "invalid_element") {
|
|
56309
|
-
processError({ issues: issue2.issues }, [...
|
|
56944
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
56310
56945
|
} else {
|
|
56311
|
-
const fullpath = [...
|
|
56946
|
+
const fullpath = [...path8, ...issue2.path];
|
|
56312
56947
|
if (fullpath.length === 0) {
|
|
56313
56948
|
result.errors.push(mapper(issue2));
|
|
56314
56949
|
continue;
|
|
@@ -56340,8 +56975,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
56340
56975
|
}
|
|
56341
56976
|
function toDotPath(_path) {
|
|
56342
56977
|
const segs = [];
|
|
56343
|
-
const
|
|
56344
|
-
for (const seg of
|
|
56978
|
+
const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
56979
|
+
for (const seg of path8) {
|
|
56345
56980
|
if (typeof seg === "number")
|
|
56346
56981
|
segs.push(`[${seg}]`);
|
|
56347
56982
|
else if (typeof seg === "symbol")
|
|
@@ -69466,13 +70101,13 @@ function resolveRef(ref, ctx2) {
|
|
|
69466
70101
|
if (!ref.startsWith("#")) {
|
|
69467
70102
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
69468
70103
|
}
|
|
69469
|
-
const
|
|
69470
|
-
if (
|
|
70104
|
+
const path8 = ref.slice(1).split("/").filter(Boolean);
|
|
70105
|
+
if (path8.length === 0) {
|
|
69471
70106
|
return ctx2.rootSchema;
|
|
69472
70107
|
}
|
|
69473
70108
|
const defsKey = ctx2.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
69474
|
-
if (
|
|
69475
|
-
const key =
|
|
70109
|
+
if (path8[0] === defsKey) {
|
|
70110
|
+
const key = path8[1];
|
|
69476
70111
|
if (!key || !ctx2.defs[key]) {
|
|
69477
70112
|
throw new Error(`Reference not found: ${ref}`);
|
|
69478
70113
|
}
|
|
@@ -73244,7 +73879,7 @@ var Protocol = class {
|
|
|
73244
73879
|
return;
|
|
73245
73880
|
}
|
|
73246
73881
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
73247
|
-
await new Promise((
|
|
73882
|
+
await new Promise((resolve33) => setTimeout(resolve33, pollInterval));
|
|
73248
73883
|
options?.signal?.throwIfAborted();
|
|
73249
73884
|
}
|
|
73250
73885
|
} catch (error51) {
|
|
@@ -73261,7 +73896,7 @@ var Protocol = class {
|
|
|
73261
73896
|
*/
|
|
73262
73897
|
request(request, resultSchema, options) {
|
|
73263
73898
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
73264
|
-
return new Promise((
|
|
73899
|
+
return new Promise((resolve33, reject) => {
|
|
73265
73900
|
const earlyReject = (error51) => {
|
|
73266
73901
|
reject(error51);
|
|
73267
73902
|
};
|
|
@@ -73339,7 +73974,7 @@ var Protocol = class {
|
|
|
73339
73974
|
if (!parseResult.success) {
|
|
73340
73975
|
reject(parseResult.error);
|
|
73341
73976
|
} else {
|
|
73342
|
-
|
|
73977
|
+
resolve33(parseResult.data);
|
|
73343
73978
|
}
|
|
73344
73979
|
} catch (error51) {
|
|
73345
73980
|
reject(error51);
|
|
@@ -73600,12 +74235,12 @@ var Protocol = class {
|
|
|
73600
74235
|
}
|
|
73601
74236
|
} catch {
|
|
73602
74237
|
}
|
|
73603
|
-
return new Promise((
|
|
74238
|
+
return new Promise((resolve33, reject) => {
|
|
73604
74239
|
if (signal.aborted) {
|
|
73605
74240
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
73606
74241
|
return;
|
|
73607
74242
|
}
|
|
73608
|
-
const timeoutId = setTimeout(
|
|
74243
|
+
const timeoutId = setTimeout(resolve33, interval);
|
|
73609
74244
|
signal.addEventListener("abort", () => {
|
|
73610
74245
|
clearTimeout(timeoutId);
|
|
73611
74246
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -74705,7 +75340,7 @@ var McpServer = class {
|
|
|
74705
75340
|
let task = createTaskResult.task;
|
|
74706
75341
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
74707
75342
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
74708
|
-
await new Promise((
|
|
75343
|
+
await new Promise((resolve33) => setTimeout(resolve33, pollInterval));
|
|
74709
75344
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
74710
75345
|
if (!updatedTask) {
|
|
74711
75346
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -75408,12 +76043,12 @@ var StdioServerTransport = class {
|
|
|
75408
76043
|
this.onclose?.();
|
|
75409
76044
|
}
|
|
75410
76045
|
send(message) {
|
|
75411
|
-
return new Promise((
|
|
76046
|
+
return new Promise((resolve33) => {
|
|
75412
76047
|
const json2 = serializeMessage(message);
|
|
75413
76048
|
if (this._stdout.write(json2)) {
|
|
75414
|
-
|
|
76049
|
+
resolve33();
|
|
75415
76050
|
} else {
|
|
75416
|
-
this._stdout.once("drain",
|
|
76051
|
+
this._stdout.once("drain", resolve33);
|
|
75417
76052
|
}
|
|
75418
76053
|
});
|
|
75419
76054
|
}
|
|
@@ -75912,7 +76547,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
|
75912
76547
|
});
|
|
75913
76548
|
if (!chunk) {
|
|
75914
76549
|
if (i === 1) {
|
|
75915
|
-
await new Promise((
|
|
76550
|
+
await new Promise((resolve33) => setTimeout(resolve33));
|
|
75916
76551
|
maxReadCount = 3;
|
|
75917
76552
|
continue;
|
|
75918
76553
|
}
|
|
@@ -76412,9 +77047,9 @@ data:
|
|
|
76412
77047
|
const initRequest = messages.find((m) => isInitializeRequest(m));
|
|
76413
77048
|
const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
|
|
76414
77049
|
if (this._enableJsonResponse) {
|
|
76415
|
-
return new Promise((
|
|
77050
|
+
return new Promise((resolve33) => {
|
|
76416
77051
|
this._streamMapping.set(streamId, {
|
|
76417
|
-
resolveJson:
|
|
77052
|
+
resolveJson: resolve33,
|
|
76418
77053
|
cleanup: () => {
|
|
76419
77054
|
this._streamMapping.delete(streamId);
|
|
76420
77055
|
}
|
|
@@ -76799,8 +77434,8 @@ init_native_tasks();
|
|
|
76799
77434
|
|
|
76800
77435
|
// apps/cli/src/handlers/dispatch.ts
|
|
76801
77436
|
var import_crypto34 = require("crypto");
|
|
76802
|
-
var
|
|
76803
|
-
var
|
|
77437
|
+
var import_fs79 = require("fs");
|
|
77438
|
+
var import_path86 = require("path");
|
|
76804
77439
|
init_src4();
|
|
76805
77440
|
init_src3();
|
|
76806
77441
|
|
|
@@ -76934,10 +77569,11 @@ function nativeDispatchViaLabel(host = detectNativeHost()) {
|
|
|
76934
77569
|
|
|
76935
77570
|
// apps/cli/src/handlers/dispatch.ts
|
|
76936
77571
|
init_mcp_context();
|
|
77572
|
+
init_orchestrator_precondition_runner();
|
|
76937
77573
|
init_native_tasks();
|
|
76938
77574
|
init_dispatch_prompt_storage();
|
|
76939
77575
|
init_dispatch_prompt_cache();
|
|
76940
|
-
var
|
|
77576
|
+
var import_fs80 = require("fs");
|
|
76941
77577
|
|
|
76942
77578
|
// apps/cli/src/handlers/relay-tasks.ts
|
|
76943
77579
|
init_mcp_context();
|
|
@@ -77108,7 +77744,7 @@ function tryWarmCacheHit(liveTaskBlock, cacheKey2, promptFormat) {
|
|
|
77108
77744
|
const cached4 = getCachedPrompt(cacheKey2);
|
|
77109
77745
|
if (!cached4) return null;
|
|
77110
77746
|
if (cached4.skillFingerprint !== cacheKey2.skillFingerprint) return null;
|
|
77111
|
-
if (!(0,
|
|
77747
|
+
if (!(0, import_fs80.existsSync)(cached4.skillsSectionPath)) return null;
|
|
77112
77748
|
try {
|
|
77113
77749
|
const skillsSection = require("fs").readFileSync(cached4.skillsSectionPath, "utf8");
|
|
77114
77750
|
return skillsSection + liveTaskBlock;
|
|
@@ -77185,9 +77821,9 @@ function formatFalsifiedNote(block, verdicts) {
|
|
|
77185
77821
|
}
|
|
77186
77822
|
function writePremiseVerificationLog(projectRoot, taskId, result, opts) {
|
|
77187
77823
|
try {
|
|
77188
|
-
const logPath = (0,
|
|
77824
|
+
const logPath = (0, import_path86.join)(projectRoot, PREMISE_VERIFICATION_LOG);
|
|
77189
77825
|
rotateIfNeeded2(logPath, MAX_PREMISE_VERIFICATION_BYTES);
|
|
77190
|
-
(0,
|
|
77826
|
+
(0, import_fs79.mkdirSync)((0, import_path86.join)(projectRoot, ".gossip"), { recursive: true });
|
|
77191
77827
|
const row = {
|
|
77192
77828
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
77193
77829
|
consensus_id: null,
|
|
@@ -77201,7 +77837,7 @@ function writePremiseVerificationLog(projectRoot, taskId, result, opts) {
|
|
|
77201
77837
|
skill_bound: opts.skill_bound
|
|
77202
77838
|
};
|
|
77203
77839
|
if (opts.schema_lint) row.schema_lint = opts.schema_lint;
|
|
77204
|
-
(0,
|
|
77840
|
+
(0, import_fs79.appendFileSync)(logPath, JSON.stringify(row) + "\n");
|
|
77205
77841
|
} catch {
|
|
77206
77842
|
}
|
|
77207
77843
|
}
|
|
@@ -77313,7 +77949,7 @@ var AGENT_PROVIDER_MAP = {
|
|
|
77313
77949
|
};
|
|
77314
77950
|
function readQuotaState() {
|
|
77315
77951
|
try {
|
|
77316
|
-
const raw = (0,
|
|
77952
|
+
const raw = (0, import_fs79.readFileSync)((0, import_path86.join)(process.cwd(), ".gossip", "quota-state.json"), "utf8");
|
|
77317
77953
|
return JSON.parse(raw);
|
|
77318
77954
|
} catch {
|
|
77319
77955
|
return {};
|
|
@@ -77379,6 +78015,19 @@ async function handleDispatchSingle(agent_id, task, write_mode, scope, timeout_m
|
|
|
77379
78015
|
const relayToken = (0, import_crypto34.randomUUID)().slice(0, 12);
|
|
77380
78016
|
const timeoutMs = timeout_ms ?? NATIVE_TASK_TTL_MS;
|
|
77381
78017
|
stashDispatchWarnings([taskId], dispatchWarnings);
|
|
78018
|
+
runDispatchPreconditionGuard({
|
|
78019
|
+
projectRoot: process.cwd(),
|
|
78020
|
+
taskId,
|
|
78021
|
+
resolutionRoots,
|
|
78022
|
+
taskText: task,
|
|
78023
|
+
writeMode: write_mode
|
|
78024
|
+
}).then(({ warnings: precondWarnings }) => {
|
|
78025
|
+
for (const w of precondWarnings) {
|
|
78026
|
+
process.stderr.write(`[gossipcat] \u26A0\uFE0F precondition: ${w}
|
|
78027
|
+
`);
|
|
78028
|
+
}
|
|
78029
|
+
}).catch(() => {
|
|
78030
|
+
});
|
|
77382
78031
|
const premiseResult = await maybeVerifyPremiseClaims(task, process.cwd(), taskId, agent_id);
|
|
77383
78032
|
task = premiseResult.annotatedTask;
|
|
77384
78033
|
if (premiseResult.signals.length > 0) {
|
|
@@ -77796,6 +78445,24 @@ Task: ${def.task}`;
|
|
|
77796
78445
|
}
|
|
77797
78446
|
}
|
|
77798
78447
|
stashDispatchWarnings(allParallelTaskIds, dispatchWarnings);
|
|
78448
|
+
if (allParallelTaskIds.length > 0) {
|
|
78449
|
+
runDispatchPreconditionGuard({
|
|
78450
|
+
projectRoot: process.cwd(),
|
|
78451
|
+
taskId: allParallelTaskIds[0],
|
|
78452
|
+
resolutionRoots: effectiveResolutionRoots,
|
|
78453
|
+
taskText: taskDefs[0]?.task ?? "",
|
|
78454
|
+
writeMode: taskDefs[0]?.write_mode,
|
|
78455
|
+
// Bug A follow-up (Fix 1): scan ALL tasks for referenced paths, not just
|
|
78456
|
+
// taskDefs[0]. Stale-base/mid-flight stay one-per-dispatch above.
|
|
78457
|
+
additionalTasks: taskDefs.slice(1).map((d) => ({ taskText: d.task ?? "", writeMode: d.write_mode }))
|
|
78458
|
+
}).then(({ warnings: precondWarnings }) => {
|
|
78459
|
+
for (const w of precondWarnings) {
|
|
78460
|
+
process.stderr.write(`[gossipcat] \u26A0\uFE0F precondition: ${w}
|
|
78461
|
+
`);
|
|
78462
|
+
}
|
|
78463
|
+
}).catch(() => {
|
|
78464
|
+
});
|
|
78465
|
+
}
|
|
77799
78466
|
const parallelHost = detectNativeHost();
|
|
77800
78467
|
let msg = "";
|
|
77801
78468
|
if (nativeInstructions.length > 0) {
|
|
@@ -77874,8 +78541,8 @@ async function handleDispatchConsensus(taskDefs, _utility_task_id, dispatchResol
|
|
|
77874
78541
|
});
|
|
77875
78542
|
const lenses = await Promise.race([
|
|
77876
78543
|
lensPromise,
|
|
77877
|
-
new Promise((
|
|
77878
|
-
timerId = setTimeout(() =>
|
|
78544
|
+
new Promise((resolve33) => {
|
|
78545
|
+
timerId = setTimeout(() => resolve33(null), LENS_TIMEOUT_MS);
|
|
77879
78546
|
})
|
|
77880
78547
|
]);
|
|
77881
78548
|
if (timerId) clearTimeout(timerId);
|
|
@@ -78031,6 +78698,24 @@ Task: ${def.task}`;
|
|
|
78031
78698
|
}
|
|
78032
78699
|
}
|
|
78033
78700
|
stashDispatchWarnings(allTaskIds, dispatchRoundWarnings);
|
|
78701
|
+
if (allTaskIds.length > 0) {
|
|
78702
|
+
runDispatchPreconditionGuard({
|
|
78703
|
+
projectRoot: process.cwd(),
|
|
78704
|
+
taskId: allTaskIds[0],
|
|
78705
|
+
resolutionRoots: dispatchResolutionRoots,
|
|
78706
|
+
taskText: taskDefs[0]?.task ?? "",
|
|
78707
|
+
writeMode: taskDefs[0]?.write_mode,
|
|
78708
|
+
// Bug A follow-up (Fix 1): scan ALL tasks for referenced paths, not just
|
|
78709
|
+
// taskDefs[0]. Stale-base/mid-flight stay one-per-dispatch above.
|
|
78710
|
+
additionalTasks: taskDefs.slice(1).map((d) => ({ taskText: d.task ?? "", writeMode: d.write_mode }))
|
|
78711
|
+
}).then(({ warnings: precondWarnings }) => {
|
|
78712
|
+
for (const w of precondWarnings) {
|
|
78713
|
+
process.stderr.write(`[gossipcat] \u26A0\uFE0F precondition: ${w}
|
|
78714
|
+
`);
|
|
78715
|
+
}
|
|
78716
|
+
}).catch(() => {
|
|
78717
|
+
});
|
|
78718
|
+
}
|
|
78034
78719
|
const consensusHost = detectNativeHost();
|
|
78035
78720
|
const nativeTool = nativeToolName(consensusHost);
|
|
78036
78721
|
const collectCall = `gossip_collect(task_ids: [${allTaskIds.map((id) => `"${id}"`).join(", ")}], consensus: true)`;
|
|
@@ -78080,6 +78765,70 @@ ${p.prompt}` });
|
|
|
78080
78765
|
return dispatchWarnings.length > 0 ? { content, warnings: dispatchWarnings } : { content };
|
|
78081
78766
|
}
|
|
78082
78767
|
|
|
78768
|
+
// apps/cli/src/handlers/ask-back.ts
|
|
78769
|
+
var import_fs81 = require("fs");
|
|
78770
|
+
var import_path87 = require("path");
|
|
78771
|
+
var LEDGER_REL = (0, import_path87.join)(".gossip", "fabrication-introspections.jsonl");
|
|
78772
|
+
var MAX_INTROSPECTION_BYTES = 5 * 1024 * 1024;
|
|
78773
|
+
function ledgerPath(projectRoot) {
|
|
78774
|
+
return (0, import_path87.join)(projectRoot, LEDGER_REL);
|
|
78775
|
+
}
|
|
78776
|
+
function buildIntrospectionPrompt(claim, groundTruth) {
|
|
78777
|
+
return [
|
|
78778
|
+
"You are being asked to help improve the reliability of this review pipeline.",
|
|
78779
|
+
"",
|
|
78780
|
+
"A prior response from you was identified as a fabrication:",
|
|
78781
|
+
` Claim made: ${claim}`,
|
|
78782
|
+
` Ground truth: ${groundTruth}`,
|
|
78783
|
+
"",
|
|
78784
|
+
"Please reflect on the specific process failure that led to this.",
|
|
78785
|
+
"Do not apologize \u2014 instead, name the exact mechanism: for example,",
|
|
78786
|
+
'"I pattern-matched the task framing and assumed the identifier existed"',
|
|
78787
|
+
'or "I cited from memory without opening the file to verify".',
|
|
78788
|
+
"",
|
|
78789
|
+
"Your answer should be one to three sentences describing the HOW and WHY",
|
|
78790
|
+
"of the specific reasoning step that went wrong."
|
|
78791
|
+
].join("\n");
|
|
78792
|
+
}
|
|
78793
|
+
function appendIntrospection(projectRoot, record2, deps) {
|
|
78794
|
+
if (typeof record2.agentId !== "string" || !record2.agentId || typeof record2.status !== "string" || !record2.status) {
|
|
78795
|
+
return;
|
|
78796
|
+
}
|
|
78797
|
+
if (record2.status === "asked") {
|
|
78798
|
+
if (typeof record2.claim !== "string" || !record2.claim.trim() || typeof record2.groundTruth !== "string" || !record2.groundTruth.trim()) {
|
|
78799
|
+
return;
|
|
78800
|
+
}
|
|
78801
|
+
}
|
|
78802
|
+
const clean = {
|
|
78803
|
+
agentId: record2.agentId,
|
|
78804
|
+
claim: record2.claim,
|
|
78805
|
+
groundTruth: record2.groundTruth,
|
|
78806
|
+
status: record2.status
|
|
78807
|
+
};
|
|
78808
|
+
if (record2.askedAt !== void 0) clean["askedAt"] = record2.askedAt;
|
|
78809
|
+
if (record2.findingId !== void 0) clean["findingId"] = record2.findingId;
|
|
78810
|
+
if (record2.answer !== void 0) clean["answer"] = record2.answer;
|
|
78811
|
+
if (record2.answeredAt !== void 0) clean["answeredAt"] = record2.answeredAt;
|
|
78812
|
+
const line = JSON.stringify(clean) + "\n";
|
|
78813
|
+
const path8 = ledgerPath(projectRoot);
|
|
78814
|
+
try {
|
|
78815
|
+
const fsMkdir = deps?.mkdirSync ?? import_fs81.mkdirSync;
|
|
78816
|
+
const fsAppend = deps?.appendFileSync ?? import_fs81.appendFileSync;
|
|
78817
|
+
const fsStat = deps?.statSync ?? import_fs81.statSync;
|
|
78818
|
+
const fsRename = deps?.renameSync ?? import_fs81.renameSync;
|
|
78819
|
+
fsMkdir((0, import_path87.join)(projectRoot, ".gossip"), { recursive: true });
|
|
78820
|
+
try {
|
|
78821
|
+
const st = fsStat(path8);
|
|
78822
|
+
if (st.size >= MAX_INTROSPECTION_BYTES) {
|
|
78823
|
+
fsRename(path8, path8 + ".1");
|
|
78824
|
+
}
|
|
78825
|
+
} catch {
|
|
78826
|
+
}
|
|
78827
|
+
fsAppend(path8, line);
|
|
78828
|
+
} catch {
|
|
78829
|
+
}
|
|
78830
|
+
}
|
|
78831
|
+
|
|
78083
78832
|
// apps/cli/src/mcp-server-sdk.ts
|
|
78084
78833
|
init_dispatch_prompt_cache();
|
|
78085
78834
|
|
|
@@ -78120,6 +78869,7 @@ function discoverVerifier(agents, override) {
|
|
|
78120
78869
|
init_src4();
|
|
78121
78870
|
var import_node_fs = require("node:fs");
|
|
78122
78871
|
var import_node_path = require("node:path");
|
|
78872
|
+
init_orchestrator_precondition_runner();
|
|
78123
78873
|
function scheduleSkillRunner(c, mainAgent) {
|
|
78124
78874
|
if (!c.skillEngine) return;
|
|
78125
78875
|
const skillEngine = c.skillEngine;
|
|
@@ -78263,7 +79013,7 @@ Relay may be down. Check gossip_status() for connection state.` }] };
|
|
|
78263
79013
|
process.stderr.write(`[gossipcat] \u23F3 Consensus: ${doneCount}/${pendingNativeIds.length} agents complete (${agentStatus})
|
|
78264
79014
|
`);
|
|
78265
79015
|
}
|
|
78266
|
-
await new Promise((
|
|
79016
|
+
await new Promise((resolve33) => setTimeout(resolve33, POLL_INTERVAL));
|
|
78267
79017
|
}
|
|
78268
79018
|
const arrived = pendingNativeIds.filter((id) => ctx.nativeResultMap.has(id)).length;
|
|
78269
79019
|
const timedOutCount = pendingNativeIds.filter((id) => {
|
|
@@ -78645,6 +79395,7 @@ ${t.skillWarnings.map((w) => ` - ${w}`).join("\n")}`;
|
|
|
78645
79395
|
relayCrossReviewSkipped
|
|
78646
79396
|
);
|
|
78647
79397
|
} else {
|
|
79398
|
+
const roundStartSha = captureHeadSha(process.cwd());
|
|
78648
79399
|
ctx.pendingConsensusRounds.set(consensusId, {
|
|
78649
79400
|
consensusId,
|
|
78650
79401
|
allResults: allResults.filter((r) => r.status === "completed"),
|
|
@@ -78668,7 +79419,12 @@ ${t.skillWarnings.map((w) => ` - ${w}`).join("\n")}`;
|
|
|
78668
79419
|
// warnings + read its roots. The flat resolutionRoots above stays
|
|
78669
79420
|
// populated in parallel for old-reader back-compat. PR-C: this is
|
|
78670
79421
|
// always a concrete RoundContext (the engine now requires one).
|
|
78671
|
-
roundContext: effectiveRound
|
|
79422
|
+
roundContext: effectiveRound,
|
|
79423
|
+
// UNIT 3: capture HEAD SHA at Phase 2 start for mid_flight_fixup detection.
|
|
79424
|
+
// Best-effort — undefined when git is unavailable (never blocks the round).
|
|
79425
|
+
// FIX 2: hoisted out of the set() literal so execFileSync does not block
|
|
79426
|
+
// the MCP handler inline inside the Map mutation.
|
|
79427
|
+
roundStartSha
|
|
78672
79428
|
});
|
|
78673
79429
|
const recentTaskIds = [
|
|
78674
79430
|
...allResults.filter((r) => r.status === "completed").map((r) => r.id)
|
|
@@ -78855,7 +79611,7 @@ ${np.user}
|
|
|
78855
79611
|
const autoResolveEnabled = cfgPathAr?.consensus?.autoResolveOnRoundClose !== false;
|
|
78856
79612
|
if (autoResolveEnabled) {
|
|
78857
79613
|
const { resolveFindings: rf } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
78858
|
-
const resolveResult = await rf(process.cwd(), { lineAnchored: cfgPathAr?.consensus?.resolverLineAnchored ??
|
|
79614
|
+
const resolveResult = await rf(process.cwd(), { lineAnchored: cfgPathAr?.consensus?.resolverLineAnchored ?? true });
|
|
78859
79615
|
if (resolveResult.ok) {
|
|
78860
79616
|
if (resolveResult.resolved > 0) {
|
|
78861
79617
|
process.stderr.write(
|
|
@@ -79158,19 +79914,19 @@ function filterWatchEvents(rawJsonl, opts) {
|
|
|
79158
79914
|
}
|
|
79159
79915
|
|
|
79160
79916
|
// apps/cli/src/stickyPort.ts
|
|
79161
|
-
var
|
|
79162
|
-
var
|
|
79917
|
+
var import_fs84 = require("fs");
|
|
79918
|
+
var import_path90 = require("path");
|
|
79163
79919
|
var import_net = require("net");
|
|
79164
|
-
var RELAY_STICKY_FILE = (0,
|
|
79165
|
-
var HTTP_MCP_STICKY_FILE = (0,
|
|
79920
|
+
var RELAY_STICKY_FILE = (0, import_path90.join)(".gossip", "relay.port");
|
|
79921
|
+
var HTTP_MCP_STICKY_FILE = (0, import_path90.join)(".gossip", "http-mcp.port");
|
|
79166
79922
|
function stickyPath(filename) {
|
|
79167
|
-
return (0,
|
|
79923
|
+
return (0, import_path90.join)(process.cwd(), filename);
|
|
79168
79924
|
}
|
|
79169
79925
|
function readStickyPort(filename) {
|
|
79170
79926
|
const p = stickyPath(filename);
|
|
79171
|
-
if (!(0,
|
|
79927
|
+
if (!(0, import_fs84.existsSync)(p)) return null;
|
|
79172
79928
|
try {
|
|
79173
|
-
const raw = (0,
|
|
79929
|
+
const raw = (0, import_fs84.readFileSync)(p, "utf-8").trim();
|
|
79174
79930
|
const n = parseInt(raw, 10);
|
|
79175
79931
|
if (!Number.isFinite(n) || n < 1 || n > 65535) return null;
|
|
79176
79932
|
return n;
|
|
@@ -79182,13 +79938,13 @@ function writeStickyPort(filename, port) {
|
|
|
79182
79938
|
if (!Number.isFinite(port) || port < 1 || port > 65535) return;
|
|
79183
79939
|
const p = stickyPath(filename);
|
|
79184
79940
|
try {
|
|
79185
|
-
(0,
|
|
79186
|
-
(0,
|
|
79941
|
+
(0, import_fs84.mkdirSync)((0, import_path90.dirname)(p), { recursive: true });
|
|
79942
|
+
(0, import_fs84.writeFileSync)(p, String(port), "utf-8");
|
|
79187
79943
|
} catch {
|
|
79188
79944
|
}
|
|
79189
79945
|
}
|
|
79190
79946
|
function probePort(port, host = "127.0.0.1") {
|
|
79191
|
-
return new Promise((
|
|
79947
|
+
return new Promise((resolve33) => {
|
|
79192
79948
|
const srv = (0, import_net.createServer)();
|
|
79193
79949
|
let settled = false;
|
|
79194
79950
|
const done = (ok) => {
|
|
@@ -79198,7 +79954,7 @@ function probePort(port, host = "127.0.0.1") {
|
|
|
79198
79954
|
srv.close();
|
|
79199
79955
|
} catch {
|
|
79200
79956
|
}
|
|
79201
|
-
|
|
79957
|
+
resolve33(ok);
|
|
79202
79958
|
};
|
|
79203
79959
|
srv.once("error", () => done(false));
|
|
79204
79960
|
try {
|
|
@@ -79256,20 +80012,20 @@ function mergeSetupConfig(input) {
|
|
|
79256
80012
|
function buildMalformedConfigHint(configPath, message) {
|
|
79257
80013
|
return `\u26A0\uFE0F config.json is malformed: ${message} \u2014 fix or delete ${configPath}`;
|
|
79258
80014
|
}
|
|
79259
|
-
function flushStagedAgentFileWrites(writes,
|
|
80015
|
+
function flushStagedAgentFileWrites(writes, fs7) {
|
|
79260
80016
|
for (const w of writes) {
|
|
79261
|
-
|
|
79262
|
-
|
|
80017
|
+
fs7.mkdirSync(w.dir, { recursive: true });
|
|
80018
|
+
fs7.writeFileSync(w.path, w.content, "utf-8");
|
|
79263
80019
|
}
|
|
79264
80020
|
}
|
|
79265
80021
|
|
|
79266
80022
|
// apps/cli/src/native-agent-cache.ts
|
|
79267
|
-
var
|
|
79268
|
-
var
|
|
80023
|
+
var import_fs85 = require("fs");
|
|
80024
|
+
var import_path91 = require("path");
|
|
79269
80025
|
var realFs = {
|
|
79270
|
-
existsSync:
|
|
79271
|
-
readFileSync:
|
|
79272
|
-
statSync: (p) => ({ mtimeMs: (0,
|
|
80026
|
+
existsSync: import_fs85.existsSync,
|
|
80027
|
+
readFileSync: import_fs85.readFileSync,
|
|
80028
|
+
statSync: (p) => ({ mtimeMs: (0, import_fs85.statSync)(p).mtimeMs })
|
|
79273
80029
|
};
|
|
79274
80030
|
function modelTierFromId(modelId) {
|
|
79275
80031
|
if (modelId.includes("opus")) return "opus";
|
|
@@ -79277,16 +80033,16 @@ function modelTierFromId(modelId) {
|
|
|
79277
80033
|
if (modelId.includes("fable")) return "fable";
|
|
79278
80034
|
return "sonnet";
|
|
79279
80035
|
}
|
|
79280
|
-
function refreshNativeAgentFromDisk(ac, cache3, projectRoot,
|
|
79281
|
-
const claudeAgentPath = (0,
|
|
79282
|
-
const instrPath = (0,
|
|
80036
|
+
function refreshNativeAgentFromDisk(ac, cache3, projectRoot, fs7 = realFs) {
|
|
80037
|
+
const claudeAgentPath = (0, import_path91.join)(projectRoot, ".claude", "agents", `${ac.id}.md`);
|
|
80038
|
+
const instrPath = (0, import_path91.join)(projectRoot, ".gossip", "agents", ac.id, "instructions.md");
|
|
79283
80039
|
const prev = cache3.get(ac.id);
|
|
79284
80040
|
let sourcePath = null;
|
|
79285
80041
|
let stripFrontmatter = false;
|
|
79286
|
-
if (
|
|
80042
|
+
if (fs7.existsSync(claudeAgentPath)) {
|
|
79287
80043
|
sourcePath = claudeAgentPath;
|
|
79288
80044
|
stripFrontmatter = true;
|
|
79289
|
-
} else if (
|
|
80045
|
+
} else if (fs7.existsSync(instrPath)) {
|
|
79290
80046
|
sourcePath = instrPath;
|
|
79291
80047
|
stripFrontmatter = false;
|
|
79292
80048
|
}
|
|
@@ -79305,7 +80061,7 @@ function refreshNativeAgentFromDisk(ac, cache3, projectRoot, fs6 = realFs) {
|
|
|
79305
80061
|
}
|
|
79306
80062
|
let currentMtimeMs;
|
|
79307
80063
|
try {
|
|
79308
|
-
currentMtimeMs =
|
|
80064
|
+
currentMtimeMs = fs7.statSync(sourcePath).mtimeMs;
|
|
79309
80065
|
} catch {
|
|
79310
80066
|
if (prev && prev.instructions.length > 0) {
|
|
79311
80067
|
return;
|
|
@@ -79321,7 +80077,7 @@ function refreshNativeAgentFromDisk(ac, cache3, projectRoot, fs6 = realFs) {
|
|
|
79321
80077
|
if (prev && prev.cachedMtimeMs === currentMtimeMs) {
|
|
79322
80078
|
return;
|
|
79323
80079
|
}
|
|
79324
|
-
let instructions =
|
|
80080
|
+
let instructions = fs7.readFileSync(sourcePath, "utf-8");
|
|
79325
80081
|
if (stripFrontmatter) {
|
|
79326
80082
|
instructions = instructions.replace(/^---\n[\s\S]*?\n---\n*/, "").trim();
|
|
79327
80083
|
}
|
|
@@ -79338,22 +80094,22 @@ function refreshNativeAgentFromDisk(ac, cache3, projectRoot, fs6 = realFs) {
|
|
|
79338
80094
|
}
|
|
79339
80095
|
|
|
79340
80096
|
// apps/cli/src/rules-content.ts
|
|
79341
|
-
var
|
|
79342
|
-
var
|
|
80097
|
+
var import_fs86 = require("fs");
|
|
80098
|
+
var import_path92 = require("path");
|
|
79343
80099
|
var AGENT_LIST_PLACEHOLDER = "{{AGENT_LIST}}";
|
|
79344
80100
|
function resolveRulesPath(host = detectNativeHost()) {
|
|
79345
80101
|
const fileName = host === "cursor" ? "CURSOR_RULES.md" : "RULES.md";
|
|
79346
80102
|
const candidates = [
|
|
79347
|
-
(0,
|
|
79348
|
-
(0,
|
|
79349
|
-
(0,
|
|
80103
|
+
(0, import_path92.join)(process.cwd(), "docs", fileName),
|
|
80104
|
+
(0, import_path92.join)(__dirname, "..", "docs", fileName),
|
|
80105
|
+
(0, import_path92.join)(__dirname, "docs", fileName),
|
|
79350
80106
|
// Fallback: bundled RULES.md when CURSOR_RULES.md not yet shipped
|
|
79351
80107
|
...host === "cursor" ? [
|
|
79352
|
-
(0,
|
|
79353
|
-
(0,
|
|
80108
|
+
(0, import_path92.join)(process.cwd(), "docs", "RULES.md"),
|
|
80109
|
+
(0, import_path92.join)(__dirname, "..", "docs", "RULES.md")
|
|
79354
80110
|
] : []
|
|
79355
80111
|
];
|
|
79356
|
-
return candidates.find((p) => (0,
|
|
80112
|
+
return candidates.find((p) => (0, import_fs86.existsSync)(p)) ?? null;
|
|
79357
80113
|
}
|
|
79358
80114
|
function generateRulesContent(agentList, host) {
|
|
79359
80115
|
const resolvedHost = host ?? detectNativeHost();
|
|
@@ -79363,7 +80119,7 @@ function generateRulesContent(agentList, host) {
|
|
|
79363
80119
|
`[gossipcat] generateRulesContent: docs/RULES.md not found for host=${resolvedHost} (cwd=${process.cwd()}, dirname=${__dirname}). Expected docs/RULES.md or docs/CURSOR_RULES.md tracked in the gossipcat repo or shipped alongside the MCP bundle.`
|
|
79364
80120
|
);
|
|
79365
80121
|
}
|
|
79366
|
-
let template = (0,
|
|
80122
|
+
let template = (0, import_fs86.readFileSync)(rulesPath, "utf-8");
|
|
79367
80123
|
if (resolvedHost === "cursor" && rulesPath.endsWith("RULES.md")) {
|
|
79368
80124
|
template = template.replace(/Agent\(\)/g, "Task()").replace(/Agent\(/g, "Task(").replace(/Claude Code/g, "Cursor");
|
|
79369
80125
|
}
|
|
@@ -79463,7 +80219,7 @@ var __argvShimHandled = (() => {
|
|
|
79463
80219
|
}
|
|
79464
80220
|
if (kind === "help") {
|
|
79465
80221
|
process.stdout.write(
|
|
79466
|
-
"gossipcat \u2014 Multi-Agent Orchestration\n\nUsage:\n gossipcat Start MCP server (for Claude Code / Cursor)\n gossipcat hook --run Run UserPromptSubmit bootstrap hook (internal)\n gossipcat hook mirror-prompt|mirror-stop|mirror-tool Activity-mirror hooks (internal; opt-in via gossip_setup mirror_hooks)\n gossipcat key set <provider> Store an API key in the OS keychain (service: gossip-mesh)\n gossipcat key list Show which providers have a stored key\n gossipcat code [args...] Launch Claude Code with the gossipcat channel active\n gossipcat help Show this help\n\nThe published binary is the MCP server bundle. The full CLI\n(setup wizard, create-agent, chat, etc.) lives in apps/cli/src/index.ts\nand is available via `npm start` / `npx ts-node` in the source repo.\nThe `code` subcommand is available in the published binary.\n"
|
|
80222
|
+
"gossipcat \u2014 Multi-Agent Orchestration\n\nUsage:\n gossipcat Start MCP server (for Claude Code / Cursor)\n gossipcat hook --run Run UserPromptSubmit bootstrap hook (internal)\n gossipcat hook mirror-prompt|mirror-stop|mirror-tool Activity-mirror hooks (internal; opt-in via gossip_setup mirror_hooks)\n gossipcat key set <provider> Store an API key in the OS keychain (service: gossip-mesh)\n gossipcat key list Show which providers have a stored key\n gossipcat code [args...] Launch Claude Code with the gossipcat channel active\n Note: <cwd>/.mcp.json is treated as trusted config (server name is read from it).\n gossipcat help Show this help\n\nThe published binary is the MCP server bundle. The full CLI\n(setup wizard, create-agent, chat, etc.) lives in apps/cli/src/index.ts\nand is available via `npm start` / `npx ts-node` in the source repo.\nThe `code` subcommand is available in the published binary.\n"
|
|
79467
80223
|
);
|
|
79468
80224
|
process.exit(0);
|
|
79469
80225
|
}
|
|
@@ -79511,15 +80267,15 @@ var __argvShimHandled = (() => {
|
|
|
79511
80267
|
function readSecretFromStdin() {
|
|
79512
80268
|
const stdin = process.stdin;
|
|
79513
80269
|
if (!stdin.isTTY) {
|
|
79514
|
-
return new Promise((
|
|
80270
|
+
return new Promise((resolve33, reject) => {
|
|
79515
80271
|
const chunks = [];
|
|
79516
80272
|
stdin.on("data", (c) => chunks.push(c));
|
|
79517
|
-
stdin.on("end", () =>
|
|
80273
|
+
stdin.on("end", () => resolve33(Buffer.concat(chunks).toString("utf8")));
|
|
79518
80274
|
stdin.on("error", (e) => reject(e));
|
|
79519
80275
|
stdin.resume();
|
|
79520
80276
|
});
|
|
79521
80277
|
}
|
|
79522
|
-
return new Promise((
|
|
80278
|
+
return new Promise((resolve33) => {
|
|
79523
80279
|
process.stderr.write("Paste the API key, then Enter: ");
|
|
79524
80280
|
let buf = "";
|
|
79525
80281
|
const wasRaw = stdin.isRaw === true;
|
|
@@ -79534,7 +80290,7 @@ function readSecretFromStdin() {
|
|
|
79534
80290
|
stdin.pause();
|
|
79535
80291
|
stdin.removeListener("data", onData);
|
|
79536
80292
|
process.stderr.write("\n");
|
|
79537
|
-
|
|
80293
|
+
resolve33(buf);
|
|
79538
80294
|
return;
|
|
79539
80295
|
} else if (code === 3) {
|
|
79540
80296
|
stdin.setRawMode(wasRaw);
|
|
@@ -79553,12 +80309,12 @@ function readSecretFromStdin() {
|
|
|
79553
80309
|
});
|
|
79554
80310
|
}
|
|
79555
80311
|
if (process.env.GOSSIPCAT_MCP_NO_MAIN !== "1" && !__argvShimHandled) {
|
|
79556
|
-
const gossipDir = (0,
|
|
80312
|
+
const gossipDir = (0, import_path97.join)(process.cwd(), ".gossip");
|
|
79557
80313
|
try {
|
|
79558
|
-
(0,
|
|
80314
|
+
(0, import_fs91.mkdirSync)(gossipDir, { recursive: true });
|
|
79559
80315
|
} catch {
|
|
79560
80316
|
}
|
|
79561
|
-
const logStream = (0,
|
|
80317
|
+
const logStream = (0, import_fs91.createWriteStream)((0, import_path97.join)(gossipDir, "mcp.log"), { flags: "a", mode: 384 });
|
|
79562
80318
|
process.stderr.write = ((chunk, ...args) => {
|
|
79563
80319
|
return logStream.write(chunk, ...args);
|
|
79564
80320
|
});
|
|
@@ -79569,7 +80325,7 @@ try {
|
|
|
79569
80325
|
} catch {
|
|
79570
80326
|
}
|
|
79571
80327
|
function memoryDirForProject(cwd) {
|
|
79572
|
-
return (0,
|
|
80328
|
+
return (0, import_path97.join)((0, import_os8.homedir)(), ".claude", "projects", cwd.replaceAll("/", "-"), "memory");
|
|
79573
80329
|
}
|
|
79574
80330
|
function dashboardClickableUrl(url2, key) {
|
|
79575
80331
|
if (!key) return url2;
|
|
@@ -79644,14 +80400,14 @@ var _pendingPlanData = /* @__PURE__ */ new Map();
|
|
|
79644
80400
|
var _utilityGuardSnapshots = /* @__PURE__ */ new Map();
|
|
79645
80401
|
var _modules = null;
|
|
79646
80402
|
function lookupFindingSeverity(findingId, projectRoot) {
|
|
79647
|
-
const { existsSync:
|
|
79648
|
-
const { join:
|
|
79649
|
-
const reportsDir =
|
|
79650
|
-
if (!
|
|
80403
|
+
const { existsSync: existsSync74, readdirSync: readdirSync22, readFileSync: readFileSync70 } = require("fs");
|
|
80404
|
+
const { join: join93 } = require("path");
|
|
80405
|
+
const reportsDir = join93(projectRoot, ".gossip", "consensus-reports");
|
|
80406
|
+
if (!existsSync74(reportsDir)) return null;
|
|
79651
80407
|
try {
|
|
79652
80408
|
const files = readdirSync22(reportsDir).filter((f) => f.endsWith(".json"));
|
|
79653
80409
|
for (const file2 of files) {
|
|
79654
|
-
const report = JSON.parse(
|
|
80410
|
+
const report = JSON.parse(readFileSync70(join93(reportsDir, file2), "utf-8"));
|
|
79655
80411
|
for (const bucket of ["confirmed", "disputed", "unverified", "unique"]) {
|
|
79656
80412
|
for (const finding of report[bucket] || []) {
|
|
79657
80413
|
if (finding.id === findingId && finding.severity) {
|
|
@@ -79750,7 +80506,7 @@ async function doBoot() {
|
|
|
79750
80506
|
const agentConfigs = m.configToAgentConfigs(config2);
|
|
79751
80507
|
ctx.keychain = new m.Keychain();
|
|
79752
80508
|
const { existsSync: pidExists, readFileSync: readPid, writeFileSync: writePid, unlinkSync: delPid } = require("fs");
|
|
79753
|
-
const pidFile = (0,
|
|
80509
|
+
const pidFile = (0, import_path97.join)(process.cwd(), ".gossip", "relay.pid");
|
|
79754
80510
|
if (pidExists(pidFile)) {
|
|
79755
80511
|
const oldPid = parseInt(readPid(pidFile, "utf-8").trim(), 10);
|
|
79756
80512
|
if (!isNaN(oldPid) && oldPid !== process.pid) {
|
|
@@ -79872,10 +80628,10 @@ async function doBoot() {
|
|
|
79872
80628
|
{ id: ac.id, provider: ac.provider, model: ac.model, base_url: ac.base_url, key_ref: ac.key_ref },
|
|
79873
80629
|
(s) => ctx.keychain.getKey(s)
|
|
79874
80630
|
);
|
|
79875
|
-
const { existsSync:
|
|
79876
|
-
const { join:
|
|
79877
|
-
const instructionsPath =
|
|
79878
|
-
const baseInstructions =
|
|
80631
|
+
const { existsSync: existsSync74, readFileSync: readFileSync70 } = require("fs");
|
|
80632
|
+
const { join: join93 } = require("path");
|
|
80633
|
+
const instructionsPath = join93(process.cwd(), ".gossip", "agents", ac.id, "instructions.md");
|
|
80634
|
+
const baseInstructions = existsSync74(instructionsPath) ? readFileSync70(instructionsPath, "utf-8") : "";
|
|
79879
80635
|
const identity = ctx.identityRegistry.get(ac.id);
|
|
79880
80636
|
const identityBlock = identity ? m.formatIdentityBlock(identity) + "\n" : "";
|
|
79881
80637
|
const instructions = (identityBlock + baseInstructions).trim() || void 0;
|
|
@@ -80804,6 +81560,70 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
80804
81560
|
};
|
|
80805
81561
|
}
|
|
80806
81562
|
);
|
|
81563
|
+
server.tool(
|
|
81564
|
+
"gossip_ask_back",
|
|
81565
|
+
`Re-engage an agent after a fabrication (hallucination_caught) for first-person root-cause analysis. action:"ask" dispatches an introspection prompt to the agent and logs the event; action:"record" stores the agent's answer. Builds a rich failure ledger (.gossip/fabrication-introspections.jsonl) that feeds skill development.`,
|
|
81566
|
+
{
|
|
81567
|
+
action: external_exports.enum(["ask", "record"]).default("ask").describe(`"ask" (default): dispatch an introspection prompt to the agent. "record": store the agent's answer.`),
|
|
81568
|
+
agent_id: external_exports.string().describe("The agent that produced the fabrication."),
|
|
81569
|
+
claim: external_exports.string().optional().describe('Required for action:"ask". The fabricated claim the agent made.'),
|
|
81570
|
+
ground_truth: external_exports.string().optional().describe('Required for action:"ask". What the code/evidence actually shows.'),
|
|
81571
|
+
finding_id: external_exports.string().optional().describe("Optional consensus finding_id (format: <consensus_id>:<agent:fN>) to link the introspection to a specific finding."),
|
|
81572
|
+
answer: external_exports.string().optional().describe(`Required for action:"record". The agent's root-cause explanation.`)
|
|
81573
|
+
},
|
|
81574
|
+
async ({ action, agent_id, claim, ground_truth, finding_id, answer }) => {
|
|
81575
|
+
const projectRoot = process.cwd();
|
|
81576
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
81577
|
+
if (action === "ask") {
|
|
81578
|
+
if (!claim || !ground_truth) {
|
|
81579
|
+
return {
|
|
81580
|
+
content: [{ type: "text", text: 'gossip_ask_back error: action:"ask" requires both claim and ground_truth.' }],
|
|
81581
|
+
isError: true
|
|
81582
|
+
};
|
|
81583
|
+
}
|
|
81584
|
+
appendIntrospection(projectRoot, {
|
|
81585
|
+
agentId: agent_id,
|
|
81586
|
+
findingId: finding_id,
|
|
81587
|
+
claim,
|
|
81588
|
+
groundTruth: ground_truth,
|
|
81589
|
+
status: "asked",
|
|
81590
|
+
askedAt: now
|
|
81591
|
+
});
|
|
81592
|
+
const prompt = buildIntrospectionPrompt(claim, ground_truth);
|
|
81593
|
+
const dispatchResult = await handleDispatchSingle(agent_id, prompt);
|
|
81594
|
+
const instruction = `After the agent answers, call gossip_ask_back(action:'record', agent_id:'${agent_id}'` + (finding_id ? `, finding_id:'${finding_id}'` : "") + `, answer:<agent response>) to log the introspection.
|
|
81595
|
+
|
|
81596
|
+
`;
|
|
81597
|
+
const dispatchText = dispatchResult.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
81598
|
+
return {
|
|
81599
|
+
content: [{ type: "text", text: instruction + dispatchText }]
|
|
81600
|
+
};
|
|
81601
|
+
}
|
|
81602
|
+
if (!answer) {
|
|
81603
|
+
return {
|
|
81604
|
+
content: [{ type: "text", text: 'gossip_ask_back error: action:"record" requires answer.' }],
|
|
81605
|
+
isError: true
|
|
81606
|
+
};
|
|
81607
|
+
}
|
|
81608
|
+
appendIntrospection(projectRoot, {
|
|
81609
|
+
agentId: agent_id,
|
|
81610
|
+
findingId: finding_id,
|
|
81611
|
+
claim: claim ?? "",
|
|
81612
|
+
groundTruth: ground_truth ?? "",
|
|
81613
|
+
answer,
|
|
81614
|
+
status: "answered",
|
|
81615
|
+
answeredAt: now
|
|
81616
|
+
});
|
|
81617
|
+
const ledgerPath2 = `${projectRoot}/.gossip/fabrication-introspections.jsonl`;
|
|
81618
|
+
return {
|
|
81619
|
+
content: [{
|
|
81620
|
+
type: "text",
|
|
81621
|
+
text: `Introspection recorded for ${agent_id}${finding_id ? ` (finding: ${finding_id})` : ""}.
|
|
81622
|
+
Ledger: ${ledgerPath2}`
|
|
81623
|
+
}]
|
|
81624
|
+
};
|
|
81625
|
+
}
|
|
81626
|
+
);
|
|
80807
81627
|
server.tool(
|
|
80808
81628
|
"gossip_status",
|
|
80809
81629
|
"Check Gossip Mesh system status, host environment, available agents, dashboard URL/key, and agent list with provider/model/skills. Pass slim:true to skip the handbook inline (~21KB savings) on reconnect refreshes.",
|
|
@@ -80861,7 +81681,7 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
80861
81681
|
}
|
|
80862
81682
|
try {
|
|
80863
81683
|
const { readFileSync: rfHealth } = await import("fs");
|
|
80864
|
-
const healthPath = (0,
|
|
81684
|
+
const healthPath = (0, import_path97.join)(process.cwd(), ".gossip", "skill-runner-health.json");
|
|
80865
81685
|
const raw = rfHealth(healthPath, "utf8");
|
|
80866
81686
|
const h = JSON.parse(raw);
|
|
80867
81687
|
const lastMs = h.last_run_at ? new Date(h.last_run_at).getTime() : NaN;
|
|
@@ -80877,9 +81697,9 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
80877
81697
|
lines.push(" Skill graduation: never run since session start (expected after first gossip_collect)");
|
|
80878
81698
|
}
|
|
80879
81699
|
try {
|
|
80880
|
-
const { readFileSync:
|
|
80881
|
-
const quotaPath = (0,
|
|
80882
|
-
const quotaRaw =
|
|
81700
|
+
const { readFileSync: readFileSync70 } = await import("fs");
|
|
81701
|
+
const quotaPath = (0, import_path97.join)(process.cwd(), ".gossip", "quota-state.json");
|
|
81702
|
+
const quotaRaw = readFileSync70(quotaPath, "utf8");
|
|
80883
81703
|
const quotaState = JSON.parse(quotaRaw);
|
|
80884
81704
|
for (const [provider, state] of Object.entries(quotaState)) {
|
|
80885
81705
|
const now = Date.now();
|
|
@@ -80931,7 +81751,7 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
80931
81751
|
}
|
|
80932
81752
|
try {
|
|
80933
81753
|
const { existsSync: hookExists } = await import("fs");
|
|
80934
|
-
const hookScriptPath = (0,
|
|
81754
|
+
const hookScriptPath = (0, import_path97.join)(process.cwd(), ".claude", "hooks", "worktree-sandbox.sh");
|
|
80935
81755
|
const { isWorktreeSandboxHookRegistered: isWorktreeSandboxHookRegistered2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
80936
81756
|
if (hookExists(hookScriptPath) && !isWorktreeSandboxHookRegistered2(process.cwd())) {
|
|
80937
81757
|
lines.push(" \u26A0\uFE0F Sandbox: worktree-sandbox hook installed but UNREGISTERED \u2014 run gossip_setup to re-register");
|
|
@@ -80939,21 +81759,21 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
80939
81759
|
} catch {
|
|
80940
81760
|
}
|
|
80941
81761
|
try {
|
|
80942
|
-
const { readdirSync: readdirSync22, statSync: statSync36, readFileSync:
|
|
81762
|
+
const { readdirSync: readdirSync22, statSync: statSync36, readFileSync: readFileSync70 } = await import("fs");
|
|
80943
81763
|
const { readJsonlWithRotated: readJsonlRotated1506 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
80944
|
-
const reportsDir = (0,
|
|
80945
|
-
const perfPath = (0,
|
|
81764
|
+
const reportsDir = (0, import_path97.join)(process.cwd(), ".gossip", "consensus-reports");
|
|
81765
|
+
const perfPath = (0, import_path97.join)(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
80946
81766
|
const WINDOW_MS3 = 24 * 60 * 60 * 1e3;
|
|
80947
81767
|
const now = Date.now();
|
|
80948
81768
|
const recentReports = [];
|
|
80949
81769
|
try {
|
|
80950
81770
|
for (const fname of readdirSync22(reportsDir)) {
|
|
80951
81771
|
if (!fname.endsWith(".json")) continue;
|
|
80952
|
-
const fpath = (0,
|
|
81772
|
+
const fpath = (0, import_path97.join)(reportsDir, fname);
|
|
80953
81773
|
const st = statSync36(fpath);
|
|
80954
81774
|
if (now - st.mtimeMs > WINDOW_MS3) continue;
|
|
80955
81775
|
try {
|
|
80956
|
-
const report = JSON.parse(
|
|
81776
|
+
const report = JSON.parse(readFileSync70(fpath, "utf8"));
|
|
80957
81777
|
const isEmpty = (report.confirmed?.length ?? 0) === 0 && (report.disputed?.length ?? 0) === 0 && (report.unverified?.length ?? 0) === 0 && (report.unique?.length ?? 0) === 0 && (report.newFindings?.length ?? 0) === 0 && (report.insights?.length ?? 0) === 0;
|
|
80958
81778
|
if (isEmpty) continue;
|
|
80959
81779
|
} catch {
|
|
@@ -81327,8 +82147,8 @@ ${body}`
|
|
|
81327
82147
|
}
|
|
81328
82148
|
return { content: [{ type: "text", text: results.join("\n") }] };
|
|
81329
82149
|
}
|
|
81330
|
-
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45, existsSync:
|
|
81331
|
-
const { join:
|
|
82150
|
+
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45, existsSync: existsSync74 } = require("fs");
|
|
82151
|
+
const { join: join93 } = require("path");
|
|
81332
82152
|
const root = process.cwd();
|
|
81333
82153
|
const CLAUDE_MODEL_MAP2 = {
|
|
81334
82154
|
opus: { provider: "anthropic", model: "claude-opus-4-6" },
|
|
@@ -81344,8 +82164,8 @@ ${body}`
|
|
|
81344
82164
|
let existingConfig = {};
|
|
81345
82165
|
let existingAgents = {};
|
|
81346
82166
|
try {
|
|
81347
|
-
const { readFileSync:
|
|
81348
|
-
const existing = JSON.parse(
|
|
82167
|
+
const { readFileSync: readFileSync70 } = require("fs");
|
|
82168
|
+
const existing = JSON.parse(readFileSync70(join93(root, ".gossip", "config.json"), "utf-8"));
|
|
81349
82169
|
if (existing && typeof existing === "object" && !Array.isArray(existing)) {
|
|
81350
82170
|
existingConfig = existing;
|
|
81351
82171
|
if (mode === "merge") existingAgents = existing.agents || {};
|
|
@@ -81379,8 +82199,8 @@ ${body}`
|
|
|
81379
82199
|
body
|
|
81380
82200
|
].join("\n");
|
|
81381
82201
|
pendingAgentFileWrites.push({
|
|
81382
|
-
dir:
|
|
81383
|
-
path:
|
|
82202
|
+
dir: join93(root, ".claude", "agents"),
|
|
82203
|
+
path: join93(root, ".claude", "agents", `${agent.id}.md`),
|
|
81384
82204
|
content: md
|
|
81385
82205
|
});
|
|
81386
82206
|
nativeCreated.push(agent.id);
|
|
@@ -81401,8 +82221,8 @@ ${body}`
|
|
|
81401
82221
|
errors.push(`${agent.id}: custom agent requires "custom_model" field`);
|
|
81402
82222
|
continue;
|
|
81403
82223
|
}
|
|
81404
|
-
const nativeFile =
|
|
81405
|
-
const wasNative = existingAgents[agent.id]?.native || configAgents[agent.id]?.native ||
|
|
82224
|
+
const nativeFile = join93(root, ".claude", "agents", `${agent.id}.md`);
|
|
82225
|
+
const wasNative = existingAgents[agent.id]?.native || configAgents[agent.id]?.native || existsSync74(nativeFile);
|
|
81406
82226
|
if (wasNative) {
|
|
81407
82227
|
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.`);
|
|
81408
82228
|
continue;
|
|
@@ -81417,10 +82237,10 @@ ${body}`
|
|
|
81417
82237
|
};
|
|
81418
82238
|
customCreated.push(agent.id);
|
|
81419
82239
|
if (agent.instructions) {
|
|
81420
|
-
const instrDir =
|
|
82240
|
+
const instrDir = join93(root, ".gossip", "agents", agent.id);
|
|
81421
82241
|
pendingAgentFileWrites.push({
|
|
81422
82242
|
dir: instrDir,
|
|
81423
|
-
path:
|
|
82243
|
+
path: join93(instrDir, "instructions.md"),
|
|
81424
82244
|
content: agent.instructions
|
|
81425
82245
|
});
|
|
81426
82246
|
}
|
|
@@ -81439,8 +82259,8 @@ ${body}`
|
|
|
81439
82259
|
return { content: [{ type: "text", text: `Invalid config: ${err.message}` }] };
|
|
81440
82260
|
}
|
|
81441
82261
|
flushStagedAgentFileWrites(pendingAgentFileWrites, { mkdirSync: mkdirSync45, writeFileSync: writeFileSync38 });
|
|
81442
|
-
mkdirSync45(
|
|
81443
|
-
writeFileSync38(
|
|
82262
|
+
mkdirSync45(join93(root, ".gossip"), { recursive: true });
|
|
82263
|
+
writeFileSync38(join93(root, ".gossip", "config.json"), JSON.stringify(config2, null, 2));
|
|
81444
82264
|
let hookSummary = "";
|
|
81445
82265
|
try {
|
|
81446
82266
|
const { installWorktreeSandboxHook: installWorktreeSandboxHook2, writeOrchestratorRoleMarker: writeOrchestratorRoleMarker2 } = (init_src4(), __toCommonJS(src_exports3));
|
|
@@ -81543,8 +82363,8 @@ ${body}`
|
|
|
81543
82363
|
}
|
|
81544
82364
|
}
|
|
81545
82365
|
const agentList = Object.entries(config2.agents).map(([id, a]) => `- ${id}: ${a.provider}/${a.model} (${a.preset || "custom"})${a.native ? " \u2014 native" : ""}`).join("\n");
|
|
81546
|
-
const rulesDir =
|
|
81547
|
-
const rulesFile =
|
|
82366
|
+
const rulesDir = join93(root, env.rulesDir);
|
|
82367
|
+
const rulesFile = join93(root, env.rulesFile);
|
|
81548
82368
|
mkdirSync45(rulesDir, { recursive: true });
|
|
81549
82369
|
writeFileSync38(rulesFile, generateRulesContent(
|
|
81550
82370
|
agentList,
|
|
@@ -81853,11 +82673,11 @@ The original signal remains in the audit log but will be excluded from scoring.`
|
|
|
81853
82673
|
const fid = finding_id.trim();
|
|
81854
82674
|
const cwd = process.cwd();
|
|
81855
82675
|
const findingsPath = require("path").join(cwd, ".gossip", "implementation-findings.jsonl");
|
|
81856
|
-
const { readFileSync:
|
|
81857
|
-
if (!
|
|
82676
|
+
const { readFileSync: readFileSync70, existsSync: existsSync74, writeFileSync: writeFileSync38, renameSync: renameSync18 } = require("fs");
|
|
82677
|
+
if (!existsSync74(findingsPath)) {
|
|
81858
82678
|
return { content: [{ type: "text", text: `No implementation-findings.jsonl found at ${findingsPath}` }] };
|
|
81859
82679
|
}
|
|
81860
|
-
const lines =
|
|
82680
|
+
const lines = readFileSync70(findingsPath, "utf-8").split("\n");
|
|
81861
82681
|
let matched = false;
|
|
81862
82682
|
let alreadyTarget = false;
|
|
81863
82683
|
let matchedEntry = null;
|
|
@@ -81945,18 +82765,18 @@ The original signal remains in the audit log but will be excluded from scoring.`
|
|
|
81945
82765
|
return { content: [{ type: "text", text: "Error: consensus_id is required for bulk_from_consensus." }] };
|
|
81946
82766
|
}
|
|
81947
82767
|
try {
|
|
81948
|
-
const { readFileSync:
|
|
81949
|
-
const { join:
|
|
81950
|
-
const reportPath =
|
|
82768
|
+
const { readFileSync: readFileSync70 } = await import("fs");
|
|
82769
|
+
const { join: join93 } = await import("path");
|
|
82770
|
+
const reportPath = join93(process.cwd(), ".gossip", "consensus-reports", `${consensus_id}.json`);
|
|
81951
82771
|
let report;
|
|
81952
82772
|
try {
|
|
81953
|
-
report = JSON.parse(
|
|
82773
|
+
report = JSON.parse(readFileSync70(reportPath, "utf-8"));
|
|
81954
82774
|
} catch {
|
|
81955
82775
|
return { content: [{ type: "text", text: `Error: consensus report not found: ${consensus_id}` }] };
|
|
81956
82776
|
}
|
|
81957
82777
|
const existingFindingIds = /* @__PURE__ */ new Set();
|
|
81958
82778
|
try {
|
|
81959
|
-
const perfPath =
|
|
82779
|
+
const perfPath = join93(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
81960
82780
|
const { readJsonlWithRotated: readJsonlRotated2570 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
81961
82781
|
const lines = readJsonlRotated2570(perfPath).split("\n").filter(Boolean);
|
|
81962
82782
|
for (const line of lines) {
|
|
@@ -82571,7 +83391,7 @@ These will influence future agent selection via dispatch weighting.`;
|
|
|
82571
83391
|
return null;
|
|
82572
83392
|
}
|
|
82573
83393
|
})();
|
|
82574
|
-
const result = await resolveFindings2(process.cwd(), { full, sinceSha, lineAnchored: cfg?.consensus?.resolverLineAnchored ??
|
|
83394
|
+
const result = await resolveFindings2(process.cwd(), { full, sinceSha, lineAnchored: cfg?.consensus?.resolverLineAnchored ?? true });
|
|
82575
83395
|
if (!result.ok) {
|
|
82576
83396
|
return { content: [{ type: "text", text: `Resolver skipped: ${result.reason} (another resolver run in progress; try again in a moment).` }] };
|
|
82577
83397
|
}
|
|
@@ -82591,7 +83411,7 @@ These will influence future agent selection via dispatch weighting.`;
|
|
|
82591
83411
|
if (nonZeroSkips.length > 0) {
|
|
82592
83412
|
lines.push(` skipped: ${nonZeroSkips.map(([k, n]) => `${k}=${n}`).join(", ")}`);
|
|
82593
83413
|
if ((result.skipReasons?.lineAnchoredOff ?? 0) > 0) {
|
|
82594
|
-
lines.push(` (lineAnchoredOff:
|
|
83414
|
+
lines.push(` (lineAnchoredOff: consensus.resolverLineAnchored is explicitly false in your config; set it to true or remove it \u2014 it now defaults on \u2014 to resolve present-elsewhere findings as stale_anchor)`);
|
|
82595
83415
|
}
|
|
82596
83416
|
}
|
|
82597
83417
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
@@ -83004,16 +83824,16 @@ ${preview}` }]
|
|
|
83004
83824
|
const { SkillGapTracker: SkillGapTracker2, parseSkillFrontmatter: parseSkillFrontmatter2, normalizeSkillName: normalizeSkillName2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
83005
83825
|
const tracker = new SkillGapTracker2(process.cwd());
|
|
83006
83826
|
if (skills && skills.length > 0) {
|
|
83007
|
-
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45, existsSync:
|
|
83008
|
-
const { join:
|
|
83009
|
-
const dir =
|
|
83827
|
+
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45, existsSync: existsSync74, readFileSync: readFileSync70 } = require("fs");
|
|
83828
|
+
const { join: join93 } = require("path");
|
|
83829
|
+
const dir = join93(process.cwd(), ".gossip", "skills");
|
|
83010
83830
|
mkdirSync45(dir, { recursive: true });
|
|
83011
83831
|
const results = [];
|
|
83012
83832
|
for (const sk of skills) {
|
|
83013
83833
|
const name = normalizeSkillName2(sk.name);
|
|
83014
|
-
const filePath =
|
|
83015
|
-
if (
|
|
83016
|
-
const existing =
|
|
83834
|
+
const filePath = join93(dir, `${name}.md`);
|
|
83835
|
+
if (existsSync74(filePath)) {
|
|
83836
|
+
const existing = readFileSync70(filePath, "utf-8");
|
|
83017
83837
|
const fm = parseSkillFrontmatter2(existing);
|
|
83018
83838
|
if (fm) {
|
|
83019
83839
|
if (fm.generated_by === "manual") {
|
|
@@ -83737,7 +84557,8 @@ Paste this entire block into any Agent() prompt that should produce parseable fi
|
|
|
83737
84557
|
{ name: "gossip_watch", desc: "Pull signals recorded since a cursor timestamp. Stateless, cursor-based; max 24h lookback. Use to see consensus signals as they land." },
|
|
83738
84558
|
{ name: "gossip_reload", desc: "Terminate MCP server so Claude Code respawns with fresh bundle. Use after npm run build:mcp." },
|
|
83739
84559
|
{ name: "gossip_format", desc: "Return the CONSENSUS_OUTPUT_FORMAT block to paste into ad-hoc Agent() prompts so native subagents emit parseable <agent_finding> tags." },
|
|
83740
|
-
{ name: "gossip_bug_feedback", desc: "File a GitHub issue on the gossipcat repo from an in-session bug report. Dedupes against open issues." }
|
|
84560
|
+
{ name: "gossip_bug_feedback", desc: "File a GitHub issue on the gossipcat repo from an in-session bug report. Dedupes against open issues." },
|
|
84561
|
+
{ name: "gossip_ask_back", desc: 'Re-engage an agent after a fabrication for first-person root-cause analysis. action:"ask" dispatches the introspection prompt; action:"record" logs the answer.' }
|
|
83741
84562
|
];
|
|
83742
84563
|
const list = tools.map((t) => `- ${t.name}: ${t.desc}`).join("\n");
|
|
83743
84564
|
return { content: [{ type: "text", text: `Gossipcat Tools (${tools.length}):
|
|
@@ -83853,9 +84674,9 @@ ${p.user}
|
|
|
83853
84674
|
max_events: external_exports.number().int().positive().max(WATCH_MAX_EVENTS).optional().describe(`Cap events returned (default ${WATCH_MAX_EVENTS}).`)
|
|
83854
84675
|
},
|
|
83855
84676
|
async ({ cursor, max_events }) => {
|
|
83856
|
-
const { join:
|
|
84677
|
+
const { join: join93 } = await import("node:path");
|
|
83857
84678
|
const { readJsonlWithRotated: readJsonlWithRotated2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
83858
|
-
const perfPath =
|
|
84679
|
+
const perfPath = join93(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
83859
84680
|
const raw = readJsonlWithRotated2(perfPath);
|
|
83860
84681
|
const result = filterWatchEvents(raw, { cursor, maxEvents: max_events });
|
|
83861
84682
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
@@ -84002,10 +84823,10 @@ async function startHttpMcpTransport() {
|
|
|
84002
84823
|
}
|
|
84003
84824
|
let body;
|
|
84004
84825
|
if (req.method === "POST") {
|
|
84005
|
-
const raw = await new Promise((
|
|
84826
|
+
const raw = await new Promise((resolve33, reject) => {
|
|
84006
84827
|
const chunks = [];
|
|
84007
84828
|
req.on("data", (c) => chunks.push(c));
|
|
84008
|
-
req.on("end", () =>
|
|
84829
|
+
req.on("end", () => resolve33(Buffer.concat(chunks).toString("utf-8")));
|
|
84009
84830
|
req.on("error", reject);
|
|
84010
84831
|
});
|
|
84011
84832
|
try {
|