nexus-agents 2.125.24 → 2.125.25
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-647PSXJ5.js → chunk-B3TJNOKQ.js} +3 -3
- package/dist/{chunk-SDA5GEWO.js → chunk-F6VJEXXJ.js} +2 -2
- package/dist/{chunk-QIEXH2EA.js → chunk-YQARWBVL.js} +2 -2
- package/dist/cli.js +251 -102
- package/dist/cli.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{setup-command-63KWDRWL.js → setup-command-PRTMR4DK.js} +3 -3
- package/package.json +1 -1
- /package/dist/{chunk-647PSXJ5.js.map → chunk-B3TJNOKQ.js.map} +0 -0
- /package/dist/{chunk-SDA5GEWO.js.map → chunk-F6VJEXXJ.js.map} +0 -0
- /package/dist/{chunk-QIEXH2EA.js.map → chunk-YQARWBVL.js.map} +0 -0
- /package/dist/{setup-command-63KWDRWL.js.map → setup-command-PRTMR4DK.js.map} +0 -0
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
} from "./chunk-CH7QIDHQ.js";
|
|
41
41
|
|
|
42
42
|
// src/version.ts
|
|
43
|
-
var VERSION = true ? "2.125.
|
|
43
|
+
var VERSION = true ? "2.125.25" : "dev";
|
|
44
44
|
|
|
45
45
|
// src/config/schemas-core.ts
|
|
46
46
|
import { z } from "zod";
|
|
@@ -2099,7 +2099,7 @@ async function runDoctorFix(result) {
|
|
|
2099
2099
|
writeLine2("\u2500".repeat(40));
|
|
2100
2100
|
let fixCount = 0;
|
|
2101
2101
|
if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
|
|
2102
|
-
const { runSetup } = await import("./setup-command-
|
|
2102
|
+
const { runSetup } = await import("./setup-command-PRTMR4DK.js");
|
|
2103
2103
|
const setupResult = runSetup({
|
|
2104
2104
|
skipMcp: true,
|
|
2105
2105
|
skipRules: true,
|
|
@@ -2211,4 +2211,4 @@ export {
|
|
|
2211
2211
|
startStdioServer,
|
|
2212
2212
|
closeServer
|
|
2213
2213
|
};
|
|
2214
|
-
//# sourceMappingURL=chunk-
|
|
2214
|
+
//# sourceMappingURL=chunk-B3TJNOKQ.js.map
|
|
@@ -123,7 +123,7 @@ import {
|
|
|
123
123
|
DEFAULT_TASK_TTL_MS,
|
|
124
124
|
DEFAULT_TOOL_RATE_LIMITS,
|
|
125
125
|
clampTaskTtl
|
|
126
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-B3TJNOKQ.js";
|
|
127
127
|
import {
|
|
128
128
|
resolveInsideRoot
|
|
129
129
|
} from "./chunk-NUBSJGQZ.js";
|
|
@@ -49800,4 +49800,4 @@ export {
|
|
|
49800
49800
|
shutdownFeedbackSubscriber,
|
|
49801
49801
|
createEventBusBridge
|
|
49802
49802
|
};
|
|
49803
|
-
//# sourceMappingURL=chunk-
|
|
49803
|
+
//# sourceMappingURL=chunk-F6VJEXXJ.js.map
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
checkSqlite,
|
|
9
9
|
defaultConfig,
|
|
10
10
|
initDataDirectories
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-B3TJNOKQ.js";
|
|
12
12
|
import {
|
|
13
13
|
probeAllClis
|
|
14
14
|
} from "./chunk-QN3353M2.js";
|
|
@@ -2000,4 +2000,4 @@ export {
|
|
|
2000
2000
|
setupCommand,
|
|
2001
2001
|
setupCommandAsync
|
|
2002
2002
|
};
|
|
2003
|
-
//# sourceMappingURL=chunk-
|
|
2003
|
+
//# sourceMappingURL=chunk-YQARWBVL.js.map
|
package/dist/cli.js
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
import {
|
|
25
25
|
setupCommandAsync,
|
|
26
26
|
verifyCommand
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-YQARWBVL.js";
|
|
28
28
|
import "./chunk-MMWNGT2K.js";
|
|
29
29
|
import {
|
|
30
30
|
AuthHandler,
|
|
@@ -144,7 +144,7 @@ import {
|
|
|
144
144
|
validateCommand,
|
|
145
145
|
validateWorkflow,
|
|
146
146
|
wrapInMarkdownFence
|
|
147
|
-
} from "./chunk-
|
|
147
|
+
} from "./chunk-F6VJEXXJ.js";
|
|
148
148
|
import "./chunk-3ACDP4E6.js";
|
|
149
149
|
import {
|
|
150
150
|
CATEGORY_DISPLAY_NAMES,
|
|
@@ -246,7 +246,7 @@ import {
|
|
|
246
246
|
loadConfig,
|
|
247
247
|
runDoctor,
|
|
248
248
|
validateNexusEnv
|
|
249
|
-
} from "./chunk-
|
|
249
|
+
} from "./chunk-B3TJNOKQ.js";
|
|
250
250
|
import "./chunk-NUBSJGQZ.js";
|
|
251
251
|
import {
|
|
252
252
|
capitalize,
|
|
@@ -12743,8 +12743,8 @@ async function exportSessionMetrics(storage, sessionId, exportPath) {
|
|
|
12743
12743
|
const session = sessionResult.value;
|
|
12744
12744
|
const metrics = buildMetricsObject(session, sessionId);
|
|
12745
12745
|
if (exportPath !== void 0) {
|
|
12746
|
-
const { writeFile:
|
|
12747
|
-
await
|
|
12746
|
+
const { writeFile: writeFile7 } = await import("fs/promises");
|
|
12747
|
+
await writeFile7(exportPath, JSON.stringify(metrics, null, 2));
|
|
12748
12748
|
logger14.info("Metrics exported", { path: exportPath });
|
|
12749
12749
|
} else {
|
|
12750
12750
|
logger14.debug("Session metrics", summarizeMetricsForDebug(metrics));
|
|
@@ -23036,6 +23036,235 @@ function stripRefsPrefix(ref) {
|
|
|
23036
23036
|
return ref.replace(/^refs\//, "");
|
|
23037
23037
|
}
|
|
23038
23038
|
|
|
23039
|
+
// src/mcp/tools/remediation-proposal-pr.ts
|
|
23040
|
+
import { execFile as execFile4 } from "child_process";
|
|
23041
|
+
import { promisify as promisify4 } from "util";
|
|
23042
|
+
import { writeFile as writeFile6, mkdir as mkdir5 } from "fs/promises";
|
|
23043
|
+
import { join as join18, dirname as dirname11 } from "path";
|
|
23044
|
+
|
|
23045
|
+
// src/mcp/tools/improvement-remediation-capability.ts
|
|
23046
|
+
import { z as z8 } from "zod";
|
|
23047
|
+
var PHASE_CAPABILITIES = {
|
|
23048
|
+
research: /* @__PURE__ */ new Set(["untrusted-input", "secrets"]),
|
|
23049
|
+
implement: /* @__PURE__ */ new Set(["repo-write", "secrets"])
|
|
23050
|
+
};
|
|
23051
|
+
var RuleOfTwoViolation = class extends Error {
|
|
23052
|
+
constructor(message) {
|
|
23053
|
+
super(message);
|
|
23054
|
+
this.name = "RuleOfTwoViolation";
|
|
23055
|
+
}
|
|
23056
|
+
};
|
|
23057
|
+
var CapabilityLedger = class {
|
|
23058
|
+
phase;
|
|
23059
|
+
/** Enter a phase, setting its declared capability set as active. */
|
|
23060
|
+
enterPhase(phase) {
|
|
23061
|
+
this.phase = phase;
|
|
23062
|
+
}
|
|
23063
|
+
/** The active phase, or undefined if none entered. */
|
|
23064
|
+
currentPhase() {
|
|
23065
|
+
return this.phase;
|
|
23066
|
+
}
|
|
23067
|
+
/**
|
|
23068
|
+
* Assert that `capability` is permitted right now. Throws {@link RuleOfTwoViolation}
|
|
23069
|
+
* (fail-closed) if no phase is active or the active phase doesn't grant it —
|
|
23070
|
+
* which structurally prevents the forbidden three-leg conjunction, since no
|
|
23071
|
+
* phase grants more than two legs.
|
|
23072
|
+
*/
|
|
23073
|
+
assertCapability(capability) {
|
|
23074
|
+
if (this.phase === void 0) {
|
|
23075
|
+
throw new RuleOfTwoViolation(
|
|
23076
|
+
`capability '${capability}' requested before any remediation phase was entered (fail-closed)`
|
|
23077
|
+
);
|
|
23078
|
+
}
|
|
23079
|
+
const allowed = PHASE_CAPABILITIES[this.phase];
|
|
23080
|
+
if (!allowed.has(capability)) {
|
|
23081
|
+
throw new RuleOfTwoViolation(
|
|
23082
|
+
`capability '${capability}' is not permitted in phase '${this.phase}' (allowed: ${[...allowed].join(", ")})`
|
|
23083
|
+
);
|
|
23084
|
+
}
|
|
23085
|
+
}
|
|
23086
|
+
};
|
|
23087
|
+
var RemediationActionKindSchema = z8.enum([
|
|
23088
|
+
"investigate",
|
|
23089
|
+
"adjust-routing",
|
|
23090
|
+
"add-test",
|
|
23091
|
+
"refactor",
|
|
23092
|
+
"update-docs",
|
|
23093
|
+
"fix-bug"
|
|
23094
|
+
]);
|
|
23095
|
+
var RemediationStepSchema = z8.object({
|
|
23096
|
+
kind: RemediationActionKindSchema,
|
|
23097
|
+
description: z8.string().min(1).max(500),
|
|
23098
|
+
/** Optional path hint; bounded inert string, validated for traversal at use. */
|
|
23099
|
+
targetPath: z8.string().min(1).max(300).optional()
|
|
23100
|
+
}).strict();
|
|
23101
|
+
var RemediationPlanSchema = z8.object({
|
|
23102
|
+
/** Source signal key (mirrors ImprovementSignal.signalKey). */
|
|
23103
|
+
signalKey: z8.string().min(1).max(200),
|
|
23104
|
+
/** Signal category (mirrors SignalCategory). */
|
|
23105
|
+
category: z8.enum(["routing", "tech-debt", "bug", "security", "consensus"]),
|
|
23106
|
+
summary: z8.string().min(1).max(1e3),
|
|
23107
|
+
steps: z8.array(RemediationStepSchema).min(1).max(20)
|
|
23108
|
+
}).strict();
|
|
23109
|
+
function parseRemediationPlan(raw) {
|
|
23110
|
+
const result = RemediationPlanSchema.safeParse(raw);
|
|
23111
|
+
if (!result.success) {
|
|
23112
|
+
throw new RuleOfTwoViolation(
|
|
23113
|
+
`RemediationPlan failed strict validation at the RESEARCH\u2192IMPLEMENT boundary: ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
|
|
23114
|
+
);
|
|
23115
|
+
}
|
|
23116
|
+
return result.data;
|
|
23117
|
+
}
|
|
23118
|
+
function renderPlanAsResearch(plan) {
|
|
23119
|
+
const steps = plan.steps.map((s, i) => {
|
|
23120
|
+
const target = s.targetPath !== void 0 ? ` (target: ${s.targetPath})` : "";
|
|
23121
|
+
return `${String(i + 1)}. [${s.kind}] ${s.description}${target}`;
|
|
23122
|
+
}).join("\n");
|
|
23123
|
+
return `Remediation plan for signal '${plan.signalKey}' (category: ${plan.category}).
|
|
23124
|
+
|
|
23125
|
+
${plan.summary}
|
|
23126
|
+
|
|
23127
|
+
Steps:
|
|
23128
|
+
${steps}`;
|
|
23129
|
+
}
|
|
23130
|
+
|
|
23131
|
+
// src/mcp/tools/auto-remediation-branch.ts
|
|
23132
|
+
var AUTO_REMEDIATION_BRANCH_PREFIX = "auto-remediation/";
|
|
23133
|
+
function autoRemediationBranchName(signalKey) {
|
|
23134
|
+
const slug = signalKey.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 100);
|
|
23135
|
+
return `${AUTO_REMEDIATION_BRANCH_PREFIX}${slug || "signal"}`;
|
|
23136
|
+
}
|
|
23137
|
+
|
|
23138
|
+
// src/mcp/tools/diff-secret-scan.ts
|
|
23139
|
+
var SECRET_PATTERNS = [
|
|
23140
|
+
{ name: "private-key-block", re: /-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----/ },
|
|
23141
|
+
{ name: "aws-access-key-id", re: /\bAKIA[0-9A-Z]{16}\b/ },
|
|
23142
|
+
{ name: "github-token", re: /\bgh[pousr]_[A-Za-z0-9]{36,}\b/ },
|
|
23143
|
+
{ name: "slack-token", re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/ },
|
|
23144
|
+
{ name: "google-api-key", re: /\bAIza[0-9A-Za-z_-]{35}\b/ },
|
|
23145
|
+
{ name: "openai-key", re: /\bsk-[A-Za-z0-9]{32,}\b/ },
|
|
23146
|
+
{ name: "anthropic-key", re: /\bsk-ant-[A-Za-z0-9_-]{20,}\b/ },
|
|
23147
|
+
{ name: "jwt", re: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/ },
|
|
23148
|
+
// Generic `secret/token/password/api_key = "long-value"` assignments.
|
|
23149
|
+
{
|
|
23150
|
+
name: "generic-credential-assignment",
|
|
23151
|
+
re: /(?:api[_-]?key|secret|token|password|passwd|credential)\s*[:=]\s*["'][A-Za-z0-9/+_-]{16,}["']/i
|
|
23152
|
+
}
|
|
23153
|
+
];
|
|
23154
|
+
function scanForSecrets(text) {
|
|
23155
|
+
const findings = [];
|
|
23156
|
+
const lines = text.split("\n");
|
|
23157
|
+
for (let i = 0; i < lines.length; i++) {
|
|
23158
|
+
const line = lines[i] ?? "";
|
|
23159
|
+
for (const { name, re } of SECRET_PATTERNS) {
|
|
23160
|
+
if (re.test(line)) findings.push({ pattern: name, line: i + 1 });
|
|
23161
|
+
}
|
|
23162
|
+
}
|
|
23163
|
+
return { clean: findings.length === 0, findings };
|
|
23164
|
+
}
|
|
23165
|
+
function describeSecretFindings(result) {
|
|
23166
|
+
if (result.clean) return "no secrets detected";
|
|
23167
|
+
return result.findings.map((f) => `${f.pattern}@L${String(f.line)}`).join(", ");
|
|
23168
|
+
}
|
|
23169
|
+
|
|
23170
|
+
// src/mcp/tools/remediation-proposal-pr.ts
|
|
23171
|
+
var execFileAsync4 = promisify4(execFile4);
|
|
23172
|
+
function buildProposalDoc(plan) {
|
|
23173
|
+
return `# Auto-remediation proposal \u2014 \`${plan.signalKey}\`
|
|
23174
|
+
|
|
23175
|
+
> Consensus-approved remediation **proposal** (not auto-implemented). A human or coder implements the steps below; this PR is the reviewable plan.
|
|
23176
|
+
|
|
23177
|
+
${renderPlanAsResearch(plan)}
|
|
23178
|
+
`;
|
|
23179
|
+
}
|
|
23180
|
+
function planSlug(signalKey) {
|
|
23181
|
+
return autoRemediationBranchName(signalKey).replace(/^auto-remediation\//, "");
|
|
23182
|
+
}
|
|
23183
|
+
function makeProposalPrImplementAdapter(opts) {
|
|
23184
|
+
const scan = opts.scan ?? scanForSecrets;
|
|
23185
|
+
const baseBranch = opts.baseBranch ?? "main";
|
|
23186
|
+
const logger19 = opts.logger ?? createLogger({ tool: "auto-remediation-pr" });
|
|
23187
|
+
return async (plan, ledger) => {
|
|
23188
|
+
ledger.assertCapability("repo-write");
|
|
23189
|
+
const branch = autoRemediationBranchName(plan.signalKey);
|
|
23190
|
+
const doc = buildProposalDoc(plan);
|
|
23191
|
+
const result = scan(doc);
|
|
23192
|
+
if (!result.clean) {
|
|
23193
|
+
throw new Error(
|
|
23194
|
+
`proposal PR aborted \u2014 secrets in plan doc: ${describeSecretFindings(result)}`
|
|
23195
|
+
);
|
|
23196
|
+
}
|
|
23197
|
+
const worktree = await opts.ops.addWorktree(branch, baseBranch);
|
|
23198
|
+
try {
|
|
23199
|
+
await opts.ops.writeFileIn(worktree, `remediation-plans/${planSlug(plan.signalKey)}.md`, doc);
|
|
23200
|
+
await opts.ops.commitAll(worktree, `chore(auto-remediation): proposal for ${plan.signalKey}`);
|
|
23201
|
+
await opts.ops.pushBranch(worktree, branch);
|
|
23202
|
+
const prUrl = await opts.pr.createDraftPr({
|
|
23203
|
+
branch,
|
|
23204
|
+
baseBranch,
|
|
23205
|
+
title: `auto-remediation proposal: ${plan.signalKey}`,
|
|
23206
|
+
body: doc
|
|
23207
|
+
});
|
|
23208
|
+
logger19.info("auto-remediation proposal PR opened", { branch, prUrl });
|
|
23209
|
+
return { branch, prUrl };
|
|
23210
|
+
} finally {
|
|
23211
|
+
await opts.ops.removeWorktree(worktree).catch((err2) => {
|
|
23212
|
+
logger19.warn("worktree cleanup failed (non-fatal)", {
|
|
23213
|
+
worktree,
|
|
23214
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
23215
|
+
});
|
|
23216
|
+
});
|
|
23217
|
+
}
|
|
23218
|
+
};
|
|
23219
|
+
}
|
|
23220
|
+
function makeGitWorktreeOps(repoRoot) {
|
|
23221
|
+
const git = async (args, cwd) => {
|
|
23222
|
+
await execFileAsync4("git", [...args], { cwd });
|
|
23223
|
+
};
|
|
23224
|
+
return {
|
|
23225
|
+
async addWorktree(branch, baseBranch) {
|
|
23226
|
+
const path21 = join18(repoRoot, ".nexus-worktrees", branch.replace(/\//g, "_"));
|
|
23227
|
+
await git(["worktree", "add", "-b", branch, path21, baseBranch], repoRoot);
|
|
23228
|
+
return path21;
|
|
23229
|
+
},
|
|
23230
|
+
async writeFileIn(worktreePath, relPath, content) {
|
|
23231
|
+
const abs = join18(worktreePath, relPath);
|
|
23232
|
+
await mkdir5(dirname11(abs), { recursive: true });
|
|
23233
|
+
await writeFile6(abs, content, "utf8");
|
|
23234
|
+
},
|
|
23235
|
+
async commitAll(worktreePath, message) {
|
|
23236
|
+
await git(["add", "-A"], worktreePath);
|
|
23237
|
+
await git(["commit", "-m", message], worktreePath);
|
|
23238
|
+
},
|
|
23239
|
+
async pushBranch(worktreePath, branch) {
|
|
23240
|
+
await git(["push", "-u", "origin", branch], worktreePath);
|
|
23241
|
+
},
|
|
23242
|
+
async removeWorktree(worktreePath) {
|
|
23243
|
+
await git(["worktree", "remove", worktreePath, "--force"], repoRoot);
|
|
23244
|
+
}
|
|
23245
|
+
};
|
|
23246
|
+
}
|
|
23247
|
+
function makeGhPrCreator() {
|
|
23248
|
+
return {
|
|
23249
|
+
async createDraftPr({ branch, baseBranch, title, body }) {
|
|
23250
|
+
const { stdout } = await execFileAsync4("gh", [
|
|
23251
|
+
"pr",
|
|
23252
|
+
"create",
|
|
23253
|
+
"--draft",
|
|
23254
|
+
"--head",
|
|
23255
|
+
branch,
|
|
23256
|
+
"--base",
|
|
23257
|
+
baseBranch,
|
|
23258
|
+
"--title",
|
|
23259
|
+
title,
|
|
23260
|
+
"--body",
|
|
23261
|
+
body
|
|
23262
|
+
]);
|
|
23263
|
+
return stdout.trim();
|
|
23264
|
+
}
|
|
23265
|
+
};
|
|
23266
|
+
}
|
|
23267
|
+
|
|
23039
23268
|
// src/mcp/tools/auto-remediation-deps.ts
|
|
23040
23269
|
var NOT_READY = {
|
|
23041
23270
|
shadowSelections: 0,
|
|
@@ -23049,16 +23278,22 @@ function buildAutoRemediationDeps(opts = {}) {
|
|
|
23049
23278
|
// lease, so enforce must not proceed. (Audit never calls this.)
|
|
23050
23279
|
async () => Promise.resolve(null)
|
|
23051
23280
|
);
|
|
23281
|
+
const implement = opts.repoRoot !== void 0 && opts.repo !== void 0 ? makeProposalPrImplementAdapter({
|
|
23282
|
+
ops: makeGitWorktreeOps(opts.repoRoot),
|
|
23283
|
+
pr: makeGhPrCreator(),
|
|
23284
|
+
...opts.baseBranch !== void 0 ? { baseBranch: opts.baseBranch } : {},
|
|
23285
|
+
logger: logger19
|
|
23286
|
+
}) : () => Promise.reject(
|
|
23287
|
+
new Error(
|
|
23288
|
+
"auto-remediation implement not wired \u2014 set repo + repoRoot to enable Option B (#3669)"
|
|
23289
|
+
)
|
|
23290
|
+
);
|
|
23052
23291
|
return {
|
|
23053
23292
|
research: (signal) => Promise.resolve(buildRemediationPlanFromSignal(signal)),
|
|
23054
23293
|
vote: makeVoteAdapter(opts.voteRunner, logger19),
|
|
23055
23294
|
acquireLease,
|
|
23056
23295
|
readinessEvidence: opts.readiness ?? (() => Promise.resolve(NOT_READY)),
|
|
23057
|
-
implement
|
|
23058
|
-
new Error(
|
|
23059
|
-
"auto-remediation implement adapter not wired yet (Option B, #3669) \u2014 enforce unavailable"
|
|
23060
|
-
)
|
|
23061
|
-
),
|
|
23296
|
+
implement,
|
|
23062
23297
|
audit: (event) => {
|
|
23063
23298
|
logger19.info(`[auto-remediation] ${event.step}`, {
|
|
23064
23299
|
...event.signalKey !== void 0 ? { signalKey: event.signalKey } : {},
|
|
@@ -23195,92 +23430,6 @@ function evaluateEnforceReadiness(evidence, config = DEFAULT_ENFORCE_READINESS_C
|
|
|
23195
23430
|
return { ready: blockers.length === 0, criteria, blockers };
|
|
23196
23431
|
}
|
|
23197
23432
|
|
|
23198
|
-
// src/mcp/tools/improvement-remediation-capability.ts
|
|
23199
|
-
import { z as z8 } from "zod";
|
|
23200
|
-
var PHASE_CAPABILITIES = {
|
|
23201
|
-
research: /* @__PURE__ */ new Set(["untrusted-input", "secrets"]),
|
|
23202
|
-
implement: /* @__PURE__ */ new Set(["repo-write", "secrets"])
|
|
23203
|
-
};
|
|
23204
|
-
var RuleOfTwoViolation = class extends Error {
|
|
23205
|
-
constructor(message) {
|
|
23206
|
-
super(message);
|
|
23207
|
-
this.name = "RuleOfTwoViolation";
|
|
23208
|
-
}
|
|
23209
|
-
};
|
|
23210
|
-
var CapabilityLedger = class {
|
|
23211
|
-
phase;
|
|
23212
|
-
/** Enter a phase, setting its declared capability set as active. */
|
|
23213
|
-
enterPhase(phase) {
|
|
23214
|
-
this.phase = phase;
|
|
23215
|
-
}
|
|
23216
|
-
/** The active phase, or undefined if none entered. */
|
|
23217
|
-
currentPhase() {
|
|
23218
|
-
return this.phase;
|
|
23219
|
-
}
|
|
23220
|
-
/**
|
|
23221
|
-
* Assert that `capability` is permitted right now. Throws {@link RuleOfTwoViolation}
|
|
23222
|
-
* (fail-closed) if no phase is active or the active phase doesn't grant it —
|
|
23223
|
-
* which structurally prevents the forbidden three-leg conjunction, since no
|
|
23224
|
-
* phase grants more than two legs.
|
|
23225
|
-
*/
|
|
23226
|
-
assertCapability(capability) {
|
|
23227
|
-
if (this.phase === void 0) {
|
|
23228
|
-
throw new RuleOfTwoViolation(
|
|
23229
|
-
`capability '${capability}' requested before any remediation phase was entered (fail-closed)`
|
|
23230
|
-
);
|
|
23231
|
-
}
|
|
23232
|
-
const allowed = PHASE_CAPABILITIES[this.phase];
|
|
23233
|
-
if (!allowed.has(capability)) {
|
|
23234
|
-
throw new RuleOfTwoViolation(
|
|
23235
|
-
`capability '${capability}' is not permitted in phase '${this.phase}' (allowed: ${[...allowed].join(", ")})`
|
|
23236
|
-
);
|
|
23237
|
-
}
|
|
23238
|
-
}
|
|
23239
|
-
};
|
|
23240
|
-
var RemediationActionKindSchema = z8.enum([
|
|
23241
|
-
"investigate",
|
|
23242
|
-
"adjust-routing",
|
|
23243
|
-
"add-test",
|
|
23244
|
-
"refactor",
|
|
23245
|
-
"update-docs",
|
|
23246
|
-
"fix-bug"
|
|
23247
|
-
]);
|
|
23248
|
-
var RemediationStepSchema = z8.object({
|
|
23249
|
-
kind: RemediationActionKindSchema,
|
|
23250
|
-
description: z8.string().min(1).max(500),
|
|
23251
|
-
/** Optional path hint; bounded inert string, validated for traversal at use. */
|
|
23252
|
-
targetPath: z8.string().min(1).max(300).optional()
|
|
23253
|
-
}).strict();
|
|
23254
|
-
var RemediationPlanSchema = z8.object({
|
|
23255
|
-
/** Source signal key (mirrors ImprovementSignal.signalKey). */
|
|
23256
|
-
signalKey: z8.string().min(1).max(200),
|
|
23257
|
-
/** Signal category (mirrors SignalCategory). */
|
|
23258
|
-
category: z8.enum(["routing", "tech-debt", "bug", "security", "consensus"]),
|
|
23259
|
-
summary: z8.string().min(1).max(1e3),
|
|
23260
|
-
steps: z8.array(RemediationStepSchema).min(1).max(20)
|
|
23261
|
-
}).strict();
|
|
23262
|
-
function parseRemediationPlan(raw) {
|
|
23263
|
-
const result = RemediationPlanSchema.safeParse(raw);
|
|
23264
|
-
if (!result.success) {
|
|
23265
|
-
throw new RuleOfTwoViolation(
|
|
23266
|
-
`RemediationPlan failed strict validation at the RESEARCH\u2192IMPLEMENT boundary: ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
|
|
23267
|
-
);
|
|
23268
|
-
}
|
|
23269
|
-
return result.data;
|
|
23270
|
-
}
|
|
23271
|
-
function renderPlanAsResearch(plan) {
|
|
23272
|
-
const steps = plan.steps.map((s, i) => {
|
|
23273
|
-
const target = s.targetPath !== void 0 ? ` (target: ${s.targetPath})` : "";
|
|
23274
|
-
return `${String(i + 1)}. [${s.kind}] ${s.description}${target}`;
|
|
23275
|
-
}).join("\n");
|
|
23276
|
-
return `Remediation plan for signal '${plan.signalKey}' (category: ${plan.category}).
|
|
23277
|
-
|
|
23278
|
-
${plan.summary}
|
|
23279
|
-
|
|
23280
|
-
Steps:
|
|
23281
|
-
${steps}`;
|
|
23282
|
-
}
|
|
23283
|
-
|
|
23284
23433
|
// src/mcp/tools/remediation-circuit-breaker.ts
|
|
23285
23434
|
var DEFAULT_CIRCUIT_BREAKER_CONFIG = { threshold: 3 };
|
|
23286
23435
|
var RemediationCircuitBreaker = class {
|
|
@@ -23584,16 +23733,16 @@ async function handleAutoRemediateCommand(args) {
|
|
|
23584
23733
|
// src/cli/migrate-command.ts
|
|
23585
23734
|
import { cpSync, existsSync as existsSync22, mkdirSync as mkdirSync6, readdirSync as readdirSync3 } from "fs";
|
|
23586
23735
|
import { homedir } from "os";
|
|
23587
|
-
import { join as
|
|
23736
|
+
import { join as join19 } from "path";
|
|
23588
23737
|
var logger18 = createLogger({ component: "migrate-command" });
|
|
23589
|
-
var HOMEDIR_DEFAULT_BASE =
|
|
23738
|
+
var HOMEDIR_DEFAULT_BASE = join19(homedir(), ".nexus-agents");
|
|
23590
23739
|
function countItems(dir) {
|
|
23591
23740
|
if (!existsSync22(dir)) return 0;
|
|
23592
23741
|
try {
|
|
23593
23742
|
const entries = readdirSync3(dir, { withFileTypes: true });
|
|
23594
23743
|
let n = 0;
|
|
23595
23744
|
for (const e of entries) {
|
|
23596
|
-
const p =
|
|
23745
|
+
const p = join19(dir, e.name);
|
|
23597
23746
|
if (e.isDirectory()) {
|
|
23598
23747
|
n += countItems(p);
|
|
23599
23748
|
} else {
|
|
@@ -23648,8 +23797,8 @@ function checkEarlyExits(fromBase, toBase, dryRun) {
|
|
|
23648
23797
|
return null;
|
|
23649
23798
|
}
|
|
23650
23799
|
function planAndExecuteEntry(name, fromBase, toBase, perRepoSet, dryRun) {
|
|
23651
|
-
const source =
|
|
23652
|
-
const target =
|
|
23800
|
+
const source = join19(fromBase, name);
|
|
23801
|
+
const target = join19(toBase, name);
|
|
23653
23802
|
if (!perRepoSet.has(name)) {
|
|
23654
23803
|
return { subdir: name, status: "skipped-not-per-repo", source, target: "", itemsCopied: 0 };
|
|
23655
23804
|
}
|
|
@@ -23669,7 +23818,7 @@ function planAndExecuteEntry(name, fromBase, toBase, perRepoSet, dryRun) {
|
|
|
23669
23818
|
function resolveDefaultTarget(cwd) {
|
|
23670
23819
|
const repoRoot = findRepoRoot(cwd);
|
|
23671
23820
|
if (repoRoot === null) return null;
|
|
23672
|
-
return
|
|
23821
|
+
return join19(repoRoot, ".nexus-agents");
|
|
23673
23822
|
}
|
|
23674
23823
|
function formatMigrationResult(result) {
|
|
23675
23824
|
if (!result.success) {
|