nexus-agents 11.3.0 → 11.4.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-WDAND5YU.js → chunk-BDP422B2.js} +4 -2
- package/dist/{chunk-WDAND5YU.js.map → chunk-BDP422B2.js.map} +1 -1
- package/dist/{chunk-QOJPTGQI.js → chunk-C4ZXUDDS.js} +2 -2
- package/dist/{chunk-PIBIAVWQ.js → chunk-CVHLQFUX.js} +3 -3
- package/dist/{chunk-ZZ2BEXLC.js → chunk-HF36DB2G.js} +3 -3
- package/dist/{chunk-A7XDON63.js → chunk-HHOSB6LL.js} +1258 -622
- package/dist/chunk-HHOSB6LL.js.map +1 -0
- package/dist/{chunk-3OQBXYFS.js → chunk-JEESPQIQ.js} +2 -2
- package/dist/{chunk-KS7CAJAC.js → chunk-JYZLBQ7M.js} +2 -2
- package/dist/{chunk-BREDDYX4.js → chunk-XXNSAOCH.js} +2 -2
- package/dist/cli.js +70 -15
- package/dist/cli.js.map +1 -1
- package/dist/{consensus-vote-BD5NWZU5.js → consensus-vote-36TUM35R.js} +4 -4
- package/dist/{improvement-review-FLF7N7PR.js → improvement-review-NHXRFXMD.js} +4 -4
- package/dist/index.d.ts +61 -0
- package/dist/index.js +7 -7
- package/dist/{pr-reviewer-helpers-HZGPA2OS.js → pr-reviewer-helpers-BB3QNAWD.js} +3 -3
- package/dist/{setup-data-dir-A37RQCGA.js → setup-data-dir-UQOVBXCR.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-A7XDON63.js.map +0 -1
- /package/dist/{chunk-QOJPTGQI.js.map → chunk-C4ZXUDDS.js.map} +0 -0
- /package/dist/{chunk-PIBIAVWQ.js.map → chunk-CVHLQFUX.js.map} +0 -0
- /package/dist/{chunk-ZZ2BEXLC.js.map → chunk-HF36DB2G.js.map} +0 -0
- /package/dist/{chunk-3OQBXYFS.js.map → chunk-JEESPQIQ.js.map} +0 -0
- /package/dist/{chunk-KS7CAJAC.js.map → chunk-JYZLBQ7M.js.map} +0 -0
- /package/dist/{chunk-BREDDYX4.js.map → chunk-XXNSAOCH.js.map} +0 -0
- /package/dist/{consensus-vote-BD5NWZU5.js.map → consensus-vote-36TUM35R.js.map} +0 -0
- /package/dist/{improvement-review-FLF7N7PR.js.map → improvement-review-NHXRFXMD.js.map} +0 -0
- /package/dist/{pr-reviewer-helpers-HZGPA2OS.js.map → pr-reviewer-helpers-BB3QNAWD.js.map} +0 -0
- /package/dist/{setup-data-dir-A37RQCGA.js.map → setup-data-dir-UQOVBXCR.js.map} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
FINDING_SEVERITY_LEVELS,
|
|
3
3
|
SARIF_LEVEL_MAP,
|
|
4
4
|
SEVERITY_ORDER
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-BDP422B2.js";
|
|
6
6
|
import {
|
|
7
7
|
executeExpert
|
|
8
8
|
} from "./chunk-XAEGIDWX.js";
|
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
updateStage,
|
|
59
59
|
withFileLock,
|
|
60
60
|
writeJobCancelled
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-CVHLQFUX.js";
|
|
62
62
|
import {
|
|
63
63
|
normalizeTopicToCanonical,
|
|
64
64
|
synthesizeResearch
|
|
@@ -77,7 +77,7 @@ import {
|
|
|
77
77
|
} from "./chunk-HQ2SMW4Y.js";
|
|
78
78
|
import {
|
|
79
79
|
withPrerequisite
|
|
80
|
-
} from "./chunk-
|
|
80
|
+
} from "./chunk-JYZLBQ7M.js";
|
|
81
81
|
import {
|
|
82
82
|
NOOP_NOTIFIER,
|
|
83
83
|
RateLimiter,
|
|
@@ -105,7 +105,7 @@ import {
|
|
|
105
105
|
toolSuccess,
|
|
106
106
|
withProgressHeartbeat,
|
|
107
107
|
wrapToolWithTimeout
|
|
108
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-XXNSAOCH.js";
|
|
109
109
|
import {
|
|
110
110
|
generateSecurityPlan
|
|
111
111
|
} from "./chunk-6ZTMMN2N.js";
|
|
@@ -187,7 +187,7 @@ import {
|
|
|
187
187
|
import {
|
|
188
188
|
DEFAULT_TASK_TTL_MS,
|
|
189
189
|
clampTaskTtl
|
|
190
|
-
} from "./chunk-
|
|
190
|
+
} from "./chunk-HF36DB2G.js";
|
|
191
191
|
import {
|
|
192
192
|
allOf,
|
|
193
193
|
anyOf
|
|
@@ -196,7 +196,7 @@ import {
|
|
|
196
196
|
VERSION,
|
|
197
197
|
createRequestContext,
|
|
198
198
|
measuredTrustTier
|
|
199
|
-
} from "./chunk-
|
|
199
|
+
} from "./chunk-JEESPQIQ.js";
|
|
200
200
|
import {
|
|
201
201
|
BWRAP_READ_ONLY_ARGS,
|
|
202
202
|
CliDetectionCache,
|
|
@@ -787,19 +787,19 @@ function suggestSimilar(name, known) {
|
|
|
787
787
|
function classifyEnvKeys(nexusKeys, env) {
|
|
788
788
|
const knownRecord = {};
|
|
789
789
|
const unknownVars = [];
|
|
790
|
-
for (const
|
|
791
|
-
if (isDynamicFamilyMember(
|
|
790
|
+
for (const key2 of nexusKeys) {
|
|
791
|
+
if (isDynamicFamilyMember(key2)) {
|
|
792
792
|
continue;
|
|
793
793
|
}
|
|
794
|
-
if (KNOWN_NAMES.includes(
|
|
795
|
-
const value = env[
|
|
794
|
+
if (KNOWN_NAMES.includes(key2)) {
|
|
795
|
+
const value = env[key2];
|
|
796
796
|
if (value !== void 0) {
|
|
797
|
-
knownRecord[
|
|
797
|
+
knownRecord[key2] = value;
|
|
798
798
|
}
|
|
799
799
|
} else {
|
|
800
800
|
unknownVars.push({
|
|
801
|
-
name:
|
|
802
|
-
suggestion: suggestSimilar(
|
|
801
|
+
name: key2,
|
|
802
|
+
suggestion: suggestSimilar(key2, KNOWN_NAMES)
|
|
803
803
|
});
|
|
804
804
|
}
|
|
805
805
|
}
|
|
@@ -963,14 +963,14 @@ var PERSISTENCE_AWARE_FLAGS = /* @__PURE__ */ new Set([
|
|
|
963
963
|
function resolveStageFlags(stagesConfig) {
|
|
964
964
|
const persistenceOn = isPersistenceEnabled();
|
|
965
965
|
const result = {};
|
|
966
|
-
for (const
|
|
967
|
-
const explicit = stagesConfig[
|
|
966
|
+
for (const key2 of STAGE_FLAG_KEYS) {
|
|
967
|
+
const explicit = stagesConfig[key2];
|
|
968
968
|
if (explicit !== void 0) {
|
|
969
|
-
result[
|
|
970
|
-
} else if (PERSISTENCE_AWARE_FLAGS.has(
|
|
971
|
-
result[
|
|
969
|
+
result[key2] = explicit;
|
|
970
|
+
} else if (PERSISTENCE_AWARE_FLAGS.has(key2) && persistenceOn) {
|
|
971
|
+
result[key2] = true;
|
|
972
972
|
} else {
|
|
973
|
-
result[
|
|
973
|
+
result[key2] = DEFAULT_COMPOSITE_CONFIG[key2];
|
|
974
974
|
}
|
|
975
975
|
}
|
|
976
976
|
return result;
|
|
@@ -1062,13 +1062,13 @@ var ConfigManager = class _ConfigManager {
|
|
|
1062
1062
|
_ConfigManager.instance = null;
|
|
1063
1063
|
}
|
|
1064
1064
|
/** Gets the effective value for a configuration key. */
|
|
1065
|
-
get(category,
|
|
1066
|
-
return this.getWithMeta(category,
|
|
1065
|
+
get(category, key2) {
|
|
1066
|
+
return this.getWithMeta(category, key2).value;
|
|
1067
1067
|
}
|
|
1068
1068
|
/** Gets the effective value with source metadata. */
|
|
1069
|
-
getWithMeta(category,
|
|
1070
|
-
const fullKey = `${category}.${String(
|
|
1071
|
-
const defaultValue = DEFAULTS[category][
|
|
1069
|
+
getWithMeta(category, key2) {
|
|
1070
|
+
const fullKey = `${category}.${String(key2)}`;
|
|
1071
|
+
const defaultValue = DEFAULTS[category][key2];
|
|
1072
1072
|
const override = this.overrides.get(fullKey);
|
|
1073
1073
|
if (override) {
|
|
1074
1074
|
return {
|
|
@@ -1101,9 +1101,9 @@ var ConfigManager = class _ConfigManager {
|
|
|
1101
1101
|
* Sets an override for a configuration key.
|
|
1102
1102
|
* @throws {Error} If value fails type validation
|
|
1103
1103
|
*/
|
|
1104
|
-
setOverride(category,
|
|
1105
|
-
const fullKey = `${category}.${String(
|
|
1106
|
-
const defaultValue = DEFAULTS[category][
|
|
1104
|
+
setOverride(category, key2, value, source) {
|
|
1105
|
+
const fullKey = `${category}.${String(key2)}`;
|
|
1106
|
+
const defaultValue = DEFAULTS[category][key2];
|
|
1107
1107
|
if (!validateValue(value, defaultValue)) {
|
|
1108
1108
|
throw new Error(
|
|
1109
1109
|
`Invalid value type for ${fullKey}: expected ${typeof defaultValue}, got ${typeof value}`
|
|
@@ -1112,8 +1112,8 @@ var ConfigManager = class _ConfigManager {
|
|
|
1112
1112
|
this.overrides.set(fullKey, { value, source, setAt: new Date(getTimeProvider().now()) });
|
|
1113
1113
|
}
|
|
1114
1114
|
/** Clears an override. Returns true if it existed. */
|
|
1115
|
-
clearOverride(category,
|
|
1116
|
-
return this.overrides.delete(`${category}.${String(
|
|
1115
|
+
clearOverride(category, key2) {
|
|
1116
|
+
return this.overrides.delete(`${category}.${String(key2)}`);
|
|
1117
1117
|
}
|
|
1118
1118
|
/** Clears all overrides. */
|
|
1119
1119
|
clearAllOverrides() {
|
|
@@ -1121,8 +1121,8 @@ var ConfigManager = class _ConfigManager {
|
|
|
1121
1121
|
}
|
|
1122
1122
|
/** Lists all active overrides. */
|
|
1123
1123
|
listOverrides() {
|
|
1124
|
-
return Array.from(this.overrides.entries()).map(([
|
|
1125
|
-
key,
|
|
1124
|
+
return Array.from(this.overrides.entries()).map(([key2, override]) => ({
|
|
1125
|
+
key: key2,
|
|
1126
1126
|
value: override.value,
|
|
1127
1127
|
source: override.source,
|
|
1128
1128
|
setAt: override.setAt
|
|
@@ -1133,12 +1133,12 @@ var ConfigManager = class _ConfigManager {
|
|
|
1133
1133
|
const categories = categoryFilter ? [categoryFilter] : Object.keys(DEFAULTS);
|
|
1134
1134
|
const result = [];
|
|
1135
1135
|
for (const category of categories) {
|
|
1136
|
-
for (const
|
|
1137
|
-
const fullKey = `${category}.${
|
|
1138
|
-
const meta = this.getWithMeta(category,
|
|
1136
|
+
for (const key2 of Object.keys(DEFAULTS[category])) {
|
|
1137
|
+
const fullKey = `${category}.${key2}`;
|
|
1138
|
+
const meta = this.getWithMeta(category, key2);
|
|
1139
1139
|
result.push({
|
|
1140
1140
|
category,
|
|
1141
|
-
key,
|
|
1141
|
+
key: key2,
|
|
1142
1142
|
value: meta.value,
|
|
1143
1143
|
source: meta.source,
|
|
1144
1144
|
envVar: ENV_VAR_MAP[fullKey]
|
|
@@ -1148,12 +1148,12 @@ var ConfigManager = class _ConfigManager {
|
|
|
1148
1148
|
return result;
|
|
1149
1149
|
}
|
|
1150
1150
|
/** Gets the environment variable name for a config key. */
|
|
1151
|
-
getEnvVarName(category,
|
|
1152
|
-
return ENV_VAR_MAP[`${category}.${String(
|
|
1151
|
+
getEnvVarName(category, key2) {
|
|
1152
|
+
return ENV_VAR_MAP[`${category}.${String(key2)}`];
|
|
1153
1153
|
}
|
|
1154
1154
|
/** Checks if a key has an active override. */
|
|
1155
|
-
hasOverride(category,
|
|
1156
|
-
return this.overrides.has(`${category}.${String(
|
|
1155
|
+
hasOverride(category, key2) {
|
|
1156
|
+
return this.overrides.has(`${category}.${String(key2)}`);
|
|
1157
1157
|
}
|
|
1158
1158
|
};
|
|
1159
1159
|
function getConfigManager() {
|
|
@@ -1522,7 +1522,7 @@ var RateLimiter2 = class {
|
|
|
1522
1522
|
* Sleeps for the specified duration.
|
|
1523
1523
|
*/
|
|
1524
1524
|
sleep(ms) {
|
|
1525
|
-
return new Promise((
|
|
1525
|
+
return new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
1526
1526
|
}
|
|
1527
1527
|
/**
|
|
1528
1528
|
* Returns the current number of available tokens.
|
|
@@ -1745,14 +1745,14 @@ function notifyRetry(onRetry, info) {
|
|
|
1745
1745
|
function sleepUnlessAborted(ms, signal) {
|
|
1746
1746
|
if (signal === void 0) return sleep(ms).then(() => true);
|
|
1747
1747
|
if (signal.aborted) return Promise.resolve(false);
|
|
1748
|
-
return new Promise((
|
|
1748
|
+
return new Promise((resolve13) => {
|
|
1749
1749
|
const onAbort = () => {
|
|
1750
1750
|
clearTimeout(timer);
|
|
1751
|
-
|
|
1751
|
+
resolve13(false);
|
|
1752
1752
|
};
|
|
1753
1753
|
const timer = setTimeout(() => {
|
|
1754
1754
|
signal.removeEventListener("abort", onAbort);
|
|
1755
|
-
|
|
1755
|
+
resolve13(true);
|
|
1756
1756
|
}, ms);
|
|
1757
1757
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
1758
1758
|
});
|
|
@@ -4363,7 +4363,7 @@ function getAgentStateKey(agentId) {
|
|
|
4363
4363
|
|
|
4364
4364
|
// src/agents/memory-operations.ts
|
|
4365
4365
|
async function persistMemoryState(backend, state, logger58) {
|
|
4366
|
-
const
|
|
4366
|
+
const key2 = getAgentStateKey(state.agentId);
|
|
4367
4367
|
const metadata = {
|
|
4368
4368
|
importance: MemoryImportance.HIGH,
|
|
4369
4369
|
tags: ["agent-state", state.role]
|
|
@@ -4372,7 +4372,7 @@ async function persistMemoryState(backend, state, logger58) {
|
|
|
4372
4372
|
...state,
|
|
4373
4373
|
persistedAt: new Date(getTimeProvider().now())
|
|
4374
4374
|
};
|
|
4375
|
-
const result = await backend.store(
|
|
4375
|
+
const result = await backend.store(key2, updatedState, metadata);
|
|
4376
4376
|
if (!result.ok) {
|
|
4377
4377
|
logger58.error("Failed to persist agent memory state", result.error, { agentId: state.agentId });
|
|
4378
4378
|
return err(
|
|
@@ -4388,8 +4388,8 @@ async function persistMemoryState(backend, state, logger58) {
|
|
|
4388
4388
|
return ok(void 0);
|
|
4389
4389
|
}
|
|
4390
4390
|
async function loadMemoryState(backend, agentId, role, logger58) {
|
|
4391
|
-
const
|
|
4392
|
-
const result = await backend.retrieve(
|
|
4391
|
+
const key2 = getAgentStateKey(agentId);
|
|
4392
|
+
const result = await backend.retrieve(key2);
|
|
4393
4393
|
if (!result.ok) {
|
|
4394
4394
|
logger58.debug("No existing memory state found, creating fresh state", { agentId });
|
|
4395
4395
|
return ok(createInitialMemoryState(agentId, role));
|
|
@@ -4741,13 +4741,13 @@ function makeCancelError(taskId) {
|
|
|
4741
4741
|
}
|
|
4742
4742
|
function executeWithTimeout(params) {
|
|
4743
4743
|
const { task, maxDurationMs, executeTask, transformError, signal } = params;
|
|
4744
|
-
return new Promise((
|
|
4744
|
+
return new Promise((resolve13) => {
|
|
4745
4745
|
let settled = false;
|
|
4746
4746
|
const settle = (result) => {
|
|
4747
4747
|
if (settled) return;
|
|
4748
4748
|
settled = true;
|
|
4749
4749
|
clearTimeout(timeoutId);
|
|
4750
|
-
|
|
4750
|
+
resolve13(result);
|
|
4751
4751
|
};
|
|
4752
4752
|
const timeoutId = setTimeout(() => {
|
|
4753
4753
|
settle(
|
|
@@ -6102,9 +6102,9 @@ function mergeArrays(outputs) {
|
|
|
6102
6102
|
const merged = [];
|
|
6103
6103
|
for (const output2 of outputs) {
|
|
6104
6104
|
for (const item of output2) {
|
|
6105
|
-
const
|
|
6106
|
-
if (!seen.has(
|
|
6107
|
-
seen.add(
|
|
6105
|
+
const key2 = JSON.stringify(item);
|
|
6106
|
+
if (!seen.has(key2)) {
|
|
6107
|
+
seen.add(key2);
|
|
6108
6108
|
merged.push(item);
|
|
6109
6109
|
}
|
|
6110
6110
|
}
|
|
@@ -6131,7 +6131,7 @@ function deepEquals(a, b) {
|
|
|
6131
6131
|
if (aKeys.length !== bKeys.length) {
|
|
6132
6132
|
return false;
|
|
6133
6133
|
}
|
|
6134
|
-
return aKeys.every((
|
|
6134
|
+
return aKeys.every((key2) => deepEquals(aObj[key2], bObj[key2]));
|
|
6135
6135
|
}
|
|
6136
6136
|
function handleFieldConflict(ctx) {
|
|
6137
6137
|
const conflict = {
|
|
@@ -6162,25 +6162,25 @@ function mergeObjects(results, outputs, conflictResolver) {
|
|
|
6162
6162
|
const output2 = outputs[i];
|
|
6163
6163
|
const result = results[i];
|
|
6164
6164
|
if (output2 === void 0 || result === void 0) continue;
|
|
6165
|
-
for (const [
|
|
6166
|
-
const existing = keyOwners.get(
|
|
6165
|
+
for (const [key2, value] of Object.entries(output2)) {
|
|
6166
|
+
const existing = keyOwners.get(key2);
|
|
6167
6167
|
if (existing === void 0) {
|
|
6168
|
-
keyOwners.set(
|
|
6169
|
-
merged[
|
|
6168
|
+
keyOwners.set(key2, { expertId: result.expertId, value });
|
|
6169
|
+
merged[key2] = value;
|
|
6170
6170
|
continue;
|
|
6171
6171
|
}
|
|
6172
6172
|
if (deepEquals(existing.value, value)) continue;
|
|
6173
6173
|
const conflict = handleFieldConflict({
|
|
6174
6174
|
existing,
|
|
6175
6175
|
newResult: result,
|
|
6176
|
-
key,
|
|
6176
|
+
key: key2,
|
|
6177
6177
|
value,
|
|
6178
6178
|
results,
|
|
6179
6179
|
conflictResolver
|
|
6180
6180
|
});
|
|
6181
6181
|
if (conflict.resolution === "expert2") {
|
|
6182
|
-
merged[
|
|
6183
|
-
keyOwners.set(
|
|
6182
|
+
merged[key2] = value;
|
|
6183
|
+
keyOwners.set(key2, { expertId: result.expertId, value });
|
|
6184
6184
|
}
|
|
6185
6185
|
conflicts.push(conflict);
|
|
6186
6186
|
}
|
|
@@ -10500,13 +10500,13 @@ var WaveScheduler = class {
|
|
|
10500
10500
|
}
|
|
10501
10501
|
async withTimeout(promise, timeoutMs, taskId) {
|
|
10502
10502
|
if (timeoutMs <= 0) return promise;
|
|
10503
|
-
return new Promise((
|
|
10503
|
+
return new Promise((resolve13, reject) => {
|
|
10504
10504
|
const timer = setTimeout(() => {
|
|
10505
10505
|
reject(new Error(`Task ${taskId} timed out after ${String(timeoutMs)}ms`));
|
|
10506
10506
|
}, timeoutMs);
|
|
10507
10507
|
promise.then((result) => {
|
|
10508
10508
|
clearTimeout(timer);
|
|
10509
|
-
|
|
10509
|
+
resolve13(result);
|
|
10510
10510
|
}).catch((error) => {
|
|
10511
10511
|
clearTimeout(timer);
|
|
10512
10512
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -10518,8 +10518,8 @@ function chunkByDirectory(files, basePath) {
|
|
|
10518
10518
|
const normalizedBase = basePath.endsWith("/") ? basePath : `${basePath}/`;
|
|
10519
10519
|
const groups = /* @__PURE__ */ new Map();
|
|
10520
10520
|
for (const file of files) {
|
|
10521
|
-
const
|
|
10522
|
-
const stripped =
|
|
10521
|
+
const relative7 = file.startsWith(normalizedBase) ? file.slice(normalizedBase.length) : file;
|
|
10522
|
+
const stripped = relative7.startsWith("/") ? relative7.slice(1) : relative7;
|
|
10523
10523
|
const topDir = stripped.split("/")[0] ?? "root";
|
|
10524
10524
|
const existing = groups.get(topDir);
|
|
10525
10525
|
if (existing !== void 0) {
|
|
@@ -13500,8 +13500,8 @@ var RecoveryManager = class {
|
|
|
13500
13500
|
* Resets the attempt count for a failure archetype.
|
|
13501
13501
|
*/
|
|
13502
13502
|
resetAttemptCount(failure) {
|
|
13503
|
-
const
|
|
13504
|
-
this.attemptCounts.delete(
|
|
13503
|
+
const key2 = this.getAttemptKey(failure);
|
|
13504
|
+
this.attemptCounts.delete(key2);
|
|
13505
13505
|
}
|
|
13506
13506
|
/**
|
|
13507
13507
|
* Checks if recovery should be attempted.
|
|
@@ -13622,8 +13622,8 @@ INDICATORS FOUND: ${ctx.failure.indicators.join("; ")}
|
|
|
13622
13622
|
}
|
|
13623
13623
|
/** Increments the attempt count. */
|
|
13624
13624
|
incrementAttemptCount(failure) {
|
|
13625
|
-
const
|
|
13626
|
-
this.attemptCounts.set(
|
|
13625
|
+
const key2 = this.getAttemptKey(failure);
|
|
13626
|
+
this.attemptCounts.set(key2, (this.attemptCounts.get(key2) ?? 0) + 1);
|
|
13627
13627
|
}
|
|
13628
13628
|
};
|
|
13629
13629
|
|
|
@@ -13878,12 +13878,12 @@ function categoryToGuidance(category, count) {
|
|
|
13878
13878
|
function groupByCategory(outcomes) {
|
|
13879
13879
|
const groups = /* @__PURE__ */ new Map();
|
|
13880
13880
|
for (const outcome of outcomes) {
|
|
13881
|
-
const
|
|
13882
|
-
const group = groups.get(
|
|
13881
|
+
const key2 = outcome.failureCategory ?? "unknown";
|
|
13882
|
+
const group = groups.get(key2);
|
|
13883
13883
|
if (group !== void 0) {
|
|
13884
13884
|
group.push(outcome);
|
|
13885
13885
|
} else {
|
|
13886
|
-
groups.set(
|
|
13886
|
+
groups.set(key2, [outcome]);
|
|
13887
13887
|
}
|
|
13888
13888
|
}
|
|
13889
13889
|
return groups;
|
|
@@ -18121,8 +18121,8 @@ var Semaphore = class {
|
|
|
18121
18121
|
this.available -= 1;
|
|
18122
18122
|
return Promise.resolve();
|
|
18123
18123
|
}
|
|
18124
|
-
return new Promise((
|
|
18125
|
-
this.waiters.push(
|
|
18124
|
+
return new Promise((resolve13) => {
|
|
18125
|
+
this.waiters.push(resolve13);
|
|
18126
18126
|
});
|
|
18127
18127
|
}
|
|
18128
18128
|
release() {
|
|
@@ -19758,8 +19758,8 @@ function inferLastPattern(recentOutputs) {
|
|
|
19758
19758
|
const lastOutput = recentOutputs[recentOutputs.length - 1];
|
|
19759
19759
|
if (lastOutput === void 0) return void 0;
|
|
19760
19760
|
const lastAgentId = lastOutput.agentId;
|
|
19761
|
-
for (const [
|
|
19762
|
-
if (lastAgentId.includes(
|
|
19761
|
+
for (const [key2, pattern] of Object.entries(AGENT_PATTERN_MAP)) {
|
|
19762
|
+
if (lastAgentId.includes(key2)) return pattern;
|
|
19763
19763
|
}
|
|
19764
19764
|
return void 0;
|
|
19765
19765
|
}
|
|
@@ -20094,8 +20094,8 @@ function extractFeatureValues(features) {
|
|
|
20094
20094
|
}
|
|
20095
20095
|
function computeGradients(trajectory, returns, baseline) {
|
|
20096
20096
|
const gradients = {};
|
|
20097
|
-
for (const
|
|
20098
|
-
gradients[
|
|
20097
|
+
for (const key2 of LEARNABLE_WEIGHTS) {
|
|
20098
|
+
gradients[key2] = 0;
|
|
20099
20099
|
}
|
|
20100
20100
|
for (let t = 0; t < trajectory.length; t++) {
|
|
20101
20101
|
const step = trajectory[t];
|
|
@@ -20104,16 +20104,16 @@ function computeGradients(trajectory, returns, baseline) {
|
|
|
20104
20104
|
const advantage = returnValue - baseline;
|
|
20105
20105
|
const features = extractFeatures(step.state);
|
|
20106
20106
|
const featureValues = extractFeatureValues(features);
|
|
20107
|
-
for (const
|
|
20108
|
-
const featureVal = featureValues[
|
|
20109
|
-
const currentGrad = gradients[
|
|
20110
|
-
gradients[
|
|
20107
|
+
for (const key2 of LEARNABLE_WEIGHTS) {
|
|
20108
|
+
const featureVal = featureValues[key2];
|
|
20109
|
+
const currentGrad = gradients[key2] ?? 0;
|
|
20110
|
+
gradients[key2] = currentGrad + advantage * featureVal;
|
|
20111
20111
|
}
|
|
20112
20112
|
}
|
|
20113
20113
|
if (trajectory.length > 0) {
|
|
20114
|
-
for (const
|
|
20115
|
-
const currentGrad = gradients[
|
|
20116
|
-
gradients[
|
|
20114
|
+
for (const key2 of LEARNABLE_WEIGHTS) {
|
|
20115
|
+
const currentGrad = gradients[key2] ?? 0;
|
|
20116
|
+
gradients[key2] = currentGrad / trajectory.length;
|
|
20117
20117
|
}
|
|
20118
20118
|
}
|
|
20119
20119
|
return gradients;
|
|
@@ -20122,9 +20122,9 @@ function normalizeWeights(weights) {
|
|
|
20122
20122
|
const weightSum = Object.values(weights).reduce((s, w) => s + Math.abs(w), 0);
|
|
20123
20123
|
if (weightSum === 0) return weights;
|
|
20124
20124
|
const normalized = { ...weights };
|
|
20125
|
-
for (const
|
|
20126
|
-
const weight = normalized[
|
|
20127
|
-
normalized[
|
|
20125
|
+
for (const key2 of Object.keys(normalized)) {
|
|
20126
|
+
const weight = normalized[key2] ?? 0;
|
|
20127
|
+
normalized[key2] = Math.abs(weight) / weightSum;
|
|
20128
20128
|
}
|
|
20129
20129
|
return normalized;
|
|
20130
20130
|
}
|
|
@@ -20132,10 +20132,10 @@ function applyGradientUpdate(gradients, currentWeights, learningRate, gradientCl
|
|
|
20132
20132
|
const gradNorm = Math.sqrt(Object.values(gradients).reduce((sum, g) => sum + g * g, 0));
|
|
20133
20133
|
const clipRatio = gradNorm > gradientClip ? gradientClip / gradNorm : 1;
|
|
20134
20134
|
const newWeights = { ...currentWeights };
|
|
20135
|
-
for (const
|
|
20136
|
-
const currentWeight = newWeights[
|
|
20137
|
-
const gradient = gradients[
|
|
20138
|
-
newWeights[
|
|
20135
|
+
for (const key2 of LEARNABLE_WEIGHTS) {
|
|
20136
|
+
const currentWeight = newWeights[key2] ?? 0;
|
|
20137
|
+
const gradient = gradients[key2] ?? 0;
|
|
20138
|
+
newWeights[key2] = currentWeight + learningRate * gradient * clipRatio;
|
|
20139
20139
|
}
|
|
20140
20140
|
return {
|
|
20141
20141
|
weights: normalizeWeights(newWeights),
|
|
@@ -20448,14 +20448,14 @@ var PatternTracker = class {
|
|
|
20448
20448
|
const ngramCounts = /* @__PURE__ */ new Map();
|
|
20449
20449
|
for (let i = 0; i <= sequence2.length - length; i++) {
|
|
20450
20450
|
const ngram = sequence2.slice(i, i + length);
|
|
20451
|
-
const
|
|
20452
|
-
ngramCounts.set(
|
|
20451
|
+
const key2 = ngram.join("|");
|
|
20452
|
+
ngramCounts.set(key2, (ngramCounts.get(key2) ?? 0) + 1);
|
|
20453
20453
|
}
|
|
20454
20454
|
const cycles = [];
|
|
20455
|
-
for (const [
|
|
20455
|
+
for (const [key2, count] of ngramCounts) {
|
|
20456
20456
|
if (count >= 2) {
|
|
20457
20457
|
cycles.push({
|
|
20458
|
-
agents:
|
|
20458
|
+
agents: key2.split("|"),
|
|
20459
20459
|
occurrences: count
|
|
20460
20460
|
});
|
|
20461
20461
|
}
|
|
@@ -20465,14 +20465,14 @@ var PatternTracker = class {
|
|
|
20465
20465
|
mergeCycles(cycles) {
|
|
20466
20466
|
const grouped = /* @__PURE__ */ new Map();
|
|
20467
20467
|
for (const cycle of cycles) {
|
|
20468
|
-
const
|
|
20469
|
-
const existing = grouped.get(
|
|
20468
|
+
const key2 = this.normalizeCycleKey(cycle.agents);
|
|
20469
|
+
const existing = grouped.get(key2);
|
|
20470
20470
|
if (existing) {
|
|
20471
20471
|
if (cycle.occurrences > existing.occurrences) {
|
|
20472
|
-
grouped.set(
|
|
20472
|
+
grouped.set(key2, cycle);
|
|
20473
20473
|
}
|
|
20474
20474
|
} else {
|
|
20475
|
-
grouped.set(
|
|
20475
|
+
grouped.set(key2, cycle);
|
|
20476
20476
|
}
|
|
20477
20477
|
}
|
|
20478
20478
|
return [...grouped.values()].sort((a, b) => b.occurrences - a.occurrences);
|
|
@@ -21541,9 +21541,9 @@ var ExpertPool = class {
|
|
|
21541
21541
|
if (this.active < this.capacity) {
|
|
21542
21542
|
return this.issuePermit();
|
|
21543
21543
|
}
|
|
21544
|
-
return new Promise((
|
|
21544
|
+
return new Promise((resolve13, reject) => {
|
|
21545
21545
|
const timer = setTimeout(() => {
|
|
21546
|
-
const idx = this.queue.findIndex((e) => e.resolve ===
|
|
21546
|
+
const idx = this.queue.findIndex((e) => e.resolve === resolve13);
|
|
21547
21547
|
if (idx !== -1) {
|
|
21548
21548
|
this.queue.splice(idx, 1);
|
|
21549
21549
|
}
|
|
@@ -21553,7 +21553,7 @@ var ExpertPool = class {
|
|
|
21553
21553
|
)
|
|
21554
21554
|
);
|
|
21555
21555
|
}, this.acquireTimeoutMs);
|
|
21556
|
-
this.queue.push({ resolve:
|
|
21556
|
+
this.queue.push({ resolve: resolve13, reject, timer });
|
|
21557
21557
|
});
|
|
21558
21558
|
}
|
|
21559
21559
|
/** Release a permit back to the pool. */
|
|
@@ -22148,8 +22148,8 @@ var TaskQueue = class {
|
|
|
22148
22148
|
if (this.cancelled) {
|
|
22149
22149
|
return Promise.reject(new Error("Queue has been cancelled"));
|
|
22150
22150
|
}
|
|
22151
|
-
return new Promise((
|
|
22152
|
-
this.queue.push({ task, resolve:
|
|
22151
|
+
return new Promise((resolve13, reject) => {
|
|
22152
|
+
this.queue.push({ task, resolve: resolve13, reject });
|
|
22153
22153
|
this.processNext();
|
|
22154
22154
|
});
|
|
22155
22155
|
}
|
|
@@ -22425,16 +22425,16 @@ async function executeStepWithTimeout(step, context, stepExecutor, signal) {
|
|
|
22425
22425
|
return executeWithTimeout2(step, stepContext, stepExecutor, stepTimeout, startTime);
|
|
22426
22426
|
}
|
|
22427
22427
|
function executeWithTimeout2(step, context, executor, timeout, startTime) {
|
|
22428
|
-
return new Promise((
|
|
22428
|
+
return new Promise((resolve13) => {
|
|
22429
22429
|
const timeoutId = setTimeout(() => {
|
|
22430
|
-
|
|
22430
|
+
resolve13(createTimeoutResult(step.id, getTimeProvider().now() - startTime, timeout));
|
|
22431
22431
|
}, timeout);
|
|
22432
22432
|
executor(step, context).then((result) => {
|
|
22433
22433
|
clearTimeout(timeoutId);
|
|
22434
|
-
|
|
22434
|
+
resolve13(result);
|
|
22435
22435
|
}).catch((error) => {
|
|
22436
22436
|
clearTimeout(timeoutId);
|
|
22437
|
-
|
|
22437
|
+
resolve13(createErrorResult(step.id, getTimeProvider().now() - startTime, error));
|
|
22438
22438
|
});
|
|
22439
22439
|
});
|
|
22440
22440
|
}
|
|
@@ -23235,12 +23235,12 @@ function isCancelled(context) {
|
|
|
23235
23235
|
}
|
|
23236
23236
|
function snapshotContext(context) {
|
|
23237
23237
|
const stepResults = {};
|
|
23238
|
-
for (const [
|
|
23239
|
-
stepResults[
|
|
23238
|
+
for (const [key2, value] of context.stepResults) {
|
|
23239
|
+
stepResults[key2] = value;
|
|
23240
23240
|
}
|
|
23241
23241
|
const variables = {};
|
|
23242
|
-
for (const [
|
|
23243
|
-
variables[
|
|
23242
|
+
for (const [key2, value] of context.variables) {
|
|
23243
|
+
variables[key2] = value;
|
|
23244
23244
|
}
|
|
23245
23245
|
return {
|
|
23246
23246
|
workflowId: context.workflowId,
|
|
@@ -23271,14 +23271,14 @@ function validateRequiredInputs(inputs, required) {
|
|
|
23271
23271
|
// src/workflows/expression-resolver-helpers.ts
|
|
23272
23272
|
function getNestedValue(obj, path9) {
|
|
23273
23273
|
let current = obj;
|
|
23274
|
-
for (const
|
|
23274
|
+
for (const key2 of path9) {
|
|
23275
23275
|
if (current === null || current === void 0) {
|
|
23276
23276
|
return void 0;
|
|
23277
23277
|
}
|
|
23278
23278
|
if (typeof current !== "object") {
|
|
23279
23279
|
return void 0;
|
|
23280
23280
|
}
|
|
23281
|
-
current = current[
|
|
23281
|
+
current = current[key2];
|
|
23282
23282
|
}
|
|
23283
23283
|
return current;
|
|
23284
23284
|
}
|
|
@@ -23467,8 +23467,8 @@ function resolveInput(input, context) {
|
|
|
23467
23467
|
}
|
|
23468
23468
|
if (input !== null && typeof input === "object") {
|
|
23469
23469
|
const resolved = {};
|
|
23470
|
-
for (const [
|
|
23471
|
-
resolved[
|
|
23470
|
+
for (const [key2, value] of Object.entries(input)) {
|
|
23471
|
+
resolved[key2] = resolveInput(value, context);
|
|
23472
23472
|
}
|
|
23473
23473
|
return resolved;
|
|
23474
23474
|
}
|
|
@@ -23595,7 +23595,7 @@ function formatValue(value) {
|
|
|
23595
23595
|
return typeof value === "number" || typeof value === "boolean" ? String(value) : "[complex]";
|
|
23596
23596
|
}
|
|
23597
23597
|
function buildTaskDescription(step, inputs) {
|
|
23598
|
-
const inputSummary = Object.entries(inputs).map(([
|
|
23598
|
+
const inputSummary = Object.entries(inputs).map(([key2, value]) => `- ${key2}: ${formatValue(value)}`).join("\n");
|
|
23599
23599
|
return `Execute action: ${step.action}
|
|
23600
23600
|
|
|
23601
23601
|
Inputs:
|
|
@@ -26393,8 +26393,8 @@ function buildTopEdges(graph) {
|
|
|
26393
26393
|
const edges = graph.getEdges();
|
|
26394
26394
|
const edgeMap = /* @__PURE__ */ new Map();
|
|
26395
26395
|
for (const edge of edges) {
|
|
26396
|
-
const
|
|
26397
|
-
const existing = edgeMap.get(
|
|
26396
|
+
const key2 = `${edge.from}|${edge.to}`;
|
|
26397
|
+
const existing = edgeMap.get(key2) ?? { count: 0, successes: 0, totalLatency: 0, timed: 0 };
|
|
26398
26398
|
existing.count++;
|
|
26399
26399
|
if (edge.outcome === "success") {
|
|
26400
26400
|
existing.successes++;
|
|
@@ -26403,10 +26403,10 @@ function buildTopEdges(graph) {
|
|
|
26403
26403
|
existing.totalLatency += edge.durationMs;
|
|
26404
26404
|
existing.timed++;
|
|
26405
26405
|
}
|
|
26406
|
-
edgeMap.set(
|
|
26406
|
+
edgeMap.set(key2, existing);
|
|
26407
26407
|
}
|
|
26408
|
-
return Array.from(edgeMap.entries()).map(([
|
|
26409
|
-
const [from, to] =
|
|
26408
|
+
return Array.from(edgeMap.entries()).map(([key2, stats]) => {
|
|
26409
|
+
const [from, to] = key2.split("|");
|
|
26410
26410
|
return {
|
|
26411
26411
|
from: from ?? "",
|
|
26412
26412
|
to: to ?? "",
|
|
@@ -26919,10 +26919,10 @@ function calculateDifferenceCI(p1, p2, total1, total2, confidence) {
|
|
|
26919
26919
|
const difference = p1 - p2;
|
|
26920
26920
|
const measured = total1 > 0 && total2 > 0;
|
|
26921
26921
|
const seDiff = Math.sqrt(p1 * (1 - p1) / (total1 || 1) + p2 * (1 - p2) / (total2 || 1));
|
|
26922
|
-
const
|
|
26922
|
+
const z116 = getZScore(confidence);
|
|
26923
26923
|
return {
|
|
26924
|
-
lower: difference -
|
|
26925
|
-
upper: difference +
|
|
26924
|
+
lower: difference - z116 * seDiff,
|
|
26925
|
+
upper: difference + z116 * seDiff,
|
|
26926
26926
|
estimate: difference,
|
|
26927
26927
|
confidence,
|
|
26928
26928
|
n: total1 + total2,
|
|
@@ -26950,11 +26950,11 @@ function proportionConfidenceInterval(successes, total, options = {}) {
|
|
|
26950
26950
|
measured: false
|
|
26951
26951
|
};
|
|
26952
26952
|
}
|
|
26953
|
-
const
|
|
26954
|
-
const z210 =
|
|
26953
|
+
const z116 = getZScore(opts.confidence);
|
|
26954
|
+
const z210 = z116 * z116;
|
|
26955
26955
|
const denominator = 1 + z210 / n;
|
|
26956
26956
|
const center = (p + z210 / (2 * n)) / denominator;
|
|
26957
|
-
const margin =
|
|
26957
|
+
const margin = z116 / denominator * Math.sqrt(p * (1 - p) / n + z210 / (4 * n * n));
|
|
26958
26958
|
const lower = Math.max(0, center - margin);
|
|
26959
26959
|
const upper = Math.min(1, center + margin);
|
|
26960
26960
|
const standardError = Math.sqrt(p * (1 - p) / n);
|
|
@@ -26992,8 +26992,8 @@ function meanConfidenceInterval(values, options = {}) {
|
|
|
26992
26992
|
const variance = values.reduce((sum, v) => sum + (v - mean) ** 2, 0) / (n - 1 || 1);
|
|
26993
26993
|
const stdDev = Math.sqrt(variance);
|
|
26994
26994
|
const standardError = stdDev / Math.sqrt(n);
|
|
26995
|
-
const
|
|
26996
|
-
const margin =
|
|
26995
|
+
const z116 = getZScore(opts.confidence);
|
|
26996
|
+
const margin = z116 * standardError;
|
|
26997
26997
|
return {
|
|
26998
26998
|
lower: mean - margin,
|
|
26999
26999
|
upper: mean + margin,
|
|
@@ -29085,8 +29085,8 @@ function budgetHaltFailure(context) {
|
|
|
29085
29085
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
29086
29086
|
function resolveExecutionEngineOrError(deps, workflowName) {
|
|
29087
29087
|
try {
|
|
29088
|
-
const
|
|
29089
|
-
return { ok: true, value:
|
|
29088
|
+
const resolve13 = deps.resolveExecutionEngine ?? (() => deps.workflowEngine);
|
|
29089
|
+
return { ok: true, value: resolve13() };
|
|
29090
29090
|
} catch (error) {
|
|
29091
29091
|
const message = error instanceof Error ? error.message : String(error);
|
|
29092
29092
|
deps.logger?.error(
|
|
@@ -30053,8 +30053,8 @@ function initializeState(graph, inputs) {
|
|
|
30053
30053
|
for (const [field, schema] of Object.entries(graph.stateSchema)) {
|
|
30054
30054
|
state[field] = schema.defaultValue;
|
|
30055
30055
|
}
|
|
30056
|
-
for (const [
|
|
30057
|
-
state[
|
|
30056
|
+
for (const [key2, value] of Object.entries(inputs)) {
|
|
30057
|
+
state[key2] = value;
|
|
30058
30058
|
}
|
|
30059
30059
|
return state;
|
|
30060
30060
|
}
|
|
@@ -30072,9 +30072,9 @@ function applyStateUpdates(graph, state, updates) {
|
|
|
30072
30072
|
for (const [field, value] of Object.entries(updates)) {
|
|
30073
30073
|
const schema = graph.stateSchema[field];
|
|
30074
30074
|
if (schema === void 0) {
|
|
30075
|
-
const
|
|
30076
|
-
if (!undeclaredFieldWarned.has(
|
|
30077
|
-
undeclaredFieldWarned.add(
|
|
30075
|
+
const key2 = `${String(Object.keys(graph.stateSchema).length)}:${field}`;
|
|
30076
|
+
if (!undeclaredFieldWarned.has(key2)) {
|
|
30077
|
+
undeclaredFieldWarned.add(key2);
|
|
30078
30078
|
logger17.warn("Node wrote to undeclared state field; defaulting to overwrite reducer", {
|
|
30079
30079
|
field,
|
|
30080
30080
|
knownFields: Object.keys(graph.stateSchema)
|
|
@@ -30291,13 +30291,13 @@ function dedupe(ids) {
|
|
|
30291
30291
|
return [...new Set(ids)];
|
|
30292
30292
|
}
|
|
30293
30293
|
async function withTimeout3(promise, ms) {
|
|
30294
|
-
return new Promise((
|
|
30294
|
+
return new Promise((resolve13, reject) => {
|
|
30295
30295
|
const timer = setTimeout(() => {
|
|
30296
30296
|
reject(new Error(`Node timed out after ${String(ms)}ms`));
|
|
30297
30297
|
}, ms);
|
|
30298
30298
|
promise.then((result) => {
|
|
30299
30299
|
clearTimeout(timer);
|
|
30300
|
-
|
|
30300
|
+
resolve13(result);
|
|
30301
30301
|
}).catch((error) => {
|
|
30302
30302
|
clearTimeout(timer);
|
|
30303
30303
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -32661,12 +32661,12 @@ function computeMetrics2(outcomes, filterPattern) {
|
|
|
32661
32661
|
const groups = /* @__PURE__ */ new Map();
|
|
32662
32662
|
for (const o of outcomes) {
|
|
32663
32663
|
if (filterPattern !== void 0 && o.pattern !== filterPattern) continue;
|
|
32664
|
-
const
|
|
32665
|
-
const group = groups.get(
|
|
32664
|
+
const key2 = `${o.pattern}:${o.taskType}`;
|
|
32665
|
+
const group = groups.get(key2);
|
|
32666
32666
|
if (group !== void 0) {
|
|
32667
32667
|
group.push(o);
|
|
32668
32668
|
} else {
|
|
32669
|
-
groups.set(
|
|
32669
|
+
groups.set(key2, [o]);
|
|
32670
32670
|
}
|
|
32671
32671
|
}
|
|
32672
32672
|
const metrics = [];
|
|
@@ -32848,11 +32848,11 @@ function createMockOrchestrator() {
|
|
|
32848
32848
|
async function raceAgainstDeadline(promise, deadlineMs, onTimeout) {
|
|
32849
32849
|
const startedAt = Date.now();
|
|
32850
32850
|
let timer;
|
|
32851
|
-
const timeoutP = new Promise((
|
|
32851
|
+
const timeoutP = new Promise((resolve13, reject) => {
|
|
32852
32852
|
timer = setTimeout(
|
|
32853
32853
|
() => {
|
|
32854
32854
|
try {
|
|
32855
|
-
|
|
32855
|
+
resolve13(onTimeout(Date.now() - startedAt));
|
|
32856
32856
|
} catch (err2) {
|
|
32857
32857
|
reject(err2 instanceof Error ? err2 : new Error(String(err2)));
|
|
32858
32858
|
}
|
|
@@ -34039,11 +34039,11 @@ function createWorkerTask(entry, taskIndex, waveNumber, opts) {
|
|
|
34039
34039
|
const staggerSlot = taskIndex % opts.maxConcurrency;
|
|
34040
34040
|
const staggerMs = staggerSlot * opts.staggerDelayMs;
|
|
34041
34041
|
if (staggerMs > 0) {
|
|
34042
|
-
await new Promise((
|
|
34042
|
+
await new Promise((resolve13) => setTimeout(resolve13, staggerMs));
|
|
34043
34043
|
}
|
|
34044
34044
|
const spacingDelay = opts.failureTracker.getSpacingDelay(entry.role);
|
|
34045
34045
|
if (spacingDelay > 0) {
|
|
34046
|
-
await new Promise((
|
|
34046
|
+
await new Promise((resolve13) => setTimeout(resolve13, spacingDelay));
|
|
34047
34047
|
}
|
|
34048
34048
|
const timeoutMs = opts.options.workerTimeoutMs ?? getExpertTaskTimeout(entry.subTask);
|
|
34049
34049
|
const result = await executeSafe({
|
|
@@ -34096,7 +34096,7 @@ async function maybeDelayForRateLimit(results, waveIdx, totalWaves) {
|
|
|
34096
34096
|
);
|
|
34097
34097
|
if (hasRateLimit) {
|
|
34098
34098
|
logger27.warn("Rate-limit detected \u2014 delaying next wave", { delayMs: RATE_LIMIT_WAVE_DELAY_MS });
|
|
34099
|
-
await new Promise((
|
|
34099
|
+
await new Promise((resolve13) => setTimeout(resolve13, RATE_LIMIT_WAVE_DELAY_MS));
|
|
34100
34100
|
}
|
|
34101
34101
|
}
|
|
34102
34102
|
function emitWaveStarted(ctx, workerCount, roles) {
|
|
@@ -34203,7 +34203,7 @@ async function maybeRetryAfterTriage(opts) {
|
|
|
34203
34203
|
}
|
|
34204
34204
|
const useAltCli = triage.action === "retry_different_cli" && altExecuteWorker !== void 0;
|
|
34205
34205
|
if (triage.action === "retry_different_cli") {
|
|
34206
|
-
await new Promise((
|
|
34206
|
+
await new Promise((resolve13) => setTimeout(resolve13, RATE_LIMIT_SPACING_MS));
|
|
34207
34207
|
}
|
|
34208
34208
|
if (isCancelled2(opts.signal)) return { ...failedResult2, triageAction: triage.action };
|
|
34209
34209
|
const retryTimeout = triage.action === "extend_timeout" ? Math.min(timeoutMs * TIMEOUT_EXTENSION_FACTOR, MAX_WORKER_TIMEOUT_MS) : timeoutMs;
|
|
@@ -34657,12 +34657,12 @@ function extractFilePaths(output2) {
|
|
|
34657
34657
|
FILE_PATH_PATTERN.lastIndex = 0;
|
|
34658
34658
|
return [...paths];
|
|
34659
34659
|
}
|
|
34660
|
-
function addToOverlapMap(map,
|
|
34661
|
-
const existing = map.get(
|
|
34660
|
+
function addToOverlapMap(map, key2, role) {
|
|
34661
|
+
const existing = map.get(key2);
|
|
34662
34662
|
if (existing !== void 0) {
|
|
34663
34663
|
existing.add(role);
|
|
34664
34664
|
} else {
|
|
34665
|
-
map.set(
|
|
34665
|
+
map.set(key2, /* @__PURE__ */ new Set([role]));
|
|
34666
34666
|
}
|
|
34667
34667
|
}
|
|
34668
34668
|
function detectConflicts(results) {
|
|
@@ -34751,8 +34751,8 @@ var SynthesisHistoryTracker = class {
|
|
|
34751
34751
|
if (this.patterns.size <= MAX_PATTERNS) return;
|
|
34752
34752
|
const sorted = [...this.patterns.entries()].sort((a, b) => a[1].lastUpdated - b[1].lastUpdated);
|
|
34753
34753
|
const toRemove = sorted.slice(0, this.patterns.size - MAX_PATTERNS);
|
|
34754
|
-
for (const [
|
|
34755
|
-
this.patterns.delete(
|
|
34754
|
+
for (const [key2] of toRemove) {
|
|
34755
|
+
this.patterns.delete(key2);
|
|
34756
34756
|
}
|
|
34757
34757
|
}
|
|
34758
34758
|
};
|
|
@@ -35131,18 +35131,18 @@ function createCheckpoint2(role, subTask, partialOutput = "") {
|
|
|
35131
35131
|
var WorkerCheckpointStore = class {
|
|
35132
35132
|
store = /* @__PURE__ */ new Map();
|
|
35133
35133
|
/** Save a checkpoint, truncating partial output if needed. */
|
|
35134
|
-
save(
|
|
35134
|
+
save(key2, checkpoint) {
|
|
35135
35135
|
const truncated = truncateOutput(checkpoint);
|
|
35136
|
-
this.store.set(
|
|
35136
|
+
this.store.set(key2, truncated);
|
|
35137
35137
|
this.enforceCapacity();
|
|
35138
35138
|
}
|
|
35139
35139
|
/** Retrieve a checkpoint by key. */
|
|
35140
|
-
get(
|
|
35141
|
-
return this.store.get(
|
|
35140
|
+
get(key2) {
|
|
35141
|
+
return this.store.get(key2);
|
|
35142
35142
|
}
|
|
35143
35143
|
/** Remove a specific checkpoint. Returns true if it existed. */
|
|
35144
|
-
remove(
|
|
35145
|
-
return this.store.delete(
|
|
35144
|
+
remove(key2) {
|
|
35145
|
+
return this.store.delete(key2);
|
|
35146
35146
|
}
|
|
35147
35147
|
/** Clear all checkpoints. */
|
|
35148
35148
|
clear() {
|
|
@@ -35705,25 +35705,25 @@ var ReflectionCache = class {
|
|
|
35705
35705
|
return query.toLowerCase().trim().replace(/\s+/g, " ");
|
|
35706
35706
|
}
|
|
35707
35707
|
get(query) {
|
|
35708
|
-
const
|
|
35709
|
-
const entry = this.entries.get(
|
|
35708
|
+
const key2 = this.normalize(query);
|
|
35709
|
+
const entry = this.entries.get(key2);
|
|
35710
35710
|
if (entry === void 0) return void 0;
|
|
35711
35711
|
if (getTimeProvider().now() - entry.timestamp > this.ttlMs) {
|
|
35712
|
-
this.entries.delete(
|
|
35712
|
+
this.entries.delete(key2);
|
|
35713
35713
|
return void 0;
|
|
35714
35714
|
}
|
|
35715
|
-
this.entries.delete(
|
|
35716
|
-
this.entries.set(
|
|
35715
|
+
this.entries.delete(key2);
|
|
35716
|
+
this.entries.set(key2, entry);
|
|
35717
35717
|
return entry.criteria;
|
|
35718
35718
|
}
|
|
35719
35719
|
set(query, criteria) {
|
|
35720
|
-
const
|
|
35721
|
-
this.entries.delete(
|
|
35720
|
+
const key2 = this.normalize(query);
|
|
35721
|
+
this.entries.delete(key2);
|
|
35722
35722
|
if (this.entries.size >= this.maxEntries) {
|
|
35723
35723
|
const oldest = this.entries.keys().next();
|
|
35724
35724
|
if (oldest.done !== true) this.entries.delete(oldest.value);
|
|
35725
35725
|
}
|
|
35726
|
-
this.entries.set(
|
|
35726
|
+
this.entries.set(key2, { criteria, timestamp: getTimeProvider().now() });
|
|
35727
35727
|
}
|
|
35728
35728
|
get size() {
|
|
35729
35729
|
return this.entries.size;
|
|
@@ -37060,7 +37060,7 @@ var REASON_MAP = [
|
|
|
37060
37060
|
["needsExploration", "exploration/research task benefits from large context"]
|
|
37061
37061
|
];
|
|
37062
37062
|
function buildReasons(requirements, pref, billingMode = "api", specialization = null, chosenCli) {
|
|
37063
|
-
const reasons = REASON_MAP.filter(([
|
|
37063
|
+
const reasons = REASON_MAP.filter(([key2]) => requirements[key2] === true).map(([, desc]) => desc);
|
|
37064
37064
|
if (specialization !== null) {
|
|
37065
37065
|
if (chosenCli !== void 0 && specialization.primaryCli !== chosenCli) {
|
|
37066
37066
|
reasons.push(
|
|
@@ -38146,8 +38146,8 @@ function getSecuritySetupRegistry() {
|
|
|
38146
38146
|
}
|
|
38147
38147
|
|
|
38148
38148
|
// src/mcp/tools/run-graph-workflow-templates.ts
|
|
38149
|
-
function stateStrings(state,
|
|
38150
|
-
const val = state[
|
|
38149
|
+
function stateStrings(state, key2) {
|
|
38150
|
+
const val = state[key2];
|
|
38151
38151
|
return Array.isArray(val) ? val : [];
|
|
38152
38152
|
}
|
|
38153
38153
|
var WORKFLOW_METADATA = [
|
|
@@ -40211,8 +40211,8 @@ function failureResponse(focus, registry = "techniques") {
|
|
|
40211
40211
|
function countByKey(items, keyFn) {
|
|
40212
40212
|
const counts = {};
|
|
40213
40213
|
for (const item of items) {
|
|
40214
|
-
for (const
|
|
40215
|
-
counts[
|
|
40214
|
+
for (const key2 of keyFn(item)) {
|
|
40215
|
+
counts[key2] = (counts[key2] ?? 0) + 1;
|
|
40216
40216
|
}
|
|
40217
40217
|
}
|
|
40218
40218
|
return counts;
|
|
@@ -40387,8 +40387,8 @@ function countTechniqueStatuses(techniques, topic) {
|
|
|
40387
40387
|
for (const tech of Object.values(techniques)) {
|
|
40388
40388
|
if (topic !== void 0 && tech.topic !== topic) continue;
|
|
40389
40389
|
counts.total++;
|
|
40390
|
-
const
|
|
40391
|
-
if (
|
|
40390
|
+
const key2 = statusMap[tech.status];
|
|
40391
|
+
if (key2 !== void 0) counts[key2]++;
|
|
40392
40392
|
}
|
|
40393
40393
|
return counts;
|
|
40394
40394
|
}
|
|
@@ -41254,8 +41254,8 @@ function extractSections2(lines) {
|
|
|
41254
41254
|
}
|
|
41255
41255
|
function extractOverview(sections) {
|
|
41256
41256
|
const keys = ["overview", "goal", "description", "summary"];
|
|
41257
|
-
for (const
|
|
41258
|
-
const content = sections.get(
|
|
41257
|
+
for (const key2 of keys) {
|
|
41258
|
+
const content = sections.get(key2);
|
|
41259
41259
|
if (content !== void 0 && content.length > 0) {
|
|
41260
41260
|
return joinNonEmpty(content);
|
|
41261
41261
|
}
|
|
@@ -41266,8 +41266,8 @@ function extractOverview(sections) {
|
|
|
41266
41266
|
}
|
|
41267
41267
|
function extractListItems(sections, keys) {
|
|
41268
41268
|
const items = [];
|
|
41269
|
-
for (const
|
|
41270
|
-
const content = sections.get(
|
|
41269
|
+
for (const key2 of keys) {
|
|
41270
|
+
const content = sections.get(key2);
|
|
41271
41271
|
if (content === void 0) continue;
|
|
41272
41272
|
for (const line of content) {
|
|
41273
41273
|
const trimmed = line.trim();
|
|
@@ -42178,48 +42178,48 @@ var MemoryWriteInputSchema = z73.object({
|
|
|
42178
42178
|
metadata: z73.record(z73.string().max(100), z73.string().max(500)).optional().describe("Optional key-value metadata tags"),
|
|
42179
42179
|
sourceTrustTier: TrustTierSchema.optional().describe(SOURCE_TRUST_TIER_DESCRIPTION)
|
|
42180
42180
|
});
|
|
42181
|
-
function writeToSession(
|
|
42181
|
+
function writeToSession(key2, content, confidence, trustTier) {
|
|
42182
42182
|
const toolMemory = getToolMemory();
|
|
42183
42183
|
const numericConfidence = confidence === "high" ? 0.9 : confidence === "medium" ? 0.7 : 0.4;
|
|
42184
42184
|
const outcome = toolMemory.recordLearning({
|
|
42185
42185
|
pattern: content,
|
|
42186
|
-
context:
|
|
42186
|
+
context: key2,
|
|
42187
42187
|
confidence: numericConfidence,
|
|
42188
42188
|
source: "memory_write_tool",
|
|
42189
42189
|
...trustTier !== void 0 ? { trustTier } : {}
|
|
42190
42190
|
});
|
|
42191
42191
|
if (!outcome.persisted) {
|
|
42192
|
-
return { success: false, backend: "session", key, error: outcome.reason };
|
|
42192
|
+
return { success: false, backend: "session", key: key2, error: outcome.reason };
|
|
42193
42193
|
}
|
|
42194
|
-
return { success: true, backend: "session", key };
|
|
42194
|
+
return { success: true, backend: "session", key: key2 };
|
|
42195
42195
|
}
|
|
42196
|
-
async function writeToBelief(
|
|
42196
|
+
async function writeToBelief(key2, content, confidence, trustTier) {
|
|
42197
42197
|
const toolMemory = getToolMemory();
|
|
42198
42198
|
const countBefore = toolMemory.getBeliefCount();
|
|
42199
42199
|
const outcome = await toolMemory.recordBelief(
|
|
42200
|
-
|
|
42200
|
+
key2,
|
|
42201
42201
|
"has_knowledge",
|
|
42202
42202
|
content,
|
|
42203
42203
|
confidence,
|
|
42204
42204
|
trustTier
|
|
42205
42205
|
);
|
|
42206
42206
|
if (!outcome.persisted) {
|
|
42207
|
-
return { success: false, backend: "belief", key, error: outcome.reason };
|
|
42207
|
+
return { success: false, backend: "belief", key: key2, error: outcome.reason };
|
|
42208
42208
|
}
|
|
42209
42209
|
const deduplicated = toolMemory.getBeliefCount() === countBefore;
|
|
42210
|
-
return { success: true, backend: "belief", key, ...deduplicated ? { deduplicated: true } : {} };
|
|
42210
|
+
return { success: true, backend: "belief", key: key2, ...deduplicated ? { deduplicated: true } : {} };
|
|
42211
42211
|
}
|
|
42212
|
-
async function writeToAgentic(
|
|
42212
|
+
async function writeToAgentic(key2, content, confidence, metadata, trustTier) {
|
|
42213
42213
|
const toolMemory = getToolMemory();
|
|
42214
42214
|
if (!toolMemory.isAgenticMemoryAvailable()) {
|
|
42215
42215
|
return {
|
|
42216
42216
|
success: false,
|
|
42217
42217
|
backend: "agentic",
|
|
42218
|
-
key,
|
|
42218
|
+
key: key2,
|
|
42219
42219
|
error: "Agentic memory backend unavailable (requires SQLite)"
|
|
42220
42220
|
};
|
|
42221
42221
|
}
|
|
42222
|
-
const outcome = await toolMemory.recordKnowledge(
|
|
42222
|
+
const outcome = await toolMemory.recordKnowledge(key2, content, {
|
|
42223
42223
|
importance: confidence,
|
|
42224
42224
|
tags: [
|
|
42225
42225
|
...metadata !== void 0 ? Object.keys(metadata) : [],
|
|
@@ -42227,53 +42227,53 @@ async function writeToAgentic(key, content, confidence, metadata, trustTier) {
|
|
|
42227
42227
|
]
|
|
42228
42228
|
});
|
|
42229
42229
|
if (!outcome.persisted) {
|
|
42230
|
-
return { success: false, backend: "agentic", key, error: outcome.reason };
|
|
42230
|
+
return { success: false, backend: "agentic", key: key2, error: outcome.reason };
|
|
42231
42231
|
}
|
|
42232
|
-
return { success: true, backend: "agentic", key };
|
|
42232
|
+
return { success: true, backend: "agentic", key: key2 };
|
|
42233
42233
|
}
|
|
42234
|
-
async function writeToAdaptive(
|
|
42234
|
+
async function writeToAdaptive(key2, content, confidence, trustTier) {
|
|
42235
42235
|
const toolMemory = getToolMemory();
|
|
42236
42236
|
if (!toolMemory.isAdaptiveMemoryAvailable()) {
|
|
42237
42237
|
return {
|
|
42238
42238
|
success: false,
|
|
42239
42239
|
backend: "adaptive",
|
|
42240
|
-
key,
|
|
42240
|
+
key: key2,
|
|
42241
42241
|
error: "Adaptive memory backend unavailable (requires SQLite)"
|
|
42242
42242
|
};
|
|
42243
42243
|
}
|
|
42244
42244
|
const importance = confidence === "high" ? 0.9 : confidence === "medium" ? 0.7 : 0.5;
|
|
42245
42245
|
const outcome = await toolMemory.storeAdaptive(
|
|
42246
|
-
|
|
42246
|
+
key2,
|
|
42247
42247
|
content,
|
|
42248
42248
|
importance,
|
|
42249
42249
|
trustTier
|
|
42250
42250
|
);
|
|
42251
42251
|
if (!outcome.persisted) {
|
|
42252
|
-
return { success: false, backend: "adaptive", key, error: outcome.reason };
|
|
42252
|
+
return { success: false, backend: "adaptive", key: key2, error: outcome.reason };
|
|
42253
42253
|
}
|
|
42254
|
-
return { success: true, backend: "adaptive", key };
|
|
42254
|
+
return { success: true, backend: "adaptive", key: key2 };
|
|
42255
42255
|
}
|
|
42256
|
-
async function writeToTyped(
|
|
42256
|
+
async function writeToTyped(key2, content, confidence, trustTier) {
|
|
42257
42257
|
const toolMemory = getToolMemory();
|
|
42258
42258
|
if (!toolMemory.isTypedMemoryAvailable()) {
|
|
42259
42259
|
return {
|
|
42260
42260
|
success: false,
|
|
42261
42261
|
backend: "typed",
|
|
42262
|
-
key,
|
|
42262
|
+
key: key2,
|
|
42263
42263
|
error: "Typed memory backend unavailable (requires SQLite)"
|
|
42264
42264
|
};
|
|
42265
42265
|
}
|
|
42266
42266
|
const importance = confidence === "high" ? "high" : confidence === "medium" ? "medium" : "low";
|
|
42267
42267
|
const outcome = await toolMemory.storeTyped(
|
|
42268
|
-
|
|
42268
|
+
key2,
|
|
42269
42269
|
content,
|
|
42270
42270
|
importance,
|
|
42271
42271
|
trustTier
|
|
42272
42272
|
);
|
|
42273
42273
|
if (!outcome.persisted) {
|
|
42274
|
-
return { success: false, backend: "typed", key, error: outcome.reason };
|
|
42274
|
+
return { success: false, backend: "typed", key: key2, error: outcome.reason };
|
|
42275
42275
|
}
|
|
42276
|
-
return { success: true, backend: "typed", key };
|
|
42276
|
+
return { success: true, backend: "typed", key: key2 };
|
|
42277
42277
|
}
|
|
42278
42278
|
var recentWriteKeys = /* @__PURE__ */ new Map();
|
|
42279
42279
|
var MAX_DEDUP_CACHE = 200;
|
|
@@ -44572,12 +44572,12 @@ var FileAuditStorage = class _FileAuditStorage {
|
|
|
44572
44572
|
const data = this.writeBuffer.join("");
|
|
44573
44573
|
this.writeBuffer = [];
|
|
44574
44574
|
const stream = this.writeStream;
|
|
44575
|
-
return new Promise((
|
|
44575
|
+
return new Promise((resolve13, reject) => {
|
|
44576
44576
|
stream.write(data, (err2) => {
|
|
44577
44577
|
if (err2 !== void 0 && err2 !== null) {
|
|
44578
44578
|
reject(new AuditError("Failed to flush audit log", { cause: err2 }));
|
|
44579
44579
|
} else {
|
|
44580
|
-
|
|
44580
|
+
resolve13();
|
|
44581
44581
|
}
|
|
44582
44582
|
});
|
|
44583
44583
|
});
|
|
@@ -44638,15 +44638,15 @@ var FileAuditStorage = class _FileAuditStorage {
|
|
|
44638
44638
|
}
|
|
44639
44639
|
async close() {
|
|
44640
44640
|
await this.flush();
|
|
44641
|
-
return new Promise((
|
|
44641
|
+
return new Promise((resolve13) => {
|
|
44642
44642
|
if (this.writeStream === null) {
|
|
44643
|
-
|
|
44643
|
+
resolve13();
|
|
44644
44644
|
return;
|
|
44645
44645
|
}
|
|
44646
44646
|
this.writeStream.end(() => {
|
|
44647
44647
|
this.writeStream = null;
|
|
44648
44648
|
this.logger.info("Audit storage closed");
|
|
44649
|
-
|
|
44649
|
+
resolve13();
|
|
44650
44650
|
});
|
|
44651
44651
|
});
|
|
44652
44652
|
}
|
|
@@ -46077,8 +46077,8 @@ function buildError(templateId, error, startTime) {
|
|
|
46077
46077
|
error
|
|
46078
46078
|
};
|
|
46079
46079
|
}
|
|
46080
|
-
function extractStateValue(state,
|
|
46081
|
-
return state[
|
|
46080
|
+
function extractStateValue(state, key2) {
|
|
46081
|
+
return state[key2];
|
|
46082
46082
|
}
|
|
46083
46083
|
|
|
46084
46084
|
// src/pipeline/templates.ts
|
|
@@ -46682,7 +46682,7 @@ function buildVotingInput(plan, config) {
|
|
|
46682
46682
|
}
|
|
46683
46683
|
async function executeSingleVote(plan, config, log) {
|
|
46684
46684
|
try {
|
|
46685
|
-
const { executeVoting } = await import("./consensus-vote-
|
|
46685
|
+
const { executeVoting } = await import("./consensus-vote-36TUM35R.js");
|
|
46686
46686
|
const input = buildVotingInput(plan, config);
|
|
46687
46687
|
const result = await executeVoting(input, log);
|
|
46688
46688
|
return parseVotingResult(result);
|
|
@@ -46839,8 +46839,8 @@ async function recallPriorBeliefContext(bm, task, sessionId) {
|
|
|
46839
46839
|
try {
|
|
46840
46840
|
const records = [];
|
|
46841
46841
|
const seen = /* @__PURE__ */ new Set();
|
|
46842
|
-
for (const
|
|
46843
|
-
const result = await bm.getHindsightRecords(
|
|
46842
|
+
for (const key2 of pipelineHindsightKeys(task, sessionId)) {
|
|
46843
|
+
const result = await bm.getHindsightRecords(key2);
|
|
46844
46844
|
if (!result.ok) continue;
|
|
46845
46845
|
for (const rec of result.value) {
|
|
46846
46846
|
if (seen.has(rec.hindsightId)) continue;
|
|
@@ -47192,7 +47192,7 @@ function execFileTree(command, args, options) {
|
|
|
47192
47192
|
return Promise.reject(new AbortError(`${command} aborted before it started`));
|
|
47193
47193
|
}
|
|
47194
47194
|
const graceMs = options.graceMs ?? SIGKILL_GRACE_MS;
|
|
47195
|
-
return new Promise((
|
|
47195
|
+
return new Promise((resolve13, reject) => {
|
|
47196
47196
|
const run = {
|
|
47197
47197
|
settled: false,
|
|
47198
47198
|
child: void 0
|
|
@@ -47220,8 +47220,8 @@ function execFileTree(command, args, options) {
|
|
|
47220
47220
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
47221
47221
|
run.child = spawnTracked(command, args, options, (error, stdout, stderr) => {
|
|
47222
47222
|
finish(() => {
|
|
47223
|
-
if (error === null)
|
|
47224
|
-
else reject(error);
|
|
47223
|
+
if (error === null) resolve13({ stdout, stderr });
|
|
47224
|
+
else reject(Object.assign(error, { stdout, stderr }));
|
|
47225
47225
|
});
|
|
47226
47226
|
});
|
|
47227
47227
|
});
|
|
@@ -47628,6 +47628,7 @@ async function withDevPipelineWorkspace(stages, run, install = installDependenci
|
|
|
47628
47628
|
const dependencies = await provisionDependencies(scratch.path, install, sandbox.wrapper);
|
|
47629
47629
|
const bound = stages.withWorkspace({
|
|
47630
47630
|
directory: join13(scratch.path, relative4(repoRoot, directory)),
|
|
47631
|
+
baseline: { sha: baseSha, directory: repoRoot },
|
|
47631
47632
|
dependencies,
|
|
47632
47633
|
wrapper: sandbox.wrapper
|
|
47633
47634
|
});
|
|
@@ -47927,6 +47928,7 @@ async function runImplSecurityPhase(planResult, tasks, stages, run) {
|
|
|
47927
47928
|
qaIterations: implResult.totalIterations,
|
|
47928
47929
|
securityPassed: security.passed,
|
|
47929
47930
|
securityRan: security.verdict !== "skip",
|
|
47931
|
+
...security.comparison !== void 0 ? { securityComparison: security.comparison } : {},
|
|
47930
47932
|
taskStatus,
|
|
47931
47933
|
...security.verdict === "skip" ? { securityNote: security.feedback } : {},
|
|
47932
47934
|
...warnings
|
|
@@ -48282,8 +48284,8 @@ function recordRoutingExperience(category, success, durationMs, tokensUsed = 0,
|
|
|
48282
48284
|
// #3234: record the run's research-maturity (RECORD + measure; #3815 gates use).
|
|
48283
48285
|
...researchMaturity !== void 0 ? { researchMaturity } : {}
|
|
48284
48286
|
};
|
|
48285
|
-
const callRecord = (
|
|
48286
|
-
|
|
48287
|
+
const callRecord = (rm2) => {
|
|
48288
|
+
rm2.recordExperience(category, ["claude"], success, metrics);
|
|
48287
48289
|
};
|
|
48288
48290
|
if (routingMemoryCache !== null) {
|
|
48289
48291
|
callRecord(routingMemoryCache);
|
|
@@ -48298,8 +48300,8 @@ function recordRoutingExperience(category, success, durationMs, tokensUsed = 0,
|
|
|
48298
48300
|
logger44.debug("Routing memory init failed; continuing without it", { error: msg });
|
|
48299
48301
|
return null;
|
|
48300
48302
|
});
|
|
48301
|
-
void routingMemoryInitPromise.then((
|
|
48302
|
-
if (
|
|
48303
|
+
void routingMemoryInitPromise.then((rm2) => {
|
|
48304
|
+
if (rm2 !== null) callRecord(rm2);
|
|
48303
48305
|
});
|
|
48304
48306
|
}
|
|
48305
48307
|
|
|
@@ -48377,6 +48379,14 @@ function accessModeSignals(args) {
|
|
|
48377
48379
|
}
|
|
48378
48380
|
return [];
|
|
48379
48381
|
}
|
|
48382
|
+
function securityStageResult(result, passed) {
|
|
48383
|
+
return {
|
|
48384
|
+
passed,
|
|
48385
|
+
verdict: result.verdict,
|
|
48386
|
+
feedback: result.details,
|
|
48387
|
+
...result.comparison !== void 0 ? { comparison: result.comparison } : {}
|
|
48388
|
+
};
|
|
48389
|
+
}
|
|
48380
48390
|
function throwIfAborted2(signal, expertType) {
|
|
48381
48391
|
if (signal?.aborted !== true) return;
|
|
48382
48392
|
const reason = signal.reason;
|
|
@@ -48515,7 +48525,7 @@ function createVoteStage({ config, startStage }) {
|
|
|
48515
48525
|
const strategy = config.votingStrategy ?? "higher_order";
|
|
48516
48526
|
await postProgress(config, "Vote", `Running consensus with ${strategy} strategy...`);
|
|
48517
48527
|
try {
|
|
48518
|
-
const { executeVoting } = await import("./consensus-vote-
|
|
48528
|
+
const { executeVoting } = await import("./consensus-vote-36TUM35R.js");
|
|
48519
48529
|
const proposal = buildVoteProposal(plan, research);
|
|
48520
48530
|
const votingResult = await executeVoting(
|
|
48521
48531
|
{
|
|
@@ -48615,6 +48625,9 @@ Verdict: PASS/NEEDS_WORK/REJECT`;
|
|
|
48615
48625
|
};
|
|
48616
48626
|
}
|
|
48617
48627
|
|
|
48628
|
+
// src/mcp/tools/security-scan.ts
|
|
48629
|
+
import { z as z93 } from "zod";
|
|
48630
|
+
|
|
48618
48631
|
// src/security/sarif-parser.ts
|
|
48619
48632
|
import { z as z92 } from "zod";
|
|
48620
48633
|
var SarifLocationSchema = z92.object({
|
|
@@ -48623,7 +48636,11 @@ var SarifLocationSchema = z92.object({
|
|
|
48623
48636
|
region: z92.object({
|
|
48624
48637
|
startLine: z92.number().optional().catch(void 0),
|
|
48625
48638
|
endLine: z92.number().int().min(1).optional().catch(void 0),
|
|
48626
|
-
snippet: z92.object({
|
|
48639
|
+
snippet: z92.object({
|
|
48640
|
+
text: z92.string().optional().catch(void 0),
|
|
48641
|
+
// Unknown truncation metadata cannot establish a complete snippet.
|
|
48642
|
+
truncated: z92.boolean().optional().catch(true)
|
|
48643
|
+
}).optional().catch(void 0)
|
|
48627
48644
|
}).optional()
|
|
48628
48645
|
}).optional()
|
|
48629
48646
|
});
|
|
@@ -48654,7 +48671,18 @@ var SarifRunSchema = z92.object({
|
|
|
48654
48671
|
rules: z92.array(z92.unknown()).optional()
|
|
48655
48672
|
}).optional()
|
|
48656
48673
|
}).optional(),
|
|
48657
|
-
results: z92.array(z92.unknown()).nullish()
|
|
48674
|
+
results: z92.array(z92.unknown()).nullish(),
|
|
48675
|
+
invocations: z92.array(z92.unknown()).optional()
|
|
48676
|
+
});
|
|
48677
|
+
var SarifNotificationSchema = z92.object({
|
|
48678
|
+
descriptor: z92.object({ id: z92.string().optional() }).optional(),
|
|
48679
|
+
level: z92.string().optional(),
|
|
48680
|
+
message: z92.object({ text: z92.string().optional() }).optional()
|
|
48681
|
+
});
|
|
48682
|
+
var SarifInvocationSchema = z92.object({
|
|
48683
|
+
executionSuccessful: z92.boolean().optional(),
|
|
48684
|
+
toolExecutionNotifications: z92.array(SarifNotificationSchema).optional(),
|
|
48685
|
+
toolConfigurationNotifications: z92.array(SarifNotificationSchema).optional()
|
|
48658
48686
|
});
|
|
48659
48687
|
var SarifLogSchema = z92.object({
|
|
48660
48688
|
version: z92.string().optional(),
|
|
@@ -48685,7 +48713,7 @@ function parseSarif(sarifJson, maxFindings = 100) {
|
|
|
48685
48713
|
const errors = [];
|
|
48686
48714
|
const envelope = parseEnvelope(sarifJson);
|
|
48687
48715
|
if (!envelope.ok) {
|
|
48688
|
-
return
|
|
48716
|
+
return emptyResult(envelope.error);
|
|
48689
48717
|
}
|
|
48690
48718
|
return parseLog(envelope.log, maxFindings, errors);
|
|
48691
48719
|
}
|
|
@@ -48694,25 +48722,91 @@ function describeDriver(run) {
|
|
|
48694
48722
|
return { scanner: driver?.name ?? "unknown", rules: driver?.rules ?? [] };
|
|
48695
48723
|
}
|
|
48696
48724
|
function emptyResult(error) {
|
|
48697
|
-
return {
|
|
48725
|
+
return {
|
|
48726
|
+
scanner: "unknown",
|
|
48727
|
+
totalFindings: 0,
|
|
48728
|
+
findings: [],
|
|
48729
|
+
errors: [error],
|
|
48730
|
+
coverageComplete: false
|
|
48731
|
+
};
|
|
48698
48732
|
}
|
|
48699
48733
|
function parseLog(log, maxFindings, errors) {
|
|
48700
48734
|
const runs = log.runs;
|
|
48701
48735
|
if (runs === void 0 || runs.length === 0) return emptyResult("No runs in SARIF");
|
|
48702
|
-
|
|
48703
|
-
|
|
48704
|
-
|
|
48736
|
+
let scanner = "unknown";
|
|
48737
|
+
const parseDiagnostics = [];
|
|
48738
|
+
const findings = [];
|
|
48739
|
+
for (const [index, raw] of runs.entries()) {
|
|
48740
|
+
const parsedRun = SarifRunSchema.safeParse(raw);
|
|
48741
|
+
if (!parsedRun.success) {
|
|
48742
|
+
errors.push(`Malformed SARIF run ${String(index)}: ${describeZodError(parsedRun.error)}`);
|
|
48743
|
+
continue;
|
|
48744
|
+
}
|
|
48745
|
+
const driver = describeDriver(parsedRun.data);
|
|
48746
|
+
checkRunCoverage(parsedRun.data, errors);
|
|
48747
|
+
if (index === 0) scanner = driver.scanner;
|
|
48748
|
+
checkInvocations(parsedRun.data.invocations ?? [], errors, parseDiagnostics);
|
|
48749
|
+
const ruleMap = buildRuleMap(driver.rules, errors);
|
|
48750
|
+
findings.push(
|
|
48751
|
+
...collectFindings(parsedRun.data.results ?? [], driver.scanner, ruleMap, errors)
|
|
48752
|
+
);
|
|
48753
|
+
}
|
|
48754
|
+
findings.sort((a, b) => SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity]);
|
|
48755
|
+
if (findings.length > maxFindings) {
|
|
48756
|
+
errors.push(
|
|
48757
|
+
`Truncated findings: returned ${String(maxFindings)} of ${String(findings.length)}`
|
|
48758
|
+
);
|
|
48705
48759
|
}
|
|
48706
|
-
const { scanner, rules } = describeDriver(parsedRun.data);
|
|
48707
|
-
const ruleMap = buildRuleMap(rules, errors);
|
|
48708
|
-
const findings = collectFindings(parsedRun.data.results ?? [], scanner, ruleMap, errors);
|
|
48709
48760
|
return {
|
|
48710
48761
|
scanner,
|
|
48711
48762
|
totalFindings: findings.length,
|
|
48712
48763
|
findings: findings.slice(0, maxFindings),
|
|
48713
|
-
errors
|
|
48764
|
+
errors,
|
|
48765
|
+
coverageComplete: errors.length === 0,
|
|
48766
|
+
...parseDiagnostics.length > 0 ? { parseDiagnostics } : {}
|
|
48714
48767
|
};
|
|
48715
48768
|
}
|
|
48769
|
+
function checkRunCoverage(run, errors) {
|
|
48770
|
+
if (run.tool?.driver?.name === void 0 || run.tool.driver.name.length === 0) {
|
|
48771
|
+
errors.push("SARIF run missing scanner identity");
|
|
48772
|
+
}
|
|
48773
|
+
if (run.results === void 0 || run.results === null) {
|
|
48774
|
+
errors.push("SARIF run missing measured results");
|
|
48775
|
+
}
|
|
48776
|
+
}
|
|
48777
|
+
function checkInvocations(invocations, errors, parseDiagnostics) {
|
|
48778
|
+
for (const raw of invocations) {
|
|
48779
|
+
const parsed = SarifInvocationSchema.safeParse(raw);
|
|
48780
|
+
if (!parsed.success) {
|
|
48781
|
+
errors.push(`Malformed SARIF invocation: ${describeZodError(parsed.error)}`);
|
|
48782
|
+
continue;
|
|
48783
|
+
}
|
|
48784
|
+
if (parsed.data.executionSuccessful === false) errors.push("Scanner invocation failed");
|
|
48785
|
+
const notifications = [
|
|
48786
|
+
...parsed.data.toolExecutionNotifications ?? [],
|
|
48787
|
+
...parsed.data.toolConfigurationNotifications ?? []
|
|
48788
|
+
];
|
|
48789
|
+
checkNotifications(notifications, errors, parseDiagnostics);
|
|
48790
|
+
}
|
|
48791
|
+
}
|
|
48792
|
+
function checkNotifications(notifications, errors, parseDiagnostics) {
|
|
48793
|
+
for (const notification of notifications ?? []) {
|
|
48794
|
+
const diagnostic = parseNotification(notification);
|
|
48795
|
+
if (diagnostic !== void 0) parseDiagnostics.push(diagnostic);
|
|
48796
|
+
else if (notification.level !== "note" && notification.level !== "none")
|
|
48797
|
+
errors.push(`Scanner notification: ${notification.message?.text ?? "unknown scanner error"}`);
|
|
48798
|
+
}
|
|
48799
|
+
}
|
|
48800
|
+
function parseNotification(notification) {
|
|
48801
|
+
if (!/^(?:Syntax error|Other syntax error)$/.test(notification.descriptor?.id ?? ""))
|
|
48802
|
+
return void 0;
|
|
48803
|
+
const message = notification.message?.text;
|
|
48804
|
+
if (message === void 0) return void 0;
|
|
48805
|
+
const file = /^(?:Syntax error|Other syntax error) at line (.+):(\d+):(?:\n|$| )/.exec(
|
|
48806
|
+
message
|
|
48807
|
+
)?.[1];
|
|
48808
|
+
return file === void 0 ? void 0 : { file, kind: "parse", message };
|
|
48809
|
+
}
|
|
48716
48810
|
function collectFindings(results, scanner, ruleMap, errors) {
|
|
48717
48811
|
const findings = [];
|
|
48718
48812
|
for (const [index, raw] of results.entries()) {
|
|
@@ -48751,7 +48845,8 @@ function buildLocation(file, startLine, phys) {
|
|
|
48751
48845
|
const endLine = phys.region?.endLine;
|
|
48752
48846
|
const snippetText = phys.region?.snippet?.text;
|
|
48753
48847
|
if (endLine !== void 0) loc.endLine = endLine;
|
|
48754
|
-
if (snippetText !== void 0) loc.snippet = snippetText
|
|
48848
|
+
if (snippetText !== void 0) loc.snippet = snippetText;
|
|
48849
|
+
if (phys.region?.snippet?.truncated === true) loc.snippetTruncated = true;
|
|
48755
48850
|
return loc;
|
|
48756
48851
|
}
|
|
48757
48852
|
function extractLocation(result, ruleId, errors) {
|
|
@@ -48807,6 +48902,7 @@ function parseResult(result, scanner, ruleMap, errors) {
|
|
|
48807
48902
|
cweIds: extractCweIds(rule),
|
|
48808
48903
|
confidence: resolveConfidence(rule),
|
|
48809
48904
|
snippet: loc.snippet,
|
|
48905
|
+
snippetTruncated: loc.snippetTruncated,
|
|
48810
48906
|
helpUrl: rule?.helpUri
|
|
48811
48907
|
};
|
|
48812
48908
|
}
|
|
@@ -48857,25 +48953,46 @@ function resolveConfidence(rule) {
|
|
|
48857
48953
|
}
|
|
48858
48954
|
|
|
48859
48955
|
// src/mcp/tools/security-scan.ts
|
|
48956
|
+
import { access, constants as constants2 } from "node:fs/promises";
|
|
48957
|
+
import { readFile as readFile5, realpath as realpath2, writeFile as writeFile2 } from "node:fs/promises";
|
|
48958
|
+
import { delimiter as delimiter2, isAbsolute as isAbsolute6, join as join14, parse as parse4, resolve as resolve8 } from "node:path";
|
|
48860
48959
|
var logger47 = createLogger({ component: "security-scan" });
|
|
48861
48960
|
var SCAN_TIMEOUT_MS = 3e5;
|
|
48862
|
-
async function isSemgrepAvailable(signal, env, wrapper) {
|
|
48961
|
+
async function isSemgrepAvailable(signal, env, wrapper, binary = "semgrep", cwd) {
|
|
48863
48962
|
try {
|
|
48864
|
-
await execFileTree(
|
|
48865
|
-
|
|
48963
|
+
const { stdout } = await execFileTree(binary, ["--version"], {
|
|
48964
|
+
timeoutMs: 1e4,
|
|
48965
|
+
signal,
|
|
48966
|
+
env,
|
|
48967
|
+
wrapper,
|
|
48968
|
+
cwd
|
|
48969
|
+
});
|
|
48970
|
+
return stdout.trim() || void 0;
|
|
48866
48971
|
} catch {
|
|
48867
|
-
return
|
|
48972
|
+
return void 0;
|
|
48868
48973
|
}
|
|
48869
48974
|
}
|
|
48870
|
-
async function runSemgrep(targetDir, rulesets, signal, env,
|
|
48871
|
-
const
|
|
48872
|
-
const
|
|
48975
|
+
async function runSemgrep(targetDir, rulesets, signal, env, options) {
|
|
48976
|
+
const prepared = options.preparedScan;
|
|
48977
|
+
const flags = prepared?.flags ?? (options.completeResults === true ? COMPLETE_SCAN_FLAGS : []);
|
|
48978
|
+
const configs = prepared?.rulesets ?? rulesets.map(
|
|
48979
|
+
(ruleset) => /^(?:[pr]\/|https?:\/\/|auto$)/.test(ruleset) ? ruleset : resolve8(ruleset)
|
|
48980
|
+
);
|
|
48981
|
+
const args = [
|
|
48982
|
+
"--sarif",
|
|
48983
|
+
"--quiet",
|
|
48984
|
+
...flags,
|
|
48985
|
+
...configs.flatMap((r) => ["--config", r]),
|
|
48986
|
+
targetDir
|
|
48987
|
+
];
|
|
48988
|
+
const { stdout } = await execFileTree(prepared?.binary ?? "semgrep", args, {
|
|
48989
|
+
cwd: parse4(targetDir).root,
|
|
48873
48990
|
timeoutMs: SCAN_TIMEOUT_MS,
|
|
48874
48991
|
maxBuffer: 10 * 1024 * 1024,
|
|
48875
48992
|
// 10MB for large SARIF output
|
|
48876
48993
|
signal,
|
|
48877
48994
|
env,
|
|
48878
|
-
wrapper
|
|
48995
|
+
wrapper: options.wrapper
|
|
48879
48996
|
});
|
|
48880
48997
|
return stdout;
|
|
48881
48998
|
}
|
|
@@ -48886,6 +49003,105 @@ function validateTargetPath(target, root = process.cwd()) {
|
|
|
48886
49003
|
}
|
|
48887
49004
|
return resolved;
|
|
48888
49005
|
}
|
|
49006
|
+
var COMPLETE_SCAN_FLAGS = [
|
|
49007
|
+
"--no-git-ignore",
|
|
49008
|
+
"--max-target-bytes=0",
|
|
49009
|
+
"--metrics=off",
|
|
49010
|
+
"--disable-nosem",
|
|
49011
|
+
"--no-rewrite-rule-ids",
|
|
49012
|
+
// Avoid mutable ignore files and hidden-ancestor skips in scratch worktrees.
|
|
49013
|
+
// Unsupported scanner versions fail closed on this explicitly pinned flag.
|
|
49014
|
+
"--x-ignore-semgrepignore-files",
|
|
49015
|
+
"--exclude=node_modules",
|
|
49016
|
+
"--exclude=.git"
|
|
49017
|
+
];
|
|
49018
|
+
async function resolveSemgrep(env) {
|
|
49019
|
+
for (const directory of (env["PATH"] ?? "").split(delimiter2)) {
|
|
49020
|
+
if (!isAbsolute6(directory)) continue;
|
|
49021
|
+
const binary = join14(directory, process.platform === "win32" ? "semgrep.exe" : "semgrep");
|
|
49022
|
+
try {
|
|
49023
|
+
await access(binary, constants2.X_OK);
|
|
49024
|
+
return await realpath2(binary);
|
|
49025
|
+
} catch {
|
|
49026
|
+
}
|
|
49027
|
+
}
|
|
49028
|
+
throw new Error("semgrep is not installed. Install with: pip install semgrep");
|
|
49029
|
+
}
|
|
49030
|
+
async function readRuleset(ruleset, signal) {
|
|
49031
|
+
const url = /^[pr]\//.test(ruleset) ? `https://semgrep.dev/c/${ruleset}` : ruleset;
|
|
49032
|
+
if (!/^https?:\/\//.test(url)) return await readFile5(resolve8(ruleset), "utf8");
|
|
49033
|
+
const timeout = AbortSignal.timeout(3e4);
|
|
49034
|
+
const response = await fetch(url, {
|
|
49035
|
+
headers: { Accept: "application/json" },
|
|
49036
|
+
signal: signal === void 0 ? timeout : AbortSignal.any([signal, timeout])
|
|
49037
|
+
});
|
|
49038
|
+
if (!response.ok) throw new Error(`Ruleset download failed: HTTP ${String(response.status)}`);
|
|
49039
|
+
const text = await response.text();
|
|
49040
|
+
if (text.length > 10 * 1024 * 1024) throw new Error("Ruleset download exceeds 10MB");
|
|
49041
|
+
return unwrapRuleset(text);
|
|
49042
|
+
}
|
|
49043
|
+
function unwrapRuleset(text) {
|
|
49044
|
+
let raw;
|
|
49045
|
+
try {
|
|
49046
|
+
raw = JSON.parse(text);
|
|
49047
|
+
} catch {
|
|
49048
|
+
return text;
|
|
49049
|
+
}
|
|
49050
|
+
if (typeof raw === "object" && raw !== null && "rule_config" in raw) {
|
|
49051
|
+
const config = raw.rule_config;
|
|
49052
|
+
return typeof config === "string" ? config : JSON.stringify(config);
|
|
49053
|
+
}
|
|
49054
|
+
return text;
|
|
49055
|
+
}
|
|
49056
|
+
async function measureScannerVersion(options, targetDir) {
|
|
49057
|
+
const version = await isSemgrepAvailable(
|
|
49058
|
+
options.signal,
|
|
49059
|
+
options.env,
|
|
49060
|
+
options.wrapper,
|
|
49061
|
+
options.preparedScan?.binary,
|
|
49062
|
+
parse4(targetDir).root
|
|
49063
|
+
);
|
|
49064
|
+
if (options.signal?.aborted === true) return { error: "Scan aborted before semgrep ran" };
|
|
49065
|
+
if (version === void 0)
|
|
49066
|
+
return { error: "semgrep is not installed. Install with: pip install semgrep" };
|
|
49067
|
+
if (options.preparedScan !== void 0 && options.preparedScan.version !== version) {
|
|
49068
|
+
return {
|
|
49069
|
+
error: `Scanner version changed: expected ${options.preparedScan.version}, got ${version}`
|
|
49070
|
+
};
|
|
49071
|
+
}
|
|
49072
|
+
return version;
|
|
49073
|
+
}
|
|
49074
|
+
async function prepareSecurityScan(rulesets, options) {
|
|
49075
|
+
try {
|
|
49076
|
+
if (rulesets.length === 0) throw new Error("No security rulesets configured");
|
|
49077
|
+
const binary = await resolveSemgrep(options.env ?? process.env);
|
|
49078
|
+
const version = await isSemgrepAvailable(
|
|
49079
|
+
options.signal,
|
|
49080
|
+
options.env,
|
|
49081
|
+
options.wrapper,
|
|
49082
|
+
binary,
|
|
49083
|
+
parse4(resolve8(options.directory)).root
|
|
49084
|
+
);
|
|
49085
|
+
if (version === void 0) throw new Error("Cannot measure semgrep version");
|
|
49086
|
+
const configs = [];
|
|
49087
|
+
for (const [index, ruleset] of rulesets.entries()) {
|
|
49088
|
+
const contents = await readRuleset(ruleset, options.signal);
|
|
49089
|
+
const file = join14(options.directory, `security-rules-${String(index)}.yaml`);
|
|
49090
|
+
await writeFile2(file, contents, { mode: 256, flag: "wx" });
|
|
49091
|
+
configs.push(file);
|
|
49092
|
+
}
|
|
49093
|
+
return Object.freeze({
|
|
49094
|
+
binary,
|
|
49095
|
+
version,
|
|
49096
|
+
rulesets: Object.freeze(configs),
|
|
49097
|
+
flags: COMPLETE_SCAN_FLAGS
|
|
49098
|
+
});
|
|
49099
|
+
} catch (error) {
|
|
49100
|
+
return {
|
|
49101
|
+
error: `Security scan preparation failed: ${error instanceof Error ? error.message : String(error)}`
|
|
49102
|
+
};
|
|
49103
|
+
}
|
|
49104
|
+
}
|
|
48889
49105
|
async function executeSecurityScan(input, options = {}) {
|
|
48890
49106
|
const { signal, env } = options;
|
|
48891
49107
|
let targetDir;
|
|
@@ -48899,42 +49115,104 @@ async function executeSecurityScan(input, options = {}) {
|
|
|
48899
49115
|
scanner: input.scanner,
|
|
48900
49116
|
rulesets: input.rulesets
|
|
48901
49117
|
});
|
|
48902
|
-
const
|
|
48903
|
-
if (
|
|
48904
|
-
if (!available) {
|
|
48905
|
-
return {
|
|
48906
|
-
error: "semgrep is not installed. Install with: pip install semgrep"
|
|
48907
|
-
};
|
|
48908
|
-
}
|
|
49118
|
+
const version = await measureScannerVersion(options, targetDir);
|
|
49119
|
+
if (typeof version !== "string") return version;
|
|
48909
49120
|
try {
|
|
48910
|
-
const sarifOutput = await runSemgrep(targetDir, input.rulesets, signal, env, options
|
|
48911
|
-
const result = parseSarif(
|
|
49121
|
+
const sarifOutput = await runSemgrep(targetDir, input.rulesets, signal, env, options);
|
|
49122
|
+
const result = parseSarif(
|
|
49123
|
+
sarifOutput,
|
|
49124
|
+
options.completeResults === true ? Infinity : input.maxFindings
|
|
49125
|
+
);
|
|
48912
49126
|
logger47.info("Security scan completed", {
|
|
48913
49127
|
scanner: result.scanner,
|
|
48914
49128
|
findings: result.totalFindings,
|
|
48915
49129
|
errors: result.errors.length
|
|
48916
49130
|
});
|
|
48917
|
-
return result;
|
|
49131
|
+
return { ...result, scannerVersion: version };
|
|
48918
49132
|
} catch (error) {
|
|
48919
|
-
|
|
48920
|
-
|
|
48921
|
-
|
|
49133
|
+
return handleScanFailure(
|
|
49134
|
+
error,
|
|
49135
|
+
version,
|
|
49136
|
+
options.completeResults === true ? Infinity : input.maxFindings
|
|
49137
|
+
);
|
|
48922
49138
|
}
|
|
48923
49139
|
}
|
|
49140
|
+
var InvocationSuccessSchema = z93.object({
|
|
49141
|
+
runs: z93.array(
|
|
49142
|
+
z93.object({
|
|
49143
|
+
invocations: z93.array(z93.object({ executionSuccessful: z93.literal(true) })).min(1)
|
|
49144
|
+
})
|
|
49145
|
+
).min(1)
|
|
49146
|
+
});
|
|
49147
|
+
function failureCode(error) {
|
|
49148
|
+
return typeof error === "object" && error !== null && "code" in error ? error.code : "unknown";
|
|
49149
|
+
}
|
|
49150
|
+
function failureOutput(error) {
|
|
49151
|
+
if (typeof error !== "object" || error === null || !("stdout" in error)) return void 0;
|
|
49152
|
+
return typeof error.stdout === "string" && error.stdout.length > 0 ? error.stdout : void 0;
|
|
49153
|
+
}
|
|
49154
|
+
function scannerInvocationsSuccessful(output2) {
|
|
49155
|
+
try {
|
|
49156
|
+
return InvocationSuccessSchema.safeParse(JSON.parse(output2)).success;
|
|
49157
|
+
} catch {
|
|
49158
|
+
return false;
|
|
49159
|
+
}
|
|
49160
|
+
}
|
|
49161
|
+
function handleScanFailure(error, version, maxFindings) {
|
|
49162
|
+
const output2 = failureOutput(error);
|
|
49163
|
+
const result = output2 === void 0 ? void 0 : parseSarif(output2, maxFindings);
|
|
49164
|
+
if (result !== void 0 && output2 !== void 0 && failureCode(error) === 3) {
|
|
49165
|
+
if (result.coverageComplete === true && (result.parseDiagnostics?.length ?? 0) > 0 && scannerInvocationsSuccessful(output2)) {
|
|
49166
|
+
return { ...result, scannerVersion: version };
|
|
49167
|
+
}
|
|
49168
|
+
}
|
|
49169
|
+
const message = `${summarizeScanFailure(error)}${failedOutputDetails(result)}`;
|
|
49170
|
+
logger47.warn("Security scan failed", { error: message });
|
|
49171
|
+
return { error: message };
|
|
49172
|
+
}
|
|
49173
|
+
function failedOutputDetails(result) {
|
|
49174
|
+
if (result === void 0) return "";
|
|
49175
|
+
const files = result.parseDiagnostics?.map((diagnostic) => diagnostic.file) ?? [];
|
|
49176
|
+
const diagnostics = files.length > 0 ? `; affected files: ${[...new Set(files)].join(", ")}` : "";
|
|
49177
|
+
const errors = result.errors.length > 0 ? `; ${result.errors.join("; ")}` : "";
|
|
49178
|
+
return diagnostics + errors;
|
|
49179
|
+
}
|
|
49180
|
+
function summarizeScanFailure(error) {
|
|
49181
|
+
const code = String(failureCode(error));
|
|
49182
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
49183
|
+
const commandFailure = message.startsWith("Command failed:");
|
|
49184
|
+
const newline = message.indexOf("\n");
|
|
49185
|
+
const rawDiagnostic = commandFailure && newline >= 0 ? message.slice(newline + 1) : message;
|
|
49186
|
+
const diagnostic = rawDiagnostic.split("\n").filter((line) => !isScannerNoise(line)).join("\n");
|
|
49187
|
+
const detail = diagnostic.length > 500 ? `[diagnostic truncated] ${diagnostic.slice(-500)}` : diagnostic;
|
|
49188
|
+
const files = [
|
|
49189
|
+
...new Set(
|
|
49190
|
+
[...diagnostic.matchAll(/^(?:Syntax error|Other syntax error) at line (.+):\d+:/gm)].map(
|
|
49191
|
+
(match) => match[1]
|
|
49192
|
+
)
|
|
49193
|
+
)
|
|
49194
|
+
];
|
|
49195
|
+
const affected = files.length > 0 ? `; affected files: ${files.join(", ")}` : "";
|
|
49196
|
+
const unavailable = commandFailure && failureOutput(error) === void 0 ? "; scanner stdout unavailable" : "";
|
|
49197
|
+
return `Scan failed (exit ${code}${unavailable}${affected}): ${detail}`;
|
|
49198
|
+
}
|
|
49199
|
+
function isScannerNoise(line) {
|
|
49200
|
+
return /opentelemetry\/instrumentation\/dependencies\.py.*UserWarning: pkg_resources/.test(line) || /^\s*from pkg_resources import \(/.test(line) || /^pyenv: (?:cannot rehash|warning:)/.test(line) || /^.*WARNING.*(?:experimental|--x-).*$/i.test(line) || /^.*These options are not part of the semgrep API.*$/.test(line);
|
|
49201
|
+
}
|
|
48924
49202
|
|
|
48925
49203
|
// src/security/osv-lookup.ts
|
|
48926
|
-
import { z as
|
|
49204
|
+
import { z as z94 } from "zod";
|
|
48927
49205
|
var logger48 = createLogger({ component: "osv-lookup" });
|
|
48928
49206
|
var OSV_API_URL = "https://api.osv.dev/v1/query";
|
|
48929
49207
|
var DEFAULT_TIMEOUT_MS4 = NETWORK_FETCH_TIMEOUT_MS;
|
|
48930
|
-
var OsvVulnerabilitySchema =
|
|
48931
|
-
id:
|
|
48932
|
-
summary:
|
|
48933
|
-
severity:
|
|
48934
|
-
aliases:
|
|
48935
|
-
affectedVersions:
|
|
48936
|
-
fixedVersion:
|
|
48937
|
-
url:
|
|
49208
|
+
var OsvVulnerabilitySchema = z94.object({
|
|
49209
|
+
id: z94.string(),
|
|
49210
|
+
summary: z94.string().optional(),
|
|
49211
|
+
severity: z94.enum(["CRITICAL", "HIGH", "MODERATE", "LOW", "UNKNOWN"]).optional(),
|
|
49212
|
+
aliases: z94.array(z94.string()).default([]),
|
|
49213
|
+
affectedVersions: z94.string().optional(),
|
|
49214
|
+
fixedVersion: z94.string().optional(),
|
|
49215
|
+
url: z94.string().optional()
|
|
48938
49216
|
});
|
|
48939
49217
|
var DEFAULT_OSV_CONFIG = {
|
|
48940
49218
|
timeoutMs: DEFAULT_TIMEOUT_MS4
|
|
@@ -49026,11 +49304,343 @@ async function queryOsvBatch(packages, config = DEFAULT_OSV_CONFIG, signal) {
|
|
|
49026
49304
|
return results;
|
|
49027
49305
|
}
|
|
49028
49306
|
|
|
49307
|
+
// src/pipeline/security-baseline.ts
|
|
49308
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
49309
|
+
import { mkdtemp, rm, readFile as readFile7, readlink } from "node:fs/promises";
|
|
49310
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
49311
|
+
import { isAbsolute as isAbsolute8, join as join16 } from "node:path";
|
|
49312
|
+
|
|
49313
|
+
// src/pipeline/security-baseline-coverage.ts
|
|
49314
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
49315
|
+
import { isAbsolute as isAbsolute7, join as join15, relative as relative6 } from "node:path";
|
|
49316
|
+
function scanErrors(scan, side) {
|
|
49317
|
+
if ("error" in scan) return [`${side}: ${scan.error}`];
|
|
49318
|
+
const errors = scan.errors.map((error) => `${side}: ${error}`);
|
|
49319
|
+
if (scan.coverageComplete !== true || scan.totalFindings !== scan.findings.length)
|
|
49320
|
+
errors.push(`${side}: scan coverage is incomplete`);
|
|
49321
|
+
for (const finding of scan.findings) {
|
|
49322
|
+
if (isAbsolute7(finding.file) || finding.file.split("/").includes("..") || /^[a-z]+:/i.test(finding.file))
|
|
49323
|
+
errors.push(`${side}: finding path outside scanned tree: ${finding.file}`);
|
|
49324
|
+
if (ambiguousSnippet(finding))
|
|
49325
|
+
errors.push(
|
|
49326
|
+
`${side}: missing or truncated snippet: ${finding.rule} ${finding.file}:${String(finding.startLine)}`
|
|
49327
|
+
);
|
|
49328
|
+
}
|
|
49329
|
+
return errors;
|
|
49330
|
+
}
|
|
49331
|
+
function normalizedScan(scan, directory) {
|
|
49332
|
+
if ("error" in scan) return scan;
|
|
49333
|
+
return {
|
|
49334
|
+
...scan,
|
|
49335
|
+
parseDiagnostics: (scan.parseDiagnostics ?? []).map((diagnostic) => ({
|
|
49336
|
+
...diagnostic,
|
|
49337
|
+
file: isAbsolute7(diagnostic.file) ? relative6(directory, diagnostic.file) : diagnostic.file.replace(/^\.\//, ""),
|
|
49338
|
+
message: diagnostic.message.split(join15(directory, "/")).join("")
|
|
49339
|
+
})),
|
|
49340
|
+
findings: scan.findings.map((finding) => ({
|
|
49341
|
+
...finding,
|
|
49342
|
+
file: isAbsolute7(finding.file) ? relative6(directory, finding.file) : finding.file.replace(/^\.\//, "")
|
|
49343
|
+
}))
|
|
49344
|
+
};
|
|
49345
|
+
}
|
|
49346
|
+
function ambiguousSnippet(finding) {
|
|
49347
|
+
return finding.snippet === void 0 || finding.snippet.trim() === "" || finding.snippetTruncated === true;
|
|
49348
|
+
}
|
|
49349
|
+
async function compareParseCoverage(input) {
|
|
49350
|
+
const base = input.base.parseDiagnostics ?? [];
|
|
49351
|
+
const worktree = input.worktree.parseDiagnostics ?? [];
|
|
49352
|
+
const files = [...new Set([...base, ...worktree].map((diagnostic) => diagnostic.file))].sort();
|
|
49353
|
+
const errors = [];
|
|
49354
|
+
const unscannedCoverage = [];
|
|
49355
|
+
for (const file of files) {
|
|
49356
|
+
if (outsideTree(file)) {
|
|
49357
|
+
errors.push(`Parse diagnostic path outside scanned tree: ${file}`);
|
|
49358
|
+
continue;
|
|
49359
|
+
}
|
|
49360
|
+
const identities = (diagnostics) => JSON.stringify(
|
|
49361
|
+
diagnostics.filter((d) => d.file === file).map(({ kind, message }) => JSON.stringify([kind, message])).sort()
|
|
49362
|
+
);
|
|
49363
|
+
if (identities(base) !== identities(worktree)) {
|
|
49364
|
+
errors.push(`New or changed parse diagnostics: ${file}`);
|
|
49365
|
+
continue;
|
|
49366
|
+
}
|
|
49367
|
+
try {
|
|
49368
|
+
const [oldBytes, newBytes, diff] = await Promise.all([
|
|
49369
|
+
readFile6(join15(input.baseDirectory, file)),
|
|
49370
|
+
readFile6(join15(input.target, file)),
|
|
49371
|
+
input.diff(file)
|
|
49372
|
+
]);
|
|
49373
|
+
if (!oldBytes.equals(newBytes) || diff !== "") {
|
|
49374
|
+
errors.push(`Change touches partially parsed file: ${file}`);
|
|
49375
|
+
} else unscannedCoverage.push(file);
|
|
49376
|
+
} catch (error) {
|
|
49377
|
+
errors.push(
|
|
49378
|
+
`Cannot verify partially parsed file ${file}: ${error instanceof Error ? error.message : String(error)}`
|
|
49379
|
+
);
|
|
49380
|
+
}
|
|
49381
|
+
}
|
|
49382
|
+
return { errors, unscannedCoverage };
|
|
49383
|
+
}
|
|
49384
|
+
function outsideTree(file) {
|
|
49385
|
+
return isAbsolute7(file) || file.split("/").includes("..") || /^[a-z]+:/i.test(file);
|
|
49386
|
+
}
|
|
49387
|
+
|
|
49388
|
+
// src/pipeline/security-baseline.ts
|
|
49389
|
+
var blocking = (finding) => finding.severity === "critical" || finding.severity === "high";
|
|
49390
|
+
function key(finding) {
|
|
49391
|
+
return JSON.stringify([finding.rule, finding.file, finding.snippet?.replace(/\s+/g, " ").trim()]);
|
|
49392
|
+
}
|
|
49393
|
+
function preservedLine(finding, diff) {
|
|
49394
|
+
let offset = 0;
|
|
49395
|
+
for (const match of diff.matchAll(/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/gm)) {
|
|
49396
|
+
const oldStart = Number(match[1]);
|
|
49397
|
+
const oldCount = Number(match[2] ?? 1);
|
|
49398
|
+
const newCount = Number(match[4] ?? 1);
|
|
49399
|
+
const oldEnd = oldStart + oldCount - 1;
|
|
49400
|
+
if (oldCount > 0 && finding.startLine <= oldEnd && (finding.endLine ?? finding.startLine) >= oldStart)
|
|
49401
|
+
return void 0;
|
|
49402
|
+
if ((oldCount === 0 ? oldStart : oldEnd) < finding.startLine) offset += newCount - oldCount;
|
|
49403
|
+
}
|
|
49404
|
+
return finding.startLine + offset;
|
|
49405
|
+
}
|
|
49406
|
+
async function introducedFindings(base, worktree, git2, target, sha) {
|
|
49407
|
+
const diffs = /* @__PURE__ */ new Map();
|
|
49408
|
+
for (const file of new Set(base.map((finding) => finding.file))) {
|
|
49409
|
+
if (isAbsolute8(file) || file.split("/").includes(".."))
|
|
49410
|
+
throw new Error("Finding path outside scanned tree");
|
|
49411
|
+
diffs.set(
|
|
49412
|
+
file,
|
|
49413
|
+
await git2(target, [
|
|
49414
|
+
"diff",
|
|
49415
|
+
"--text",
|
|
49416
|
+
"--no-color",
|
|
49417
|
+
"--no-ext-diff",
|
|
49418
|
+
"--no-textconv",
|
|
49419
|
+
"--no-renames",
|
|
49420
|
+
"--unified=0",
|
|
49421
|
+
sha,
|
|
49422
|
+
"--",
|
|
49423
|
+
file
|
|
49424
|
+
])
|
|
49425
|
+
);
|
|
49426
|
+
}
|
|
49427
|
+
const remaining = [...base];
|
|
49428
|
+
const result = [];
|
|
49429
|
+
for (const finding of worktree) {
|
|
49430
|
+
const index = remaining.findIndex(
|
|
49431
|
+
(old) => key(old) === key(finding) && preservedLine(old, diffs.get(old.file) ?? "") === finding.startLine && SEVERITY_ORDER[finding.severity] >= SEVERITY_ORDER[old.severity]
|
|
49432
|
+
);
|
|
49433
|
+
if (index >= 0) remaining.splice(index, 1);
|
|
49434
|
+
else if (blocking(finding) || remaining.some(
|
|
49435
|
+
(old) => key(old) === key(finding) && SEVERITY_ORDER[finding.severity] < SEVERITY_ORDER[old.severity]
|
|
49436
|
+
))
|
|
49437
|
+
result.push(finding);
|
|
49438
|
+
}
|
|
49439
|
+
return result;
|
|
49440
|
+
}
|
|
49441
|
+
async function compareSecurityBaseline(target, rulesets, config, signal) {
|
|
49442
|
+
const baseline = config.baseline;
|
|
49443
|
+
if (baseline === void 0) throw new Error("Security baseline required");
|
|
49444
|
+
let directory;
|
|
49445
|
+
let base = { error: "base scan did not run" };
|
|
49446
|
+
let worktree = { error: "worktree scan did not run" };
|
|
49447
|
+
let sha = baseline.sha;
|
|
49448
|
+
const execOptions = comparisonExecOptions(config, signal);
|
|
49449
|
+
const git2 = comparisonGit(execOptions);
|
|
49450
|
+
try {
|
|
49451
|
+
sha = (await git2(baseline.directory, ["rev-parse", "--verify", `${baseline.sha}^{commit}`])).trim();
|
|
49452
|
+
if (!/^[a-f0-9]{40,64}$/.test(sha)) throw new Error("Base did not resolve to a commit SHA");
|
|
49453
|
+
directory = await allocateComparisonDirectory(config, execOptions);
|
|
49454
|
+
const archive = await archiveBaseline({ target, directory, baseline, sha, git: git2, execOptions });
|
|
49455
|
+
({ base, worktree } = await scanTrees({
|
|
49456
|
+
target,
|
|
49457
|
+
rulesets,
|
|
49458
|
+
config,
|
|
49459
|
+
signal,
|
|
49460
|
+
directory,
|
|
49461
|
+
archive
|
|
49462
|
+
}));
|
|
49463
|
+
throwIfAborted(signal, "Security baseline scan aborted");
|
|
49464
|
+
return await assessComparison({
|
|
49465
|
+
sha,
|
|
49466
|
+
base,
|
|
49467
|
+
worktree,
|
|
49468
|
+
git: git2,
|
|
49469
|
+
target,
|
|
49470
|
+
baseDirectory: archive.target
|
|
49471
|
+
});
|
|
49472
|
+
} catch (error) {
|
|
49473
|
+
throwIfAborted(signal, "Security baseline scan aborted");
|
|
49474
|
+
return incomplete(sha, base, worktree, [
|
|
49475
|
+
error instanceof Error ? error.message : String(error)
|
|
49476
|
+
]);
|
|
49477
|
+
} finally {
|
|
49478
|
+
if (directory !== void 0) await rm(directory, { recursive: true, force: true });
|
|
49479
|
+
}
|
|
49480
|
+
}
|
|
49481
|
+
function incomplete(sha, base, worktree, errors, unscannedCoverage = []) {
|
|
49482
|
+
return {
|
|
49483
|
+
baseSha: sha,
|
|
49484
|
+
baseCount: "error" in base ? null : base.totalFindings,
|
|
49485
|
+
worktreeCount: "error" in worktree ? null : worktree.totalFindings,
|
|
49486
|
+
introducedBlockingCount: null,
|
|
49487
|
+
blockingFindings: [],
|
|
49488
|
+
unscannedCoverage,
|
|
49489
|
+
...scannerVersion(base, worktree),
|
|
49490
|
+
complete: false,
|
|
49491
|
+
errors
|
|
49492
|
+
};
|
|
49493
|
+
}
|
|
49494
|
+
async function allocateComparisonDirectory(config, options) {
|
|
49495
|
+
if (config.wrapper === void 0) return mkdtemp(join16(tmpdir2(), "security-baseline-"));
|
|
49496
|
+
const path9 = (await execFileTree("mktemp", ["-d"], options)).stdout.trim();
|
|
49497
|
+
if (!isAbsolute8(path9)) throw new Error("Sandbox did not allocate a comparison directory");
|
|
49498
|
+
return path9;
|
|
49499
|
+
}
|
|
49500
|
+
async function assessComparison(input) {
|
|
49501
|
+
const { sha, base, worktree, git: git2, target } = input;
|
|
49502
|
+
const errors = [...scanErrors(base, "base"), ...scanErrors(worktree, "worktree")];
|
|
49503
|
+
if ("error" in base || "error" in worktree) return incomplete(sha, base, worktree, errors);
|
|
49504
|
+
const coverage = await compareParseCoverage({
|
|
49505
|
+
base,
|
|
49506
|
+
worktree,
|
|
49507
|
+
baseDirectory: input.baseDirectory,
|
|
49508
|
+
target,
|
|
49509
|
+
diff: async (file) => git2(target, [
|
|
49510
|
+
"diff",
|
|
49511
|
+
"--text",
|
|
49512
|
+
"--no-color",
|
|
49513
|
+
"--no-ext-diff",
|
|
49514
|
+
"--no-textconv",
|
|
49515
|
+
"--no-renames",
|
|
49516
|
+
"--unified=0",
|
|
49517
|
+
sha,
|
|
49518
|
+
"--",
|
|
49519
|
+
file
|
|
49520
|
+
])
|
|
49521
|
+
});
|
|
49522
|
+
errors.push(...coverage.errors);
|
|
49523
|
+
if (errors.length > 0) return incomplete(sha, base, worktree, errors, coverage.unscannedCoverage);
|
|
49524
|
+
const findings = await introducedFindings(base.findings, worktree.findings, git2, target, sha);
|
|
49525
|
+
return {
|
|
49526
|
+
baseSha: sha,
|
|
49527
|
+
baseCount: base.totalFindings,
|
|
49528
|
+
worktreeCount: worktree.totalFindings,
|
|
49529
|
+
introducedBlockingCount: findings.length,
|
|
49530
|
+
blockingFindings: actionableFindings(findings),
|
|
49531
|
+
complete: true,
|
|
49532
|
+
errors: [],
|
|
49533
|
+
unscannedCoverage: coverage.unscannedCoverage,
|
|
49534
|
+
...scannerVersion(base, worktree)
|
|
49535
|
+
};
|
|
49536
|
+
}
|
|
49537
|
+
async function verifyArchive(directory, tree) {
|
|
49538
|
+
if (tree === "") return;
|
|
49539
|
+
for (const entry of tree.split("\0").filter((record) => record !== "")) {
|
|
49540
|
+
const { mode, hash, file } = parseTreeEntry(entry);
|
|
49541
|
+
const contents = mode === "120000" ? Buffer.from(await readlink(join16(directory, file))) : await readFile7(join16(directory, file));
|
|
49542
|
+
const digest = createHash4(hash.length === 64 ? "sha256" : "sha1").update(`blob ${String(contents.length)}\0`).update(contents).digest("hex");
|
|
49543
|
+
if (digest !== hash) throw new Error(`Pinned archive content differs: ${file}`);
|
|
49544
|
+
}
|
|
49545
|
+
}
|
|
49546
|
+
function parseTreeEntry(entry) {
|
|
49547
|
+
const match = /^(\d+) (\w+) ([a-f0-9]+)\t([\s\S]+)$/.exec(entry);
|
|
49548
|
+
if (match === null) throw new Error("Unreadable pinned Git tree");
|
|
49549
|
+
const [, mode, type, hash, file] = match;
|
|
49550
|
+
if (mode === void 0 || type !== "blob" || hash === void 0 || file === void 0 || isAbsolute8(file) || file.split("/").includes(".."))
|
|
49551
|
+
throw new Error("Pinned tree coverage incomplete: unsupported tree entry");
|
|
49552
|
+
return { mode, hash, file };
|
|
49553
|
+
}
|
|
49554
|
+
function comparisonExecOptions(config, signal) {
|
|
49555
|
+
return {
|
|
49556
|
+
signal,
|
|
49557
|
+
env: hermeticGitEnv(config.env),
|
|
49558
|
+
wrapper: config.wrapper,
|
|
49559
|
+
timeoutMs: 3e4,
|
|
49560
|
+
maxBuffer: 16 * 1024 * 1024
|
|
49561
|
+
};
|
|
49562
|
+
}
|
|
49563
|
+
function comparisonGit(options) {
|
|
49564
|
+
return async (cwd, args) => (await execFileTree(
|
|
49565
|
+
"git",
|
|
49566
|
+
[
|
|
49567
|
+
"--literal-pathspecs",
|
|
49568
|
+
"-c",
|
|
49569
|
+
"core.hooksPath=/dev/null",
|
|
49570
|
+
"-c",
|
|
49571
|
+
"core.fsmonitor=false",
|
|
49572
|
+
...args
|
|
49573
|
+
],
|
|
49574
|
+
{ ...options, cwd }
|
|
49575
|
+
)).stdout;
|
|
49576
|
+
}
|
|
49577
|
+
async function archiveBaseline(input) {
|
|
49578
|
+
const { target, directory, baseline, sha, git: git2, execOptions } = input;
|
|
49579
|
+
const baseDir = join16(directory, "base");
|
|
49580
|
+
const prefix = (await git2(target, ["rev-parse", "--show-prefix"])).trim();
|
|
49581
|
+
if (isAbsolute8(prefix) || prefix.split("/").includes(".."))
|
|
49582
|
+
throw new Error("Invalid scan subtree");
|
|
49583
|
+
const { mkdir: mkdir2 } = await import("node:fs/promises");
|
|
49584
|
+
await mkdir2(baseDir);
|
|
49585
|
+
const archive = join16(directory, "base.tar");
|
|
49586
|
+
await git2(baseline.directory, ["archive", "--format=tar", `--output=${archive}`, sha]);
|
|
49587
|
+
await execFileTree("tar", ["-xf", archive, "-C", baseDir], execOptions);
|
|
49588
|
+
await verifyArchive(baseDir, await git2(baseline.directory, ["ls-tree", "-r", "-z", sha]));
|
|
49589
|
+
return { root: baseDir, target: join16(baseDir, prefix) };
|
|
49590
|
+
}
|
|
49591
|
+
async function scanTrees(input) {
|
|
49592
|
+
const { target, rulesets, config, signal, directory, archive } = input;
|
|
49593
|
+
const prepared = await prepareSecurityScan(rulesets, {
|
|
49594
|
+
...comparisonExecOptions(config, signal),
|
|
49595
|
+
directory
|
|
49596
|
+
});
|
|
49597
|
+
if ("error" in prepared) throw new Error(prepared.error);
|
|
49598
|
+
const scanInput = {
|
|
49599
|
+
scanner: "semgrep",
|
|
49600
|
+
rulesets: [...rulesets],
|
|
49601
|
+
maxFindings: Number.MAX_SAFE_INTEGER
|
|
49602
|
+
};
|
|
49603
|
+
const options = {
|
|
49604
|
+
signal,
|
|
49605
|
+
env: config.env,
|
|
49606
|
+
wrapper: config.wrapper,
|
|
49607
|
+
completeResults: true,
|
|
49608
|
+
preparedScan: prepared
|
|
49609
|
+
};
|
|
49610
|
+
const base = normalizedScan(
|
|
49611
|
+
await executeSecurityScan(
|
|
49612
|
+
{ ...scanInput, target: archive.target },
|
|
49613
|
+
{ ...options, root: archive.root }
|
|
49614
|
+
),
|
|
49615
|
+
archive.target
|
|
49616
|
+
);
|
|
49617
|
+
const worktree = normalizedScan(
|
|
49618
|
+
await executeSecurityScan({ ...scanInput, target }, { ...options, root: config.root }),
|
|
49619
|
+
target
|
|
49620
|
+
);
|
|
49621
|
+
return { base, worktree };
|
|
49622
|
+
}
|
|
49623
|
+
function actionableFindings(findings) {
|
|
49624
|
+
return findings.map(({ rule, file, startLine, severity }) => ({
|
|
49625
|
+
rule,
|
|
49626
|
+
file,
|
|
49627
|
+
startLine,
|
|
49628
|
+
severity
|
|
49629
|
+
}));
|
|
49630
|
+
}
|
|
49631
|
+
function scannerVersion(base, worktree) {
|
|
49632
|
+
const version = "error" in base ? void 0 : base.scannerVersion;
|
|
49633
|
+
const other = "error" in worktree ? void 0 : worktree.scannerVersion;
|
|
49634
|
+
const measured = version ?? other;
|
|
49635
|
+
return measured === void 0 ? {} : { scannerVersion: measured };
|
|
49636
|
+
}
|
|
49637
|
+
|
|
49029
49638
|
// src/pipeline/security-gate.ts
|
|
49030
49639
|
var logger49 = createLogger({ component: "security-gate" });
|
|
49031
49640
|
var BLOCKING_SEVERITIES = /* @__PURE__ */ new Set(["critical", "high"]);
|
|
49032
49641
|
function checkSecurityScan(targetDir, rulesets = ["p/default"], config = {}) {
|
|
49033
49642
|
return async (signal) => {
|
|
49643
|
+
if (config.baseline !== void 0) return runBaselineGate(targetDir, rulesets, config, signal);
|
|
49034
49644
|
const start = Date.now();
|
|
49035
49645
|
const result = await executeSecurityScan(
|
|
49036
49646
|
{
|
|
@@ -49051,33 +49661,59 @@ function checkSecurityScan(targetDir, rulesets = ["p/default"], config = {}) {
|
|
|
49051
49661
|
durationMs: Date.now() - start
|
|
49052
49662
|
};
|
|
49053
49663
|
}
|
|
49054
|
-
|
|
49664
|
+
const gateResult = await runSecurityPipeline(result, targetDir, config, start, signal);
|
|
49665
|
+
if (gateResult.verdict === "fail") return gateResult;
|
|
49666
|
+
if (result.parseDiagnostics !== void 0 && result.parseDiagnostics.length > 0) {
|
|
49667
|
+
return {
|
|
49668
|
+
...gateResult,
|
|
49669
|
+
verdict: "skip",
|
|
49670
|
+
details: `Security scan incomplete: unparsed files ${result.parseDiagnostics.map((d) => d.file).join(", ")}`,
|
|
49671
|
+
durationMs: Date.now() - start
|
|
49672
|
+
};
|
|
49673
|
+
}
|
|
49674
|
+
return gateResult;
|
|
49675
|
+
};
|
|
49676
|
+
}
|
|
49677
|
+
async function runBaselineGate(target, rulesets, config, signal) {
|
|
49678
|
+
const start = Date.now();
|
|
49679
|
+
const comparison = await compareSecurityBaseline(target, rulesets, config, signal);
|
|
49680
|
+
const osv = comparison.complete ? await runOsvCheck(target, config.enableOsv ?? true, signal) : OSV_EMPTY;
|
|
49681
|
+
throwIfAborted(signal, "Security baseline scan aborted");
|
|
49682
|
+
const osvFailed = osv.vulnerabilities.some((v) => v.severity === "CRITICAL");
|
|
49683
|
+
const details = comparison.complete ? `Base ${String(comparison.baseCount)}, worktree ${String(comparison.worktreeCount)} findings; ${String(comparison.introducedBlockingCount)} introduced blocking; ${buildScanSummary(comparison.worktreeCount ?? 0, comparison.introducedBlockingCount ?? 0, osv.vulnerabilities.length, osv)}` : `Security comparison incomplete: ${comparison.errors.join("; ")}`;
|
|
49684
|
+
return {
|
|
49685
|
+
name: "security_scan",
|
|
49686
|
+
verdict: !comparison.complete ? "skip" : comparison.introducedBlockingCount === 0 && !osvFailed ? "pass" : "fail",
|
|
49687
|
+
details: details.slice(0, 500),
|
|
49688
|
+
comparison,
|
|
49689
|
+
durationMs: Date.now() - start
|
|
49055
49690
|
};
|
|
49056
49691
|
}
|
|
49057
49692
|
async function runSecurityPipeline(sarifResult, targetDir, config, start, signal) {
|
|
49058
49693
|
const osv = await runOsvCheck(targetDir, config.enableOsv ?? true, signal);
|
|
49059
49694
|
throwIfAborted(signal, "Security scan aborted");
|
|
49060
49695
|
const osvVulns = osv.vulnerabilities;
|
|
49061
|
-
const
|
|
49696
|
+
const blocking2 = getBlockingFindings(sarifResult.findings);
|
|
49062
49697
|
const details = buildScanSummary(
|
|
49063
49698
|
sarifResult.totalFindings,
|
|
49064
|
-
|
|
49699
|
+
blocking2.length,
|
|
49065
49700
|
osvVulns.length,
|
|
49066
49701
|
osv,
|
|
49067
49702
|
sarifResult.errors.length
|
|
49068
49703
|
);
|
|
49069
49704
|
logger49.info("Security gate complete", {
|
|
49070
49705
|
total: sarifResult.totalFindings,
|
|
49071
|
-
blocking:
|
|
49706
|
+
blocking: blocking2.length,
|
|
49072
49707
|
osvVulns: osvVulns.length,
|
|
49073
49708
|
osvFailedLookups: osv.failedLookups,
|
|
49074
49709
|
sarifParseErrors: sarifResult.errors.length
|
|
49075
49710
|
});
|
|
49076
|
-
const failed =
|
|
49711
|
+
const failed = blocking2.length > 0 || osvVulns.some((v) => v.severity === "CRITICAL");
|
|
49077
49712
|
return {
|
|
49078
49713
|
name: "security_scan",
|
|
49079
49714
|
verdict: failed ? "fail" : "pass",
|
|
49080
49715
|
details,
|
|
49716
|
+
blockingFindings: blocking2,
|
|
49081
49717
|
durationMs: Date.now() - start
|
|
49082
49718
|
};
|
|
49083
49719
|
}
|
|
@@ -49124,26 +49760,26 @@ async function runOsvCheck(targetDir, enabled, signal) {
|
|
|
49124
49760
|
function getBlockingFindings(findings) {
|
|
49125
49761
|
return findings.filter((f) => BLOCKING_SEVERITIES.has(f.severity));
|
|
49126
49762
|
}
|
|
49127
|
-
function osvCoverageNote(
|
|
49763
|
+
function osvCoverageNote(blocking2, osvCount, osv) {
|
|
49128
49764
|
if (osv?.checkFailed === true) {
|
|
49129
49765
|
return "OSV check did not run (error) \u2014 dependency vulnerabilities unknown";
|
|
49130
49766
|
}
|
|
49131
49767
|
if (osv !== void 0 && osv.failedLookups > 0) {
|
|
49132
49768
|
return `OSV not checked for ${String(osv.failedLookups)} of ${String(osv.queried)} dependencies (lookup failed)`;
|
|
49133
49769
|
}
|
|
49134
|
-
if (
|
|
49770
|
+
if (blocking2 === 0 && osvCount === 0) return "none blocking";
|
|
49135
49771
|
return "";
|
|
49136
49772
|
}
|
|
49137
|
-
function buildScanSummary(total,
|
|
49773
|
+
function buildScanSummary(total, blocking2, osvCount, osv, sarifParseErrors = 0) {
|
|
49138
49774
|
const parts = [`${String(total)} SAST findings`];
|
|
49139
49775
|
if (sarifParseErrors > 0) {
|
|
49140
49776
|
parts.push(
|
|
49141
49777
|
`${String(sarifParseErrors)} scanner output line(s) unreadable \u2014 SAST coverage is partial`
|
|
49142
49778
|
);
|
|
49143
49779
|
}
|
|
49144
|
-
if (
|
|
49780
|
+
if (blocking2 > 0) parts.push(`${String(blocking2)} blocking`);
|
|
49145
49781
|
if (osvCount > 0) parts.push(`${String(osvCount)} OSV dependency vulnerabilities`);
|
|
49146
|
-
parts.push(osvCoverageNote(
|
|
49782
|
+
parts.push(osvCoverageNote(blocking2, osvCount, osv));
|
|
49147
49783
|
if (osv !== void 0 && osv.declared > osv.queried) {
|
|
49148
49784
|
parts.push(
|
|
49149
49785
|
`OSV covered ${String(osv.queried)} of ${String(osv.declared)} declared dependencies`
|
|
@@ -49154,7 +49790,7 @@ function buildScanSummary(total, blocking, osvCount, osv, sarifParseErrors = 0)
|
|
|
49154
49790
|
|
|
49155
49791
|
// src/security/quality-gate-commands.ts
|
|
49156
49792
|
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
|
|
49157
|
-
import { join as
|
|
49793
|
+
import { join as join17 } from "node:path";
|
|
49158
49794
|
var LOCKFILES = [
|
|
49159
49795
|
{ file: "pnpm-lock.yaml", manager: "pnpm" },
|
|
49160
49796
|
{ file: "yarn.lock", manager: "yarn" },
|
|
@@ -49169,12 +49805,12 @@ var SCRIPT_CANDIDATES = {
|
|
|
49169
49805
|
};
|
|
49170
49806
|
function detectPackageManager(projectDir) {
|
|
49171
49807
|
for (const { file, manager } of LOCKFILES) {
|
|
49172
|
-
if (existsSync11(
|
|
49808
|
+
if (existsSync11(join17(projectDir, file))) return manager;
|
|
49173
49809
|
}
|
|
49174
49810
|
return "npm";
|
|
49175
49811
|
}
|
|
49176
49812
|
function readScripts(projectDir) {
|
|
49177
|
-
const manifest =
|
|
49813
|
+
const manifest = join17(projectDir, "package.json");
|
|
49178
49814
|
if (!existsSync11(manifest)) return void 0;
|
|
49179
49815
|
try {
|
|
49180
49816
|
const parsed = JSON.parse(readFileSync9(manifest, "utf-8"));
|
|
@@ -49376,8 +50012,8 @@ function getTrendContext() {
|
|
|
49376
50012
|
|
|
49377
50013
|
// src/pipeline/agent-executor-parsers.ts
|
|
49378
50014
|
var logger50 = createLogger({ component: "agent-executor" });
|
|
49379
|
-
function stringField(record,
|
|
49380
|
-
const value = record[
|
|
50015
|
+
function stringField(record, key2, fallback) {
|
|
50016
|
+
const value = record[key2];
|
|
49381
50017
|
if (typeof value === "string") return value;
|
|
49382
50018
|
if (typeof value === "number") return String(value);
|
|
49383
50019
|
return fallback;
|
|
@@ -49765,12 +50401,8 @@ function createQualityGateStage({
|
|
|
49765
50401
|
return { passed, verdict: result.verdict, feedback };
|
|
49766
50402
|
};
|
|
49767
50403
|
}
|
|
49768
|
-
function createSecurityScanStage({
|
|
49769
|
-
config,
|
|
49770
|
-
startStage,
|
|
49771
|
-
workspaceDependencies,
|
|
49772
|
-
wrapper
|
|
49773
|
-
}) {
|
|
50404
|
+
function createSecurityScanStage(deps) {
|
|
50405
|
+
const { config, startStage, workspaceDependencies, wrapper } = deps;
|
|
49774
50406
|
return async (signal) => {
|
|
49775
50407
|
startStage("security");
|
|
49776
50408
|
const start = getTimeProvider().now();
|
|
@@ -49778,6 +50410,7 @@ function createSecurityScanStage({
|
|
|
49778
50410
|
await postProgress(config, "Security", `Scanning ${target}...`);
|
|
49779
50411
|
const scratchBound = workspaceDependencies !== void 0;
|
|
49780
50412
|
const check = checkSecurityScan(target, void 0, {
|
|
50413
|
+
baseline: config.securityBaseline,
|
|
49781
50414
|
env: scratchBound ? hermeticGitEnv() : void 0,
|
|
49782
50415
|
root: scratchBound ? target : void 0,
|
|
49783
50416
|
wrapper
|
|
@@ -49801,7 +50434,7 @@ function createSecurityScanStage({
|
|
|
49801
50434
|
const securityNote = result.verdict === "skip" ? `Security scan did not run: ${result.details}. Install the scanner, or use qualityGate 'advisory' to proceed without security evidence.` : `BLOCKED: ${result.details}`;
|
|
49802
50435
|
await postProgress(config, "Security", passed ? "Passed" : securityNote);
|
|
49803
50436
|
flushPipelineMemory();
|
|
49804
|
-
return
|
|
50437
|
+
return securityStageResult(result, passed);
|
|
49805
50438
|
};
|
|
49806
50439
|
}
|
|
49807
50440
|
|
|
@@ -49826,12 +50459,12 @@ function createAgentStages(config = {}) {
|
|
|
49826
50459
|
decompose: createDecomposeStage(deps),
|
|
49827
50460
|
...createExecutionStages(deps),
|
|
49828
50461
|
// #6794: execution closures share the same guard and scratch directory.
|
|
49829
|
-
withWorkspace: ({ directory, dependencies: workspaceDependencies, wrapper }) => {
|
|
50462
|
+
withWorkspace: ({ directory, dependencies: workspaceDependencies, wrapper, baseline }) => {
|
|
49830
50463
|
const bound = {
|
|
49831
50464
|
...deps,
|
|
49832
50465
|
workspaceDependencies,
|
|
49833
50466
|
wrapper,
|
|
49834
|
-
config: { ...config, scanTarget: directory }
|
|
50467
|
+
config: { ...config, scanTarget: directory, securityBaseline: baseline }
|
|
49835
50468
|
};
|
|
49836
50469
|
return {
|
|
49837
50470
|
...createExecutionStages(bound),
|
|
@@ -49857,11 +50490,11 @@ function createExecutionStages(deps) {
|
|
|
49857
50490
|
}
|
|
49858
50491
|
|
|
49859
50492
|
// src/pipeline/stage-wrappers.ts
|
|
49860
|
-
function output(
|
|
49861
|
-
return { stateKey:
|
|
50493
|
+
function output(key2, value, durationMs, success) {
|
|
50494
|
+
return { stateKey: key2, value, durationMs, success };
|
|
49862
50495
|
}
|
|
49863
|
-
function failOutput(
|
|
49864
|
-
return { stateKey:
|
|
50496
|
+
function failOutput(key2, error, durationMs) {
|
|
50497
|
+
return { stateKey: key2, value: null, durationMs, success: false, error };
|
|
49865
50498
|
}
|
|
49866
50499
|
function createParseSpecStageWrapper() {
|
|
49867
50500
|
return {
|
|
@@ -50401,7 +51034,7 @@ ${FINDINGS_FORMAT_INSTRUCTIONS}
|
|
|
50401
51034
|
}
|
|
50402
51035
|
|
|
50403
51036
|
// src/mcp/tools/pr-review-tool.ts
|
|
50404
|
-
import { z as
|
|
51037
|
+
import { z as z95 } from "zod";
|
|
50405
51038
|
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
50406
51039
|
|
|
50407
51040
|
// src/audit/reviewed-diff-hash.ts
|
|
@@ -50952,19 +51585,19 @@ var MAX_REPO_CONTEXT_LENGTH = 2e3;
|
|
|
50952
51585
|
var MAX_TITLE_LENGTH = 500;
|
|
50953
51586
|
var MAX_DESCRIPTION_LENGTH = 1e4;
|
|
50954
51587
|
var PR_REVIEW_ASYNC_HINT = "A pr_review run fans out to 5 live LLM voters and 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.";
|
|
50955
|
-
var PrReviewInputSchema =
|
|
50956
|
-
prTitle:
|
|
50957
|
-
prDescription:
|
|
50958
|
-
prDiff:
|
|
51588
|
+
var PrReviewInputSchema = z95.object({
|
|
51589
|
+
prTitle: z95.string().min(1).max(MAX_TITLE_LENGTH).describe("PR title"),
|
|
51590
|
+
prDescription: z95.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("PR body / description"),
|
|
51591
|
+
prDiff: z95.string().min(1).max(MAX_DIFF_INPUT_LENGTH).refine(looksLikeUnifiedDiff, {
|
|
50959
51592
|
message: "prDiff must be a unified diff (expected a `diff --git`, `---`/`+++`, or `@@ \u2026 @@` line). Prose descriptions of a change are rejected: a review of a summary is not a review of the code, and would be recorded as though it were (#4451)."
|
|
50960
51593
|
}).describe(
|
|
50961
51594
|
`Unified diff text (max ${String(MAX_DIFF_INPUT_LENGTH)} chars). REQUIRED SHAPE (#4451): must contain a \`diff --git\` header, an \`@@ \u2026 @@\` hunk header backed by +/- lines, or a \`---\`/\`+++\` header pair \u2014 a prose summary of the change is REJECTED, because reviewing a summary is not reviewing the code and would be recorded as though it were. (Stated here because Zod refinements do not survive JSON-schema generation, so this constraint is otherwise invisible to clients.) No need to truncate before calling: the panel reads the whole diff whenever it fits the voters' context windows (#6003); a diff larger than that is security-prioritized and PARTIALLY reviewed (lowest-priority whole files dropped; a partial panel read can block but never verified-approve). Separately, the audit record's hash binds only the first ${String(MAX_DIFF_LENGTH)} UTF-8 bytes; the response \`coverage\` and the record summary state both what the panel read and what the hash binds.`
|
|
50962
51595
|
),
|
|
50963
|
-
repoContext:
|
|
51596
|
+
repoContext: z95.string().max(MAX_REPO_CONTEXT_LENGTH).optional().describe(
|
|
50964
51597
|
`Optional one-paragraph repo context (architecture, conventions; max ${String(MAX_REPO_CONTEXT_LENGTH)} chars; trim before calling)`
|
|
50965
51598
|
),
|
|
50966
|
-
baseRef:
|
|
50967
|
-
headRef:
|
|
51599
|
+
baseRef: z95.string().max(200).optional().describe("Base branch ref (e.g. main)"),
|
|
51600
|
+
headRef: z95.string().max(200).optional().describe("Head branch ref"),
|
|
50968
51601
|
/**
|
|
50969
51602
|
* Option-C audit binding (#4031). When BOTH `prNumber` and `baseSha` are
|
|
50970
51603
|
* supplied AND the review is live (not simulated), pr_review persists an
|
|
@@ -50980,14 +51613,14 @@ var PrReviewInputSchema = z94.object({
|
|
|
50980
51613
|
* the PR opened and drifts as main advances), so pass the merge-base as
|
|
50981
51614
|
* `baseSha` or the record will not match on an aged branch (#5692).
|
|
50982
51615
|
*/
|
|
50983
|
-
prNumber:
|
|
50984
|
-
baseSha:
|
|
51616
|
+
prNumber: z95.number().int().positive().optional().describe("PR number \u2014 with baseSha, enables Option-C audit-record persistence (#4031)"),
|
|
51617
|
+
baseSha: z95.string().regex(/^[0-9a-f]{40}$/, "baseSha must be a 40-char lowercase hex commit sha").optional().describe(
|
|
50985
51618
|
"40-hex base commit sha the reviewed diff was computed from \u2014 pass `git merge-base origin/<base> <head>`, the base the gate recomputes (Option-C binding, #4031, #5692)"
|
|
50986
51619
|
),
|
|
50987
|
-
repoPath:
|
|
51620
|
+
repoPath: z95.string().max(1024).optional().describe(
|
|
50988
51621
|
"Repo root path for persisting the governance pr-review record (overrides cwd auto-detection). Must contain a .git ancestor \u2014 relative paths are resolved against cwd; ignored (falls back to cwd auto-detection) if it is not a real repo root. Env NEXUS_PR_REVIEW_RECORDS_PATH still takes precedence and is unrestricted."
|
|
50989
51622
|
),
|
|
50990
|
-
simulate:
|
|
51623
|
+
simulate: z95.boolean().default(false).describe("Use simulated voters (testing only; never ship live with this true)"),
|
|
50991
51624
|
/**
|
|
50992
51625
|
* Error policy (#4132). `standard` (default) excludes absent voters but
|
|
50993
51626
|
* requires a majority of the requested panel to approve. `absolute_quorum` gates
|
|
@@ -50999,7 +51632,7 @@ var PrReviewInputSchema = z94.object({
|
|
|
50999
51632
|
* verified approve. A genuine `request_changes` blocker still wins (Tiers 1-2
|
|
51000
51633
|
* run first).
|
|
51001
51634
|
*/
|
|
51002
|
-
errorPolicy:
|
|
51635
|
+
errorPolicy: z95.enum(["standard", "absolute_quorum"]).default("standard").describe(
|
|
51003
51636
|
"Error policy (#4132). 'standard' (default): absent voters excluded; approval requires a majority of the requested panel. 'absolute_quorum': any errored voter \u2014 esp. the contrarian \u2014 degrades a would-be approve to a recoverable abstain (verified:false); never manufactures a verified approve from an induced error."
|
|
51004
51637
|
),
|
|
51005
51638
|
// #6123: same field as consensus_vote — the panel judges the caller's project.
|
|
@@ -51355,27 +51988,27 @@ function absoluteQuorumApprove(reviews, valid) {
|
|
|
51355
51988
|
}
|
|
51356
51989
|
|
|
51357
51990
|
// src/mcp/tools/survey-oss-landscape.ts
|
|
51358
|
-
import { z as
|
|
51359
|
-
var SurveyOssLandscapeInputSchema =
|
|
51360
|
-
query:
|
|
51361
|
-
maxResults:
|
|
51362
|
-
minStars:
|
|
51363
|
-
language:
|
|
51991
|
+
import { z as z96 } from "zod";
|
|
51992
|
+
var SurveyOssLandscapeInputSchema = z96.object({
|
|
51993
|
+
query: z96.string().min(1).max(200).describe('Free-text search query, e.g. "cargo nextest replacement" or "OSS SBOM tools"'),
|
|
51994
|
+
maxResults: z96.number().int().min(1).max(50).optional().default(10).describe("Maximum candidates to return (1-50; default 10)"),
|
|
51995
|
+
minStars: z96.number().int().min(0).optional().default(0).describe("Minimum star count to include (default 0; useful for filtering noise)"),
|
|
51996
|
+
language: z96.string().max(50).optional().describe('GitHub language filter, e.g. "rust" or "typescript"')
|
|
51364
51997
|
});
|
|
51365
|
-
var GitHubRepoSchema =
|
|
51366
|
-
full_name:
|
|
51367
|
-
html_url:
|
|
51368
|
-
description:
|
|
51369
|
-
stargazers_count:
|
|
51370
|
-
pushed_at:
|
|
51371
|
-
language:
|
|
51372
|
-
license:
|
|
51373
|
-
spdx_id:
|
|
51998
|
+
var GitHubRepoSchema = z96.object({
|
|
51999
|
+
full_name: z96.string().optional(),
|
|
52000
|
+
html_url: z96.string().optional(),
|
|
52001
|
+
description: z96.string().nullable().optional(),
|
|
52002
|
+
stargazers_count: z96.number().optional(),
|
|
52003
|
+
pushed_at: z96.string().nullable().optional(),
|
|
52004
|
+
language: z96.string().nullable().optional(),
|
|
52005
|
+
license: z96.object({
|
|
52006
|
+
spdx_id: z96.string().nullable().optional()
|
|
51374
52007
|
}).nullable().optional()
|
|
51375
52008
|
});
|
|
51376
|
-
var GitHubSearchResponseSchema =
|
|
51377
|
-
total_count:
|
|
51378
|
-
items:
|
|
52009
|
+
var GitHubSearchResponseSchema = z96.object({
|
|
52010
|
+
total_count: z96.number().optional(),
|
|
52011
|
+
items: z96.array(GitHubRepoSchema).optional()
|
|
51379
52012
|
});
|
|
51380
52013
|
var GITHUB_SEARCH_BASE = "https://api.github.com/search/repositories";
|
|
51381
52014
|
function buildGithubQuery(input) {
|
|
@@ -51497,16 +52130,16 @@ function createSurveyHandler(deps) {
|
|
|
51497
52130
|
});
|
|
51498
52131
|
return withToolError("Survey failed", logger58, async () => {
|
|
51499
52132
|
const result = await executeSurvey(validation.data, logger58);
|
|
51500
|
-
return structuredToolSuccess(
|
|
52133
|
+
return structuredToolSuccess(z96.object(SURVEY_OUTPUT_SCHEMA), result);
|
|
51501
52134
|
});
|
|
51502
52135
|
};
|
|
51503
52136
|
}
|
|
51504
52137
|
var SURVEY_OUTPUT_SCHEMA = {
|
|
51505
|
-
query:
|
|
51506
|
-
totalFound:
|
|
51507
|
-
candidates:
|
|
51508
|
-
sourcesQueried:
|
|
51509
|
-
sourcesFailed:
|
|
52138
|
+
query: z96.string(),
|
|
52139
|
+
totalFound: z96.number(),
|
|
52140
|
+
candidates: z96.array(z96.unknown()),
|
|
52141
|
+
sourcesQueried: z96.array(z96.string()),
|
|
52142
|
+
sourcesFailed: z96.array(z96.string())
|
|
51510
52143
|
};
|
|
51511
52144
|
var SURVEY_DESCRIPTION = 'Transient OSS project search. Returns a ranked list of GitHub repositories with license, last-commit, star-count, and one-line description. Does NOT persist to the research registry \u2014 use `research_add_source` for that. Best for one-off engineering decisions like "what tools exist in this space?".';
|
|
51512
52145
|
function registerSurveyOssLandscapeTool(server, deps) {
|
|
@@ -51536,7 +52169,7 @@ function registerSurveyOssLandscapeTool(server, deps) {
|
|
|
51536
52169
|
}
|
|
51537
52170
|
|
|
51538
52171
|
// src/mcp/tools/vendor-publishing-audit.ts
|
|
51539
|
-
import { z as
|
|
52172
|
+
import { z as z97 } from "zod";
|
|
51540
52173
|
|
|
51541
52174
|
// src/mcp/tools/vendor-publishing-seed.ts
|
|
51542
52175
|
var VENDOR_PUBLISHING_SEED = {
|
|
@@ -51609,8 +52242,8 @@ function listKnownVendors() {
|
|
|
51609
52242
|
}
|
|
51610
52243
|
|
|
51611
52244
|
// src/mcp/tools/vendor-publishing-audit.ts
|
|
51612
|
-
var VendorPublishingAuditInputSchema =
|
|
51613
|
-
vendor:
|
|
52245
|
+
var VendorPublishingAuditInputSchema = z97.object({
|
|
52246
|
+
vendor: z97.string().min(1).max(50).toLowerCase().describe('Vendor identifier, lowercase. e.g. "ubuntu", "debian", "fedora"')
|
|
51614
52247
|
});
|
|
51615
52248
|
function lookupVendor(vendor) {
|
|
51616
52249
|
if (isKnownVendor(vendor)) {
|
|
@@ -51638,26 +52271,26 @@ function createVendorPublishingAuditHandler(deps) {
|
|
|
51638
52271
|
return withToolError("Vendor publishing audit failed", logger58, () => {
|
|
51639
52272
|
const result = lookupVendor(validation.data.vendor);
|
|
51640
52273
|
return Promise.resolve(
|
|
51641
|
-
structuredToolSuccess(
|
|
52274
|
+
structuredToolSuccess(z97.object(VENDOR_PUBLISHING_OUTPUT_SCHEMA), result)
|
|
51642
52275
|
);
|
|
51643
52276
|
});
|
|
51644
52277
|
};
|
|
51645
52278
|
}
|
|
51646
52279
|
var VENDOR_PUBLISHING_OUTPUT_SCHEMA = {
|
|
51647
|
-
vendor:
|
|
51648
|
-
known:
|
|
52280
|
+
vendor: z97.string(),
|
|
52281
|
+
known: z97.boolean(),
|
|
51649
52282
|
// Fields below populate when known=true; permissive optional for known=false.
|
|
51650
|
-
sha256SumsUrlPattern:
|
|
51651
|
-
sha256SumsSignatureUrlPattern:
|
|
51652
|
-
signaturePattern:
|
|
51653
|
-
gpgKeys:
|
|
51654
|
-
releaseCadence:
|
|
51655
|
-
keyRotationNotes:
|
|
51656
|
-
vendorDocUrl:
|
|
51657
|
-
citedAt:
|
|
52283
|
+
sha256SumsUrlPattern: z97.string().optional(),
|
|
52284
|
+
sha256SumsSignatureUrlPattern: z97.string().optional(),
|
|
52285
|
+
signaturePattern: z97.string().optional(),
|
|
52286
|
+
gpgKeys: z97.array(z97.unknown()).optional(),
|
|
52287
|
+
releaseCadence: z97.string().optional(),
|
|
52288
|
+
keyRotationNotes: z97.string().optional(),
|
|
52289
|
+
vendorDocUrl: z97.string().optional(),
|
|
52290
|
+
citedAt: z97.string().optional(),
|
|
51658
52291
|
// Fields below populate when known=false.
|
|
51659
|
-
message:
|
|
51660
|
-
knownVendors:
|
|
52292
|
+
message: z97.string().optional(),
|
|
52293
|
+
knownVendors: z97.array(z97.string()).optional()
|
|
51661
52294
|
};
|
|
51662
52295
|
var VENDOR_PUBLISHING_DESCRIPTION = "Look up a vendor's published-artifact signing infrastructure: GPG key fingerprints, SHA256SUMS URL pattern, signature shape (clearsigned / detached / detached-on-iso), release cadence, key rotation notes, and the vendor doc citation. Static lookup against a curated seed dataset; the vendor doc URL is the authoritative source. Returns `{known: false, knownVendors: [...]}` for vendors without a seed entry. v1 covers ubuntu, debian, fedora.";
|
|
51663
52296
|
function registerVendorPublishingAuditTool(server, deps) {
|
|
@@ -51687,17 +52320,17 @@ function registerVendorPublishingAuditTool(server, deps) {
|
|
|
51687
52320
|
}
|
|
51688
52321
|
|
|
51689
52322
|
// src/mcp/tools/compare-data-feeds.ts
|
|
51690
|
-
import { z as
|
|
52323
|
+
import { z as z98 } from "zod";
|
|
51691
52324
|
import * as path6 from "node:path";
|
|
51692
52325
|
import * as fs7 from "node:fs";
|
|
51693
52326
|
import * as yaml3 from "yaml";
|
|
51694
|
-
var CompareDataFeedsInputSchema =
|
|
51695
|
-
feedAPath:
|
|
51696
|
-
feedBPath:
|
|
51697
|
-
keyPath:
|
|
52327
|
+
var CompareDataFeedsInputSchema = z98.object({
|
|
52328
|
+
feedAPath: z98.string().min(1).max(1e3).describe("Filesystem path to feed A (YAML or JSON, auto-detected by extension)"),
|
|
52329
|
+
feedBPath: z98.string().min(1).max(1e3).describe("Filesystem path to feed B"),
|
|
52330
|
+
keyPath: z98.string().min(1).max(200).describe(
|
|
51698
52331
|
'Dotted path to the entry key, e.g. "id" or "name". Each entry must have this field.'
|
|
51699
52332
|
),
|
|
51700
|
-
compareFields:
|
|
52333
|
+
compareFields: z98.array(z98.string().min(1).max(200)).max(20).optional().describe(
|
|
51701
52334
|
'Optional dotted field paths to compare across matched entries (e.g. ["license", "sha256"])'
|
|
51702
52335
|
)
|
|
51703
52336
|
});
|
|
@@ -51737,16 +52370,16 @@ function indexByKey(entries, keyPath) {
|
|
|
51737
52370
|
const missingKeyAt = [];
|
|
51738
52371
|
for (let i = 0; i < entries.length; i++) {
|
|
51739
52372
|
const entry = entries[i];
|
|
51740
|
-
const
|
|
51741
|
-
if (
|
|
52373
|
+
const key2 = readDottedPath(entry, keyPath);
|
|
52374
|
+
if (key2 === void 0 || key2 === null) {
|
|
51742
52375
|
missingKeyAt.push(i);
|
|
51743
52376
|
continue;
|
|
51744
52377
|
}
|
|
51745
|
-
if (typeof
|
|
52378
|
+
if (typeof key2 === "object") {
|
|
51746
52379
|
missingKeyAt.push(i);
|
|
51747
52380
|
continue;
|
|
51748
52381
|
}
|
|
51749
|
-
const keyStr = typeof
|
|
52382
|
+
const keyStr = typeof key2 === "string" ? key2 : typeof key2 === "number" ? String(key2) : typeof key2 === "bigint" ? key2.toString() : typeof key2 === "boolean" ? String(key2) : "";
|
|
51750
52383
|
if (keyStr === "") {
|
|
51751
52384
|
missingKeyAt.push(i);
|
|
51752
52385
|
continue;
|
|
@@ -51759,12 +52392,12 @@ function membershipDiff(indexA, indexB) {
|
|
|
51759
52392
|
const onlyInA = [];
|
|
51760
52393
|
const onlyInB = [];
|
|
51761
52394
|
const inBoth = [];
|
|
51762
|
-
for (const
|
|
51763
|
-
if (indexB.has(
|
|
51764
|
-
else onlyInA.push(
|
|
52395
|
+
for (const key2 of indexA.keys()) {
|
|
52396
|
+
if (indexB.has(key2)) inBoth.push(key2);
|
|
52397
|
+
else onlyInA.push(key2);
|
|
51765
52398
|
}
|
|
51766
|
-
for (const
|
|
51767
|
-
if (!indexA.has(
|
|
52399
|
+
for (const key2 of indexB.keys()) {
|
|
52400
|
+
if (!indexA.has(key2)) onlyInB.push(key2);
|
|
51768
52401
|
}
|
|
51769
52402
|
onlyInA.sort();
|
|
51770
52403
|
onlyInB.sort();
|
|
@@ -51773,14 +52406,14 @@ function membershipDiff(indexA, indexB) {
|
|
|
51773
52406
|
}
|
|
51774
52407
|
function compareFields(inBothKeys, indexA, indexB, fields) {
|
|
51775
52408
|
const out = [];
|
|
51776
|
-
for (const
|
|
51777
|
-
const a = indexA.get(
|
|
51778
|
-
const b = indexB.get(
|
|
52409
|
+
for (const key2 of inBothKeys) {
|
|
52410
|
+
const a = indexA.get(key2);
|
|
52411
|
+
const b = indexB.get(key2);
|
|
51779
52412
|
for (const field of fields) {
|
|
51780
52413
|
const valueA = readDottedPath(a, field);
|
|
51781
52414
|
const valueB = readDottedPath(b, field);
|
|
51782
52415
|
if (!deepEqual(valueA, valueB)) {
|
|
51783
|
-
out.push({ key, field, valueA, valueB });
|
|
52416
|
+
out.push({ key: key2, field, valueA, valueB });
|
|
51784
52417
|
}
|
|
51785
52418
|
}
|
|
51786
52419
|
}
|
|
@@ -51875,29 +52508,29 @@ function createCompareDataFeedsHandler(deps) {
|
|
|
51875
52508
|
});
|
|
51876
52509
|
return withToolError("Compare data feeds failed", logger58, () => {
|
|
51877
52510
|
const result = executeCompare(validation.data);
|
|
51878
|
-
return Promise.resolve(structuredToolSuccess(
|
|
52511
|
+
return Promise.resolve(structuredToolSuccess(z98.object(COMPARE_OUTPUT_SCHEMA), result));
|
|
51879
52512
|
});
|
|
51880
52513
|
};
|
|
51881
52514
|
}
|
|
51882
52515
|
var COMPARE_OUTPUT_SCHEMA = {
|
|
51883
|
-
feedAPath:
|
|
51884
|
-
feedBPath:
|
|
51885
|
-
keyPath:
|
|
51886
|
-
counts:
|
|
51887
|
-
entriesInA:
|
|
51888
|
-
entriesInB:
|
|
51889
|
-
onlyInA:
|
|
51890
|
-
onlyInB:
|
|
51891
|
-
inBoth:
|
|
51892
|
-
fieldDifferences:
|
|
52516
|
+
feedAPath: z98.string(),
|
|
52517
|
+
feedBPath: z98.string(),
|
|
52518
|
+
keyPath: z98.string(),
|
|
52519
|
+
counts: z98.object({
|
|
52520
|
+
entriesInA: z98.number(),
|
|
52521
|
+
entriesInB: z98.number(),
|
|
52522
|
+
onlyInA: z98.number(),
|
|
52523
|
+
onlyInB: z98.number(),
|
|
52524
|
+
inBoth: z98.number(),
|
|
52525
|
+
fieldDifferences: z98.number()
|
|
51893
52526
|
}),
|
|
51894
|
-
coverage:
|
|
51895
|
-
onlyInA:
|
|
51896
|
-
onlyInB:
|
|
51897
|
-
inBoth:
|
|
52527
|
+
coverage: z98.object({
|
|
52528
|
+
onlyInA: z98.array(z98.string()),
|
|
52529
|
+
onlyInB: z98.array(z98.string()),
|
|
52530
|
+
inBoth: z98.array(z98.string())
|
|
51898
52531
|
}),
|
|
51899
|
-
fieldDifferences:
|
|
51900
|
-
summary:
|
|
52532
|
+
fieldDifferences: z98.array(z98.unknown()),
|
|
52533
|
+
summary: z98.string()
|
|
51901
52534
|
};
|
|
51902
52535
|
var COMPARE_DESCRIPTION = "Diff two upstream data feeds (YAML or JSON files) along coverage and per-field axes. Returns which entries exist in A, B, both, plus optional field-level diffs across matched entries. v1 takes file paths only (no URL fetch \u2014 that needs an SSRF design pass). Both feeds must be a top-level array OR a top-level object with exactly one array field.";
|
|
51903
52536
|
function registerCompareDataFeedsTool(server, deps) {
|
|
@@ -51927,9 +52560,9 @@ function registerCompareDataFeedsTool(server, deps) {
|
|
|
51927
52560
|
}
|
|
51928
52561
|
|
|
51929
52562
|
// src/mcp/tools/query-task-state-tool.ts
|
|
51930
|
-
import { z as
|
|
51931
|
-
var QueryTaskStateInputSchema =
|
|
51932
|
-
taskId:
|
|
52563
|
+
import { z as z99 } from "zod";
|
|
52564
|
+
var QueryTaskStateInputSchema = z99.object({
|
|
52565
|
+
taskId: z99.string().min(1).max(128).describe("Task ID whose structured state log should be read")
|
|
51933
52566
|
});
|
|
51934
52567
|
function queryTaskStateHandler(args, ctx) {
|
|
51935
52568
|
const parsed = QueryTaskStateInputSchema.safeParse(args);
|
|
@@ -51964,7 +52597,7 @@ function queryTaskStateHandler(args, ctx) {
|
|
|
51964
52597
|
function registerQueryTaskStateTool(server, deps) {
|
|
51965
52598
|
const logger58 = deps.logger ?? createLogger({ tool: "query_task_state" });
|
|
51966
52599
|
const toolSchema = {
|
|
51967
|
-
taskId:
|
|
52600
|
+
taskId: z99.string().min(1).max(128).describe("Task ID whose structured state log should be read")
|
|
51968
52601
|
};
|
|
51969
52602
|
const description = "Read the structured state log for a task ID and return the current snapshot. Includes Magentic-One Task Ledger (facts/guesses/openQuestions) and Progress Ledger (per-step reflections with suggestedAction) when orchestrators have written them. Structured state is only written when NEXUS_TASK_STATE_ENABLED=1 was set during the orchestrate invocation.";
|
|
51970
52603
|
const secureHandler = createSecureHandler(queryTaskStateHandler, {
|
|
@@ -51986,28 +52619,28 @@ function registerQueryTaskStateTool(server, deps) {
|
|
|
51986
52619
|
}
|
|
51987
52620
|
|
|
51988
52621
|
// src/mcp/tools/ci-health-check-tool.ts
|
|
51989
|
-
import { z as
|
|
52622
|
+
import { z as z102 } from "zod";
|
|
51990
52623
|
|
|
51991
52624
|
// src/mcp/tools/ci-health-log.ts
|
|
51992
52625
|
import { appendFileSync as appendFileSync5, existsSync as existsSync13, readFileSync as readFileSync11, statSync as statSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
51993
|
-
import { z as
|
|
52626
|
+
import { z as z101 } from "zod";
|
|
51994
52627
|
|
|
51995
52628
|
// src/mcp/tools/ci-health-types.ts
|
|
51996
|
-
import { z as
|
|
51997
|
-
var CiHealthStatusSchema =
|
|
52629
|
+
import { z as z100 } from "zod";
|
|
52630
|
+
var CiHealthStatusSchema = z100.enum(["healthy", "degraded", "outage", "unknown"]);
|
|
51998
52631
|
|
|
51999
52632
|
// src/mcp/tools/ci-health-log.ts
|
|
52000
52633
|
var logger52 = createLogger({ component: "ci-health-log" });
|
|
52001
|
-
var CiHealthEventSchema =
|
|
52002
|
-
v:
|
|
52003
|
-
ts:
|
|
52634
|
+
var CiHealthEventSchema = z101.object({
|
|
52635
|
+
v: z101.literal(1),
|
|
52636
|
+
ts: z101.iso.datetime(),
|
|
52004
52637
|
status: CiHealthStatusSchema,
|
|
52005
|
-
repo:
|
|
52006
|
-
signals:
|
|
52007
|
-
|
|
52008
|
-
source:
|
|
52638
|
+
repo: z101.string().optional(),
|
|
52639
|
+
signals: z101.array(
|
|
52640
|
+
z101.object({
|
|
52641
|
+
source: z101.enum(["github-status", "repo-activity-window"]),
|
|
52009
52642
|
status: CiHealthStatusSchema,
|
|
52010
|
-
evidence:
|
|
52643
|
+
evidence: z101.string()
|
|
52011
52644
|
})
|
|
52012
52645
|
)
|
|
52013
52646
|
});
|
|
@@ -52087,17 +52720,17 @@ function eventFromCheck(params) {
|
|
|
52087
52720
|
}
|
|
52088
52721
|
|
|
52089
52722
|
// src/mcp/tools/ci-health-check-tool.ts
|
|
52090
|
-
var CiHealthCheckInputSchema =
|
|
52723
|
+
var CiHealthCheckInputSchema = z102.object({
|
|
52091
52724
|
/**
|
|
52092
52725
|
* Repo to check for the recent-runs activity signal (in `owner/repo` form).
|
|
52093
52726
|
* Optional — when omitted, only the status-page signal is consulted.
|
|
52094
52727
|
*/
|
|
52095
|
-
repo:
|
|
52728
|
+
repo: z102.string().regex(/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/, "Must be owner/repo form").optional().describe("GitHub repo (owner/repo) to check for recent CI activity. Optional."),
|
|
52096
52729
|
/**
|
|
52097
52730
|
* How far back to look for recent-runs activity (minutes). Default 30 —
|
|
52098
52731
|
* matches the typical wedge-detection window from the #3070 / #3076 outages.
|
|
52099
52732
|
*/
|
|
52100
|
-
activityWindowMinutes:
|
|
52733
|
+
activityWindowMinutes: z102.number().int().min(5).max(180).default(30).describe("Recent-runs lookback window in minutes (5-180; default 30).")
|
|
52101
52734
|
});
|
|
52102
52735
|
var STATUS_PAGE_URL = "https://www.githubstatus.com/api/v2/components.json";
|
|
52103
52736
|
function mapStatusPageStatus(raw) {
|
|
@@ -52256,8 +52889,8 @@ var DESCRIPTION = "Check CI infrastructure health before triggering / polling ru
|
|
|
52256
52889
|
function registerCiHealthCheckTool(server, deps) {
|
|
52257
52890
|
const logger58 = deps.logger ?? createLogger({ tool: "ci_health_check" });
|
|
52258
52891
|
const toolSchema = {
|
|
52259
|
-
repo:
|
|
52260
|
-
activityWindowMinutes:
|
|
52892
|
+
repo: z102.string().regex(/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/, "Must be owner/repo form").optional().describe("GitHub repo (owner/repo) to check for recent CI activity. Optional."),
|
|
52893
|
+
activityWindowMinutes: z102.number().int().min(5).max(180).optional().describe("Recent-runs lookback window in minutes (5-180; default 30).")
|
|
52261
52894
|
};
|
|
52262
52895
|
const secureHandler = createSecureHandler((args) => ciHealthCheckHandler(args, logger58), {
|
|
52263
52896
|
toolName: "ci_health_check",
|
|
@@ -52283,18 +52916,18 @@ function registerCiHealthCheckTool(server, deps) {
|
|
|
52283
52916
|
|
|
52284
52917
|
// src/mcp/tools/quality-gate-tool.ts
|
|
52285
52918
|
import { statSync as statSync3 } from "node:fs";
|
|
52286
|
-
import { z as
|
|
52287
|
-
var QualityCheckSchema =
|
|
52919
|
+
import { z as z103 } from "zod";
|
|
52920
|
+
var QualityCheckSchema = z103.enum(["typecheck", "lint", "tests", "build", "security"]);
|
|
52288
52921
|
var DEFAULT_CHECKS = ["typecheck", "lint", "tests"];
|
|
52289
|
-
var RunQualityGateInputSchema =
|
|
52922
|
+
var RunQualityGateInputSchema = z103.object({
|
|
52290
52923
|
/** Project directory to run checks against. Must resolve inside the repo/cwd root. */
|
|
52291
|
-
projectDir:
|
|
52924
|
+
projectDir: z103.string().optional().describe(
|
|
52292
52925
|
"Project directory to run checks against (default: cwd). Must stay inside the repo root."
|
|
52293
52926
|
),
|
|
52294
52927
|
/** Which allowlisted checks to run. */
|
|
52295
|
-
checks:
|
|
52928
|
+
checks: z103.array(QualityCheckSchema).nonempty().default([...DEFAULT_CHECKS]).describe("Allowlisted checks to run (default: ['typecheck','lint','tests'])."),
|
|
52296
52929
|
/** 1-based iteration counter, forwarded to the engine for feedback context. */
|
|
52297
|
-
iteration:
|
|
52930
|
+
iteration: z103.number().int().min(1).default(1).describe("1-based iteration number (default 1).")
|
|
52298
52931
|
});
|
|
52299
52932
|
function validateProjectDir(raw) {
|
|
52300
52933
|
const candidate = raw ?? process.cwd();
|
|
@@ -52369,11 +53002,11 @@ var DESCRIPTION2 = "Run the QA quality gate (#1684 engine) against a project dir
|
|
|
52369
53002
|
function registerRunQualityGateTool(server, deps) {
|
|
52370
53003
|
const logger58 = deps.logger ?? createLogger({ tool: "run_quality_gate" });
|
|
52371
53004
|
const toolSchema = {
|
|
52372
|
-
projectDir:
|
|
53005
|
+
projectDir: z103.string().optional().describe(
|
|
52373
53006
|
"Project directory to run checks against (default: cwd). Must stay inside the repo root."
|
|
52374
53007
|
),
|
|
52375
|
-
checks:
|
|
52376
|
-
iteration:
|
|
53008
|
+
checks: z103.array(QualityCheckSchema).nonempty().optional().describe("Allowlisted checks to run (default: ['typecheck','lint','tests'])."),
|
|
53009
|
+
iteration: z103.number().int().min(1).optional().describe("1-based iteration number (default 1).")
|
|
52377
53010
|
};
|
|
52378
53011
|
const secureHandler = createSecureHandler(
|
|
52379
53012
|
(args) => runQualityGateHandler(args, logger58),
|
|
@@ -52403,7 +53036,7 @@ function registerRunQualityGateTool(server, deps) {
|
|
|
52403
53036
|
// src/mcp/tools/verify-audit-chain-tool.ts
|
|
52404
53037
|
import * as fs8 from "node:fs/promises";
|
|
52405
53038
|
import * as path7 from "node:path";
|
|
52406
|
-
import { z as
|
|
53039
|
+
import { z as z104 } from "zod";
|
|
52407
53040
|
|
|
52408
53041
|
// src/cli-server-auth.ts
|
|
52409
53042
|
function resolveAuthEnabled(config) {
|
|
@@ -52577,11 +53210,11 @@ function logSecurityConfig(logger58, config) {
|
|
|
52577
53210
|
}
|
|
52578
53211
|
|
|
52579
53212
|
// src/mcp/tools/verify-audit-chain-tool.ts
|
|
52580
|
-
var VerifyAuditChainInputSchema =
|
|
52581
|
-
logDir:
|
|
53213
|
+
var VerifyAuditChainInputSchema = z104.object({
|
|
53214
|
+
logDir: z104.string().min(1).max(512).describe(
|
|
52582
53215
|
"Filesystem path to the FileAuditStorage log directory. Must lie inside the nexus data dir, a repo-local `.nexus-agents/`, or the configured `security.audit.logDir`. Tool reads all `audit-*.jsonl` files in lexicographic order and verifies the combined chain."
|
|
52583
53216
|
),
|
|
52584
|
-
filePrefix:
|
|
53217
|
+
filePrefix: z104.string().min(1).max(64).optional().default(DEFAULT_AUDIT_FILE_PREFIX).describe(
|
|
52585
53218
|
'Filename prefix for audit log files (defaults to "audit"). Files matching `${filePrefix}-*.jsonl` will be verified.'
|
|
52586
53219
|
)
|
|
52587
53220
|
});
|
|
@@ -52710,10 +53343,10 @@ async function handler2(args, ctx, security) {
|
|
|
52710
53343
|
function registerVerifyAuditChainTool(server, deps) {
|
|
52711
53344
|
const logger58 = deps.logger ?? createLogger({ tool: "verify_audit_chain" });
|
|
52712
53345
|
const toolSchema = {
|
|
52713
|
-
logDir:
|
|
53346
|
+
logDir: z104.string().min(1).max(512).describe(
|
|
52714
53347
|
"Filesystem path to the FileAuditStorage log directory. Must lie inside the nexus data dir, a repo-local `.nexus-agents/`, or the configured `security.audit.logDir`. Tool reads all `audit-*.jsonl` files and verifies the combined hash chain."
|
|
52715
53348
|
),
|
|
52716
|
-
filePrefix:
|
|
53349
|
+
filePrefix: z104.string().min(1).max(64).optional().describe(
|
|
52717
53350
|
'Filename prefix for audit log files (defaults to "audit"). Files matching `${filePrefix}-*.jsonl` will be verified.'
|
|
52718
53351
|
)
|
|
52719
53352
|
};
|
|
@@ -52737,15 +53370,15 @@ function registerVerifyAuditChainTool(server, deps) {
|
|
|
52737
53370
|
}
|
|
52738
53371
|
|
|
52739
53372
|
// src/mcp/tools/suggest-research-tasks-tool.ts
|
|
52740
|
-
import { z as
|
|
53373
|
+
import { z as z105 } from "zod";
|
|
52741
53374
|
var SUGGEST_RESEARCH_TASKS_NOTE = "Suggestions derived from external research (untrusted); review before acting \u2014 nothing was executed or filed.";
|
|
52742
53375
|
var RESEARCH_BUDGET_MS = 2e4;
|
|
52743
53376
|
var RESEARCH_TIMED_OUT = /* @__PURE__ */ Symbol("research-budget-exceeded");
|
|
52744
53377
|
async function withResearchBudget(p, ms) {
|
|
52745
53378
|
let timer;
|
|
52746
|
-
const budget = new Promise((
|
|
53379
|
+
const budget = new Promise((resolve13) => {
|
|
52747
53380
|
timer = setTimeout(() => {
|
|
52748
|
-
|
|
53381
|
+
resolve13(RESEARCH_TIMED_OUT);
|
|
52749
53382
|
}, ms);
|
|
52750
53383
|
});
|
|
52751
53384
|
try {
|
|
@@ -52754,11 +53387,11 @@ async function withResearchBudget(p, ms) {
|
|
|
52754
53387
|
if (timer !== void 0) clearTimeout(timer);
|
|
52755
53388
|
}
|
|
52756
53389
|
}
|
|
52757
|
-
var SuggestResearchTasksInputSchema =
|
|
52758
|
-
topic:
|
|
52759
|
-
qualityThreshold:
|
|
52760
|
-
maxTriggers:
|
|
52761
|
-
existingTaskIds:
|
|
53390
|
+
var SuggestResearchTasksInputSchema = z105.object({
|
|
53391
|
+
topic: z105.string().optional().describe("Topic filter passed to research_discover. Optional."),
|
|
53392
|
+
qualityThreshold: z105.number().min(0).max(10).optional().describe("Minimum quality score (0-10) a discovery must meet to be suggested. Optional."),
|
|
53393
|
+
maxTriggers: z105.number().int().min(1).optional().describe("Max number of candidate tasks to return (>=1). Optional."),
|
|
53394
|
+
existingTaskIds: z105.array(z105.string()).optional().describe("Known task IDs to skip (dedup). Optional.")
|
|
52762
53395
|
});
|
|
52763
53396
|
function toTriggerConfig(input) {
|
|
52764
53397
|
return {
|
|
@@ -52815,10 +53448,10 @@ var DESCRIPTION3 = "SUGGEST-ONLY: surface candidate pipeline tasks for human/orc
|
|
|
52815
53448
|
function registerSuggestResearchTasksTool(server, deps) {
|
|
52816
53449
|
const logger58 = deps.logger ?? createLogger({ tool: "suggest_research_tasks" });
|
|
52817
53450
|
const toolSchema = {
|
|
52818
|
-
topic:
|
|
52819
|
-
qualityThreshold:
|
|
52820
|
-
maxTriggers:
|
|
52821
|
-
existingTaskIds:
|
|
53451
|
+
topic: z105.string().optional().describe("Topic filter passed to research_discover. Optional."),
|
|
53452
|
+
qualityThreshold: z105.number().min(0).max(10).optional().describe("Minimum quality score (0-10) a discovery must meet to be suggested. Optional."),
|
|
53453
|
+
maxTriggers: z105.number().int().min(1).optional().describe("Max number of candidate tasks to return (>=1). Optional."),
|
|
53454
|
+
existingTaskIds: z105.array(z105.string()).optional().describe("Known task IDs to skip (dedup). Optional.")
|
|
52822
53455
|
};
|
|
52823
53456
|
const secureHandler = createSecureHandler(
|
|
52824
53457
|
(args) => suggestResearchTasksHandler(args, logger58),
|
|
@@ -52846,7 +53479,7 @@ function registerSuggestResearchTasksTool(server, deps) {
|
|
|
52846
53479
|
}
|
|
52847
53480
|
|
|
52848
53481
|
// src/mcp/tools/run-tool.ts
|
|
52849
|
-
import { z as
|
|
53482
|
+
import { z as z109 } from "zod";
|
|
52850
53483
|
import { randomUUID as randomUUID19 } from "node:crypto";
|
|
52851
53484
|
|
|
52852
53485
|
// src/orchestration/consensus-enforcement-mode.ts
|
|
@@ -53468,7 +54101,7 @@ function createMetaOrchestrator(options) {
|
|
|
53468
54101
|
|
|
53469
54102
|
// src/orchestration/meta-shadow-selector.ts
|
|
53470
54103
|
import { appendFileSync as appendFileSync6, existsSync as existsSync14, readFileSync as readFileSync12 } from "node:fs";
|
|
53471
|
-
import { z as
|
|
54104
|
+
import { z as z106 } from "zod";
|
|
53472
54105
|
var SHADOW_STRATEGY_ARMS = [
|
|
53473
54106
|
"single-shot",
|
|
53474
54107
|
"dev-pipeline",
|
|
@@ -53557,19 +54190,19 @@ function createHydratableSelector() {
|
|
|
53557
54190
|
var META_OUTCOME_SCHEMA_VERSION = 1;
|
|
53558
54191
|
var HYDRATE_LOOKBACK_DAYS = 30;
|
|
53559
54192
|
var HYDRATE_LOOKBACK_MS = HYDRATE_LOOKBACK_DAYS * 24 * 60 * 60 * 1e3;
|
|
53560
|
-
var PersistedContextSchema =
|
|
53561
|
-
taskComplexity:
|
|
53562
|
-
contextLengthNormalized:
|
|
53563
|
-
isCodeTask:
|
|
53564
|
-
isReasoningTask:
|
|
53565
|
-
budgetUtilization:
|
|
53566
|
-
timePressure:
|
|
54193
|
+
var PersistedContextSchema = z106.object({
|
|
54194
|
+
taskComplexity: z106.number(),
|
|
54195
|
+
contextLengthNormalized: z106.number(),
|
|
54196
|
+
isCodeTask: z106.number(),
|
|
54197
|
+
isReasoningTask: z106.number(),
|
|
54198
|
+
budgetUtilization: z106.number(),
|
|
54199
|
+
timePressure: z106.number()
|
|
53567
54200
|
});
|
|
53568
|
-
var PersistedMetaOutcomeSchema =
|
|
53569
|
-
schema:
|
|
53570
|
-
timestamp:
|
|
53571
|
-
strategy:
|
|
53572
|
-
success:
|
|
54201
|
+
var PersistedMetaOutcomeSchema = z106.object({
|
|
54202
|
+
schema: z106.literal(META_OUTCOME_SCHEMA_VERSION),
|
|
54203
|
+
timestamp: z106.string(),
|
|
54204
|
+
strategy: z106.enum(SHADOW_STRATEGY_ARMS),
|
|
54205
|
+
success: z106.boolean(),
|
|
53573
54206
|
context: PersistedContextSchema
|
|
53574
54207
|
});
|
|
53575
54208
|
var persistLogger = createLogger({ component: "MetaShadowSelector" });
|
|
@@ -53962,7 +54595,7 @@ function evaluateMetaStrategyReadiness(result, config = DEFAULT_META_STRATEGY_RE
|
|
|
53962
54595
|
}
|
|
53963
54596
|
|
|
53964
54597
|
// src/mcp/tools/dev-pipeline-tool.ts
|
|
53965
|
-
import { z as
|
|
54598
|
+
import { z as z107 } from "zod";
|
|
53966
54599
|
import * as fs10 from "node:fs";
|
|
53967
54600
|
import { randomUUID as randomUUID17 } from "node:crypto";
|
|
53968
54601
|
|
|
@@ -54016,8 +54649,11 @@ function warningsField(result) {
|
|
|
54016
54649
|
return result.warnings !== void 0 ? { warnings: result.warnings } : {};
|
|
54017
54650
|
}
|
|
54018
54651
|
function securityStatus(result) {
|
|
54019
|
-
|
|
54020
|
-
|
|
54652
|
+
const comparison = result.securityComparison ?? {};
|
|
54653
|
+
if (result.securityRan !== true || result.securityComparison?.complete === false) {
|
|
54654
|
+
return { status: "unmeasured", ...comparison };
|
|
54655
|
+
}
|
|
54656
|
+
return { status: result.securityPassed ? "passed" : "failed", ...comparison };
|
|
54021
54657
|
}
|
|
54022
54658
|
function planVoteVerdictFields(result) {
|
|
54023
54659
|
return {
|
|
@@ -54030,7 +54666,7 @@ function planVoteVerdictFields(result) {
|
|
|
54030
54666
|
}
|
|
54031
54667
|
|
|
54032
54668
|
// src/mcp/tools/dev-pipeline-tool.ts
|
|
54033
|
-
import { resolve as
|
|
54669
|
+
import { resolve as resolve11 } from "node:path";
|
|
54034
54670
|
|
|
54035
54671
|
// src/mcp/tools/dev-pipeline-options.ts
|
|
54036
54672
|
function buildPipelineOptions(input, trustTier, auditLogger) {
|
|
@@ -54223,48 +54859,48 @@ var DEV_PIPELINE_DRY_RUN_NOTE = "This was a dry run (plan+vote), which always ru
|
|
|
54223
54859
|
function dispatchNoteFor(dryRun) {
|
|
54224
54860
|
return dryRun ? DEV_PIPELINE_DRY_RUN_NOTE : DEV_PIPELINE_ASYNC_HINT;
|
|
54225
54861
|
}
|
|
54226
|
-
var DevPipelineInputSchema =
|
|
54862
|
+
var DevPipelineInputSchema = z107.object({
|
|
54227
54863
|
/** Direct task instructions. */
|
|
54228
|
-
task:
|
|
54864
|
+
task: z107.string().max(1e4).optional().describe("Direct task instructions (what to build)"),
|
|
54229
54865
|
/** Declared provenance of the task text (#6795); omitted means '3'. */
|
|
54230
54866
|
sourceTrustTier: TaskSourceTrustTierSchema,
|
|
54231
54867
|
/** Path to a plan file (.md, .yaml, .txt) to use as input. */
|
|
54232
|
-
planFile:
|
|
54868
|
+
planFile: z107.string().max(500).optional().describe("Path to a plan/spec file to use as input"),
|
|
54233
54869
|
/** Whether to run in dry-run mode (plan+vote only, no implementation). */
|
|
54234
|
-
dryRun:
|
|
54870
|
+
dryRun: z107.boolean().default(false).describe("If true, stop after plan+vote (no implementation)"),
|
|
54235
54871
|
/** Maximum vote iterations before proceeding (default: 3). */
|
|
54236
|
-
maxVoteIterations:
|
|
54872
|
+
maxVoteIterations: z107.number().int().min(1).max(5).default(3).describe("Max plan\u2192vote iterations"),
|
|
54237
54873
|
/** Maximum QA iterations per task (default: 3). */
|
|
54238
|
-
maxQaIterations:
|
|
54874
|
+
maxQaIterations: z107.number().int().min(1).max(5).default(3).describe("Max QA review iterations per task"),
|
|
54239
54875
|
/** Working directory for the pipeline (default: cwd). Used for security scan and context. */
|
|
54240
|
-
workingDir:
|
|
54876
|
+
workingDir: z107.string().max(500).optional().describe("Working directory (default: cwd)"),
|
|
54241
54877
|
/** GitHub issue number to track progress on. Updates posted as comments. */
|
|
54242
|
-
issueNumber:
|
|
54878
|
+
issueNumber: z107.number().int().positive().optional().describe("GitHub issue to post progress to"),
|
|
54243
54879
|
/** GitHub repo (owner/name) for issue tracking. */
|
|
54244
|
-
repo:
|
|
54880
|
+
repo: z107.string().max(200).optional().describe("GitHub repo for issue tracking (e.g., owner/repo)"),
|
|
54245
54881
|
/** Task tracking backend: github, gitlab, or json (default: json). */
|
|
54246
|
-
trackerBackend:
|
|
54882
|
+
trackerBackend: z107.enum(["github", "gitlab", "json"]).default("json").describe("Task tracking backend for issue creation"),
|
|
54247
54883
|
/** Labels to apply to created issues. */
|
|
54248
|
-
labels:
|
|
54884
|
+
labels: z107.array(z107.string()).optional().describe("Labels for created issues"),
|
|
54249
54885
|
/** Session ID for checkpoint/resume. Enables crash recovery. */
|
|
54250
|
-
sessionId:
|
|
54886
|
+
sessionId: z107.string().max(128).regex(/^[a-zA-Z0-9_-]+$/).optional().describe("Session ID for checkpoint/resume (crash recovery)"),
|
|
54251
54887
|
/**
|
|
54252
54888
|
* TESTS ONLY — when true, voters return random decisions. Must not be used as
|
|
54253
54889
|
* a fallback when adapters are unavailable; configure an adapter instead. (#2319)
|
|
54254
54890
|
*/
|
|
54255
|
-
simulateVotes:
|
|
54891
|
+
simulateVotes: z107.boolean().default(false).describe("TESTS ONLY \u2014 random output, must not be used for real decisions (#2319)"),
|
|
54256
54892
|
/** Voting strategy for consensus stages. */
|
|
54257
54893
|
votingStrategy: VotingStrategySchema.optional().describe(
|
|
54258
54894
|
"Voting strategy for plan approval (default: higher_order)"
|
|
54259
54895
|
),
|
|
54260
54896
|
/** Use 3 agents instead of 6 for faster voting. */
|
|
54261
|
-
quickMode:
|
|
54897
|
+
quickMode: z107.boolean().default(false).describe("Use 3 agents instead of 6 for faster consensus voting"),
|
|
54262
54898
|
/**
|
|
54263
54899
|
* Deadline for EACH stage call in milliseconds (min 30s, max 600s), not a
|
|
54264
54900
|
* budget for the whole run (#6736). Replaces every stage's default, the
|
|
54265
54901
|
* vote's included; clamped to the `pipeline` class guard.
|
|
54266
54902
|
*/
|
|
54267
|
-
timeoutMs:
|
|
54903
|
+
timeoutMs: z107.number().int().min(3e4).max(6e5).optional().describe(
|
|
54268
54904
|
"Max time for EACH stage call in ms (30000-600000), not for the whole run; applies to every stage, the vote included, and to each plan/vote and implement/QA iteration. A stage past it fails with a timeout and its model calls are aborted. Default: the vote stage gets the multi-LLM panel guard (900000 unless overridden), other stages the pipeline guard (1800000 unless overridden)"
|
|
54269
54905
|
),
|
|
54270
54906
|
/**
|
|
@@ -54272,7 +54908,7 @@ var DevPipelineInputSchema = z106.object({
|
|
|
54272
54908
|
* dispatch. A caller who learned `mode: 'async'` elsewhere gets an error
|
|
54273
54909
|
* naming `dispatch` rather than the bare enum message (#4968).
|
|
54274
54910
|
*/
|
|
54275
|
-
mode:
|
|
54911
|
+
mode: z107.enum(["autonomous", "harness"], { error: modeEnumErrorNamingDispatch }).default("autonomous").describe(
|
|
54276
54912
|
"'autonomous': full pipeline. 'harness': stops after decompose, returns tasks for caller to implement. (Not the async switch \u2014 that is `dispatch`.)"
|
|
54277
54913
|
),
|
|
54278
54914
|
/**
|
|
@@ -54286,11 +54922,11 @@ var DevPipelineInputSchema = z106.object({
|
|
|
54286
54922
|
*/
|
|
54287
54923
|
dispatch: dispatchFieldDefaultSync("Ignored for dryRun."),
|
|
54288
54924
|
/** Local pre-ship quality gate (typecheck/lint/tests) mode (#3356). */
|
|
54289
|
-
qualityGate:
|
|
54925
|
+
qualityGate: z107.enum(["off", "advisory", "blocking"]).default("off").describe(
|
|
54290
54926
|
"Pre-ship local quality gate. 'off' (default): skip. 'advisory': run + record feedback, never fail. 'blocking': a red gate fails the pipeline."
|
|
54291
54927
|
),
|
|
54292
54928
|
/** Opt-in per-run token budget — a safety cap for unattended runs (#3395). */
|
|
54293
|
-
maxBudgetTokens:
|
|
54929
|
+
maxBudgetTokens: z107.number().int().positive().optional().describe(
|
|
54294
54930
|
"Per-run token ceiling (#3395). When set, expert calls stop (returning failures) once cumulative usage crosses it \u2014 a hard-stop safety cap for unattended/multi-day runs. Omit to disable (default)."
|
|
54295
54931
|
)
|
|
54296
54932
|
});
|
|
@@ -54319,7 +54955,7 @@ function containWorkingDir(workingDir) {
|
|
|
54319
54955
|
const roots = [process.cwd()];
|
|
54320
54956
|
const workspaceRoot = getActiveWorkspaceRoot();
|
|
54321
54957
|
if (workspaceRoot !== void 0) roots.push(workspaceRoot);
|
|
54322
|
-
const absolute =
|
|
54958
|
+
const absolute = resolve11(workingDir);
|
|
54323
54959
|
for (const root of roots) {
|
|
54324
54960
|
const contained = resolveInsideRoot(absolute, root);
|
|
54325
54961
|
if (contained !== null) return contained;
|
|
@@ -54377,7 +55013,7 @@ async function executeDevPipelineBody(taskText, stages, pipelineOptions, simulat
|
|
|
54377
55013
|
detail: output2
|
|
54378
55014
|
});
|
|
54379
55015
|
}
|
|
54380
|
-
return structuredToolSuccess(
|
|
55016
|
+
return structuredToolSuccess(z107.record(z107.string(), z107.unknown()), output2);
|
|
54381
55017
|
}
|
|
54382
55018
|
function describeIncompleteRun(result) {
|
|
54383
55019
|
if (result.planStatus !== void 0) {
|
|
@@ -54509,33 +55145,33 @@ function registerDevPipelineTool(server, deps) {
|
|
|
54509
55145
|
}
|
|
54510
55146
|
|
|
54511
55147
|
// src/mcp/tools/pipeline-tool.ts
|
|
54512
|
-
import { z as
|
|
55148
|
+
import { z as z108 } from "zod";
|
|
54513
55149
|
import * as fs11 from "node:fs";
|
|
54514
55150
|
import { randomUUID as randomUUID18 } from "node:crypto";
|
|
54515
55151
|
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.";
|
|
54516
|
-
var PipelineInputSchema =
|
|
55152
|
+
var PipelineInputSchema = z108.object({
|
|
54517
55153
|
/** The task to execute. */
|
|
54518
|
-
task:
|
|
55154
|
+
task: z108.string().min(5).max(1e4).describe("Task description \u2014 pipeline template auto-selected based on content"),
|
|
54519
55155
|
/** Path to a spec file (.md, .yaml) to use as task input. */
|
|
54520
|
-
specFile:
|
|
55156
|
+
specFile: z108.string().max(500).optional().describe("Path to a spec file \u2014 content prepended to task for greenfield projects"),
|
|
54521
55157
|
/** Override template — see `listTemplateIds()` for the canonical list (#2728). Auto-detected if omitted. */
|
|
54522
|
-
template:
|
|
55158
|
+
template: z108.string().max(50).optional().describe(`Pipeline template override. Available: ${listTemplateIds().join(", ")}`),
|
|
54523
55159
|
/** Voting strategy for consensus stages. */
|
|
54524
55160
|
votingStrategy: VotingStrategySchema.optional().describe(
|
|
54525
55161
|
"Voting strategy for plan approval. simple_majority (default), supermajority (67%), unanimous, higher_order (Bayesian), opinion_wise"
|
|
54526
55162
|
),
|
|
54527
55163
|
/** Use 3 agents instead of 7 for faster voting. */
|
|
54528
|
-
quickMode:
|
|
55164
|
+
quickMode: z108.boolean().default(false).describe("Use 3 agents instead of 7 for faster consensus voting"),
|
|
54529
55165
|
/**
|
|
54530
55166
|
* Deadline for EACH stage in milliseconds (min 30s, max 600s), not a budget
|
|
54531
55167
|
* for the whole run (#6730). Replaces every stage's default, the vote's
|
|
54532
55168
|
* included; clamped to the `pipeline` class guard.
|
|
54533
55169
|
*/
|
|
54534
|
-
timeoutMs:
|
|
55170
|
+
timeoutMs: z108.number().int().min(3e4).max(6e5).optional().describe(
|
|
54535
55171
|
"Max time for EACH stage in ms (30000-600000), not for the whole run; applies to every stage, the vote included. Default: the vote stage gets the multi-LLM panel guard (900000 unless overridden), other stages 120000"
|
|
54536
55172
|
),
|
|
54537
55173
|
/** Stop after planning/voting (no implementation). */
|
|
54538
|
-
dryRun:
|
|
55174
|
+
dryRun: z108.boolean().default(false).describe("Stop after vote stage (no implementation)"),
|
|
54539
55175
|
/**
|
|
54540
55176
|
* Dispatch mode (#3730). `sync` (default) runs the pipeline inline and
|
|
54541
55177
|
* returns the result — but a real multi-stage adaptive run can exceed the
|
|
@@ -54546,7 +55182,7 @@ var PipelineInputSchema = z107.object({
|
|
|
54546
55182
|
*/
|
|
54547
55183
|
...asyncDispatchInputDefaultSync("Ignored for dryRun."),
|
|
54548
55184
|
/** TESTS ONLY — random output, must not be used for real decisions. (#2319) */
|
|
54549
|
-
simulateVotes:
|
|
55185
|
+
simulateVotes: z108.boolean().default(false).describe("TESTS ONLY \u2014 random output, must not be used for real decisions (#2319)")
|
|
54550
55186
|
});
|
|
54551
55187
|
function buildOutput3(result, simulated) {
|
|
54552
55188
|
return {
|
|
@@ -54572,14 +55208,14 @@ function buildOutput3(result, simulated) {
|
|
|
54572
55208
|
rateLimitHint: result.error?.toLowerCase().includes("rate limit") === true ? "Consider using quickMode or increasing delay between pipeline runs" : void 0
|
|
54573
55209
|
};
|
|
54574
55210
|
}
|
|
54575
|
-
var VoteEvidenceSchema =
|
|
54576
|
-
approvalPercentage:
|
|
54577
|
-
voteRecordId:
|
|
55211
|
+
var VoteEvidenceSchema = z108.object({
|
|
55212
|
+
approvalPercentage: z108.number(),
|
|
55213
|
+
voteRecordId: z108.string().optional()
|
|
54578
55214
|
});
|
|
54579
|
-
var VoteResultSchema =
|
|
54580
|
-
VoteEvidenceSchema.extend({ kind:
|
|
54581
|
-
VoteEvidenceSchema.extend({ kind:
|
|
54582
|
-
VoteEvidenceSchema.extend({ kind:
|
|
55215
|
+
var VoteResultSchema = z108.discriminatedUnion("kind", [
|
|
55216
|
+
VoteEvidenceSchema.extend({ kind: z108.literal("approved") }),
|
|
55217
|
+
VoteEvidenceSchema.extend({ kind: z108.literal("rejected"), feedback: z108.string() }),
|
|
55218
|
+
VoteEvidenceSchema.extend({ kind: z108.literal("no_quorum"), reason: z108.string() })
|
|
54583
55219
|
]);
|
|
54584
55220
|
function isVoteResult(value) {
|
|
54585
55221
|
return VoteResultSchema.safeParse(value).success;
|
|
@@ -54681,7 +55317,7 @@ async function executePipelineBody(task, stages, run) {
|
|
|
54681
55317
|
detail: output2
|
|
54682
55318
|
});
|
|
54683
55319
|
}
|
|
54684
|
-
return structuredToolSuccess(
|
|
55320
|
+
return structuredToolSuccess(z108.record(z108.string(), z108.unknown()), output2);
|
|
54685
55321
|
}
|
|
54686
55322
|
function createPipelineAgentStages(input, config) {
|
|
54687
55323
|
return createAgentStages({
|
|
@@ -54832,9 +55468,9 @@ function cancellableExecutor(strategy, executor, signal) {
|
|
|
54832
55468
|
}
|
|
54833
55469
|
|
|
54834
55470
|
// src/mcp/tools/run-tool.ts
|
|
54835
|
-
var RunInputSchema =
|
|
54836
|
-
goal:
|
|
54837
|
-
forceStrategy:
|
|
55471
|
+
var RunInputSchema = z109.object({
|
|
55472
|
+
goal: z109.string().min(1).describe("Natural-language goal. nexus-agents selects how to execute it."),
|
|
55473
|
+
forceStrategy: z109.enum([
|
|
54838
55474
|
"single-shot",
|
|
54839
55475
|
"dev-pipeline",
|
|
54840
55476
|
"pipeline",
|
|
@@ -54846,10 +55482,10 @@ var RunInputSchema = z108.object({
|
|
|
54846
55482
|
]).optional().describe(
|
|
54847
55483
|
"Power-user override: force a specific strategy instead of letting the router choose."
|
|
54848
55484
|
),
|
|
54849
|
-
requiresConsensus:
|
|
54850
|
-
dependencyStructure:
|
|
54851
|
-
isNovel:
|
|
54852
|
-
execute:
|
|
55485
|
+
requiresConsensus: z109.boolean().optional().describe("Hint: the task needs a multi-perspective consensus decision."),
|
|
55486
|
+
dependencyStructure: z109.enum(["linear", "dag", "independent", "unknown"]).optional().describe("Hint: the dependency structure of the work."),
|
|
55487
|
+
isNovel: z109.boolean().optional().describe("Hint: this kind of task has not been seen before."),
|
|
55488
|
+
execute: z109.boolean().optional().describe(
|
|
54853
55489
|
"When true, actually run the selected strategy (if an executor is wired) and return its result; otherwise return the routing decision only (default false, read-only)."
|
|
54854
55490
|
),
|
|
54855
55491
|
/**
|
|
@@ -54864,7 +55500,7 @@ var RunInputSchema = z108.object({
|
|
|
54864
55500
|
* other, the call is REFUSED rather than executed: silently ignoring a
|
|
54865
55501
|
* do-not-act flag is the one outcome a governance substrate cannot allow.
|
|
54866
55502
|
*/
|
|
54867
|
-
dryRun:
|
|
55503
|
+
dryRun: z109.boolean().optional().describe(
|
|
54868
55504
|
"Plan and vote only, no implementation (#4806). Requires the dev-pipeline strategy \u2014 refused (never silently executed) when the router selects another."
|
|
54869
55505
|
),
|
|
54870
55506
|
/**
|
|
@@ -55100,12 +55736,12 @@ function registerRunTool(server, deps) {
|
|
|
55100
55736
|
}
|
|
55101
55737
|
|
|
55102
55738
|
// src/mcp/tools/list-available-models-tool.ts
|
|
55103
|
-
import { z as
|
|
55739
|
+
import { z as z110 } from "zod";
|
|
55104
55740
|
var DESCRIPTION5 = "Probe every model-discovery transport (OpenRouter API, the configured gateway, and the opencode/claude/codex/gemini CLIs) and report a per-transport health summary: probe ok/failed, model count, and a sample of usable ids. Models with open route breakers are excluded; each CLI reports whether its default-route breaker is open. Use it to validate the CLIs and APIs are wired and reachable. Read-only; does not change routing.";
|
|
55105
55741
|
var PROBE_TIMEOUT_MS = 12e3;
|
|
55106
|
-
var ListAvailableModelsInputSchema =
|
|
55107
|
-
includeModelIds:
|
|
55108
|
-
includeOpenRouter:
|
|
55742
|
+
var ListAvailableModelsInputSchema = z110.object({
|
|
55743
|
+
includeModelIds: z110.boolean().optional().describe("Include the full model-id list per transport (default false \u2192 sample of 5 only)."),
|
|
55744
|
+
includeOpenRouter: z110.boolean().optional().describe("Probe the OpenRouter live catalog (default true).")
|
|
55109
55745
|
});
|
|
55110
55746
|
async function probeSource(source, includeModelIds) {
|
|
55111
55747
|
let timer;
|
|
@@ -55214,8 +55850,8 @@ async function listAvailableModelsHandler(args, deps, logger58) {
|
|
|
55214
55850
|
function registerListAvailableModelsTool(server, deps) {
|
|
55215
55851
|
const logger58 = deps.logger ?? createLogger({ tool: "list_available_models" });
|
|
55216
55852
|
const toolSchema = {
|
|
55217
|
-
includeModelIds:
|
|
55218
|
-
includeOpenRouter:
|
|
55853
|
+
includeModelIds: z110.boolean().optional().describe("Include the full model-id list per transport (default false \u2192 sample of 5 only)."),
|
|
55854
|
+
includeOpenRouter: z110.boolean().optional().describe("Probe the OpenRouter live catalog (default true).")
|
|
55219
55855
|
};
|
|
55220
55856
|
const secureHandler = createSecureHandler(
|
|
55221
55857
|
(args) => listAvailableModelsHandler(args, deps, logger58),
|
|
@@ -55239,9 +55875,9 @@ function registerListAvailableModelsTool(server, deps) {
|
|
|
55239
55875
|
}
|
|
55240
55876
|
|
|
55241
55877
|
// src/mcp/tools/pr-review-eval-types.ts
|
|
55242
|
-
import { z as
|
|
55878
|
+
import { z as z111 } from "zod";
|
|
55243
55879
|
var MAX_EVAL_FINDINGS = 100;
|
|
55244
|
-
var VoterEvalFindingSchema =
|
|
55880
|
+
var VoterEvalFindingSchema = z111.object({
|
|
55245
55881
|
summary: RawFindingSchema.shape.summary,
|
|
55246
55882
|
location: RawFindingSchema.shape.location,
|
|
55247
55883
|
severity: RawFindingSchema.shape.severity.unwrap(),
|
|
@@ -55249,14 +55885,14 @@ var VoterEvalFindingSchema = z110.object({
|
|
|
55249
55885
|
gate: RawFindingSchema.shape.gate.extend({
|
|
55250
55886
|
named_assertion: RawFindingSchema.shape.claim.min(0)
|
|
55251
55887
|
}).optional(),
|
|
55252
|
-
verified:
|
|
55253
|
-
classification:
|
|
55254
|
-
source:
|
|
55888
|
+
verified: z111.boolean().optional(),
|
|
55889
|
+
classification: z111.enum(["TP", "FP", "FN", "excluded"]),
|
|
55890
|
+
source: z111.enum(["voter", "ground_truth"]),
|
|
55255
55891
|
/** Original index in the voter's raw findings; repeated TP evidence shares it. */
|
|
55256
|
-
findingIndex:
|
|
55257
|
-
knownBugIndex:
|
|
55892
|
+
findingIndex: z111.number().int().nonnegative().optional(),
|
|
55893
|
+
knownBugIndex: z111.number().int().nonnegative().optional(),
|
|
55258
55894
|
/** String fields shortened by the producer, never silently truncated. */
|
|
55259
|
-
truncatedFields:
|
|
55895
|
+
truncatedFields: z111.array(z111.enum(["summary", "location", "rationale", "gate.named_assertion"])).max(4).optional()
|
|
55260
55896
|
});
|
|
55261
55897
|
var PR_REVIEW_EVAL_ROLES = [
|
|
55262
55898
|
"architect",
|
|
@@ -55265,47 +55901,47 @@ var PR_REVIEW_EVAL_ROLES = [
|
|
|
55265
55901
|
"catfish",
|
|
55266
55902
|
"scope_steward"
|
|
55267
55903
|
];
|
|
55268
|
-
var PrReviewEvalRoleSchema =
|
|
55269
|
-
var PrReviewCaseClassSchema =
|
|
55270
|
-
var VoterEvalVerdictSchema =
|
|
55904
|
+
var PrReviewEvalRoleSchema = z111.enum(PR_REVIEW_EVAL_ROLES);
|
|
55905
|
+
var PrReviewCaseClassSchema = z111.enum(["buggy", "clean", "borderline"]);
|
|
55906
|
+
var VoterEvalVerdictSchema = z111.object({
|
|
55271
55907
|
/** Stable record id (e.g. `${runId}:${caseNumber}:${role}`). */
|
|
55272
|
-
id:
|
|
55908
|
+
id: z111.string().min(1).max(160),
|
|
55273
55909
|
/** The pr_review run / batch this verdict belongs to. */
|
|
55274
|
-
runId:
|
|
55910
|
+
runId: z111.string().min(1).max(64),
|
|
55275
55911
|
/** Dataset case identifier (the dataset's `number` field). */
|
|
55276
|
-
caseNumber:
|
|
55912
|
+
caseNumber: z111.string().min(1).max(80),
|
|
55277
55913
|
/** Rubric class of the case (ground-truth label). */
|
|
55278
55914
|
caseClass: PrReviewCaseClassSchema,
|
|
55279
55915
|
/** The voter role being scored. */
|
|
55280
55916
|
role: PrReviewEvalRoleSchema,
|
|
55281
55917
|
/** Verified findings that matched a known bug. */
|
|
55282
|
-
truePositives:
|
|
55918
|
+
truePositives: z111.number().int().nonnegative(),
|
|
55283
55919
|
/** Verified findings on clean code that matched no known bug. */
|
|
55284
|
-
falsePositives:
|
|
55920
|
+
falsePositives: z111.number().int().nonnegative(),
|
|
55285
55921
|
/** Known bugs this voter failed to flag. */
|
|
55286
|
-
falseNegatives:
|
|
55922
|
+
falseNegatives: z111.number().int().nonnegative(),
|
|
55287
55923
|
/** Optional for legacy records/count-only callers; [] means measured, no evidence. */
|
|
55288
|
-
findings:
|
|
55924
|
+
findings: z111.array(VoterEvalFindingSchema).max(MAX_EVAL_FINDINGS).optional(),
|
|
55289
55925
|
/** Number of evidence entries omitted at the cap; full tallies are unchanged. */
|
|
55290
|
-
findingsTruncated:
|
|
55926
|
+
findingsTruncated: z111.number().int().nonnegative().optional(),
|
|
55291
55927
|
/** Rubric version the ground truth was adjudicated under. */
|
|
55292
|
-
rubricVersion:
|
|
55928
|
+
rubricVersion: z111.string().min(1).max(32),
|
|
55293
55929
|
/** ISO-8601 timestamp the verdict was recorded. */
|
|
55294
|
-
timestamp:
|
|
55930
|
+
timestamp: z111.string().min(1).max(40)
|
|
55295
55931
|
});
|
|
55296
|
-
var VoterEvalVerdictQuerySchema =
|
|
55932
|
+
var VoterEvalVerdictQuerySchema = z111.object({
|
|
55297
55933
|
role: PrReviewEvalRoleSchema.optional(),
|
|
55298
|
-
runId:
|
|
55934
|
+
runId: z111.string().min(1).max(64).optional(),
|
|
55299
55935
|
caseClass: PrReviewCaseClassSchema.optional(),
|
|
55300
|
-
rubricVersion:
|
|
55936
|
+
rubricVersion: z111.string().min(1).max(32).optional(),
|
|
55301
55937
|
/** ISO-8601 lower bound (inclusive) on `timestamp`. */
|
|
55302
|
-
since:
|
|
55938
|
+
since: z111.string().optional(),
|
|
55303
55939
|
/** Most-recent-N cap. */
|
|
55304
|
-
limit:
|
|
55940
|
+
limit: z111.number().int().positive().optional()
|
|
55305
55941
|
});
|
|
55306
55942
|
|
|
55307
55943
|
// src/mcp/tools/supply-chain-tradeoff-panel.ts
|
|
55308
|
-
import { z as
|
|
55944
|
+
import { z as z112 } from "zod";
|
|
55309
55945
|
import { randomUUID as randomUUID20 } from "node:crypto";
|
|
55310
55946
|
var DEFAULT_AXES = [
|
|
55311
55947
|
"build_time_determinism",
|
|
@@ -55327,16 +55963,16 @@ var FULL_PANEL = [
|
|
|
55327
55963
|
"scope_steward"
|
|
55328
55964
|
];
|
|
55329
55965
|
var QUICK_PANEL = ["architect", "security", "scope_steward"];
|
|
55330
|
-
var SupplyChainTradeoffPanelInputSchema =
|
|
55331
|
-
proposal:
|
|
55332
|
-
axes:
|
|
55966
|
+
var SupplyChainTradeoffPanelInputSchema = z112.object({
|
|
55967
|
+
proposal: z112.string().min(1).max(MAX_PROPOSAL_LENGTH).describe('The proposal under tradeoff review (e.g. "Should aegis-boot adopt cargo-nextest?")'),
|
|
55968
|
+
axes: z112.array(z112.string().min(1).max(MAX_AXIS_NAME_LENGTH)).min(1).max(MAX_AXES).optional().describe(
|
|
55333
55969
|
`Tradeoff axes to evaluate. Default: ${DEFAULT_AXES.join(", ")}. Custom axes accepted; max ${String(MAX_AXES)}.`
|
|
55334
55970
|
),
|
|
55335
|
-
context:
|
|
55971
|
+
context: z112.string().max(MAX_CONTEXT_LENGTH).optional().describe(
|
|
55336
55972
|
"Optional context: relevant repo state, dependency tree, vendor publishing patterns, etc."
|
|
55337
55973
|
),
|
|
55338
|
-
quickMode:
|
|
55339
|
-
simulate:
|
|
55974
|
+
quickMode: z112.boolean().optional().default(false).describe("Use 3 voters (architect, security, scope_steward) instead of 7"),
|
|
55975
|
+
simulate: z112.boolean().optional().default(false).describe("Use simulated voters (testing only)"),
|
|
55340
55976
|
// #6123: same field as consensus_vote — the panel judges the caller's project.
|
|
55341
55977
|
project: VoterProjectInputSchema,
|
|
55342
55978
|
/**
|
|
@@ -55636,7 +56272,7 @@ function createAnnotationsProxy(server) {
|
|
|
55636
56272
|
|
|
55637
56273
|
// src/mcp/workspace-roots.ts
|
|
55638
56274
|
import { existsSync as existsSync15, realpathSync as realpathSync6, statSync as statSync4 } from "node:fs";
|
|
55639
|
-
import { isAbsolute as
|
|
56275
|
+
import { isAbsolute as isAbsolute9, join as join19 } from "node:path";
|
|
55640
56276
|
import { homedir as homedir3 } from "node:os";
|
|
55641
56277
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
55642
56278
|
function deriveWorkspaceRootFromRoots(roots) {
|
|
@@ -55651,7 +56287,7 @@ function deriveWorkspaceRootFromRoots(roots) {
|
|
|
55651
56287
|
continue;
|
|
55652
56288
|
}
|
|
55653
56289
|
first ??= path9;
|
|
55654
|
-
if (gitRoot === null && existsSync15(
|
|
56290
|
+
if (gitRoot === null && existsSync15(join19(path9, ".git"))) gitRoot = path9;
|
|
55655
56291
|
}
|
|
55656
56292
|
return gitRoot ?? first;
|
|
55657
56293
|
}
|
|
@@ -55662,7 +56298,7 @@ function resolveClaudeProjectRoot(logger58) {
|
|
|
55662
56298
|
const candidate = process.env["CLAUDE_PROJECT_DIR"];
|
|
55663
56299
|
if (candidate === void 0) return null;
|
|
55664
56300
|
try {
|
|
55665
|
-
if (
|
|
56301
|
+
if (isAbsolute9(candidate)) {
|
|
55666
56302
|
const canonical = realpathSync6(candidate);
|
|
55667
56303
|
const root = statSync4(canonical).isDirectory() ? findRepoRoot(canonical) : null;
|
|
55668
56304
|
if (root !== null && setActiveWorkspaceRoot(root)) return root;
|
|
@@ -55675,8 +56311,8 @@ function resolveClaudeProjectRoot(logger58) {
|
|
|
55675
56311
|
function beginWorkspaceRootResolution(logger58) {
|
|
55676
56312
|
if (resolution?.timer !== void 0) clearTimeout(resolution.timer);
|
|
55677
56313
|
let resolveReady;
|
|
55678
|
-
workspaceRootReady = new Promise((
|
|
55679
|
-
resolveReady =
|
|
56314
|
+
workspaceRootReady = new Promise((resolve13) => {
|
|
56315
|
+
resolveReady = resolve13;
|
|
55680
56316
|
});
|
|
55681
56317
|
const root = resolveClaudeProjectRoot(logger58);
|
|
55682
56318
|
resolution = {
|
|
@@ -55958,40 +56594,40 @@ var RiskLevel = /* @__PURE__ */ ((RiskLevel2) => {
|
|
|
55958
56594
|
})(RiskLevel || {});
|
|
55959
56595
|
|
|
55960
56596
|
// src/mcp/safety/stpa-schemas.ts
|
|
55961
|
-
import { z as
|
|
55962
|
-
var HazardCategorySchema =
|
|
55963
|
-
var HazardSeveritySchema =
|
|
55964
|
-
var ConstraintPrioritySchema =
|
|
55965
|
-
var RiskLevelSchema =
|
|
55966
|
-
var TriggerPatternSchema =
|
|
55967
|
-
parameter:
|
|
55968
|
-
matchType:
|
|
55969
|
-
pattern:
|
|
55970
|
-
reason:
|
|
56597
|
+
import { z as z113 } from "zod";
|
|
56598
|
+
var HazardCategorySchema = z113.enum(HazardCategory);
|
|
56599
|
+
var HazardSeveritySchema = z113.enum(HazardSeverity);
|
|
56600
|
+
var ConstraintPrioritySchema = z113.enum(ConstraintPriority);
|
|
56601
|
+
var RiskLevelSchema = z113.enum(RiskLevel);
|
|
56602
|
+
var TriggerPatternSchema = z113.object({
|
|
56603
|
+
parameter: z113.string().min(1),
|
|
56604
|
+
matchType: z113.enum(["contains", "regex", "equals", "startsWith", "endsWith"]),
|
|
56605
|
+
pattern: z113.string(),
|
|
56606
|
+
reason: z113.string()
|
|
55971
56607
|
});
|
|
55972
|
-
var HazardSchema =
|
|
55973
|
-
id:
|
|
55974
|
-
description:
|
|
56608
|
+
var HazardSchema = z113.object({
|
|
56609
|
+
id: z113.string().min(1),
|
|
56610
|
+
description: z113.string(),
|
|
55975
56611
|
category: HazardCategorySchema,
|
|
55976
56612
|
severity: HazardSeveritySchema,
|
|
55977
|
-
likelihood:
|
|
55978
|
-
triggerConditions:
|
|
55979
|
-
consequences:
|
|
56613
|
+
likelihood: z113.enum(["almost_certain", "likely", "possible", "unlikely", "rare"]),
|
|
56614
|
+
triggerConditions: z113.array(z113.string()),
|
|
56615
|
+
consequences: z113.array(z113.string())
|
|
55980
56616
|
});
|
|
55981
|
-
var UnsafeControlActionSchema =
|
|
55982
|
-
id:
|
|
55983
|
-
toolName:
|
|
55984
|
-
type:
|
|
55985
|
-
description:
|
|
55986
|
-
unsafeContext:
|
|
55987
|
-
relatedHazards:
|
|
55988
|
-
triggerPatterns:
|
|
56617
|
+
var UnsafeControlActionSchema = z113.object({
|
|
56618
|
+
id: z113.string().min(1),
|
|
56619
|
+
toolName: z113.string().min(1),
|
|
56620
|
+
type: z113.enum(["not_provided", "provided_causes_hazard", "wrong_timing", "wrong_duration"]),
|
|
56621
|
+
description: z113.string(),
|
|
56622
|
+
unsafeContext: z113.string(),
|
|
56623
|
+
relatedHazards: z113.array(z113.string()),
|
|
56624
|
+
triggerPatterns: z113.array(TriggerPatternSchema).optional()
|
|
55989
56625
|
});
|
|
55990
|
-
var SafetyConstraintSchema =
|
|
55991
|
-
id:
|
|
55992
|
-
description:
|
|
55993
|
-
mitigates:
|
|
55994
|
-
enforcement:
|
|
56626
|
+
var SafetyConstraintSchema = z113.object({
|
|
56627
|
+
id: z113.string().min(1),
|
|
56628
|
+
description: z113.string(),
|
|
56629
|
+
mitigates: z113.array(z113.string()),
|
|
56630
|
+
enforcement: z113.enum([
|
|
55995
56631
|
"prevent",
|
|
55996
56632
|
"require_confirmation",
|
|
55997
56633
|
"alert",
|
|
@@ -55999,52 +56635,52 @@ var SafetyConstraintSchema = z112.object({
|
|
|
55999
56635
|
"rate_limit",
|
|
56000
56636
|
"require_privilege"
|
|
56001
56637
|
]),
|
|
56002
|
-
validationFunction:
|
|
56638
|
+
validationFunction: z113.string().optional(),
|
|
56003
56639
|
priority: ConstraintPrioritySchema
|
|
56004
56640
|
});
|
|
56005
|
-
var PropertySchemaSchema =
|
|
56006
|
-
type:
|
|
56007
|
-
description:
|
|
56008
|
-
enum:
|
|
56009
|
-
pattern:
|
|
56010
|
-
minimum:
|
|
56011
|
-
maximum:
|
|
56641
|
+
var PropertySchemaSchema = z113.object({
|
|
56642
|
+
type: z113.string(),
|
|
56643
|
+
description: z113.string().optional(),
|
|
56644
|
+
enum: z113.array(z113.unknown()).optional(),
|
|
56645
|
+
pattern: z113.string().optional(),
|
|
56646
|
+
minimum: z113.number().optional(),
|
|
56647
|
+
maximum: z113.number().optional()
|
|
56012
56648
|
});
|
|
56013
|
-
var ToolInputSchemaSchema =
|
|
56014
|
-
type:
|
|
56015
|
-
properties:
|
|
56016
|
-
required:
|
|
56017
|
-
additionalProperties:
|
|
56649
|
+
var ToolInputSchemaSchema = z113.object({
|
|
56650
|
+
type: z113.string(),
|
|
56651
|
+
properties: z113.record(z113.string(), PropertySchemaSchema).optional(),
|
|
56652
|
+
required: z113.array(z113.string()).optional(),
|
|
56653
|
+
additionalProperties: z113.boolean().optional()
|
|
56018
56654
|
});
|
|
56019
|
-
var ToolDefinitionSchema =
|
|
56020
|
-
name:
|
|
56021
|
-
description:
|
|
56655
|
+
var ToolDefinitionSchema = z113.object({
|
|
56656
|
+
name: z113.string().min(1),
|
|
56657
|
+
description: z113.string(),
|
|
56022
56658
|
inputSchema: ToolInputSchemaSchema
|
|
56023
56659
|
});
|
|
56024
|
-
var AnalysisConfigurationSchema =
|
|
56025
|
-
includeLowSeverity:
|
|
56026
|
-
generateAllConstraints:
|
|
56027
|
-
checkInteractions:
|
|
56028
|
-
maxHazardsPerTool:
|
|
56029
|
-
categories:
|
|
56660
|
+
var AnalysisConfigurationSchema = z113.object({
|
|
56661
|
+
includeLowSeverity: z113.boolean().default(true),
|
|
56662
|
+
generateAllConstraints: z113.boolean().default(true),
|
|
56663
|
+
checkInteractions: z113.boolean().default(true),
|
|
56664
|
+
maxHazardsPerTool: z113.number().int().min(1).max(100).default(50),
|
|
56665
|
+
categories: z113.array(HazardCategorySchema).default([])
|
|
56030
56666
|
});
|
|
56031
|
-
var ConstraintViolationSchema =
|
|
56032
|
-
constraintId:
|
|
56033
|
-
constraintDescription:
|
|
56667
|
+
var ConstraintViolationSchema = z113.object({
|
|
56668
|
+
constraintId: z113.string().min(1),
|
|
56669
|
+
constraintDescription: z113.string(),
|
|
56034
56670
|
severity: HazardSeveritySchema,
|
|
56035
|
-
details:
|
|
56036
|
-
remediation:
|
|
56671
|
+
details: z113.string(),
|
|
56672
|
+
remediation: z113.string()
|
|
56037
56673
|
});
|
|
56038
|
-
var ValidationWarningSchema =
|
|
56039
|
-
code:
|
|
56040
|
-
message:
|
|
56041
|
-
affected:
|
|
56674
|
+
var ValidationWarningSchema = z113.object({
|
|
56675
|
+
code: z113.string().min(1),
|
|
56676
|
+
message: z113.string(),
|
|
56677
|
+
affected: z113.string()
|
|
56042
56678
|
});
|
|
56043
|
-
var ValidationResultSchema =
|
|
56044
|
-
valid:
|
|
56045
|
-
toolName:
|
|
56046
|
-
violations:
|
|
56047
|
-
passed:
|
|
56679
|
+
var ValidationResultSchema = z113.object({
|
|
56680
|
+
valid: z113.boolean(),
|
|
56681
|
+
toolName: z113.string().min(1),
|
|
56682
|
+
violations: z113.array(ConstraintViolationSchema),
|
|
56683
|
+
passed: z113.array(z113.string()),
|
|
56048
56684
|
// Optional rather than required, deliberately. `ValidationResult` declares
|
|
56049
56685
|
// both fields required because every result this package produces has them;
|
|
56050
56686
|
// the schema is the lenient inbound edge for a result that arrived from
|
|
@@ -56055,10 +56691,10 @@ var ValidationResultSchema = z112.object({
|
|
|
56055
56691
|
// "nothing was evaluated". The strict/lenient split is safe because nothing
|
|
56056
56692
|
// bridges the two with `z.infer`: a parsed result will not typecheck as a
|
|
56057
56693
|
// `ValidationResult` without handling the absent fields.
|
|
56058
|
-
evaluated:
|
|
56059
|
-
notApplicable:
|
|
56060
|
-
warnings:
|
|
56061
|
-
validatedAt:
|
|
56694
|
+
evaluated: z113.array(z113.string()).optional(),
|
|
56695
|
+
notApplicable: z113.array(z113.string()).optional(),
|
|
56696
|
+
warnings: z113.array(ValidationWarningSchema),
|
|
56697
|
+
validatedAt: z113.date()
|
|
56062
56698
|
});
|
|
56063
56699
|
|
|
56064
56700
|
// src/mcp/safety/stpa-types.ts
|
|
@@ -57143,18 +57779,18 @@ var GeminiResponseParser = class {
|
|
|
57143
57779
|
};
|
|
57144
57780
|
|
|
57145
57781
|
// src/cli-adapters/router-types.ts
|
|
57146
|
-
import { z as
|
|
57147
|
-
var RouterConfigSchema =
|
|
57148
|
-
preferCostEfficient:
|
|
57782
|
+
import { z as z114 } from "zod";
|
|
57783
|
+
var RouterConfigSchema = z114.object({
|
|
57784
|
+
preferCostEfficient: z114.boolean().default(false)
|
|
57149
57785
|
});
|
|
57150
57786
|
|
|
57151
57787
|
// src/cli-adapters/task-classifier.ts
|
|
57152
|
-
import { z as
|
|
57153
|
-
var ClassificationPatternsSchema =
|
|
57154
|
-
code:
|
|
57155
|
-
research:
|
|
57156
|
-
documentation:
|
|
57157
|
-
analysis:
|
|
57788
|
+
import { z as z115 } from "zod";
|
|
57789
|
+
var ClassificationPatternsSchema = z115.object({
|
|
57790
|
+
code: z115.array(z115.string()).readonly(),
|
|
57791
|
+
research: z115.array(z115.string()).readonly(),
|
|
57792
|
+
documentation: z115.array(z115.string()).readonly(),
|
|
57793
|
+
analysis: z115.array(z115.string()).readonly()
|
|
57158
57794
|
});
|
|
57159
57795
|
|
|
57160
57796
|
// src/security/sandbox/sandbox-types.ts
|
|
@@ -57389,25 +58025,25 @@ function sanitizeEnvironment(sourceEnv, allowedVars, additionalEnv) {
|
|
|
57389
58025
|
const blocked = [];
|
|
57390
58026
|
const violations = [];
|
|
57391
58027
|
const effectiveAllowlist = allowedVars.length > 0 ? allowedVars : SAFE_ENV_VARS;
|
|
57392
|
-
for (const [
|
|
58028
|
+
for (const [key2, value] of Object.entries(sourceEnv)) {
|
|
57393
58029
|
if (value === void 0) continue;
|
|
57394
|
-
const validation = validateEnvVar(
|
|
58030
|
+
const validation = validateEnvVar(key2, effectiveAllowlist);
|
|
57395
58031
|
if (validation !== null) {
|
|
57396
|
-
blocked.push(
|
|
58032
|
+
blocked.push(key2);
|
|
57397
58033
|
violations.push(validation);
|
|
57398
58034
|
continue;
|
|
57399
58035
|
}
|
|
57400
|
-
result[
|
|
58036
|
+
result[key2] = value;
|
|
57401
58037
|
}
|
|
57402
58038
|
if (additionalEnv !== void 0) {
|
|
57403
|
-
for (const [
|
|
57404
|
-
const denyCheck = isDeniedEnvVar(
|
|
58039
|
+
for (const [key2, value] of Object.entries(additionalEnv)) {
|
|
58040
|
+
const denyCheck = isDeniedEnvVar(key2);
|
|
57405
58041
|
if (denyCheck !== null) {
|
|
57406
|
-
blocked.push(
|
|
58042
|
+
blocked.push(key2);
|
|
57407
58043
|
violations.push(denyCheck);
|
|
57408
58044
|
continue;
|
|
57409
58045
|
}
|
|
57410
|
-
result[
|
|
58046
|
+
result[key2] = value;
|
|
57411
58047
|
}
|
|
57412
58048
|
}
|
|
57413
58049
|
return { env: result, blocked, violations };
|
|
@@ -57583,7 +58219,7 @@ function getPolicy(id) {
|
|
|
57583
58219
|
// src/security/sandbox/sandbox-executor.ts
|
|
57584
58220
|
import { execFile as execFile2 } from "node:child_process";
|
|
57585
58221
|
import { promisify } from "node:util";
|
|
57586
|
-
import { resolve as
|
|
58222
|
+
import { resolve as resolve12 } from "node:path";
|
|
57587
58223
|
var execFileAsync = promisify(execFile2);
|
|
57588
58224
|
var logger55 = createLogger({ component: "sandbox-executor" });
|
|
57589
58225
|
function parseExecError(error) {
|
|
@@ -57675,7 +58311,7 @@ var PolicySandboxExecutor = class {
|
|
|
57675
58311
|
* following symlinks, else `null`. No rules means no allowed directory.
|
|
57676
58312
|
*/
|
|
57677
58313
|
resolveAllowedCwd(cwd, policy) {
|
|
57678
|
-
const absolute =
|
|
58314
|
+
const absolute = resolve12(cwd);
|
|
57679
58315
|
for (const rule of policy.pathRules) {
|
|
57680
58316
|
if (rule.access === "none") continue;
|
|
57681
58317
|
const contained = resolveInsideRoot(absolute, rule.path);
|
|
@@ -58532,4 +59168,4 @@ export {
|
|
|
58532
59168
|
initializeSandbox,
|
|
58533
59169
|
getSandboxMode
|
|
58534
59170
|
};
|
|
58535
|
-
//# sourceMappingURL=chunk-
|
|
59171
|
+
//# sourceMappingURL=chunk-HHOSB6LL.js.map
|