gossipcat 0.6.6 → 0.6.7
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 +1457 -664
- package/docs/HANDBOOK.md +11 -3
- package/package.json +1 -1
- 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 });
|
|
@@ -7009,9 +7009,9 @@ var init_log = __esm({
|
|
|
7009
7009
|
function statePath(projectRoot) {
|
|
7010
7010
|
return (0, import_path4.join)(projectRoot, ".gossip", "auth-state.json");
|
|
7011
7011
|
}
|
|
7012
|
-
function readState(
|
|
7012
|
+
function readState(path8) {
|
|
7013
7013
|
try {
|
|
7014
|
-
return JSON.parse((0, import_fs5.readFileSync)(
|
|
7014
|
+
return JSON.parse((0, import_fs5.readFileSync)(path8, "utf-8"));
|
|
7015
7015
|
} catch {
|
|
7016
7016
|
return {};
|
|
7017
7017
|
}
|
|
@@ -7020,33 +7020,33 @@ function recordAuthFailure(projectRoot, provider, status) {
|
|
|
7020
7020
|
if (!projectRoot) return;
|
|
7021
7021
|
if (!PROVIDER_RE.test(provider)) return;
|
|
7022
7022
|
try {
|
|
7023
|
-
const
|
|
7024
|
-
const dir = (0, import_path4.join)(
|
|
7023
|
+
const path8 = statePath(projectRoot);
|
|
7024
|
+
const dir = (0, import_path4.join)(path8, "..");
|
|
7025
7025
|
if (!(0, import_fs5.existsSync)(dir)) (0, import_fs5.mkdirSync)(dir, { recursive: true });
|
|
7026
|
-
const existing = readState(
|
|
7026
|
+
const existing = readState(path8);
|
|
7027
7027
|
existing[provider] = { status, at: Date.now() };
|
|
7028
|
-
(0, import_fs5.writeFileSync)(
|
|
7028
|
+
(0, import_fs5.writeFileSync)(path8, JSON.stringify(existing, null, 2));
|
|
7029
7029
|
} catch {
|
|
7030
7030
|
}
|
|
7031
7031
|
}
|
|
7032
7032
|
function clearAuthFailure(projectRoot, provider) {
|
|
7033
7033
|
if (!projectRoot) return;
|
|
7034
7034
|
try {
|
|
7035
|
-
const
|
|
7036
|
-
if (!(0, import_fs5.existsSync)(
|
|
7037
|
-
const existing = readState(
|
|
7035
|
+
const path8 = statePath(projectRoot);
|
|
7036
|
+
if (!(0, import_fs5.existsSync)(path8)) return;
|
|
7037
|
+
const existing = readState(path8);
|
|
7038
7038
|
if (!(provider in existing)) return;
|
|
7039
7039
|
delete existing[provider];
|
|
7040
|
-
(0, import_fs5.writeFileSync)(
|
|
7040
|
+
(0, import_fs5.writeFileSync)(path8, JSON.stringify(existing, null, 2));
|
|
7041
7041
|
} catch {
|
|
7042
7042
|
}
|
|
7043
7043
|
}
|
|
7044
7044
|
function readRecentAuthFailures(projectRoot, ttlMs = 6 * 60 * 60 * 1e3) {
|
|
7045
7045
|
if (!projectRoot) return [];
|
|
7046
7046
|
try {
|
|
7047
|
-
const
|
|
7048
|
-
if (!(0, import_fs5.existsSync)(
|
|
7049
|
-
const state = readState(
|
|
7047
|
+
const path8 = statePath(projectRoot);
|
|
7048
|
+
if (!(0, import_fs5.existsSync)(path8)) return [];
|
|
7049
|
+
const state = readState(path8);
|
|
7050
7050
|
const now = Date.now();
|
|
7051
7051
|
const out = [];
|
|
7052
7052
|
for (const [provider, entry] of Object.entries(state)) {
|
|
@@ -13951,7 +13951,7 @@ var init_gossip_agent = __esm({
|
|
|
13951
13951
|
}
|
|
13952
13952
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
13953
13953
|
connect() {
|
|
13954
|
-
return new Promise((
|
|
13954
|
+
return new Promise((resolve33, reject) => {
|
|
13955
13955
|
const ws = new wrapper_default(this.config.relayUrl);
|
|
13956
13956
|
const timeout = setTimeout(() => {
|
|
13957
13957
|
ws.removeAllListeners();
|
|
@@ -13984,7 +13984,7 @@ var init_gossip_agent = __esm({
|
|
|
13984
13984
|
ws.on("error", (err) => this.emit("error", err));
|
|
13985
13985
|
this.startKeepAlive();
|
|
13986
13986
|
this.emit("connect", msg.sessionId);
|
|
13987
|
-
|
|
13987
|
+
resolve33();
|
|
13988
13988
|
} else if (msg.type === "error") {
|
|
13989
13989
|
clearTimeout(timeout);
|
|
13990
13990
|
ws.removeAllListeners();
|
|
@@ -14010,7 +14010,7 @@ var init_gossip_agent = __esm({
|
|
|
14010
14010
|
this.reconnectTimer = null;
|
|
14011
14011
|
}
|
|
14012
14012
|
if (!this.ws) return;
|
|
14013
|
-
return new Promise((
|
|
14013
|
+
return new Promise((resolve33) => {
|
|
14014
14014
|
this.intentionalDisconnect = true;
|
|
14015
14015
|
this._connected = false;
|
|
14016
14016
|
const ws = this.ws;
|
|
@@ -14021,7 +14021,7 @@ var init_gossip_agent = __esm({
|
|
|
14021
14021
|
settled = true;
|
|
14022
14022
|
this.intentionalDisconnect = false;
|
|
14023
14023
|
this.emit("disconnect", code);
|
|
14024
|
-
|
|
14024
|
+
resolve33();
|
|
14025
14025
|
};
|
|
14026
14026
|
const timer = setTimeout(() => done(1e3), 2e3);
|
|
14027
14027
|
ws.once("close", (code) => {
|
|
@@ -14060,8 +14060,8 @@ var init_gossip_agent = __esm({
|
|
|
14060
14060
|
throw new Error("Not connected to relay");
|
|
14061
14061
|
}
|
|
14062
14062
|
const encoded = Buffer.from(this.codec.encode(envelope));
|
|
14063
|
-
return new Promise((
|
|
14064
|
-
this.ws.send(encoded, (err) => err ? reject(err) :
|
|
14063
|
+
return new Promise((resolve33, reject) => {
|
|
14064
|
+
this.ws.send(encoded, (err) => err ? reject(err) : resolve33());
|
|
14065
14065
|
});
|
|
14066
14066
|
}
|
|
14067
14067
|
// ─── Internal ────────────────────────────────────────────────────────────────
|
|
@@ -14541,7 +14541,7 @@ ${context}` : ""}
|
|
|
14541
14541
|
this.memoryQueryCalled = true;
|
|
14542
14542
|
}
|
|
14543
14543
|
const requestId = (0, import_crypto6.randomUUID)();
|
|
14544
|
-
const resultPromise = new Promise((
|
|
14544
|
+
const resultPromise = new Promise((resolve33, reject) => {
|
|
14545
14545
|
const timer = setTimeout(() => {
|
|
14546
14546
|
if (this.pendingToolCalls.has(requestId)) {
|
|
14547
14547
|
this.pendingToolCalls.delete(requestId);
|
|
@@ -14552,7 +14552,7 @@ ${context}` : ""}
|
|
|
14552
14552
|
this.pendingToolCalls.set(requestId, {
|
|
14553
14553
|
resolve: (r) => {
|
|
14554
14554
|
clearTimeout(timer);
|
|
14555
|
-
|
|
14555
|
+
resolve33(r);
|
|
14556
14556
|
},
|
|
14557
14557
|
reject: (e) => {
|
|
14558
14558
|
clearTimeout(timer);
|
|
@@ -15566,8 +15566,8 @@ var init_parseUtil = __esm({
|
|
|
15566
15566
|
init_errors2();
|
|
15567
15567
|
init_en();
|
|
15568
15568
|
makeIssue2 = (params) => {
|
|
15569
|
-
const { data, path:
|
|
15570
|
-
const fullPath = [...
|
|
15569
|
+
const { data, path: path8, errorMaps, issueData } = params;
|
|
15570
|
+
const fullPath = [...path8, ...issueData.path || []];
|
|
15571
15571
|
const fullIssue = {
|
|
15572
15572
|
...issueData,
|
|
15573
15573
|
path: fullPath
|
|
@@ -15878,11 +15878,11 @@ var init_types = __esm({
|
|
|
15878
15878
|
init_parseUtil();
|
|
15879
15879
|
init_util();
|
|
15880
15880
|
ParseInputLazyPath2 = class {
|
|
15881
|
-
constructor(parent, value,
|
|
15881
|
+
constructor(parent, value, path8, key) {
|
|
15882
15882
|
this._cachedPath = [];
|
|
15883
15883
|
this.parent = parent;
|
|
15884
15884
|
this.data = value;
|
|
15885
|
-
this._path =
|
|
15885
|
+
this._path = path8;
|
|
15886
15886
|
this._key = key;
|
|
15887
15887
|
}
|
|
15888
15888
|
get path() {
|
|
@@ -19916,7 +19916,7 @@ ${truncateAtLine(fullDiff, 3e3)}`;
|
|
|
19916
19916
|
}
|
|
19917
19917
|
async requestPeerReview(callerId, diff, testResult) {
|
|
19918
19918
|
const requestId = (0, import_crypto8.randomUUID)();
|
|
19919
|
-
const reviewPromise = new Promise((
|
|
19919
|
+
const reviewPromise = new Promise((resolve33, reject) => {
|
|
19920
19920
|
const timer = setTimeout(() => {
|
|
19921
19921
|
this.pendingReviews.delete(requestId);
|
|
19922
19922
|
reject(new Error("Review timed out"));
|
|
@@ -19925,7 +19925,7 @@ ${truncateAtLine(fullDiff, 3e3)}`;
|
|
|
19925
19925
|
this.pendingReviews.set(requestId, {
|
|
19926
19926
|
resolve: (r) => {
|
|
19927
19927
|
clearTimeout(timer);
|
|
19928
|
-
|
|
19928
|
+
resolve33(r);
|
|
19929
19929
|
},
|
|
19930
19930
|
reject: (e) => {
|
|
19931
19931
|
clearTimeout(timer);
|
|
@@ -20296,7 +20296,14 @@ var init_consensus_types = __esm({
|
|
|
20296
20296
|
"transport_failure",
|
|
20297
20297
|
"worktree_isolation_failed",
|
|
20298
20298
|
"auto_verify_attempted",
|
|
20299
|
-
"auto_verify_skipped_misconfigured"
|
|
20299
|
+
"auto_verify_skipped_misconfigured",
|
|
20300
|
+
/**
|
|
20301
|
+
* Orchestrator dispatch-hygiene signals (UNIT 1 — orchestrator signal pipeline).
|
|
20302
|
+
* Tallied as operational; never affect agent accuracy scoring.
|
|
20303
|
+
*/
|
|
20304
|
+
"dispatched_stale_base",
|
|
20305
|
+
"referenced_unreadable_path",
|
|
20306
|
+
"mid_flight_fixup"
|
|
20300
20307
|
]);
|
|
20301
20308
|
}
|
|
20302
20309
|
});
|
|
@@ -20324,21 +20331,21 @@ function extractFrontmatterField(content, field) {
|
|
|
20324
20331
|
return null;
|
|
20325
20332
|
}
|
|
20326
20333
|
function readSkillFreshness(agentId, category, skillRoot) {
|
|
20327
|
-
const
|
|
20328
|
-
if (!(0, import_fs12.existsSync)(
|
|
20329
|
-
return { boundAt: null, status: null, path:
|
|
20334
|
+
const path8 = resolveSkillFilePath(agentId, category, skillRoot);
|
|
20335
|
+
if (!(0, import_fs12.existsSync)(path8)) {
|
|
20336
|
+
return { boundAt: null, status: null, path: path8, regressedFromPassedAt: null };
|
|
20330
20337
|
}
|
|
20331
20338
|
let content;
|
|
20332
20339
|
try {
|
|
20333
|
-
content = (0, import_fs12.readFileSync)(
|
|
20340
|
+
content = (0, import_fs12.readFileSync)(path8, "utf-8");
|
|
20334
20341
|
} catch {
|
|
20335
|
-
return { boundAt: null, status: null, path:
|
|
20342
|
+
return { boundAt: null, status: null, path: path8, regressedFromPassedAt: null };
|
|
20336
20343
|
}
|
|
20337
20344
|
const boundAt = extractFrontmatterField(content, "bound_at");
|
|
20338
20345
|
const rawStatus = extractFrontmatterField(content, "status");
|
|
20339
20346
|
const status = rawStatus === null ? null : coerceStatus(rawStatus);
|
|
20340
20347
|
const regressedFromPassedAt = extractFrontmatterField(content, "regressed_from_passed_at");
|
|
20341
|
-
return { boundAt, status, path:
|
|
20348
|
+
return { boundAt, status, path: path8, regressedFromPassedAt };
|
|
20342
20349
|
}
|
|
20343
20350
|
function computeCooldown(input) {
|
|
20344
20351
|
let status;
|
|
@@ -21928,15 +21935,15 @@ function classifyForAggregate(signal) {
|
|
|
21928
21935
|
}
|
|
21929
21936
|
}
|
|
21930
21937
|
function readAggregateIndex(projectRoot) {
|
|
21931
|
-
const
|
|
21932
|
-
if (!(0, import_fs14.existsSync)(
|
|
21938
|
+
const path8 = (0, import_path14.join)(projectRoot, ".gossip", SIDECAR_FILENAME);
|
|
21939
|
+
if (!(0, import_fs14.existsSync)(path8)) {
|
|
21933
21940
|
cachedAggregateData = null;
|
|
21934
21941
|
cachedAggregateMtimeMs = 0;
|
|
21935
21942
|
return null;
|
|
21936
21943
|
}
|
|
21937
21944
|
let mtimeMs = 0;
|
|
21938
21945
|
try {
|
|
21939
|
-
mtimeMs = (0, import_fs14.statSync)(
|
|
21946
|
+
mtimeMs = (0, import_fs14.statSync)(path8).mtimeMs;
|
|
21940
21947
|
} catch (err) {
|
|
21941
21948
|
logSidecarError("stat", err);
|
|
21942
21949
|
return null;
|
|
@@ -21946,7 +21953,7 @@ function readAggregateIndex(projectRoot) {
|
|
|
21946
21953
|
}
|
|
21947
21954
|
let raw;
|
|
21948
21955
|
try {
|
|
21949
|
-
raw = (0, import_fs14.readFileSync)(
|
|
21956
|
+
raw = (0, import_fs14.readFileSync)(path8, "utf-8");
|
|
21950
21957
|
} catch (err) {
|
|
21951
21958
|
logSidecarError("read", err);
|
|
21952
21959
|
return null;
|
|
@@ -21982,14 +21989,14 @@ function readAggregateIndex(projectRoot) {
|
|
|
21982
21989
|
return result;
|
|
21983
21990
|
}
|
|
21984
21991
|
function writeAggregateIndex(projectRoot, data) {
|
|
21985
|
-
const
|
|
21992
|
+
const path8 = (0, import_path14.join)(projectRoot, ".gossip", SIDECAR_FILENAME);
|
|
21986
21993
|
try {
|
|
21987
|
-
(0, import_fs14.mkdirSync)((0, import_path14.dirname)(
|
|
21988
|
-
const tmp =
|
|
21994
|
+
(0, import_fs14.mkdirSync)((0, import_path14.dirname)(path8), { recursive: true });
|
|
21995
|
+
const tmp = path8 + ".tmp";
|
|
21989
21996
|
(0, import_fs14.writeFileSync)(tmp, JSON.stringify(data, null, 2) + "\n");
|
|
21990
|
-
(0, import_fs14.renameSync)(tmp,
|
|
21997
|
+
(0, import_fs14.renameSync)(tmp, path8);
|
|
21991
21998
|
cachedAggregateData = data;
|
|
21992
|
-
cachedAggregateMtimeMs = (0, import_fs14.statSync)(
|
|
21999
|
+
cachedAggregateMtimeMs = (0, import_fs14.statSync)(path8).mtimeMs;
|
|
21993
22000
|
} catch (err) {
|
|
21994
22001
|
logSidecarError("write", err);
|
|
21995
22002
|
}
|
|
@@ -22375,14 +22382,14 @@ var init_performance_reader = __esm({
|
|
|
22375
22382
|
*/
|
|
22376
22383
|
getSkillIndexEnabledMap() {
|
|
22377
22384
|
if (this.skillIndexCache !== void 0) return this.skillIndexCache;
|
|
22378
|
-
const
|
|
22385
|
+
const path8 = (0, import_path15.join)(this.projectRoot, ".gossip", "skill-index.json");
|
|
22379
22386
|
let parsed;
|
|
22380
22387
|
try {
|
|
22381
|
-
if (!(0, import_fs15.existsSync)(
|
|
22388
|
+
if (!(0, import_fs15.existsSync)(path8)) {
|
|
22382
22389
|
this.skillIndexCache = null;
|
|
22383
22390
|
return null;
|
|
22384
22391
|
}
|
|
22385
|
-
parsed = JSON.parse((0, import_fs15.readFileSync)(
|
|
22392
|
+
parsed = JSON.parse((0, import_fs15.readFileSync)(path8, "utf-8"));
|
|
22386
22393
|
} catch {
|
|
22387
22394
|
this.skillIndexCache = null;
|
|
22388
22395
|
return null;
|
|
@@ -23776,7 +23783,14 @@ var init_performance_writer = __esm({
|
|
|
23776
23783
|
"relay_findings_dropped",
|
|
23777
23784
|
// Phase A self-telemetry: collect-end reconciliation detected fewer signals
|
|
23778
23785
|
// written than findings in the consensus report. Observability-only.
|
|
23779
|
-
"signal_loss_suspected"
|
|
23786
|
+
"signal_loss_suspected",
|
|
23787
|
+
// UNIT 1 orchestrator signal pipeline: dispatch-hygiene precondition signals.
|
|
23788
|
+
// Operational-only (tallied, never scored). Emitted by orchestrator-preconditions.ts
|
|
23789
|
+
// when a dispatch-hygiene failure is detected (stale base, unreadable reference
|
|
23790
|
+
// paths, mid-flight commits during a consensus round).
|
|
23791
|
+
"dispatched_stale_base",
|
|
23792
|
+
"referenced_unreadable_path",
|
|
23793
|
+
"mid_flight_fixup"
|
|
23780
23794
|
]);
|
|
23781
23795
|
SYSTEM_SENTINEL_AGENT_ID = "_system";
|
|
23782
23796
|
rowsWrittenSinceCheck = 0;
|
|
@@ -24489,13 +24503,13 @@ function resolveSkill(agentId, skill, projectRoot) {
|
|
|
24489
24503
|
if ((0, import_fs19.existsSync)(candidate)) {
|
|
24490
24504
|
try {
|
|
24491
24505
|
const content = (0, import_fs19.readFileSync)(candidate, "utf-8");
|
|
24492
|
-
let
|
|
24506
|
+
let path8;
|
|
24493
24507
|
try {
|
|
24494
|
-
|
|
24508
|
+
path8 = (0, import_fs19.realpathSync)(candidate);
|
|
24495
24509
|
} catch {
|
|
24496
|
-
|
|
24510
|
+
path8 = candidate;
|
|
24497
24511
|
}
|
|
24498
|
-
return { content, path:
|
|
24512
|
+
return { content, path: path8 };
|
|
24499
24513
|
} catch (err) {
|
|
24500
24514
|
log("skill-loader", `Failed to read skill file ${candidate}: ${err?.message ?? err}`);
|
|
24501
24515
|
continue;
|
|
@@ -25599,14 +25613,14 @@ ${cleanSummary}` : cleanSummary;
|
|
|
25599
25613
|
const citations = [];
|
|
25600
25614
|
let m;
|
|
25601
25615
|
while ((m = fileRegex.exec(body)) !== null) {
|
|
25602
|
-
const
|
|
25616
|
+
const path8 = m[1];
|
|
25603
25617
|
const before = body.slice(Math.max(0, m.index - 8), m.index + 1);
|
|
25604
|
-
if (/https?:\/\//.test(before) || /https?:\/\//.test(
|
|
25618
|
+
if (/https?:\/\//.test(before) || /https?:\/\//.test(path8)) continue;
|
|
25605
25619
|
const line = m[2] ? parseInt(m[2], 10) : void 0;
|
|
25606
|
-
const key = line !== void 0 ? `${
|
|
25620
|
+
const key = line !== void 0 ? `${path8}:${line}` : path8;
|
|
25607
25621
|
if (seen.has(key)) continue;
|
|
25608
25622
|
seen.add(key);
|
|
25609
|
-
citations.push({ path:
|
|
25623
|
+
citations.push({ path: path8, line, key });
|
|
25610
25624
|
}
|
|
25611
25625
|
const roots = [this.projectRoot, ...resolutionRoots ?? []];
|
|
25612
25626
|
const unverified = [];
|
|
@@ -29268,12 +29282,12 @@ async function getUncategorizedStatusLine(projectRoot, opts) {
|
|
|
29268
29282
|
let mostRecentText = "";
|
|
29269
29283
|
let mostRecentTs = 0;
|
|
29270
29284
|
const uncatPath = (0, import_path31.join)(projectRoot, ".gossip", "uncategorized-findings.jsonl");
|
|
29271
|
-
const scanFile = (filePath) => new Promise((
|
|
29285
|
+
const scanFile = (filePath) => new Promise((resolve33) => {
|
|
29272
29286
|
if (!(0, import_fs29.existsSync)(filePath)) {
|
|
29273
|
-
return
|
|
29287
|
+
return resolve33();
|
|
29274
29288
|
}
|
|
29275
29289
|
const stream = (0, import_fs29.createReadStream)(filePath, { encoding: "utf8" });
|
|
29276
|
-
stream.on("error", () =>
|
|
29290
|
+
stream.on("error", () => resolve33());
|
|
29277
29291
|
const rl = (0, import_readline.createInterface)({ input: stream, crlfDelay: Infinity });
|
|
29278
29292
|
rl.on("line", (line) => {
|
|
29279
29293
|
if (!line) return;
|
|
@@ -29290,8 +29304,8 @@ async function getUncategorizedStatusLine(projectRoot, opts) {
|
|
|
29290
29304
|
} catch {
|
|
29291
29305
|
}
|
|
29292
29306
|
});
|
|
29293
|
-
rl.on("close",
|
|
29294
|
-
rl.on("error", () =>
|
|
29307
|
+
rl.on("close", resolve33);
|
|
29308
|
+
rl.on("error", () => resolve33());
|
|
29295
29309
|
});
|
|
29296
29310
|
await scanFile(uncatPath);
|
|
29297
29311
|
if ((0, import_fs29.existsSync)(uncatPath + ".1")) {
|
|
@@ -29480,6 +29494,26 @@ var init_consensus_engine = __esm({
|
|
|
29480
29494
|
if (!report.warnings) report.warnings = [];
|
|
29481
29495
|
report.warnings.push(entry);
|
|
29482
29496
|
}
|
|
29497
|
+
/**
|
|
29498
|
+
* Idempotent helper: appends the UNSCORED ROUND banner to report.summary and
|
|
29499
|
+
* records a zero_tags warning when any agents emitted zero <agent_finding> tags.
|
|
29500
|
+
* Safe to call multiple times — skips if the banner is already present or if
|
|
29501
|
+
* zeroTagAgents is empty/absent.
|
|
29502
|
+
* Called at each finalization point: run(), runSelectedCrossReview(), and
|
|
29503
|
+
* synthesizeWithCrossReview() — so ALL synthesize paths surface the banner.
|
|
29504
|
+
*/
|
|
29505
|
+
surfaceZeroTagBanner(report) {
|
|
29506
|
+
if (!report.zeroTagAgents?.length) return;
|
|
29507
|
+
if (report.summary.includes("UNSCORED ROUND")) return;
|
|
29508
|
+
const n = report.zeroTagAgents.length;
|
|
29509
|
+
const overflow = report.zeroTagOverflow ?? 0;
|
|
29510
|
+
const list = report.zeroTagAgents.join(", ");
|
|
29511
|
+
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})`;
|
|
29512
|
+
report.summary += `
|
|
29513
|
+
\u26A0\uFE0F ${evidence}
|
|
29514
|
+
`;
|
|
29515
|
+
this.appendReportWarning(report, "zero_tags", evidence);
|
|
29516
|
+
}
|
|
29483
29517
|
/** True when a PerformanceReader is available for orchestrator-selected cross-review (Step 3). */
|
|
29484
29518
|
get hasPerformanceReader() {
|
|
29485
29519
|
return this.config.performanceReader !== void 0;
|
|
@@ -29730,6 +29764,7 @@ var init_consensus_engine = __esm({
|
|
|
29730
29764
|
);
|
|
29731
29765
|
report.unverified = enriched;
|
|
29732
29766
|
report.summary = this.formatReport(report.confirmed, report.disputed, report.unverified, report.unique, report.newFindings, successful.length, report.rounds, timing, report.insights);
|
|
29767
|
+
this.surfaceZeroTagBanner(report);
|
|
29733
29768
|
return report;
|
|
29734
29769
|
}
|
|
29735
29770
|
/**
|
|
@@ -30107,7 +30142,7 @@ Return only valid JSON.${skillsBlock}`;
|
|
|
30107
30142
|
}
|
|
30108
30143
|
log(
|
|
30109
30144
|
"consensus",
|
|
30110
|
-
`\u26A0 agent "${r.agentId}" emitted ZERO tags \u2014 falling back to bullet parsing.
|
|
30145
|
+
`\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
30146
|
);
|
|
30112
30147
|
} else {
|
|
30113
30148
|
const offending = Object.entries(parseResult.droppedUnknownType).map(([t, n]) => `${t}:${n}`).join(",") || "(missing type attribute)";
|
|
@@ -31547,7 +31582,9 @@ ${safeSnippet}
|
|
|
31547
31582
|
}
|
|
31548
31583
|
if (findingSeq === 0) {
|
|
31549
31584
|
log("consensus", "runSelectedCrossReview: no structured findings extracted; synthesizing without cross-review");
|
|
31550
|
-
|
|
31585
|
+
const report2 = await this.synthesize(results, [], consensusId);
|
|
31586
|
+
this.surfaceZeroTagBanner(report2);
|
|
31587
|
+
return report2;
|
|
31551
31588
|
}
|
|
31552
31589
|
const agentCandidates = successful.map((r) => ({ agentId: r.agentId }));
|
|
31553
31590
|
const assignments = selectCrossReviewers(findingsForSelection, agentCandidates, performanceReader);
|
|
@@ -31555,6 +31592,7 @@ ${safeSnippet}
|
|
|
31555
31592
|
log("consensus", "runSelectedCrossReview: no reviewers selected; synthesizing without cross-review");
|
|
31556
31593
|
const report2 = await this.synthesize(results, [], consensusId);
|
|
31557
31594
|
this.appendReportWarning(report2, "partial_review", "no cross-reviewers selected \u2014 every finding is under-reviewed (0 of target K)");
|
|
31595
|
+
this.surfaceZeroTagBanner(report2);
|
|
31558
31596
|
return report2;
|
|
31559
31597
|
}
|
|
31560
31598
|
const reviewerCountPerFinding = /* @__PURE__ */ new Map();
|
|
@@ -31609,6 +31647,7 @@ ${safeSnippet}
|
|
|
31609
31647
|
assigned: reviewerCountPerFinding.get(f.id) ?? 0,
|
|
31610
31648
|
targetK: findingKMap.get(f.id) ?? 2
|
|
31611
31649
|
}));
|
|
31650
|
+
this.surfaceZeroTagBanner(report);
|
|
31612
31651
|
return report;
|
|
31613
31652
|
}
|
|
31614
31653
|
/**
|
|
@@ -31654,6 +31693,7 @@ ${safeSnippet}
|
|
|
31654
31693
|
`;
|
|
31655
31694
|
this.appendReportWarning(report, "coverage_degraded", evidence);
|
|
31656
31695
|
}
|
|
31696
|
+
this.surfaceZeroTagBanner(report);
|
|
31657
31697
|
if (relayCrossReviewSkipped && relayCrossReviewSkipped.length > 0) {
|
|
31658
31698
|
const lines = ["", "\u26A0\uFE0F Relay cross-review skipped:"];
|
|
31659
31699
|
for (const s of relayCrossReviewSkipped) {
|
|
@@ -34212,11 +34252,11 @@ var init_archetype_catalog = __esm({
|
|
|
34212
34252
|
ArchetypeCatalog = class {
|
|
34213
34253
|
archetypes;
|
|
34214
34254
|
constructor(catalogPath) {
|
|
34215
|
-
const
|
|
34216
|
-
if (!
|
|
34255
|
+
const path8 = catalogPath ?? findArchetypeCatalog();
|
|
34256
|
+
if (!path8) {
|
|
34217
34257
|
throw new Error("archetypes.json not found \u2014 tried bundled dist-mcp/data/, dev ts-node path, and cwd/data/. Reinstall gossipcat.");
|
|
34218
34258
|
}
|
|
34219
|
-
const raw = (0, import_fs34.readFileSync)(
|
|
34259
|
+
const raw = (0, import_fs34.readFileSync)(path8, "utf-8");
|
|
34220
34260
|
this.archetypes = JSON.parse(raw);
|
|
34221
34261
|
}
|
|
34222
34262
|
/** Return all archetype IDs */
|
|
@@ -34270,8 +34310,7 @@ function findBundledHook() {
|
|
|
34270
34310
|
const candidates = [
|
|
34271
34311
|
(0, import_path37.resolve)(__dirname, "assets", "hooks", HOOK_FILENAME),
|
|
34272
34312
|
(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)
|
|
34313
|
+
(0, import_path37.resolve)(__dirname, "..", "assets", "hooks", HOOK_FILENAME)
|
|
34275
34314
|
];
|
|
34276
34315
|
for (const p of candidates) {
|
|
34277
34316
|
if ((0, import_fs35.existsSync)(p)) return p;
|
|
@@ -34331,11 +34370,6 @@ function installWorktreeSandboxHook(projectRoot) {
|
|
|
34331
34370
|
try {
|
|
34332
34371
|
const bundled = findBundledHook();
|
|
34333
34372
|
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
34373
|
const settingsPath = (0, import_path37.join)(projectRoot, ".claude", "settings.json");
|
|
34340
34374
|
(0, import_fs35.mkdirSync)((0, import_path37.dirname)(settingsPath), { recursive: true });
|
|
34341
34375
|
let settings;
|
|
@@ -34348,6 +34382,11 @@ function installWorktreeSandboxHook(projectRoot) {
|
|
|
34348
34382
|
);
|
|
34349
34383
|
return { installed: false, reason: err.message };
|
|
34350
34384
|
}
|
|
34385
|
+
const targetDir = (0, import_path37.join)(projectRoot, ".claude", "hooks");
|
|
34386
|
+
const target = (0, import_path37.join)(targetDir, HOOK_FILENAME);
|
|
34387
|
+
(0, import_fs35.mkdirSync)(targetDir, { recursive: true });
|
|
34388
|
+
(0, import_fs35.copyFileSync)(bundled, target);
|
|
34389
|
+
(0, import_fs35.chmodSync)(target, 493);
|
|
34351
34390
|
const mutated = mergePreToolUseEntry(settings);
|
|
34352
34391
|
if (mutated) {
|
|
34353
34392
|
(0, import_fs35.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
@@ -34381,8 +34420,7 @@ function findDisciplineHook(filename) {
|
|
|
34381
34420
|
const candidates = [
|
|
34382
34421
|
(0, import_path37.resolve)(__dirname, "assets", "hooks", DISCIPLINE_HOOK_DIR, filename),
|
|
34383
34422
|
(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)
|
|
34423
|
+
(0, import_path37.resolve)(__dirname, "..", "assets", "hooks", DISCIPLINE_HOOK_DIR, filename)
|
|
34386
34424
|
];
|
|
34387
34425
|
for (const p of candidates) {
|
|
34388
34426
|
if ((0, import_fs35.existsSync)(p)) return p;
|
|
@@ -34563,18 +34601,6 @@ function installDisciplineHooks(projectRoot) {
|
|
|
34563
34601
|
const installed = [];
|
|
34564
34602
|
const skipped = [];
|
|
34565
34603
|
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
34604
|
const settingsPath = (0, import_path37.join)(projectRoot, ".claude", "settings.local.json");
|
|
34579
34605
|
(0, import_fs35.mkdirSync)((0, import_path37.dirname)(settingsPath), { recursive: true });
|
|
34580
34606
|
let settings;
|
|
@@ -34587,6 +34613,18 @@ function installDisciplineHooks(projectRoot) {
|
|
|
34587
34613
|
);
|
|
34588
34614
|
return { installed, skipped, reason: err.message };
|
|
34589
34615
|
}
|
|
34616
|
+
const targetDir = (0, import_path37.join)(projectRoot, ".claude", "hooks", DISCIPLINE_HOOK_DIR);
|
|
34617
|
+
(0, import_fs35.mkdirSync)(targetDir, { recursive: true });
|
|
34618
|
+
for (const hook of DISCIPLINE_HOOKS) {
|
|
34619
|
+
const bundled = findDisciplineHook(hook.filename);
|
|
34620
|
+
if (!bundled) {
|
|
34621
|
+
skipped.push(hook.name);
|
|
34622
|
+
continue;
|
|
34623
|
+
}
|
|
34624
|
+
const target = (0, import_path37.join)(targetDir, hook.filename);
|
|
34625
|
+
(0, import_fs35.copyFileSync)(bundled, target);
|
|
34626
|
+
(0, import_fs35.chmodSync)(target, 493);
|
|
34627
|
+
}
|
|
34590
34628
|
let anyMutated = false;
|
|
34591
34629
|
for (const hook of DISCIPLINE_HOOKS) {
|
|
34592
34630
|
const bundled = findDisciplineHook(hook.filename);
|
|
@@ -35274,8 +35312,8 @@ message: Your question?
|
|
|
35274
35312
|
}
|
|
35275
35313
|
/** Start all worker agents (connect to relay) */
|
|
35276
35314
|
async start() {
|
|
35277
|
-
const { existsSync:
|
|
35278
|
-
const { join:
|
|
35315
|
+
const { existsSync: existsSync74, readFileSync: readFileSync70 } = await import("fs");
|
|
35316
|
+
const { join: join93 } = await import("path");
|
|
35279
35317
|
for (const config2 of this.registry.getAll()) {
|
|
35280
35318
|
if (config2.native) continue;
|
|
35281
35319
|
if (this.workers.has(config2.id)) continue;
|
|
@@ -35293,8 +35331,8 @@ message: Your question?
|
|
|
35293
35331
|
void 0,
|
|
35294
35332
|
config2.key_ref
|
|
35295
35333
|
);
|
|
35296
|
-
const instructionsPath =
|
|
35297
|
-
const instructions =
|
|
35334
|
+
const instructionsPath = join93(this.projectRoot, ".gossip", "agents", config2.id, "instructions.md");
|
|
35335
|
+
const instructions = existsSync74(instructionsPath) ? readFileSync70(instructionsPath, "utf-8") : void 0;
|
|
35298
35336
|
const enableWebSearch = config2.preset === "researcher" || config2.skills.includes("research");
|
|
35299
35337
|
const worker = new WorkerAgent(config2.id, llm, this.relayUrl, ALL_TOOLS, instructions, enableWebSearch, this.relayApiKey, config2.maxToolTurns);
|
|
35300
35338
|
await worker.start();
|
|
@@ -35491,8 +35529,8 @@ message: Your question?
|
|
|
35491
35529
|
this.registry.register(config2);
|
|
35492
35530
|
}
|
|
35493
35531
|
async syncWorkers(keyProvider) {
|
|
35494
|
-
const { existsSync:
|
|
35495
|
-
const { join:
|
|
35532
|
+
const { existsSync: existsSync74, readFileSync: readFileSync70 } = await import("fs");
|
|
35533
|
+
const { join: join93 } = await import("path");
|
|
35496
35534
|
let added = 0;
|
|
35497
35535
|
for (const ac of this.registry.getAll()) {
|
|
35498
35536
|
if (ac.native) continue;
|
|
@@ -35509,8 +35547,8 @@ message: Your question?
|
|
|
35509
35547
|
this.workers.delete(ac.id);
|
|
35510
35548
|
}
|
|
35511
35549
|
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 =
|
|
35550
|
+
const instructionsPath = join93(this.projectRoot, ".gossip", "agents", ac.id, "instructions.md");
|
|
35551
|
+
const instructions = existsSync74(instructionsPath) ? readFileSync70(instructionsPath, "utf-8") : void 0;
|
|
35514
35552
|
const enableWebSearch = ac.preset === "researcher" || ac.skills.includes("research");
|
|
35515
35553
|
const worker = new WorkerAgent(ac.id, llm, this.relayUrl, ALL_TOOLS, instructions, enableWebSearch, this.relayApiKey, ac.maxToolTurns);
|
|
35516
35554
|
await worker.start();
|
|
@@ -36487,8 +36525,8 @@ function applyStatusTags(input, statusMap) {
|
|
|
36487
36525
|
}
|
|
36488
36526
|
return { output: lines.join("\n"), changed };
|
|
36489
36527
|
}
|
|
36490
|
-
function atomicWrite(
|
|
36491
|
-
const tmp = `${
|
|
36528
|
+
function atomicWrite(path8, content) {
|
|
36529
|
+
const tmp = `${path8}.tmp`;
|
|
36492
36530
|
let fd;
|
|
36493
36531
|
try {
|
|
36494
36532
|
(0, import_fs40.writeFileSync)(tmp, content, "utf-8");
|
|
@@ -36496,7 +36534,7 @@ function atomicWrite(path7, content) {
|
|
|
36496
36534
|
(0, import_fs40.fsyncSync)(fd);
|
|
36497
36535
|
(0, import_fs40.closeSync)(fd);
|
|
36498
36536
|
fd = void 0;
|
|
36499
|
-
(0, import_fs40.renameSync)(tmp,
|
|
36537
|
+
(0, import_fs40.renameSync)(tmp, path8);
|
|
36500
36538
|
} catch (err) {
|
|
36501
36539
|
if (fd !== void 0) {
|
|
36502
36540
|
try {
|
|
@@ -36637,8 +36675,8 @@ function corpusDir(projectRoot) {
|
|
|
36637
36675
|
const encoded = projectRoot.replace(/\//g, "-");
|
|
36638
36676
|
return (0, import_path43.join)((0, import_os3.homedir)(), ".claude", "projects", encoded, "memory");
|
|
36639
36677
|
}
|
|
36640
|
-
function atomicWriteJson(
|
|
36641
|
-
const tmp = `${
|
|
36678
|
+
function atomicWriteJson(path8, data) {
|
|
36679
|
+
const tmp = `${path8}.tmp`;
|
|
36642
36680
|
let fd;
|
|
36643
36681
|
try {
|
|
36644
36682
|
(0, import_fs41.writeFileSync)(tmp, JSON.stringify(data, null, 2), "utf-8");
|
|
@@ -36646,7 +36684,7 @@ function atomicWriteJson(path7, data) {
|
|
|
36646
36684
|
(0, import_fs41.fsyncSync)(fd);
|
|
36647
36685
|
(0, import_fs41.closeSync)(fd);
|
|
36648
36686
|
fd = void 0;
|
|
36649
|
-
(0, import_fs41.renameSync)(tmp,
|
|
36687
|
+
(0, import_fs41.renameSync)(tmp, path8);
|
|
36650
36688
|
} catch (err) {
|
|
36651
36689
|
if (fd !== void 0) {
|
|
36652
36690
|
try {
|
|
@@ -36856,8 +36894,8 @@ function rebuildIndex(projectRoot) {
|
|
|
36856
36894
|
atomicWriteJson(idxPath, index);
|
|
36857
36895
|
return index;
|
|
36858
36896
|
}
|
|
36859
|
-
function atomicWriteText(
|
|
36860
|
-
const tmp = `${
|
|
36897
|
+
function atomicWriteText(path8, content) {
|
|
36898
|
+
const tmp = `${path8}.tmp`;
|
|
36861
36899
|
let fd;
|
|
36862
36900
|
try {
|
|
36863
36901
|
(0, import_fs41.writeFileSync)(tmp, content, "utf-8");
|
|
@@ -36865,7 +36903,7 @@ function atomicWriteText(path7, content) {
|
|
|
36865
36903
|
(0, import_fs41.fsyncSync)(fd);
|
|
36866
36904
|
(0, import_fs41.closeSync)(fd);
|
|
36867
36905
|
fd = void 0;
|
|
36868
|
-
(0, import_fs41.renameSync)(tmp,
|
|
36906
|
+
(0, import_fs41.renameSync)(tmp, path8);
|
|
36869
36907
|
} catch (err) {
|
|
36870
36908
|
if (fd !== void 0) {
|
|
36871
36909
|
try {
|
|
@@ -37259,29 +37297,29 @@ var init_task_graph_sync = __esm({
|
|
|
37259
37297
|
);
|
|
37260
37298
|
}
|
|
37261
37299
|
}
|
|
37262
|
-
async patch(
|
|
37263
|
-
const res = await fetch(`${this.supabaseUrl}${
|
|
37300
|
+
async patch(path8, body) {
|
|
37301
|
+
const res = await fetch(`${this.supabaseUrl}${path8}`, {
|
|
37264
37302
|
method: "PATCH",
|
|
37265
37303
|
headers: this.headers(),
|
|
37266
37304
|
body: JSON.stringify(body)
|
|
37267
37305
|
});
|
|
37268
|
-
if (!res.ok) throw new Error(`PATCH ${
|
|
37306
|
+
if (!res.ok) throw new Error(`PATCH ${path8} failed: ${res.status} ${await res.text()}`);
|
|
37269
37307
|
}
|
|
37270
|
-
async post(
|
|
37271
|
-
const res = await fetch(`${this.supabaseUrl}${
|
|
37308
|
+
async post(path8, body) {
|
|
37309
|
+
const res = await fetch(`${this.supabaseUrl}${path8}`, {
|
|
37272
37310
|
method: "POST",
|
|
37273
37311
|
headers: { ...this.headers(), "Prefer": "return=representation" },
|
|
37274
37312
|
body: JSON.stringify(body)
|
|
37275
37313
|
});
|
|
37276
|
-
if (!res.ok) throw new Error(`POST ${
|
|
37314
|
+
if (!res.ok) throw new Error(`POST ${path8} failed: ${res.status} ${await res.text()}`);
|
|
37277
37315
|
}
|
|
37278
|
-
async upsert(
|
|
37279
|
-
const res = await fetch(`${this.supabaseUrl}${
|
|
37316
|
+
async upsert(path8, body) {
|
|
37317
|
+
const res = await fetch(`${this.supabaseUrl}${path8}`, {
|
|
37280
37318
|
method: "POST",
|
|
37281
37319
|
headers: { ...this.headers(), "Prefer": "resolution=merge-duplicates,return=representation" },
|
|
37282
37320
|
body: JSON.stringify(body)
|
|
37283
37321
|
});
|
|
37284
|
-
if (!res.ok) throw new Error(`UPSERT ${
|
|
37322
|
+
if (!res.ok) throw new Error(`UPSERT ${path8} failed: ${res.status} ${await res.text()}`);
|
|
37285
37323
|
}
|
|
37286
37324
|
headers() {
|
|
37287
37325
|
return {
|
|
@@ -37478,22 +37516,22 @@ async function readJsonBody(req, cap) {
|
|
|
37478
37516
|
return { err: "invalid_json", msg: err instanceof Error ? err.message : "parse error" };
|
|
37479
37517
|
}
|
|
37480
37518
|
}
|
|
37481
|
-
function replyBodyErr(ctx2, req, res, rec, started,
|
|
37519
|
+
function replyBodyErr(ctx2, req, res, rec, started, path8, body) {
|
|
37482
37520
|
if (body.err === "too_large") {
|
|
37483
37521
|
ctx2.sendJson(res, 413, ctx2.errBody("payload_too_large", "payload_too_large", body.msg));
|
|
37484
|
-
ctx2.logEvent({ started, req, status: 413, path:
|
|
37522
|
+
ctx2.logEvent({ started, req, status: 413, path: path8, bytesRead: 0, bytesWritten: 0, token: rec.token });
|
|
37485
37523
|
} else {
|
|
37486
37524
|
ctx2.sendJson(res, 400, ctx2.errBody("bad_request", "bad_request", body.msg));
|
|
37487
|
-
ctx2.logEvent({ started, req, status: 400, path:
|
|
37525
|
+
ctx2.logEvent({ started, req, status: 400, path: path8, bytesRead: 0, bytesWritten: 0, token: rec.token });
|
|
37488
37526
|
}
|
|
37489
37527
|
}
|
|
37490
|
-
function reply403(ctx2, req, res, rec, started,
|
|
37528
|
+
function reply403(ctx2, req, res, rec, started, path8, msg) {
|
|
37491
37529
|
ctx2.sendJson(res, 403, ctx2.errBody("forbidden", "scope_violation", msg));
|
|
37492
|
-
ctx2.logEvent({ started, req, status: 403, path:
|
|
37530
|
+
ctx2.logEvent({ started, req, status: 403, path: path8, bytesRead: 0, bytesWritten: 0, token: rec.token });
|
|
37493
37531
|
}
|
|
37494
|
-
function reply429(ctx2, req, res, rec, started,
|
|
37532
|
+
function reply429(ctx2, req, res, rec, started, path8) {
|
|
37495
37533
|
ctx2.send429(res);
|
|
37496
|
-
ctx2.logEvent({ started, req, status: 429, path:
|
|
37534
|
+
ctx2.logEvent({ started, req, status: 429, path: path8, bytesRead: 0, bytesWritten: 0, token: rec.token });
|
|
37497
37535
|
}
|
|
37498
37536
|
async function handleBridgeInfo(ctx2, req, res, started, ip) {
|
|
37499
37537
|
if (!ctx2.limBridgeInfo.record(ip)) {
|
|
@@ -37532,12 +37570,12 @@ async function handleFileRead(ctx2, req, res, rec, started) {
|
|
|
37532
37570
|
if (!ctx2.limRead.record(`read:${rec.token}`)) return reply429(ctx2, req, res, rec, started, "/file-read");
|
|
37533
37571
|
const body = await readJsonBody(req, MAX_FILE_BYTES);
|
|
37534
37572
|
if ("err" in body) return replyBodyErr(ctx2, req, res, rec, started, "/file-read", body);
|
|
37535
|
-
const
|
|
37536
|
-
if (!
|
|
37573
|
+
const path8 = typeof body.value?.path === "string" ? body.value.path : "";
|
|
37574
|
+
if (!path8) {
|
|
37537
37575
|
ctx2.sendJson(res, 400, ctx2.errBody("bad_request", "bad_request", "path is required"));
|
|
37538
37576
|
return ctx2.logEvent({ started, req, status: 400, path: "/file-read", bytesRead: 0, bytesWritten: 0, token: rec.token });
|
|
37539
37577
|
}
|
|
37540
|
-
const abs = resolveInScope(rec,
|
|
37578
|
+
const abs = resolveInScope(rec, path8);
|
|
37541
37579
|
if (!abs.ok) return reply403(ctx2, req, res, rec, started, "/file-read", abs.msg);
|
|
37542
37580
|
let fileSize;
|
|
37543
37581
|
let mtime;
|
|
@@ -37578,14 +37616,14 @@ async function handleFileWrite(ctx2, req, res, rec, started) {
|
|
|
37578
37616
|
if (!ctx2.limWrite.record(`write:${rec.token}`)) return reply429(ctx2, req, res, rec, started, "/file-write");
|
|
37579
37617
|
const body = await readJsonBody(req, MAX_FILE_BYTES);
|
|
37580
37618
|
if ("err" in body) return replyBodyErr(ctx2, req, res, rec, started, "/file-write", body);
|
|
37581
|
-
const
|
|
37619
|
+
const path8 = typeof body.value?.path === "string" ? body.value.path : "";
|
|
37582
37620
|
const content = typeof body.value?.content === "string" ? body.value.content : "";
|
|
37583
37621
|
const ifMatch = typeof body.value?.if_match === "string" ? body.value.if_match : void 0;
|
|
37584
|
-
if (!
|
|
37622
|
+
if (!path8) {
|
|
37585
37623
|
ctx2.sendJson(res, 400, ctx2.errBody("bad_request", "bad_request", "path is required"));
|
|
37586
37624
|
return ctx2.logEvent({ started, req, status: 400, path: "/file-write", bytesRead: 0, bytesWritten: 0, token: rec.token });
|
|
37587
37625
|
}
|
|
37588
|
-
const abs = resolveInScope(rec,
|
|
37626
|
+
const abs = resolveInScope(rec, path8);
|
|
37589
37627
|
if (!abs.ok) return reply403(ctx2, req, res, rec, started, "/file-write", abs.msg);
|
|
37590
37628
|
const buf = Buffer.from(content, "utf-8");
|
|
37591
37629
|
if (buf.byteLength > MAX_FILE_BYTES) {
|
|
@@ -38234,12 +38272,12 @@ function buildIndexFromDisk(memoryDir, agentIds) {
|
|
|
38234
38272
|
};
|
|
38235
38273
|
}
|
|
38236
38274
|
function readValidSidecar(projectRoot, memoryDir) {
|
|
38237
|
-
const
|
|
38238
|
-
if (!(0, import_fs44.existsSync)(
|
|
38275
|
+
const path8 = proseResolverPath(projectRoot);
|
|
38276
|
+
if (!(0, import_fs44.existsSync)(path8)) return null;
|
|
38239
38277
|
let parsed;
|
|
38240
38278
|
try {
|
|
38241
|
-
if ((0, import_fs44.statSync)(
|
|
38242
|
-
parsed = JSON.parse((0, import_fs44.readFileSync)(
|
|
38279
|
+
if ((0, import_fs44.statSync)(path8).size > SIDECAR_READ_LIMIT) return null;
|
|
38280
|
+
parsed = JSON.parse((0, import_fs44.readFileSync)(path8, "utf-8"));
|
|
38243
38281
|
} catch {
|
|
38244
38282
|
return null;
|
|
38245
38283
|
}
|
|
@@ -38259,10 +38297,10 @@ function readValidSidecar(projectRoot, memoryDir) {
|
|
|
38259
38297
|
return idx;
|
|
38260
38298
|
}
|
|
38261
38299
|
function writeSidecar(projectRoot, idx) {
|
|
38262
|
-
const
|
|
38300
|
+
const path8 = proseResolverPath(projectRoot);
|
|
38263
38301
|
try {
|
|
38264
|
-
(0, import_fs44.mkdirSync)((0, import_path48.dirname)(
|
|
38265
|
-
(0, import_fs44.writeFileSync)(
|
|
38302
|
+
(0, import_fs44.mkdirSync)((0, import_path48.dirname)(path8), { recursive: true });
|
|
38303
|
+
(0, import_fs44.writeFileSync)(path8, JSON.stringify(idx));
|
|
38266
38304
|
} catch {
|
|
38267
38305
|
}
|
|
38268
38306
|
}
|
|
@@ -38427,11 +38465,11 @@ function isLedgerIndex(x) {
|
|
|
38427
38465
|
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
38466
|
}
|
|
38429
38467
|
function readLedgerIndex(projectRoot, liveLedgerContent, liveLedgerMtime) {
|
|
38430
|
-
const
|
|
38431
|
-
if (!(0, import_fs45.existsSync)(
|
|
38468
|
+
const path8 = ledgerIndexPath(projectRoot);
|
|
38469
|
+
if (!(0, import_fs45.existsSync)(path8)) return null;
|
|
38432
38470
|
let parsed;
|
|
38433
38471
|
try {
|
|
38434
|
-
parsed = JSON.parse((0, import_fs45.readFileSync)(
|
|
38472
|
+
parsed = JSON.parse((0, import_fs45.readFileSync)(path8, "utf-8"));
|
|
38435
38473
|
} catch {
|
|
38436
38474
|
return null;
|
|
38437
38475
|
}
|
|
@@ -38441,10 +38479,10 @@ function readLedgerIndex(projectRoot, liveLedgerContent, liveLedgerMtime) {
|
|
|
38441
38479
|
return parsed;
|
|
38442
38480
|
}
|
|
38443
38481
|
function writeLedgerIndex(projectRoot, index) {
|
|
38444
|
-
const
|
|
38482
|
+
const path8 = ledgerIndexPath(projectRoot);
|
|
38445
38483
|
try {
|
|
38446
|
-
(0, import_fs45.mkdirSync)((0, import_path49.dirname)(
|
|
38447
|
-
(0, import_fs45.writeFileSync)(
|
|
38484
|
+
(0, import_fs45.mkdirSync)((0, import_path49.dirname)(path8), { recursive: true });
|
|
38485
|
+
(0, import_fs45.writeFileSync)(path8, JSON.stringify(index, null, 2));
|
|
38448
38486
|
} catch {
|
|
38449
38487
|
}
|
|
38450
38488
|
}
|
|
@@ -38552,9 +38590,9 @@ function annotateLedgerText(raw, bullets, entriesByHash) {
|
|
|
38552
38590
|
}
|
|
38553
38591
|
return lines.join("\n");
|
|
38554
38592
|
}
|
|
38555
|
-
function ledgerMtime(
|
|
38593
|
+
function ledgerMtime(ledgerPath2) {
|
|
38556
38594
|
try {
|
|
38557
|
-
return (0, import_fs45.statSync)(
|
|
38595
|
+
return (0, import_fs45.statSync)(ledgerPath2).mtimeMs;
|
|
38558
38596
|
} catch {
|
|
38559
38597
|
return 0;
|
|
38560
38598
|
}
|
|
@@ -38616,10 +38654,10 @@ function checkDistMcpStaleness(bundlePath) {
|
|
|
38616
38654
|
let newestMtime = 0;
|
|
38617
38655
|
let newestPath;
|
|
38618
38656
|
for (const root of SRC_ROOTS) {
|
|
38619
|
-
walk((0, import_path50.join)(repoRoot, root), (
|
|
38657
|
+
walk((0, import_path50.join)(repoRoot, root), (path8, mtimeMs) => {
|
|
38620
38658
|
if (mtimeMs > newestMtime) {
|
|
38621
38659
|
newestMtime = mtimeMs;
|
|
38622
|
-
newestPath =
|
|
38660
|
+
newestPath = path8;
|
|
38623
38661
|
}
|
|
38624
38662
|
});
|
|
38625
38663
|
}
|
|
@@ -39089,13 +39127,13 @@ Skills are auto-injected from agent config. Project-wide skills in .gossip/skill
|
|
|
39089
39127
|
*
|
|
39090
39128
|
* Bootstrap critical path stays synchronous and fast.
|
|
39091
39129
|
*/
|
|
39092
|
-
applyLedgerAnnotations(content,
|
|
39130
|
+
applyLedgerAnnotations(content, ledgerPath2) {
|
|
39093
39131
|
try {
|
|
39094
39132
|
const bullets = parseNextSessionBullets(content);
|
|
39095
39133
|
if (bullets.length === 0) return content;
|
|
39096
39134
|
let mtime = 0;
|
|
39097
39135
|
try {
|
|
39098
|
-
mtime = (0, import_fs47.statSync)(
|
|
39136
|
+
mtime = (0, import_fs47.statSync)(ledgerPath2).mtimeMs;
|
|
39099
39137
|
} catch {
|
|
39100
39138
|
}
|
|
39101
39139
|
const index = readLedgerIndex(this.projectRoot, content, mtime);
|
|
@@ -39241,19 +39279,19 @@ function hasControlChars(s) {
|
|
|
39241
39279
|
}
|
|
39242
39280
|
return false;
|
|
39243
39281
|
}
|
|
39244
|
-
async function gitCommonDir(
|
|
39282
|
+
async function gitCommonDir(path8) {
|
|
39245
39283
|
try {
|
|
39246
39284
|
const { stdout } = await execFileP(
|
|
39247
39285
|
"git",
|
|
39248
|
-
["-C",
|
|
39286
|
+
["-C", path8, "rev-parse", "--git-common-dir"],
|
|
39249
39287
|
GIT_EXEC_OPTS
|
|
39250
39288
|
);
|
|
39251
39289
|
const out = stdout.trim();
|
|
39252
39290
|
if (!out) return null;
|
|
39253
39291
|
try {
|
|
39254
|
-
return (0, import_fs48.realpathSync)((0, import_path52.resolve)(
|
|
39292
|
+
return (0, import_fs48.realpathSync)((0, import_path52.resolve)(path8, out));
|
|
39255
39293
|
} catch {
|
|
39256
|
-
return (0, import_path52.resolve)(
|
|
39294
|
+
return (0, import_path52.resolve)(path8, out);
|
|
39257
39295
|
}
|
|
39258
39296
|
} catch {
|
|
39259
39297
|
return null;
|
|
@@ -39279,17 +39317,17 @@ function parseWorktreePorcelain(stdout, { includeLocked = false } = {}) {
|
|
|
39279
39317
|
const fields = rec.split("\0").filter(Boolean);
|
|
39280
39318
|
const worktreeField = fields.find((f) => f.startsWith("worktree "));
|
|
39281
39319
|
if (!worktreeField) continue;
|
|
39282
|
-
const
|
|
39320
|
+
const path8 = worktreeField.slice("worktree ".length);
|
|
39283
39321
|
if (fields.some(
|
|
39284
39322
|
(f) => f === "bare" || !includeLocked && f.startsWith("locked") || f.startsWith("prunable")
|
|
39285
39323
|
)) {
|
|
39286
39324
|
continue;
|
|
39287
39325
|
}
|
|
39288
|
-
let canonical =
|
|
39326
|
+
let canonical = path8;
|
|
39289
39327
|
try {
|
|
39290
|
-
canonical = (0, import_fs48.realpathSync)((0, import_path52.resolve)(
|
|
39328
|
+
canonical = (0, import_fs48.realpathSync)((0, import_path52.resolve)(path8));
|
|
39291
39329
|
} catch {
|
|
39292
|
-
canonical = (0, import_path52.resolve)(
|
|
39330
|
+
canonical = (0, import_path52.resolve)(path8);
|
|
39293
39331
|
}
|
|
39294
39332
|
out.push(canonical);
|
|
39295
39333
|
if (out.length >= 100) break;
|
|
@@ -40415,6 +40453,89 @@ var init_chatbot_agent = __esm({
|
|
|
40415
40453
|
}
|
|
40416
40454
|
});
|
|
40417
40455
|
|
|
40456
|
+
// packages/orchestrator/src/orchestrator-preconditions.ts
|
|
40457
|
+
function detectStaleBase(dispatchSha, originMasterSha, mergeBaseSha) {
|
|
40458
|
+
if (dispatchSha === originMasterSha) {
|
|
40459
|
+
return { stale: false, reason: null };
|
|
40460
|
+
}
|
|
40461
|
+
if (mergeBaseSha === dispatchSha) {
|
|
40462
|
+
return { stale: true, reason: "behind_origin" };
|
|
40463
|
+
}
|
|
40464
|
+
if (mergeBaseSha === originMasterSha) {
|
|
40465
|
+
return { stale: false, reason: "ahead_of_origin" };
|
|
40466
|
+
}
|
|
40467
|
+
return { stale: true, reason: "branched_pre_merge" };
|
|
40468
|
+
}
|
|
40469
|
+
function findUnreadablePaths(paths, canRead) {
|
|
40470
|
+
return paths.filter((p) => !canRead(p));
|
|
40471
|
+
}
|
|
40472
|
+
function extractReferencedPathsWithMeta(taskText) {
|
|
40473
|
+
if (!taskText) {
|
|
40474
|
+
return { paths: [], droppedOverCap: 0 };
|
|
40475
|
+
}
|
|
40476
|
+
const rawTokens = taskText.split(/[\s`]+/);
|
|
40477
|
+
const seen = /* @__PURE__ */ new Set();
|
|
40478
|
+
const out = [];
|
|
40479
|
+
let droppedOverCap = 0;
|
|
40480
|
+
for (const raw of rawTokens) {
|
|
40481
|
+
const trimmed = raw.replace(/^[([{<"']+/, "").replace(/[)\]}>"',.;:]+$/, "");
|
|
40482
|
+
const token = trimmed.replace(/:\d+(?::\d+)?$/, "");
|
|
40483
|
+
if (token.length === 0) {
|
|
40484
|
+
continue;
|
|
40485
|
+
}
|
|
40486
|
+
if (token.startsWith("/") || token.includes("..")) {
|
|
40487
|
+
continue;
|
|
40488
|
+
}
|
|
40489
|
+
if (!REPO_PATH_SHAPE.test(token)) {
|
|
40490
|
+
continue;
|
|
40491
|
+
}
|
|
40492
|
+
if (seen.has(token)) {
|
|
40493
|
+
continue;
|
|
40494
|
+
}
|
|
40495
|
+
seen.add(token);
|
|
40496
|
+
if (out.length >= MAX_REFERENCED_PATHS) {
|
|
40497
|
+
droppedOverCap += 1;
|
|
40498
|
+
continue;
|
|
40499
|
+
}
|
|
40500
|
+
out.push(token);
|
|
40501
|
+
}
|
|
40502
|
+
return { paths: out, droppedOverCap };
|
|
40503
|
+
}
|
|
40504
|
+
function extractReferencedPaths(taskText) {
|
|
40505
|
+
return extractReferencedPathsWithMeta(taskText).paths;
|
|
40506
|
+
}
|
|
40507
|
+
function findUnreadableReferencedPaths(taskText, opts) {
|
|
40508
|
+
return findUnreadableReferencedPathsWithMeta(taskText, opts).unreadable;
|
|
40509
|
+
}
|
|
40510
|
+
function findUnreadableReferencedPathsWithMeta(taskText, opts) {
|
|
40511
|
+
const { paths, droppedOverCap } = extractReferencedPathsWithMeta(taskText);
|
|
40512
|
+
const out = [];
|
|
40513
|
+
const isWorktree = opts.writeMode === "worktree";
|
|
40514
|
+
for (const path8 of paths) {
|
|
40515
|
+
const exists = opts.pathExists(path8);
|
|
40516
|
+
if (!exists) {
|
|
40517
|
+
out.push({ path: path8, reason: "missing" });
|
|
40518
|
+
continue;
|
|
40519
|
+
}
|
|
40520
|
+
if (isWorktree && opts.isGitignoredOrUntracked(path8)) {
|
|
40521
|
+
out.push({ path: path8, reason: "gitignored_in_worktree" });
|
|
40522
|
+
}
|
|
40523
|
+
}
|
|
40524
|
+
return { unreadable: out, droppedOverCap };
|
|
40525
|
+
}
|
|
40526
|
+
function detectMidFlightCommits(commitsBetween) {
|
|
40527
|
+
const count = commitsBetween.length;
|
|
40528
|
+
return { detected: count > 0, count };
|
|
40529
|
+
}
|
|
40530
|
+
var REPO_PATH_SHAPE, MAX_REFERENCED_PATHS;
|
|
40531
|
+
var init_orchestrator_preconditions = __esm({
|
|
40532
|
+
"packages/orchestrator/src/orchestrator-preconditions.ts"() {
|
|
40533
|
+
"use strict";
|
|
40534
|
+
REPO_PATH_SHAPE = /^(?:\.\/)?[\w./-]+\.(?:md|ts|tsx|js|json|txt|ya?ml)$/;
|
|
40535
|
+
MAX_REFERENCED_PATHS = 20;
|
|
40536
|
+
}
|
|
40537
|
+
});
|
|
40538
|
+
|
|
40418
40539
|
// packages/orchestrator/src/index.ts
|
|
40419
40540
|
var src_exports3 = {};
|
|
40420
40541
|
__export(src_exports3, {
|
|
@@ -40540,6 +40661,8 @@ __export(src_exports3, {
|
|
|
40540
40661
|
defaultVerifierFactory: () => defaultVerifierFactory,
|
|
40541
40662
|
deriveConsensusId: () => deriveConsensusId,
|
|
40542
40663
|
detectFormatCompliance: () => detectFormatCompliance,
|
|
40664
|
+
detectMidFlightCommits: () => detectMidFlightCommits,
|
|
40665
|
+
detectStaleBase: () => detectStaleBase,
|
|
40543
40666
|
discoverAgentIdsForRoot: () => discoverAgentIdsForRoot,
|
|
40544
40667
|
discoverGitWorktrees: () => discoverGitWorktrees,
|
|
40545
40668
|
emitCitationFabricatedSignal: () => emitCitationFabricatedSignal,
|
|
@@ -40552,11 +40675,16 @@ __export(src_exports3, {
|
|
|
40552
40675
|
ensureRulesFile: () => ensureRulesFile,
|
|
40553
40676
|
extractCategories: () => extractCategories,
|
|
40554
40677
|
extractConsensusId: () => extractConsensusId,
|
|
40678
|
+
extractReferencedPaths: () => extractReferencedPaths,
|
|
40679
|
+
extractReferencedPathsWithMeta: () => extractReferencedPathsWithMeta,
|
|
40555
40680
|
extractSpecReferences: () => extractSpecReferences,
|
|
40556
40681
|
extractTokens: () => extractTokens,
|
|
40557
40682
|
findBundledHook: () => findBundledHook,
|
|
40558
40683
|
findBundledRules: () => findBundledRules,
|
|
40559
40684
|
findOpenSectionLine: () => findOpenSectionLine,
|
|
40685
|
+
findUnreadablePaths: () => findUnreadablePaths,
|
|
40686
|
+
findUnreadableReferencedPaths: () => findUnreadableReferencedPaths,
|
|
40687
|
+
findUnreadableReferencedPathsWithMeta: () => findUnreadableReferencedPathsWithMeta,
|
|
40560
40688
|
formatCooldownMessage: () => formatCooldownMessage,
|
|
40561
40689
|
formatStalenessWarning: () => formatStalenessWarning,
|
|
40562
40690
|
getRoundCounter: () => get,
|
|
@@ -40739,6 +40867,7 @@ var init_src4 = __esm({
|
|
|
40739
40867
|
init_runtime_config();
|
|
40740
40868
|
init_runtime_config_schema();
|
|
40741
40869
|
init_chatbot_agent();
|
|
40870
|
+
init_orchestrator_preconditions();
|
|
40742
40871
|
}
|
|
40743
40872
|
});
|
|
40744
40873
|
|
|
@@ -41958,10 +42087,10 @@ var init_auth = __esm({
|
|
|
41958
42087
|
* left half-written by a crash. Validate the shape before trusting it and
|
|
41959
42088
|
* fail closed (regenerate) on anything unexpected — never throw.
|
|
41960
42089
|
*/
|
|
41961
|
-
loadPersisted(
|
|
42090
|
+
loadPersisted(path8) {
|
|
41962
42091
|
try {
|
|
41963
|
-
if (!(0, import_fs54.existsSync)(
|
|
41964
|
-
const parsed = JSON.parse((0, import_fs54.readFileSync)(
|
|
42092
|
+
if (!(0, import_fs54.existsSync)(path8)) return false;
|
|
42093
|
+
const parsed = JSON.parse((0, import_fs54.readFileSync)(path8, "utf8"));
|
|
41965
42094
|
if (!isPersistedAuth(parsed)) return false;
|
|
41966
42095
|
this.key = parsed.key;
|
|
41967
42096
|
this.sessions.clear();
|
|
@@ -42197,9 +42326,9 @@ var init_api_open_findings = __esm({
|
|
|
42197
42326
|
});
|
|
42198
42327
|
|
|
42199
42328
|
// packages/relay/src/dashboard/api-overview.ts
|
|
42200
|
-
function readSkillStatus(
|
|
42329
|
+
function readSkillStatus(path8) {
|
|
42201
42330
|
try {
|
|
42202
|
-
const content = (0, import_fs56.readFileSync)(
|
|
42331
|
+
const content = (0, import_fs56.readFileSync)(path8, "utf-8");
|
|
42203
42332
|
const m = content.match(/^---\n([\s\S]*?)\n---/);
|
|
42204
42333
|
if (!m) return null;
|
|
42205
42334
|
const block = m[1];
|
|
@@ -42513,9 +42642,9 @@ var init_api_fleet_trend = __esm({
|
|
|
42513
42642
|
// packages/relay/src/dashboard/api-agents.ts
|
|
42514
42643
|
function readSkillFrontmatter(projectRoot, agentId, skillName) {
|
|
42515
42644
|
try {
|
|
42516
|
-
const
|
|
42517
|
-
if (!(0, import_fs58.existsSync)(
|
|
42518
|
-
const raw = (0, import_fs58.readFileSync)(
|
|
42645
|
+
const path8 = (0, import_path62.join)(projectRoot, ".gossip", "agents", agentId, "skills", `${skillName}.md`);
|
|
42646
|
+
if (!(0, import_fs58.existsSync)(path8)) return null;
|
|
42647
|
+
const raw = (0, import_fs58.readFileSync)(path8, "utf-8");
|
|
42519
42648
|
if (!raw.startsWith("---")) return null;
|
|
42520
42649
|
const end = raw.indexOf("\n---", 3);
|
|
42521
42650
|
if (end === -1) return null;
|
|
@@ -42553,9 +42682,9 @@ function normalizeCategory(s) {
|
|
|
42553
42682
|
}
|
|
42554
42683
|
function readForcedDevelops(projectRoot, agentId, category) {
|
|
42555
42684
|
try {
|
|
42556
|
-
const
|
|
42557
|
-
if (!(0, import_fs58.existsSync)(
|
|
42558
|
-
const raw = (0, import_fs58.readFileSync)(
|
|
42685
|
+
const path8 = (0, import_path62.join)(projectRoot, ".gossip", "forced-skill-develops.jsonl");
|
|
42686
|
+
if (!(0, import_fs58.existsSync)(path8)) return [];
|
|
42687
|
+
const raw = (0, import_fs58.readFileSync)(path8, "utf-8");
|
|
42559
42688
|
const target = normalizeCategory(category);
|
|
42560
42689
|
const out = [];
|
|
42561
42690
|
for (const line of raw.split("\n")) {
|
|
@@ -43837,7 +43966,9 @@ async function tasksHandler(projectRoot, query) {
|
|
|
43837
43966
|
});
|
|
43838
43967
|
} else if (entry.type === "task.completed") {
|
|
43839
43968
|
completed.set(entry.taskId, {
|
|
43840
|
-
|
|
43969
|
+
// On-disk field is "durationMs"; "entry.duration" was previously
|
|
43970
|
+
// undefined, silently dropping all task durations from the response.
|
|
43971
|
+
duration: entry.durationMs ?? entry.duration,
|
|
43841
43972
|
timestamp: entry.timestamp,
|
|
43842
43973
|
failed: false,
|
|
43843
43974
|
inputTokens: entry.inputTokens,
|
|
@@ -43873,7 +44004,11 @@ async function tasksHandler(projectRoot, query) {
|
|
|
43873
44004
|
result: result?.result,
|
|
43874
44005
|
status: result ? result.cancelled ? "cancelled" : result.failed ? "failed" : "completed" : "running",
|
|
43875
44006
|
duration: result?.duration,
|
|
44007
|
+
// timestamp = completion time for terminal tasks (used as "Completed" node in timeline).
|
|
44008
|
+
// For running tasks, falls back to createdAt.
|
|
43876
44009
|
timestamp: result?.timestamp || info.timestamp,
|
|
44010
|
+
// createdAt = always the dispatch time (task.created event timestamp).
|
|
44011
|
+
createdAt: info.timestamp,
|
|
43877
44012
|
inputTokens: result?.inputTokens,
|
|
43878
44013
|
outputTokens: result?.outputTokens
|
|
43879
44014
|
});
|
|
@@ -43891,14 +44026,149 @@ var init_api_tasks = __esm({
|
|
|
43891
44026
|
}
|
|
43892
44027
|
});
|
|
43893
44028
|
|
|
44029
|
+
// packages/relay/src/dashboard/api-task-detail.ts
|
|
44030
|
+
function readJsonlLines(filePath) {
|
|
44031
|
+
const out = [];
|
|
44032
|
+
const archive = filePath + ".1";
|
|
44033
|
+
if ((0, import_fs67.existsSync)(archive)) {
|
|
44034
|
+
out.push(...(0, import_fs67.readFileSync)(archive, "utf-8").split("\n").filter(Boolean));
|
|
44035
|
+
}
|
|
44036
|
+
if ((0, import_fs67.existsSync)(filePath)) {
|
|
44037
|
+
out.push(...(0, import_fs67.readFileSync)(filePath, "utf-8").split("\n").filter(Boolean));
|
|
44038
|
+
}
|
|
44039
|
+
return out;
|
|
44040
|
+
}
|
|
44041
|
+
async function taskDetailHandler(projectRoot, taskId) {
|
|
44042
|
+
const graphPath = (0, import_path74.join)(projectRoot, ".gossip", "task-graph.jsonl");
|
|
44043
|
+
if (!(0, import_fs67.existsSync)(graphPath) && !(0, import_fs67.existsSync)(graphPath + ".1")) {
|
|
44044
|
+
return null;
|
|
44045
|
+
}
|
|
44046
|
+
const created = /* @__PURE__ */ new Map();
|
|
44047
|
+
const completed = /* @__PURE__ */ new Map();
|
|
44048
|
+
try {
|
|
44049
|
+
const lines = readJsonlLines(graphPath);
|
|
44050
|
+
for (const line of lines) {
|
|
44051
|
+
try {
|
|
44052
|
+
const entry = JSON.parse(line);
|
|
44053
|
+
if (entry.type === "task.created") {
|
|
44054
|
+
created.set(entry.taskId, {
|
|
44055
|
+
agentId: entry.agentId || "?",
|
|
44056
|
+
task: entry.task || "",
|
|
44057
|
+
timestamp: entry.timestamp
|
|
44058
|
+
});
|
|
44059
|
+
} else if (entry.type === "task.completed") {
|
|
44060
|
+
completed.set(entry.taskId, {
|
|
44061
|
+
duration: entry.durationMs ?? entry.duration,
|
|
44062
|
+
timestamp: entry.timestamp,
|
|
44063
|
+
failed: false,
|
|
44064
|
+
inputTokens: entry.inputTokens,
|
|
44065
|
+
outputTokens: entry.outputTokens,
|
|
44066
|
+
result: typeof entry.result === "string" ? entry.result : void 0
|
|
44067
|
+
});
|
|
44068
|
+
} else if (entry.type === "task.failed") {
|
|
44069
|
+
completed.set(entry.taskId, { timestamp: entry.timestamp, failed: true });
|
|
44070
|
+
} else if (entry.type === "task.cancelled") {
|
|
44071
|
+
completed.set(entry.taskId, { timestamp: entry.timestamp, failed: false, cancelled: true });
|
|
44072
|
+
}
|
|
44073
|
+
} catch {
|
|
44074
|
+
}
|
|
44075
|
+
}
|
|
44076
|
+
} catch {
|
|
44077
|
+
return null;
|
|
44078
|
+
}
|
|
44079
|
+
const info = created.get(taskId);
|
|
44080
|
+
if (!info) return null;
|
|
44081
|
+
const result = completed.get(taskId);
|
|
44082
|
+
const base = {
|
|
44083
|
+
taskId,
|
|
44084
|
+
agentId: info.agentId,
|
|
44085
|
+
task: info.task,
|
|
44086
|
+
result: result?.result,
|
|
44087
|
+
status: result ? result.cancelled ? "cancelled" : result.failed ? "failed" : "completed" : "running",
|
|
44088
|
+
duration: result?.duration,
|
|
44089
|
+
timestamp: result?.timestamp || info.timestamp,
|
|
44090
|
+
createdAt: info.timestamp,
|
|
44091
|
+
inputTokens: result?.inputTokens,
|
|
44092
|
+
outputTokens: result?.outputTokens
|
|
44093
|
+
};
|
|
44094
|
+
let consensusId;
|
|
44095
|
+
let signalCount = 0;
|
|
44096
|
+
const siblingSet = /* @__PURE__ */ new Set();
|
|
44097
|
+
const perfPath = (0, import_path74.join)(projectRoot, ".gossip", "agent-performance.jsonl");
|
|
44098
|
+
try {
|
|
44099
|
+
const lines = readJsonlLines(perfPath);
|
|
44100
|
+
const allEntries = [];
|
|
44101
|
+
for (const line of lines) {
|
|
44102
|
+
try {
|
|
44103
|
+
const entry = JSON.parse(line);
|
|
44104
|
+
if (typeof entry.taskId !== "string") continue;
|
|
44105
|
+
allEntries.push(entry);
|
|
44106
|
+
if (entry.taskId === taskId) {
|
|
44107
|
+
signalCount++;
|
|
44108
|
+
if (!consensusId && typeof entry.consensusId === "string" && entry.consensusId) {
|
|
44109
|
+
consensusId = entry.consensusId;
|
|
44110
|
+
}
|
|
44111
|
+
}
|
|
44112
|
+
} catch {
|
|
44113
|
+
}
|
|
44114
|
+
}
|
|
44115
|
+
if (consensusId) {
|
|
44116
|
+
for (const entry of allEntries) {
|
|
44117
|
+
if (siblingSet.size >= SIBLING_CAP) break;
|
|
44118
|
+
if (entry.consensusId === consensusId && typeof entry.taskId === "string" && entry.taskId && entry.taskId !== taskId) {
|
|
44119
|
+
siblingSet.add(entry.taskId);
|
|
44120
|
+
}
|
|
44121
|
+
}
|
|
44122
|
+
}
|
|
44123
|
+
} catch {
|
|
44124
|
+
}
|
|
44125
|
+
let findingCount = 0;
|
|
44126
|
+
if (consensusId) {
|
|
44127
|
+
const prefix = `${consensusId}:`;
|
|
44128
|
+
const findingsPath = (0, import_path74.join)(projectRoot, ".gossip", "implementation-findings.jsonl");
|
|
44129
|
+
try {
|
|
44130
|
+
const lines = readJsonlLines(findingsPath);
|
|
44131
|
+
for (const line of lines) {
|
|
44132
|
+
try {
|
|
44133
|
+
const entry = JSON.parse(line);
|
|
44134
|
+
if (typeof entry.taskId === "string" && entry.taskId.startsWith(prefix)) {
|
|
44135
|
+
findingCount++;
|
|
44136
|
+
}
|
|
44137
|
+
} catch {
|
|
44138
|
+
}
|
|
44139
|
+
}
|
|
44140
|
+
} catch {
|
|
44141
|
+
}
|
|
44142
|
+
}
|
|
44143
|
+
const siblingTaskIds = siblingSet.size > 0 ? [...siblingSet] : void 0;
|
|
44144
|
+
const siblingsTruncated = siblingSet.size >= SIBLING_CAP;
|
|
44145
|
+
return {
|
|
44146
|
+
...base,
|
|
44147
|
+
...consensusId !== void 0 && { consensusId },
|
|
44148
|
+
...siblingTaskIds !== void 0 && { siblingTaskIds },
|
|
44149
|
+
...siblingsTruncated && { siblingsTruncated },
|
|
44150
|
+
signalCount,
|
|
44151
|
+
findingCount
|
|
44152
|
+
};
|
|
44153
|
+
}
|
|
44154
|
+
var import_fs67, import_path74, SIBLING_CAP;
|
|
44155
|
+
var init_api_task_detail = __esm({
|
|
44156
|
+
"packages/relay/src/dashboard/api-task-detail.ts"() {
|
|
44157
|
+
"use strict";
|
|
44158
|
+
import_fs67 = require("fs");
|
|
44159
|
+
import_path74 = require("path");
|
|
44160
|
+
SIBLING_CAP = 25;
|
|
44161
|
+
}
|
|
44162
|
+
});
|
|
44163
|
+
|
|
43894
44164
|
// packages/relay/src/dashboard/api-active-tasks.ts
|
|
43895
44165
|
async function activeTasksHandler(projectRoot) {
|
|
43896
|
-
const taskGraphPath = (0,
|
|
43897
|
-
if (!(0,
|
|
44166
|
+
const taskGraphPath = (0, import_path75.join)(projectRoot, ".gossip", "task-graph.jsonl");
|
|
44167
|
+
if (!(0, import_fs68.existsSync)(taskGraphPath)) return { tasks: [] };
|
|
43898
44168
|
const created = /* @__PURE__ */ new Map();
|
|
43899
44169
|
const finished = /* @__PURE__ */ new Set();
|
|
43900
44170
|
try {
|
|
43901
|
-
const lines = (0,
|
|
44171
|
+
const lines = (0, import_fs68.readFileSync)(taskGraphPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
43902
44172
|
for (const line of lines) {
|
|
43903
44173
|
try {
|
|
43904
44174
|
const ev = JSON.parse(line);
|
|
@@ -43926,19 +44196,19 @@ async function activeTasksHandler(projectRoot) {
|
|
|
43926
44196
|
active.sort((a, b) => b.startedAt.localeCompare(a.startedAt));
|
|
43927
44197
|
return { tasks: active.slice(0, 10) };
|
|
43928
44198
|
}
|
|
43929
|
-
var
|
|
44199
|
+
var import_fs68, import_path75;
|
|
43930
44200
|
var init_api_active_tasks = __esm({
|
|
43931
44201
|
"packages/relay/src/dashboard/api-active-tasks.ts"() {
|
|
43932
44202
|
"use strict";
|
|
43933
|
-
|
|
43934
|
-
|
|
44203
|
+
import_fs68 = require("fs");
|
|
44204
|
+
import_path75 = require("path");
|
|
43935
44205
|
init_utility_agents();
|
|
43936
44206
|
}
|
|
43937
44207
|
});
|
|
43938
44208
|
|
|
43939
44209
|
// packages/relay/src/dashboard/api-session.ts
|
|
43940
44210
|
function resolveGitBranch(cwd) {
|
|
43941
|
-
return new Promise((
|
|
44211
|
+
return new Promise((resolve33) => {
|
|
43942
44212
|
let done = false;
|
|
43943
44213
|
const child = (0, import_node_child_process2.execFile)(
|
|
43944
44214
|
"git",
|
|
@@ -43948,21 +44218,21 @@ function resolveGitBranch(cwd) {
|
|
|
43948
44218
|
if (done) return;
|
|
43949
44219
|
done = true;
|
|
43950
44220
|
if (err) {
|
|
43951
|
-
|
|
44221
|
+
resolve33(null);
|
|
43952
44222
|
return;
|
|
43953
44223
|
}
|
|
43954
44224
|
const branch = stdout.trim();
|
|
43955
44225
|
if (!branch || branch === "HEAD") {
|
|
43956
|
-
|
|
44226
|
+
resolve33(null);
|
|
43957
44227
|
return;
|
|
43958
44228
|
}
|
|
43959
|
-
|
|
44229
|
+
resolve33(branch);
|
|
43960
44230
|
}
|
|
43961
44231
|
);
|
|
43962
44232
|
child.on("error", () => {
|
|
43963
44233
|
if (!done) {
|
|
43964
44234
|
done = true;
|
|
43965
|
-
|
|
44235
|
+
resolve33(null);
|
|
43966
44236
|
}
|
|
43967
44237
|
});
|
|
43968
44238
|
});
|
|
@@ -43974,16 +44244,16 @@ async function sessionHandler(projectRoot) {
|
|
|
43974
44244
|
]);
|
|
43975
44245
|
return {
|
|
43976
44246
|
gitBranch,
|
|
43977
|
-
projectName: (0,
|
|
44247
|
+
projectName: (0, import_path76.basename)(projectRoot),
|
|
43978
44248
|
activeTasks
|
|
43979
44249
|
};
|
|
43980
44250
|
}
|
|
43981
|
-
var import_node_child_process2,
|
|
44251
|
+
var import_node_child_process2, import_path76;
|
|
43982
44252
|
var init_api_session = __esm({
|
|
43983
44253
|
"packages/relay/src/dashboard/api-session.ts"() {
|
|
43984
44254
|
"use strict";
|
|
43985
44255
|
import_node_child_process2 = require("node:child_process");
|
|
43986
|
-
|
|
44256
|
+
import_path76 = require("path");
|
|
43987
44257
|
init_api_active_tasks();
|
|
43988
44258
|
}
|
|
43989
44259
|
});
|
|
@@ -43997,25 +44267,25 @@ function categorize(text) {
|
|
|
43997
44267
|
return "other";
|
|
43998
44268
|
}
|
|
43999
44269
|
function logsHandler(projectRoot, query) {
|
|
44000
|
-
const logPath = (0,
|
|
44001
|
-
if (!(0,
|
|
44270
|
+
const logPath = (0, import_path77.join)(projectRoot, ".gossip", "mcp.log");
|
|
44271
|
+
if (!(0, import_fs69.existsSync)(logPath)) {
|
|
44002
44272
|
return { entries: [], totalLines: 0, fileSize: 0 };
|
|
44003
44273
|
}
|
|
44004
44274
|
const filter = query?.get("filter") || void 0;
|
|
44005
44275
|
const tail = parseInt(query?.get("tail") || "200", 10);
|
|
44006
44276
|
const clampedTail = Math.min(Math.max(tail, 10), 2e3);
|
|
44007
|
-
const fileSize = (0,
|
|
44277
|
+
const fileSize = (0, import_fs69.statSync)(logPath).size;
|
|
44008
44278
|
const MAX_READ = 512 * 1024;
|
|
44009
44279
|
const readFrom = Math.max(0, fileSize - MAX_READ);
|
|
44010
44280
|
const readLen = fileSize - readFrom;
|
|
44011
|
-
const fd = (0,
|
|
44281
|
+
const fd = (0, import_fs69.openSync)(logPath, "r");
|
|
44012
44282
|
let buf = Buffer.alloc(0);
|
|
44013
44283
|
try {
|
|
44014
44284
|
buf = Buffer.allocUnsafe(readLen);
|
|
44015
|
-
const bytesRead = (0,
|
|
44285
|
+
const bytesRead = (0, import_fs69.readSync)(fd, buf, 0, readLen, readFrom);
|
|
44016
44286
|
buf = buf.subarray(0, bytesRead);
|
|
44017
44287
|
} finally {
|
|
44018
|
-
(0,
|
|
44288
|
+
(0, import_fs69.closeSync)(fd);
|
|
44019
44289
|
}
|
|
44020
44290
|
let raw = buf.toString("utf-8");
|
|
44021
44291
|
let lineOffset = 0;
|
|
@@ -44023,13 +44293,13 @@ function logsHandler(projectRoot, query) {
|
|
|
44023
44293
|
const nl = raw.indexOf("\n");
|
|
44024
44294
|
raw = nl >= 0 ? raw.slice(nl + 1) : raw;
|
|
44025
44295
|
const SCAN_CHUNK = 64 * 1024;
|
|
44026
|
-
const scanFd = (0,
|
|
44296
|
+
const scanFd = (0, import_fs69.openSync)(logPath, "r");
|
|
44027
44297
|
try {
|
|
44028
44298
|
let pos = 0;
|
|
44029
44299
|
const chunk = Buffer.allocUnsafe(SCAN_CHUNK);
|
|
44030
44300
|
while (pos < readFrom) {
|
|
44031
44301
|
const len = Math.min(SCAN_CHUNK, readFrom - pos);
|
|
44032
|
-
const n = (0,
|
|
44302
|
+
const n = (0, import_fs69.readSync)(scanFd, chunk, 0, len, pos);
|
|
44033
44303
|
if (n === 0) break;
|
|
44034
44304
|
for (let j = 0; j < n; j++) {
|
|
44035
44305
|
if (chunk[j] === 10) lineOffset++;
|
|
@@ -44037,7 +44307,7 @@ function logsHandler(projectRoot, query) {
|
|
|
44037
44307
|
pos += n;
|
|
44038
44308
|
}
|
|
44039
44309
|
} finally {
|
|
44040
|
-
(0,
|
|
44310
|
+
(0, import_fs69.closeSync)(scanFd);
|
|
44041
44311
|
}
|
|
44042
44312
|
}
|
|
44043
44313
|
const allLines = raw.split("\n").filter(Boolean);
|
|
@@ -44055,12 +44325,12 @@ function logsHandler(projectRoot, query) {
|
|
|
44055
44325
|
entries = entries.slice(-clampedTail);
|
|
44056
44326
|
return { entries, totalLines, fileSize, filter };
|
|
44057
44327
|
}
|
|
44058
|
-
var
|
|
44328
|
+
var import_fs69, import_path77, CATEGORY_PATTERNS2;
|
|
44059
44329
|
var init_api_logs = __esm({
|
|
44060
44330
|
"packages/relay/src/dashboard/api-logs.ts"() {
|
|
44061
44331
|
"use strict";
|
|
44062
|
-
|
|
44063
|
-
|
|
44332
|
+
import_fs69 = require("fs");
|
|
44333
|
+
import_path77 = require("path");
|
|
44064
44334
|
CATEGORY_PATTERNS2 = [
|
|
44065
44335
|
[/^\[worker:/, "worker"],
|
|
44066
44336
|
[/^\[Gemini\]/, "gemini"],
|
|
@@ -44092,11 +44362,11 @@ function violationsHandler(projectRoot, query) {
|
|
|
44092
44362
|
const page = Math.max(1, parseInt(query?.get("page") ?? "1", 10));
|
|
44093
44363
|
const pageSize = Math.min(100, Math.max(1, parseInt(query?.get("pageSize") ?? "25", 10)));
|
|
44094
44364
|
const agentFilter = query?.get("agentId") ?? null;
|
|
44095
|
-
const filePath = (0,
|
|
44096
|
-
if (!(0,
|
|
44365
|
+
const filePath = (0, import_path78.join)(projectRoot, FILE);
|
|
44366
|
+
if (!(0, import_fs70.existsSync)(filePath)) {
|
|
44097
44367
|
return { items: [], total: 0, page, pageSize };
|
|
44098
44368
|
}
|
|
44099
|
-
const raw = (0,
|
|
44369
|
+
const raw = (0, import_fs70.readFileSync)(filePath, "utf-8");
|
|
44100
44370
|
const lines = raw.trim().split("\n").filter(Boolean);
|
|
44101
44371
|
const entries = [];
|
|
44102
44372
|
for (const line of lines) {
|
|
@@ -44116,12 +44386,12 @@ function violationsHandler(projectRoot, query) {
|
|
|
44116
44386
|
const start = (page - 1) * pageSize;
|
|
44117
44387
|
return { items: entries.slice(start, start + pageSize), total, page, pageSize };
|
|
44118
44388
|
}
|
|
44119
|
-
var
|
|
44389
|
+
var import_fs70, import_path78, FILE;
|
|
44120
44390
|
var init_api_violations = __esm({
|
|
44121
44391
|
"packages/relay/src/dashboard/api-violations.ts"() {
|
|
44122
44392
|
"use strict";
|
|
44123
|
-
|
|
44124
|
-
|
|
44393
|
+
import_fs70 = require("fs");
|
|
44394
|
+
import_path78 = require("path");
|
|
44125
44395
|
FILE = ".gossip/process-violations.jsonl";
|
|
44126
44396
|
}
|
|
44127
44397
|
});
|
|
@@ -44217,12 +44487,12 @@ function isMirrorFrameShaped(obj) {
|
|
|
44217
44487
|
const f = obj;
|
|
44218
44488
|
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
44489
|
}
|
|
44220
|
-
var
|
|
44490
|
+
var import_fs71, import_path79, CHAT_ID_RE, PERSIST_CAP, MAX_LINE_BYTES, NullChatStore, FileChatStore;
|
|
44221
44491
|
var init_chat_store = __esm({
|
|
44222
44492
|
"packages/relay/src/dashboard/chat-store.ts"() {
|
|
44223
44493
|
"use strict";
|
|
44224
|
-
|
|
44225
|
-
|
|
44494
|
+
import_fs71 = require("fs");
|
|
44495
|
+
import_path79 = require("path");
|
|
44226
44496
|
CHAT_ID_RE = /^[a-zA-Z0-9_-]{1,128}$/;
|
|
44227
44497
|
PERSIST_CAP = 1e3;
|
|
44228
44498
|
MAX_LINE_BYTES = 256 * 1024;
|
|
@@ -44254,15 +44524,15 @@ var init_chat_store = __esm({
|
|
|
44254
44524
|
return CHAT_ID_RE.test(chatId);
|
|
44255
44525
|
}
|
|
44256
44526
|
filePath(chatId) {
|
|
44257
|
-
return (0,
|
|
44527
|
+
return (0, import_path79.join)(this.chatDir, `${chatId}.jsonl`);
|
|
44258
44528
|
}
|
|
44259
44529
|
append(chatId, frame) {
|
|
44260
44530
|
if (!this.isValidChatId(chatId)) return;
|
|
44261
44531
|
if (chatId.startsWith("_")) return;
|
|
44262
44532
|
try {
|
|
44263
|
-
(0,
|
|
44533
|
+
(0, import_fs71.mkdirSync)(this.chatDir, { recursive: true });
|
|
44264
44534
|
const line = JSON.stringify(frame) + "\n";
|
|
44265
|
-
(0,
|
|
44535
|
+
(0, import_fs71.appendFileSync)(this.filePath(chatId), line, "utf8");
|
|
44266
44536
|
const prev = this.appendCounters.get(chatId);
|
|
44267
44537
|
const count = (prev ?? 0) + 1;
|
|
44268
44538
|
this.appendCounters.set(chatId, count);
|
|
@@ -44278,13 +44548,13 @@ var init_chat_store = __esm({
|
|
|
44278
44548
|
if (chatId.startsWith("_")) return;
|
|
44279
44549
|
try {
|
|
44280
44550
|
const fp = this.filePath(chatId);
|
|
44281
|
-
const content = (0,
|
|
44551
|
+
const content = (0, import_fs71.readFileSync)(fp, "utf8");
|
|
44282
44552
|
const lines = content.split("\n").filter((l) => l.length > 0);
|
|
44283
44553
|
if (lines.length < 2 * PERSIST_CAP) return;
|
|
44284
44554
|
const kept = lines.slice(lines.length - PERSIST_CAP);
|
|
44285
44555
|
const tmp = fp + ".tmp";
|
|
44286
|
-
(0,
|
|
44287
|
-
(0,
|
|
44556
|
+
(0, import_fs71.writeFileSync)(tmp, kept.join("\n") + "\n", "utf8");
|
|
44557
|
+
(0, import_fs71.renameSync)(tmp, fp);
|
|
44288
44558
|
} catch (err) {
|
|
44289
44559
|
this.cleanupStaleTmp(chatId);
|
|
44290
44560
|
console.warn(`[chat-store] retain failed for chatId=${chatId}`, err);
|
|
@@ -44299,7 +44569,7 @@ var init_chat_store = __esm({
|
|
|
44299
44569
|
*/
|
|
44300
44570
|
cleanupStaleTmp(chatId) {
|
|
44301
44571
|
try {
|
|
44302
|
-
(0,
|
|
44572
|
+
(0, import_fs71.unlinkSync)(this.filePath(chatId) + ".tmp");
|
|
44303
44573
|
} catch (err) {
|
|
44304
44574
|
if (err?.code !== "ENOENT") {
|
|
44305
44575
|
console.warn(`[chat-store] stale .tmp cleanup failed for chatId=${chatId}:`, err);
|
|
@@ -44311,7 +44581,7 @@ var init_chat_store = __esm({
|
|
|
44311
44581
|
this.cleanupStaleTmp(chatId);
|
|
44312
44582
|
let content;
|
|
44313
44583
|
try {
|
|
44314
|
-
content = (0,
|
|
44584
|
+
content = (0, import_fs71.readFileSync)(this.filePath(chatId), "utf8");
|
|
44315
44585
|
} catch (err) {
|
|
44316
44586
|
if (err?.code === "ENOENT") return [];
|
|
44317
44587
|
console.warn(`[chat-store] load failed for chatId=${chatId}:`, err);
|
|
@@ -44341,7 +44611,7 @@ var init_chat_store = __esm({
|
|
|
44341
44611
|
drop(chatId) {
|
|
44342
44612
|
if (!this.isValidChatId(chatId)) return;
|
|
44343
44613
|
try {
|
|
44344
|
-
(0,
|
|
44614
|
+
(0, import_fs71.unlinkSync)(this.filePath(chatId));
|
|
44345
44615
|
} catch (err) {
|
|
44346
44616
|
if (err?.code !== "ENOENT") {
|
|
44347
44617
|
console.warn(`[chat-store] drop failed for chatId=${chatId}:`, err);
|
|
@@ -45552,20 +45822,20 @@ function normalizeLegacyDegradedFields(report) {
|
|
|
45552
45822
|
}
|
|
45553
45823
|
function resolveDashboardRoot(projectRoot) {
|
|
45554
45824
|
const candidates = [
|
|
45555
|
-
(0,
|
|
45825
|
+
(0, import_path80.resolve)(__dirname, "..", "dist-dashboard"),
|
|
45556
45826
|
// bundled: dist-mcp/mcp-server.js → ../dist-dashboard
|
|
45557
|
-
(0,
|
|
45827
|
+
(0, import_path80.resolve)(__dirname, "..", "..", "..", "..", "dist-dashboard"),
|
|
45558
45828
|
// tsc dev: packages/relay/dist/dashboard → repo-root
|
|
45559
|
-
(0,
|
|
45829
|
+
(0, import_path80.join)(projectRoot, "dist-dashboard")
|
|
45560
45830
|
// legacy dev fallback (git-clone running from repo root)
|
|
45561
45831
|
];
|
|
45562
45832
|
for (const p of candidates) {
|
|
45563
|
-
if ((0,
|
|
45833
|
+
if ((0, import_fs72.existsSync)(p)) return p;
|
|
45564
45834
|
}
|
|
45565
45835
|
return null;
|
|
45566
45836
|
}
|
|
45567
45837
|
function readBody(req, maxBytes = MAX_BODY_SIZE) {
|
|
45568
|
-
return new Promise((
|
|
45838
|
+
return new Promise((resolve33, reject) => {
|
|
45569
45839
|
const chunks = [];
|
|
45570
45840
|
let size = 0;
|
|
45571
45841
|
let tooLarge = false;
|
|
@@ -45580,14 +45850,14 @@ function readBody(req, maxBytes = MAX_BODY_SIZE) {
|
|
|
45580
45850
|
chunks.push(chunk);
|
|
45581
45851
|
});
|
|
45582
45852
|
req.on("end", () => {
|
|
45583
|
-
if (!tooLarge)
|
|
45853
|
+
if (!tooLarge) resolve33(Buffer.concat(chunks).toString("utf-8"));
|
|
45584
45854
|
});
|
|
45585
45855
|
req.on("error", (err) => {
|
|
45586
45856
|
if (!tooLarge) reject(err);
|
|
45587
45857
|
});
|
|
45588
45858
|
});
|
|
45589
45859
|
}
|
|
45590
|
-
var
|
|
45860
|
+
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
45861
|
var init_routes = __esm({
|
|
45592
45862
|
"packages/relay/src/dashboard/routes.ts"() {
|
|
45593
45863
|
"use strict";
|
|
@@ -45607,6 +45877,7 @@ var init_routes = __esm({
|
|
|
45607
45877
|
init_api_open_findings();
|
|
45608
45878
|
init_api_learnings();
|
|
45609
45879
|
init_api_tasks();
|
|
45880
|
+
init_api_task_detail();
|
|
45610
45881
|
init_api_active_tasks();
|
|
45611
45882
|
init_api_session();
|
|
45612
45883
|
init_api_logs();
|
|
@@ -45615,8 +45886,8 @@ var init_routes = __esm({
|
|
|
45615
45886
|
init_api_bridge();
|
|
45616
45887
|
init_chat_session_store();
|
|
45617
45888
|
init_src4();
|
|
45618
|
-
|
|
45619
|
-
|
|
45889
|
+
import_fs72 = require("fs");
|
|
45890
|
+
import_path80 = require("path");
|
|
45620
45891
|
import_crypto28 = require("crypto");
|
|
45621
45892
|
AUTH_MAX_ATTEMPTS = 10;
|
|
45622
45893
|
AUTH_LOCKOUT_MS = 6e4;
|
|
@@ -45634,7 +45905,7 @@ var init_routes = __esm({
|
|
|
45634
45905
|
this.projectRoot = projectRoot;
|
|
45635
45906
|
this.ctx = ctx2;
|
|
45636
45907
|
this.dashboardRoot = resolveDashboardRoot(projectRoot);
|
|
45637
|
-
this.bridge = new BridgeHub({ chatDir: (0,
|
|
45908
|
+
this.bridge = new BridgeHub({ chatDir: (0, import_path80.join)(projectRoot, ".gossip", "chat") });
|
|
45638
45909
|
}
|
|
45639
45910
|
auth;
|
|
45640
45911
|
projectRoot;
|
|
@@ -45935,6 +46206,19 @@ var init_routes = __esm({
|
|
|
45935
46206
|
this.json(res, 200, data);
|
|
45936
46207
|
return true;
|
|
45937
46208
|
}
|
|
46209
|
+
{
|
|
46210
|
+
const m = url2.match(/^\/dashboard\/api\/tasks\/([^/]+)$/);
|
|
46211
|
+
if (m && req.method === "GET") {
|
|
46212
|
+
const taskId = decodeURIComponent(m[1]);
|
|
46213
|
+
const data = await taskDetailHandler(this.projectRoot, taskId);
|
|
46214
|
+
if (data === null) {
|
|
46215
|
+
this.json(res, 404, { error: `Task not found: ${taskId}` });
|
|
46216
|
+
} else {
|
|
46217
|
+
this.json(res, 200, data);
|
|
46218
|
+
}
|
|
46219
|
+
return true;
|
|
46220
|
+
}
|
|
46221
|
+
}
|
|
45938
46222
|
if (url2 === "/dashboard/api/active-tasks" && req.method === "GET") {
|
|
45939
46223
|
const data = await activeTasksHandler(this.projectRoot);
|
|
45940
46224
|
this.json(res, 200, data);
|
|
@@ -46147,13 +46431,13 @@ var init_routes = __esm({
|
|
|
46147
46431
|
res.end("Dashboard assets not found. Reinstall gossipcat or rebuild from source.");
|
|
46148
46432
|
return true;
|
|
46149
46433
|
}
|
|
46150
|
-
const htmlPath = (0,
|
|
46151
|
-
if (!(0,
|
|
46434
|
+
const htmlPath = (0, import_path80.join)(this.dashboardRoot, "index.html");
|
|
46435
|
+
if (!(0, import_fs72.existsSync)(htmlPath)) {
|
|
46152
46436
|
res.writeHead(503, { "Content-Type": "text/plain" });
|
|
46153
46437
|
res.end(`Dashboard index.html missing at ${this.dashboardRoot}. Reinstall gossipcat.`);
|
|
46154
46438
|
return true;
|
|
46155
46439
|
}
|
|
46156
|
-
const html = (0,
|
|
46440
|
+
const html = (0, import_fs72.readFileSync)(htmlPath, "utf-8");
|
|
46157
46441
|
res.writeHead(200, {
|
|
46158
46442
|
"Content-Type": "text/html; charset=utf-8",
|
|
46159
46443
|
"Cache-Control": "no-cache"
|
|
@@ -46182,16 +46466,16 @@ var init_routes = __esm({
|
|
|
46182
46466
|
const ext = "." + (relativePath.split(".").pop() || "");
|
|
46183
46467
|
const mime = MIME[ext];
|
|
46184
46468
|
if (!mime) return false;
|
|
46185
|
-
const filePath = (0,
|
|
46469
|
+
const filePath = (0, import_path80.join)(this.dashboardRoot, relativePath);
|
|
46186
46470
|
try {
|
|
46187
|
-
const realFile = (0,
|
|
46188
|
-
const realBase = (0,
|
|
46471
|
+
const realFile = (0, import_fs72.realpathSync)(filePath);
|
|
46472
|
+
const realBase = (0, import_fs72.realpathSync)(this.dashboardRoot);
|
|
46189
46473
|
if (!realFile.startsWith(realBase + "/")) {
|
|
46190
46474
|
res.writeHead(404);
|
|
46191
46475
|
res.end();
|
|
46192
46476
|
return true;
|
|
46193
46477
|
}
|
|
46194
|
-
const data = (0,
|
|
46478
|
+
const data = (0, import_fs72.readFileSync)(realFile);
|
|
46195
46479
|
res.writeHead(200, { "Content-Type": mime, "Cache-Control": "public, max-age=86400" });
|
|
46196
46480
|
res.end(data);
|
|
46197
46481
|
return true;
|
|
@@ -46206,8 +46490,8 @@ var init_routes = __esm({
|
|
|
46206
46490
|
return match ? match[1] : null;
|
|
46207
46491
|
}
|
|
46208
46492
|
getConsensusReports(page = 1, pageSize = 5) {
|
|
46209
|
-
const { readdirSync: readdirSync22, readFileSync:
|
|
46210
|
-
const reportsDir = (0,
|
|
46493
|
+
const { readdirSync: readdirSync22, readFileSync: readFileSync70, existsSync: existsSync74 } = require("fs");
|
|
46494
|
+
const reportsDir = (0, import_path80.join)(this.projectRoot, ".gossip", "consensus-reports");
|
|
46211
46495
|
let retractedConsensusIds = [];
|
|
46212
46496
|
let roundRetractions = [];
|
|
46213
46497
|
try {
|
|
@@ -46217,13 +46501,13 @@ var init_routes = __esm({
|
|
|
46217
46501
|
roundRetractions = reader.getRoundRetractions();
|
|
46218
46502
|
} catch {
|
|
46219
46503
|
}
|
|
46220
|
-
if (!
|
|
46504
|
+
if (!existsSync74(reportsDir)) return { reports: [], totalReports: 0, page, pageSize, retractedConsensusIds, roundRetractions };
|
|
46221
46505
|
try {
|
|
46222
46506
|
const { statSync: statSync36 } = require("fs");
|
|
46223
46507
|
const allFiles = readdirSync22(reportsDir).filter((f) => f.endsWith(".json")).sort((a, b) => {
|
|
46224
46508
|
try {
|
|
46225
|
-
const aTime = statSync36((0,
|
|
46226
|
-
const bTime = statSync36((0,
|
|
46509
|
+
const aTime = statSync36((0, import_path80.join)(reportsDir, a)).mtimeMs;
|
|
46510
|
+
const bTime = statSync36((0, import_path80.join)(reportsDir, b)).mtimeMs;
|
|
46227
46511
|
return bTime - aTime;
|
|
46228
46512
|
} catch {
|
|
46229
46513
|
return 0;
|
|
@@ -46234,13 +46518,13 @@ var init_routes = __esm({
|
|
|
46234
46518
|
const clampedPage = Math.max(page, 1);
|
|
46235
46519
|
const start = (clampedPage - 1) * clampedPageSize;
|
|
46236
46520
|
const files = allFiles.slice(start, start + clampedPageSize);
|
|
46237
|
-
const realReportsDir = (0,
|
|
46521
|
+
const realReportsDir = (0, import_fs72.realpathSync)(reportsDir);
|
|
46238
46522
|
const reports = files.map((f) => {
|
|
46239
46523
|
try {
|
|
46240
|
-
const filePath = (0,
|
|
46241
|
-
const realFile = (0,
|
|
46524
|
+
const filePath = (0, import_path80.join)(reportsDir, f);
|
|
46525
|
+
const realFile = (0, import_fs72.realpathSync)(filePath);
|
|
46242
46526
|
if (!realFile.startsWith(realReportsDir + "/")) return null;
|
|
46243
|
-
return normalizeLegacyDegradedFields(JSON.parse(
|
|
46527
|
+
return normalizeLegacyDegradedFields(JSON.parse(readFileSync70(realFile, "utf-8")));
|
|
46244
46528
|
} catch {
|
|
46245
46529
|
return null;
|
|
46246
46530
|
}
|
|
@@ -46251,29 +46535,29 @@ var init_routes = __esm({
|
|
|
46251
46535
|
}
|
|
46252
46536
|
}
|
|
46253
46537
|
archiveFindings() {
|
|
46254
|
-
const { readdirSync: readdirSync22, readFileSync:
|
|
46255
|
-
const reportsDir = (0,
|
|
46256
|
-
const archiveDir = (0,
|
|
46538
|
+
const { readdirSync: readdirSync22, readFileSync: readFileSync70, renameSync: renameSync18, writeFileSync: writeFileSync38, mkdirSync: mkdirSync45, existsSync: existsSync74 } = require("fs");
|
|
46539
|
+
const reportsDir = (0, import_path80.join)(this.projectRoot, ".gossip", "consensus-reports");
|
|
46540
|
+
const archiveDir = (0, import_path80.join)(this.projectRoot, ".gossip", "consensus-reports-archive");
|
|
46257
46541
|
let archived = 0;
|
|
46258
|
-
if (
|
|
46542
|
+
if (existsSync74(reportsDir)) {
|
|
46259
46543
|
const files = readdirSync22(reportsDir).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
46260
46544
|
if (files.length > 5) {
|
|
46261
46545
|
mkdirSync45(archiveDir, { recursive: true });
|
|
46262
46546
|
const toArchive = files.slice(5);
|
|
46263
46547
|
for (const f of toArchive) {
|
|
46264
46548
|
try {
|
|
46265
|
-
renameSync18((0,
|
|
46549
|
+
renameSync18((0, import_path80.join)(reportsDir, f), (0, import_path80.join)(archiveDir, f));
|
|
46266
46550
|
archived++;
|
|
46267
46551
|
} catch {
|
|
46268
46552
|
}
|
|
46269
46553
|
}
|
|
46270
46554
|
}
|
|
46271
46555
|
}
|
|
46272
|
-
const findingsPath = (0,
|
|
46556
|
+
const findingsPath = (0, import_path80.join)(this.projectRoot, ".gossip", "implementation-findings.jsonl");
|
|
46273
46557
|
let findingsCleared = 0;
|
|
46274
|
-
if (
|
|
46558
|
+
if (existsSync74(findingsPath)) {
|
|
46275
46559
|
try {
|
|
46276
|
-
const lines =
|
|
46560
|
+
const lines = readFileSync70(findingsPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
46277
46561
|
const kept = lines.filter((line) => {
|
|
46278
46562
|
try {
|
|
46279
46563
|
const entry = JSON.parse(line);
|
|
@@ -46290,7 +46574,7 @@ var init_routes = __esm({
|
|
|
46290
46574
|
} catch {
|
|
46291
46575
|
}
|
|
46292
46576
|
}
|
|
46293
|
-
const remaining =
|
|
46577
|
+
const remaining = existsSync74(reportsDir) ? readdirSync22(reportsDir).filter((f) => f.endsWith(".json")).length : 0;
|
|
46294
46578
|
return { archived, remaining, findingsCleared };
|
|
46295
46579
|
}
|
|
46296
46580
|
json(res, status, data) {
|
|
@@ -46303,14 +46587,14 @@ var init_routes = __esm({
|
|
|
46303
46587
|
});
|
|
46304
46588
|
|
|
46305
46589
|
// packages/relay/src/dashboard/ws.ts
|
|
46306
|
-
var
|
|
46590
|
+
var import_fs73, import_fs74, import_path81, DashboardWs;
|
|
46307
46591
|
var init_ws = __esm({
|
|
46308
46592
|
"packages/relay/src/dashboard/ws.ts"() {
|
|
46309
46593
|
"use strict";
|
|
46310
46594
|
init_wrapper();
|
|
46311
|
-
import_fs72 = require("fs");
|
|
46312
46595
|
import_fs73 = require("fs");
|
|
46313
|
-
|
|
46596
|
+
import_fs74 = require("fs");
|
|
46597
|
+
import_path81 = require("path");
|
|
46314
46598
|
DashboardWs = class {
|
|
46315
46599
|
clients = /* @__PURE__ */ new Set();
|
|
46316
46600
|
logWatcher = null;
|
|
@@ -46335,15 +46619,15 @@ var init_ws = __esm({
|
|
|
46335
46619
|
/** Start watching mcp.log for new lines and broadcasting them to connected clients. */
|
|
46336
46620
|
startLogWatcher(projectRoot) {
|
|
46337
46621
|
this.stopLogWatcher();
|
|
46338
|
-
this.logPath = (0,
|
|
46339
|
-
if (!(0,
|
|
46622
|
+
this.logPath = (0, import_path81.join)(projectRoot, ".gossip", "mcp.log");
|
|
46623
|
+
if (!(0, import_fs73.existsSync)(this.logPath)) return;
|
|
46340
46624
|
try {
|
|
46341
|
-
this.logOffset = (0,
|
|
46625
|
+
this.logOffset = (0, import_fs73.statSync)(this.logPath).size;
|
|
46342
46626
|
} catch {
|
|
46343
46627
|
this.logOffset = 0;
|
|
46344
46628
|
}
|
|
46345
46629
|
try {
|
|
46346
|
-
this.logWatcher = (0,
|
|
46630
|
+
this.logWatcher = (0, import_fs74.watch)(this.logPath, () => {
|
|
46347
46631
|
if (this.clients.size === 0) return;
|
|
46348
46632
|
this.readNewLines();
|
|
46349
46633
|
});
|
|
@@ -46360,7 +46644,7 @@ var init_ws = __esm({
|
|
|
46360
46644
|
if (this.logReading) return;
|
|
46361
46645
|
this.logReading = true;
|
|
46362
46646
|
try {
|
|
46363
|
-
const currentSize = (0,
|
|
46647
|
+
const currentSize = (0, import_fs73.statSync)(this.logPath).size;
|
|
46364
46648
|
if (currentSize < this.logOffset) {
|
|
46365
46649
|
this.logOffset = 0;
|
|
46366
46650
|
this.logCarry = "";
|
|
@@ -46373,7 +46657,7 @@ var init_ws = __esm({
|
|
|
46373
46657
|
const readFrom = capped ? (this.logCarry = "", this.logCapped = true, currentSize - 65536) : (this.logCapped = false, this.logOffset);
|
|
46374
46658
|
let stream;
|
|
46375
46659
|
try {
|
|
46376
|
-
stream = (0,
|
|
46660
|
+
stream = (0, import_fs73.createReadStream)(this.logPath, { start: readFrom, end: currentSize - 1 });
|
|
46377
46661
|
} catch {
|
|
46378
46662
|
this.logReading = false;
|
|
46379
46663
|
return;
|
|
@@ -46487,7 +46771,7 @@ var init_server = __esm({
|
|
|
46487
46771
|
return this.heartbeatRunning;
|
|
46488
46772
|
}
|
|
46489
46773
|
async start() {
|
|
46490
|
-
return new Promise((
|
|
46774
|
+
return new Promise((resolve33) => {
|
|
46491
46775
|
this.httpServer = (0, import_http.createServer)(this.handleHttp.bind(this));
|
|
46492
46776
|
if (this.config.dashboard) {
|
|
46493
46777
|
this.dashboardAuth = new DashboardAuth();
|
|
@@ -46533,7 +46817,7 @@ var init_server = __esm({
|
|
|
46533
46817
|
this.httpServer.listen(this.config.port, this.config.host ?? "127.0.0.1", () => {
|
|
46534
46818
|
const addr = this.httpServer.address();
|
|
46535
46819
|
this._port = addr.port;
|
|
46536
|
-
|
|
46820
|
+
resolve33();
|
|
46537
46821
|
});
|
|
46538
46822
|
});
|
|
46539
46823
|
}
|
|
@@ -46553,9 +46837,9 @@ var init_server = __esm({
|
|
|
46553
46837
|
for (const client of this.wss.clients) {
|
|
46554
46838
|
client.close(1001, "Server shutting down");
|
|
46555
46839
|
}
|
|
46556
|
-
return new Promise((
|
|
46840
|
+
return new Promise((resolve33) => {
|
|
46557
46841
|
this.wss.close(() => {
|
|
46558
|
-
this.httpServer.close(() =>
|
|
46842
|
+
this.httpServer.close(() => resolve33());
|
|
46559
46843
|
});
|
|
46560
46844
|
});
|
|
46561
46845
|
}
|
|
@@ -46969,8 +47253,8 @@ function parsePorcelain(output) {
|
|
|
46969
47253
|
const paths = [];
|
|
46970
47254
|
for (const line of lines) {
|
|
46971
47255
|
if (line.length < 4) continue;
|
|
46972
|
-
const
|
|
46973
|
-
if (
|
|
47256
|
+
const path8 = line.slice(3);
|
|
47257
|
+
if (path8) paths.push(path8);
|
|
46974
47258
|
}
|
|
46975
47259
|
return paths.sort();
|
|
46976
47260
|
}
|
|
@@ -46993,12 +47277,12 @@ function revertLeakedPaths(cwd, paths) {
|
|
|
46993
47277
|
if (!paths || paths.length === 0) return result;
|
|
46994
47278
|
const { safe: safePaths, rejected } = filterSafePaths(paths);
|
|
46995
47279
|
result.rejected = rejected;
|
|
46996
|
-
const
|
|
46997
|
-
const
|
|
47280
|
+
const fs7 = require("fs");
|
|
47281
|
+
const path8 = require("path");
|
|
46998
47282
|
const present = [];
|
|
46999
47283
|
for (const p of safePaths) {
|
|
47000
|
-
const abs =
|
|
47001
|
-
if (
|
|
47284
|
+
const abs = path8.join(cwd, p);
|
|
47285
|
+
if (fs7.existsSync(abs)) {
|
|
47002
47286
|
present.push(p);
|
|
47003
47287
|
} else {
|
|
47004
47288
|
result.skipped.push(p);
|
|
@@ -47028,12 +47312,12 @@ function preserveLeakedPaths(cwd, paths, taskId) {
|
|
|
47028
47312
|
}
|
|
47029
47313
|
const { safe: safePaths, rejected } = filterSafePaths(paths);
|
|
47030
47314
|
result.rejected = rejected;
|
|
47031
|
-
const
|
|
47032
|
-
const
|
|
47315
|
+
const fs7 = require("fs");
|
|
47316
|
+
const path8 = require("path");
|
|
47033
47317
|
const crypto3 = require("crypto");
|
|
47034
47318
|
const present = [];
|
|
47035
47319
|
for (const p of safePaths) {
|
|
47036
|
-
if (
|
|
47320
|
+
if (fs7.existsSync(path8.join(cwd, p))) {
|
|
47037
47321
|
present.push(p);
|
|
47038
47322
|
} else {
|
|
47039
47323
|
result.skipped.push(p);
|
|
@@ -47068,16 +47352,16 @@ function preserveLeakedPaths(cwd, paths, taskId) {
|
|
|
47068
47352
|
result.emptyDiff = true;
|
|
47069
47353
|
return result;
|
|
47070
47354
|
}
|
|
47071
|
-
const recoveryDir =
|
|
47072
|
-
|
|
47073
|
-
const finalPath =
|
|
47074
|
-
const tmpPath =
|
|
47355
|
+
const recoveryDir = path8.join(cwd, ".gossip", "recovery");
|
|
47356
|
+
fs7.mkdirSync(recoveryDir, { recursive: true });
|
|
47357
|
+
const finalPath = path8.join(recoveryDir, `${taskId}.patch`);
|
|
47358
|
+
const tmpPath = path8.join(recoveryDir, `${taskId}.patch.${crypto3.randomUUID().slice(0, 8)}.tmp`);
|
|
47075
47359
|
try {
|
|
47076
|
-
|
|
47077
|
-
|
|
47360
|
+
fs7.writeFileSync(tmpPath, diff);
|
|
47361
|
+
fs7.renameSync(tmpPath, finalPath);
|
|
47078
47362
|
} catch (err) {
|
|
47079
47363
|
try {
|
|
47080
|
-
|
|
47364
|
+
fs7.unlinkSync(tmpPath);
|
|
47081
47365
|
} catch {
|
|
47082
47366
|
}
|
|
47083
47367
|
throw err;
|
|
@@ -47221,14 +47505,14 @@ __export(sandbox_exports, {
|
|
|
47221
47505
|
});
|
|
47222
47506
|
function rotateIfNeeded2(filePath, maxBytes) {
|
|
47223
47507
|
try {
|
|
47224
|
-
const st = (0,
|
|
47508
|
+
const st = (0, import_fs75.statSync)(filePath);
|
|
47225
47509
|
if (st.size < maxBytes) return;
|
|
47226
47510
|
const rotated = filePath + ".1";
|
|
47227
47511
|
try {
|
|
47228
|
-
if ((0,
|
|
47512
|
+
if ((0, import_fs75.existsSync)(rotated)) (0, import_fs75.unlinkSync)(rotated);
|
|
47229
47513
|
} catch {
|
|
47230
47514
|
}
|
|
47231
|
-
(0,
|
|
47515
|
+
(0, import_fs75.renameSync)(filePath, rotated);
|
|
47232
47516
|
} catch {
|
|
47233
47517
|
}
|
|
47234
47518
|
}
|
|
@@ -47301,9 +47585,9 @@ Tests passing is NOT sufficient verification \u2014 the 2026-04-22 incident had
|
|
|
47301
47585
|
}
|
|
47302
47586
|
function readSandboxMode(projectRoot) {
|
|
47303
47587
|
try {
|
|
47304
|
-
const p = (0,
|
|
47305
|
-
if (!(0,
|
|
47306
|
-
const raw = JSON.parse((0,
|
|
47588
|
+
const p = (0, import_path82.join)(projectRoot, ".gossip", "config.json");
|
|
47589
|
+
if (!(0, import_fs75.existsSync)(p)) return "warn";
|
|
47590
|
+
const raw = JSON.parse((0, import_fs75.readFileSync)(p, "utf-8"));
|
|
47307
47591
|
const mode = raw?.sandboxEnforcement;
|
|
47308
47592
|
if (mode === "off" || mode === "warn" || mode === "block") return mode;
|
|
47309
47593
|
return "warn";
|
|
@@ -47313,8 +47597,8 @@ function readSandboxMode(projectRoot) {
|
|
|
47313
47597
|
}
|
|
47314
47598
|
function recordDispatchMetadata(projectRoot, meta3) {
|
|
47315
47599
|
try {
|
|
47316
|
-
const dir = (0,
|
|
47317
|
-
(0,
|
|
47600
|
+
const dir = (0, import_path82.join)(projectRoot, ".gossip");
|
|
47601
|
+
(0, import_fs75.mkdirSync)(dir, { recursive: true });
|
|
47318
47602
|
const snapshotted = { ...meta3 };
|
|
47319
47603
|
if (meta3.writeMode === "scoped" || meta3.writeMode === "worktree") {
|
|
47320
47604
|
try {
|
|
@@ -47332,15 +47616,15 @@ function recordDispatchMetadata(projectRoot, meta3) {
|
|
|
47332
47616
|
} catch {
|
|
47333
47617
|
}
|
|
47334
47618
|
}
|
|
47335
|
-
(0,
|
|
47619
|
+
(0, import_fs75.appendFileSync)((0, import_path82.join)(dir, METADATA_FILE), JSON.stringify(snapshotted) + "\n");
|
|
47336
47620
|
} catch {
|
|
47337
47621
|
}
|
|
47338
47622
|
}
|
|
47339
47623
|
function updateDispatchMetadata(projectRoot, taskId, patch) {
|
|
47340
47624
|
try {
|
|
47341
|
-
const p = (0,
|
|
47342
|
-
if (!(0,
|
|
47343
|
-
const raw = (0,
|
|
47625
|
+
const p = (0, import_path82.join)(projectRoot, ".gossip", METADATA_FILE);
|
|
47626
|
+
if (!(0, import_fs75.existsSync)(p)) return false;
|
|
47627
|
+
const raw = (0, import_fs75.readFileSync)(p, "utf-8");
|
|
47344
47628
|
const lines = raw.split("\n");
|
|
47345
47629
|
let patched = false;
|
|
47346
47630
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -47358,7 +47642,7 @@ function updateDispatchMetadata(projectRoot, taskId, patch) {
|
|
|
47358
47642
|
}
|
|
47359
47643
|
}
|
|
47360
47644
|
if (!patched) return false;
|
|
47361
|
-
(0,
|
|
47645
|
+
(0, import_fs75.writeFileSync)(p, lines.join("\n"));
|
|
47362
47646
|
return true;
|
|
47363
47647
|
} catch {
|
|
47364
47648
|
return false;
|
|
@@ -47367,15 +47651,15 @@ function updateDispatchMetadata(projectRoot, taskId, patch) {
|
|
|
47367
47651
|
function stampTaskSentinel(projectRoot, taskId) {
|
|
47368
47652
|
if (!taskId) return null;
|
|
47369
47653
|
try {
|
|
47370
|
-
const dir = (0,
|
|
47371
|
-
(0,
|
|
47654
|
+
const dir = (0, import_path82.join)(projectRoot, ".gossip", SENTINEL_DIR);
|
|
47655
|
+
(0, import_fs75.mkdirSync)(dir, { recursive: true });
|
|
47372
47656
|
const slug = taskId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
47373
|
-
const
|
|
47374
|
-
const fd = (0,
|
|
47375
|
-
(0,
|
|
47657
|
+
const path8 = (0, import_path82.join)(dir, `${slug}.sentinel`);
|
|
47658
|
+
const fd = (0, import_fs75.openSync)(path8, "w");
|
|
47659
|
+
(0, import_fs75.closeSync)(fd);
|
|
47376
47660
|
const stampTime = new Date(Date.now() - 2e3);
|
|
47377
|
-
(0,
|
|
47378
|
-
return
|
|
47661
|
+
(0, import_fs75.utimesSync)(path8, stampTime, stampTime);
|
|
47662
|
+
return path8;
|
|
47379
47663
|
} catch {
|
|
47380
47664
|
return null;
|
|
47381
47665
|
}
|
|
@@ -47383,15 +47667,15 @@ function stampTaskSentinel(projectRoot, taskId) {
|
|
|
47383
47667
|
function cleanupTaskSentinel(sentinelPath) {
|
|
47384
47668
|
if (!sentinelPath) return;
|
|
47385
47669
|
try {
|
|
47386
|
-
(0,
|
|
47670
|
+
(0, import_fs75.unlinkSync)(sentinelPath);
|
|
47387
47671
|
} catch {
|
|
47388
47672
|
}
|
|
47389
47673
|
}
|
|
47390
47674
|
function lookupDispatchMetadata(projectRoot, taskId) {
|
|
47391
47675
|
try {
|
|
47392
|
-
const p = (0,
|
|
47393
|
-
if (!(0,
|
|
47394
|
-
const raw = (0,
|
|
47676
|
+
const p = (0, import_path82.join)(projectRoot, ".gossip", METADATA_FILE);
|
|
47677
|
+
if (!(0, import_fs75.existsSync)(p)) return null;
|
|
47678
|
+
const raw = (0, import_fs75.readFileSync)(p, "utf-8");
|
|
47395
47679
|
const lines = raw.split("\n").filter(Boolean);
|
|
47396
47680
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
47397
47681
|
try {
|
|
@@ -47423,21 +47707,21 @@ function parseGitStatus(porcelain) {
|
|
|
47423
47707
|
function normalizeScope(scope, projectRoot) {
|
|
47424
47708
|
let s = scope.trim();
|
|
47425
47709
|
if (!s) return "";
|
|
47426
|
-
if ((0,
|
|
47427
|
-
s = (0,
|
|
47710
|
+
if ((0, import_path82.isAbsolute)(s)) {
|
|
47711
|
+
s = (0, import_path82.relative)(projectRoot, s);
|
|
47428
47712
|
} else if (s.startsWith("./")) {
|
|
47429
47713
|
s = s.slice(2);
|
|
47430
47714
|
}
|
|
47431
|
-
s = (0,
|
|
47715
|
+
s = (0, import_path82.normalize)(s).replace(/\/+$/, "");
|
|
47432
47716
|
if (s === "." || s === "") return "";
|
|
47433
47717
|
return s;
|
|
47434
47718
|
}
|
|
47435
47719
|
function isInsideScope(filePath, scope) {
|
|
47436
47720
|
if (!scope) return true;
|
|
47437
|
-
const f = (0,
|
|
47721
|
+
const f = (0, import_path82.normalize)(filePath).replace(/^\.\//, "");
|
|
47438
47722
|
const s = scope.replace(/^\.\//, "").replace(/\/+$/, "");
|
|
47439
47723
|
if (f === s) return true;
|
|
47440
|
-
return f.startsWith(s + "/") || f.startsWith(s +
|
|
47724
|
+
return f.startsWith(s + "/") || f.startsWith(s + import_path82.sep);
|
|
47441
47725
|
}
|
|
47442
47726
|
function detectBoundaryEscapes(meta3, modifiedFiles, projectRoot) {
|
|
47443
47727
|
const mode = meta3.writeMode;
|
|
@@ -47498,8 +47782,8 @@ function recordBoundaryEscape(projectRoot, meta3, violations, mode) {
|
|
|
47498
47782
|
} catch {
|
|
47499
47783
|
}
|
|
47500
47784
|
try {
|
|
47501
|
-
const dir = (0,
|
|
47502
|
-
(0,
|
|
47785
|
+
const dir = (0, import_path82.join)(projectRoot, ".gossip");
|
|
47786
|
+
(0, import_fs75.mkdirSync)(dir, { recursive: true });
|
|
47503
47787
|
const line = {
|
|
47504
47788
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
47505
47789
|
taskId: meta3.taskId,
|
|
@@ -47510,15 +47794,15 @@ function recordBoundaryEscape(projectRoot, meta3, violations, mode) {
|
|
|
47510
47794
|
action: mode
|
|
47511
47795
|
// "warn" or "block"
|
|
47512
47796
|
};
|
|
47513
|
-
const escapeFile = (0,
|
|
47797
|
+
const escapeFile = (0, import_path82.join)(dir, BOUNDARY_ESCAPE_FILE);
|
|
47514
47798
|
rotateIfNeeded2(escapeFile, MAX_BOUNDARY_ESCAPE_BYTES);
|
|
47515
|
-
(0,
|
|
47799
|
+
(0, import_fs75.appendFileSync)(escapeFile, JSON.stringify(line) + "\n");
|
|
47516
47800
|
} catch {
|
|
47517
47801
|
}
|
|
47518
47802
|
}
|
|
47519
47803
|
function canonicalize(p) {
|
|
47520
47804
|
try {
|
|
47521
|
-
return (0,
|
|
47805
|
+
return (0, import_path82.resolve)(p).replace(/\/+$/, "") || "/";
|
|
47522
47806
|
} catch {
|
|
47523
47807
|
return p.replace(/\/+$/, "") || "/";
|
|
47524
47808
|
}
|
|
@@ -47544,8 +47828,8 @@ function defaultScanRoots(writeMode, projectRoot) {
|
|
|
47544
47828
|
out.add("/private/tmp");
|
|
47545
47829
|
return Array.from(out);
|
|
47546
47830
|
}
|
|
47547
|
-
function expandTmpVariants(
|
|
47548
|
-
const p =
|
|
47831
|
+
function expandTmpVariants(path8) {
|
|
47832
|
+
const p = path8.replace(/\/+$/, "") || "/";
|
|
47549
47833
|
for (const root of ["/tmp", "/etc", "/var"]) {
|
|
47550
47834
|
if (p === root || p.startsWith(root + "/")) {
|
|
47551
47835
|
return [p, "/private" + p];
|
|
@@ -47629,7 +47913,7 @@ function buildAuditExclusions(projectRoot, ownWorktree, scope) {
|
|
|
47629
47913
|
for (const v of expandTmpVariants(wt)) excl.add(v);
|
|
47630
47914
|
}
|
|
47631
47915
|
if (scope) {
|
|
47632
|
-
const s = canonicalize((0,
|
|
47916
|
+
const s = canonicalize((0, import_path82.join)(projectRoot, scope));
|
|
47633
47917
|
for (const v of expandTmpVariants(s)) excl.add(v);
|
|
47634
47918
|
}
|
|
47635
47919
|
return Array.from(excl);
|
|
@@ -47718,12 +48002,12 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
|
|
|
47718
48002
|
return { violations: [], skipped: "win32" };
|
|
47719
48003
|
}
|
|
47720
48004
|
const sentinel = meta3.sentinelPath;
|
|
47721
|
-
if (!sentinel || !(0,
|
|
48005
|
+
if (!sentinel || !(0, import_fs75.existsSync)(sentinel)) {
|
|
47722
48006
|
return { violations: [], skipped: "sentinel missing" };
|
|
47723
48007
|
}
|
|
47724
48008
|
let sentinelMtimeMs = 0;
|
|
47725
48009
|
try {
|
|
47726
|
-
sentinelMtimeMs = (0,
|
|
48010
|
+
sentinelMtimeMs = (0, import_fs75.statSync)(sentinel).mtimeMs;
|
|
47727
48011
|
} catch {
|
|
47728
48012
|
}
|
|
47729
48013
|
if (sentinelMtimeMs === 0) {
|
|
@@ -47735,11 +48019,11 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
|
|
|
47735
48019
|
);
|
|
47736
48020
|
const exclusions = buildAuditExclusions(projectRoot, meta3.worktreePath, options.scope);
|
|
47737
48021
|
const findBin = options.findBinary ?? "find";
|
|
47738
|
-
const sentinelDir = canonicalize((0,
|
|
48022
|
+
const sentinelDir = canonicalize((0, import_path82.join)(projectRoot, ".gossip", SENTINEL_DIR));
|
|
47739
48023
|
const mainSet = /* @__PURE__ */ new Set();
|
|
47740
48024
|
const sensitiveSet = /* @__PURE__ */ new Set();
|
|
47741
48025
|
for (const root of scanRoots) {
|
|
47742
|
-
if (!(0,
|
|
48026
|
+
if (!(0, import_fs75.existsSync)(root)) continue;
|
|
47743
48027
|
const canonRoot = canonicalize(root);
|
|
47744
48028
|
const allExcl = [...exclusions, ...expandTmpVariants(sentinelDir)];
|
|
47745
48029
|
const args = buildFindPruneArgs(canonRoot, allExcl, sentinel);
|
|
@@ -47775,7 +48059,7 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
|
|
|
47775
48059
|
}
|
|
47776
48060
|
const sensitiveTargets = buildSensitiveTargets(platform2);
|
|
47777
48061
|
for (const target of sensitiveTargets) {
|
|
47778
|
-
if (!(0,
|
|
48062
|
+
if (!(0, import_fs75.existsSync)(target.path)) continue;
|
|
47779
48063
|
const canonTarget = canonicalize(target.path);
|
|
47780
48064
|
const args = buildSensitiveFindArgs(
|
|
47781
48065
|
canonTarget,
|
|
@@ -47849,21 +48133,21 @@ function auditFilesystemSinceSentinel(projectRoot, meta3, options = {}) {
|
|
|
47849
48133
|
}
|
|
47850
48134
|
function recordLayer3Violations(projectRoot, meta3, violations, source) {
|
|
47851
48135
|
try {
|
|
47852
|
-
const dir = (0,
|
|
47853
|
-
(0,
|
|
48136
|
+
const dir = (0, import_path82.join)(projectRoot, ".gossip");
|
|
48137
|
+
(0, import_fs75.mkdirSync)(dir, { recursive: true });
|
|
47854
48138
|
const ts2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
47855
48139
|
const lines = violations.map(
|
|
47856
|
-
(
|
|
48140
|
+
(path8) => JSON.stringify({
|
|
47857
48141
|
timestamp: ts2,
|
|
47858
48142
|
taskId: meta3.taskId,
|
|
47859
48143
|
agentId: meta3.agentId,
|
|
47860
|
-
violatingPaths: [
|
|
48144
|
+
violatingPaths: [path8],
|
|
47861
48145
|
source
|
|
47862
48146
|
})
|
|
47863
48147
|
);
|
|
47864
|
-
const escapeFile = (0,
|
|
48148
|
+
const escapeFile = (0, import_path82.join)(dir, BOUNDARY_ESCAPE_FILE);
|
|
47865
48149
|
rotateIfNeeded2(escapeFile, MAX_BOUNDARY_ESCAPE_BYTES);
|
|
47866
|
-
(0,
|
|
48150
|
+
(0, import_fs75.appendFileSync)(escapeFile, lines.join("\n") + "\n");
|
|
47867
48151
|
} catch {
|
|
47868
48152
|
}
|
|
47869
48153
|
if (source === "layer3-sensitive" && violations.length > 0) {
|
|
@@ -47920,14 +48204,14 @@ function runLayer3Audit(projectRoot, taskId) {
|
|
|
47920
48204
|
}
|
|
47921
48205
|
return { blockError, warnPrefix };
|
|
47922
48206
|
}
|
|
47923
|
-
var import_child_process12,
|
|
48207
|
+
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
48208
|
var init_sandbox2 = __esm({
|
|
47925
48209
|
"apps/cli/src/sandbox.ts"() {
|
|
47926
48210
|
"use strict";
|
|
47927
48211
|
import_child_process12 = require("child_process");
|
|
47928
|
-
|
|
48212
|
+
import_fs75 = require("fs");
|
|
47929
48213
|
import_os5 = require("os");
|
|
47930
|
-
|
|
48214
|
+
import_path82 = require("path");
|
|
47931
48215
|
METADATA_FILE = "dispatch-metadata.jsonl";
|
|
47932
48216
|
BOUNDARY_ESCAPE_FILE = "boundary-escapes.jsonl";
|
|
47933
48217
|
SENTINEL_DIR = "sentinels";
|
|
@@ -47999,7 +48283,7 @@ __export(dispatch_prompt_storage_exports, {
|
|
|
47999
48283
|
writeDispatchPrompt: () => writeDispatchPrompt
|
|
48000
48284
|
});
|
|
48001
48285
|
function dispatchPromptsDir(projectRoot) {
|
|
48002
|
-
return (0,
|
|
48286
|
+
return (0, import_path83.join)(projectRoot, ".gossip", DISPATCH_PROMPTS_SUBDIR);
|
|
48003
48287
|
}
|
|
48004
48288
|
function assertSafeTaskId(taskId) {
|
|
48005
48289
|
if (typeof taskId !== "string" || taskId.length === 0) {
|
|
@@ -48012,35 +48296,35 @@ function assertSafeTaskId(taskId) {
|
|
|
48012
48296
|
function writeDispatchPrompt(projectRoot, taskId, body) {
|
|
48013
48297
|
assertSafeTaskId(taskId);
|
|
48014
48298
|
const dir = dispatchPromptsDir(projectRoot);
|
|
48015
|
-
(0,
|
|
48016
|
-
const finalPath = (0,
|
|
48017
|
-
const tmpPath = (0,
|
|
48299
|
+
(0, import_fs76.mkdirSync)(dir, { recursive: true });
|
|
48300
|
+
const finalPath = (0, import_path83.join)(dir, `${taskId}.txt`);
|
|
48301
|
+
const tmpPath = (0, import_path83.join)(dir, `${taskId}.txt.${(0, import_crypto30.randomUUID)().slice(0, 8)}.tmp`);
|
|
48018
48302
|
try {
|
|
48019
|
-
(0,
|
|
48020
|
-
(0,
|
|
48303
|
+
(0, import_fs76.writeFileSync)(tmpPath, body, "utf8");
|
|
48304
|
+
(0, import_fs76.renameSync)(tmpPath, finalPath);
|
|
48021
48305
|
} catch (err) {
|
|
48022
48306
|
try {
|
|
48023
|
-
(0,
|
|
48307
|
+
(0, import_fs76.unlinkSync)(tmpPath);
|
|
48024
48308
|
} catch {
|
|
48025
48309
|
}
|
|
48026
48310
|
throw err;
|
|
48027
48311
|
}
|
|
48028
|
-
return (0,
|
|
48312
|
+
return (0, import_path83.resolve)(finalPath);
|
|
48029
48313
|
}
|
|
48030
48314
|
function cleanupExpiredDispatchPrompts(projectRoot, maxAgeMs = DEFAULT_PROMPT_TTL_MS, capBytes = DISPATCH_PROMPT_CAP_BYTES) {
|
|
48031
48315
|
const dir = dispatchPromptsDir(projectRoot);
|
|
48032
|
-
if (!(0,
|
|
48316
|
+
if (!(0, import_fs76.existsSync)(dir)) return { evictedAge: 0, evictedCap: 0 };
|
|
48033
48317
|
const now = Date.now();
|
|
48034
48318
|
let entries = [];
|
|
48035
48319
|
try {
|
|
48036
|
-
for (const name of (0,
|
|
48037
|
-
const
|
|
48320
|
+
for (const name of (0, import_fs76.readdirSync)(dir)) {
|
|
48321
|
+
const path8 = (0, import_path83.join)(dir, name);
|
|
48038
48322
|
try {
|
|
48039
|
-
const st = (0,
|
|
48323
|
+
const st = (0, import_fs76.statSync)(path8);
|
|
48040
48324
|
if (!st.isFile()) continue;
|
|
48041
|
-
entries.push({ name, path:
|
|
48325
|
+
entries.push({ name, path: path8, mtimeMs: st.mtimeMs, size: st.size });
|
|
48042
48326
|
} catch (err) {
|
|
48043
|
-
process.stderr.write(`[gossipcat] dispatch-prompt stat failed for ${(0,
|
|
48327
|
+
process.stderr.write(`[gossipcat] dispatch-prompt stat failed for ${(0, import_path83.basename)(path8)}: ${err.message}
|
|
48044
48328
|
`);
|
|
48045
48329
|
}
|
|
48046
48330
|
}
|
|
@@ -48054,7 +48338,7 @@ function cleanupExpiredDispatchPrompts(projectRoot, maxAgeMs = DEFAULT_PROMPT_TT
|
|
|
48054
48338
|
for (const e of entries) {
|
|
48055
48339
|
if (now - e.mtimeMs > maxAgeMs) {
|
|
48056
48340
|
try {
|
|
48057
|
-
(0,
|
|
48341
|
+
(0, import_fs76.unlinkSync)(e.path);
|
|
48058
48342
|
evictedAge++;
|
|
48059
48343
|
} catch (err) {
|
|
48060
48344
|
process.stderr.write(`[gossipcat] dispatch-prompt unlink failed for ${e.name}: ${err.message}
|
|
@@ -48071,7 +48355,7 @@ function cleanupExpiredDispatchPrompts(projectRoot, maxAgeMs = DEFAULT_PROMPT_TT
|
|
|
48071
48355
|
for (const e of survivors) {
|
|
48072
48356
|
if (totalBytes <= capBytes) break;
|
|
48073
48357
|
try {
|
|
48074
|
-
(0,
|
|
48358
|
+
(0, import_fs76.unlinkSync)(e.path);
|
|
48075
48359
|
totalBytes -= e.size;
|
|
48076
48360
|
evictedCap++;
|
|
48077
48361
|
} catch (err) {
|
|
@@ -48084,18 +48368,18 @@ function cleanupExpiredDispatchPrompts(projectRoot, maxAgeMs = DEFAULT_PROMPT_TT
|
|
|
48084
48368
|
}
|
|
48085
48369
|
function pruneOrphanDispatchPrompts(projectRoot, knownTaskIds, maxAgeMs = DEFAULT_PROMPT_TTL_MS) {
|
|
48086
48370
|
const dir = dispatchPromptsDir(projectRoot);
|
|
48087
|
-
if (!(0,
|
|
48371
|
+
if (!(0, import_fs76.existsSync)(dir)) return { orphans: 0, aged: 0 };
|
|
48088
48372
|
const now = Date.now();
|
|
48089
48373
|
let orphans = 0;
|
|
48090
48374
|
let aged = 0;
|
|
48091
48375
|
try {
|
|
48092
|
-
for (const name of (0,
|
|
48376
|
+
for (const name of (0, import_fs76.readdirSync)(dir)) {
|
|
48093
48377
|
if (!name.endsWith(".txt")) continue;
|
|
48094
48378
|
const taskId = name.slice(0, -4);
|
|
48095
|
-
const
|
|
48379
|
+
const path8 = (0, import_path83.join)(dir, name);
|
|
48096
48380
|
let mtimeMs = 0;
|
|
48097
48381
|
try {
|
|
48098
|
-
mtimeMs = (0,
|
|
48382
|
+
mtimeMs = (0, import_fs76.statSync)(path8).mtimeMs;
|
|
48099
48383
|
} catch {
|
|
48100
48384
|
continue;
|
|
48101
48385
|
}
|
|
@@ -48103,7 +48387,7 @@ function pruneOrphanDispatchPrompts(projectRoot, knownTaskIds, maxAgeMs = DEFAUL
|
|
|
48103
48387
|
const orphaned = !knownTaskIds.has(taskId);
|
|
48104
48388
|
if (tooOld || orphaned) {
|
|
48105
48389
|
try {
|
|
48106
|
-
(0,
|
|
48390
|
+
(0, import_fs76.unlinkSync)(path8);
|
|
48107
48391
|
if (orphaned) orphans++;
|
|
48108
48392
|
if (tooOld) aged++;
|
|
48109
48393
|
} catch (err) {
|
|
@@ -48120,14 +48404,14 @@ function pruneOrphanDispatchPrompts(projectRoot, knownTaskIds, maxAgeMs = DEFAUL
|
|
|
48120
48404
|
}
|
|
48121
48405
|
function dispatchPromptPath(projectRoot, taskId) {
|
|
48122
48406
|
assertSafeTaskId(taskId);
|
|
48123
|
-
return (0,
|
|
48407
|
+
return (0, import_path83.resolve)((0, import_path83.join)(dispatchPromptsDir(projectRoot), `${taskId}.txt`));
|
|
48124
48408
|
}
|
|
48125
|
-
var
|
|
48409
|
+
var import_fs76, import_path83, import_crypto30, SAFE_TASK_ID2, DISPATCH_PROMPT_CAP_BYTES, DEFAULT_PROMPT_TTL_MS, DISPATCH_PROMPTS_SUBDIR;
|
|
48126
48410
|
var init_dispatch_prompt_storage = __esm({
|
|
48127
48411
|
"apps/cli/src/handlers/dispatch-prompt-storage.ts"() {
|
|
48128
48412
|
"use strict";
|
|
48129
|
-
|
|
48130
|
-
|
|
48413
|
+
import_fs76 = require("fs");
|
|
48414
|
+
import_path83 = require("path");
|
|
48131
48415
|
import_crypto30 = require("crypto");
|
|
48132
48416
|
SAFE_TASK_ID2 = /^(?!.*\.\.)[A-Za-z0-9._-]{1,64}$/;
|
|
48133
48417
|
DISPATCH_PROMPT_CAP_BYTES = 100 * 1024 * 1024;
|
|
@@ -48181,9 +48465,9 @@ function getCommitRange(preSha, postSha) {
|
|
|
48181
48465
|
function appendViolationRecord(record2) {
|
|
48182
48466
|
try {
|
|
48183
48467
|
const projectRoot = process.cwd();
|
|
48184
|
-
(0,
|
|
48185
|
-
const logPath = (0,
|
|
48186
|
-
(0,
|
|
48468
|
+
(0, import_fs77.mkdirSync)((0, import_path84.join)(projectRoot, ".gossip"), { recursive: true });
|
|
48469
|
+
const logPath = (0, import_path84.join)(projectRoot, PROCESS_VIOLATIONS_FILE);
|
|
48470
|
+
(0, import_fs77.appendFileSync)(logPath, JSON.stringify(record2) + "\n", "utf8");
|
|
48187
48471
|
} catch (err) {
|
|
48188
48472
|
process.stderr.write(`[gossipcat] ref-allowlist: failed to append violation record: ${err.message}
|
|
48189
48473
|
`);
|
|
@@ -48233,17 +48517,289 @@ Full audit trail at .gossip/process-violations.jsonl
|
|
|
48233
48517
|
`
|
|
48234
48518
|
);
|
|
48235
48519
|
}
|
|
48236
|
-
var
|
|
48520
|
+
var import_fs77, import_path84, import_child_process13, PROCESS_VIOLATIONS_FILE;
|
|
48237
48521
|
var init_ref_allowlist_detection = __esm({
|
|
48238
48522
|
"apps/cli/src/handlers/ref-allowlist-detection.ts"() {
|
|
48239
48523
|
"use strict";
|
|
48240
|
-
|
|
48241
|
-
|
|
48524
|
+
import_fs77 = require("fs");
|
|
48525
|
+
import_path84 = require("path");
|
|
48242
48526
|
import_child_process13 = require("child_process");
|
|
48243
48527
|
PROCESS_VIOLATIONS_FILE = ".gossip/process-violations.jsonl";
|
|
48244
48528
|
}
|
|
48245
48529
|
});
|
|
48246
48530
|
|
|
48531
|
+
// apps/cli/src/handlers/orchestrator-precondition-runner.ts
|
|
48532
|
+
function captureHeadSha(projectRoot, execFile6 = defaultExecFile) {
|
|
48533
|
+
try {
|
|
48534
|
+
const cwd = projectRoot || process.cwd();
|
|
48535
|
+
const sha = execFile6("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8" }).trim();
|
|
48536
|
+
return sha || void 0;
|
|
48537
|
+
} catch {
|
|
48538
|
+
return void 0;
|
|
48539
|
+
}
|
|
48540
|
+
}
|
|
48541
|
+
function getCommitsSince(sinceSha, projectRoot, execFile6 = defaultExecFile) {
|
|
48542
|
+
try {
|
|
48543
|
+
const output = execFile6("git", ["log", `${sinceSha}..HEAD`, "--format=%H"], {
|
|
48544
|
+
cwd: projectRoot,
|
|
48545
|
+
encoding: "utf8"
|
|
48546
|
+
});
|
|
48547
|
+
return output.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
48548
|
+
} catch {
|
|
48549
|
+
return [];
|
|
48550
|
+
}
|
|
48551
|
+
}
|
|
48552
|
+
async function runMidFlightCheck(input, deps = {}) {
|
|
48553
|
+
const warnings = [];
|
|
48554
|
+
if (!input.roundStartSha) {
|
|
48555
|
+
return { warnings };
|
|
48556
|
+
}
|
|
48557
|
+
const execFile6 = deps.execFile ?? defaultExecFile;
|
|
48558
|
+
const emitSignals = deps.emitSignals ?? defaultEmitSignals;
|
|
48559
|
+
try {
|
|
48560
|
+
const { projectRoot, consensusId, roundStartSha } = input;
|
|
48561
|
+
const commits = getCommitsSince(roundStartSha, projectRoot, execFile6);
|
|
48562
|
+
const { detected, count } = detectMidFlightCommits(commits);
|
|
48563
|
+
if (!detected) {
|
|
48564
|
+
return { warnings };
|
|
48565
|
+
}
|
|
48566
|
+
warnings.push(
|
|
48567
|
+
`[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}.`
|
|
48568
|
+
);
|
|
48569
|
+
try {
|
|
48570
|
+
emitSignals(projectRoot, [{
|
|
48571
|
+
type: "pipeline",
|
|
48572
|
+
signal: "mid_flight_fixup",
|
|
48573
|
+
agentId: "orchestrator",
|
|
48574
|
+
taskId: consensusId,
|
|
48575
|
+
consensusId,
|
|
48576
|
+
metadata: {
|
|
48577
|
+
count,
|
|
48578
|
+
roundStartSha,
|
|
48579
|
+
commits
|
|
48580
|
+
},
|
|
48581
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
48582
|
+
}]);
|
|
48583
|
+
} catch {
|
|
48584
|
+
}
|
|
48585
|
+
} catch {
|
|
48586
|
+
}
|
|
48587
|
+
return { warnings };
|
|
48588
|
+
}
|
|
48589
|
+
function defaultExecFile(cmd, args, opts) {
|
|
48590
|
+
return (0, import_child_process14.execFileSync)(cmd, args, opts);
|
|
48591
|
+
}
|
|
48592
|
+
function defaultCanRead(p) {
|
|
48593
|
+
try {
|
|
48594
|
+
fs6.accessSync(p, fs6.constants.R_OK);
|
|
48595
|
+
return true;
|
|
48596
|
+
} catch {
|
|
48597
|
+
return false;
|
|
48598
|
+
}
|
|
48599
|
+
}
|
|
48600
|
+
function defaultPathExists(projectRoot, p) {
|
|
48601
|
+
try {
|
|
48602
|
+
const resolved = path7.resolve(projectRoot, p);
|
|
48603
|
+
fs6.accessSync(resolved, fs6.constants.R_OK);
|
|
48604
|
+
return true;
|
|
48605
|
+
} catch {
|
|
48606
|
+
return false;
|
|
48607
|
+
}
|
|
48608
|
+
}
|
|
48609
|
+
function defaultIsGitignoredOrUntracked(projectRoot, p, execFile6) {
|
|
48610
|
+
try {
|
|
48611
|
+
execFile6("git", ["check-ignore", "-q", p], { cwd: projectRoot, encoding: "utf8" });
|
|
48612
|
+
return true;
|
|
48613
|
+
} catch {
|
|
48614
|
+
}
|
|
48615
|
+
try {
|
|
48616
|
+
execFile6("git", ["ls-files", "--error-unmatch", p], { cwd: projectRoot, encoding: "utf8" });
|
|
48617
|
+
return false;
|
|
48618
|
+
} catch {
|
|
48619
|
+
return true;
|
|
48620
|
+
}
|
|
48621
|
+
}
|
|
48622
|
+
function defaultEmitSignals(projectRoot, signals) {
|
|
48623
|
+
try {
|
|
48624
|
+
emitPipelineSignals(projectRoot, signals);
|
|
48625
|
+
} catch {
|
|
48626
|
+
}
|
|
48627
|
+
}
|
|
48628
|
+
async function gatherStaleBaseInputs(projectRoot, execFile6 = defaultExecFile) {
|
|
48629
|
+
try {
|
|
48630
|
+
const dispatchSha = execFile6("git", ["rev-parse", "HEAD"], {
|
|
48631
|
+
cwd: projectRoot,
|
|
48632
|
+
encoding: "utf8"
|
|
48633
|
+
}).trim();
|
|
48634
|
+
const originMasterSha = execFile6("git", ["rev-parse", "origin/master"], {
|
|
48635
|
+
cwd: projectRoot,
|
|
48636
|
+
encoding: "utf8"
|
|
48637
|
+
}).trim();
|
|
48638
|
+
const mergeBaseSha = execFile6("git", ["merge-base", "HEAD", "origin/master"], {
|
|
48639
|
+
cwd: projectRoot,
|
|
48640
|
+
encoding: "utf8"
|
|
48641
|
+
}).trim();
|
|
48642
|
+
return { dispatchSha, originMasterSha, mergeBaseSha };
|
|
48643
|
+
} catch {
|
|
48644
|
+
return null;
|
|
48645
|
+
}
|
|
48646
|
+
}
|
|
48647
|
+
async function runDispatchPreconditionGuard(input, deps = {}) {
|
|
48648
|
+
const warnings = [];
|
|
48649
|
+
const execFile6 = deps.execFile ?? defaultExecFile;
|
|
48650
|
+
const canRead = deps.canRead ?? defaultCanRead;
|
|
48651
|
+
const pathExists = deps.pathExists ?? defaultPathExists;
|
|
48652
|
+
const isGitignoredOrUntracked = deps.isGitignoredOrUntracked ?? defaultIsGitignoredOrUntracked;
|
|
48653
|
+
const emitSignals = deps.emitSignals ?? defaultEmitSignals;
|
|
48654
|
+
const { projectRoot, taskId, resolutionRoots, taskText, writeMode, additionalTasks } = input;
|
|
48655
|
+
try {
|
|
48656
|
+
const gitInputs = await gatherStaleBaseInputs(projectRoot, execFile6);
|
|
48657
|
+
if (gitInputs !== null) {
|
|
48658
|
+
const staleResult = detectStaleBase(
|
|
48659
|
+
gitInputs.dispatchSha,
|
|
48660
|
+
gitInputs.originMasterSha,
|
|
48661
|
+
gitInputs.mergeBaseSha
|
|
48662
|
+
);
|
|
48663
|
+
if (staleResult.stale && staleResult.reason !== null) {
|
|
48664
|
+
const reason = staleResult.reason;
|
|
48665
|
+
warnings.push(
|
|
48666
|
+
`[dispatch-hygiene] stale base detected (${reason}): dispatch SHA ${gitInputs.dispatchSha} is behind origin/master ${gitInputs.originMasterSha}. Pull and rebase before dispatching.`
|
|
48667
|
+
);
|
|
48668
|
+
try {
|
|
48669
|
+
emitSignals(projectRoot, [{
|
|
48670
|
+
type: "pipeline",
|
|
48671
|
+
signal: "dispatched_stale_base",
|
|
48672
|
+
agentId: "orchestrator",
|
|
48673
|
+
taskId,
|
|
48674
|
+
metadata: {
|
|
48675
|
+
reason,
|
|
48676
|
+
dispatchSha: gitInputs.dispatchSha
|
|
48677
|
+
},
|
|
48678
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
48679
|
+
}]);
|
|
48680
|
+
} catch {
|
|
48681
|
+
}
|
|
48682
|
+
}
|
|
48683
|
+
}
|
|
48684
|
+
const roots = resolutionRoots ?? [];
|
|
48685
|
+
if (roots.length > 0) {
|
|
48686
|
+
let unreadable;
|
|
48687
|
+
try {
|
|
48688
|
+
unreadable = findUnreadablePaths(roots, canRead);
|
|
48689
|
+
} catch {
|
|
48690
|
+
unreadable = [];
|
|
48691
|
+
}
|
|
48692
|
+
if (unreadable.length > 0) {
|
|
48693
|
+
warnings.push(
|
|
48694
|
+
`[dispatch-hygiene] ${unreadable.length} resolutionRoot(s) are unreadable: ${unreadable.join(", ")}. Cross-reviewers will fall back to project root.`
|
|
48695
|
+
);
|
|
48696
|
+
try {
|
|
48697
|
+
emitSignals(projectRoot, [{
|
|
48698
|
+
type: "pipeline",
|
|
48699
|
+
signal: "referenced_unreadable_path",
|
|
48700
|
+
agentId: "orchestrator",
|
|
48701
|
+
taskId,
|
|
48702
|
+
metadata: {
|
|
48703
|
+
unreadable
|
|
48704
|
+
},
|
|
48705
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
48706
|
+
}]);
|
|
48707
|
+
} catch {
|
|
48708
|
+
}
|
|
48709
|
+
}
|
|
48710
|
+
}
|
|
48711
|
+
const scanTasks = [];
|
|
48712
|
+
if (taskText) {
|
|
48713
|
+
scanTasks.push({ taskText, writeMode });
|
|
48714
|
+
}
|
|
48715
|
+
if (additionalTasks) {
|
|
48716
|
+
for (const t of additionalTasks) {
|
|
48717
|
+
if (t && t.taskText) {
|
|
48718
|
+
scanTasks.push({ taskText: t.taskText, writeMode: t.writeMode });
|
|
48719
|
+
}
|
|
48720
|
+
}
|
|
48721
|
+
}
|
|
48722
|
+
if (scanTasks.length > 0) {
|
|
48723
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
48724
|
+
let droppedOverCap = 0;
|
|
48725
|
+
for (const t of scanTasks) {
|
|
48726
|
+
let result = {
|
|
48727
|
+
unreadable: [],
|
|
48728
|
+
droppedOverCap: 0
|
|
48729
|
+
};
|
|
48730
|
+
try {
|
|
48731
|
+
result = findUnreadableReferencedPathsWithMeta(t.taskText, {
|
|
48732
|
+
writeMode: t.writeMode,
|
|
48733
|
+
pathExists: (p) => {
|
|
48734
|
+
try {
|
|
48735
|
+
return pathExists(projectRoot, p);
|
|
48736
|
+
} catch {
|
|
48737
|
+
return true;
|
|
48738
|
+
}
|
|
48739
|
+
},
|
|
48740
|
+
isGitignoredOrUntracked: (p) => {
|
|
48741
|
+
try {
|
|
48742
|
+
return isGitignoredOrUntracked(projectRoot, p, execFile6);
|
|
48743
|
+
} catch {
|
|
48744
|
+
return false;
|
|
48745
|
+
}
|
|
48746
|
+
}
|
|
48747
|
+
});
|
|
48748
|
+
} catch {
|
|
48749
|
+
result = { unreadable: [], droppedOverCap: 0 };
|
|
48750
|
+
}
|
|
48751
|
+
droppedOverCap += result.droppedOverCap;
|
|
48752
|
+
for (const entry of result.unreadable) {
|
|
48753
|
+
const existing = byPath.get(entry.path);
|
|
48754
|
+
if (!existing) {
|
|
48755
|
+
byPath.set(entry.path, entry);
|
|
48756
|
+
} else if (existing.reason !== "gitignored_in_worktree" && entry.reason === "gitignored_in_worktree") {
|
|
48757
|
+
byPath.set(entry.path, entry);
|
|
48758
|
+
}
|
|
48759
|
+
}
|
|
48760
|
+
}
|
|
48761
|
+
const referenced = [...byPath.values()];
|
|
48762
|
+
if (referenced.length > 0) {
|
|
48763
|
+
const detail = referenced.map((r) => `${r.path} (${r.reason})`).join(", ");
|
|
48764
|
+
warnings.push(
|
|
48765
|
+
`[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.`
|
|
48766
|
+
);
|
|
48767
|
+
try {
|
|
48768
|
+
emitSignals(projectRoot, [{
|
|
48769
|
+
type: "pipeline",
|
|
48770
|
+
signal: "referenced_unreadable_path",
|
|
48771
|
+
agentId: "orchestrator",
|
|
48772
|
+
taskId,
|
|
48773
|
+
metadata: {
|
|
48774
|
+
referenced
|
|
48775
|
+
},
|
|
48776
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
48777
|
+
}]);
|
|
48778
|
+
} catch {
|
|
48779
|
+
}
|
|
48780
|
+
}
|
|
48781
|
+
if (droppedOverCap > 0) {
|
|
48782
|
+
warnings.push(
|
|
48783
|
+
`[dispatch-hygiene] ${droppedOverCap} referenced path(s) beyond the 20-path cap were not checked.`
|
|
48784
|
+
);
|
|
48785
|
+
}
|
|
48786
|
+
}
|
|
48787
|
+
} catch {
|
|
48788
|
+
}
|
|
48789
|
+
return { warnings };
|
|
48790
|
+
}
|
|
48791
|
+
var fs6, path7, import_child_process14;
|
|
48792
|
+
var init_orchestrator_precondition_runner = __esm({
|
|
48793
|
+
"apps/cli/src/handlers/orchestrator-precondition-runner.ts"() {
|
|
48794
|
+
"use strict";
|
|
48795
|
+
fs6 = __toESM(require("fs"));
|
|
48796
|
+
path7 = __toESM(require("path"));
|
|
48797
|
+
import_child_process14 = require("child_process");
|
|
48798
|
+
init_src4();
|
|
48799
|
+
init_src4();
|
|
48800
|
+
}
|
|
48801
|
+
});
|
|
48802
|
+
|
|
48247
48803
|
// apps/cli/src/handlers/relay-cross-review.ts
|
|
48248
48804
|
var relay_cross_review_exports = {};
|
|
48249
48805
|
__export(relay_cross_review_exports, {
|
|
@@ -48274,11 +48830,11 @@ async function synthesizeTimeoutRound(snapshot, consensusId, missingAgents, llm,
|
|
|
48274
48830
|
);
|
|
48275
48831
|
try {
|
|
48276
48832
|
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45 } = require("fs");
|
|
48277
|
-
const { join:
|
|
48278
|
-
const reportsDir =
|
|
48833
|
+
const { join: join93 } = require("path");
|
|
48834
|
+
const reportsDir = join93(projectRoot, ".gossip", "consensus-reports");
|
|
48279
48835
|
mkdirSync45(reportsDir, { recursive: true });
|
|
48280
48836
|
const topic = snapshot.allResults?.find((r) => r.task)?.task?.slice(0, 500) || "";
|
|
48281
|
-
writeFileSync38(
|
|
48837
|
+
writeFileSync38(join93(reportsDir, `${consensusId}.json`), JSON.stringify({
|
|
48282
48838
|
id: consensusId,
|
|
48283
48839
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
48284
48840
|
topic,
|
|
@@ -48313,6 +48869,7 @@ function startConsensusTimeout(consensusId) {
|
|
|
48313
48869
|
return;
|
|
48314
48870
|
}
|
|
48315
48871
|
const missingAgents = [...current.pendingNativeAgents];
|
|
48872
|
+
const roundStartShaForMidFlight = current.roundStartSha;
|
|
48316
48873
|
const snapshot = { allResults: current.allResults, relayCrossReviewEntries: current.relayCrossReviewEntries, relayCrossReviewSkipped: current.relayCrossReviewSkipped, nativeCrossReviewEntries: [...current.nativeCrossReviewEntries], resolutionRoots: current.resolutionRoots, roundContext: current.roundContext };
|
|
48317
48874
|
seedRecentConsensusAgentIds(Array.from(current.participatingNativeAgents), RECENT_CONSENSUS_TASK_TTL_MS);
|
|
48318
48875
|
ctx.pendingConsensusRounds.delete(consensusId);
|
|
@@ -48342,6 +48899,18 @@ function startConsensusTimeout(consensusId) {
|
|
|
48342
48899
|
const { report } = await synthesizeTimeoutRound(snapshot, consensusId, missingAgents, timeoutLlm);
|
|
48343
48900
|
process.stderr.write(`[gossipcat] \u{1F52E} Timeout synthesis complete: ${report.confirmed.length} confirmed, ${report.disputed.length} disputed
|
|
48344
48901
|
`);
|
|
48902
|
+
try {
|
|
48903
|
+
const midFlightResult = await runMidFlightCheck({
|
|
48904
|
+
projectRoot: process.cwd(),
|
|
48905
|
+
consensusId,
|
|
48906
|
+
roundStartSha: roundStartShaForMidFlight
|
|
48907
|
+
});
|
|
48908
|
+
for (const warn of midFlightResult.warnings) {
|
|
48909
|
+
process.stderr.write(`[gossipcat] ${warn}
|
|
48910
|
+
`);
|
|
48911
|
+
}
|
|
48912
|
+
} catch {
|
|
48913
|
+
}
|
|
48345
48914
|
} catch (err) {
|
|
48346
48915
|
process.stderr.write(`[gossipcat] \u274C Timeout synthesis failed: ${err.message}
|
|
48347
48916
|
`);
|
|
@@ -48452,6 +49021,7 @@ async function handleRelayCrossReview(consensus_id, agent_id, result) {
|
|
|
48452
49021
|
}]
|
|
48453
49022
|
};
|
|
48454
49023
|
}
|
|
49024
|
+
const completionRoundStartSha = round.roundStartSha;
|
|
48455
49025
|
const synthSnapshot = {
|
|
48456
49026
|
allResults: round.allResults,
|
|
48457
49027
|
relayCrossReviewEntries: round.relayCrossReviewEntries,
|
|
@@ -48497,10 +49067,10 @@ async function handleRelayCrossReview(consensus_id, agent_id, result) {
|
|
|
48497
49067
|
);
|
|
48498
49068
|
try {
|
|
48499
49069
|
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45 } = require("fs");
|
|
48500
|
-
const { join:
|
|
48501
|
-
const reportsDir =
|
|
49070
|
+
const { join: join93 } = require("path");
|
|
49071
|
+
const reportsDir = join93(process.cwd(), ".gossip", "consensus-reports");
|
|
48502
49072
|
mkdirSync45(reportsDir, { recursive: true });
|
|
48503
|
-
const reportPath =
|
|
49073
|
+
const reportPath = join93(reportsDir, `${consensus_id}.json`);
|
|
48504
49074
|
const topic = synthSnapshot.allResults?.find((r) => r.task)?.task?.slice(0, 500) || "";
|
|
48505
49075
|
writeFileSync38(reportPath, JSON.stringify({
|
|
48506
49076
|
id: consensus_id,
|
|
@@ -48527,6 +49097,18 @@ async function handleRelayCrossReview(consensus_id, agent_id, result) {
|
|
|
48527
49097
|
}
|
|
48528
49098
|
} catch {
|
|
48529
49099
|
}
|
|
49100
|
+
try {
|
|
49101
|
+
const midFlightResult = await runMidFlightCheck({
|
|
49102
|
+
projectRoot: process.cwd(),
|
|
49103
|
+
consensusId: synthSnapshot.consensusId,
|
|
49104
|
+
roundStartSha: completionRoundStartSha
|
|
49105
|
+
});
|
|
49106
|
+
for (const warn of midFlightResult.warnings) {
|
|
49107
|
+
process.stderr.write(`[gossipcat] ${warn}
|
|
49108
|
+
`);
|
|
49109
|
+
}
|
|
49110
|
+
} catch {
|
|
49111
|
+
}
|
|
48530
49112
|
return {
|
|
48531
49113
|
content: [{
|
|
48532
49114
|
type: "text",
|
|
@@ -48600,8 +49182,8 @@ function persistPendingConsensus() {
|
|
|
48600
49182
|
const projectRoot = ctx.mainAgent?.projectRoot;
|
|
48601
49183
|
if (!projectRoot) return;
|
|
48602
49184
|
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45 } = require("fs");
|
|
48603
|
-
const { join:
|
|
48604
|
-
const dir =
|
|
49185
|
+
const { join: join93 } = require("path");
|
|
49186
|
+
const dir = join93(projectRoot, ".gossip");
|
|
48605
49187
|
mkdirSync45(dir, { recursive: true });
|
|
48606
49188
|
const rounds = {};
|
|
48607
49189
|
for (const [id, round] of ctx.pendingConsensusRounds) {
|
|
@@ -48636,7 +49218,7 @@ function persistPendingConsensus() {
|
|
|
48636
49218
|
} : void 0
|
|
48637
49219
|
};
|
|
48638
49220
|
}
|
|
48639
|
-
writeFileSync38(
|
|
49221
|
+
writeFileSync38(join93(dir, CONSENSUS_FILE), JSON.stringify(rounds));
|
|
48640
49222
|
} catch (err) {
|
|
48641
49223
|
process.stderr.write(`[gossipcat] persistPendingConsensus failed: ${err.message}
|
|
48642
49224
|
`);
|
|
@@ -48644,11 +49226,11 @@ function persistPendingConsensus() {
|
|
|
48644
49226
|
}
|
|
48645
49227
|
function restorePendingConsensus(projectRoot) {
|
|
48646
49228
|
try {
|
|
48647
|
-
const { existsSync:
|
|
48648
|
-
const { join:
|
|
48649
|
-
const filePath =
|
|
48650
|
-
if (!
|
|
48651
|
-
const raw = JSON.parse(
|
|
49229
|
+
const { existsSync: existsSync74, readFileSync: readFileSync70, unlinkSync: unlinkSync16 } = require("fs");
|
|
49230
|
+
const { join: join93 } = require("path");
|
|
49231
|
+
const filePath = join93(projectRoot, ".gossip", CONSENSUS_FILE);
|
|
49232
|
+
if (!existsSync74(filePath)) return;
|
|
49233
|
+
const raw = JSON.parse(readFileSync70(filePath, "utf-8"));
|
|
48652
49234
|
const now = Date.now();
|
|
48653
49235
|
for (const [id, data] of Object.entries(raw)) {
|
|
48654
49236
|
if (now > data.deadline + 3e5) {
|
|
@@ -48674,6 +49256,8 @@ function restorePendingConsensus(projectRoot) {
|
|
|
48674
49256
|
createdAt: data.createdAt,
|
|
48675
49257
|
nativePrompts: data.nativePrompts || [],
|
|
48676
49258
|
resolutionRoots: Array.isArray(data.resolutionRoots) && data.resolutionRoots.length > 0 ? data.resolutionRoots : void 0,
|
|
49259
|
+
// UNIT 3: restore roundStartSha from persisted data (back-compat: undefined for old rounds).
|
|
49260
|
+
roundStartSha: typeof data.roundStartSha === "string" ? data.roundStartSha : void 0,
|
|
48677
49261
|
// Spec §3.2 disk back-compat: prefer the embedded roundContext; fall
|
|
48678
49262
|
// back per-field to the old flat shape (mirrors the
|
|
48679
49263
|
// participatingNativeAgents back-compat pattern above). Old pre-PR-A
|
|
@@ -48695,6 +49279,7 @@ var init_relay_cross_review = __esm({
|
|
|
48695
49279
|
"use strict";
|
|
48696
49280
|
init_mcp_context();
|
|
48697
49281
|
init_native_tasks();
|
|
49282
|
+
init_orchestrator_precondition_runner();
|
|
48698
49283
|
CONSENSUS_FILE = "pending-consensus.json";
|
|
48699
49284
|
}
|
|
48700
49285
|
});
|
|
@@ -48779,10 +49364,10 @@ function taskWasInConsensusRound(taskId, agentId, rounds, recentTaskIds, recentA
|
|
|
48779
49364
|
function appendRelayWarning(projectRoot, entry) {
|
|
48780
49365
|
try {
|
|
48781
49366
|
const { appendFileSync: appendFileSync22, mkdirSync: mkdirSync45 } = require("fs");
|
|
48782
|
-
const { join:
|
|
48783
|
-
const dir =
|
|
49367
|
+
const { join: join93 } = require("path");
|
|
49368
|
+
const dir = join93(projectRoot, ".gossip");
|
|
48784
49369
|
mkdirSync45(dir, { recursive: true });
|
|
48785
|
-
appendFileSync22(
|
|
49370
|
+
appendFileSync22(join93(dir, RELAY_WARNINGS_FILE), JSON.stringify(entry) + "\n", "utf8");
|
|
48786
49371
|
} catch (err) {
|
|
48787
49372
|
process.stderr.write(`[gossipcat] append relay-warning failed: ${err.message}
|
|
48788
49373
|
`);
|
|
@@ -48791,8 +49376,8 @@ function appendRelayWarning(projectRoot, entry) {
|
|
|
48791
49376
|
function checkWorktreeEngaged(startedAt, projectRoot = process.cwd()) {
|
|
48792
49377
|
try {
|
|
48793
49378
|
const { readdirSync: readdirSync22, statSync: statSync36 } = require("fs");
|
|
48794
|
-
const { join:
|
|
48795
|
-
const wtDir =
|
|
49379
|
+
const { join: join93 } = require("path");
|
|
49380
|
+
const wtDir = join93(projectRoot, ".claude", "worktrees");
|
|
48796
49381
|
let entries;
|
|
48797
49382
|
try {
|
|
48798
49383
|
entries = readdirSync22(wtDir);
|
|
@@ -48803,7 +49388,7 @@ function checkWorktreeEngaged(startedAt, projectRoot = process.cwd()) {
|
|
|
48803
49388
|
for (const entry of entries) {
|
|
48804
49389
|
if (!entry.startsWith("agent-")) continue;
|
|
48805
49390
|
try {
|
|
48806
|
-
const st = statSync36(
|
|
49391
|
+
const st = statSync36(join93(wtDir, entry));
|
|
48807
49392
|
if (st.isDirectory() && st.mtimeMs >= startedAt - 2e3) return true;
|
|
48808
49393
|
} catch {
|
|
48809
49394
|
}
|
|
@@ -49684,7 +50269,7 @@ function computeSkillFingerprint(paths) {
|
|
|
49684
50269
|
const pairs = [];
|
|
49685
50270
|
for (const p of paths) {
|
|
49686
50271
|
try {
|
|
49687
|
-
const st = (0,
|
|
50272
|
+
const st = (0, import_fs78.statSync)(p);
|
|
49688
50273
|
pairs.push(`${p}:${st.mtimeMs}`);
|
|
49689
50274
|
} catch {
|
|
49690
50275
|
}
|
|
@@ -49719,7 +50304,7 @@ function setCachedPrompt(k, e) {
|
|
|
49719
50304
|
const evicted = promptCache.get(oldestKey);
|
|
49720
50305
|
promptCache.delete(oldestKey);
|
|
49721
50306
|
try {
|
|
49722
|
-
(0,
|
|
50307
|
+
(0, import_fs78.unlinkSync)(evicted.skillsSectionPath);
|
|
49723
50308
|
} catch {
|
|
49724
50309
|
}
|
|
49725
50310
|
const evictedAgentId = oldestKey.split("|")[0] ?? "_system";
|
|
@@ -49733,7 +50318,7 @@ function invalidateAgent(agentId) {
|
|
|
49733
50318
|
if (k.startsWith(`${agentId}|`)) {
|
|
49734
50319
|
promptCache.delete(k);
|
|
49735
50320
|
try {
|
|
49736
|
-
(0,
|
|
50321
|
+
(0, import_fs78.unlinkSync)(v.skillsSectionPath);
|
|
49737
50322
|
} catch {
|
|
49738
50323
|
}
|
|
49739
50324
|
emitCacheEvictedSignal(agentId, "invalidation");
|
|
@@ -49746,7 +50331,7 @@ function invalidateAll() {
|
|
|
49746
50331
|
const n = promptCache.size;
|
|
49747
50332
|
for (const v of promptCache.values()) {
|
|
49748
50333
|
try {
|
|
49749
|
-
(0,
|
|
50334
|
+
(0, import_fs78.unlinkSync)(v.skillsSectionPath);
|
|
49750
50335
|
} catch {
|
|
49751
50336
|
}
|
|
49752
50337
|
}
|
|
@@ -49793,29 +50378,29 @@ function writeCachedSkillsSection(projectRoot, fingerprint2, skillsSection) {
|
|
|
49793
50378
|
if (!/^[a-f0-9]{64}$/.test(fingerprint2)) {
|
|
49794
50379
|
throw new Error(`writeCachedSkillsSection: invalid fingerprint ${JSON.stringify(fingerprint2).slice(0, 32)}`);
|
|
49795
50380
|
}
|
|
49796
|
-
const dir = (0,
|
|
49797
|
-
(0,
|
|
49798
|
-
const finalPath = (0,
|
|
49799
|
-
const tmpPath = (0,
|
|
50381
|
+
const dir = (0, import_path85.join)(projectRoot, ".gossip", "dispatch-prompts", "cache");
|
|
50382
|
+
(0, import_fs78.mkdirSync)(dir, { recursive: true });
|
|
50383
|
+
const finalPath = (0, import_path85.join)(dir, `skills-${fingerprint2}.txt`);
|
|
50384
|
+
const tmpPath = (0, import_path85.join)(dir, `skills-${fingerprint2}.txt.${(0, import_crypto33.randomUUID)().slice(0, 8)}.tmp`);
|
|
49800
50385
|
try {
|
|
49801
|
-
(0,
|
|
49802
|
-
(0,
|
|
50386
|
+
(0, import_fs78.writeFileSync)(tmpPath, skillsSection, "utf8");
|
|
50387
|
+
(0, import_fs78.renameSync)(tmpPath, finalPath);
|
|
49803
50388
|
} catch (err) {
|
|
49804
50389
|
try {
|
|
49805
|
-
(0,
|
|
50390
|
+
(0, import_fs78.unlinkSync)(tmpPath);
|
|
49806
50391
|
} catch {
|
|
49807
50392
|
}
|
|
49808
50393
|
throw err;
|
|
49809
50394
|
}
|
|
49810
|
-
return (0,
|
|
50395
|
+
return (0, import_path85.resolve)(finalPath);
|
|
49811
50396
|
}
|
|
49812
|
-
var import_crypto32,
|
|
50397
|
+
var import_crypto32, import_fs78, import_path85, import_crypto33, DISPATCH_PROMPT_CACHE_MAX_ENTRIES, promptCache;
|
|
49813
50398
|
var init_dispatch_prompt_cache = __esm({
|
|
49814
50399
|
"apps/cli/src/handlers/dispatch-prompt-cache.ts"() {
|
|
49815
50400
|
"use strict";
|
|
49816
50401
|
import_crypto32 = require("crypto");
|
|
49817
|
-
|
|
49818
|
-
|
|
50402
|
+
import_fs78 = require("fs");
|
|
50403
|
+
import_path85 = require("path");
|
|
49819
50404
|
import_crypto33 = require("crypto");
|
|
49820
50405
|
DISPATCH_PROMPT_CACHE_MAX_ENTRIES = 64;
|
|
49821
50406
|
promptCache = /* @__PURE__ */ new Map();
|
|
@@ -49842,7 +50427,7 @@ function drainLifecycleTasks(maxMs = 8e3) {
|
|
|
49842
50427
|
const snapshot = [...inFlight];
|
|
49843
50428
|
return Promise.race([
|
|
49844
50429
|
Promise.allSettled(snapshot).then(() => void 0),
|
|
49845
|
-
new Promise((
|
|
50430
|
+
new Promise((resolve33) => setTimeout(resolve33, maxMs).unref?.())
|
|
49846
50431
|
]).then(() => void 0);
|
|
49847
50432
|
}
|
|
49848
50433
|
function installLifecycleDrainHandlers() {
|
|
@@ -49885,31 +50470,31 @@ __export(check_effectiveness_runner_exports, {
|
|
|
49885
50470
|
runCheckEffectivenessForAllSkills: () => runCheckEffectivenessForAllSkills
|
|
49886
50471
|
});
|
|
49887
50472
|
function writeHealthAtomic(projectRoot, record2) {
|
|
49888
|
-
const dir = (0,
|
|
49889
|
-
const finalPath = (0,
|
|
50473
|
+
const dir = (0, import_path88.join)(projectRoot, ".gossip");
|
|
50474
|
+
const finalPath = (0, import_path88.join)(dir, "skill-runner-health.json");
|
|
49890
50475
|
const tmpPath = finalPath + ".tmp";
|
|
49891
50476
|
try {
|
|
49892
|
-
(0,
|
|
49893
|
-
(0,
|
|
49894
|
-
(0,
|
|
50477
|
+
(0, import_fs82.mkdirSync)(dir, { recursive: true });
|
|
50478
|
+
(0, import_fs82.writeFileSync)(tmpPath, JSON.stringify(record2, null, 2));
|
|
50479
|
+
(0, import_fs82.renameSync)(tmpPath, finalPath);
|
|
49895
50480
|
} catch (e) {
|
|
49896
50481
|
process.stderr.write(`[gossipcat] checkEffectiveness: health write failed: ${e.message}
|
|
49897
50482
|
`);
|
|
49898
50483
|
try {
|
|
49899
|
-
if ((0,
|
|
50484
|
+
if ((0, import_fs82.existsSync)(tmpPath)) (0, import_fs82.unlinkSync)(tmpPath);
|
|
49900
50485
|
} catch {
|
|
49901
50486
|
}
|
|
49902
50487
|
}
|
|
49903
50488
|
}
|
|
49904
50489
|
async function runCheckEffectivenessForAllSkills(opts) {
|
|
49905
50490
|
const startedAt = Date.now();
|
|
49906
|
-
const baseDir = (0,
|
|
50491
|
+
const baseDir = (0, import_path88.join)(opts.projectRoot, ".gossip", "agents");
|
|
49907
50492
|
let agentDirs = [];
|
|
49908
50493
|
let canonicalBaseDir;
|
|
49909
|
-
if ((0,
|
|
50494
|
+
if ((0, import_fs82.existsSync)(baseDir)) {
|
|
49910
50495
|
try {
|
|
49911
|
-
canonicalBaseDir = (0,
|
|
49912
|
-
agentDirs = (0,
|
|
50496
|
+
canonicalBaseDir = (0, import_fs82.realpathSync)(baseDir);
|
|
50497
|
+
agentDirs = (0, import_fs82.readdirSync)(canonicalBaseDir);
|
|
49913
50498
|
} catch {
|
|
49914
50499
|
}
|
|
49915
50500
|
}
|
|
@@ -49928,11 +50513,11 @@ async function runCheckEffectivenessForAllSkills(opts) {
|
|
|
49928
50513
|
for (const agentId of agentDirs) {
|
|
49929
50514
|
if (agentId.startsWith("_")) continue;
|
|
49930
50515
|
if (!SAFE_NAME2.test(agentId)) continue;
|
|
49931
|
-
const skillsDir = (0,
|
|
49932
|
-
if (!(0,
|
|
50516
|
+
const skillsDir = (0, import_path88.join)(canonicalBaseDir, agentId, "skills");
|
|
50517
|
+
if (!(0, import_fs82.existsSync)(skillsDir)) continue;
|
|
49933
50518
|
let canonicalSkillsDir;
|
|
49934
50519
|
try {
|
|
49935
|
-
canonicalSkillsDir = (0,
|
|
50520
|
+
canonicalSkillsDir = (0, import_fs82.realpathSync)(skillsDir);
|
|
49936
50521
|
} catch {
|
|
49937
50522
|
continue;
|
|
49938
50523
|
}
|
|
@@ -49943,7 +50528,7 @@ async function runCheckEffectivenessForAllSkills(opts) {
|
|
|
49943
50528
|
}
|
|
49944
50529
|
const role = opts.registryGet(agentId)?.role;
|
|
49945
50530
|
if (role === "implementer") continue;
|
|
49946
|
-
const files = (0,
|
|
50531
|
+
const files = (0, import_fs82.readdirSync)(canonicalSkillsDir).filter((f) => f.endsWith(".md"));
|
|
49947
50532
|
for (const file2 of files) {
|
|
49948
50533
|
const category = file2.replace(/\.md$/, "");
|
|
49949
50534
|
if (!SAFE_NAME2.test(category)) continue;
|
|
@@ -49990,12 +50575,12 @@ async function runCheckEffectivenessForAllSkills(opts) {
|
|
|
49990
50575
|
last_error: lastError
|
|
49991
50576
|
});
|
|
49992
50577
|
}
|
|
49993
|
-
var
|
|
50578
|
+
var import_fs82, import_path88, SAFE_NAME2;
|
|
49994
50579
|
var init_check_effectiveness_runner = __esm({
|
|
49995
50580
|
"apps/cli/src/handlers/check-effectiveness-runner.ts"() {
|
|
49996
50581
|
"use strict";
|
|
49997
|
-
|
|
49998
|
-
|
|
50582
|
+
import_fs82 = require("fs");
|
|
50583
|
+
import_path88 = require("path");
|
|
49999
50584
|
init_dispatch_prompt_cache();
|
|
50000
50585
|
SAFE_NAME2 = /^(?!.*\.\.)[a-zA-Z0-9._-]+$/;
|
|
50001
50586
|
}
|
|
@@ -50008,20 +50593,20 @@ __export(skill_develop_audit_exports, {
|
|
|
50008
50593
|
});
|
|
50009
50594
|
function appendSkillDevelopAudit(entry) {
|
|
50010
50595
|
try {
|
|
50011
|
-
const gossipDir = (0,
|
|
50012
|
-
(0,
|
|
50596
|
+
const gossipDir = (0, import_path89.join)(process.cwd(), ".gossip");
|
|
50597
|
+
(0, import_fs83.mkdirSync)(gossipDir, { recursive: true });
|
|
50013
50598
|
const line = JSON.stringify(entry) + "\n";
|
|
50014
|
-
(0,
|
|
50015
|
-
(0,
|
|
50599
|
+
(0, import_fs83.appendFileSync)((0, import_path89.join)(gossipDir, AUDIT_FILE2), line);
|
|
50600
|
+
(0, import_fs83.appendFileSync)((0, import_path89.join)(gossipDir, LEGACY_FILE), line);
|
|
50016
50601
|
} catch {
|
|
50017
50602
|
}
|
|
50018
50603
|
}
|
|
50019
|
-
var
|
|
50604
|
+
var import_fs83, import_path89, AUDIT_FILE2, LEGACY_FILE;
|
|
50020
50605
|
var init_skill_develop_audit = __esm({
|
|
50021
50606
|
"apps/cli/src/handlers/skill-develop-audit.ts"() {
|
|
50022
50607
|
"use strict";
|
|
50023
|
-
|
|
50024
|
-
|
|
50608
|
+
import_fs83 = require("fs");
|
|
50609
|
+
import_path89 = require("path");
|
|
50025
50610
|
AUDIT_FILE2 = "skill-develop-audit.jsonl";
|
|
50026
50611
|
LEGACY_FILE = "forced-skill-develops.jsonl";
|
|
50027
50612
|
}
|
|
@@ -50079,14 +50664,14 @@ var keychain_exports = {};
|
|
|
50079
50664
|
__export(keychain_exports, {
|
|
50080
50665
|
Keychain: () => Keychain
|
|
50081
50666
|
});
|
|
50082
|
-
var
|
|
50667
|
+
var import_child_process15, import_os6, import_fs87, import_path93, import_crypto35, DEFAULT_SERVICE_NAME, VALID_PROVIDERS3, ENCRYPTED_FILE, ALGO, Keychain;
|
|
50083
50668
|
var init_keychain = __esm({
|
|
50084
50669
|
"apps/cli/src/keychain.ts"() {
|
|
50085
50670
|
"use strict";
|
|
50086
|
-
|
|
50671
|
+
import_child_process15 = require("child_process");
|
|
50087
50672
|
import_os6 = require("os");
|
|
50088
|
-
|
|
50089
|
-
|
|
50673
|
+
import_fs87 = require("fs");
|
|
50674
|
+
import_path93 = require("path");
|
|
50090
50675
|
import_crypto35 = require("crypto");
|
|
50091
50676
|
DEFAULT_SERVICE_NAME = "gossip-mesh";
|
|
50092
50677
|
VALID_PROVIDERS3 = /^[a-zA-Z0-9_-]{1,32}$/;
|
|
@@ -50130,10 +50715,10 @@ var init_keychain = __esm({
|
|
|
50130
50715
|
return (0, import_crypto35.pbkdf2Sync)(seed, salt, 6e5, 32, "sha256");
|
|
50131
50716
|
}
|
|
50132
50717
|
loadEncryptedFile() {
|
|
50133
|
-
const filePath = (0,
|
|
50134
|
-
if (!(0,
|
|
50718
|
+
const filePath = (0, import_path93.join)(process.cwd(), ENCRYPTED_FILE);
|
|
50719
|
+
if (!(0, import_fs87.existsSync)(filePath)) return;
|
|
50135
50720
|
try {
|
|
50136
|
-
const raw = (0,
|
|
50721
|
+
const raw = (0, import_fs87.readFileSync)(filePath);
|
|
50137
50722
|
if (raw.length < 61) return;
|
|
50138
50723
|
const salt = raw.subarray(0, 32);
|
|
50139
50724
|
const iv = raw.subarray(32, 44);
|
|
@@ -50151,9 +50736,9 @@ var init_keychain = __esm({
|
|
|
50151
50736
|
}
|
|
50152
50737
|
}
|
|
50153
50738
|
saveEncryptedFile() {
|
|
50154
|
-
const filePath = (0,
|
|
50155
|
-
const dir = (0,
|
|
50156
|
-
if (!(0,
|
|
50739
|
+
const filePath = (0, import_path93.join)(process.cwd(), ENCRYPTED_FILE);
|
|
50740
|
+
const dir = (0, import_path93.join)(process.cwd(), ".gossip");
|
|
50741
|
+
if (!(0, import_fs87.existsSync)(dir)) (0, import_fs87.mkdirSync)(dir, { recursive: true });
|
|
50157
50742
|
const data = JSON.stringify(Object.fromEntries(this.inMemoryStore));
|
|
50158
50743
|
const salt = (0, import_crypto35.randomBytes)(32);
|
|
50159
50744
|
const iv = (0, import_crypto35.randomBytes)(12);
|
|
@@ -50161,12 +50746,12 @@ var init_keychain = __esm({
|
|
|
50161
50746
|
const cipher = (0, import_crypto35.createCipheriv)(ALGO, key, iv);
|
|
50162
50747
|
const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
|
|
50163
50748
|
const tag = cipher.getAuthTag();
|
|
50164
|
-
(0,
|
|
50749
|
+
(0, import_fs87.writeFileSync)(filePath, Buffer.concat([salt, iv, tag, encrypted]), { mode: 384 });
|
|
50165
50750
|
}
|
|
50166
50751
|
isKeychainAvailable() {
|
|
50167
50752
|
if ((0, import_os6.platform)() === "darwin") {
|
|
50168
50753
|
try {
|
|
50169
|
-
(0,
|
|
50754
|
+
(0, import_child_process15.execFileSync)("security", ["help"], { stdio: "pipe" });
|
|
50170
50755
|
return true;
|
|
50171
50756
|
} catch {
|
|
50172
50757
|
return false;
|
|
@@ -50174,7 +50759,7 @@ var init_keychain = __esm({
|
|
|
50174
50759
|
}
|
|
50175
50760
|
if ((0, import_os6.platform)() === "linux") {
|
|
50176
50761
|
try {
|
|
50177
|
-
(0,
|
|
50762
|
+
(0, import_child_process15.execFileSync)("which", ["secret-tool"], { stdio: "pipe" });
|
|
50178
50763
|
return true;
|
|
50179
50764
|
} catch {
|
|
50180
50765
|
return false;
|
|
@@ -50190,7 +50775,7 @@ var init_keychain = __esm({
|
|
|
50190
50775
|
readFromKeychain(provider) {
|
|
50191
50776
|
this.validateProvider(provider);
|
|
50192
50777
|
if ((0, import_os6.platform)() === "darwin") {
|
|
50193
|
-
return (0,
|
|
50778
|
+
return (0, import_child_process15.execFileSync)("security", [
|
|
50194
50779
|
"find-generic-password",
|
|
50195
50780
|
"-s",
|
|
50196
50781
|
this.serviceName,
|
|
@@ -50200,7 +50785,7 @@ var init_keychain = __esm({
|
|
|
50200
50785
|
], { stdio: "pipe" }).toString().trim();
|
|
50201
50786
|
}
|
|
50202
50787
|
if ((0, import_os6.platform)() === "linux") {
|
|
50203
|
-
return (0,
|
|
50788
|
+
return (0, import_child_process15.execFileSync)("secret-tool", [
|
|
50204
50789
|
"lookup",
|
|
50205
50790
|
"service",
|
|
50206
50791
|
this.serviceName,
|
|
@@ -50214,7 +50799,7 @@ var init_keychain = __esm({
|
|
|
50214
50799
|
this.validateProvider(provider);
|
|
50215
50800
|
if ((0, import_os6.platform)() === "darwin") {
|
|
50216
50801
|
try {
|
|
50217
|
-
(0,
|
|
50802
|
+
(0, import_child_process15.execFileSync)("security", [
|
|
50218
50803
|
"delete-generic-password",
|
|
50219
50804
|
"-s",
|
|
50220
50805
|
this.serviceName,
|
|
@@ -50223,7 +50808,7 @@ var init_keychain = __esm({
|
|
|
50223
50808
|
], { stdio: "pipe" });
|
|
50224
50809
|
} catch {
|
|
50225
50810
|
}
|
|
50226
|
-
(0,
|
|
50811
|
+
(0, import_child_process15.execFileSync)("security", [
|
|
50227
50812
|
"add-generic-password",
|
|
50228
50813
|
"-s",
|
|
50229
50814
|
this.serviceName,
|
|
@@ -50235,7 +50820,7 @@ var init_keychain = __esm({
|
|
|
50235
50820
|
return;
|
|
50236
50821
|
}
|
|
50237
50822
|
if ((0, import_os6.platform)() === "linux") {
|
|
50238
|
-
(0,
|
|
50823
|
+
(0, import_child_process15.execFileSync)("secret-tool", [
|
|
50239
50824
|
"store",
|
|
50240
50825
|
"--label",
|
|
50241
50826
|
`Gossip Mesh ${provider}`,
|
|
@@ -50254,12 +50839,13 @@ var init_keychain = __esm({
|
|
|
50254
50839
|
// apps/cli/src/code-launch.ts
|
|
50255
50840
|
var code_launch_exports = {};
|
|
50256
50841
|
__export(code_launch_exports, {
|
|
50842
|
+
detectServerName: () => detectServerName,
|
|
50257
50843
|
runCodeCommand: () => runCodeCommand
|
|
50258
50844
|
});
|
|
50259
50845
|
function safeReadJson(filePath) {
|
|
50260
50846
|
try {
|
|
50261
|
-
if (!(0,
|
|
50262
|
-
const raw = (0,
|
|
50847
|
+
if (!(0, import_fs88.existsSync)(filePath)) return null;
|
|
50848
|
+
const raw = (0, import_fs88.readFileSync)(filePath, "utf-8");
|
|
50263
50849
|
return JSON.parse(raw);
|
|
50264
50850
|
} catch {
|
|
50265
50851
|
return null;
|
|
@@ -50276,21 +50862,23 @@ function isGossipMcpEntry(entry) {
|
|
|
50276
50862
|
return false;
|
|
50277
50863
|
}
|
|
50278
50864
|
function detectServerName(cwd) {
|
|
50865
|
+
const cwdPath = (0, import_path94.join)(cwd, ".mcp.json");
|
|
50866
|
+
const homePath = (0, import_path94.join)((0, import_os7.homedir)(), ".claude.json");
|
|
50279
50867
|
const candidates = [
|
|
50280
|
-
[
|
|
50281
|
-
[
|
|
50868
|
+
[cwdPath, safeReadJson(cwdPath)],
|
|
50869
|
+
[homePath, safeReadJson(homePath)]
|
|
50282
50870
|
];
|
|
50283
|
-
|
|
50284
|
-
if (!data || typeof data !== "object")
|
|
50871
|
+
function extractName(data, filePath) {
|
|
50872
|
+
if (!data || typeof data !== "object") return null;
|
|
50285
50873
|
const root = data;
|
|
50286
50874
|
const mcpServers = root["mcpServers"];
|
|
50287
|
-
if (!mcpServers || typeof mcpServers !== "object")
|
|
50875
|
+
if (!mcpServers || typeof mcpServers !== "object") return null;
|
|
50288
50876
|
const servers = mcpServers;
|
|
50289
50877
|
for (const [name, entry] of Object.entries(servers)) {
|
|
50290
50878
|
if (!entry || typeof entry !== "object") continue;
|
|
50291
50879
|
if (isGossipMcpEntry(entry)) {
|
|
50292
50880
|
if (SAFE_SERVER_NAME_RE.test(name)) {
|
|
50293
|
-
return
|
|
50881
|
+
return name;
|
|
50294
50882
|
}
|
|
50295
50883
|
process.stderr.write(
|
|
50296
50884
|
`[gossipcat code] Warning: found gossipcat MCP entry in ${filePath} but server name "${name}" contains unsafe characters; falling back to "gossipcat".
|
|
@@ -50298,11 +50886,30 @@ function detectServerName(cwd) {
|
|
|
50298
50886
|
);
|
|
50299
50887
|
}
|
|
50300
50888
|
}
|
|
50889
|
+
return null;
|
|
50890
|
+
}
|
|
50891
|
+
const cwdName = extractName(candidates[0][1], cwdPath);
|
|
50892
|
+
const homeName = extractName(candidates[1][1], homePath);
|
|
50893
|
+
if (cwdName !== null) {
|
|
50894
|
+
process.stderr.write(
|
|
50895
|
+
`[gossipcat code] Using channel server "${cwdName}" from ${cwdPath} (cwd-local config \u2014 only run this in repos you trust).
|
|
50896
|
+
`
|
|
50897
|
+
);
|
|
50898
|
+
if (homeName !== null && homeName !== cwdName) {
|
|
50899
|
+
process.stderr.write(
|
|
50900
|
+
`[gossipcat code] Warning: gossipcat server name differs between ${cwdPath} ("${cwdName}") and ${homePath} ("${homeName}"); using "${cwdName}" (cwd takes precedence).
|
|
50901
|
+
`
|
|
50902
|
+
);
|
|
50903
|
+
}
|
|
50904
|
+
return [cwdName, false];
|
|
50905
|
+
}
|
|
50906
|
+
if (homeName !== null) {
|
|
50907
|
+
return [homeName, false];
|
|
50301
50908
|
}
|
|
50302
50909
|
return ["gossipcat", true];
|
|
50303
50910
|
}
|
|
50304
50911
|
function isChannelAllowlisted(cwd) {
|
|
50305
|
-
const configPath = (0,
|
|
50912
|
+
const configPath = (0, import_path94.join)(cwd, ".gossip", "config.json");
|
|
50306
50913
|
try {
|
|
50307
50914
|
const data = safeReadJson(configPath);
|
|
50308
50915
|
if (!data || typeof data !== "object") return false;
|
|
@@ -50334,7 +50941,7 @@ function runCodeCommand(argv) {
|
|
|
50334
50941
|
);
|
|
50335
50942
|
claudeArgs = ["--dangerously-load-development-channels", `server:${serverName}`, ...argv];
|
|
50336
50943
|
}
|
|
50337
|
-
const child = (0,
|
|
50944
|
+
const child = (0, import_child_process16.spawn)("claude", claudeArgs, { stdio: "inherit" });
|
|
50338
50945
|
child.on("error", (err) => {
|
|
50339
50946
|
if (err.code === "ENOENT") {
|
|
50340
50947
|
process.stderr.write(
|
|
@@ -50355,14 +50962,14 @@ function runCodeCommand(argv) {
|
|
|
50355
50962
|
}
|
|
50356
50963
|
});
|
|
50357
50964
|
}
|
|
50358
|
-
var
|
|
50965
|
+
var import_fs88, import_path94, import_os7, import_child_process16, SAFE_SERVER_NAME_RE;
|
|
50359
50966
|
var init_code_launch = __esm({
|
|
50360
50967
|
"apps/cli/src/code-launch.ts"() {
|
|
50361
50968
|
"use strict";
|
|
50362
|
-
|
|
50363
|
-
|
|
50969
|
+
import_fs88 = require("fs");
|
|
50970
|
+
import_path94 = require("path");
|
|
50364
50971
|
import_os7 = require("os");
|
|
50365
|
-
|
|
50972
|
+
import_child_process16 = require("child_process");
|
|
50366
50973
|
SAFE_SERVER_NAME_RE = /^[a-zA-Z0-9._-]{1,64}$/;
|
|
50367
50974
|
}
|
|
50368
50975
|
});
|
|
@@ -50377,23 +50984,23 @@ __export(identity_exports, {
|
|
|
50377
50984
|
normalizeGitUrl: () => normalizeGitUrl
|
|
50378
50985
|
});
|
|
50379
50986
|
function getOrCreateSalt(projectRoot) {
|
|
50380
|
-
const saltPath = (0,
|
|
50987
|
+
const saltPath = (0, import_path95.join)(projectRoot, ".gossip", "local-salt");
|
|
50381
50988
|
try {
|
|
50382
|
-
return (0,
|
|
50989
|
+
return (0, import_fs89.readFileSync)(saltPath, "utf-8").trim();
|
|
50383
50990
|
} catch {
|
|
50384
50991
|
const salt = (0, import_crypto36.randomBytes)(16).toString("hex");
|
|
50385
|
-
(0,
|
|
50992
|
+
(0, import_fs89.mkdirSync)((0, import_path95.join)(projectRoot, ".gossip"), { recursive: true });
|
|
50386
50993
|
try {
|
|
50387
|
-
(0,
|
|
50994
|
+
(0, import_fs89.writeFileSync)(saltPath, salt, { flag: "wx" });
|
|
50388
50995
|
return salt;
|
|
50389
50996
|
} catch {
|
|
50390
|
-
return (0,
|
|
50997
|
+
return (0, import_fs89.readFileSync)(saltPath, "utf-8").trim();
|
|
50391
50998
|
}
|
|
50392
50999
|
}
|
|
50393
51000
|
}
|
|
50394
51001
|
function getUserId(projectRoot) {
|
|
50395
51002
|
try {
|
|
50396
|
-
const email3 = (0,
|
|
51003
|
+
const email3 = (0, import_child_process17.execFileSync)("git", ["config", "user.email"], { stdio: "pipe" }).toString().trim();
|
|
50397
51004
|
const salt = getOrCreateSalt(projectRoot);
|
|
50398
51005
|
return (0, import_crypto36.createHash)("sha256").update(email3 + projectRoot + salt).digest("hex").slice(0, 16);
|
|
50399
51006
|
} catch {
|
|
@@ -50416,7 +51023,7 @@ function getTeamUserId(email3, teamSalt) {
|
|
|
50416
51023
|
}
|
|
50417
51024
|
function getGitEmail() {
|
|
50418
51025
|
try {
|
|
50419
|
-
const email3 = (0,
|
|
51026
|
+
const email3 = (0, import_child_process17.execFileSync)("git", ["config", "user.email"], { stdio: "pipe" }).toString().trim();
|
|
50420
51027
|
return email3 || null;
|
|
50421
51028
|
} catch {
|
|
50422
51029
|
return null;
|
|
@@ -50424,7 +51031,7 @@ function getGitEmail() {
|
|
|
50424
51031
|
}
|
|
50425
51032
|
function getProjectId(projectRoot) {
|
|
50426
51033
|
try {
|
|
50427
|
-
const remoteUrl = (0,
|
|
51034
|
+
const remoteUrl = (0, import_child_process17.execFileSync)(
|
|
50428
51035
|
"git",
|
|
50429
51036
|
["config", "--get", "remote.origin.url"],
|
|
50430
51037
|
{ cwd: projectRoot, stdio: "pipe" }
|
|
@@ -50437,14 +51044,14 @@ function getProjectId(projectRoot) {
|
|
|
50437
51044
|
}
|
|
50438
51045
|
return (0, import_crypto36.createHash)("sha256").update(projectRoot).digest("hex").slice(0, 16);
|
|
50439
51046
|
}
|
|
50440
|
-
var
|
|
51047
|
+
var import_fs89, import_path95, import_crypto36, import_child_process17;
|
|
50441
51048
|
var init_identity = __esm({
|
|
50442
51049
|
"apps/cli/src/identity.ts"() {
|
|
50443
51050
|
"use strict";
|
|
50444
|
-
|
|
50445
|
-
|
|
51051
|
+
import_fs89 = require("fs");
|
|
51052
|
+
import_path95 = require("path");
|
|
50446
51053
|
import_crypto36 = require("crypto");
|
|
50447
|
-
|
|
51054
|
+
import_child_process17 = require("child_process");
|
|
50448
51055
|
}
|
|
50449
51056
|
});
|
|
50450
51057
|
|
|
@@ -50511,9 +51118,9 @@ async function getLatestVersion() {
|
|
|
50511
51118
|
return data.version;
|
|
50512
51119
|
}
|
|
50513
51120
|
function detectInstallMethod() {
|
|
50514
|
-
const packageRoot = (0,
|
|
51121
|
+
const packageRoot = (0, import_path96.resolve)(__dirname, "..", "..", "..", "..");
|
|
50515
51122
|
if (process.env.npm_config_global === "true") return "global";
|
|
50516
|
-
if ((0,
|
|
51123
|
+
if ((0, import_fs90.existsSync)((0, import_path96.join)(packageRoot, ".git"))) return "git-clone";
|
|
50517
51124
|
return "local";
|
|
50518
51125
|
}
|
|
50519
51126
|
function updateCommand(method, version2) {
|
|
@@ -50566,9 +51173,9 @@ Check your internet connection or visit https://www.npmjs.com/package/gossipcat
|
|
|
50566
51173
|
if (/^GOSSIPCAT_/i.test(key)) delete scrubbedEnv[key];
|
|
50567
51174
|
}
|
|
50568
51175
|
try {
|
|
50569
|
-
(0,
|
|
51176
|
+
(0, import_child_process18.execSync)(command, {
|
|
50570
51177
|
stdio: "inherit",
|
|
50571
|
-
cwd: method === "git-clone" ? (0,
|
|
51178
|
+
cwd: method === "git-clone" ? (0, import_path96.resolve)(__dirname, "..", "..", "..", "..") : process.cwd(),
|
|
50572
51179
|
env: scrubbedEnv
|
|
50573
51180
|
});
|
|
50574
51181
|
} catch (err) {
|
|
@@ -50591,13 +51198,13 @@ Run /mcp reconnect in Claude Code to load the new version.`
|
|
|
50591
51198
|
}]
|
|
50592
51199
|
};
|
|
50593
51200
|
}
|
|
50594
|
-
var
|
|
51201
|
+
var import_child_process18, import_fs90, import_path96;
|
|
50595
51202
|
var init_gossip_update = __esm({
|
|
50596
51203
|
"apps/cli/src/handlers/gossip-update.ts"() {
|
|
50597
51204
|
"use strict";
|
|
50598
|
-
|
|
50599
|
-
|
|
50600
|
-
|
|
51205
|
+
import_child_process18 = require("child_process");
|
|
51206
|
+
import_fs90 = require("fs");
|
|
51207
|
+
import_path96 = require("path");
|
|
50601
51208
|
init_version();
|
|
50602
51209
|
}
|
|
50603
51210
|
});
|
|
@@ -50810,8 +51417,8 @@ __export(mcp_server_sdk_exports, {
|
|
|
50810
51417
|
resolveHookAction: () => resolveHookAction
|
|
50811
51418
|
});
|
|
50812
51419
|
module.exports = __toCommonJS(mcp_server_sdk_exports);
|
|
50813
|
-
var
|
|
50814
|
-
var
|
|
51420
|
+
var import_fs91 = require("fs");
|
|
51421
|
+
var import_path97 = require("path");
|
|
50815
51422
|
|
|
50816
51423
|
// apps/cli/src/hook-run.ts
|
|
50817
51424
|
var import_fs = require("fs");
|
|
@@ -50894,10 +51501,10 @@ var RELAY_PORT_FILE = "relay.port";
|
|
|
50894
51501
|
var AUTH_MAX_READ = 64 * 1024;
|
|
50895
51502
|
var CURL_MAX_TIME = "2";
|
|
50896
51503
|
function readDashboardKey(cwd) {
|
|
50897
|
-
const
|
|
51504
|
+
const path8 = (0, import_path2.join)(cwd, ".gossip", AUTH_FILE_NAME);
|
|
50898
51505
|
let fd = null;
|
|
50899
51506
|
try {
|
|
50900
|
-
fd = (0, import_fs2.openSync)(
|
|
51507
|
+
fd = (0, import_fs2.openSync)(path8, "r");
|
|
50901
51508
|
const st = (0, import_fs2.fstatSync)(fd);
|
|
50902
51509
|
if (!st.isFile()) return null;
|
|
50903
51510
|
if ((st.mode & 63) !== 0) return null;
|
|
@@ -50994,7 +51601,7 @@ function resolveCwd(payloadCwd) {
|
|
|
50994
51601
|
return process.cwd();
|
|
50995
51602
|
}
|
|
50996
51603
|
function readStdin() {
|
|
50997
|
-
return new Promise((
|
|
51604
|
+
return new Promise((resolve33) => {
|
|
50998
51605
|
let data = "";
|
|
50999
51606
|
try {
|
|
51000
51607
|
const stdin = process.stdin;
|
|
@@ -51002,11 +51609,11 @@ function readStdin() {
|
|
|
51002
51609
|
stdin.on("data", (chunk) => {
|
|
51003
51610
|
data += chunk;
|
|
51004
51611
|
});
|
|
51005
|
-
stdin.on("end", () =>
|
|
51006
|
-
stdin.on("error", () =>
|
|
51007
|
-
if (stdin.isTTY)
|
|
51612
|
+
stdin.on("end", () => resolve33(data));
|
|
51613
|
+
stdin.on("error", () => resolve33(data));
|
|
51614
|
+
if (stdin.isTTY) resolve33("");
|
|
51008
51615
|
} catch {
|
|
51009
|
-
|
|
51616
|
+
resolve33("");
|
|
51010
51617
|
}
|
|
51011
51618
|
});
|
|
51012
51619
|
}
|
|
@@ -51243,9 +51850,9 @@ function getLastKnownLatest(cwd = process.cwd()) {
|
|
|
51243
51850
|
async function checkForUpgrade(cwd = process.cwd()) {
|
|
51244
51851
|
try {
|
|
51245
51852
|
if (process.env.GOSSIP_DISABLE_UPGRADE_CHECK === "1") return;
|
|
51246
|
-
const
|
|
51853
|
+
const path8 = cachePath(cwd);
|
|
51247
51854
|
try {
|
|
51248
|
-
const raw = (0, import_fs4.readFileSync)(
|
|
51855
|
+
const raw = (0, import_fs4.readFileSync)(path8, "utf8");
|
|
51249
51856
|
const data = JSON.parse(raw);
|
|
51250
51857
|
if (typeof data.checkedAt === "string") {
|
|
51251
51858
|
const checkedMs = new Date(data.checkedAt).getTime();
|
|
@@ -51262,13 +51869,13 @@ async function checkForUpgrade(cwd = process.cwd()) {
|
|
|
51262
51869
|
latestVersion: json2.version
|
|
51263
51870
|
};
|
|
51264
51871
|
try {
|
|
51265
|
-
(0, import_fs4.mkdirSync)((0, import_path3.dirname)(
|
|
51872
|
+
(0, import_fs4.mkdirSync)((0, import_path3.dirname)(path8), { recursive: true });
|
|
51266
51873
|
} catch {
|
|
51267
51874
|
}
|
|
51268
|
-
const tmp = `${
|
|
51875
|
+
const tmp = `${path8}.${process.pid}.tmp`;
|
|
51269
51876
|
(0, import_fs4.writeFileSync)(tmp, JSON.stringify(cache3), "utf8");
|
|
51270
51877
|
try {
|
|
51271
|
-
(0, import_fs4.renameSync)(tmp,
|
|
51878
|
+
(0, import_fs4.renameSync)(tmp, path8);
|
|
51272
51879
|
} catch (err) {
|
|
51273
51880
|
try {
|
|
51274
51881
|
(0, import_fs4.unlinkSync)(tmp);
|
|
@@ -51659,8 +52266,8 @@ function getErrorMap() {
|
|
|
51659
52266
|
|
|
51660
52267
|
// node_modules/zod/v3/helpers/parseUtil.js
|
|
51661
52268
|
var makeIssue = (params) => {
|
|
51662
|
-
const { data, path:
|
|
51663
|
-
const fullPath = [...
|
|
52269
|
+
const { data, path: path8, errorMaps, issueData } = params;
|
|
52270
|
+
const fullPath = [...path8, ...issueData.path || []];
|
|
51664
52271
|
const fullIssue = {
|
|
51665
52272
|
...issueData,
|
|
51666
52273
|
path: fullPath
|
|
@@ -51775,11 +52382,11 @@ var errorUtil;
|
|
|
51775
52382
|
|
|
51776
52383
|
// node_modules/zod/v3/types.js
|
|
51777
52384
|
var ParseInputLazyPath = class {
|
|
51778
|
-
constructor(parent, value,
|
|
52385
|
+
constructor(parent, value, path8, key) {
|
|
51779
52386
|
this._cachedPath = [];
|
|
51780
52387
|
this.parent = parent;
|
|
51781
52388
|
this.data = value;
|
|
51782
|
-
this._path =
|
|
52389
|
+
this._path = path8;
|
|
51783
52390
|
this._key = key;
|
|
51784
52391
|
}
|
|
51785
52392
|
get path() {
|
|
@@ -55699,10 +56306,10 @@ function mergeDefs(...defs) {
|
|
|
55699
56306
|
function cloneDef(schema) {
|
|
55700
56307
|
return mergeDefs(schema._zod.def);
|
|
55701
56308
|
}
|
|
55702
|
-
function getElementAtPath(obj,
|
|
55703
|
-
if (!
|
|
56309
|
+
function getElementAtPath(obj, path8) {
|
|
56310
|
+
if (!path8)
|
|
55704
56311
|
return obj;
|
|
55705
|
-
return
|
|
56312
|
+
return path8.reduce((acc, key) => acc?.[key], obj);
|
|
55706
56313
|
}
|
|
55707
56314
|
function promiseAllObject(promisesObj) {
|
|
55708
56315
|
const keys = Object.keys(promisesObj);
|
|
@@ -56111,11 +56718,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
56111
56718
|
}
|
|
56112
56719
|
return false;
|
|
56113
56720
|
}
|
|
56114
|
-
function prefixIssues(
|
|
56721
|
+
function prefixIssues(path8, issues) {
|
|
56115
56722
|
return issues.map((iss) => {
|
|
56116
56723
|
var _a3;
|
|
56117
56724
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
56118
|
-
iss.path.unshift(
|
|
56725
|
+
iss.path.unshift(path8);
|
|
56119
56726
|
return iss;
|
|
56120
56727
|
});
|
|
56121
56728
|
}
|
|
@@ -56262,16 +56869,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
56262
56869
|
}
|
|
56263
56870
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
56264
56871
|
const fieldErrors = { _errors: [] };
|
|
56265
|
-
const processError = (error52,
|
|
56872
|
+
const processError = (error52, path8 = []) => {
|
|
56266
56873
|
for (const issue2 of error52.issues) {
|
|
56267
56874
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
56268
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
56875
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
56269
56876
|
} else if (issue2.code === "invalid_key") {
|
|
56270
|
-
processError({ issues: issue2.issues }, [...
|
|
56877
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
56271
56878
|
} else if (issue2.code === "invalid_element") {
|
|
56272
|
-
processError({ issues: issue2.issues }, [...
|
|
56879
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
56273
56880
|
} else {
|
|
56274
|
-
const fullpath = [...
|
|
56881
|
+
const fullpath = [...path8, ...issue2.path];
|
|
56275
56882
|
if (fullpath.length === 0) {
|
|
56276
56883
|
fieldErrors._errors.push(mapper(issue2));
|
|
56277
56884
|
} else {
|
|
@@ -56298,17 +56905,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
56298
56905
|
}
|
|
56299
56906
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
56300
56907
|
const result = { errors: [] };
|
|
56301
|
-
const processError = (error52,
|
|
56908
|
+
const processError = (error52, path8 = []) => {
|
|
56302
56909
|
var _a3, _b;
|
|
56303
56910
|
for (const issue2 of error52.issues) {
|
|
56304
56911
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
56305
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
56912
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
56306
56913
|
} else if (issue2.code === "invalid_key") {
|
|
56307
|
-
processError({ issues: issue2.issues }, [...
|
|
56914
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
56308
56915
|
} else if (issue2.code === "invalid_element") {
|
|
56309
|
-
processError({ issues: issue2.issues }, [...
|
|
56916
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
56310
56917
|
} else {
|
|
56311
|
-
const fullpath = [...
|
|
56918
|
+
const fullpath = [...path8, ...issue2.path];
|
|
56312
56919
|
if (fullpath.length === 0) {
|
|
56313
56920
|
result.errors.push(mapper(issue2));
|
|
56314
56921
|
continue;
|
|
@@ -56340,8 +56947,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
56340
56947
|
}
|
|
56341
56948
|
function toDotPath(_path) {
|
|
56342
56949
|
const segs = [];
|
|
56343
|
-
const
|
|
56344
|
-
for (const seg of
|
|
56950
|
+
const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
56951
|
+
for (const seg of path8) {
|
|
56345
56952
|
if (typeof seg === "number")
|
|
56346
56953
|
segs.push(`[${seg}]`);
|
|
56347
56954
|
else if (typeof seg === "symbol")
|
|
@@ -69466,13 +70073,13 @@ function resolveRef(ref, ctx2) {
|
|
|
69466
70073
|
if (!ref.startsWith("#")) {
|
|
69467
70074
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
69468
70075
|
}
|
|
69469
|
-
const
|
|
69470
|
-
if (
|
|
70076
|
+
const path8 = ref.slice(1).split("/").filter(Boolean);
|
|
70077
|
+
if (path8.length === 0) {
|
|
69471
70078
|
return ctx2.rootSchema;
|
|
69472
70079
|
}
|
|
69473
70080
|
const defsKey = ctx2.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
69474
|
-
if (
|
|
69475
|
-
const key =
|
|
70081
|
+
if (path8[0] === defsKey) {
|
|
70082
|
+
const key = path8[1];
|
|
69476
70083
|
if (!key || !ctx2.defs[key]) {
|
|
69477
70084
|
throw new Error(`Reference not found: ${ref}`);
|
|
69478
70085
|
}
|
|
@@ -73244,7 +73851,7 @@ var Protocol = class {
|
|
|
73244
73851
|
return;
|
|
73245
73852
|
}
|
|
73246
73853
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
73247
|
-
await new Promise((
|
|
73854
|
+
await new Promise((resolve33) => setTimeout(resolve33, pollInterval));
|
|
73248
73855
|
options?.signal?.throwIfAborted();
|
|
73249
73856
|
}
|
|
73250
73857
|
} catch (error51) {
|
|
@@ -73261,7 +73868,7 @@ var Protocol = class {
|
|
|
73261
73868
|
*/
|
|
73262
73869
|
request(request, resultSchema, options) {
|
|
73263
73870
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
73264
|
-
return new Promise((
|
|
73871
|
+
return new Promise((resolve33, reject) => {
|
|
73265
73872
|
const earlyReject = (error51) => {
|
|
73266
73873
|
reject(error51);
|
|
73267
73874
|
};
|
|
@@ -73339,7 +73946,7 @@ var Protocol = class {
|
|
|
73339
73946
|
if (!parseResult.success) {
|
|
73340
73947
|
reject(parseResult.error);
|
|
73341
73948
|
} else {
|
|
73342
|
-
|
|
73949
|
+
resolve33(parseResult.data);
|
|
73343
73950
|
}
|
|
73344
73951
|
} catch (error51) {
|
|
73345
73952
|
reject(error51);
|
|
@@ -73600,12 +74207,12 @@ var Protocol = class {
|
|
|
73600
74207
|
}
|
|
73601
74208
|
} catch {
|
|
73602
74209
|
}
|
|
73603
|
-
return new Promise((
|
|
74210
|
+
return new Promise((resolve33, reject) => {
|
|
73604
74211
|
if (signal.aborted) {
|
|
73605
74212
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
73606
74213
|
return;
|
|
73607
74214
|
}
|
|
73608
|
-
const timeoutId = setTimeout(
|
|
74215
|
+
const timeoutId = setTimeout(resolve33, interval);
|
|
73609
74216
|
signal.addEventListener("abort", () => {
|
|
73610
74217
|
clearTimeout(timeoutId);
|
|
73611
74218
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -74705,7 +75312,7 @@ var McpServer = class {
|
|
|
74705
75312
|
let task = createTaskResult.task;
|
|
74706
75313
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
74707
75314
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
74708
|
-
await new Promise((
|
|
75315
|
+
await new Promise((resolve33) => setTimeout(resolve33, pollInterval));
|
|
74709
75316
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
74710
75317
|
if (!updatedTask) {
|
|
74711
75318
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -75408,12 +76015,12 @@ var StdioServerTransport = class {
|
|
|
75408
76015
|
this.onclose?.();
|
|
75409
76016
|
}
|
|
75410
76017
|
send(message) {
|
|
75411
|
-
return new Promise((
|
|
76018
|
+
return new Promise((resolve33) => {
|
|
75412
76019
|
const json2 = serializeMessage(message);
|
|
75413
76020
|
if (this._stdout.write(json2)) {
|
|
75414
|
-
|
|
76021
|
+
resolve33();
|
|
75415
76022
|
} else {
|
|
75416
|
-
this._stdout.once("drain",
|
|
76023
|
+
this._stdout.once("drain", resolve33);
|
|
75417
76024
|
}
|
|
75418
76025
|
});
|
|
75419
76026
|
}
|
|
@@ -75912,7 +76519,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
|
75912
76519
|
});
|
|
75913
76520
|
if (!chunk) {
|
|
75914
76521
|
if (i === 1) {
|
|
75915
|
-
await new Promise((
|
|
76522
|
+
await new Promise((resolve33) => setTimeout(resolve33));
|
|
75916
76523
|
maxReadCount = 3;
|
|
75917
76524
|
continue;
|
|
75918
76525
|
}
|
|
@@ -76412,9 +77019,9 @@ data:
|
|
|
76412
77019
|
const initRequest = messages.find((m) => isInitializeRequest(m));
|
|
76413
77020
|
const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
|
|
76414
77021
|
if (this._enableJsonResponse) {
|
|
76415
|
-
return new Promise((
|
|
77022
|
+
return new Promise((resolve33) => {
|
|
76416
77023
|
this._streamMapping.set(streamId, {
|
|
76417
|
-
resolveJson:
|
|
77024
|
+
resolveJson: resolve33,
|
|
76418
77025
|
cleanup: () => {
|
|
76419
77026
|
this._streamMapping.delete(streamId);
|
|
76420
77027
|
}
|
|
@@ -76799,8 +77406,8 @@ init_native_tasks();
|
|
|
76799
77406
|
|
|
76800
77407
|
// apps/cli/src/handlers/dispatch.ts
|
|
76801
77408
|
var import_crypto34 = require("crypto");
|
|
76802
|
-
var
|
|
76803
|
-
var
|
|
77409
|
+
var import_fs79 = require("fs");
|
|
77410
|
+
var import_path86 = require("path");
|
|
76804
77411
|
init_src4();
|
|
76805
77412
|
init_src3();
|
|
76806
77413
|
|
|
@@ -76934,10 +77541,11 @@ function nativeDispatchViaLabel(host = detectNativeHost()) {
|
|
|
76934
77541
|
|
|
76935
77542
|
// apps/cli/src/handlers/dispatch.ts
|
|
76936
77543
|
init_mcp_context();
|
|
77544
|
+
init_orchestrator_precondition_runner();
|
|
76937
77545
|
init_native_tasks();
|
|
76938
77546
|
init_dispatch_prompt_storage();
|
|
76939
77547
|
init_dispatch_prompt_cache();
|
|
76940
|
-
var
|
|
77548
|
+
var import_fs80 = require("fs");
|
|
76941
77549
|
|
|
76942
77550
|
// apps/cli/src/handlers/relay-tasks.ts
|
|
76943
77551
|
init_mcp_context();
|
|
@@ -77108,7 +77716,7 @@ function tryWarmCacheHit(liveTaskBlock, cacheKey2, promptFormat) {
|
|
|
77108
77716
|
const cached4 = getCachedPrompt(cacheKey2);
|
|
77109
77717
|
if (!cached4) return null;
|
|
77110
77718
|
if (cached4.skillFingerprint !== cacheKey2.skillFingerprint) return null;
|
|
77111
|
-
if (!(0,
|
|
77719
|
+
if (!(0, import_fs80.existsSync)(cached4.skillsSectionPath)) return null;
|
|
77112
77720
|
try {
|
|
77113
77721
|
const skillsSection = require("fs").readFileSync(cached4.skillsSectionPath, "utf8");
|
|
77114
77722
|
return skillsSection + liveTaskBlock;
|
|
@@ -77185,9 +77793,9 @@ function formatFalsifiedNote(block, verdicts) {
|
|
|
77185
77793
|
}
|
|
77186
77794
|
function writePremiseVerificationLog(projectRoot, taskId, result, opts) {
|
|
77187
77795
|
try {
|
|
77188
|
-
const logPath = (0,
|
|
77796
|
+
const logPath = (0, import_path86.join)(projectRoot, PREMISE_VERIFICATION_LOG);
|
|
77189
77797
|
rotateIfNeeded2(logPath, MAX_PREMISE_VERIFICATION_BYTES);
|
|
77190
|
-
(0,
|
|
77798
|
+
(0, import_fs79.mkdirSync)((0, import_path86.join)(projectRoot, ".gossip"), { recursive: true });
|
|
77191
77799
|
const row = {
|
|
77192
77800
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
77193
77801
|
consensus_id: null,
|
|
@@ -77201,7 +77809,7 @@ function writePremiseVerificationLog(projectRoot, taskId, result, opts) {
|
|
|
77201
77809
|
skill_bound: opts.skill_bound
|
|
77202
77810
|
};
|
|
77203
77811
|
if (opts.schema_lint) row.schema_lint = opts.schema_lint;
|
|
77204
|
-
(0,
|
|
77812
|
+
(0, import_fs79.appendFileSync)(logPath, JSON.stringify(row) + "\n");
|
|
77205
77813
|
} catch {
|
|
77206
77814
|
}
|
|
77207
77815
|
}
|
|
@@ -77313,7 +77921,7 @@ var AGENT_PROVIDER_MAP = {
|
|
|
77313
77921
|
};
|
|
77314
77922
|
function readQuotaState() {
|
|
77315
77923
|
try {
|
|
77316
|
-
const raw = (0,
|
|
77924
|
+
const raw = (0, import_fs79.readFileSync)((0, import_path86.join)(process.cwd(), ".gossip", "quota-state.json"), "utf8");
|
|
77317
77925
|
return JSON.parse(raw);
|
|
77318
77926
|
} catch {
|
|
77319
77927
|
return {};
|
|
@@ -77379,6 +77987,19 @@ async function handleDispatchSingle(agent_id, task, write_mode, scope, timeout_m
|
|
|
77379
77987
|
const relayToken = (0, import_crypto34.randomUUID)().slice(0, 12);
|
|
77380
77988
|
const timeoutMs = timeout_ms ?? NATIVE_TASK_TTL_MS;
|
|
77381
77989
|
stashDispatchWarnings([taskId], dispatchWarnings);
|
|
77990
|
+
runDispatchPreconditionGuard({
|
|
77991
|
+
projectRoot: process.cwd(),
|
|
77992
|
+
taskId,
|
|
77993
|
+
resolutionRoots,
|
|
77994
|
+
taskText: task,
|
|
77995
|
+
writeMode: write_mode
|
|
77996
|
+
}).then(({ warnings: precondWarnings }) => {
|
|
77997
|
+
for (const w of precondWarnings) {
|
|
77998
|
+
process.stderr.write(`[gossipcat] \u26A0\uFE0F precondition: ${w}
|
|
77999
|
+
`);
|
|
78000
|
+
}
|
|
78001
|
+
}).catch(() => {
|
|
78002
|
+
});
|
|
77382
78003
|
const premiseResult = await maybeVerifyPremiseClaims(task, process.cwd(), taskId, agent_id);
|
|
77383
78004
|
task = premiseResult.annotatedTask;
|
|
77384
78005
|
if (premiseResult.signals.length > 0) {
|
|
@@ -77796,6 +78417,24 @@ Task: ${def.task}`;
|
|
|
77796
78417
|
}
|
|
77797
78418
|
}
|
|
77798
78419
|
stashDispatchWarnings(allParallelTaskIds, dispatchWarnings);
|
|
78420
|
+
if (allParallelTaskIds.length > 0) {
|
|
78421
|
+
runDispatchPreconditionGuard({
|
|
78422
|
+
projectRoot: process.cwd(),
|
|
78423
|
+
taskId: allParallelTaskIds[0],
|
|
78424
|
+
resolutionRoots: effectiveResolutionRoots,
|
|
78425
|
+
taskText: taskDefs[0]?.task ?? "",
|
|
78426
|
+
writeMode: taskDefs[0]?.write_mode,
|
|
78427
|
+
// Bug A follow-up (Fix 1): scan ALL tasks for referenced paths, not just
|
|
78428
|
+
// taskDefs[0]. Stale-base/mid-flight stay one-per-dispatch above.
|
|
78429
|
+
additionalTasks: taskDefs.slice(1).map((d) => ({ taskText: d.task ?? "", writeMode: d.write_mode }))
|
|
78430
|
+
}).then(({ warnings: precondWarnings }) => {
|
|
78431
|
+
for (const w of precondWarnings) {
|
|
78432
|
+
process.stderr.write(`[gossipcat] \u26A0\uFE0F precondition: ${w}
|
|
78433
|
+
`);
|
|
78434
|
+
}
|
|
78435
|
+
}).catch(() => {
|
|
78436
|
+
});
|
|
78437
|
+
}
|
|
77799
78438
|
const parallelHost = detectNativeHost();
|
|
77800
78439
|
let msg = "";
|
|
77801
78440
|
if (nativeInstructions.length > 0) {
|
|
@@ -77874,8 +78513,8 @@ async function handleDispatchConsensus(taskDefs, _utility_task_id, dispatchResol
|
|
|
77874
78513
|
});
|
|
77875
78514
|
const lenses = await Promise.race([
|
|
77876
78515
|
lensPromise,
|
|
77877
|
-
new Promise((
|
|
77878
|
-
timerId = setTimeout(() =>
|
|
78516
|
+
new Promise((resolve33) => {
|
|
78517
|
+
timerId = setTimeout(() => resolve33(null), LENS_TIMEOUT_MS);
|
|
77879
78518
|
})
|
|
77880
78519
|
]);
|
|
77881
78520
|
if (timerId) clearTimeout(timerId);
|
|
@@ -78031,6 +78670,24 @@ Task: ${def.task}`;
|
|
|
78031
78670
|
}
|
|
78032
78671
|
}
|
|
78033
78672
|
stashDispatchWarnings(allTaskIds, dispatchRoundWarnings);
|
|
78673
|
+
if (allTaskIds.length > 0) {
|
|
78674
|
+
runDispatchPreconditionGuard({
|
|
78675
|
+
projectRoot: process.cwd(),
|
|
78676
|
+
taskId: allTaskIds[0],
|
|
78677
|
+
resolutionRoots: dispatchResolutionRoots,
|
|
78678
|
+
taskText: taskDefs[0]?.task ?? "",
|
|
78679
|
+
writeMode: taskDefs[0]?.write_mode,
|
|
78680
|
+
// Bug A follow-up (Fix 1): scan ALL tasks for referenced paths, not just
|
|
78681
|
+
// taskDefs[0]. Stale-base/mid-flight stay one-per-dispatch above.
|
|
78682
|
+
additionalTasks: taskDefs.slice(1).map((d) => ({ taskText: d.task ?? "", writeMode: d.write_mode }))
|
|
78683
|
+
}).then(({ warnings: precondWarnings }) => {
|
|
78684
|
+
for (const w of precondWarnings) {
|
|
78685
|
+
process.stderr.write(`[gossipcat] \u26A0\uFE0F precondition: ${w}
|
|
78686
|
+
`);
|
|
78687
|
+
}
|
|
78688
|
+
}).catch(() => {
|
|
78689
|
+
});
|
|
78690
|
+
}
|
|
78034
78691
|
const consensusHost = detectNativeHost();
|
|
78035
78692
|
const nativeTool = nativeToolName(consensusHost);
|
|
78036
78693
|
const collectCall = `gossip_collect(task_ids: [${allTaskIds.map((id) => `"${id}"`).join(", ")}], consensus: true)`;
|
|
@@ -78080,6 +78737,70 @@ ${p.prompt}` });
|
|
|
78080
78737
|
return dispatchWarnings.length > 0 ? { content, warnings: dispatchWarnings } : { content };
|
|
78081
78738
|
}
|
|
78082
78739
|
|
|
78740
|
+
// apps/cli/src/handlers/ask-back.ts
|
|
78741
|
+
var import_fs81 = require("fs");
|
|
78742
|
+
var import_path87 = require("path");
|
|
78743
|
+
var LEDGER_REL = (0, import_path87.join)(".gossip", "fabrication-introspections.jsonl");
|
|
78744
|
+
var MAX_INTROSPECTION_BYTES = 5 * 1024 * 1024;
|
|
78745
|
+
function ledgerPath(projectRoot) {
|
|
78746
|
+
return (0, import_path87.join)(projectRoot, LEDGER_REL);
|
|
78747
|
+
}
|
|
78748
|
+
function buildIntrospectionPrompt(claim, groundTruth) {
|
|
78749
|
+
return [
|
|
78750
|
+
"You are being asked to help improve the reliability of this review pipeline.",
|
|
78751
|
+
"",
|
|
78752
|
+
"A prior response from you was identified as a fabrication:",
|
|
78753
|
+
` Claim made: ${claim}`,
|
|
78754
|
+
` Ground truth: ${groundTruth}`,
|
|
78755
|
+
"",
|
|
78756
|
+
"Please reflect on the specific process failure that led to this.",
|
|
78757
|
+
"Do not apologize \u2014 instead, name the exact mechanism: for example,",
|
|
78758
|
+
'"I pattern-matched the task framing and assumed the identifier existed"',
|
|
78759
|
+
'or "I cited from memory without opening the file to verify".',
|
|
78760
|
+
"",
|
|
78761
|
+
"Your answer should be one to three sentences describing the HOW and WHY",
|
|
78762
|
+
"of the specific reasoning step that went wrong."
|
|
78763
|
+
].join("\n");
|
|
78764
|
+
}
|
|
78765
|
+
function appendIntrospection(projectRoot, record2, deps) {
|
|
78766
|
+
if (typeof record2.agentId !== "string" || !record2.agentId || typeof record2.status !== "string" || !record2.status) {
|
|
78767
|
+
return;
|
|
78768
|
+
}
|
|
78769
|
+
if (record2.status === "asked") {
|
|
78770
|
+
if (typeof record2.claim !== "string" || !record2.claim.trim() || typeof record2.groundTruth !== "string" || !record2.groundTruth.trim()) {
|
|
78771
|
+
return;
|
|
78772
|
+
}
|
|
78773
|
+
}
|
|
78774
|
+
const clean = {
|
|
78775
|
+
agentId: record2.agentId,
|
|
78776
|
+
claim: record2.claim,
|
|
78777
|
+
groundTruth: record2.groundTruth,
|
|
78778
|
+
status: record2.status
|
|
78779
|
+
};
|
|
78780
|
+
if (record2.askedAt !== void 0) clean["askedAt"] = record2.askedAt;
|
|
78781
|
+
if (record2.findingId !== void 0) clean["findingId"] = record2.findingId;
|
|
78782
|
+
if (record2.answer !== void 0) clean["answer"] = record2.answer;
|
|
78783
|
+
if (record2.answeredAt !== void 0) clean["answeredAt"] = record2.answeredAt;
|
|
78784
|
+
const line = JSON.stringify(clean) + "\n";
|
|
78785
|
+
const path8 = ledgerPath(projectRoot);
|
|
78786
|
+
try {
|
|
78787
|
+
const fsMkdir = deps?.mkdirSync ?? import_fs81.mkdirSync;
|
|
78788
|
+
const fsAppend = deps?.appendFileSync ?? import_fs81.appendFileSync;
|
|
78789
|
+
const fsStat = deps?.statSync ?? import_fs81.statSync;
|
|
78790
|
+
const fsRename = deps?.renameSync ?? import_fs81.renameSync;
|
|
78791
|
+
fsMkdir((0, import_path87.join)(projectRoot, ".gossip"), { recursive: true });
|
|
78792
|
+
try {
|
|
78793
|
+
const st = fsStat(path8);
|
|
78794
|
+
if (st.size >= MAX_INTROSPECTION_BYTES) {
|
|
78795
|
+
fsRename(path8, path8 + ".1");
|
|
78796
|
+
}
|
|
78797
|
+
} catch {
|
|
78798
|
+
}
|
|
78799
|
+
fsAppend(path8, line);
|
|
78800
|
+
} catch {
|
|
78801
|
+
}
|
|
78802
|
+
}
|
|
78803
|
+
|
|
78083
78804
|
// apps/cli/src/mcp-server-sdk.ts
|
|
78084
78805
|
init_dispatch_prompt_cache();
|
|
78085
78806
|
|
|
@@ -78120,6 +78841,7 @@ function discoverVerifier(agents, override) {
|
|
|
78120
78841
|
init_src4();
|
|
78121
78842
|
var import_node_fs = require("node:fs");
|
|
78122
78843
|
var import_node_path = require("node:path");
|
|
78844
|
+
init_orchestrator_precondition_runner();
|
|
78123
78845
|
function scheduleSkillRunner(c, mainAgent) {
|
|
78124
78846
|
if (!c.skillEngine) return;
|
|
78125
78847
|
const skillEngine = c.skillEngine;
|
|
@@ -78263,7 +78985,7 @@ Relay may be down. Check gossip_status() for connection state.` }] };
|
|
|
78263
78985
|
process.stderr.write(`[gossipcat] \u23F3 Consensus: ${doneCount}/${pendingNativeIds.length} agents complete (${agentStatus})
|
|
78264
78986
|
`);
|
|
78265
78987
|
}
|
|
78266
|
-
await new Promise((
|
|
78988
|
+
await new Promise((resolve33) => setTimeout(resolve33, POLL_INTERVAL));
|
|
78267
78989
|
}
|
|
78268
78990
|
const arrived = pendingNativeIds.filter((id) => ctx.nativeResultMap.has(id)).length;
|
|
78269
78991
|
const timedOutCount = pendingNativeIds.filter((id) => {
|
|
@@ -78645,6 +79367,7 @@ ${t.skillWarnings.map((w) => ` - ${w}`).join("\n")}`;
|
|
|
78645
79367
|
relayCrossReviewSkipped
|
|
78646
79368
|
);
|
|
78647
79369
|
} else {
|
|
79370
|
+
const roundStartSha = captureHeadSha(process.cwd());
|
|
78648
79371
|
ctx.pendingConsensusRounds.set(consensusId, {
|
|
78649
79372
|
consensusId,
|
|
78650
79373
|
allResults: allResults.filter((r) => r.status === "completed"),
|
|
@@ -78668,7 +79391,12 @@ ${t.skillWarnings.map((w) => ` - ${w}`).join("\n")}`;
|
|
|
78668
79391
|
// warnings + read its roots. The flat resolutionRoots above stays
|
|
78669
79392
|
// populated in parallel for old-reader back-compat. PR-C: this is
|
|
78670
79393
|
// always a concrete RoundContext (the engine now requires one).
|
|
78671
|
-
roundContext: effectiveRound
|
|
79394
|
+
roundContext: effectiveRound,
|
|
79395
|
+
// UNIT 3: capture HEAD SHA at Phase 2 start for mid_flight_fixup detection.
|
|
79396
|
+
// Best-effort — undefined when git is unavailable (never blocks the round).
|
|
79397
|
+
// FIX 2: hoisted out of the set() literal so execFileSync does not block
|
|
79398
|
+
// the MCP handler inline inside the Map mutation.
|
|
79399
|
+
roundStartSha
|
|
78672
79400
|
});
|
|
78673
79401
|
const recentTaskIds = [
|
|
78674
79402
|
...allResults.filter((r) => r.status === "completed").map((r) => r.id)
|
|
@@ -78855,7 +79583,7 @@ ${np.user}
|
|
|
78855
79583
|
const autoResolveEnabled = cfgPathAr?.consensus?.autoResolveOnRoundClose !== false;
|
|
78856
79584
|
if (autoResolveEnabled) {
|
|
78857
79585
|
const { resolveFindings: rf } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
78858
|
-
const resolveResult = await rf(process.cwd(), { lineAnchored: cfgPathAr?.consensus?.resolverLineAnchored ??
|
|
79586
|
+
const resolveResult = await rf(process.cwd(), { lineAnchored: cfgPathAr?.consensus?.resolverLineAnchored ?? true });
|
|
78859
79587
|
if (resolveResult.ok) {
|
|
78860
79588
|
if (resolveResult.resolved > 0) {
|
|
78861
79589
|
process.stderr.write(
|
|
@@ -79158,19 +79886,19 @@ function filterWatchEvents(rawJsonl, opts) {
|
|
|
79158
79886
|
}
|
|
79159
79887
|
|
|
79160
79888
|
// apps/cli/src/stickyPort.ts
|
|
79161
|
-
var
|
|
79162
|
-
var
|
|
79889
|
+
var import_fs84 = require("fs");
|
|
79890
|
+
var import_path90 = require("path");
|
|
79163
79891
|
var import_net = require("net");
|
|
79164
|
-
var RELAY_STICKY_FILE = (0,
|
|
79165
|
-
var HTTP_MCP_STICKY_FILE = (0,
|
|
79892
|
+
var RELAY_STICKY_FILE = (0, import_path90.join)(".gossip", "relay.port");
|
|
79893
|
+
var HTTP_MCP_STICKY_FILE = (0, import_path90.join)(".gossip", "http-mcp.port");
|
|
79166
79894
|
function stickyPath(filename) {
|
|
79167
|
-
return (0,
|
|
79895
|
+
return (0, import_path90.join)(process.cwd(), filename);
|
|
79168
79896
|
}
|
|
79169
79897
|
function readStickyPort(filename) {
|
|
79170
79898
|
const p = stickyPath(filename);
|
|
79171
|
-
if (!(0,
|
|
79899
|
+
if (!(0, import_fs84.existsSync)(p)) return null;
|
|
79172
79900
|
try {
|
|
79173
|
-
const raw = (0,
|
|
79901
|
+
const raw = (0, import_fs84.readFileSync)(p, "utf-8").trim();
|
|
79174
79902
|
const n = parseInt(raw, 10);
|
|
79175
79903
|
if (!Number.isFinite(n) || n < 1 || n > 65535) return null;
|
|
79176
79904
|
return n;
|
|
@@ -79182,13 +79910,13 @@ function writeStickyPort(filename, port) {
|
|
|
79182
79910
|
if (!Number.isFinite(port) || port < 1 || port > 65535) return;
|
|
79183
79911
|
const p = stickyPath(filename);
|
|
79184
79912
|
try {
|
|
79185
|
-
(0,
|
|
79186
|
-
(0,
|
|
79913
|
+
(0, import_fs84.mkdirSync)((0, import_path90.dirname)(p), { recursive: true });
|
|
79914
|
+
(0, import_fs84.writeFileSync)(p, String(port), "utf-8");
|
|
79187
79915
|
} catch {
|
|
79188
79916
|
}
|
|
79189
79917
|
}
|
|
79190
79918
|
function probePort(port, host = "127.0.0.1") {
|
|
79191
|
-
return new Promise((
|
|
79919
|
+
return new Promise((resolve33) => {
|
|
79192
79920
|
const srv = (0, import_net.createServer)();
|
|
79193
79921
|
let settled = false;
|
|
79194
79922
|
const done = (ok) => {
|
|
@@ -79198,7 +79926,7 @@ function probePort(port, host = "127.0.0.1") {
|
|
|
79198
79926
|
srv.close();
|
|
79199
79927
|
} catch {
|
|
79200
79928
|
}
|
|
79201
|
-
|
|
79929
|
+
resolve33(ok);
|
|
79202
79930
|
};
|
|
79203
79931
|
srv.once("error", () => done(false));
|
|
79204
79932
|
try {
|
|
@@ -79256,20 +79984,20 @@ function mergeSetupConfig(input) {
|
|
|
79256
79984
|
function buildMalformedConfigHint(configPath, message) {
|
|
79257
79985
|
return `\u26A0\uFE0F config.json is malformed: ${message} \u2014 fix or delete ${configPath}`;
|
|
79258
79986
|
}
|
|
79259
|
-
function flushStagedAgentFileWrites(writes,
|
|
79987
|
+
function flushStagedAgentFileWrites(writes, fs7) {
|
|
79260
79988
|
for (const w of writes) {
|
|
79261
|
-
|
|
79262
|
-
|
|
79989
|
+
fs7.mkdirSync(w.dir, { recursive: true });
|
|
79990
|
+
fs7.writeFileSync(w.path, w.content, "utf-8");
|
|
79263
79991
|
}
|
|
79264
79992
|
}
|
|
79265
79993
|
|
|
79266
79994
|
// apps/cli/src/native-agent-cache.ts
|
|
79267
|
-
var
|
|
79268
|
-
var
|
|
79995
|
+
var import_fs85 = require("fs");
|
|
79996
|
+
var import_path91 = require("path");
|
|
79269
79997
|
var realFs = {
|
|
79270
|
-
existsSync:
|
|
79271
|
-
readFileSync:
|
|
79272
|
-
statSync: (p) => ({ mtimeMs: (0,
|
|
79998
|
+
existsSync: import_fs85.existsSync,
|
|
79999
|
+
readFileSync: import_fs85.readFileSync,
|
|
80000
|
+
statSync: (p) => ({ mtimeMs: (0, import_fs85.statSync)(p).mtimeMs })
|
|
79273
80001
|
};
|
|
79274
80002
|
function modelTierFromId(modelId) {
|
|
79275
80003
|
if (modelId.includes("opus")) return "opus";
|
|
@@ -79277,16 +80005,16 @@ function modelTierFromId(modelId) {
|
|
|
79277
80005
|
if (modelId.includes("fable")) return "fable";
|
|
79278
80006
|
return "sonnet";
|
|
79279
80007
|
}
|
|
79280
|
-
function refreshNativeAgentFromDisk(ac, cache3, projectRoot,
|
|
79281
|
-
const claudeAgentPath = (0,
|
|
79282
|
-
const instrPath = (0,
|
|
80008
|
+
function refreshNativeAgentFromDisk(ac, cache3, projectRoot, fs7 = realFs) {
|
|
80009
|
+
const claudeAgentPath = (0, import_path91.join)(projectRoot, ".claude", "agents", `${ac.id}.md`);
|
|
80010
|
+
const instrPath = (0, import_path91.join)(projectRoot, ".gossip", "agents", ac.id, "instructions.md");
|
|
79283
80011
|
const prev = cache3.get(ac.id);
|
|
79284
80012
|
let sourcePath = null;
|
|
79285
80013
|
let stripFrontmatter = false;
|
|
79286
|
-
if (
|
|
80014
|
+
if (fs7.existsSync(claudeAgentPath)) {
|
|
79287
80015
|
sourcePath = claudeAgentPath;
|
|
79288
80016
|
stripFrontmatter = true;
|
|
79289
|
-
} else if (
|
|
80017
|
+
} else if (fs7.existsSync(instrPath)) {
|
|
79290
80018
|
sourcePath = instrPath;
|
|
79291
80019
|
stripFrontmatter = false;
|
|
79292
80020
|
}
|
|
@@ -79305,7 +80033,7 @@ function refreshNativeAgentFromDisk(ac, cache3, projectRoot, fs6 = realFs) {
|
|
|
79305
80033
|
}
|
|
79306
80034
|
let currentMtimeMs;
|
|
79307
80035
|
try {
|
|
79308
|
-
currentMtimeMs =
|
|
80036
|
+
currentMtimeMs = fs7.statSync(sourcePath).mtimeMs;
|
|
79309
80037
|
} catch {
|
|
79310
80038
|
if (prev && prev.instructions.length > 0) {
|
|
79311
80039
|
return;
|
|
@@ -79321,7 +80049,7 @@ function refreshNativeAgentFromDisk(ac, cache3, projectRoot, fs6 = realFs) {
|
|
|
79321
80049
|
if (prev && prev.cachedMtimeMs === currentMtimeMs) {
|
|
79322
80050
|
return;
|
|
79323
80051
|
}
|
|
79324
|
-
let instructions =
|
|
80052
|
+
let instructions = fs7.readFileSync(sourcePath, "utf-8");
|
|
79325
80053
|
if (stripFrontmatter) {
|
|
79326
80054
|
instructions = instructions.replace(/^---\n[\s\S]*?\n---\n*/, "").trim();
|
|
79327
80055
|
}
|
|
@@ -79338,22 +80066,22 @@ function refreshNativeAgentFromDisk(ac, cache3, projectRoot, fs6 = realFs) {
|
|
|
79338
80066
|
}
|
|
79339
80067
|
|
|
79340
80068
|
// apps/cli/src/rules-content.ts
|
|
79341
|
-
var
|
|
79342
|
-
var
|
|
80069
|
+
var import_fs86 = require("fs");
|
|
80070
|
+
var import_path92 = require("path");
|
|
79343
80071
|
var AGENT_LIST_PLACEHOLDER = "{{AGENT_LIST}}";
|
|
79344
80072
|
function resolveRulesPath(host = detectNativeHost()) {
|
|
79345
80073
|
const fileName = host === "cursor" ? "CURSOR_RULES.md" : "RULES.md";
|
|
79346
80074
|
const candidates = [
|
|
79347
|
-
(0,
|
|
79348
|
-
(0,
|
|
79349
|
-
(0,
|
|
80075
|
+
(0, import_path92.join)(process.cwd(), "docs", fileName),
|
|
80076
|
+
(0, import_path92.join)(__dirname, "..", "docs", fileName),
|
|
80077
|
+
(0, import_path92.join)(__dirname, "docs", fileName),
|
|
79350
80078
|
// Fallback: bundled RULES.md when CURSOR_RULES.md not yet shipped
|
|
79351
80079
|
...host === "cursor" ? [
|
|
79352
|
-
(0,
|
|
79353
|
-
(0,
|
|
80080
|
+
(0, import_path92.join)(process.cwd(), "docs", "RULES.md"),
|
|
80081
|
+
(0, import_path92.join)(__dirname, "..", "docs", "RULES.md")
|
|
79354
80082
|
] : []
|
|
79355
80083
|
];
|
|
79356
|
-
return candidates.find((p) => (0,
|
|
80084
|
+
return candidates.find((p) => (0, import_fs86.existsSync)(p)) ?? null;
|
|
79357
80085
|
}
|
|
79358
80086
|
function generateRulesContent(agentList, host) {
|
|
79359
80087
|
const resolvedHost = host ?? detectNativeHost();
|
|
@@ -79363,7 +80091,7 @@ function generateRulesContent(agentList, host) {
|
|
|
79363
80091
|
`[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
80092
|
);
|
|
79365
80093
|
}
|
|
79366
|
-
let template = (0,
|
|
80094
|
+
let template = (0, import_fs86.readFileSync)(rulesPath, "utf-8");
|
|
79367
80095
|
if (resolvedHost === "cursor" && rulesPath.endsWith("RULES.md")) {
|
|
79368
80096
|
template = template.replace(/Agent\(\)/g, "Task()").replace(/Agent\(/g, "Task(").replace(/Claude Code/g, "Cursor");
|
|
79369
80097
|
}
|
|
@@ -79463,7 +80191,7 @@ var __argvShimHandled = (() => {
|
|
|
79463
80191
|
}
|
|
79464
80192
|
if (kind === "help") {
|
|
79465
80193
|
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"
|
|
80194
|
+
"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
80195
|
);
|
|
79468
80196
|
process.exit(0);
|
|
79469
80197
|
}
|
|
@@ -79511,15 +80239,15 @@ var __argvShimHandled = (() => {
|
|
|
79511
80239
|
function readSecretFromStdin() {
|
|
79512
80240
|
const stdin = process.stdin;
|
|
79513
80241
|
if (!stdin.isTTY) {
|
|
79514
|
-
return new Promise((
|
|
80242
|
+
return new Promise((resolve33, reject) => {
|
|
79515
80243
|
const chunks = [];
|
|
79516
80244
|
stdin.on("data", (c) => chunks.push(c));
|
|
79517
|
-
stdin.on("end", () =>
|
|
80245
|
+
stdin.on("end", () => resolve33(Buffer.concat(chunks).toString("utf8")));
|
|
79518
80246
|
stdin.on("error", (e) => reject(e));
|
|
79519
80247
|
stdin.resume();
|
|
79520
80248
|
});
|
|
79521
80249
|
}
|
|
79522
|
-
return new Promise((
|
|
80250
|
+
return new Promise((resolve33) => {
|
|
79523
80251
|
process.stderr.write("Paste the API key, then Enter: ");
|
|
79524
80252
|
let buf = "";
|
|
79525
80253
|
const wasRaw = stdin.isRaw === true;
|
|
@@ -79534,7 +80262,7 @@ function readSecretFromStdin() {
|
|
|
79534
80262
|
stdin.pause();
|
|
79535
80263
|
stdin.removeListener("data", onData);
|
|
79536
80264
|
process.stderr.write("\n");
|
|
79537
|
-
|
|
80265
|
+
resolve33(buf);
|
|
79538
80266
|
return;
|
|
79539
80267
|
} else if (code === 3) {
|
|
79540
80268
|
stdin.setRawMode(wasRaw);
|
|
@@ -79553,12 +80281,12 @@ function readSecretFromStdin() {
|
|
|
79553
80281
|
});
|
|
79554
80282
|
}
|
|
79555
80283
|
if (process.env.GOSSIPCAT_MCP_NO_MAIN !== "1" && !__argvShimHandled) {
|
|
79556
|
-
const gossipDir = (0,
|
|
80284
|
+
const gossipDir = (0, import_path97.join)(process.cwd(), ".gossip");
|
|
79557
80285
|
try {
|
|
79558
|
-
(0,
|
|
80286
|
+
(0, import_fs91.mkdirSync)(gossipDir, { recursive: true });
|
|
79559
80287
|
} catch {
|
|
79560
80288
|
}
|
|
79561
|
-
const logStream = (0,
|
|
80289
|
+
const logStream = (0, import_fs91.createWriteStream)((0, import_path97.join)(gossipDir, "mcp.log"), { flags: "a", mode: 384 });
|
|
79562
80290
|
process.stderr.write = ((chunk, ...args) => {
|
|
79563
80291
|
return logStream.write(chunk, ...args);
|
|
79564
80292
|
});
|
|
@@ -79569,7 +80297,7 @@ try {
|
|
|
79569
80297
|
} catch {
|
|
79570
80298
|
}
|
|
79571
80299
|
function memoryDirForProject(cwd) {
|
|
79572
|
-
return (0,
|
|
80300
|
+
return (0, import_path97.join)((0, import_os8.homedir)(), ".claude", "projects", cwd.replaceAll("/", "-"), "memory");
|
|
79573
80301
|
}
|
|
79574
80302
|
function dashboardClickableUrl(url2, key) {
|
|
79575
80303
|
if (!key) return url2;
|
|
@@ -79644,14 +80372,14 @@ var _pendingPlanData = /* @__PURE__ */ new Map();
|
|
|
79644
80372
|
var _utilityGuardSnapshots = /* @__PURE__ */ new Map();
|
|
79645
80373
|
var _modules = null;
|
|
79646
80374
|
function lookupFindingSeverity(findingId, projectRoot) {
|
|
79647
|
-
const { existsSync:
|
|
79648
|
-
const { join:
|
|
79649
|
-
const reportsDir =
|
|
79650
|
-
if (!
|
|
80375
|
+
const { existsSync: existsSync74, readdirSync: readdirSync22, readFileSync: readFileSync70 } = require("fs");
|
|
80376
|
+
const { join: join93 } = require("path");
|
|
80377
|
+
const reportsDir = join93(projectRoot, ".gossip", "consensus-reports");
|
|
80378
|
+
if (!existsSync74(reportsDir)) return null;
|
|
79651
80379
|
try {
|
|
79652
80380
|
const files = readdirSync22(reportsDir).filter((f) => f.endsWith(".json"));
|
|
79653
80381
|
for (const file2 of files) {
|
|
79654
|
-
const report = JSON.parse(
|
|
80382
|
+
const report = JSON.parse(readFileSync70(join93(reportsDir, file2), "utf-8"));
|
|
79655
80383
|
for (const bucket of ["confirmed", "disputed", "unverified", "unique"]) {
|
|
79656
80384
|
for (const finding of report[bucket] || []) {
|
|
79657
80385
|
if (finding.id === findingId && finding.severity) {
|
|
@@ -79750,7 +80478,7 @@ async function doBoot() {
|
|
|
79750
80478
|
const agentConfigs = m.configToAgentConfigs(config2);
|
|
79751
80479
|
ctx.keychain = new m.Keychain();
|
|
79752
80480
|
const { existsSync: pidExists, readFileSync: readPid, writeFileSync: writePid, unlinkSync: delPid } = require("fs");
|
|
79753
|
-
const pidFile = (0,
|
|
80481
|
+
const pidFile = (0, import_path97.join)(process.cwd(), ".gossip", "relay.pid");
|
|
79754
80482
|
if (pidExists(pidFile)) {
|
|
79755
80483
|
const oldPid = parseInt(readPid(pidFile, "utf-8").trim(), 10);
|
|
79756
80484
|
if (!isNaN(oldPid) && oldPid !== process.pid) {
|
|
@@ -79872,10 +80600,10 @@ async function doBoot() {
|
|
|
79872
80600
|
{ id: ac.id, provider: ac.provider, model: ac.model, base_url: ac.base_url, key_ref: ac.key_ref },
|
|
79873
80601
|
(s) => ctx.keychain.getKey(s)
|
|
79874
80602
|
);
|
|
79875
|
-
const { existsSync:
|
|
79876
|
-
const { join:
|
|
79877
|
-
const instructionsPath =
|
|
79878
|
-
const baseInstructions =
|
|
80603
|
+
const { existsSync: existsSync74, readFileSync: readFileSync70 } = require("fs");
|
|
80604
|
+
const { join: join93 } = require("path");
|
|
80605
|
+
const instructionsPath = join93(process.cwd(), ".gossip", "agents", ac.id, "instructions.md");
|
|
80606
|
+
const baseInstructions = existsSync74(instructionsPath) ? readFileSync70(instructionsPath, "utf-8") : "";
|
|
79879
80607
|
const identity = ctx.identityRegistry.get(ac.id);
|
|
79880
80608
|
const identityBlock = identity ? m.formatIdentityBlock(identity) + "\n" : "";
|
|
79881
80609
|
const instructions = (identityBlock + baseInstructions).trim() || void 0;
|
|
@@ -80804,6 +81532,70 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
80804
81532
|
};
|
|
80805
81533
|
}
|
|
80806
81534
|
);
|
|
81535
|
+
server.tool(
|
|
81536
|
+
"gossip_ask_back",
|
|
81537
|
+
`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.`,
|
|
81538
|
+
{
|
|
81539
|
+
action: external_exports.enum(["ask", "record"]).default("ask").describe(`"ask" (default): dispatch an introspection prompt to the agent. "record": store the agent's answer.`),
|
|
81540
|
+
agent_id: external_exports.string().describe("The agent that produced the fabrication."),
|
|
81541
|
+
claim: external_exports.string().optional().describe('Required for action:"ask". The fabricated claim the agent made.'),
|
|
81542
|
+
ground_truth: external_exports.string().optional().describe('Required for action:"ask". What the code/evidence actually shows.'),
|
|
81543
|
+
finding_id: external_exports.string().optional().describe("Optional consensus finding_id (format: <consensus_id>:<agent:fN>) to link the introspection to a specific finding."),
|
|
81544
|
+
answer: external_exports.string().optional().describe(`Required for action:"record". The agent's root-cause explanation.`)
|
|
81545
|
+
},
|
|
81546
|
+
async ({ action, agent_id, claim, ground_truth, finding_id, answer }) => {
|
|
81547
|
+
const projectRoot = process.cwd();
|
|
81548
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
81549
|
+
if (action === "ask") {
|
|
81550
|
+
if (!claim || !ground_truth) {
|
|
81551
|
+
return {
|
|
81552
|
+
content: [{ type: "text", text: 'gossip_ask_back error: action:"ask" requires both claim and ground_truth.' }],
|
|
81553
|
+
isError: true
|
|
81554
|
+
};
|
|
81555
|
+
}
|
|
81556
|
+
appendIntrospection(projectRoot, {
|
|
81557
|
+
agentId: agent_id,
|
|
81558
|
+
findingId: finding_id,
|
|
81559
|
+
claim,
|
|
81560
|
+
groundTruth: ground_truth,
|
|
81561
|
+
status: "asked",
|
|
81562
|
+
askedAt: now
|
|
81563
|
+
});
|
|
81564
|
+
const prompt = buildIntrospectionPrompt(claim, ground_truth);
|
|
81565
|
+
const dispatchResult = await handleDispatchSingle(agent_id, prompt);
|
|
81566
|
+
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.
|
|
81567
|
+
|
|
81568
|
+
`;
|
|
81569
|
+
const dispatchText = dispatchResult.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
81570
|
+
return {
|
|
81571
|
+
content: [{ type: "text", text: instruction + dispatchText }]
|
|
81572
|
+
};
|
|
81573
|
+
}
|
|
81574
|
+
if (!answer) {
|
|
81575
|
+
return {
|
|
81576
|
+
content: [{ type: "text", text: 'gossip_ask_back error: action:"record" requires answer.' }],
|
|
81577
|
+
isError: true
|
|
81578
|
+
};
|
|
81579
|
+
}
|
|
81580
|
+
appendIntrospection(projectRoot, {
|
|
81581
|
+
agentId: agent_id,
|
|
81582
|
+
findingId: finding_id,
|
|
81583
|
+
claim: claim ?? "",
|
|
81584
|
+
groundTruth: ground_truth ?? "",
|
|
81585
|
+
answer,
|
|
81586
|
+
status: "answered",
|
|
81587
|
+
answeredAt: now
|
|
81588
|
+
});
|
|
81589
|
+
const ledgerPath2 = `${projectRoot}/.gossip/fabrication-introspections.jsonl`;
|
|
81590
|
+
return {
|
|
81591
|
+
content: [{
|
|
81592
|
+
type: "text",
|
|
81593
|
+
text: `Introspection recorded for ${agent_id}${finding_id ? ` (finding: ${finding_id})` : ""}.
|
|
81594
|
+
Ledger: ${ledgerPath2}`
|
|
81595
|
+
}]
|
|
81596
|
+
};
|
|
81597
|
+
}
|
|
81598
|
+
);
|
|
80807
81599
|
server.tool(
|
|
80808
81600
|
"gossip_status",
|
|
80809
81601
|
"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 +81653,7 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
80861
81653
|
}
|
|
80862
81654
|
try {
|
|
80863
81655
|
const { readFileSync: rfHealth } = await import("fs");
|
|
80864
|
-
const healthPath = (0,
|
|
81656
|
+
const healthPath = (0, import_path97.join)(process.cwd(), ".gossip", "skill-runner-health.json");
|
|
80865
81657
|
const raw = rfHealth(healthPath, "utf8");
|
|
80866
81658
|
const h = JSON.parse(raw);
|
|
80867
81659
|
const lastMs = h.last_run_at ? new Date(h.last_run_at).getTime() : NaN;
|
|
@@ -80877,9 +81669,9 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
80877
81669
|
lines.push(" Skill graduation: never run since session start (expected after first gossip_collect)");
|
|
80878
81670
|
}
|
|
80879
81671
|
try {
|
|
80880
|
-
const { readFileSync:
|
|
80881
|
-
const quotaPath = (0,
|
|
80882
|
-
const quotaRaw =
|
|
81672
|
+
const { readFileSync: readFileSync70 } = await import("fs");
|
|
81673
|
+
const quotaPath = (0, import_path97.join)(process.cwd(), ".gossip", "quota-state.json");
|
|
81674
|
+
const quotaRaw = readFileSync70(quotaPath, "utf8");
|
|
80883
81675
|
const quotaState = JSON.parse(quotaRaw);
|
|
80884
81676
|
for (const [provider, state] of Object.entries(quotaState)) {
|
|
80885
81677
|
const now = Date.now();
|
|
@@ -80931,7 +81723,7 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
80931
81723
|
}
|
|
80932
81724
|
try {
|
|
80933
81725
|
const { existsSync: hookExists } = await import("fs");
|
|
80934
|
-
const hookScriptPath = (0,
|
|
81726
|
+
const hookScriptPath = (0, import_path97.join)(process.cwd(), ".claude", "hooks", "worktree-sandbox.sh");
|
|
80935
81727
|
const { isWorktreeSandboxHookRegistered: isWorktreeSandboxHookRegistered2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
80936
81728
|
if (hookExists(hookScriptPath) && !isWorktreeSandboxHookRegistered2(process.cwd())) {
|
|
80937
81729
|
lines.push(" \u26A0\uFE0F Sandbox: worktree-sandbox hook installed but UNREGISTERED \u2014 run gossip_setup to re-register");
|
|
@@ -80939,21 +81731,21 @@ Note: write-mode classification unavailable on this native-only install \u2014 a
|
|
|
80939
81731
|
} catch {
|
|
80940
81732
|
}
|
|
80941
81733
|
try {
|
|
80942
|
-
const { readdirSync: readdirSync22, statSync: statSync36, readFileSync:
|
|
81734
|
+
const { readdirSync: readdirSync22, statSync: statSync36, readFileSync: readFileSync70 } = await import("fs");
|
|
80943
81735
|
const { readJsonlWithRotated: readJsonlRotated1506 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
80944
|
-
const reportsDir = (0,
|
|
80945
|
-
const perfPath = (0,
|
|
81736
|
+
const reportsDir = (0, import_path97.join)(process.cwd(), ".gossip", "consensus-reports");
|
|
81737
|
+
const perfPath = (0, import_path97.join)(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
80946
81738
|
const WINDOW_MS3 = 24 * 60 * 60 * 1e3;
|
|
80947
81739
|
const now = Date.now();
|
|
80948
81740
|
const recentReports = [];
|
|
80949
81741
|
try {
|
|
80950
81742
|
for (const fname of readdirSync22(reportsDir)) {
|
|
80951
81743
|
if (!fname.endsWith(".json")) continue;
|
|
80952
|
-
const fpath = (0,
|
|
81744
|
+
const fpath = (0, import_path97.join)(reportsDir, fname);
|
|
80953
81745
|
const st = statSync36(fpath);
|
|
80954
81746
|
if (now - st.mtimeMs > WINDOW_MS3) continue;
|
|
80955
81747
|
try {
|
|
80956
|
-
const report = JSON.parse(
|
|
81748
|
+
const report = JSON.parse(readFileSync70(fpath, "utf8"));
|
|
80957
81749
|
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
81750
|
if (isEmpty) continue;
|
|
80959
81751
|
} catch {
|
|
@@ -81327,8 +82119,8 @@ ${body}`
|
|
|
81327
82119
|
}
|
|
81328
82120
|
return { content: [{ type: "text", text: results.join("\n") }] };
|
|
81329
82121
|
}
|
|
81330
|
-
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45, existsSync:
|
|
81331
|
-
const { join:
|
|
82122
|
+
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45, existsSync: existsSync74 } = require("fs");
|
|
82123
|
+
const { join: join93 } = require("path");
|
|
81332
82124
|
const root = process.cwd();
|
|
81333
82125
|
const CLAUDE_MODEL_MAP2 = {
|
|
81334
82126
|
opus: { provider: "anthropic", model: "claude-opus-4-6" },
|
|
@@ -81344,8 +82136,8 @@ ${body}`
|
|
|
81344
82136
|
let existingConfig = {};
|
|
81345
82137
|
let existingAgents = {};
|
|
81346
82138
|
try {
|
|
81347
|
-
const { readFileSync:
|
|
81348
|
-
const existing = JSON.parse(
|
|
82139
|
+
const { readFileSync: readFileSync70 } = require("fs");
|
|
82140
|
+
const existing = JSON.parse(readFileSync70(join93(root, ".gossip", "config.json"), "utf-8"));
|
|
81349
82141
|
if (existing && typeof existing === "object" && !Array.isArray(existing)) {
|
|
81350
82142
|
existingConfig = existing;
|
|
81351
82143
|
if (mode === "merge") existingAgents = existing.agents || {};
|
|
@@ -81379,8 +82171,8 @@ ${body}`
|
|
|
81379
82171
|
body
|
|
81380
82172
|
].join("\n");
|
|
81381
82173
|
pendingAgentFileWrites.push({
|
|
81382
|
-
dir:
|
|
81383
|
-
path:
|
|
82174
|
+
dir: join93(root, ".claude", "agents"),
|
|
82175
|
+
path: join93(root, ".claude", "agents", `${agent.id}.md`),
|
|
81384
82176
|
content: md
|
|
81385
82177
|
});
|
|
81386
82178
|
nativeCreated.push(agent.id);
|
|
@@ -81401,8 +82193,8 @@ ${body}`
|
|
|
81401
82193
|
errors.push(`${agent.id}: custom agent requires "custom_model" field`);
|
|
81402
82194
|
continue;
|
|
81403
82195
|
}
|
|
81404
|
-
const nativeFile =
|
|
81405
|
-
const wasNative = existingAgents[agent.id]?.native || configAgents[agent.id]?.native ||
|
|
82196
|
+
const nativeFile = join93(root, ".claude", "agents", `${agent.id}.md`);
|
|
82197
|
+
const wasNative = existingAgents[agent.id]?.native || configAgents[agent.id]?.native || existsSync74(nativeFile);
|
|
81406
82198
|
if (wasNative) {
|
|
81407
82199
|
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
82200
|
continue;
|
|
@@ -81417,10 +82209,10 @@ ${body}`
|
|
|
81417
82209
|
};
|
|
81418
82210
|
customCreated.push(agent.id);
|
|
81419
82211
|
if (agent.instructions) {
|
|
81420
|
-
const instrDir =
|
|
82212
|
+
const instrDir = join93(root, ".gossip", "agents", agent.id);
|
|
81421
82213
|
pendingAgentFileWrites.push({
|
|
81422
82214
|
dir: instrDir,
|
|
81423
|
-
path:
|
|
82215
|
+
path: join93(instrDir, "instructions.md"),
|
|
81424
82216
|
content: agent.instructions
|
|
81425
82217
|
});
|
|
81426
82218
|
}
|
|
@@ -81439,8 +82231,8 @@ ${body}`
|
|
|
81439
82231
|
return { content: [{ type: "text", text: `Invalid config: ${err.message}` }] };
|
|
81440
82232
|
}
|
|
81441
82233
|
flushStagedAgentFileWrites(pendingAgentFileWrites, { mkdirSync: mkdirSync45, writeFileSync: writeFileSync38 });
|
|
81442
|
-
mkdirSync45(
|
|
81443
|
-
writeFileSync38(
|
|
82234
|
+
mkdirSync45(join93(root, ".gossip"), { recursive: true });
|
|
82235
|
+
writeFileSync38(join93(root, ".gossip", "config.json"), JSON.stringify(config2, null, 2));
|
|
81444
82236
|
let hookSummary = "";
|
|
81445
82237
|
try {
|
|
81446
82238
|
const { installWorktreeSandboxHook: installWorktreeSandboxHook2, writeOrchestratorRoleMarker: writeOrchestratorRoleMarker2 } = (init_src4(), __toCommonJS(src_exports3));
|
|
@@ -81543,8 +82335,8 @@ ${body}`
|
|
|
81543
82335
|
}
|
|
81544
82336
|
}
|
|
81545
82337
|
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 =
|
|
82338
|
+
const rulesDir = join93(root, env.rulesDir);
|
|
82339
|
+
const rulesFile = join93(root, env.rulesFile);
|
|
81548
82340
|
mkdirSync45(rulesDir, { recursive: true });
|
|
81549
82341
|
writeFileSync38(rulesFile, generateRulesContent(
|
|
81550
82342
|
agentList,
|
|
@@ -81853,11 +82645,11 @@ The original signal remains in the audit log but will be excluded from scoring.`
|
|
|
81853
82645
|
const fid = finding_id.trim();
|
|
81854
82646
|
const cwd = process.cwd();
|
|
81855
82647
|
const findingsPath = require("path").join(cwd, ".gossip", "implementation-findings.jsonl");
|
|
81856
|
-
const { readFileSync:
|
|
81857
|
-
if (!
|
|
82648
|
+
const { readFileSync: readFileSync70, existsSync: existsSync74, writeFileSync: writeFileSync38, renameSync: renameSync18 } = require("fs");
|
|
82649
|
+
if (!existsSync74(findingsPath)) {
|
|
81858
82650
|
return { content: [{ type: "text", text: `No implementation-findings.jsonl found at ${findingsPath}` }] };
|
|
81859
82651
|
}
|
|
81860
|
-
const lines =
|
|
82652
|
+
const lines = readFileSync70(findingsPath, "utf-8").split("\n");
|
|
81861
82653
|
let matched = false;
|
|
81862
82654
|
let alreadyTarget = false;
|
|
81863
82655
|
let matchedEntry = null;
|
|
@@ -81945,18 +82737,18 @@ The original signal remains in the audit log but will be excluded from scoring.`
|
|
|
81945
82737
|
return { content: [{ type: "text", text: "Error: consensus_id is required for bulk_from_consensus." }] };
|
|
81946
82738
|
}
|
|
81947
82739
|
try {
|
|
81948
|
-
const { readFileSync:
|
|
81949
|
-
const { join:
|
|
81950
|
-
const reportPath =
|
|
82740
|
+
const { readFileSync: readFileSync70 } = await import("fs");
|
|
82741
|
+
const { join: join93 } = await import("path");
|
|
82742
|
+
const reportPath = join93(process.cwd(), ".gossip", "consensus-reports", `${consensus_id}.json`);
|
|
81951
82743
|
let report;
|
|
81952
82744
|
try {
|
|
81953
|
-
report = JSON.parse(
|
|
82745
|
+
report = JSON.parse(readFileSync70(reportPath, "utf-8"));
|
|
81954
82746
|
} catch {
|
|
81955
82747
|
return { content: [{ type: "text", text: `Error: consensus report not found: ${consensus_id}` }] };
|
|
81956
82748
|
}
|
|
81957
82749
|
const existingFindingIds = /* @__PURE__ */ new Set();
|
|
81958
82750
|
try {
|
|
81959
|
-
const perfPath =
|
|
82751
|
+
const perfPath = join93(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
81960
82752
|
const { readJsonlWithRotated: readJsonlRotated2570 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
81961
82753
|
const lines = readJsonlRotated2570(perfPath).split("\n").filter(Boolean);
|
|
81962
82754
|
for (const line of lines) {
|
|
@@ -82571,7 +83363,7 @@ These will influence future agent selection via dispatch weighting.`;
|
|
|
82571
83363
|
return null;
|
|
82572
83364
|
}
|
|
82573
83365
|
})();
|
|
82574
|
-
const result = await resolveFindings2(process.cwd(), { full, sinceSha, lineAnchored: cfg?.consensus?.resolverLineAnchored ??
|
|
83366
|
+
const result = await resolveFindings2(process.cwd(), { full, sinceSha, lineAnchored: cfg?.consensus?.resolverLineAnchored ?? true });
|
|
82575
83367
|
if (!result.ok) {
|
|
82576
83368
|
return { content: [{ type: "text", text: `Resolver skipped: ${result.reason} (another resolver run in progress; try again in a moment).` }] };
|
|
82577
83369
|
}
|
|
@@ -82591,7 +83383,7 @@ These will influence future agent selection via dispatch weighting.`;
|
|
|
82591
83383
|
if (nonZeroSkips.length > 0) {
|
|
82592
83384
|
lines.push(` skipped: ${nonZeroSkips.map(([k, n]) => `${k}=${n}`).join(", ")}`);
|
|
82593
83385
|
if ((result.skipReasons?.lineAnchoredOff ?? 0) > 0) {
|
|
82594
|
-
lines.push(` (lineAnchoredOff:
|
|
83386
|
+
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
83387
|
}
|
|
82596
83388
|
}
|
|
82597
83389
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
@@ -83004,16 +83796,16 @@ ${preview}` }]
|
|
|
83004
83796
|
const { SkillGapTracker: SkillGapTracker2, parseSkillFrontmatter: parseSkillFrontmatter2, normalizeSkillName: normalizeSkillName2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
83005
83797
|
const tracker = new SkillGapTracker2(process.cwd());
|
|
83006
83798
|
if (skills && skills.length > 0) {
|
|
83007
|
-
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45, existsSync:
|
|
83008
|
-
const { join:
|
|
83009
|
-
const dir =
|
|
83799
|
+
const { writeFileSync: writeFileSync38, mkdirSync: mkdirSync45, existsSync: existsSync74, readFileSync: readFileSync70 } = require("fs");
|
|
83800
|
+
const { join: join93 } = require("path");
|
|
83801
|
+
const dir = join93(process.cwd(), ".gossip", "skills");
|
|
83010
83802
|
mkdirSync45(dir, { recursive: true });
|
|
83011
83803
|
const results = [];
|
|
83012
83804
|
for (const sk of skills) {
|
|
83013
83805
|
const name = normalizeSkillName2(sk.name);
|
|
83014
|
-
const filePath =
|
|
83015
|
-
if (
|
|
83016
|
-
const existing =
|
|
83806
|
+
const filePath = join93(dir, `${name}.md`);
|
|
83807
|
+
if (existsSync74(filePath)) {
|
|
83808
|
+
const existing = readFileSync70(filePath, "utf-8");
|
|
83017
83809
|
const fm = parseSkillFrontmatter2(existing);
|
|
83018
83810
|
if (fm) {
|
|
83019
83811
|
if (fm.generated_by === "manual") {
|
|
@@ -83737,7 +84529,8 @@ Paste this entire block into any Agent() prompt that should produce parseable fi
|
|
|
83737
84529
|
{ 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
84530
|
{ name: "gossip_reload", desc: "Terminate MCP server so Claude Code respawns with fresh bundle. Use after npm run build:mcp." },
|
|
83739
84531
|
{ 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." }
|
|
84532
|
+
{ name: "gossip_bug_feedback", desc: "File a GitHub issue on the gossipcat repo from an in-session bug report. Dedupes against open issues." },
|
|
84533
|
+
{ 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
84534
|
];
|
|
83742
84535
|
const list = tools.map((t) => `- ${t.name}: ${t.desc}`).join("\n");
|
|
83743
84536
|
return { content: [{ type: "text", text: `Gossipcat Tools (${tools.length}):
|
|
@@ -83853,9 +84646,9 @@ ${p.user}
|
|
|
83853
84646
|
max_events: external_exports.number().int().positive().max(WATCH_MAX_EVENTS).optional().describe(`Cap events returned (default ${WATCH_MAX_EVENTS}).`)
|
|
83854
84647
|
},
|
|
83855
84648
|
async ({ cursor, max_events }) => {
|
|
83856
|
-
const { join:
|
|
84649
|
+
const { join: join93 } = await import("node:path");
|
|
83857
84650
|
const { readJsonlWithRotated: readJsonlWithRotated2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
83858
|
-
const perfPath =
|
|
84651
|
+
const perfPath = join93(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
83859
84652
|
const raw = readJsonlWithRotated2(perfPath);
|
|
83860
84653
|
const result = filterWatchEvents(raw, { cursor, maxEvents: max_events });
|
|
83861
84654
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
@@ -84002,10 +84795,10 @@ async function startHttpMcpTransport() {
|
|
|
84002
84795
|
}
|
|
84003
84796
|
let body;
|
|
84004
84797
|
if (req.method === "POST") {
|
|
84005
|
-
const raw = await new Promise((
|
|
84798
|
+
const raw = await new Promise((resolve33, reject) => {
|
|
84006
84799
|
const chunks = [];
|
|
84007
84800
|
req.on("data", (c) => chunks.push(c));
|
|
84008
|
-
req.on("end", () =>
|
|
84801
|
+
req.on("end", () => resolve33(Buffer.concat(chunks).toString("utf-8")));
|
|
84009
84802
|
req.on("error", reject);
|
|
84010
84803
|
});
|
|
84011
84804
|
try {
|