nexus-agents 8.96.0 → 8.97.0
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/dist/{chunk-CSNLW5ZS.js → chunk-6I6JETP7.js} +2 -2
- package/dist/{chunk-5VW2Z25X.js → chunk-7TXK4ZU3.js} +2 -2
- package/dist/{chunk-4LHLEHIS.js → chunk-AVGO46BN.js} +4 -3
- package/dist/{chunk-KQJHYWF5.js → chunk-GUEUV3ND.js} +268 -134
- package/dist/chunk-GUEUV3ND.js.map +1 -0
- package/dist/{chunk-GWVSAAW4.js → chunk-IR25EHPP.js} +2 -2
- package/dist/{chunk-WFFE7JSD.js → chunk-LFGVIWQ7.js} +3 -3
- package/dist/cli.js +7 -7
- package/dist/{consensus-vote-BBLGVUVU.js → consensus-vote-44KYPBV4.js} +4 -4
- package/dist/{improvement-review-I6H7JWEF.js → improvement-review-7JZHY2EK.js} +4 -4
- package/dist/index.d.ts +40 -0
- package/dist/index.js +6 -6
- package/dist/{setup-data-dir-HUGQDEYI.js → setup-data-dir-RUJUERZQ.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-KQJHYWF5.js.map +0 -1
- /package/dist/{chunk-CSNLW5ZS.js.map → chunk-6I6JETP7.js.map} +0 -0
- /package/dist/{chunk-5VW2Z25X.js.map → chunk-7TXK4ZU3.js.map} +0 -0
- /package/dist/{chunk-4LHLEHIS.js.map → chunk-AVGO46BN.js.map} +0 -0
- /package/dist/{chunk-GWVSAAW4.js.map → chunk-IR25EHPP.js.map} +0 -0
- /package/dist/{chunk-WFFE7JSD.js.map → chunk-LFGVIWQ7.js.map} +0 -0
- /package/dist/{consensus-vote-BBLGVUVU.js.map → consensus-vote-44KYPBV4.js.map} +0 -0
- /package/dist/{improvement-review-I6H7JWEF.js.map → improvement-review-7JZHY2EK.js.map} +0 -0
- /package/dist/{setup-data-dir-HUGQDEYI.js.map → setup-data-dir-RUJUERZQ.js.map} +0 -0
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
import {
|
|
22
22
|
DEFAULT_TASK_TTL_MS,
|
|
23
23
|
clampTaskTtl
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-LFGVIWQ7.js";
|
|
25
25
|
import {
|
|
26
26
|
executeExpert
|
|
27
27
|
} from "./chunk-FUU6LXIA.js";
|
|
@@ -70,9 +70,10 @@ import {
|
|
|
70
70
|
simulationDeniedResult,
|
|
71
71
|
toJobSummary,
|
|
72
72
|
updateStage,
|
|
73
|
+
withFileLock,
|
|
73
74
|
withWarnings,
|
|
74
75
|
writeJobCancelled
|
|
75
|
-
} from "./chunk-
|
|
76
|
+
} from "./chunk-AVGO46BN.js";
|
|
76
77
|
import {
|
|
77
78
|
allOf,
|
|
78
79
|
anyOf
|
|
@@ -95,7 +96,7 @@ import {
|
|
|
95
96
|
} from "./chunk-CYP33W2C.js";
|
|
96
97
|
import {
|
|
97
98
|
withPrerequisite
|
|
98
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-7TXK4ZU3.js";
|
|
99
100
|
import {
|
|
100
101
|
NOOP_NOTIFIER,
|
|
101
102
|
RateLimiter,
|
|
@@ -123,10 +124,10 @@ import {
|
|
|
123
124
|
toolSuccessStructured,
|
|
124
125
|
withProgressHeartbeat,
|
|
125
126
|
wrapToolWithTimeout
|
|
126
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-IR25EHPP.js";
|
|
127
128
|
import {
|
|
128
129
|
VERSION
|
|
129
|
-
} from "./chunk-
|
|
130
|
+
} from "./chunk-6I6JETP7.js";
|
|
130
131
|
import {
|
|
131
132
|
EventTopics,
|
|
132
133
|
UNRESOLVED_MODEL_ID,
|
|
@@ -17404,7 +17405,7 @@ function wouldCreateCycle(from, to, getNode) {
|
|
|
17404
17405
|
return canReach(to, from, /* @__PURE__ */ new Set(), getNode);
|
|
17405
17406
|
}
|
|
17406
17407
|
function findCyclePath(from, to, getNode) {
|
|
17407
|
-
const
|
|
17408
|
+
const path12 = [from, to];
|
|
17408
17409
|
const visited = /* @__PURE__ */ new Set([from]);
|
|
17409
17410
|
const findPath = (current) => {
|
|
17410
17411
|
if (current === from) return true;
|
|
@@ -17413,9 +17414,9 @@ function findCyclePath(from, to, getNode) {
|
|
|
17413
17414
|
for (const depId of node.dependencies.keys()) {
|
|
17414
17415
|
if (!visited.has(depId)) {
|
|
17415
17416
|
visited.add(depId);
|
|
17416
|
-
|
|
17417
|
+
path12.push(depId);
|
|
17417
17418
|
if (findPath(depId)) return true;
|
|
17418
|
-
|
|
17419
|
+
path12.pop();
|
|
17419
17420
|
} else if (depId === from) {
|
|
17420
17421
|
return true;
|
|
17421
17422
|
}
|
|
@@ -17423,7 +17424,7 @@ function findCyclePath(from, to, getNode) {
|
|
|
17423
17424
|
return false;
|
|
17424
17425
|
};
|
|
17425
17426
|
findPath(to);
|
|
17426
|
-
return
|
|
17427
|
+
return path12;
|
|
17427
17428
|
}
|
|
17428
17429
|
function detectCycleDFS(nodeId, visited, stack, getNode) {
|
|
17429
17430
|
visited.add(nodeId);
|
|
@@ -17442,29 +17443,29 @@ function detectCycleDFS(nodeId, visited, stack, getNode) {
|
|
|
17442
17443
|
return false;
|
|
17443
17444
|
}
|
|
17444
17445
|
function findCycleFromNode(startId, getNode) {
|
|
17445
|
-
const
|
|
17446
|
+
const path12 = [];
|
|
17446
17447
|
const visited = /* @__PURE__ */ new Set();
|
|
17447
17448
|
const dfs = (nodeId) => {
|
|
17448
|
-
if (
|
|
17449
|
-
const cycleStart =
|
|
17450
|
-
|
|
17451
|
-
|
|
17449
|
+
if (path12.includes(nodeId)) {
|
|
17450
|
+
const cycleStart = path12.indexOf(nodeId);
|
|
17451
|
+
path12.splice(0, cycleStart);
|
|
17452
|
+
path12.push(nodeId);
|
|
17452
17453
|
return true;
|
|
17453
17454
|
}
|
|
17454
17455
|
if (visited.has(nodeId)) return false;
|
|
17455
17456
|
visited.add(nodeId);
|
|
17456
|
-
|
|
17457
|
+
path12.push(nodeId);
|
|
17457
17458
|
const node = getNode(nodeId);
|
|
17458
17459
|
if (node) {
|
|
17459
17460
|
for (const depId of node.dependencies.keys()) {
|
|
17460
17461
|
if (dfs(depId)) return true;
|
|
17461
17462
|
}
|
|
17462
17463
|
}
|
|
17463
|
-
|
|
17464
|
+
path12.pop();
|
|
17464
17465
|
return false;
|
|
17465
17466
|
};
|
|
17466
17467
|
dfs(startId);
|
|
17467
|
-
return
|
|
17468
|
+
return path12;
|
|
17468
17469
|
}
|
|
17469
17470
|
|
|
17470
17471
|
// src/agents/skills/skill-dependency-graph.ts
|
|
@@ -22447,18 +22448,18 @@ var DependencyGraph = class {
|
|
|
22447
22448
|
}
|
|
22448
22449
|
const startNode = firstNode;
|
|
22449
22450
|
const visited = /* @__PURE__ */ new Set();
|
|
22450
|
-
const
|
|
22451
|
+
const path12 = [];
|
|
22451
22452
|
const dfs = (nodeId) => {
|
|
22452
|
-
if (
|
|
22453
|
-
const cycleStart =
|
|
22454
|
-
|
|
22453
|
+
if (path12.includes(nodeId)) {
|
|
22454
|
+
const cycleStart = path12.indexOf(nodeId);
|
|
22455
|
+
path12.splice(0, cycleStart);
|
|
22455
22456
|
return true;
|
|
22456
22457
|
}
|
|
22457
22458
|
if (visited.has(nodeId)) {
|
|
22458
22459
|
return false;
|
|
22459
22460
|
}
|
|
22460
22461
|
visited.add(nodeId);
|
|
22461
|
-
|
|
22462
|
+
path12.push(nodeId);
|
|
22462
22463
|
const node = this.nodes.get(nodeId);
|
|
22463
22464
|
if (node) {
|
|
22464
22465
|
for (const depId of node.dependencies) {
|
|
@@ -22469,11 +22470,11 @@ var DependencyGraph = class {
|
|
|
22469
22470
|
}
|
|
22470
22471
|
}
|
|
22471
22472
|
}
|
|
22472
|
-
|
|
22473
|
+
path12.pop();
|
|
22473
22474
|
return false;
|
|
22474
22475
|
};
|
|
22475
22476
|
dfs(startNode);
|
|
22476
|
-
return
|
|
22477
|
+
return path12.length > 0 ? path12 : cycleNodes.slice(0, 3);
|
|
22477
22478
|
}
|
|
22478
22479
|
/**
|
|
22479
22480
|
* Gets the execution order (topologically sorted step IDs).
|
|
@@ -23328,9 +23329,9 @@ function getBuiltInTemplatesPath() {
|
|
|
23328
23329
|
join3(dirname(currentDir), "workflows", "templates"),
|
|
23329
23330
|
join3(dirname(currentDir), "dist", "workflows", "templates")
|
|
23330
23331
|
];
|
|
23331
|
-
for (const
|
|
23332
|
-
if (existsSync3(
|
|
23333
|
-
return
|
|
23332
|
+
for (const path12 of possiblePaths) {
|
|
23333
|
+
if (existsSync3(path12)) {
|
|
23334
|
+
return path12;
|
|
23334
23335
|
}
|
|
23335
23336
|
}
|
|
23336
23337
|
return join3(currentDir, "templates");
|
|
@@ -23871,9 +23872,9 @@ function validateRequiredInputs(inputs, required) {
|
|
|
23871
23872
|
}
|
|
23872
23873
|
|
|
23873
23874
|
// src/workflows/expression-resolver-helpers.ts
|
|
23874
|
-
function getNestedValue(obj,
|
|
23875
|
+
function getNestedValue(obj, path12) {
|
|
23875
23876
|
let current = obj;
|
|
23876
|
-
for (const key of
|
|
23877
|
+
for (const key of path12) {
|
|
23877
23878
|
if (current === null || current === void 0) {
|
|
23878
23879
|
return void 0;
|
|
23879
23880
|
}
|
|
@@ -23884,24 +23885,24 @@ function getNestedValue(obj, path11) {
|
|
|
23884
23885
|
}
|
|
23885
23886
|
return current;
|
|
23886
23887
|
}
|
|
23887
|
-
function resolveInputs(
|
|
23888
|
-
const value = getNestedValue(context.inputs,
|
|
23888
|
+
function resolveInputs(path12, context) {
|
|
23889
|
+
const value = getNestedValue(context.inputs, path12);
|
|
23889
23890
|
if (value === void 0) {
|
|
23890
23891
|
return {
|
|
23891
23892
|
success: false,
|
|
23892
|
-
error: `Input '${
|
|
23893
|
+
error: `Input '${path12.join(".")}' not found`
|
|
23893
23894
|
};
|
|
23894
23895
|
}
|
|
23895
23896
|
return { success: true, value };
|
|
23896
23897
|
}
|
|
23897
|
-
function validateStepPath(
|
|
23898
|
-
if (
|
|
23898
|
+
function validateStepPath(path12) {
|
|
23899
|
+
if (path12.length < 2) {
|
|
23899
23900
|
return {
|
|
23900
23901
|
success: false,
|
|
23901
23902
|
error: "Steps expression requires at least stepId and output"
|
|
23902
23903
|
};
|
|
23903
23904
|
}
|
|
23904
|
-
if (
|
|
23905
|
+
if (path12[0] === void 0 || path12[1] === void 0) {
|
|
23905
23906
|
return {
|
|
23906
23907
|
success: false,
|
|
23907
23908
|
error: "Steps expression requires stepId and output"
|
|
@@ -23927,12 +23928,12 @@ function validateStepResult(stepId, outputKey, stepResult) {
|
|
|
23927
23928
|
}
|
|
23928
23929
|
return null;
|
|
23929
23930
|
}
|
|
23930
|
-
function resolveSteps(
|
|
23931
|
-
const pathError = validateStepPath(
|
|
23931
|
+
function resolveSteps(path12, context) {
|
|
23932
|
+
const pathError = validateStepPath(path12);
|
|
23932
23933
|
if (pathError !== null) return pathError;
|
|
23933
|
-
const stepId =
|
|
23934
|
-
const outputKey =
|
|
23935
|
-
const rest =
|
|
23934
|
+
const stepId = path12[0] ?? "";
|
|
23935
|
+
const outputKey = path12[1] ?? "";
|
|
23936
|
+
const rest = path12.slice(2);
|
|
23936
23937
|
const stepResult = context.stepResults.get(stepId);
|
|
23937
23938
|
const earlyReturn = validateStepResult(stepId, outputKey, stepResult);
|
|
23938
23939
|
if (earlyReturn !== null) return earlyReturn;
|
|
@@ -23948,15 +23949,15 @@ function resolveSteps(path11, context) {
|
|
|
23948
23949
|
}
|
|
23949
23950
|
return { success: true, value };
|
|
23950
23951
|
}
|
|
23951
|
-
function resolveVariables(
|
|
23952
|
-
if (
|
|
23952
|
+
function resolveVariables(path12, context) {
|
|
23953
|
+
if (path12.length === 0) {
|
|
23953
23954
|
return {
|
|
23954
23955
|
success: false,
|
|
23955
23956
|
error: "Variables expression requires a variable name"
|
|
23956
23957
|
};
|
|
23957
23958
|
}
|
|
23958
|
-
const varName =
|
|
23959
|
-
const rest =
|
|
23959
|
+
const varName = path12[0];
|
|
23960
|
+
const rest = path12.slice(1);
|
|
23960
23961
|
if (varName === void 0) {
|
|
23961
23962
|
return {
|
|
23962
23963
|
success: false,
|
|
@@ -25000,8 +25001,8 @@ var WorkflowEngine = class {
|
|
|
25000
25001
|
this.config = resolveConfig2(config);
|
|
25001
25002
|
}
|
|
25002
25003
|
/** Load workflow template from file. */
|
|
25003
|
-
async loadTemplate(
|
|
25004
|
-
return this.deps.loadWorkflowFile(
|
|
25004
|
+
async loadTemplate(path12) {
|
|
25005
|
+
return this.deps.loadWorkflowFile(path12);
|
|
25005
25006
|
}
|
|
25006
25007
|
/**
|
|
25007
25008
|
* Execute a workflow with inputs.
|
|
@@ -25130,8 +25131,8 @@ var WorkflowEngine = class {
|
|
|
25130
25131
|
}
|
|
25131
25132
|
return Promise.resolve(templates);
|
|
25132
25133
|
}
|
|
25133
|
-
createTemplate(workflow,
|
|
25134
|
-
const t = { name: workflow.name, version: workflow.version, path:
|
|
25134
|
+
createTemplate(workflow, path12, category) {
|
|
25135
|
+
const t = { name: workflow.name, version: workflow.version, path: path12, category };
|
|
25135
25136
|
if (workflow.description !== void 0) t.description = workflow.description;
|
|
25136
25137
|
return t;
|
|
25137
25138
|
}
|
|
@@ -25438,8 +25439,8 @@ function createParseWorkflow() {
|
|
|
25438
25439
|
};
|
|
25439
25440
|
}
|
|
25440
25441
|
function createLoadWorkflowFile() {
|
|
25441
|
-
return async (
|
|
25442
|
-
const result = await loadWorkflowFile(
|
|
25442
|
+
return async (path12) => {
|
|
25443
|
+
const result = await loadWorkflowFile(path12);
|
|
25443
25444
|
if (!result.ok) {
|
|
25444
25445
|
if (result.error instanceof ParseError) {
|
|
25445
25446
|
return result;
|
|
@@ -31016,31 +31017,31 @@ var GraphBuilder = class {
|
|
|
31016
31017
|
}
|
|
31017
31018
|
const visited = /* @__PURE__ */ new Set();
|
|
31018
31019
|
const stack = /* @__PURE__ */ new Set();
|
|
31019
|
-
const
|
|
31020
|
+
const path12 = [];
|
|
31020
31021
|
for (const nodeId of this.nodes.keys()) {
|
|
31021
|
-
const cycle = this.dfs(nodeId, adj, visited, stack,
|
|
31022
|
+
const cycle = this.dfs(nodeId, adj, visited, stack, path12);
|
|
31022
31023
|
if (cycle !== void 0) return cycle;
|
|
31023
31024
|
}
|
|
31024
31025
|
return void 0;
|
|
31025
31026
|
}
|
|
31026
|
-
dfs(nodeId, adj, visited, stack,
|
|
31027
|
+
dfs(nodeId, adj, visited, stack, path12) {
|
|
31027
31028
|
if (stack.has(nodeId)) {
|
|
31028
|
-
const cycleStart =
|
|
31029
|
-
const cyclePath =
|
|
31029
|
+
const cycleStart = path12.indexOf(nodeId);
|
|
31030
|
+
const cyclePath = path12.slice(cycleStart);
|
|
31030
31031
|
cyclePath.push(nodeId);
|
|
31031
31032
|
return { type: "cycle_detected", path: cyclePath };
|
|
31032
31033
|
}
|
|
31033
31034
|
if (visited.has(nodeId)) return void 0;
|
|
31034
31035
|
visited.add(nodeId);
|
|
31035
31036
|
stack.add(nodeId);
|
|
31036
|
-
|
|
31037
|
+
path12.push(nodeId);
|
|
31037
31038
|
const neighbors = adj.get(nodeId) ?? [];
|
|
31038
31039
|
for (const neighbor of neighbors) {
|
|
31039
|
-
const cycle = this.dfs(neighbor, adj, visited, stack,
|
|
31040
|
+
const cycle = this.dfs(neighbor, adj, visited, stack, path12);
|
|
31040
31041
|
if (cycle !== void 0) return cycle;
|
|
31041
31042
|
}
|
|
31042
31043
|
stack.delete(nodeId);
|
|
31043
|
-
|
|
31044
|
+
path12.pop();
|
|
31044
31045
|
return void 0;
|
|
31045
31046
|
}
|
|
31046
31047
|
checkReachability() {
|
|
@@ -32008,8 +32009,8 @@ function extractModelAttribution(event) {
|
|
|
32008
32009
|
};
|
|
32009
32010
|
}
|
|
32010
32011
|
function extractRoutingAttribution(event) {
|
|
32011
|
-
const
|
|
32012
|
-
return { modelId: event.selectedModel, reasoning: event.reasoning, decisionPath:
|
|
32012
|
+
const path12 = event.decisionPath !== void 0 ? [...event.decisionPath] : void 0;
|
|
32013
|
+
return { modelId: event.selectedModel, reasoning: event.reasoning, decisionPath: path12 };
|
|
32013
32014
|
}
|
|
32014
32015
|
function extractPipelineAttribution(event) {
|
|
32015
32016
|
if (event.type === "pipeline.completed") {
|
|
@@ -41761,12 +41762,12 @@ function extractFileReferences(markdown) {
|
|
|
41761
41762
|
let match;
|
|
41762
41763
|
FILE_REF_PATTERN.lastIndex = 0;
|
|
41763
41764
|
while ((match = FILE_REF_PATTERN.exec(markdown)) !== null) {
|
|
41764
|
-
const
|
|
41765
|
-
if (
|
|
41766
|
-
seen.add(
|
|
41765
|
+
const path12 = match[1];
|
|
41766
|
+
if (path12 === void 0 || seen.has(path12)) continue;
|
|
41767
|
+
seen.add(path12);
|
|
41767
41768
|
const lineStr = match[2];
|
|
41768
41769
|
const line = lineStr !== void 0 ? parseInt(lineStr, 10) : void 0;
|
|
41769
|
-
refs.push(line !== void 0 ? { path:
|
|
41770
|
+
refs.push(line !== void 0 ? { path: path12, line } : { path: path12 });
|
|
41770
41771
|
}
|
|
41771
41772
|
return refs;
|
|
41772
41773
|
}
|
|
@@ -44509,11 +44510,54 @@ var InMemoryAuditStorage = class {
|
|
|
44509
44510
|
// src/audit/audit-storage.ts
|
|
44510
44511
|
import * as fs5 from "node:fs";
|
|
44511
44512
|
import * as os from "node:os";
|
|
44513
|
+
import * as path4 from "node:path";
|
|
44514
|
+
|
|
44515
|
+
// src/audit/audit-chain-tail.ts
|
|
44516
|
+
import { open } from "node:fs/promises";
|
|
44512
44517
|
import * as path3 from "node:path";
|
|
44518
|
+
var TAIL_CHUNK_BYTES = 64 * 1024;
|
|
44519
|
+
async function lastEventIn(filePath) {
|
|
44520
|
+
const handle = await open(filePath, "r");
|
|
44521
|
+
try {
|
|
44522
|
+
const { size } = await handle.stat();
|
|
44523
|
+
for (let window = TAIL_CHUNK_BYTES; ; window *= 2) {
|
|
44524
|
+
const start = Math.max(0, size - window);
|
|
44525
|
+
const buffer = Buffer.alloc(size - start);
|
|
44526
|
+
await handle.read(buffer, 0, buffer.length, start);
|
|
44527
|
+
const lines = buffer.toString("utf-8").split("\n");
|
|
44528
|
+
const whole = start === 0 ? lines : lines.slice(1);
|
|
44529
|
+
for (let i = whole.length - 1; i >= 0; i--) {
|
|
44530
|
+
const event = parseEvent(whole[i] ?? "");
|
|
44531
|
+
if (event !== null) return event;
|
|
44532
|
+
}
|
|
44533
|
+
if (start === 0) return null;
|
|
44534
|
+
}
|
|
44535
|
+
} finally {
|
|
44536
|
+
await handle.close();
|
|
44537
|
+
}
|
|
44538
|
+
}
|
|
44539
|
+
function parseEvent(line) {
|
|
44540
|
+
if (line.trim().length === 0) return null;
|
|
44541
|
+
try {
|
|
44542
|
+
const parsed = AuditEventSchema.safeParse(JSON.parse(line));
|
|
44543
|
+
return parsed.success ? { hash: parsed.data.hash } : null;
|
|
44544
|
+
} catch {
|
|
44545
|
+
return null;
|
|
44546
|
+
}
|
|
44547
|
+
}
|
|
44548
|
+
async function readChainTailHash(logDir, fileNamesNewestFirst) {
|
|
44549
|
+
for (const name of fileNamesNewestFirst) {
|
|
44550
|
+
const last = await lastEventIn(path3.join(logDir, name));
|
|
44551
|
+
if (last !== null) return last.hash;
|
|
44552
|
+
}
|
|
44553
|
+
return void 0;
|
|
44554
|
+
}
|
|
44555
|
+
|
|
44556
|
+
// src/audit/audit-storage.ts
|
|
44513
44557
|
function validateLogDir(logDir, allowedRoot) {
|
|
44514
|
-
const resolvedRoot =
|
|
44515
|
-
const resolvedLogDir =
|
|
44516
|
-
if (!resolvedLogDir.startsWith(resolvedRoot +
|
|
44558
|
+
const resolvedRoot = path4.resolve(allowedRoot);
|
|
44559
|
+
const resolvedLogDir = path4.resolve(allowedRoot, logDir);
|
|
44560
|
+
if (!resolvedLogDir.startsWith(resolvedRoot + path4.sep) && resolvedLogDir !== resolvedRoot) {
|
|
44517
44561
|
return {
|
|
44518
44562
|
ok: false,
|
|
44519
44563
|
error: new SecurityError("Path traversal detected: logDir escapes allowed root directory", {
|
|
@@ -44536,8 +44580,8 @@ function validateLogDirBasic(logDir) {
|
|
|
44536
44580
|
};
|
|
44537
44581
|
}
|
|
44538
44582
|
}
|
|
44539
|
-
const resolved =
|
|
44540
|
-
if (isRefusedSystemPath(resolved,
|
|
44583
|
+
const resolved = path4.resolve(logDir);
|
|
44584
|
+
if (isRefusedSystemPath(resolved, path4.resolve(os.homedir()))) {
|
|
44541
44585
|
return {
|
|
44542
44586
|
ok: false,
|
|
44543
44587
|
error: new SecurityError("logDir cannot be a system directory", {
|
|
@@ -44550,12 +44594,12 @@ function validateLogDirBasic(logDir) {
|
|
|
44550
44594
|
var ALWAYS_REFUSED_DIRS = ["/etc", "/usr", "/bin", "/sbin", "/proc", "/sys"];
|
|
44551
44595
|
var REFUSED_OUTSIDE_HOME_DIRS = ["/root", "/var"];
|
|
44552
44596
|
function isWithin(child, parent) {
|
|
44553
|
-
const rel =
|
|
44554
|
-
return rel === "" || rel !== ".." && !rel.startsWith(".." +
|
|
44597
|
+
const rel = path4.relative(parent, child);
|
|
44598
|
+
return rel === "" || rel !== ".." && !rel.startsWith(".." + path4.sep) && !path4.isAbsolute(rel);
|
|
44555
44599
|
}
|
|
44556
44600
|
function isRefusedSystemPath(resolved, home) {
|
|
44557
44601
|
if (ALWAYS_REFUSED_DIRS.some((dir) => isWithin(resolved, dir))) return true;
|
|
44558
|
-
const homeGrants = home !==
|
|
44602
|
+
const homeGrants = home !== path4.parse(home).root && isWithin(resolved, home);
|
|
44559
44603
|
return REFUSED_OUTSIDE_HOME_DIRS.some((dir) => isWithin(resolved, dir)) && !homeGrants;
|
|
44560
44604
|
}
|
|
44561
44605
|
var FileAuditStorage = class _FileAuditStorage {
|
|
@@ -44636,7 +44680,7 @@ var FileAuditStorage = class _FileAuditStorage {
|
|
|
44636
44680
|
const existingFiles = this.getExistingLogFiles();
|
|
44637
44681
|
const latestFileName = existingFiles[0];
|
|
44638
44682
|
if (existingFiles.length > 0 && latestFileName !== void 0) {
|
|
44639
|
-
const latestFile =
|
|
44683
|
+
const latestFile = path4.join(this.logDir, latestFileName);
|
|
44640
44684
|
const stats = fs5.statSync(latestFile);
|
|
44641
44685
|
if (stats.size < this.maxFileSizeBytes) {
|
|
44642
44686
|
this.currentFile = latestFile;
|
|
@@ -44659,8 +44703,9 @@ var FileAuditStorage = class _FileAuditStorage {
|
|
|
44659
44703
|
this.writeStream.end();
|
|
44660
44704
|
this.writeStream = null;
|
|
44661
44705
|
}
|
|
44662
|
-
this.currentFile =
|
|
44706
|
+
this.currentFile = path4.join(this.logDir, this.generateFileName());
|
|
44663
44707
|
this.currentFileSize = 0;
|
|
44708
|
+
fs5.closeSync(fs5.openSync(this.currentFile, "a"));
|
|
44664
44709
|
this.openWriteStream();
|
|
44665
44710
|
this.logger.debug("Rotated audit log file", { file: this.currentFile });
|
|
44666
44711
|
this.pruneOldFiles();
|
|
@@ -44670,7 +44715,7 @@ var FileAuditStorage = class _FileAuditStorage {
|
|
|
44670
44715
|
if (files.length > this.maxFiles) {
|
|
44671
44716
|
const filesToDelete = files.slice(this.maxFiles);
|
|
44672
44717
|
for (const file of filesToDelete) {
|
|
44673
|
-
const filePath =
|
|
44718
|
+
const filePath = path4.join(this.logDir, file);
|
|
44674
44719
|
fs5.unlinkSync(filePath);
|
|
44675
44720
|
this.logger.info("Pruned old audit log", { file });
|
|
44676
44721
|
}
|
|
@@ -44702,6 +44747,60 @@ var FileAuditStorage = class _FileAuditStorage {
|
|
|
44702
44747
|
});
|
|
44703
44748
|
});
|
|
44704
44749
|
}
|
|
44750
|
+
/**
|
|
44751
|
+
* Append a chained batch under the cross-process lock (#6546). The tail
|
|
44752
|
+
* read, the seal and the flush to disk all happen while the lock is held,
|
|
44753
|
+
* so two processes can neither both chain from the same tail (a fork) nor
|
|
44754
|
+
* interleave lines between another process's read and write.
|
|
44755
|
+
*/
|
|
44756
|
+
async appendChained(seal) {
|
|
44757
|
+
await withFileLock(path4.join(this.logDir, `${this.filePrefix}.lock`), async () => {
|
|
44758
|
+
this.adoptLatestFile();
|
|
44759
|
+
this.terminateTornLine();
|
|
44760
|
+
const tailHash = await readChainTailHash(this.logDir, this.getExistingLogFiles());
|
|
44761
|
+
for (const event of seal(tailHash)) await this.write(event);
|
|
44762
|
+
await this.flush();
|
|
44763
|
+
});
|
|
44764
|
+
}
|
|
44765
|
+
/**
|
|
44766
|
+
* Under the append lock, follow whichever file is newest now: another
|
|
44767
|
+
* process may have rotated or appended since this one last wrote. Appending
|
|
44768
|
+
* to an older file would place this batch BEFORE events it chains after.
|
|
44769
|
+
*/
|
|
44770
|
+
adoptLatestFile() {
|
|
44771
|
+
const latest = this.getExistingLogFiles()[0];
|
|
44772
|
+
if (latest === void 0) {
|
|
44773
|
+
this.rotateFile();
|
|
44774
|
+
return;
|
|
44775
|
+
}
|
|
44776
|
+
const latestPath = path4.join(this.logDir, latest);
|
|
44777
|
+
if (latestPath !== this.currentFile) {
|
|
44778
|
+
this.writeStream?.end();
|
|
44779
|
+
this.writeStream = null;
|
|
44780
|
+
this.currentFile = latestPath;
|
|
44781
|
+
this.openWriteStream();
|
|
44782
|
+
}
|
|
44783
|
+
this.currentFileSize = fs5.statSync(latestPath).size;
|
|
44784
|
+
}
|
|
44785
|
+
/**
|
|
44786
|
+
* Under the append lock: if a writer crashed mid-line, end that line before
|
|
44787
|
+
* appending, or the next event would be glued onto it and lost with it. The
|
|
44788
|
+
* torn line itself is left in place — the verifier still counts it as
|
|
44789
|
+
* skipped — and the tail read links the new batch past it.
|
|
44790
|
+
*/
|
|
44791
|
+
terminateTornLine() {
|
|
44792
|
+
if (this.currentFile === null || this.currentFileSize === 0) return;
|
|
44793
|
+
const last = Buffer.alloc(1);
|
|
44794
|
+
const fd = fs5.openSync(this.currentFile, "r");
|
|
44795
|
+
try {
|
|
44796
|
+
fs5.readSync(fd, last, 0, 1, this.currentFileSize - 1);
|
|
44797
|
+
} finally {
|
|
44798
|
+
fs5.closeSync(fd);
|
|
44799
|
+
}
|
|
44800
|
+
if (last[0] === 10) return;
|
|
44801
|
+
fs5.appendFileSync(this.currentFile, "\n");
|
|
44802
|
+
this.currentFileSize += 1;
|
|
44803
|
+
}
|
|
44705
44804
|
async close() {
|
|
44706
44805
|
await this.flush();
|
|
44707
44806
|
return new Promise((resolve19) => {
|
|
@@ -44724,7 +44823,7 @@ var FileAuditStorage = class _FileAuditStorage {
|
|
|
44724
44823
|
let skipped = 0;
|
|
44725
44824
|
for (const file of files) {
|
|
44726
44825
|
if (results.length >= limit) break;
|
|
44727
|
-
const filePath =
|
|
44826
|
+
const filePath = path4.join(this.logDir, file);
|
|
44728
44827
|
const events = await readAuditFile({
|
|
44729
44828
|
filePath,
|
|
44730
44829
|
criteria,
|
|
@@ -44980,14 +45079,30 @@ var AuditLogger = class {
|
|
|
44980
45079
|
policyName: input.policyName,
|
|
44981
45080
|
policyDecision: input.policyDecision,
|
|
44982
45081
|
violationType: input.violationType,
|
|
44983
|
-
|
|
45082
|
+
// Linked at flush time by sealChain (#6546), not here.
|
|
45083
|
+
previousHash: void 0
|
|
44984
45084
|
};
|
|
44985
45085
|
if (hasTierTransitionPayload(event)) event.hashVersion = AUDIT_HASH_VERSION_TIER_TRANSITION;
|
|
44986
|
-
|
|
45086
|
+
return JSON.parse(JSON.stringify(event));
|
|
45087
|
+
}
|
|
45088
|
+
/**
|
|
45089
|
+
* Link `events` onto the chain whose head is `tailHash` (#6546).
|
|
45090
|
+
*
|
|
45091
|
+
* Runs at flush time, not at log() time: the head of a shared log is only
|
|
45092
|
+
* known under the storage's cross-process lock, after reading the last
|
|
45093
|
+
* persisted event. `tailHash` undefined is the empty case — a fresh log —
|
|
45094
|
+
* and the first event is then a genesis event with no `previousHash`.
|
|
45095
|
+
*/
|
|
45096
|
+
sealChain(events, tailHash) {
|
|
45097
|
+
if (!this.enableHashChain) return events;
|
|
45098
|
+
let prior = tailHash;
|
|
45099
|
+
for (const event of events) {
|
|
45100
|
+
event.previousHash = prior;
|
|
44987
45101
|
event.hash = computeEventHash(event);
|
|
44988
|
-
|
|
45102
|
+
prior = event.hash;
|
|
44989
45103
|
}
|
|
44990
|
-
|
|
45104
|
+
this.lastHash = prior ?? null;
|
|
45105
|
+
return events;
|
|
44991
45106
|
}
|
|
44992
45107
|
log(input) {
|
|
44993
45108
|
if (this.closed) {
|
|
@@ -44995,7 +45110,13 @@ var AuditLogger = class {
|
|
|
44995
45110
|
return;
|
|
44996
45111
|
}
|
|
44997
45112
|
if (!this.shouldLog(input)) return;
|
|
44998
|
-
|
|
45113
|
+
let event;
|
|
45114
|
+
try {
|
|
45115
|
+
event = this.createEvent(input);
|
|
45116
|
+
} catch (err2) {
|
|
45117
|
+
this.recordPersistFailure(err2);
|
|
45118
|
+
return;
|
|
45119
|
+
}
|
|
44999
45120
|
this.eventQueue.push(event);
|
|
45000
45121
|
if (this.eventQueue.length > this.maxQueueDepth) {
|
|
45001
45122
|
const dropCount = this.eventQueue.length - this.maxQueueDepth;
|
|
@@ -45196,7 +45317,20 @@ var AuditLogger = class {
|
|
|
45196
45317
|
async drainAndFlushOnce() {
|
|
45197
45318
|
if (this.eventQueue.length > 0) {
|
|
45198
45319
|
const events = this.eventQueue.splice(0, this.eventQueue.length);
|
|
45199
|
-
|
|
45320
|
+
if (this.storage.appendChained !== void 0) {
|
|
45321
|
+
const progress = { sealed: false };
|
|
45322
|
+
try {
|
|
45323
|
+
await this.storage.appendChained((tailHash) => {
|
|
45324
|
+
progress.sealed = true;
|
|
45325
|
+
return this.sealChain(events, tailHash);
|
|
45326
|
+
});
|
|
45327
|
+
} catch (err2) {
|
|
45328
|
+
if (!progress.sealed) this.eventQueue.unshift(...events);
|
|
45329
|
+
throw err2;
|
|
45330
|
+
}
|
|
45331
|
+
return;
|
|
45332
|
+
}
|
|
45333
|
+
for (const event of this.sealChain(events, this.lastHash ?? void 0)) {
|
|
45200
45334
|
await this.storage.write(event);
|
|
45201
45335
|
}
|
|
45202
45336
|
}
|
|
@@ -45535,8 +45669,8 @@ function computePrReviewRecordHash(payload) {
|
|
|
45535
45669
|
}
|
|
45536
45670
|
|
|
45537
45671
|
// src/audit/pr-review-record-store.ts
|
|
45538
|
-
import { appendFileSync as
|
|
45539
|
-
import { dirname as dirname3, isAbsolute as isAbsolute2, join as
|
|
45672
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync6 } from "node:fs";
|
|
45673
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join10, resolve as resolve11 } from "node:path";
|
|
45540
45674
|
var PR_REVIEW_RECORDS_REL_PATH = "governance/pr-review-records.jsonl";
|
|
45541
45675
|
var PR_REVIEW_RECORDS_PATH_ENV = "NEXUS_PR_REVIEW_RECORDS_PATH";
|
|
45542
45676
|
var MAX_SUMMARY_RECORD_CHARS = 500;
|
|
@@ -45575,11 +45709,11 @@ function resolvePrReviewRecordsPath(repoPathOverride) {
|
|
|
45575
45709
|
}
|
|
45576
45710
|
if (repoPathOverride !== void 0 && repoPathOverride.trim() !== "") {
|
|
45577
45711
|
const overrideRoot = findRepoRoot(repoPathOverride);
|
|
45578
|
-
if (overrideRoot !== null) return
|
|
45712
|
+
if (overrideRoot !== null) return join10(overrideRoot, PR_REVIEW_RECORDS_REL_PATH);
|
|
45579
45713
|
}
|
|
45580
45714
|
const root = findRepoRoot(process.cwd());
|
|
45581
45715
|
if (root === null) return void 0;
|
|
45582
|
-
return
|
|
45716
|
+
return join10(root, PR_REVIEW_RECORDS_REL_PATH);
|
|
45583
45717
|
}
|
|
45584
45718
|
function readPrReviewRecords(filePath) {
|
|
45585
45719
|
const records = [];
|
|
@@ -45631,7 +45765,7 @@ function persistPrReviewRecord(opts) {
|
|
|
45631
45765
|
sequence: maxSequence + 1,
|
|
45632
45766
|
previousHash: lastHash
|
|
45633
45767
|
});
|
|
45634
|
-
|
|
45768
|
+
appendFileSync3(
|
|
45635
45769
|
filePath,
|
|
45636
45770
|
serializeValidatedRecord(PrReviewRecordSchema, record, "pr-review"),
|
|
45637
45771
|
"utf-8"
|
|
@@ -46332,7 +46466,7 @@ function ensureRunnableTemplate(template, stages) {
|
|
|
46332
46466
|
|
|
46333
46467
|
// src/pipeline/pipeline-checkpoint.ts
|
|
46334
46468
|
import * as fs6 from "node:fs";
|
|
46335
|
-
import * as
|
|
46469
|
+
import * as path5 from "node:path";
|
|
46336
46470
|
import { z as z99 } from "zod";
|
|
46337
46471
|
var logger39 = createLogger({ component: "pipeline-checkpoint" });
|
|
46338
46472
|
var SESSION_ID_REGEX = /^[a-zA-Z0-9_-]{1,128}$/;
|
|
@@ -46345,7 +46479,7 @@ function getCheckpointPath(sessionId, customDir) {
|
|
|
46345
46479
|
logger39.warn("Checkpoint directory unavailable", { error: dirResult.error.message });
|
|
46346
46480
|
return null;
|
|
46347
46481
|
}
|
|
46348
|
-
return
|
|
46482
|
+
return path5.join(dirResult.value, `pipeline-${sessionId}.jsonl`);
|
|
46349
46483
|
}
|
|
46350
46484
|
function saveStageCheckpoint(sessionId, stage, data, customDir) {
|
|
46351
46485
|
if (!validateSessionId(sessionId)) {
|
|
@@ -46599,7 +46733,7 @@ function buildVotingInput(plan, config) {
|
|
|
46599
46733
|
}
|
|
46600
46734
|
async function executeSingleVote(plan, config, log) {
|
|
46601
46735
|
try {
|
|
46602
|
-
const { executeVoting } = await import("./consensus-vote-
|
|
46736
|
+
const { executeVoting } = await import("./consensus-vote-44KYPBV4.js");
|
|
46603
46737
|
const input = buildVotingInput(plan, config);
|
|
46604
46738
|
const result = await executeVoting(input, log);
|
|
46605
46739
|
return parseVotingResult(result);
|
|
@@ -47565,7 +47699,7 @@ function createVoteStage({ config, startStage }) {
|
|
|
47565
47699
|
const strategy = config.votingStrategy ?? "higher_order";
|
|
47566
47700
|
await postProgress(config, "Vote", `Running consensus with ${strategy} strategy...`);
|
|
47567
47701
|
try {
|
|
47568
|
-
const { executeVoting } = await import("./consensus-vote-
|
|
47702
|
+
const { executeVoting } = await import("./consensus-vote-44KYPBV4.js");
|
|
47569
47703
|
const votingResult = await executeVoting(
|
|
47570
47704
|
{
|
|
47571
47705
|
proposal: buildVoteProposal(plan, research),
|
|
@@ -47688,8 +47822,8 @@ function parseEnvelope(json) {
|
|
|
47688
47822
|
}
|
|
47689
47823
|
function describeZodError(error) {
|
|
47690
47824
|
return error.issues.slice(0, 3).map((issue) => {
|
|
47691
|
-
const
|
|
47692
|
-
return `${
|
|
47825
|
+
const path12 = issue.path.length > 0 ? issue.path.join(".") : "(root)";
|
|
47826
|
+
return `${path12}: ${issue.message}`;
|
|
47693
47827
|
}).join("; ");
|
|
47694
47828
|
}
|
|
47695
47829
|
function parseSarif(sarifJson, maxFindings = 100) {
|
|
@@ -47868,7 +48002,7 @@ function resolveConfidence(rule) {
|
|
|
47868
48002
|
}
|
|
47869
48003
|
|
|
47870
48004
|
// src/mcp/tools/security-scan.ts
|
|
47871
|
-
import * as
|
|
48005
|
+
import * as path6 from "node:path";
|
|
47872
48006
|
var logger46 = createLogger({ component: "security-scan" });
|
|
47873
48007
|
var SCAN_TIMEOUT_MS = 3e5;
|
|
47874
48008
|
async function isSemgrepAvailable() {
|
|
@@ -47895,9 +48029,9 @@ async function runSemgrep(targetDir, rulesets) {
|
|
|
47895
48029
|
return stdout;
|
|
47896
48030
|
}
|
|
47897
48031
|
function validateTargetPath(target) {
|
|
47898
|
-
const root =
|
|
47899
|
-
const resolved =
|
|
47900
|
-
if (resolved !== root && !resolved.startsWith(root +
|
|
48032
|
+
const root = path6.resolve(process.cwd());
|
|
48033
|
+
const resolved = path6.resolve(root, target);
|
|
48034
|
+
if (resolved !== root && !resolved.startsWith(root + path6.sep)) {
|
|
47901
48035
|
throw new Error(`Invalid target path: must resolve inside ${root} (got ${resolved})`);
|
|
47902
48036
|
}
|
|
47903
48037
|
return resolved;
|
|
@@ -48098,8 +48232,8 @@ async function runOsvCheck(targetDir, enabled) {
|
|
|
48098
48232
|
if (!enabled) return OSV_EMPTY;
|
|
48099
48233
|
try {
|
|
48100
48234
|
const fs12 = await import("node:fs");
|
|
48101
|
-
const
|
|
48102
|
-
const pkgPath =
|
|
48235
|
+
const path12 = await import("node:path");
|
|
48236
|
+
const pkgPath = path12.join(targetDir, "package.json");
|
|
48103
48237
|
if (!fs12.existsSync(pkgPath)) return OSV_EMPTY;
|
|
48104
48238
|
const pkg = JSON.parse(fs12.readFileSync(pkgPath, "utf-8"));
|
|
48105
48239
|
const declared = Object.keys(pkg.dependencies ?? {}).length;
|
|
@@ -48158,7 +48292,7 @@ function buildScanSummary(total, blocking, osvCount, osv, sarifParseErrors = 0)
|
|
|
48158
48292
|
|
|
48159
48293
|
// src/security/quality-gate-commands.ts
|
|
48160
48294
|
import { existsSync as existsSync9, readFileSync as readFileSync8 } from "node:fs";
|
|
48161
|
-
import { join as
|
|
48295
|
+
import { join as join12 } from "node:path";
|
|
48162
48296
|
var LOCKFILES = [
|
|
48163
48297
|
{ file: "pnpm-lock.yaml", manager: "pnpm" },
|
|
48164
48298
|
{ file: "yarn.lock", manager: "yarn" },
|
|
@@ -48173,12 +48307,12 @@ var SCRIPT_CANDIDATES = {
|
|
|
48173
48307
|
};
|
|
48174
48308
|
function detectPackageManager(projectDir) {
|
|
48175
48309
|
for (const { file, manager } of LOCKFILES) {
|
|
48176
|
-
if (existsSync9(
|
|
48310
|
+
if (existsSync9(join12(projectDir, file))) return manager;
|
|
48177
48311
|
}
|
|
48178
48312
|
return "npm";
|
|
48179
48313
|
}
|
|
48180
48314
|
function readScripts(projectDir) {
|
|
48181
|
-
const manifest =
|
|
48315
|
+
const manifest = join12(projectDir, "package.json");
|
|
48182
48316
|
if (!existsSync9(manifest)) return void 0;
|
|
48183
48317
|
try {
|
|
48184
48318
|
const parsed = JSON.parse(readFileSync8(manifest, "utf-8"));
|
|
@@ -49245,8 +49379,8 @@ var SENSITIVE_PATH_PATTERNS = Object.freeze([
|
|
|
49245
49379
|
"permission",
|
|
49246
49380
|
"sql"
|
|
49247
49381
|
]);
|
|
49248
|
-
function isSensitivePath(
|
|
49249
|
-
const lower =
|
|
49382
|
+
function isSensitivePath(path12) {
|
|
49383
|
+
const lower = path12.toLowerCase();
|
|
49250
49384
|
return SENSITIVE_PATH_PATTERNS.some((p) => lower.includes(p));
|
|
49251
49385
|
}
|
|
49252
49386
|
function byteLen(text) {
|
|
@@ -50391,7 +50525,7 @@ function registerVendorPublishingAuditTool(server, deps) {
|
|
|
50391
50525
|
|
|
50392
50526
|
// src/mcp/tools/compare-data-feeds.ts
|
|
50393
50527
|
import { z as z105 } from "zod";
|
|
50394
|
-
import * as
|
|
50528
|
+
import * as path7 from "node:path";
|
|
50395
50529
|
import * as fs7 from "node:fs";
|
|
50396
50530
|
import * as yaml4 from "yaml";
|
|
50397
50531
|
var CompareDataFeedsInputSchema = z105.object({
|
|
@@ -50415,7 +50549,7 @@ function readDottedPath(obj, dottedPath) {
|
|
|
50415
50549
|
return cursor;
|
|
50416
50550
|
}
|
|
50417
50551
|
function parseFeedContent(content, sourcePath) {
|
|
50418
|
-
const ext =
|
|
50552
|
+
const ext = path7.extname(sourcePath).toLowerCase();
|
|
50419
50553
|
if (ext === ".json") {
|
|
50420
50554
|
return JSON.parse(content);
|
|
50421
50555
|
}
|
|
@@ -50522,9 +50656,9 @@ function buildSummary(feedAPath, feedBPath, diff, fieldDiffs, fields) {
|
|
|
50522
50656
|
return lines.join("\n");
|
|
50523
50657
|
}
|
|
50524
50658
|
function loadFeed(feedPath) {
|
|
50525
|
-
const resolved =
|
|
50526
|
-
const cwdRoot =
|
|
50527
|
-
if (resolved !== cwdRoot && !resolved.startsWith(cwdRoot +
|
|
50659
|
+
const resolved = path7.resolve(feedPath);
|
|
50660
|
+
const cwdRoot = path7.resolve(".");
|
|
50661
|
+
if (resolved !== cwdRoot && !resolved.startsWith(cwdRoot + path7.sep)) {
|
|
50528
50662
|
throw new Error(`Path traversal denied: ${feedPath} must be within ${cwdRoot}`);
|
|
50529
50663
|
}
|
|
50530
50664
|
if (!fs7.existsSync(resolved)) {
|
|
@@ -50692,7 +50826,7 @@ function registerQueryTaskStateTool(server, deps) {
|
|
|
50692
50826
|
import { z as z109 } from "zod";
|
|
50693
50827
|
|
|
50694
50828
|
// src/mcp/tools/ci-health-log.ts
|
|
50695
|
-
import { appendFileSync as
|
|
50829
|
+
import { appendFileSync as appendFileSync5, existsSync as existsSync11, readFileSync as readFileSync10, statSync as statSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
50696
50830
|
import { z as z108 } from "zod";
|
|
50697
50831
|
|
|
50698
50832
|
// src/mcp/tools/ci-health-types.ts
|
|
@@ -50724,17 +50858,17 @@ function maxLogBytes() {
|
|
|
50724
50858
|
const n = Number.parseInt(raw, 10);
|
|
50725
50859
|
return Number.isFinite(n) && n > 0 ? n : DEFAULT_CI_HEALTH_MAX_BYTES;
|
|
50726
50860
|
}
|
|
50727
|
-
function capLogSize(
|
|
50861
|
+
function capLogSize(path12) {
|
|
50728
50862
|
const max = maxLogBytes();
|
|
50729
50863
|
let size;
|
|
50730
50864
|
try {
|
|
50731
|
-
size = statSync2(
|
|
50865
|
+
size = statSync2(path12).size;
|
|
50732
50866
|
} catch {
|
|
50733
50867
|
return;
|
|
50734
50868
|
}
|
|
50735
50869
|
if (size <= max) return;
|
|
50736
50870
|
try {
|
|
50737
|
-
const lines = readFileSync10(
|
|
50871
|
+
const lines = readFileSync10(path12, "utf-8").split("\n").filter((l) => l !== "");
|
|
50738
50872
|
const kept = [];
|
|
50739
50873
|
let bytes2 = 0;
|
|
50740
50874
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -50746,7 +50880,7 @@ function capLogSize(path11) {
|
|
|
50746
50880
|
bytes2 += lineBytes;
|
|
50747
50881
|
}
|
|
50748
50882
|
kept.reverse();
|
|
50749
|
-
writeFileSync3(
|
|
50883
|
+
writeFileSync3(path12, kept.length > 0 ? `${kept.join("\n")}
|
|
50750
50884
|
` : "");
|
|
50751
50885
|
logger51.warn("ci-health log exceeded size cap \u2014 dropped oldest events", {
|
|
50752
50886
|
maxBytes: max,
|
|
@@ -50767,10 +50901,10 @@ function appendCiHealthEvent(event) {
|
|
|
50767
50901
|
...event
|
|
50768
50902
|
};
|
|
50769
50903
|
try {
|
|
50770
|
-
const
|
|
50771
|
-
|
|
50904
|
+
const path12 = logFilePath();
|
|
50905
|
+
appendFileSync5(path12, `${JSON.stringify(record)}
|
|
50772
50906
|
`);
|
|
50773
|
-
capLogSize(
|
|
50907
|
+
capLogSize(path12);
|
|
50774
50908
|
} catch (err2) {
|
|
50775
50909
|
logger51.warn("Failed to append ci-health event", {
|
|
50776
50910
|
error: err2 instanceof Error ? err2.message : String(err2)
|
|
@@ -51079,7 +51213,7 @@ function registerRunQualityGateTool(server, deps) {
|
|
|
51079
51213
|
|
|
51080
51214
|
// src/mcp/tools/verify-audit-chain-tool.ts
|
|
51081
51215
|
import * as fs8 from "node:fs/promises";
|
|
51082
|
-
import * as
|
|
51216
|
+
import * as path8 from "node:path";
|
|
51083
51217
|
import { z as z111 } from "zod";
|
|
51084
51218
|
|
|
51085
51219
|
// src/cli-server-auth.ts
|
|
@@ -51295,7 +51429,7 @@ async function loadAuditEvents(dir, logger60, filePrefix = DEFAULT_AUDIT_FILE_PR
|
|
|
51295
51429
|
let skippedLines = 0;
|
|
51296
51430
|
let unreadableFiles = 0;
|
|
51297
51431
|
for (const filename of auditFiles) {
|
|
51298
|
-
const fullPath =
|
|
51432
|
+
const fullPath = path8.join(dir, filename);
|
|
51299
51433
|
let content;
|
|
51300
51434
|
try {
|
|
51301
51435
|
content = await fs8.readFile(fullPath, "utf-8");
|
|
@@ -51319,7 +51453,7 @@ async function handler2(args, ctx) {
|
|
|
51319
51453
|
message: `Validation error: ${formatZodError(parsed.error)}`
|
|
51320
51454
|
});
|
|
51321
51455
|
}
|
|
51322
|
-
const resolvedDir =
|
|
51456
|
+
const resolvedDir = path8.resolve(parsed.data.logDir);
|
|
51323
51457
|
let dirStats;
|
|
51324
51458
|
try {
|
|
51325
51459
|
dirStats = await fs8.stat(resolvedDir);
|
|
@@ -51975,7 +52109,7 @@ function createMetaOrchestrator(options) {
|
|
|
51975
52109
|
}
|
|
51976
52110
|
|
|
51977
52111
|
// src/orchestration/meta-shadow-selector.ts
|
|
51978
|
-
import { appendFileSync as
|
|
52112
|
+
import { appendFileSync as appendFileSync6, existsSync as existsSync12, readFileSync as readFileSync11 } from "node:fs";
|
|
51979
52113
|
import { z as z113 } from "zod";
|
|
51980
52114
|
var SHADOW_STRATEGY_ARMS = [
|
|
51981
52115
|
"single-shot",
|
|
@@ -52091,7 +52225,7 @@ function persistMetaOutcome(strategy, decision, success) {
|
|
|
52091
52225
|
};
|
|
52092
52226
|
try {
|
|
52093
52227
|
ensureLearningDir();
|
|
52094
|
-
|
|
52228
|
+
appendFileSync6(getMetaOutcomesFile(), JSON.stringify(record) + "\n", "utf-8");
|
|
52095
52229
|
} catch (err2) {
|
|
52096
52230
|
persistLogger.warn("Failed to persist meta-outcome (ignored)", {
|
|
52097
52231
|
error: getErrorMessage(err2)
|
|
@@ -52472,12 +52606,12 @@ function evaluateMetaStrategyReadiness(result, config = DEFAULT_META_STRATEGY_RE
|
|
|
52472
52606
|
// src/mcp/tools/dev-pipeline-tool.ts
|
|
52473
52607
|
import { z as z114 } from "zod";
|
|
52474
52608
|
import * as fs10 from "node:fs";
|
|
52475
|
-
import * as
|
|
52609
|
+
import * as path10 from "node:path";
|
|
52476
52610
|
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
52477
52611
|
|
|
52478
52612
|
// src/pipeline/task-tracker.ts
|
|
52479
52613
|
import * as fs9 from "node:fs";
|
|
52480
|
-
import * as
|
|
52614
|
+
import * as path9 from "node:path";
|
|
52481
52615
|
var logger52 = createLogger({ component: "task-tracker" });
|
|
52482
52616
|
async function exec(cmd, args, timeout = 15e3) {
|
|
52483
52617
|
const { execFile: execFile2 } = await import("node:child_process");
|
|
@@ -52557,8 +52691,8 @@ var JsonTaskTracker = class {
|
|
|
52557
52691
|
outputPath;
|
|
52558
52692
|
constructor(config) {
|
|
52559
52693
|
const dir = config.outputDir ?? nexusDataPath("pipeline");
|
|
52560
|
-
this.outputPath =
|
|
52561
|
-
fs9.mkdirSync(
|
|
52694
|
+
this.outputPath = path9.resolve(dir, "tasks.json");
|
|
52695
|
+
fs9.mkdirSync(path9.dirname(this.outputPath), { recursive: true });
|
|
52562
52696
|
}
|
|
52563
52697
|
async createTask(title, body) {
|
|
52564
52698
|
const id = String(this.nextId++);
|
|
@@ -52710,9 +52844,9 @@ async function resolveTaskInput(input) {
|
|
|
52710
52844
|
return input.task;
|
|
52711
52845
|
}
|
|
52712
52846
|
if (input.planFile !== void 0) {
|
|
52713
|
-
const resolved =
|
|
52714
|
-
const cwdRoot =
|
|
52715
|
-
if (resolved !== cwdRoot && !resolved.startsWith(cwdRoot +
|
|
52847
|
+
const resolved = path10.resolve(input.planFile);
|
|
52848
|
+
const cwdRoot = path10.resolve(".");
|
|
52849
|
+
if (resolved !== cwdRoot && !resolved.startsWith(cwdRoot + path10.sep)) {
|
|
52716
52850
|
throw new Error(`Path traversal denied: planFile must be within ${cwdRoot}`);
|
|
52717
52851
|
}
|
|
52718
52852
|
try {
|
|
@@ -52943,7 +53077,7 @@ function registerDevPipelineTool(server, deps) {
|
|
|
52943
53077
|
// src/mcp/tools/pipeline-tool.ts
|
|
52944
53078
|
import { z as z115 } from "zod";
|
|
52945
53079
|
import * as fs11 from "node:fs";
|
|
52946
|
-
import * as
|
|
53080
|
+
import * as path11 from "node:path";
|
|
52947
53081
|
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
52948
53082
|
var PIPELINE_ASYNC_HINT = "A full run_pipeline run can exceed the synchronous MCP request timeout. Retry with `dispatch: 'async'` to get a jobId immediately, then poll get_job_result({ jobId }) for the result.";
|
|
52949
53083
|
var PipelineInputSchema = z115.object({
|
|
@@ -53006,9 +53140,9 @@ function buildOutput3(result, simulated) {
|
|
|
53006
53140
|
}
|
|
53007
53141
|
async function resolveTask(task, specFile) {
|
|
53008
53142
|
if (specFile === void 0) return task;
|
|
53009
|
-
const resolved =
|
|
53010
|
-
const cwdRoot =
|
|
53011
|
-
if (resolved !== cwdRoot && !resolved.startsWith(cwdRoot +
|
|
53143
|
+
const resolved = path11.resolve(specFile);
|
|
53144
|
+
const cwdRoot = path11.resolve(".");
|
|
53145
|
+
if (resolved !== cwdRoot && !resolved.startsWith(cwdRoot + path11.sep)) {
|
|
53012
53146
|
throw new Error(`Path traversal denied: specFile must be within ${cwdRoot}`);
|
|
53013
53147
|
}
|
|
53014
53148
|
try {
|
|
@@ -56798,4 +56932,4 @@ export {
|
|
|
56798
56932
|
startPipelineEventBridge,
|
|
56799
56933
|
shutdownPipelineEventBridge
|
|
56800
56934
|
};
|
|
56801
|
-
//# sourceMappingURL=chunk-
|
|
56935
|
+
//# sourceMappingURL=chunk-GUEUV3ND.js.map
|