nexus-agents 2.123.5 → 2.124.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-G6FEO2N2.js → chunk-35YWAUJX.js} +38 -1
- package/dist/chunk-35YWAUJX.js.map +1 -0
- package/dist/{chunk-S4YUKUTS.js → chunk-D52WH4UW.js} +3 -3
- package/dist/{chunk-YNSSSY5X.js → chunk-JLXZPSMU.js} +3 -3
- package/dist/{chunk-RBTHFAKW.js → chunk-LKWQ3AT4.js} +2 -2
- package/dist/cli.js +5 -5
- package/dist/{improvement-review-IIKRVAWM.js → improvement-review-Z4ETNJWO.js} +2 -2
- package/dist/index.d.ts +134 -128
- package/dist/index.js +3 -3
- package/dist/{setup-command-SBPGWYG7.js → setup-command-G6IWNPE2.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-G6FEO2N2.js.map +0 -1
- /package/dist/{chunk-S4YUKUTS.js.map → chunk-D52WH4UW.js.map} +0 -0
- /package/dist/{chunk-YNSSSY5X.js.map → chunk-JLXZPSMU.js.map} +0 -0
- /package/dist/{chunk-RBTHFAKW.js.map → chunk-LKWQ3AT4.js.map} +0 -0
- /package/dist/{improvement-review-IIKRVAWM.js.map → improvement-review-Z4ETNJWO.js.map} +0 -0
- /package/dist/{setup-command-SBPGWYG7.js.map → setup-command-G6IWNPE2.js.map} +0 -0
|
@@ -704,6 +704,40 @@ function emitFitnessDeclinedSignal(audit, fitnessFloor, bus, logger) {
|
|
|
704
704
|
}
|
|
705
705
|
}
|
|
706
706
|
|
|
707
|
+
// src/mcp/tools/improvement-remediation.ts
|
|
708
|
+
var ROLE_BY_CATEGORY = {
|
|
709
|
+
security: "security",
|
|
710
|
+
bug: "coder",
|
|
711
|
+
"tech-debt": "coder",
|
|
712
|
+
routing: "researcher",
|
|
713
|
+
consensus: "researcher"
|
|
714
|
+
};
|
|
715
|
+
function remediationTaskId(signal) {
|
|
716
|
+
return `improvement-${signal.signalKey}`;
|
|
717
|
+
}
|
|
718
|
+
function improvementSignalToTask(signal) {
|
|
719
|
+
return {
|
|
720
|
+
id: remediationTaskId(signal),
|
|
721
|
+
title: signal.title,
|
|
722
|
+
description: `Auto-suggested remediation from improvement_review (#3540 \u2014 SUGGEST-ONLY, nothing executed). Category: ${signal.category}; severity: ${signal.severity}.
|
|
723
|
+
|
|
724
|
+
${signal.body}
|
|
725
|
+
|
|
726
|
+
If accepted, route this through the dev-pipeline (research \u2192 plan \u2192 vote \u2192 implement \u2192 QA \u2192 security gate). Auto-invocation is a separate, owner-gated step.`,
|
|
727
|
+
assignedTo: ROLE_BY_CATEGORY[signal.category],
|
|
728
|
+
status: "pending"
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
function improvementSignalsToTasks(signals, existingTaskIds) {
|
|
732
|
+
const tasks = [];
|
|
733
|
+
for (const signal of signals) {
|
|
734
|
+
const task = improvementSignalToTask(signal);
|
|
735
|
+
if (existingTaskIds?.has(task.id) === true) continue;
|
|
736
|
+
tasks.push(task);
|
|
737
|
+
}
|
|
738
|
+
return tasks;
|
|
739
|
+
}
|
|
740
|
+
|
|
707
741
|
// src/mcp/tools/improvement-review.ts
|
|
708
742
|
var execFileAsync2 = promisify2(execFile2);
|
|
709
743
|
var ImprovementReviewInputSchema = z.object({
|
|
@@ -1071,6 +1105,9 @@ async function runImprovementReview(input, deps = {}) {
|
|
|
1071
1105
|
window: windowLabel,
|
|
1072
1106
|
totalOutcomes: windowed.length,
|
|
1073
1107
|
signals,
|
|
1108
|
+
// #3540 increment 1: surface remediation tasks derived from the signals
|
|
1109
|
+
// (suggest-only — composes existing detection, no auto-invocation).
|
|
1110
|
+
remediationTasks: improvementSignalsToTasks(signals),
|
|
1074
1111
|
issuesFiled,
|
|
1075
1112
|
issuesSkipped
|
|
1076
1113
|
};
|
|
@@ -1138,4 +1175,4 @@ export {
|
|
|
1138
1175
|
runImprovementReview,
|
|
1139
1176
|
registerImprovementReviewTool
|
|
1140
1177
|
};
|
|
1141
|
-
//# sourceMappingURL=chunk-
|
|
1178
|
+
//# sourceMappingURL=chunk-35YWAUJX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/tools/improvement-review.ts","../src/mcp/middleware/tool-prerequisites.ts","../src/governance/fitness-score.ts","../src/mcp/tools/improvement-review-signals.ts","../src/mcp/tools/improvement-remediation.ts"],"sourcesContent":["/**\n * nexus-agents/mcp - Improvement Review Tool\n *\n * Periodic, threshold-gated observability-driven improvement loop.\n *\n * Reads from existing observability primitives (OutcomeStore, weather-report,\n * fitness-audit, audit-chain) and surfaces patterns that cross documented\n * thresholds as candidate GitHub issues. Never auto-merges; humans or\n * `consensus_vote` decide what to implement.\n *\n * Replaces the deleted `src/workflows/self-development/` engine, which never\n * wired up to consume any of these signals.\n *\n * @module mcp/tools/improvement-review\n * (Source: Issue #2402)\n */\n\nimport { execFile } from 'node:child_process';\nimport { readFile } from 'node:fs/promises';\nimport { promisify } from 'node:util';\n/* eslint-disable max-lines */\nimport { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { createLogger, formatZodError, getErrorMessage } from '../../core/index.js';\nimport { wrapToolWithTimeout, toSdkCallback, getToolTimeout } from '../middleware/tool-wrapper.js';\nimport { createSecureHandler, type HandlerContext } from '../middleware/secure-handler.js';\nimport { withPrerequisite } from '../middleware/tool-prerequisites.js';\nimport {\n toolStructuredError,\n toolSuccessStructured,\n type ToolResult,\n type BaseMcpToolDeps,\n} from './tool-result.js';\nimport { getOutcomeStore } from '../../orchestration/outcomes/outcome-store.js';\nimport type { TaskOutcome } from '../../orchestration/outcomes/outcome-types.js';\nimport { calculateFitnessScore, type FitnessAudit } from '../../governance/fitness-score.js';\nimport { getPipelineEventBus } from '../../pipeline/event-bus.js';\nimport type { VoteRejectedSignalEvent } from '../../pipeline/event-types.js';\nimport { REJECTION_CATEGORIES } from '../../consensus/types-core.js';\nimport { emitFitnessDeclinedSignal } from './improvement-review-signals.js';\nimport { improvementSignalsToTasks } from './improvement-remediation.js';\nimport type { PipelineTask } from '../../pipeline/dev-pipeline.js';\nimport { getToolAnnotations } from '../tool-annotations.js';\n\nconst execFileAsync = promisify(execFile);\n\n// ============================================================================\n// Schemas\n// ============================================================================\n\nexport const ImprovementReviewInputSchema = z.object({\n lookbackDays: z\n .number()\n .int()\n .min(1)\n .max(90)\n .optional()\n .default(7)\n .describe('Lookback window for outcome data, in days. Default 7.'),\n fileIssues: z\n .boolean()\n .optional()\n .default(false)\n .describe(\n 'When true, file candidate issues via `gh issue create` for crossed thresholds (rate-limited to 5 per run, deduped against open issues). When false (default), return signals only.'\n ),\n minSampleSize: z\n .number()\n .int()\n .min(1)\n .max(1000)\n .optional()\n .default(5)\n .describe('Minimum sample size before a CLI/category signal can fire.'),\n fitnessFloor: z\n .number()\n .int()\n .min(0)\n .max(100)\n .optional()\n .default(90)\n .describe('Fitness score below this threshold triggers a tech-debt signal.'),\n selfEvalReportPath: z\n .string()\n .optional()\n .describe(\n 'Optional path to a self-eval JSON report (from `self-eval --json`). When set, ' +\n 'high-confidence unanimous deprecate/refactor findings are surfaced as tech-debt ' +\n 'signals through the same deduped/rate-limited issue path (#3224). Unreadable/malformed ' +\n 'reports are skipped (no signal). Absent → no self-eval signals.'\n ),\n});\n\nexport type ImprovementReviewInput = z.infer<typeof ImprovementReviewInputSchema>;\n\nexport type SignalCategory = 'routing' | 'tech-debt' | 'bug' | 'security' | 'consensus';\n\nexport interface ImprovementSignal {\n readonly category: SignalCategory;\n /** Stable key used for dedup against existing issues. */\n readonly signalKey: string;\n /** Severity per CVSS-aligned scale (security uses critical; others use warning/info). */\n readonly severity: 'info' | 'warning' | 'critical';\n /** One-line title suitable for a GitHub issue. */\n readonly title: string;\n /** Multi-line body with evidence (sample counts, time windows, observed values). */\n readonly body: string;\n /** Linkable evidence the signal is grounded in observability data, not intuition. */\n readonly evidence: {\n readonly samples?: number;\n readonly window?: string;\n readonly observedValue?: number;\n readonly threshold?: number;\n };\n}\n\nexport interface ImprovementReviewResponse {\n readonly window: string;\n readonly totalOutcomes: number;\n readonly signals: readonly ImprovementSignal[];\n /**\n * Remediation tasks derived from {@link signals} (#3540 capability-loop\n * increment 1) — SUGGEST-ONLY: structured tasks for a reviewer to consider\n * routing through the dev-pipeline. Nothing here is executed or auto-invoked.\n */\n readonly remediationTasks: readonly PipelineTask[];\n readonly issuesFiled: readonly { readonly signalKey: string; readonly issueUrl: string }[];\n readonly issuesSkipped: readonly { readonly signalKey: string; readonly reason: string }[];\n}\n\n// ============================================================================\n// Pure threshold logic (testable without fs / network)\n// ============================================================================\n\nconst MAX_ISSUES_PER_RUN = 5;\n\nconst HOUR_MS = 60 * 60 * 1000;\nconst DAY_MS = 24 * HOUR_MS;\n\n/** Filter outcomes to a lookback window. Outcome timestamps are ISO strings. */\nexport function filterByLookback(\n outcomes: readonly TaskOutcome[],\n lookbackDays: number,\n now: number\n): readonly TaskOutcome[] {\n const cutoff = now - lookbackDays * DAY_MS;\n return outcomes.filter((o) => {\n const t = Date.parse(o.timestamp);\n return Number.isFinite(t) && t >= cutoff;\n });\n}\n\n/**\n * Detect CLI × category pairs whose success rate has fallen below the\n * performance floor with at least minSamples observations.\n *\n * Threshold: success rate < 60% AND samples >= minSamples.\n */\nexport function detectCliPerformanceFloor(\n outcomes: readonly TaskOutcome[],\n minSamples: number,\n windowLabel: string\n): readonly ImprovementSignal[] {\n const buckets = new Map<string, { cli: string; category: string; ok: number; total: number }>();\n for (const o of outcomes) {\n const key = `${o.cli}::${o.category}`;\n const bucket = buckets.get(key) ?? { cli: o.cli, category: o.category, ok: 0, total: 0 };\n bucket.total += 1;\n if (o.success) bucket.ok += 1;\n buckets.set(key, bucket);\n }\n\n const signals: ImprovementSignal[] = [];\n for (const b of buckets.values()) {\n if (b.total < minSamples) continue;\n const rate = b.ok / b.total;\n if (rate >= 0.6) continue;\n const ratePct = Math.round(rate * 100);\n signals.push({\n category: 'routing',\n signalKey: `routing:cli-floor:${b.cli}:${b.category}`,\n severity: rate < 0.4 ? 'critical' : 'warning',\n title: `routing: ${b.cli} success rate ${String(ratePct)}% on ${b.category} (${windowLabel})`,\n body: [\n `Observed performance floor breach in the ${windowLabel} window.`,\n '',\n `- CLI: \\`${b.cli}\\``,\n `- Category: \\`${b.category}\\``,\n `- Success rate: ${String(ratePct)}% (${String(b.ok)}/${String(b.total)})`,\n `- Threshold: 60% with ≥${String(minSamples)} samples`,\n '',\n 'Consider routing this category away from this CLI, or investigating the failure pattern via `weather_report` and the OutcomeStore.',\n ].join('\\n'),\n evidence: {\n samples: b.total,\n window: windowLabel,\n observedValue: rate,\n threshold: 0.6,\n },\n });\n }\n return signals;\n}\n\n/**\n * Minimum number of rejected plans citing the same ADR-0016 rule before a\n * recurring-rejection pattern is worth surfacing. Two is coincidence; three is\n * a systemic planning gap (mirrors the DRY \"third occurrence\" rule).\n */\nconst MIN_REJECTION_PATTERN = 3;\n\n/**\n * Detect recurring consensus-rejection patterns (#3259): a single ADR-0016\n * rejection rule (`DRY_VIOLATION`, `OVER_ENGINEERING`, `SCOPE_CREEP`, …) cited\n * across ≥{@link MIN_REJECTION_PATTERN} rejected plans in the window. The\n * `signal.vote_rejected` events are produced by `consensus_vote` on rejection\n * (consensus-vote-signals.ts) and buffered on the pipeline event bus; this\n * detector closes the loop the system review flagged as missing — recurring\n * rejection for the same reason means the planner keeps making the same class\n * of mistake, which the next improvement cycle should name explicitly.\n *\n * Events with no `rejectionRules` (un-categorized rejections) contribute no\n * pattern signal — there is nothing actionable to aggregate on.\n */\nexport function detectConsensusRejectionSignals(\n events: readonly VoteRejectedSignalEvent[],\n windowLabel: string\n): readonly ImprovementSignal[] {\n if (events.length === 0) return [];\n\n // Defense-in-depth allowlist: the only producer (consensus-vote-signals.ts)\n // sources rules from the Zod-validated ADR-0016 enum, so a free-form/poisoned\n // rule cannot reach here today. Re-validating against REJECTION_CATEGORIES\n // makes that safety local — an unexpected rule string never reaches an issue\n // title/body — instead of relying on cross-file inference (#3259 review).\n const allowed = new Set<string>(REJECTION_CATEGORIES);\n const byRule = new Map<string, number>();\n for (const e of events) {\n for (const rule of e.rejectionRules ?? []) {\n if (!allowed.has(rule)) continue;\n byRule.set(rule, (byRule.get(rule) ?? 0) + 1);\n }\n }\n\n const signals: ImprovementSignal[] = [];\n for (const [rule, count] of byRule) {\n if (count < MIN_REJECTION_PATTERN) continue;\n signals.push({\n category: 'consensus',\n signalKey: `consensus:rejection-pattern:${rule}`,\n severity: count >= MIN_REJECTION_PATTERN * 2 ? 'warning' : 'info',\n title: `consensus: ${String(count)} plans rejected for \\`${rule}\\` in ${windowLabel}`,\n body: [\n `Recurring consensus-rejection pattern in the ${windowLabel} window.`,\n '',\n `- Rejection rule: \\`${rule}\\` (ADR-0016 category)`,\n `- Occurrences: ${String(count)} rejected plans`,\n `- Threshold: ≥${String(MIN_REJECTION_PATTERN)} plans citing the same rule`,\n '',\n 'The planner keeps producing plans that voters reject for the same reason. ' +\n 'Feed this back into plan generation (e.g. a planning guardrail or a ' +\n 'targeted prompt note) rather than rejecting plan-by-plan. Inspect the ' +\n 'rejected proposals via `query_trace` / the consensus audit chain.',\n ].join('\\n'),\n evidence: {\n samples: count,\n window: windowLabel,\n observedValue: count,\n threshold: MIN_REJECTION_PATTERN,\n },\n });\n }\n return signals;\n}\n\n/**\n * Detect failure-category concentration: a single failure category accounts\n * for > 50% of all failures with at least 10 failures observed.\n */\nexport function detectFailureCategoryConcentration(\n outcomes: readonly TaskOutcome[],\n windowLabel: string\n): readonly ImprovementSignal[] {\n const failures = outcomes.filter((o) => !o.success);\n if (failures.length < 10) return [];\n\n const byCategory = new Map<string, number>();\n for (const f of failures) {\n const cat = f.failureCategory ?? 'unknown';\n byCategory.set(cat, (byCategory.get(cat) ?? 0) + 1);\n }\n\n const signals: ImprovementSignal[] = [];\n for (const [cat, count] of byCategory) {\n const share = count / failures.length;\n if (share <= 0.5) continue;\n const sharePct = Math.round(share * 100);\n signals.push({\n category: 'bug',\n signalKey: `bug:failure-concentration:${cat}`,\n severity: 'warning',\n title: `bug: ${String(sharePct)}% of failures in ${windowLabel} share category \\`${cat}\\``,\n body: [\n `Failure-category concentration breach in the ${windowLabel} window.`,\n '',\n `- Category: \\`${cat}\\``,\n `- Share: ${String(sharePct)}% (${String(count)}/${String(failures.length)} failures)`,\n `- Threshold: > 50% with ≥10 failures`,\n '',\n 'A single failure mode dominating the error budget usually means a systemic bug or routing miss. Investigate via `query_trace` and the OutcomeStore.',\n ].join('\\n'),\n evidence: {\n samples: failures.length,\n window: windowLabel,\n observedValue: share,\n threshold: 0.5,\n },\n });\n }\n return signals;\n}\n\nfunction buildFloorSignal(audit: FitnessAudit, fitnessFloor: number): ImprovementSignal {\n return {\n category: 'tech-debt',\n signalKey: `tech-debt:fitness-below-floor`,\n severity: audit.score < 70 ? 'critical' : 'warning',\n title: `tech-debt: fitness score ${String(audit.score)}/100 below floor ${String(fitnessFloor)}`,\n body: [\n `Code fitness score has dropped below the governance floor.`,\n '',\n `- Score: ${String(audit.score)} / 100`,\n `- Floor: ${String(fitnessFloor)} (governance threshold per CLAUDE.md)`,\n `- Findings: ${String(audit.findings.length)} total`,\n '',\n 'Run `nexus-agents fitness-audit` for the full breakdown. Critical findings:',\n ...audit.findings\n .filter((f) => f.severity === 'critical')\n .slice(0, 5)\n .map((f) => `- ${f.dimension}: ${f.description}`),\n ].join('\\n'),\n evidence: { observedValue: audit.score, threshold: fitnessFloor },\n };\n}\n\nfunction buildCriticalFindingSignal(finding: FitnessAudit['findings'][number]): ImprovementSignal {\n return {\n category: 'tech-debt',\n signalKey: `tech-debt:fitness-critical:${finding.dimension}`,\n severity: 'critical',\n title: `tech-debt: critical fitness finding in ${finding.dimension}`,\n body: [\n `Fitness audit returned a CRITICAL finding.`,\n '',\n `- Dimension: \\`${finding.dimension}\\``,\n `- Description: ${finding.description}`,\n `- Points deducted: ${String(finding.pointsDeducted)}`,\n finding.location !== undefined ? `- Location: ${finding.location}` : '',\n finding.suggestion !== undefined ? `- Suggestion: ${finding.suggestion}` : '',\n ]\n .filter((line) => line.length > 0)\n .join('\\n'),\n evidence: { observedValue: -finding.pointsDeducted },\n };\n}\n\n/** Detect fitness signals: score below floor OR critical findings. */\nexport function detectFitnessSignals(\n audit: FitnessAudit,\n fitnessFloor: number\n): readonly ImprovementSignal[] {\n const signals: ImprovementSignal[] = [];\n if (audit.score < fitnessFloor) signals.push(buildFloorSignal(audit, fitnessFloor));\n for (const finding of audit.findings) {\n if (finding.severity === 'critical') signals.push(buildCriticalFindingSignal(finding));\n }\n return signals;\n}\n\n// ============================================================================\n// Self-eval findings → tech-debt signals (#3224)\n// ============================================================================\n\n/** Minimum confidence for a self-eval finding to surface as a signal. */\nconst SELF_EVAL_CONFIDENCE_FLOOR = 0.8;\n\n/**\n * Minimal, defensive schema for the `self-eval --json` report. We only read the\n * fields needed to surface a finding; unknown extras are ignored so the parse\n * tolerates schema drift in the (externally produced) artifact.\n */\nconst SelfEvalReportSchema = z.object({\n results: z.array(\n z.object({\n component: z.string(),\n finalRecommendation: z.string(),\n confidence: z.number(),\n dissent: z.array(z.unknown()).optional().default([]),\n evidenceQuality: z.number().optional(),\n })\n ),\n});\n\n/**\n * Convert a parsed self-eval report into tech-debt `ImprovementSignal`s.\n *\n * Only **actionable, high-confidence, unanimous** findings surface (#3224): a\n * `deprecate`/`refactor` recommendation with NO dissent and confidence at/above\n * {@link SELF_EVAL_CONFIDENCE_FLOOR}. This is a pure transform — it surfaces a\n * human decision point (a candidate issue), never an automatic routing change.\n */\nexport function detectSelfEvalSignals(\n report: z.infer<typeof SelfEvalReportSchema>,\n windowLabel: string\n): readonly ImprovementSignal[] {\n const signals: ImprovementSignal[] = [];\n for (const r of report.results) {\n const actionable =\n r.finalRecommendation === 'deprecate' || r.finalRecommendation === 'refactor';\n if (!actionable || r.dissent.length > 0 || r.confidence < SELF_EVAL_CONFIDENCE_FLOOR) continue;\n signals.push({\n category: 'tech-debt',\n signalKey: `tech-debt:self-eval:${r.component}:${r.finalRecommendation}`,\n severity: r.finalRecommendation === 'deprecate' ? 'warning' : 'info',\n title: `tech-debt: self-eval recommends ${r.finalRecommendation} for ${r.component}`,\n body: [\n `All self-eval evaluators agreed (no dissent) on **${r.finalRecommendation}** for \\`${r.component}\\``,\n `with confidence ${(r.confidence * 100).toFixed(0)}%${r.evidenceQuality !== undefined ? ` (evidence quality ${(r.evidenceQuality * 100).toFixed(0)}%)` : ''}.`,\n '',\n 'This is a RECOMMENDATION surfaced for human review — not an automatic change.',\n ].join('\\n'),\n evidence: {\n observedValue: r.confidence,\n threshold: SELF_EVAL_CONFIDENCE_FLOOR,\n window: windowLabel,\n },\n });\n }\n return signals;\n}\n\n/**\n * Read + parse a self-eval JSON report and convert it to signals. Fail-soft:\n * an unreadable or malformed report yields NO signals (logged at warn) rather\n * than breaking the review.\n */\nexport async function loadSelfEvalSignals(\n reportPath: string,\n windowLabel: string,\n logger: ReturnType<typeof createLogger>\n): Promise<readonly ImprovementSignal[]> {\n try {\n const raw = await readFile(reportPath, 'utf8');\n const parsed = SelfEvalReportSchema.safeParse(JSON.parse(raw));\n if (!parsed.success) {\n logger.warn('Self-eval report ignored — schema mismatch', {\n reportPath,\n error: formatZodError(parsed.error),\n });\n return [];\n }\n return detectSelfEvalSignals(parsed.data, windowLabel);\n } catch (error) {\n logger.warn('Self-eval report ignored — unreadable/invalid JSON', {\n reportPath,\n error: getErrorMessage(error),\n });\n return [];\n }\n}\n\n// ============================================================================\n// Issue filing (gated, dedup-checked, command-injection-safe)\n// ============================================================================\n\n/**\n * Check whether an existing OPEN issue already covers this signal key.\n * Uses `gh issue list --search` with the signal key as a literal phrase.\n * The signal key appears in our filed-issue body so this dedup is reliable.\n */\nasync function existingIssueForSignal(signalKey: string): Promise<string | null> {\n try {\n // Strip double-quotes from the search term so a quote in the signalKey\n // (e.g. an oddly-named self-eval component path, #3224) can't break the\n // `\"...\" in:body` phrase query and silently defeat dedup → refiling.\n const searchTerm = signalKey.replace(/\"/g, '');\n const { stdout } = await execFileAsync('gh', [\n 'issue',\n 'list',\n '--state',\n 'open',\n '--search',\n `\"${searchTerm}\" in:body`,\n '--json',\n 'number,url',\n '--limit',\n '5',\n ]);\n const parsed = JSON.parse(stdout) as readonly { url?: string }[];\n if (parsed.length > 0 && typeof parsed[0]?.url === 'string') {\n return parsed[0].url;\n }\n return null;\n } catch {\n // gh failure → conservatively treat as \"no dup\" but log upstream.\n return null;\n }\n}\n\n/**\n * File an issue via `gh issue create` using execFile (no shell, no\n * command-injection risk on errorMessage / title / body content).\n */\nasync function fileIssueForSignal(\n signal: ImprovementSignal\n): Promise<{ ok: true; url: string } | { ok: false; error: string }> {\n // Embed the signal key in the body so dedup is reliable on subsequent runs.\n const body = `${signal.body}\\n\\n---\\n\\n_Signal key (do not edit): \\`${signal.signalKey}\\` · Generated by \\`improvement_review\\` (#2402) · Severity: ${signal.severity}_`;\n const labels = signal.category === 'security' ? 'security' : signal.category;\n\n try {\n const { stdout } = await execFileAsync('gh', [\n 'issue',\n 'create',\n '--title',\n signal.title,\n '--body',\n body,\n '--label',\n labels,\n ]);\n const url = stdout.trim();\n if (!url.startsWith('https://')) {\n return { ok: false, error: `gh returned unexpected output: ${stdout.slice(0, 200)}` };\n }\n return { ok: true, url };\n } catch (caught) {\n const message = caught instanceof Error ? caught.message : String(caught);\n return { ok: false, error: message };\n }\n}\n\n// ============================================================================\n// Handler\n// ============================================================================\n\nfunction safeFitnessAudit(now: number, ctx: HandlerContext): FitnessAudit {\n try {\n return calculateFitnessScore('improvement-review');\n } catch (caught) {\n ctx.logger.warn('fitness audit failed; skipping fitness signals', {\n error: caught instanceof Error ? caught.message : String(caught),\n });\n return {\n score: 100,\n dimensions: {} as FitnessAudit['dimensions'],\n findings: [],\n timestamp: new Date(now).toISOString(),\n version: 'improvement-review-fallback',\n };\n }\n}\n\nconst SEVERITY_ORDER: Record<ImprovementSignal['severity'], number> = {\n critical: 0,\n warning: 1,\n info: 2,\n};\n\nasync function fileSignalsAsIssues(\n signals: readonly ImprovementSignal[],\n ctx: HandlerContext\n): Promise<{\n issuesFiled: { signalKey: string; issueUrl: string }[];\n issuesSkipped: { signalKey: string; reason: string }[];\n}> {\n const issuesFiled: { signalKey: string; issueUrl: string }[] = [];\n const issuesSkipped: { signalKey: string; reason: string }[] = [];\n\n for (const signal of signals) {\n if (issuesFiled.length >= MAX_ISSUES_PER_RUN) {\n issuesSkipped.push({ signalKey: signal.signalKey, reason: 'rate-limit' });\n continue;\n }\n const existing = await existingIssueForSignal(signal.signalKey);\n if (existing !== null) {\n issuesSkipped.push({ signalKey: signal.signalKey, reason: `dup:${existing}` });\n continue;\n }\n const result = await fileIssueForSignal(signal);\n if (result.ok) {\n issuesFiled.push({ signalKey: signal.signalKey, issueUrl: result.url });\n ctx.logger.info('improvement signal filed', {\n signalKey: signal.signalKey,\n url: result.url,\n });\n } else {\n issuesSkipped.push({ signalKey: signal.signalKey, reason: `error:${result.error}` });\n }\n }\n\n return { issuesFiled, issuesSkipped };\n}\n\n/**\n * Read `signal.vote_rejected` events from the pipeline bus's buffered history,\n * narrowed to the lookback window. Returns `[]` if the bus is empty or every\n * event predates the window. Fail-soft: never throws into the review run.\n *\n * The bus is a per-process module singleton (event-bus.ts), so this only sees\n * rejections emitted by `consensus_vote` *in the same process* — i.e. a\n * long-lived MCP server where both tools share the buffer. In separate\n * CLI invocations the buffer starts empty and this correctly yields no signals\n * (the loop degrades to \"no consensus data\" rather than misreporting).\n */\nfunction readBufferedVoteRejections(\n now: number,\n lookbackDays: number\n): readonly VoteRejectedSignalEvent[] {\n const cutoff = now - lookbackDays * DAY_MS;\n return getPipelineEventBus()\n .query({ type: 'signal.vote_rejected' })\n .filter((e): e is VoteRejectedSignalEvent => e.type === 'signal.vote_rejected')\n .filter((e) => e.timestamp >= cutoff);\n}\n\n/**\n * Context-free runner exposed for both the MCP handler and the\n * `nexus-agents improvement-review` CLI subcommand (#2444). Pure dependencies\n * — pass a logger and an OutcomeStore-query result if you want to inject test\n * data; defaults read the global store and a no-op logger.\n */\nexport async function runImprovementReview(\n input: ImprovementReviewInput,\n deps: { readonly logger?: ReturnType<typeof createLogger> } = {}\n): Promise<ImprovementReviewResponse> {\n const logger = deps.logger ?? createLogger({ component: 'improvement_review' });\n const { lookbackDays, fileIssues, minSampleSize, fitnessFloor, selfEvalReportPath } = input;\n const now = Date.now();\n const windowLabel = `${String(lookbackDays)}d`;\n\n const allOutcomes = getOutcomeStore().query();\n const windowed = filterByLookback(allOutcomes, lookbackDays, now);\n const audit = safeFitnessAudit(now, { logger } as HandlerContext);\n\n // Surface high-confidence unanimous self-eval findings as tech-debt signals\n // (#3224) — opt-in via selfEvalReportPath, fail-soft (no path / bad file → none).\n const selfEvalSignals =\n selfEvalReportPath !== undefined\n ? await loadSelfEvalSignals(selfEvalReportPath, windowLabel, logger)\n : [];\n\n // Recurring consensus-rejection patterns (#3259). `consensus_vote` buffers a\n // `signal.vote_rejected` event per rejected plan on the pipeline bus; read the\n // buffered history (not a live subscription — this is a one-shot tool) and\n // window-filter by event timestamp before aggregating.\n const rejectionEvents = readBufferedVoteRejections(now, lookbackDays);\n\n const signals: ImprovementSignal[] = [\n ...detectCliPerformanceFloor(windowed, minSampleSize, windowLabel),\n ...detectFailureCategoryConcentration(windowed, windowLabel),\n ...detectFitnessSignals(audit, fitnessFloor),\n ...detectConsensusRejectionSignals(rejectionEvents, windowLabel),\n ...selfEvalSignals,\n ];\n signals.sort((a, b) => SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity]);\n\n // Close the self-tuning loop: a below-floor fitness audit emits\n // signal.fitness_declined onto the typed pipeline bus for the shadow\n // TuneStage (#3147; #3289 Option 2 — observability signals route through bus A).\n emitFitnessDeclinedSignal(audit, fitnessFloor, getPipelineEventBus(), logger);\n\n const { issuesFiled, issuesSkipped } = fileIssues\n ? await fileSignalsAsIssues(signals, { logger } as HandlerContext)\n : { issuesFiled: [], issuesSkipped: [] };\n\n return {\n window: windowLabel,\n totalOutcomes: windowed.length,\n signals,\n // #3540 increment 1: surface remediation tasks derived from the signals\n // (suggest-only — composes existing detection, no auto-invocation).\n remediationTasks: improvementSignalsToTasks(signals),\n issuesFiled,\n issuesSkipped,\n };\n}\n\nasync function reviewHandler(args: unknown, ctx: HandlerContext): Promise<ToolResult> {\n const parsed = ImprovementReviewInputSchema.safeParse(args);\n if (!parsed.success) {\n return toolStructuredError({\n errorCategory: 'validation',\n message: `Validation error: ${formatZodError(parsed.error)}`,\n });\n }\n const response = await runImprovementReview(parsed.data, { logger: ctx.logger });\n return toolSuccessStructured(response as unknown as Record<string, unknown>);\n}\n\n// ============================================================================\n// Registration\n// ============================================================================\n\nexport type ImprovementReviewDeps = BaseMcpToolDeps;\n\nconst description =\n 'Periodic threshold-gated observability-driven improvement loop. Reads OutcomeStore + ' +\n 'fitness audit, surfaces patterns crossing documented thresholds as candidate findings. ' +\n 'When fileIssues=true, files candidate GitHub issues via `gh issue create` (rate-limited ' +\n 'to 5 per run, deduped against open issues). Never auto-merges. Replaces the deleted ' +\n 'self-development engine (#2402).';\n\nconst TOOL_INPUT_SCHEMA = {\n lookbackDays: z\n .number()\n .int()\n .min(1)\n .max(90)\n .optional()\n .describe('Lookback window for outcome data, in days. Default 7.'),\n fileIssues: z\n .boolean()\n .optional()\n .describe(\n 'When true, file candidate issues for crossed thresholds (default false — return signals only)'\n ),\n minSampleSize: z\n .number()\n .int()\n .min(1)\n .max(1000)\n .optional()\n .describe('Minimum sample size before a CLI/category signal fires (default 5).'),\n fitnessFloor: z\n .number()\n .int()\n .min(0)\n .max(100)\n .optional()\n .describe('Fitness score below this threshold triggers a tech-debt signal (default 90).'),\n selfEvalReportPath: z\n .string()\n .optional()\n .describe(\n 'Optional path to a self-eval JSON report. High-confidence unanimous ' +\n 'deprecate/refactor findings surface as tech-debt signals (#3224).'\n ),\n};\n\n/** @category MCP */\nexport function registerImprovementReviewTool(\n server: McpServer,\n deps: ImprovementReviewDeps\n): void {\n const logger = deps.logger ?? createLogger({ tool: 'improvement_review' });\n const secureHandler = createSecureHandler(reviewHandler, {\n toolName: 'improvement_review',\n rateLimiter: deps.rateLimiter,\n logger,\n });\n const guardedHandler = withPrerequisite('improvement_review', secureHandler);\n const timeoutMs = getToolTimeout('improvement_review', deps.security);\n const wrappedHandler = wrapToolWithTimeout('improvement_review', guardedHandler, {\n timeoutMs,\n logger,\n });\n server.registerTool(\n 'improvement_review',\n {\n description,\n inputSchema: TOOL_INPUT_SCHEMA,\n annotations: getToolAnnotations('improvement_review'),\n },\n toSdkCallback(wrappedHandler)\n );\n logger.info('Registered improvement_review tool');\n}\n","/**\n * nexus-agents/mcp - Tool Prerequisite Gates\n *\n * Blocks sensitive MCP tools from running unless a **world-state\n * precondition** holds at call time (Issue #2652, Epic B).\n *\n * DESIGN — predicate, not session-ordering. A prerequisite is a predicate\n * over observable world state (is `gh` installed? is the data dir\n * writable?), evaluated on every invocation. It is NOT \"tool A must have\n * been called before tool B\" — MCP `tools/call` invocations are\n * independent, and a session-ordering gate is satisfied by an LLM calling\n * the prior tool pointlessly without making the precondition true. If a\n * requirement can only be expressed as \"call X first,\" it is not a\n * prerequisite — it is the tool's own internal responsibility (e.g.\n * untrusted-input trust-tier classification stays inside `issue_triage`\n * per `.rules/untrusted-input.md`, it is not gated here).\n *\n * Fail-closed: a predicate that throws blocks the tool.\n *\n * @module mcp/middleware/tool-prerequisites\n * @see Issue #2652\n */\n\nimport { execFile } from 'node:child_process';\nimport { access, constants } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { promisify } from 'node:util';\nimport { getErrorMessage } from '../../core/index.js';\nimport { getNexusDataDir } from '../../config/nexus-data-dir.js';\nimport { toolStructuredError, type ToolResult } from '../tools/tool-result.js';\nimport type { ContextAwareToolHandler, ToolHandler } from './middleware-chain.js';\n\nconst execFileAsync = promisify(execFile);\n\n/** Outcome of evaluating a prerequisite predicate. */\nexport interface PrerequisiteResult {\n ok: boolean;\n /** When `!ok`: what would make the predicate pass. Surfaced to the caller. */\n remediation?: string;\n}\n\n/** A world-state precondition a guarded tool requires at call time. */\nexport interface ToolPrerequisite {\n /** Stable identifier, e.g. `data-dir-writable`. */\n name: string;\n /** Why the tool needs it — for `.rules/tool-prerequisites.md` + the block envelope. */\n rationale: string;\n /** World-state predicate. MUST be cheap and side-effect-free. */\n check: () => Promise<PrerequisiteResult> | PrerequisiteResult;\n}\n\n// ============================================================================\n// Predicates\n// ============================================================================\n\n/** The `gh` CLI is on PATH — required by tools that file/read GitHub state. */\nasync function ghCliAvailable(): Promise<PrerequisiteResult> {\n try {\n await execFileAsync('gh', ['--version'], { timeout: 5000 });\n return { ok: true };\n } catch (err) {\n return {\n ok: false,\n remediation: `the 'gh' CLI is not available (${getErrorMessage(err)}) — install GitHub CLI and authenticate (\\`gh auth login\\`)`,\n };\n }\n}\n\n/**\n * The runtime data directory is writable, or — if it does not exist yet —\n * creatable (its parent is writable). Memory/registry backends create the\n * dir on demand, so \"not yet created\" is not a failure; an unwritable\n * parent is.\n */\nasync function dataDirWritable(): Promise<PrerequisiteResult> {\n const dir = getNexusDataDir();\n try {\n await access(dir, constants.W_OK);\n return { ok: true };\n } catch {\n // Dir may not exist yet — backends create it on demand. Treat a\n // writable parent (creatable) as satisfying the precondition.\n try {\n await access(dirname(dir), constants.W_OK);\n return { ok: true };\n } catch (err) {\n return {\n ok: false,\n remediation: `NEXUS_DATA_DIR (${dir}) is not writable or creatable (${getErrorMessage(err)}) — fix its permissions; run \\`nexus-agents doctor\\` to diagnose`,\n };\n }\n }\n}\n\n// ============================================================================\n// Registry\n// ============================================================================\n\n/**\n * Tools guarded by a call-time prerequisite. Keep this in sync with\n * `.rules/tool-prerequisites.md` — the `check:tool-prerequisites` CI gate\n * verifies every non-read-only tool is either listed here or in\n * `NO_PREREQUISITE` with a reason.\n */\nexport const TOOL_PREREQUISITES: Record<string, ToolPrerequisite> = {\n improvement_review: {\n name: 'gh-cli-available',\n rationale:\n \"improvement_review's fileIssues mode shells out to `gh` to file candidate issues; without it the write path fails mid-operation\",\n check: ghCliAvailable,\n },\n memory_write: {\n name: 'data-dir-writable',\n rationale:\n 'memory_write persists entries under NEXUS_DATA_DIR — an unwritable data dir fails the write confusingly mid-operation',\n check: dataDirWritable,\n },\n registry_import: {\n name: 'data-dir-writable',\n rationale:\n 'registry_import persists a draft registry entry under NEXUS_DATA_DIR when not in dryRun mode',\n check: dataDirWritable,\n },\n};\n\n/**\n * Non-read-only tools that deliberately have NO call-time prerequisite,\n * with the reason. The `check:tool-prerequisites` gate requires every\n * non-read-only tool to appear here or in `TOOL_PREREQUISITES`, so a newly\n * added sensitive tool can't ship ungated by omission.\n */\nexport const NO_PREREQUISITE: Record<string, string> = {\n orchestrate: 'orchestration is self-contained; sub-tool calls carry their own gates',\n create_expert: 'in-memory expert creation; no external precondition',\n execute_expert:\n 'adapter availability is handled by the resilient-adapter circuit breaker, not a pre-gate',\n run_workflow: 'workflow execution is self-contained; step tools carry their own gates',\n run_graph_workflow: 'graph execution is self-contained; node tools carry their own gates',\n run_pipeline: 'pipeline execution is self-contained; stage tools carry their own gates',\n run_dev_pipeline: 'pipeline execution is self-contained; stage tools carry their own gates',\n execute_spec: 'spec execution is self-contained; stage tools carry their own gates',\n consensus_vote: 'voter-CLI availability is handled by per-voter fallback, not a pre-gate',\n ci_health_check:\n 'reads upstream CI status + appends a telemetry event (#3530); no world-state precondition to gate',\n supply_chain_tradeoff_panel: 'wraps consensus_vote; same per-voter fallback applies',\n pr_review: 'wraps consensus_vote; same per-voter fallback applies',\n research_add:\n 'arXiv fetch failures surface as a transient envelope from the handler; no useful pre-gate',\n research_add_source:\n 'GitHub metadata fetch is best-effort with graceful fallback; no useful pre-gate',\n research_catalog_review: 'operates on local catalog state already loaded by the handler',\n issue_triage:\n 'untrusted-input safety (trust-tier classification, Rule of Two) is internal-handler logic per .rules/untrusted-input.md — not a call-time world-state predicate',\n cancel_job:\n 'reads + writes the local sidecar file only; cancel-after-complete is an idempotent no-op (first-wins) so misuse is bounded — no pre-gate needed',\n run_quality_gate:\n 'stateless QA gate over the given projectDir; a missing toolchain (tsc/eslint/vitest/build) surfaces as a check failure in the verdict, not a call-time world-state precondition — no pre-gate needed',\n};\n\n// ============================================================================\n// Middleware\n// ============================================================================\n\n/** Either MCP handler shape, both structurally callable with `(args, ctx?)`. */\ntype AnyToolHandler = ContextAwareToolHandler | ToolHandler;\n/** Concrete callable accepting an optional context — what the gate produces. */\ntype GuardedHandler = (args: unknown, ctx?: unknown) => Promise<ToolResult>;\n\n/**\n * Wrap `handler` so `prereq` is evaluated before it runs. A failing or\n * throwing predicate returns a structured `permission` error envelope\n * (#2649) carrying the failed prerequisite + a remediation hint in\n * `detail` — so the caller knows how to recover, not just that it was\n * blocked. Exported for testing; production code uses `withPrerequisite`.\n */\nexport function applyPrerequisite(\n toolName: string,\n prereq: ToolPrerequisite,\n handler: AnyToolHandler\n): GuardedHandler {\n return async (args: unknown, ctx?: unknown): Promise<ToolResult> => {\n let result: PrerequisiteResult;\n try {\n result = await prereq.check();\n } catch (err) {\n // Fail closed — a predicate that throws blocks the tool.\n result = { ok: false, remediation: `prerequisite check threw: ${getErrorMessage(err)}` };\n }\n if (!result.ok) {\n return toolStructuredError({\n errorCategory: 'permission',\n message: `${toolName} blocked: prerequisite '${prereq.name}' not satisfied`,\n detail: {\n failedPrerequisite: prereq.name,\n rationale: prereq.rationale,\n remediation: result.remediation ?? 'see .rules/tool-prerequisites.md',\n },\n });\n }\n return (handler as GuardedHandler)(args, ctx);\n };\n}\n\n/**\n * Wrap a handler so its tool's prerequisite (if any) is evaluated before\n * the handler runs. Tools with no entry in `TOOL_PREREQUISITES` pass\n * through untouched.\n */\nexport function withPrerequisite(toolName: string, handler: AnyToolHandler): AnyToolHandler {\n const prereq = TOOL_PREREQUISITES[toolName];\n if (prereq === undefined) return handler;\n return applyPrerequisite(toolName, prereq, handler);\n}\n","/**\n * CLI Orchestration Fitness Score — real filesystem analysis.\n * Penalizes duplicate paths, hidden behavior, non-determinism, poor\n * observability, config sprawl, cross-layer coupling. Rewards canonical\n * paths, determinism, telemetry, CLI ergonomics, governance.\n * @module governance/fitness-score\n */\n\n/* eslint-disable max-lines -- cohesive fitness calculator (governance allows 400-600) */\n\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createLogger, type ILogger } from '../core/index.js';\n\n/** Find package root by walking up from current dir to find package.json with our name */\nfunction findPkgRoot(): string {\n let dir = import.meta.dirname;\n for (let i = 0; i < 10; i++) {\n const pkgPath = join(dir, 'package.json');\n if (existsSync(pkgPath)) {\n const content = readFileSync(pkgPath, 'utf-8');\n if (content.includes('\"nexus-agents\"')) return dir;\n }\n dir = join(dir, '..');\n }\n return join(import.meta.dirname, '../..');\n}\n\nconst PKG_ROOT = findPkgRoot();\nconst SRC_ROOT = join(PKG_ROOT, 'src');\nconst REPO_ROOT = join(PKG_ROOT, '../..');\nconst DOCS_ROOT = join(REPO_ROOT, 'docs');\n\nconst DETERMINISM_EXCLUDES: RegExp[] = [\n /\\.test\\.ts$/,\n /\\.spec\\.ts$/,\n /random-provider\\.ts$/,\n /time-provider\\.ts$/,\n];\n\n// =========================================================================\n// Filesystem utility methods (inlined from scripts/fitness-utils.ts)\n// =========================================================================\n\nfunction countFiles(dir: string, pattern: RegExp): number {\n if (!existsSync(dir)) return 0;\n let count = 0;\n for (const entry of readdirSync(dir)) {\n const fullPath = join(dir, entry);\n const stat = statSync(fullPath);\n if (stat.isDirectory() && !entry.startsWith('.')) {\n count += countFiles(fullPath, pattern);\n } else if (pattern.test(entry)) {\n count++;\n }\n }\n return count;\n}\n\nfunction fileContains(filePath: string, pattern: RegExp): boolean {\n if (!existsSync(filePath)) return false;\n return pattern.test(readFileSync(filePath, 'utf-8'));\n}\n\nfunction isExcluded(entry: string, excludePatterns?: RegExp[]): boolean {\n return excludePatterns?.some((p) => p.test(entry)) ?? false;\n}\n\nfunction countMatchesInFile(fullPath: string, contentPattern: RegExp): number {\n const matches = readFileSync(fullPath, 'utf-8').match(contentPattern);\n return matches?.length ?? 0;\n}\n\nfunction countPatternInDir(\n dir: string,\n filePattern: RegExp,\n contentPattern: RegExp,\n excludePatterns?: RegExp[]\n): number {\n if (!existsSync(dir)) return 0;\n let count = 0;\n for (const entry of readdirSync(dir)) {\n const fullPath = join(dir, entry);\n const stat = statSync(fullPath);\n if (stat.isDirectory() && !entry.startsWith('.') && entry !== 'node_modules') {\n count += countPatternInDir(fullPath, filePattern, contentPattern, excludePatterns);\n } else if (filePattern.test(entry) && !isExcluded(entry, excludePatterns)) {\n count += countMatchesInFile(fullPath, contentPattern);\n }\n }\n return count;\n}\n\n// =========================================================================\n// Public types\n// =========================================================================\n\n/**\n * Individual fitness dimension scores.\n */\nexport interface FitnessDimensions {\n /** Penalty: duplicate paths to same workflow (0-20, higher = better) */\n readonly canonicalPaths: number;\n /** Penalty: hidden/magic behavior (0-15, higher = better) */\n readonly explicitBehavior: number;\n /** Reward: deterministic execution (0-15, higher = better) */\n readonly determinism: number;\n /** Reward: observability coverage (0-15, higher = better) */\n readonly observability: number;\n /** Penalty: config surface area (0-10, higher = better) */\n readonly configSimplicity: number;\n /** Penalty: cross-layer coupling (0-10, higher = better) */\n readonly layerSeparation: number;\n /** Reward: CLI ergonomics (0-10, higher = better) */\n readonly operatorErgonomics: number;\n /** Reward: governance injection (0-5, higher = better) */\n readonly governanceIntegration: number;\n}\n\n/**\n * Detailed fitness audit result.\n */\nexport interface FitnessAudit {\n /** Overall score (0-100) */\n readonly score: number;\n /** Individual dimension scores */\n readonly dimensions: FitnessDimensions;\n /** Specific findings */\n readonly findings: readonly FitnessFinding[];\n /** Timestamp of audit */\n readonly timestamp: string;\n /** Version/commit reference */\n readonly version: string;\n}\n\n/**\n * Individual finding from audit.\n */\nexport interface FitnessFinding {\n /** Dimension affected */\n readonly dimension: keyof FitnessDimensions;\n /** Issue severity: 'info' | 'warning' | 'critical' */\n readonly severity: 'info' | 'warning' | 'critical';\n /** Description */\n readonly description: string;\n /** Points deducted */\n readonly pointsDeducted: number;\n /** Location in code (optional) */\n readonly location?: string;\n /** Suggested fix (optional) */\n readonly suggestion?: string;\n}\n\n/**\n * Fitness check definition.\n */\ninterface FitnessCheck {\n readonly dimension: keyof FitnessDimensions;\n readonly maxPoints: number;\n readonly name: string;\n readonly check: () => FitnessCheckResult;\n}\n\n/**\n * Result of a single fitness check.\n */\ninterface FitnessCheckResult {\n readonly score: number;\n readonly findings: FitnessFinding[];\n}\n\n/** Clamp score to [0, max]. */\nfunction clamp(score: number, max: number): number {\n return Math.max(0, Math.min(max, score));\n}\n\n/**\n * CLI Orchestration Fitness Score calculator.\n */\nexport class FitnessScoreCalculator {\n private readonly logger: ILogger;\n private readonly checks: FitnessCheck[] = [];\n\n constructor(logger?: ILogger) {\n this.logger = logger ?? createLogger({ component: 'FitnessScoreCalculator' });\n this.registerDefaultChecks();\n }\n\n /** Register default fitness checks. */\n private registerDefaultChecks(): void {\n const reg = (\n dimension: keyof FitnessDimensions,\n maxPoints: number,\n name: string,\n check: () => FitnessCheckResult\n ): void => {\n this.checks.push({ dimension, maxPoints, name, check });\n };\n reg('canonicalPaths', 20, 'Canonical Paths', () => this.checkCanonicalPaths());\n reg('explicitBehavior', 15, 'Explicit Behavior', () => this.checkExplicitBehavior());\n reg('determinism', 15, 'Determinism', () => this.checkDeterminism());\n reg('observability', 15, 'Observability', () => this.checkObservability());\n reg('configSimplicity', 10, 'Config Simplicity', () => this.checkConfigSimplicity());\n reg('layerSeparation', 10, 'Layer Separation', () => this.checkLayerSeparation());\n reg('operatorErgonomics', 10, 'Operator Ergonomics', () => this.checkOperatorErgonomics());\n reg('governanceIntegration', 5, 'Governance Integration', () =>\n this.checkGovernanceIntegration()\n );\n }\n\n /** Run full fitness audit. */\n audit(version: string): FitnessAudit {\n const findings: FitnessFinding[] = [];\n const dimensions: Record<string, number> = {};\n\n // #2716 — the audit's existsSync checks look at SRC_ROOT-relative paths\n // (cli-adapters/composite-router.ts, cli/doctor.ts, etc). When run from\n // an `npm install -g nexus-agents` copy, SRC_ROOT points at the installed\n // package's `src/` which only contains workflow templates — not the full\n // source tree. Result: every existsSync returns false and the audit\n // emits a parade of fictional \"missing\" findings against a healthy\n // source tree. (`npx nexus-agents fitness-audit` from a repo root hits\n // this path because npx resolves to the GLOBAL bin, not the local\n // workspace bundle.) Bail with a clear single-finding result instead.\n const cliAdaptersDir = join(SRC_ROOT, 'cli-adapters');\n if (!existsSync(cliAdaptersDir)) {\n return this.notSourceRepoResult(version);\n }\n\n for (const check of this.checks) {\n this.logger.debug(`Running fitness check: ${check.name}`);\n const result = check.check();\n dimensions[check.dimension] = result.score;\n findings.push(...result.findings);\n }\n\n const score = Object.values(dimensions).reduce((sum, val) => sum + val, 0);\n this.logger.info('Fitness audit complete', { score, version });\n\n // Build a strictly-typed FitnessDimensions instead of `as unknown as` cast\n // (#1913 Class G). If a check skipped a dimension it defaults to 0,\n // making it explicit rather than UB.\n const safeDim = (k: keyof FitnessDimensions): number => dimensions[k] ?? 0;\n const typedDimensions: FitnessDimensions = {\n canonicalPaths: safeDim('canonicalPaths'),\n explicitBehavior: safeDim('explicitBehavior'),\n determinism: safeDim('determinism'),\n observability: safeDim('observability'),\n configSimplicity: safeDim('configSimplicity'),\n layerSeparation: safeDim('layerSeparation'),\n operatorErgonomics: safeDim('operatorErgonomics'),\n governanceIntegration: safeDim('governanceIntegration'),\n };\n\n return {\n score,\n dimensions: typedDimensions,\n findings,\n timestamp: new Date().toISOString(),\n version,\n };\n }\n\n /**\n * Return when the runtime SRC_ROOT doesn't look like the nexus-agents\n * source tree (#2716). One finding, score 0 — distinct from \"the source\n * tree is broken\" because every existsSync would falsely report missing.\n */\n private notSourceRepoResult(version: string): FitnessAudit {\n const finding: FitnessFinding = {\n dimension: 'governanceIntegration',\n severity: 'info',\n description:\n 'fitness-audit must run against the nexus-agents source repo, ' +\n `but ${SRC_ROOT}/cli-adapters does not exist. You are likely ` +\n 'running the installed npm package via `npx nexus-agents`, which ' +\n 'ships only the bundled dist/. Clone the source repo and run ' +\n '`node packages/nexus-agents/dist/cli.js fitness-audit` (or invoke ' +\n '`pnpm fitness-audit` from the workspace root).',\n pointsDeducted: 0,\n };\n return {\n score: 0,\n dimensions: {\n canonicalPaths: 0,\n explicitBehavior: 0,\n determinism: 0,\n observability: 0,\n configSimplicity: 0,\n layerSeparation: 0,\n operatorErgonomics: 0,\n governanceIntegration: 0,\n },\n findings: [finding],\n timestamp: new Date().toISOString(),\n version,\n };\n }\n\n // =========================================================================\n // Individual Checks — real filesystem analysis\n // =========================================================================\n\n /**\n * Check canonical paths: penalize duplicate router implementations.\n *\n * The current minimum is 6 (raised from 5 in #2063 after an audit):\n * 1. composite-router — pipeline orchestrator\n * 2. budget-router — budget/cost filtering\n * 3. zero-router — hard-constraint exclusion\n * 4. preference-router — user/task preference application\n * 5. topsis-router — TOPSIS multi-criteria scoring\n * 6. agreement-cascade-router — agreement-based cascade retry\n *\n * Each stage is distinct per CLAUDE.md's documented pipeline:\n * Task → BudgetRouter → ZeroRouter → PreferenceRouter → TopsisRouter → Agreement → Model\n */\n private checkCanonicalPaths(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 20;\n\n const routerCount = countFiles(join(SRC_ROOT, 'cli-adapters'), /router\\.ts$/);\n const ROUTER_COUNT_THRESHOLD = 6;\n if (routerCount > ROUTER_COUNT_THRESHOLD) {\n const excess = routerCount - ROUTER_COUNT_THRESHOLD;\n const deduction = Math.min(5, excess);\n score -= deduction;\n findings.push(\n this.finding(\n 'canonicalPaths',\n 'warning',\n `${String(routerCount)} router implementations found (target: <=${String(ROUTER_COUNT_THRESHOLD)})`,\n deduction,\n 'Consolidate duplicate routers into CompositeRouter'\n )\n );\n }\n\n if (existsSync(join(SRC_ROOT, 'cli-adapters/composite-router.ts'))) {\n score += 2;\n } else {\n score -= 3;\n findings.push(\n this.finding(\n 'canonicalPaths',\n 'critical',\n 'CompositeRouter missing — no unified routing entry point',\n 3\n )\n );\n }\n\n score = this.checkOrchestratorInterface(score, findings);\n\n return { score: clamp(score, 20), findings };\n }\n\n /** Sub-check for IOrchestrator interface and adapter wiring. */\n private checkOrchestratorInterface(score: number, findings: FitnessFinding[]): number {\n const orchPath = join(SRC_ROOT, 'core/types/orchestrator.ts');\n if (existsSync(orchPath) && fileContains(orchPath, /interface IOrchestrator/)) {\n score += 3;\n } else {\n score -= 2;\n findings.push(\n this.finding('canonicalPaths', 'warning', 'No IOrchestrator interface in core/types', 2)\n );\n }\n\n const adapterPath = join(SRC_ROOT, 'orchestration/orchestrator-adapters.ts');\n if (existsSync(adapterPath) && fileContains(adapterPath, /TechLeadAdapter|PuppeteerAdapter/)) {\n score += 2;\n }\n\n return score;\n }\n\n /**\n * Check explicit behavior: penalize hidden/magic behavior.\n *\n * Implementation is intentionally filesystem-signal-based (no AST parse).\n * The `NEXUS_ALLOW_MOCK_ORCHESTRATION` guard and magic-routing pattern\n * grep capture the observable failure modes that historically slipped\n * past review. AST-based detection of implicit fallbacks was considered\n * but not pursued — it would significantly widen this function's\n * footprint and the filesystem signals already catch the recurring\n * regressions. Revisit only if a new class of hidden-behavior bug\n * surfaces that this grep-over-source approach can't catch.\n */\n private checkExplicitBehavior(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 15;\n\n // Check: mock orchestration requires explicit env var opt-in\n const mockGuardCount = countPatternInDir(\n SRC_ROOT,\n /\\.ts$/,\n /NEXUS_ALLOW_MOCK_ORCHESTRATION/g,\n DETERMINISM_EXCLUDES\n );\n if (mockGuardCount === 0) {\n score -= 3;\n findings.push(\n this.finding(\n 'explicitBehavior',\n 'warning',\n 'No NEXUS_ALLOW_MOCK_ORCHESTRATION guard found — mock fallback may be implicit',\n 3,\n 'Require explicit env var for mock orchestration'\n )\n );\n }\n\n // Check: magic routing patterns (delegate without explicit capability match)\n const magicRouting = countPatternInDir(\n SRC_ROOT,\n /\\.ts$/,\n /fallback.*=.*true|implicitRoute/g,\n DETERMINISM_EXCLUDES\n );\n if (magicRouting > 5) {\n const deduction = Math.min(3, Math.floor(magicRouting / 3));\n score -= deduction;\n findings.push(\n this.finding(\n 'explicitBehavior',\n 'info',\n `${String(magicRouting)} implicit fallback/routing patterns detected`,\n deduction\n )\n );\n }\n\n return { score: clamp(score, 15), findings };\n }\n\n /** Check determinism: penalize unseeded random and raw Date.now(). */\n private checkDeterminism(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 15;\n\n score = this.checkRandomDeterminism(score, findings);\n score = this.checkTimeDeterminism(score, findings);\n\n return { score: clamp(score, 15), findings };\n }\n\n /** Sub-check for Math.random() and injectable random provider. */\n private checkRandomDeterminism(score: number, findings: FitnessFinding[]): number {\n const randomCount = countPatternInDir(\n SRC_ROOT,\n /\\.ts$/,\n /Math\\.random\\(\\)/g,\n DETERMINISM_EXCLUDES\n );\n if (randomCount > 10) {\n const deduction = Math.min(5, Math.floor(randomCount / 5));\n score -= deduction;\n findings.push(\n this.finding(\n 'determinism',\n 'warning',\n `${String(randomCount)} unseeded Math.random() calls in production code`,\n deduction,\n 'Use getRandomProvider() for injectable randomness'\n )\n );\n } else if (randomCount === 0) {\n score += 2;\n }\n\n if (existsSync(join(SRC_ROOT, 'core/random-provider.ts'))) {\n score += 1;\n }\n const randomUsage = countPatternInDir(\n SRC_ROOT,\n /\\.ts$/,\n /getRandomProvider\\(\\)/g,\n DETERMINISM_EXCLUDES\n );\n if (randomUsage > 5) {\n score += 1;\n }\n\n return score;\n }\n\n /** Sub-check for Date.now() and injectable time provider. */\n private checkTimeDeterminism(score: number, findings: FitnessFinding[]): number {\n const dateNowCount = countPatternInDir(\n SRC_ROOT,\n /\\.ts$/,\n /Date\\.now\\(\\)/g,\n DETERMINISM_EXCLUDES\n );\n if (dateNowCount > 50) {\n score -= 2;\n findings.push(\n this.finding(\n 'determinism',\n 'info',\n `${String(dateNowCount)} Date.now() calls in production code`,\n 2,\n 'Use getTimeProvider() for injectable time'\n )\n );\n }\n\n if (existsSync(join(SRC_ROOT, 'core/time-provider.ts'))) {\n score += 1;\n }\n const timeUsage = countPatternInDir(\n SRC_ROOT,\n /\\.ts$/,\n /getTimeProvider\\(\\)/g,\n DETERMINISM_EXCLUDES\n );\n if (timeUsage > 10) {\n score += 1;\n }\n\n return score;\n }\n\n /** Check observability: reward tracing, logging, and audit coverage. */\n private checkObservability(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 15;\n\n if (existsSync(join(SRC_ROOT, 'observability/swarm-observer.ts'))) {\n score += 3;\n } else {\n score -= 3;\n findings.push(\n this.finding(\n 'observability',\n 'warning',\n 'No SwarmObserver found',\n 3,\n 'Add observability/swarm-observer.ts'\n )\n );\n }\n\n if (existsSync(join(SRC_ROOT, 'core/trace.ts'))) {\n score += 2;\n }\n\n const loggerCount = countPatternInDir(SRC_ROOT, /\\.ts$/, /createLogger\\(/g);\n if (loggerCount > 50) {\n score += 2;\n } else {\n findings.push(\n this.finding(\n 'observability',\n 'info',\n `Only ${String(loggerCount)} createLogger() calls (target: >50)`,\n 0\n )\n );\n }\n\n if (existsSync(join(SRC_ROOT, 'audit'))) {\n score += 2;\n }\n\n return { score: clamp(score, 15), findings };\n }\n\n /** Check config simplicity: penalize excessive schema sprawl. */\n private checkConfigSimplicity(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 10;\n\n const schemaCount = countFiles(join(SRC_ROOT, 'config'), /schema.*\\.ts$/);\n if (schemaCount > 10) {\n score -= 2;\n findings.push(\n this.finding(\n 'configSimplicity',\n 'info',\n `${String(schemaCount)} config schemas (target: <=10)`,\n 2,\n 'Consolidate related schemas'\n )\n );\n } else {\n score += 1;\n }\n\n if (existsSync(join(SRC_ROOT, 'config/config-loader.ts'))) {\n score += 2;\n }\n if (existsSync(join(SRC_ROOT, 'config/config-manager.ts'))) {\n score += 1;\n }\n\n return { score: clamp(score, 10), findings };\n }\n\n /** Check layer separation: penalize cross-layer imports. */\n private checkLayerSeparation(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 10;\n\n const adapterAgentImports = countPatternInDir(\n join(SRC_ROOT, 'adapters'),\n /\\.ts$/,\n /from ['\"]\\.\\.\\/agents\\//g\n );\n if (adapterAgentImports > 0) {\n const deduction = Math.min(5, adapterAgentImports);\n score -= deduction;\n findings.push(\n this.finding(\n 'layerSeparation',\n 'warning',\n `${String(adapterAgentImports)} adapter->agent import violations`,\n deduction,\n 'Adapters should not import from agents layer'\n )\n );\n } else {\n score += 2;\n }\n\n const coreMcpImports = countPatternInDir(\n join(SRC_ROOT, 'core'),\n /\\.ts$/,\n /from ['\"]\\.\\.\\/mcp\\//g\n );\n if (coreMcpImports > 0) {\n const deduction = Math.min(3, coreMcpImports);\n score -= deduction;\n findings.push(\n this.finding(\n 'layerSeparation',\n 'critical',\n `${String(coreMcpImports)} core->MCP import violations`,\n deduction,\n 'Core must not depend on MCP layer'\n )\n );\n } else {\n score += 1;\n }\n\n return { score: clamp(score, 10), findings };\n }\n\n /** Check operator ergonomics: reward rich CLI commands. */\n private checkOperatorErgonomics(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 10;\n\n const commandCount = countFiles(join(SRC_ROOT, 'cli'), /\\.ts$/);\n if (commandCount >= 20) {\n score += 3;\n } else {\n findings.push(\n this.finding(\n 'operatorErgonomics',\n 'info',\n `${String(commandCount)} CLI commands (target: >=20)`,\n 0\n )\n );\n }\n\n score = this.checkCliCommands(score, findings);\n\n return { score: clamp(score, 10), findings };\n }\n\n /** Sub-check for essential CLI commands (doctor, setup, demo, config). */\n private checkCliCommands(score: number, findings: FitnessFinding[]): number {\n const commands: Array<[string, string, number]> = [\n ['cli/doctor.ts', 'Doctor command', 2],\n ['cli/setup-command.ts', 'Setup wizard', 2],\n ['cli/demo-command.ts', 'Demo command', 1],\n ['cli/config-command.ts', 'Config command', 1],\n ];\n\n for (const [path, name, bonus] of commands) {\n if (existsSync(join(SRC_ROOT, path))) {\n score += bonus;\n } else {\n findings.push(this.finding('operatorErgonomics', 'info', `Missing ${name} (${path})`, 0));\n }\n }\n\n return score;\n }\n\n /** Check governance integration: policy firewall, rate limiter, docs. */\n private checkGovernanceIntegration(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 5;\n\n score = this.checkGovernanceDocs(score, findings);\n score = this.checkGovernanceInfra(score, findings);\n\n return { score: clamp(score, 5), findings };\n }\n\n /** Sub-check for governance documentation artifacts. */\n private checkGovernanceDocs(score: number, findings: FitnessFinding[]): number {\n if (!existsSync(join(REPO_ROOT, 'CLAUDE.md'))) {\n score -= 3;\n findings.push(\n this.finding('governanceIntegration', 'critical', 'No CLAUDE.md governance document', 3)\n );\n } else {\n score += 1;\n }\n\n if (existsSync(join(DOCS_ROOT, 'architecture/wiring-graph.json'))) {\n score += 1;\n }\n\n if (existsSync(join(DOCS_ROOT, 'adr'))) {\n score += 1;\n } else {\n findings.push(this.finding('governanceIntegration', 'info', 'No ADR directory', 0));\n }\n\n return score;\n }\n\n /** Sub-check for governance runtime infrastructure. */\n private checkGovernanceInfra(score: number, findings: FitnessFinding[]): number {\n const hasPolicyFirewall =\n countPatternInDir(join(SRC_ROOT, 'security'), /\\.ts$/, /PolicyGate|policyFirewall/g) > 0;\n if (hasPolicyFirewall) {\n score += 1;\n } else {\n findings.push(\n this.finding(\n 'governanceIntegration',\n 'warning',\n 'No policy firewall detected in security layer',\n 0\n )\n );\n }\n\n const hasRateLimiter = countPatternInDir(SRC_ROOT, /\\.ts$/, /RateLimiter|rateLimiter/g) > 0;\n if (hasRateLimiter) {\n score += 1;\n }\n\n return score;\n }\n\n /** Helper to create a FitnessFinding with defaults. */\n private finding(\n dimension: keyof FitnessDimensions,\n severity: FitnessFinding['severity'],\n description: string,\n pointsDeducted: number,\n suggestion?: string\n ): FitnessFinding {\n const base: FitnessFinding = { dimension, severity, description, pointsDeducted };\n if (suggestion !== undefined) {\n return { ...base, suggestion };\n }\n return base;\n }\n}\n\n/**\n * Create a fitness score calculator.\n */\nexport function createFitnessScoreCalculator(logger?: ILogger): FitnessScoreCalculator {\n return new FitnessScoreCalculator(logger);\n}\n\n/**\n * Quick function to get current fitness score.\n */\nexport function calculateFitnessScore(version: string): FitnessAudit {\n const calculator = createFitnessScoreCalculator();\n return calculator.audit(version);\n}\n","/**\n * improvement_review → pipeline-bus signal emitter (#3147, epic #3143 P2).\n *\n * Emits `signal.fitness_declined` onto the typed pipeline event bus when the\n * fitness audit score falls below the governance floor. Runs in the\n * `improvement_review` MCP tool (server context), so the live shadow TuneStage\n * consumes it. Lives at the MCP layer to keep `governance/fitness-score`\n * decoupled from the pipeline bus, preserving the `A = observability /\n * B = messaging` boundary adopted for #3289 (scope Option 2).\n *\n * @module mcp/tools/improvement-review-signals\n */\n\nimport { getErrorMessage, getTimeProvider } from '../../core/index.js';\nimport type { ILogger } from '../../core/index.js';\nimport type { FitnessAudit } from '../../governance/fitness-score.js';\nimport type { IEventBus } from '../../pipeline/event-types.js';\n\n/** The dimension of the finding that deducted the most points, if any. */\nfunction worstDimension(audit: FitnessAudit): string | undefined {\n let worst: { dimension: string; pointsDeducted: number } | undefined;\n for (const finding of audit.findings) {\n if (worst === undefined || finding.pointsDeducted > worst.pointsDeducted) {\n worst = { dimension: finding.dimension, pointsDeducted: finding.pointsDeducted };\n }\n }\n return worst?.dimension;\n}\n\n/**\n * Emit `signal.fitness_declined` onto `bus` when `audit.score < fitnessFloor`.\n * No-op at or above floor. Emission errors are swallowed and logged — signalling\n * must never break the improvement-review path.\n */\nexport function emitFitnessDeclinedSignal(\n audit: FitnessAudit,\n fitnessFloor: number,\n bus: IEventBus,\n logger: ILogger\n): void {\n if (audit.score >= fitnessFloor) return;\n try {\n const dimension = worstDimension(audit);\n bus.emit({\n type: 'signal.fitness_declined',\n timestamp: getTimeProvider().now(),\n score: audit.score,\n floor: fitnessFloor,\n ...(dimension !== undefined ? { dimension } : {}),\n });\n } catch (error) {\n logger.warn('Failed to emit signal.fitness_declined', { error: getErrorMessage(error) });\n }\n}\n","/**\n * Improvement-signal → remediation-task bridge (#3540, capability-loop increment 1).\n *\n * The \"safe plumbing\" half of the capability loop: turn the observability\n * signals `improvement_review` already detects (fitness decline, CLI-floor,\n * failure-category concentration, consensus rejection, self-eval findings) into\n * structured remediation {@link PipelineTask}s, surfaced for human review.\n *\n * SUGGEST-ONLY by construction: this is a pure mapping. It executes nothing,\n * files nothing, and auto-invokes no pipeline — the safety-critical auto-invoke\n * gate is a deliberately separate, later increment (still owner-gated). A\n * reviewer (or a future human-gated path) decides whether to route a task\n * through the dev-pipeline.\n *\n * @module mcp/tools/improvement-remediation\n */\n\nimport type { PipelineTask, PipelineRole } from '../../pipeline/dev-pipeline.js';\nimport type { ImprovementSignal, SignalCategory } from './improvement-review.js';\n\n/**\n * Which pipeline role should own a remediation, by signal category. The\n * dev-pipeline re-plans from research anyway, so this is the seed owner, not a\n * final assignment.\n */\nconst ROLE_BY_CATEGORY: Readonly<Record<SignalCategory, PipelineRole>> = {\n security: 'security',\n bug: 'coder',\n 'tech-debt': 'coder',\n routing: 'researcher',\n consensus: 'researcher',\n};\n\n/** Stable, dedup-friendly task id for a signal (mirrors the signalKey). */\nexport function remediationTaskId(signal: ImprovementSignal): string {\n return `improvement-${signal.signalKey}`;\n}\n\n/** Maps one improvement signal to a suggest-only remediation task. */\nexport function improvementSignalToTask(signal: ImprovementSignal): PipelineTask {\n return {\n id: remediationTaskId(signal),\n title: signal.title,\n description:\n `Auto-suggested remediation from improvement_review (#3540 — SUGGEST-ONLY, nothing executed). ` +\n `Category: ${signal.category}; severity: ${signal.severity}.\\n\\n${signal.body}\\n\\n` +\n `If accepted, route this through the dev-pipeline (research → plan → vote → implement → QA → ` +\n `security gate). Auto-invocation is a separate, owner-gated step.`,\n assignedTo: ROLE_BY_CATEGORY[signal.category],\n status: 'pending',\n };\n}\n\n/**\n * Maps detected improvement signals to remediation tasks for review. Preserves\n * input order (signals arrive severity-sorted) and dedups by task id against\n * `existingTaskIds` when provided.\n */\nexport function improvementSignalsToTasks(\n signals: readonly ImprovementSignal[],\n existingTaskIds?: ReadonlySet<string>\n): PipelineTask[] {\n const tasks: PipelineTask[] = [];\n for (const signal of signals) {\n const task = improvementSignalToTask(signal);\n if (existingTaskIds?.has(task.id) === true) continue;\n tasks.push(task);\n }\n return tasks;\n}\n"],"mappings":"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","names":["execFile","promisify","description","execFileAsync","promisify","execFile"]}
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
} from "./chunk-CH7QIDHQ.js";
|
|
41
41
|
|
|
42
42
|
// src/version.ts
|
|
43
|
-
var VERSION = true ? "2.
|
|
43
|
+
var VERSION = true ? "2.124.0" : "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-G6IWNPE2.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-D52WH4UW.js.map
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
} from "./chunk-YXRDBU3Y.js";
|
|
49
49
|
import {
|
|
50
50
|
withPrerequisite
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-35YWAUJX.js";
|
|
52
52
|
import {
|
|
53
53
|
NOOP_NOTIFIER,
|
|
54
54
|
RateLimiter,
|
|
@@ -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-D52WH4UW.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-JLXZPSMU.js.map
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
checkSqlite,
|
|
9
9
|
defaultConfig,
|
|
10
10
|
initDataDirectories
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-D52WH4UW.js";
|
|
12
12
|
import {
|
|
13
13
|
probeAllClis
|
|
14
14
|
} from "./chunk-TSAEDXVB.js";
|
|
@@ -2000,4 +2000,4 @@ export {
|
|
|
2000
2000
|
setupCommand,
|
|
2001
2001
|
setupCommandAsync
|
|
2002
2002
|
};
|
|
2003
|
-
//# sourceMappingURL=chunk-
|
|
2003
|
+
//# sourceMappingURL=chunk-LKWQ3AT4.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-LKWQ3AT4.js";
|
|
28
28
|
import "./chunk-PBMXKQCK.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-JLXZPSMU.js";
|
|
148
148
|
import "./chunk-3ACDP4E6.js";
|
|
149
149
|
import {
|
|
150
150
|
CATEGORY_DISPLAY_NAMES,
|
|
@@ -184,7 +184,7 @@ import {
|
|
|
184
184
|
createFitnessScoreCalculator,
|
|
185
185
|
registerImprovementReviewTool,
|
|
186
186
|
runImprovementReview
|
|
187
|
-
} from "./chunk-
|
|
187
|
+
} from "./chunk-35YWAUJX.js";
|
|
188
188
|
import {
|
|
189
189
|
createDefaultPolicyFirewall
|
|
190
190
|
} from "./chunk-QD2C3CBD.js";
|
|
@@ -243,7 +243,7 @@ import {
|
|
|
243
243
|
loadConfig,
|
|
244
244
|
runDoctor,
|
|
245
245
|
validateNexusEnv
|
|
246
|
-
} from "./chunk-
|
|
246
|
+
} from "./chunk-D52WH4UW.js";
|
|
247
247
|
import "./chunk-NUBSJGQZ.js";
|
|
248
248
|
import {
|
|
249
249
|
capitalize,
|
|
@@ -17605,7 +17605,7 @@ function startImprovementReviewScheduler(options) {
|
|
|
17605
17605
|
let running = false;
|
|
17606
17606
|
const runOnce = async () => {
|
|
17607
17607
|
try {
|
|
17608
|
-
const { runImprovementReview: runImprovementReview2, ImprovementReviewInputSchema: ImprovementReviewInputSchema2 } = await import("./improvement-review-
|
|
17608
|
+
const { runImprovementReview: runImprovementReview2, ImprovementReviewInputSchema: ImprovementReviewInputSchema2 } = await import("./improvement-review-Z4ETNJWO.js");
|
|
17609
17609
|
const input = ImprovementReviewInputSchema2.parse({ fileIssues });
|
|
17610
17610
|
const result = await runImprovementReview2(input, { logger: logger19 });
|
|
17611
17611
|
logger19.info("Scheduled improvement_review complete", {
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
loadSelfEvalSignals,
|
|
10
10
|
registerImprovementReviewTool,
|
|
11
11
|
runImprovementReview
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-35YWAUJX.js";
|
|
13
13
|
import "./chunk-QD2C3CBD.js";
|
|
14
14
|
import "./chunk-2UXRYB7S.js";
|
|
15
15
|
import "./chunk-CH7QIDHQ.js";
|
|
@@ -26,4 +26,4 @@ export {
|
|
|
26
26
|
registerImprovementReviewTool,
|
|
27
27
|
runImprovementReview
|
|
28
28
|
};
|
|
29
|
-
//# sourceMappingURL=improvement-review-
|
|
29
|
+
//# sourceMappingURL=improvement-review-Z4ETNJWO.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -24440,6 +24440,134 @@ interface MemoryWriteResponse {
|
|
|
24440
24440
|
*/
|
|
24441
24441
|
declare function registerMemoryWriteTool(server: McpServer, deps: MemoryWriteDeps): void;
|
|
24442
24442
|
|
|
24443
|
+
/** Agent roles used in the pipeline. */
|
|
24444
|
+
type PipelineRole = 'researcher' | 'architect' | 'pm' | 'coder' | 'qa' | 'security';
|
|
24445
|
+
/** A task decomposed by the PM, potentially with conditional approval requirements. */
|
|
24446
|
+
interface PipelineTask {
|
|
24447
|
+
readonly id: string;
|
|
24448
|
+
readonly title: string;
|
|
24449
|
+
readonly description: string;
|
|
24450
|
+
readonly assignedTo: PipelineRole;
|
|
24451
|
+
readonly status: 'pending' | 'in_progress' | 'review' | 'done' | 'rejected';
|
|
24452
|
+
readonly feedback?: string;
|
|
24453
|
+
/** Implementation text from the code expert (surfaced for harness use). */
|
|
24454
|
+
readonly implementation?: string;
|
|
24455
|
+
/** Conditions required for task completion (from conditional_go vote). */
|
|
24456
|
+
readonly conditions?: readonly string[] | undefined;
|
|
24457
|
+
/** Caveats/warnings associated with the task (from conditional_go vote). */
|
|
24458
|
+
readonly caveats?: readonly string[] | undefined;
|
|
24459
|
+
}
|
|
24460
|
+
/** Vote result from consensus — discriminated union with conditional approval support. */
|
|
24461
|
+
type VoteResult = {
|
|
24462
|
+
readonly kind: 'approved';
|
|
24463
|
+
readonly approvalPercentage: number;
|
|
24464
|
+
} | {
|
|
24465
|
+
readonly kind: 'rejected';
|
|
24466
|
+
readonly feedback: string;
|
|
24467
|
+
readonly approvalPercentage: number;
|
|
24468
|
+
} | {
|
|
24469
|
+
readonly kind: 'conditional_go';
|
|
24470
|
+
readonly conditions: readonly string[];
|
|
24471
|
+
readonly caveats: readonly string[];
|
|
24472
|
+
readonly approvalPercentage: number;
|
|
24473
|
+
};
|
|
24474
|
+
/** QA review result. */
|
|
24475
|
+
interface QaReviewResult {
|
|
24476
|
+
readonly verdict: 'pass' | 'needs_work' | 'reject';
|
|
24477
|
+
readonly feedback: string;
|
|
24478
|
+
readonly issues: readonly string[];
|
|
24479
|
+
}
|
|
24480
|
+
/** Overall pipeline result. */
|
|
24481
|
+
interface DevPipelineResult {
|
|
24482
|
+
readonly completed: boolean;
|
|
24483
|
+
readonly plan: string;
|
|
24484
|
+
readonly tasks: readonly PipelineTask[];
|
|
24485
|
+
readonly voteIterations: number;
|
|
24486
|
+
readonly qaIterations: number;
|
|
24487
|
+
readonly securityPassed: boolean;
|
|
24488
|
+
}
|
|
24489
|
+
/** Pluggable stage implementations — inject real or mock agents. */
|
|
24490
|
+
interface DevPipelineStages {
|
|
24491
|
+
/** Research expert gathers context for the task. */
|
|
24492
|
+
research(task: string): Promise<string>;
|
|
24493
|
+
/** Architect creates a plan from research + task. */
|
|
24494
|
+
plan(task: string, research: string, priorFeedback?: string): Promise<string>;
|
|
24495
|
+
/**
|
|
24496
|
+
* Consensus vote on the plan. Returns approval + feedback. `research` is the
|
|
24497
|
+
* research-stage context, surfaced to voters so they can weigh research
|
|
24498
|
+
* maturity (#3258) — appended to the proposal as informational, untrusted
|
|
24499
|
+
* text (never as instructions).
|
|
24500
|
+
*/
|
|
24501
|
+
vote(plan: string, research: string): Promise<VoteResult>;
|
|
24502
|
+
/** PM decomposes approved plan into tasks. */
|
|
24503
|
+
decompose(plan: string): Promise<PipelineTask[]>;
|
|
24504
|
+
/** Code expert implements a task. Returns the work product. */
|
|
24505
|
+
implement(task: PipelineTask): Promise<string>;
|
|
24506
|
+
/** QA expert reviews implementation. */
|
|
24507
|
+
qaReview(task: PipelineTask, implementation: string): Promise<QaReviewResult>;
|
|
24508
|
+
/**
|
|
24509
|
+
* Local QA quality gate (typecheck/lint/tests/build) run before ship (#3356).
|
|
24510
|
+
* Optional: pipelines that don't supply it simply skip the gate. Returns
|
|
24511
|
+
* `passed` plus actionable `feedback` from the underlying `runQualityGate`
|
|
24512
|
+
* engine. Whether a red gate fails the phase is governed by the
|
|
24513
|
+
* `qualityGate` mode in {@link DevPipelineOptions}, not this method.
|
|
24514
|
+
*/
|
|
24515
|
+
qualityGate?(): Promise<{
|
|
24516
|
+
passed: boolean;
|
|
24517
|
+
feedback: string;
|
|
24518
|
+
}>;
|
|
24519
|
+
/** Security scan. Returns true if passed. */
|
|
24520
|
+
securityScan(): Promise<{
|
|
24521
|
+
passed: boolean;
|
|
24522
|
+
feedback: string;
|
|
24523
|
+
}>;
|
|
24524
|
+
}
|
|
24525
|
+
/** Pipeline execution mode. */
|
|
24526
|
+
type PipelineMode = 'autonomous' | 'harness';
|
|
24527
|
+
/**
|
|
24528
|
+
* Local quality-gate mode (#3356). Controls the pre-ship typecheck/lint/tests/build gate:
|
|
24529
|
+
* - 'off' (default): the gate is never run. Safe for repos lacking standard scripts.
|
|
24530
|
+
* - 'advisory': the gate runs and its feedback is recorded, but a red gate does
|
|
24531
|
+
* NOT fail the pipeline.
|
|
24532
|
+
* - 'blocking': a red gate fails the phase, the same way a blocking security
|
|
24533
|
+
* scan does.
|
|
24534
|
+
*/
|
|
24535
|
+
type QualityGateMode = 'off' | 'advisory' | 'blocking';
|
|
24536
|
+
/** Options for pipeline execution. */
|
|
24537
|
+
interface DevPipelineOptions {
|
|
24538
|
+
/** Session ID for checkpoint/resume. Omit for no persistence. */
|
|
24539
|
+
readonly sessionId?: string | undefined;
|
|
24540
|
+
/** When true, stop after plan+vote and return partial result (#1717). */
|
|
24541
|
+
readonly dryRun?: boolean | undefined;
|
|
24542
|
+
/**
|
|
24543
|
+
* Pipeline mode (#1704):
|
|
24544
|
+
* - 'autonomous' (default): full pipeline runs internally
|
|
24545
|
+
* - 'harness': stops after decompose, returns tasks for external implementation
|
|
24546
|
+
*/
|
|
24547
|
+
readonly mode?: PipelineMode | undefined;
|
|
24548
|
+
/**
|
|
24549
|
+
* Local pre-ship quality-gate mode (#3356). Default 'off' so the pipeline
|
|
24550
|
+
* never wedges repos that lack standard build/test scripts. See
|
|
24551
|
+
* {@link QualityGateMode}. Requires `stages.qualityGate` to be supplied;
|
|
24552
|
+
* if the stage is absent the gate is skipped regardless of mode.
|
|
24553
|
+
*/
|
|
24554
|
+
readonly qualityGate?: QualityGateMode | undefined;
|
|
24555
|
+
/** Optional BeliefMemory for hindsight updates after plan outcomes (#1720). */
|
|
24556
|
+
readonly beliefMemory?: IHindsightBeliefMemory | undefined;
|
|
24557
|
+
}
|
|
24558
|
+
/**
|
|
24559
|
+
* Execute the full multi-agent development pipeline.
|
|
24560
|
+
*
|
|
24561
|
+
* When `sessionId` is provided, each stage checkpoints to disk. On crash,
|
|
24562
|
+
* re-running with the same sessionId resumes from the last completed stage.
|
|
24563
|
+
*
|
|
24564
|
+
* @param task - High-level task description
|
|
24565
|
+
* @param stages - Pluggable stage implementations
|
|
24566
|
+
* @param options - Pipeline options (sessionId for checkpoint/resume)
|
|
24567
|
+
* @returns Pipeline result with all outputs
|
|
24568
|
+
*/
|
|
24569
|
+
declare function runDevPipeline(task: string, stages: DevPipelineStages, options?: DevPipelineOptions): Promise<DevPipelineResult>;
|
|
24570
|
+
|
|
24443
24571
|
/**
|
|
24444
24572
|
* nexus-agents/mcp - Improvement Review Tool
|
|
24445
24573
|
*
|
|
@@ -24488,6 +24616,12 @@ interface ImprovementReviewResponse {
|
|
|
24488
24616
|
readonly window: string;
|
|
24489
24617
|
readonly totalOutcomes: number;
|
|
24490
24618
|
readonly signals: readonly ImprovementSignal[];
|
|
24619
|
+
/**
|
|
24620
|
+
* Remediation tasks derived from {@link signals} (#3540 capability-loop
|
|
24621
|
+
* increment 1) — SUGGEST-ONLY: structured tasks for a reviewer to consider
|
|
24622
|
+
* routing through the dev-pipeline. Nothing here is executed or auto-invoked.
|
|
24623
|
+
*/
|
|
24624
|
+
readonly remediationTasks: readonly PipelineTask[];
|
|
24491
24625
|
readonly issuesFiled: readonly {
|
|
24492
24626
|
readonly signalKey: string;
|
|
24493
24627
|
readonly issueUrl: string;
|
|
@@ -25386,134 +25520,6 @@ declare class AuditLogger implements IAuditLogger {
|
|
|
25386
25520
|
}
|
|
25387
25521
|
declare function createAuditLogger(config: AuditLogConfig, storage?: IAuditStorage, logger?: ILogger): AuditLogger;
|
|
25388
25522
|
|
|
25389
|
-
/** Agent roles used in the pipeline. */
|
|
25390
|
-
type PipelineRole = 'researcher' | 'architect' | 'pm' | 'coder' | 'qa' | 'security';
|
|
25391
|
-
/** A task decomposed by the PM, potentially with conditional approval requirements. */
|
|
25392
|
-
interface PipelineTask {
|
|
25393
|
-
readonly id: string;
|
|
25394
|
-
readonly title: string;
|
|
25395
|
-
readonly description: string;
|
|
25396
|
-
readonly assignedTo: PipelineRole;
|
|
25397
|
-
readonly status: 'pending' | 'in_progress' | 'review' | 'done' | 'rejected';
|
|
25398
|
-
readonly feedback?: string;
|
|
25399
|
-
/** Implementation text from the code expert (surfaced for harness use). */
|
|
25400
|
-
readonly implementation?: string;
|
|
25401
|
-
/** Conditions required for task completion (from conditional_go vote). */
|
|
25402
|
-
readonly conditions?: readonly string[] | undefined;
|
|
25403
|
-
/** Caveats/warnings associated with the task (from conditional_go vote). */
|
|
25404
|
-
readonly caveats?: readonly string[] | undefined;
|
|
25405
|
-
}
|
|
25406
|
-
/** Vote result from consensus — discriminated union with conditional approval support. */
|
|
25407
|
-
type VoteResult = {
|
|
25408
|
-
readonly kind: 'approved';
|
|
25409
|
-
readonly approvalPercentage: number;
|
|
25410
|
-
} | {
|
|
25411
|
-
readonly kind: 'rejected';
|
|
25412
|
-
readonly feedback: string;
|
|
25413
|
-
readonly approvalPercentage: number;
|
|
25414
|
-
} | {
|
|
25415
|
-
readonly kind: 'conditional_go';
|
|
25416
|
-
readonly conditions: readonly string[];
|
|
25417
|
-
readonly caveats: readonly string[];
|
|
25418
|
-
readonly approvalPercentage: number;
|
|
25419
|
-
};
|
|
25420
|
-
/** QA review result. */
|
|
25421
|
-
interface QaReviewResult {
|
|
25422
|
-
readonly verdict: 'pass' | 'needs_work' | 'reject';
|
|
25423
|
-
readonly feedback: string;
|
|
25424
|
-
readonly issues: readonly string[];
|
|
25425
|
-
}
|
|
25426
|
-
/** Overall pipeline result. */
|
|
25427
|
-
interface DevPipelineResult {
|
|
25428
|
-
readonly completed: boolean;
|
|
25429
|
-
readonly plan: string;
|
|
25430
|
-
readonly tasks: readonly PipelineTask[];
|
|
25431
|
-
readonly voteIterations: number;
|
|
25432
|
-
readonly qaIterations: number;
|
|
25433
|
-
readonly securityPassed: boolean;
|
|
25434
|
-
}
|
|
25435
|
-
/** Pluggable stage implementations — inject real or mock agents. */
|
|
25436
|
-
interface DevPipelineStages {
|
|
25437
|
-
/** Research expert gathers context for the task. */
|
|
25438
|
-
research(task: string): Promise<string>;
|
|
25439
|
-
/** Architect creates a plan from research + task. */
|
|
25440
|
-
plan(task: string, research: string, priorFeedback?: string): Promise<string>;
|
|
25441
|
-
/**
|
|
25442
|
-
* Consensus vote on the plan. Returns approval + feedback. `research` is the
|
|
25443
|
-
* research-stage context, surfaced to voters so they can weigh research
|
|
25444
|
-
* maturity (#3258) — appended to the proposal as informational, untrusted
|
|
25445
|
-
* text (never as instructions).
|
|
25446
|
-
*/
|
|
25447
|
-
vote(plan: string, research: string): Promise<VoteResult>;
|
|
25448
|
-
/** PM decomposes approved plan into tasks. */
|
|
25449
|
-
decompose(plan: string): Promise<PipelineTask[]>;
|
|
25450
|
-
/** Code expert implements a task. Returns the work product. */
|
|
25451
|
-
implement(task: PipelineTask): Promise<string>;
|
|
25452
|
-
/** QA expert reviews implementation. */
|
|
25453
|
-
qaReview(task: PipelineTask, implementation: string): Promise<QaReviewResult>;
|
|
25454
|
-
/**
|
|
25455
|
-
* Local QA quality gate (typecheck/lint/tests/build) run before ship (#3356).
|
|
25456
|
-
* Optional: pipelines that don't supply it simply skip the gate. Returns
|
|
25457
|
-
* `passed` plus actionable `feedback` from the underlying `runQualityGate`
|
|
25458
|
-
* engine. Whether a red gate fails the phase is governed by the
|
|
25459
|
-
* `qualityGate` mode in {@link DevPipelineOptions}, not this method.
|
|
25460
|
-
*/
|
|
25461
|
-
qualityGate?(): Promise<{
|
|
25462
|
-
passed: boolean;
|
|
25463
|
-
feedback: string;
|
|
25464
|
-
}>;
|
|
25465
|
-
/** Security scan. Returns true if passed. */
|
|
25466
|
-
securityScan(): Promise<{
|
|
25467
|
-
passed: boolean;
|
|
25468
|
-
feedback: string;
|
|
25469
|
-
}>;
|
|
25470
|
-
}
|
|
25471
|
-
/** Pipeline execution mode. */
|
|
25472
|
-
type PipelineMode = 'autonomous' | 'harness';
|
|
25473
|
-
/**
|
|
25474
|
-
* Local quality-gate mode (#3356). Controls the pre-ship typecheck/lint/tests/build gate:
|
|
25475
|
-
* - 'off' (default): the gate is never run. Safe for repos lacking standard scripts.
|
|
25476
|
-
* - 'advisory': the gate runs and its feedback is recorded, but a red gate does
|
|
25477
|
-
* NOT fail the pipeline.
|
|
25478
|
-
* - 'blocking': a red gate fails the phase, the same way a blocking security
|
|
25479
|
-
* scan does.
|
|
25480
|
-
*/
|
|
25481
|
-
type QualityGateMode = 'off' | 'advisory' | 'blocking';
|
|
25482
|
-
/** Options for pipeline execution. */
|
|
25483
|
-
interface DevPipelineOptions {
|
|
25484
|
-
/** Session ID for checkpoint/resume. Omit for no persistence. */
|
|
25485
|
-
readonly sessionId?: string | undefined;
|
|
25486
|
-
/** When true, stop after plan+vote and return partial result (#1717). */
|
|
25487
|
-
readonly dryRun?: boolean | undefined;
|
|
25488
|
-
/**
|
|
25489
|
-
* Pipeline mode (#1704):
|
|
25490
|
-
* - 'autonomous' (default): full pipeline runs internally
|
|
25491
|
-
* - 'harness': stops after decompose, returns tasks for external implementation
|
|
25492
|
-
*/
|
|
25493
|
-
readonly mode?: PipelineMode | undefined;
|
|
25494
|
-
/**
|
|
25495
|
-
* Local pre-ship quality-gate mode (#3356). Default 'off' so the pipeline
|
|
25496
|
-
* never wedges repos that lack standard build/test scripts. See
|
|
25497
|
-
* {@link QualityGateMode}. Requires `stages.qualityGate` to be supplied;
|
|
25498
|
-
* if the stage is absent the gate is skipped regardless of mode.
|
|
25499
|
-
*/
|
|
25500
|
-
readonly qualityGate?: QualityGateMode | undefined;
|
|
25501
|
-
/** Optional BeliefMemory for hindsight updates after plan outcomes (#1720). */
|
|
25502
|
-
readonly beliefMemory?: IHindsightBeliefMemory | undefined;
|
|
25503
|
-
}
|
|
25504
|
-
/**
|
|
25505
|
-
* Execute the full multi-agent development pipeline.
|
|
25506
|
-
*
|
|
25507
|
-
* When `sessionId` is provided, each stage checkpoints to disk. On crash,
|
|
25508
|
-
* re-running with the same sessionId resumes from the last completed stage.
|
|
25509
|
-
*
|
|
25510
|
-
* @param task - High-level task description
|
|
25511
|
-
* @param stages - Pluggable stage implementations
|
|
25512
|
-
* @param options - Pipeline options (sessionId for checkpoint/resume)
|
|
25513
|
-
* @returns Pipeline result with all outputs
|
|
25514
|
-
*/
|
|
25515
|
-
declare function runDevPipeline(task: string, stages: DevPipelineStages, options?: DevPipelineOptions): Promise<DevPipelineResult>;
|
|
25516
|
-
|
|
25517
25523
|
/**
|
|
25518
25524
|
* Pipeline Stage Types — Shared interfaces for graph-backed pipelines (#1735, Phase 2)
|
|
25519
25525
|
*
|
package/dist/index.js
CHANGED
|
@@ -519,7 +519,7 @@ import {
|
|
|
519
519
|
validateWorkflow,
|
|
520
520
|
validateWorkflowDependencies,
|
|
521
521
|
withLogging
|
|
522
|
-
} from "./chunk-
|
|
522
|
+
} from "./chunk-JLXZPSMU.js";
|
|
523
523
|
import "./chunk-3ACDP4E6.js";
|
|
524
524
|
import "./chunk-WAYGXUSM.js";
|
|
525
525
|
import {
|
|
@@ -645,7 +645,7 @@ import {
|
|
|
645
645
|
import {
|
|
646
646
|
ImprovementReviewInputSchema,
|
|
647
647
|
registerImprovementReviewTool
|
|
648
|
-
} from "./chunk-
|
|
648
|
+
} from "./chunk-35YWAUJX.js";
|
|
649
649
|
import {
|
|
650
650
|
AgentPerformanceSchema,
|
|
651
651
|
ConsensusAlgorithmSchema,
|
|
@@ -726,7 +726,7 @@ import {
|
|
|
726
726
|
getKnownNexusVarNames,
|
|
727
727
|
startStdioServer,
|
|
728
728
|
validateNexusEnv
|
|
729
|
-
} from "./chunk-
|
|
729
|
+
} from "./chunk-D52WH4UW.js";
|
|
730
730
|
import "./chunk-NUBSJGQZ.js";
|
|
731
731
|
import "./chunk-6T3EPABN.js";
|
|
732
732
|
import {
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
runWizard,
|
|
9
9
|
setupCommand,
|
|
10
10
|
setupCommandAsync
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-LKWQ3AT4.js";
|
|
12
12
|
import "./chunk-PBMXKQCK.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-D52WH4UW.js";
|
|
14
14
|
import "./chunk-NUBSJGQZ.js";
|
|
15
15
|
import "./chunk-6T3EPABN.js";
|
|
16
16
|
import "./chunk-TSAEDXVB.js";
|
|
@@ -34,4 +34,4 @@ export {
|
|
|
34
34
|
setupCommand,
|
|
35
35
|
setupCommandAsync
|
|
36
36
|
};
|
|
37
|
-
//# sourceMappingURL=setup-command-
|
|
37
|
+
//# sourceMappingURL=setup-command-G6IWNPE2.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexus-agents",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.124.0",
|
|
4
4
|
"description": "Governance substrate for AI coding agents — adversarial PR review, drift-detected rules, immutable audit, and closed-loop outcome routing for Claude, Codex, Gemini, and OpenCode",
|
|
5
5
|
"mcpName": "io.github.nexus-substrate/nexus-agents",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/tools/improvement-review.ts","../src/mcp/middleware/tool-prerequisites.ts","../src/governance/fitness-score.ts","../src/mcp/tools/improvement-review-signals.ts"],"sourcesContent":["/**\n * nexus-agents/mcp - Improvement Review Tool\n *\n * Periodic, threshold-gated observability-driven improvement loop.\n *\n * Reads from existing observability primitives (OutcomeStore, weather-report,\n * fitness-audit, audit-chain) and surfaces patterns that cross documented\n * thresholds as candidate GitHub issues. Never auto-merges; humans or\n * `consensus_vote` decide what to implement.\n *\n * Replaces the deleted `src/workflows/self-development/` engine, which never\n * wired up to consume any of these signals.\n *\n * @module mcp/tools/improvement-review\n * (Source: Issue #2402)\n */\n\nimport { execFile } from 'node:child_process';\nimport { readFile } from 'node:fs/promises';\nimport { promisify } from 'node:util';\n/* eslint-disable max-lines */\nimport { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { createLogger, formatZodError, getErrorMessage } from '../../core/index.js';\nimport { wrapToolWithTimeout, toSdkCallback, getToolTimeout } from '../middleware/tool-wrapper.js';\nimport { createSecureHandler, type HandlerContext } from '../middleware/secure-handler.js';\nimport { withPrerequisite } from '../middleware/tool-prerequisites.js';\nimport {\n toolStructuredError,\n toolSuccessStructured,\n type ToolResult,\n type BaseMcpToolDeps,\n} from './tool-result.js';\nimport { getOutcomeStore } from '../../orchestration/outcomes/outcome-store.js';\nimport type { TaskOutcome } from '../../orchestration/outcomes/outcome-types.js';\nimport { calculateFitnessScore, type FitnessAudit } from '../../governance/fitness-score.js';\nimport { getPipelineEventBus } from '../../pipeline/event-bus.js';\nimport type { VoteRejectedSignalEvent } from '../../pipeline/event-types.js';\nimport { REJECTION_CATEGORIES } from '../../consensus/types-core.js';\nimport { emitFitnessDeclinedSignal } from './improvement-review-signals.js';\nimport { getToolAnnotations } from '../tool-annotations.js';\n\nconst execFileAsync = promisify(execFile);\n\n// ============================================================================\n// Schemas\n// ============================================================================\n\nexport const ImprovementReviewInputSchema = z.object({\n lookbackDays: z\n .number()\n .int()\n .min(1)\n .max(90)\n .optional()\n .default(7)\n .describe('Lookback window for outcome data, in days. Default 7.'),\n fileIssues: z\n .boolean()\n .optional()\n .default(false)\n .describe(\n 'When true, file candidate issues via `gh issue create` for crossed thresholds (rate-limited to 5 per run, deduped against open issues). When false (default), return signals only.'\n ),\n minSampleSize: z\n .number()\n .int()\n .min(1)\n .max(1000)\n .optional()\n .default(5)\n .describe('Minimum sample size before a CLI/category signal can fire.'),\n fitnessFloor: z\n .number()\n .int()\n .min(0)\n .max(100)\n .optional()\n .default(90)\n .describe('Fitness score below this threshold triggers a tech-debt signal.'),\n selfEvalReportPath: z\n .string()\n .optional()\n .describe(\n 'Optional path to a self-eval JSON report (from `self-eval --json`). When set, ' +\n 'high-confidence unanimous deprecate/refactor findings are surfaced as tech-debt ' +\n 'signals through the same deduped/rate-limited issue path (#3224). Unreadable/malformed ' +\n 'reports are skipped (no signal). Absent → no self-eval signals.'\n ),\n});\n\nexport type ImprovementReviewInput = z.infer<typeof ImprovementReviewInputSchema>;\n\nexport type SignalCategory = 'routing' | 'tech-debt' | 'bug' | 'security' | 'consensus';\n\nexport interface ImprovementSignal {\n readonly category: SignalCategory;\n /** Stable key used for dedup against existing issues. */\n readonly signalKey: string;\n /** Severity per CVSS-aligned scale (security uses critical; others use warning/info). */\n readonly severity: 'info' | 'warning' | 'critical';\n /** One-line title suitable for a GitHub issue. */\n readonly title: string;\n /** Multi-line body with evidence (sample counts, time windows, observed values). */\n readonly body: string;\n /** Linkable evidence the signal is grounded in observability data, not intuition. */\n readonly evidence: {\n readonly samples?: number;\n readonly window?: string;\n readonly observedValue?: number;\n readonly threshold?: number;\n };\n}\n\nexport interface ImprovementReviewResponse {\n readonly window: string;\n readonly totalOutcomes: number;\n readonly signals: readonly ImprovementSignal[];\n readonly issuesFiled: readonly { readonly signalKey: string; readonly issueUrl: string }[];\n readonly issuesSkipped: readonly { readonly signalKey: string; readonly reason: string }[];\n}\n\n// ============================================================================\n// Pure threshold logic (testable without fs / network)\n// ============================================================================\n\nconst MAX_ISSUES_PER_RUN = 5;\n\nconst HOUR_MS = 60 * 60 * 1000;\nconst DAY_MS = 24 * HOUR_MS;\n\n/** Filter outcomes to a lookback window. Outcome timestamps are ISO strings. */\nexport function filterByLookback(\n outcomes: readonly TaskOutcome[],\n lookbackDays: number,\n now: number\n): readonly TaskOutcome[] {\n const cutoff = now - lookbackDays * DAY_MS;\n return outcomes.filter((o) => {\n const t = Date.parse(o.timestamp);\n return Number.isFinite(t) && t >= cutoff;\n });\n}\n\n/**\n * Detect CLI × category pairs whose success rate has fallen below the\n * performance floor with at least minSamples observations.\n *\n * Threshold: success rate < 60% AND samples >= minSamples.\n */\nexport function detectCliPerformanceFloor(\n outcomes: readonly TaskOutcome[],\n minSamples: number,\n windowLabel: string\n): readonly ImprovementSignal[] {\n const buckets = new Map<string, { cli: string; category: string; ok: number; total: number }>();\n for (const o of outcomes) {\n const key = `${o.cli}::${o.category}`;\n const bucket = buckets.get(key) ?? { cli: o.cli, category: o.category, ok: 0, total: 0 };\n bucket.total += 1;\n if (o.success) bucket.ok += 1;\n buckets.set(key, bucket);\n }\n\n const signals: ImprovementSignal[] = [];\n for (const b of buckets.values()) {\n if (b.total < minSamples) continue;\n const rate = b.ok / b.total;\n if (rate >= 0.6) continue;\n const ratePct = Math.round(rate * 100);\n signals.push({\n category: 'routing',\n signalKey: `routing:cli-floor:${b.cli}:${b.category}`,\n severity: rate < 0.4 ? 'critical' : 'warning',\n title: `routing: ${b.cli} success rate ${String(ratePct)}% on ${b.category} (${windowLabel})`,\n body: [\n `Observed performance floor breach in the ${windowLabel} window.`,\n '',\n `- CLI: \\`${b.cli}\\``,\n `- Category: \\`${b.category}\\``,\n `- Success rate: ${String(ratePct)}% (${String(b.ok)}/${String(b.total)})`,\n `- Threshold: 60% with ≥${String(minSamples)} samples`,\n '',\n 'Consider routing this category away from this CLI, or investigating the failure pattern via `weather_report` and the OutcomeStore.',\n ].join('\\n'),\n evidence: {\n samples: b.total,\n window: windowLabel,\n observedValue: rate,\n threshold: 0.6,\n },\n });\n }\n return signals;\n}\n\n/**\n * Minimum number of rejected plans citing the same ADR-0016 rule before a\n * recurring-rejection pattern is worth surfacing. Two is coincidence; three is\n * a systemic planning gap (mirrors the DRY \"third occurrence\" rule).\n */\nconst MIN_REJECTION_PATTERN = 3;\n\n/**\n * Detect recurring consensus-rejection patterns (#3259): a single ADR-0016\n * rejection rule (`DRY_VIOLATION`, `OVER_ENGINEERING`, `SCOPE_CREEP`, …) cited\n * across ≥{@link MIN_REJECTION_PATTERN} rejected plans in the window. The\n * `signal.vote_rejected` events are produced by `consensus_vote` on rejection\n * (consensus-vote-signals.ts) and buffered on the pipeline event bus; this\n * detector closes the loop the system review flagged as missing — recurring\n * rejection for the same reason means the planner keeps making the same class\n * of mistake, which the next improvement cycle should name explicitly.\n *\n * Events with no `rejectionRules` (un-categorized rejections) contribute no\n * pattern signal — there is nothing actionable to aggregate on.\n */\nexport function detectConsensusRejectionSignals(\n events: readonly VoteRejectedSignalEvent[],\n windowLabel: string\n): readonly ImprovementSignal[] {\n if (events.length === 0) return [];\n\n // Defense-in-depth allowlist: the only producer (consensus-vote-signals.ts)\n // sources rules from the Zod-validated ADR-0016 enum, so a free-form/poisoned\n // rule cannot reach here today. Re-validating against REJECTION_CATEGORIES\n // makes that safety local — an unexpected rule string never reaches an issue\n // title/body — instead of relying on cross-file inference (#3259 review).\n const allowed = new Set<string>(REJECTION_CATEGORIES);\n const byRule = new Map<string, number>();\n for (const e of events) {\n for (const rule of e.rejectionRules ?? []) {\n if (!allowed.has(rule)) continue;\n byRule.set(rule, (byRule.get(rule) ?? 0) + 1);\n }\n }\n\n const signals: ImprovementSignal[] = [];\n for (const [rule, count] of byRule) {\n if (count < MIN_REJECTION_PATTERN) continue;\n signals.push({\n category: 'consensus',\n signalKey: `consensus:rejection-pattern:${rule}`,\n severity: count >= MIN_REJECTION_PATTERN * 2 ? 'warning' : 'info',\n title: `consensus: ${String(count)} plans rejected for \\`${rule}\\` in ${windowLabel}`,\n body: [\n `Recurring consensus-rejection pattern in the ${windowLabel} window.`,\n '',\n `- Rejection rule: \\`${rule}\\` (ADR-0016 category)`,\n `- Occurrences: ${String(count)} rejected plans`,\n `- Threshold: ≥${String(MIN_REJECTION_PATTERN)} plans citing the same rule`,\n '',\n 'The planner keeps producing plans that voters reject for the same reason. ' +\n 'Feed this back into plan generation (e.g. a planning guardrail or a ' +\n 'targeted prompt note) rather than rejecting plan-by-plan. Inspect the ' +\n 'rejected proposals via `query_trace` / the consensus audit chain.',\n ].join('\\n'),\n evidence: {\n samples: count,\n window: windowLabel,\n observedValue: count,\n threshold: MIN_REJECTION_PATTERN,\n },\n });\n }\n return signals;\n}\n\n/**\n * Detect failure-category concentration: a single failure category accounts\n * for > 50% of all failures with at least 10 failures observed.\n */\nexport function detectFailureCategoryConcentration(\n outcomes: readonly TaskOutcome[],\n windowLabel: string\n): readonly ImprovementSignal[] {\n const failures = outcomes.filter((o) => !o.success);\n if (failures.length < 10) return [];\n\n const byCategory = new Map<string, number>();\n for (const f of failures) {\n const cat = f.failureCategory ?? 'unknown';\n byCategory.set(cat, (byCategory.get(cat) ?? 0) + 1);\n }\n\n const signals: ImprovementSignal[] = [];\n for (const [cat, count] of byCategory) {\n const share = count / failures.length;\n if (share <= 0.5) continue;\n const sharePct = Math.round(share * 100);\n signals.push({\n category: 'bug',\n signalKey: `bug:failure-concentration:${cat}`,\n severity: 'warning',\n title: `bug: ${String(sharePct)}% of failures in ${windowLabel} share category \\`${cat}\\``,\n body: [\n `Failure-category concentration breach in the ${windowLabel} window.`,\n '',\n `- Category: \\`${cat}\\``,\n `- Share: ${String(sharePct)}% (${String(count)}/${String(failures.length)} failures)`,\n `- Threshold: > 50% with ≥10 failures`,\n '',\n 'A single failure mode dominating the error budget usually means a systemic bug or routing miss. Investigate via `query_trace` and the OutcomeStore.',\n ].join('\\n'),\n evidence: {\n samples: failures.length,\n window: windowLabel,\n observedValue: share,\n threshold: 0.5,\n },\n });\n }\n return signals;\n}\n\nfunction buildFloorSignal(audit: FitnessAudit, fitnessFloor: number): ImprovementSignal {\n return {\n category: 'tech-debt',\n signalKey: `tech-debt:fitness-below-floor`,\n severity: audit.score < 70 ? 'critical' : 'warning',\n title: `tech-debt: fitness score ${String(audit.score)}/100 below floor ${String(fitnessFloor)}`,\n body: [\n `Code fitness score has dropped below the governance floor.`,\n '',\n `- Score: ${String(audit.score)} / 100`,\n `- Floor: ${String(fitnessFloor)} (governance threshold per CLAUDE.md)`,\n `- Findings: ${String(audit.findings.length)} total`,\n '',\n 'Run `nexus-agents fitness-audit` for the full breakdown. Critical findings:',\n ...audit.findings\n .filter((f) => f.severity === 'critical')\n .slice(0, 5)\n .map((f) => `- ${f.dimension}: ${f.description}`),\n ].join('\\n'),\n evidence: { observedValue: audit.score, threshold: fitnessFloor },\n };\n}\n\nfunction buildCriticalFindingSignal(finding: FitnessAudit['findings'][number]): ImprovementSignal {\n return {\n category: 'tech-debt',\n signalKey: `tech-debt:fitness-critical:${finding.dimension}`,\n severity: 'critical',\n title: `tech-debt: critical fitness finding in ${finding.dimension}`,\n body: [\n `Fitness audit returned a CRITICAL finding.`,\n '',\n `- Dimension: \\`${finding.dimension}\\``,\n `- Description: ${finding.description}`,\n `- Points deducted: ${String(finding.pointsDeducted)}`,\n finding.location !== undefined ? `- Location: ${finding.location}` : '',\n finding.suggestion !== undefined ? `- Suggestion: ${finding.suggestion}` : '',\n ]\n .filter((line) => line.length > 0)\n .join('\\n'),\n evidence: { observedValue: -finding.pointsDeducted },\n };\n}\n\n/** Detect fitness signals: score below floor OR critical findings. */\nexport function detectFitnessSignals(\n audit: FitnessAudit,\n fitnessFloor: number\n): readonly ImprovementSignal[] {\n const signals: ImprovementSignal[] = [];\n if (audit.score < fitnessFloor) signals.push(buildFloorSignal(audit, fitnessFloor));\n for (const finding of audit.findings) {\n if (finding.severity === 'critical') signals.push(buildCriticalFindingSignal(finding));\n }\n return signals;\n}\n\n// ============================================================================\n// Self-eval findings → tech-debt signals (#3224)\n// ============================================================================\n\n/** Minimum confidence for a self-eval finding to surface as a signal. */\nconst SELF_EVAL_CONFIDENCE_FLOOR = 0.8;\n\n/**\n * Minimal, defensive schema for the `self-eval --json` report. We only read the\n * fields needed to surface a finding; unknown extras are ignored so the parse\n * tolerates schema drift in the (externally produced) artifact.\n */\nconst SelfEvalReportSchema = z.object({\n results: z.array(\n z.object({\n component: z.string(),\n finalRecommendation: z.string(),\n confidence: z.number(),\n dissent: z.array(z.unknown()).optional().default([]),\n evidenceQuality: z.number().optional(),\n })\n ),\n});\n\n/**\n * Convert a parsed self-eval report into tech-debt `ImprovementSignal`s.\n *\n * Only **actionable, high-confidence, unanimous** findings surface (#3224): a\n * `deprecate`/`refactor` recommendation with NO dissent and confidence at/above\n * {@link SELF_EVAL_CONFIDENCE_FLOOR}. This is a pure transform — it surfaces a\n * human decision point (a candidate issue), never an automatic routing change.\n */\nexport function detectSelfEvalSignals(\n report: z.infer<typeof SelfEvalReportSchema>,\n windowLabel: string\n): readonly ImprovementSignal[] {\n const signals: ImprovementSignal[] = [];\n for (const r of report.results) {\n const actionable =\n r.finalRecommendation === 'deprecate' || r.finalRecommendation === 'refactor';\n if (!actionable || r.dissent.length > 0 || r.confidence < SELF_EVAL_CONFIDENCE_FLOOR) continue;\n signals.push({\n category: 'tech-debt',\n signalKey: `tech-debt:self-eval:${r.component}:${r.finalRecommendation}`,\n severity: r.finalRecommendation === 'deprecate' ? 'warning' : 'info',\n title: `tech-debt: self-eval recommends ${r.finalRecommendation} for ${r.component}`,\n body: [\n `All self-eval evaluators agreed (no dissent) on **${r.finalRecommendation}** for \\`${r.component}\\``,\n `with confidence ${(r.confidence * 100).toFixed(0)}%${r.evidenceQuality !== undefined ? ` (evidence quality ${(r.evidenceQuality * 100).toFixed(0)}%)` : ''}.`,\n '',\n 'This is a RECOMMENDATION surfaced for human review — not an automatic change.',\n ].join('\\n'),\n evidence: {\n observedValue: r.confidence,\n threshold: SELF_EVAL_CONFIDENCE_FLOOR,\n window: windowLabel,\n },\n });\n }\n return signals;\n}\n\n/**\n * Read + parse a self-eval JSON report and convert it to signals. Fail-soft:\n * an unreadable or malformed report yields NO signals (logged at warn) rather\n * than breaking the review.\n */\nexport async function loadSelfEvalSignals(\n reportPath: string,\n windowLabel: string,\n logger: ReturnType<typeof createLogger>\n): Promise<readonly ImprovementSignal[]> {\n try {\n const raw = await readFile(reportPath, 'utf8');\n const parsed = SelfEvalReportSchema.safeParse(JSON.parse(raw));\n if (!parsed.success) {\n logger.warn('Self-eval report ignored — schema mismatch', {\n reportPath,\n error: formatZodError(parsed.error),\n });\n return [];\n }\n return detectSelfEvalSignals(parsed.data, windowLabel);\n } catch (error) {\n logger.warn('Self-eval report ignored — unreadable/invalid JSON', {\n reportPath,\n error: getErrorMessage(error),\n });\n return [];\n }\n}\n\n// ============================================================================\n// Issue filing (gated, dedup-checked, command-injection-safe)\n// ============================================================================\n\n/**\n * Check whether an existing OPEN issue already covers this signal key.\n * Uses `gh issue list --search` with the signal key as a literal phrase.\n * The signal key appears in our filed-issue body so this dedup is reliable.\n */\nasync function existingIssueForSignal(signalKey: string): Promise<string | null> {\n try {\n // Strip double-quotes from the search term so a quote in the signalKey\n // (e.g. an oddly-named self-eval component path, #3224) can't break the\n // `\"...\" in:body` phrase query and silently defeat dedup → refiling.\n const searchTerm = signalKey.replace(/\"/g, '');\n const { stdout } = await execFileAsync('gh', [\n 'issue',\n 'list',\n '--state',\n 'open',\n '--search',\n `\"${searchTerm}\" in:body`,\n '--json',\n 'number,url',\n '--limit',\n '5',\n ]);\n const parsed = JSON.parse(stdout) as readonly { url?: string }[];\n if (parsed.length > 0 && typeof parsed[0]?.url === 'string') {\n return parsed[0].url;\n }\n return null;\n } catch {\n // gh failure → conservatively treat as \"no dup\" but log upstream.\n return null;\n }\n}\n\n/**\n * File an issue via `gh issue create` using execFile (no shell, no\n * command-injection risk on errorMessage / title / body content).\n */\nasync function fileIssueForSignal(\n signal: ImprovementSignal\n): Promise<{ ok: true; url: string } | { ok: false; error: string }> {\n // Embed the signal key in the body so dedup is reliable on subsequent runs.\n const body = `${signal.body}\\n\\n---\\n\\n_Signal key (do not edit): \\`${signal.signalKey}\\` · Generated by \\`improvement_review\\` (#2402) · Severity: ${signal.severity}_`;\n const labels = signal.category === 'security' ? 'security' : signal.category;\n\n try {\n const { stdout } = await execFileAsync('gh', [\n 'issue',\n 'create',\n '--title',\n signal.title,\n '--body',\n body,\n '--label',\n labels,\n ]);\n const url = stdout.trim();\n if (!url.startsWith('https://')) {\n return { ok: false, error: `gh returned unexpected output: ${stdout.slice(0, 200)}` };\n }\n return { ok: true, url };\n } catch (caught) {\n const message = caught instanceof Error ? caught.message : String(caught);\n return { ok: false, error: message };\n }\n}\n\n// ============================================================================\n// Handler\n// ============================================================================\n\nfunction safeFitnessAudit(now: number, ctx: HandlerContext): FitnessAudit {\n try {\n return calculateFitnessScore('improvement-review');\n } catch (caught) {\n ctx.logger.warn('fitness audit failed; skipping fitness signals', {\n error: caught instanceof Error ? caught.message : String(caught),\n });\n return {\n score: 100,\n dimensions: {} as FitnessAudit['dimensions'],\n findings: [],\n timestamp: new Date(now).toISOString(),\n version: 'improvement-review-fallback',\n };\n }\n}\n\nconst SEVERITY_ORDER: Record<ImprovementSignal['severity'], number> = {\n critical: 0,\n warning: 1,\n info: 2,\n};\n\nasync function fileSignalsAsIssues(\n signals: readonly ImprovementSignal[],\n ctx: HandlerContext\n): Promise<{\n issuesFiled: { signalKey: string; issueUrl: string }[];\n issuesSkipped: { signalKey: string; reason: string }[];\n}> {\n const issuesFiled: { signalKey: string; issueUrl: string }[] = [];\n const issuesSkipped: { signalKey: string; reason: string }[] = [];\n\n for (const signal of signals) {\n if (issuesFiled.length >= MAX_ISSUES_PER_RUN) {\n issuesSkipped.push({ signalKey: signal.signalKey, reason: 'rate-limit' });\n continue;\n }\n const existing = await existingIssueForSignal(signal.signalKey);\n if (existing !== null) {\n issuesSkipped.push({ signalKey: signal.signalKey, reason: `dup:${existing}` });\n continue;\n }\n const result = await fileIssueForSignal(signal);\n if (result.ok) {\n issuesFiled.push({ signalKey: signal.signalKey, issueUrl: result.url });\n ctx.logger.info('improvement signal filed', {\n signalKey: signal.signalKey,\n url: result.url,\n });\n } else {\n issuesSkipped.push({ signalKey: signal.signalKey, reason: `error:${result.error}` });\n }\n }\n\n return { issuesFiled, issuesSkipped };\n}\n\n/**\n * Read `signal.vote_rejected` events from the pipeline bus's buffered history,\n * narrowed to the lookback window. Returns `[]` if the bus is empty or every\n * event predates the window. Fail-soft: never throws into the review run.\n *\n * The bus is a per-process module singleton (event-bus.ts), so this only sees\n * rejections emitted by `consensus_vote` *in the same process* — i.e. a\n * long-lived MCP server where both tools share the buffer. In separate\n * CLI invocations the buffer starts empty and this correctly yields no signals\n * (the loop degrades to \"no consensus data\" rather than misreporting).\n */\nfunction readBufferedVoteRejections(\n now: number,\n lookbackDays: number\n): readonly VoteRejectedSignalEvent[] {\n const cutoff = now - lookbackDays * DAY_MS;\n return getPipelineEventBus()\n .query({ type: 'signal.vote_rejected' })\n .filter((e): e is VoteRejectedSignalEvent => e.type === 'signal.vote_rejected')\n .filter((e) => e.timestamp >= cutoff);\n}\n\n/**\n * Context-free runner exposed for both the MCP handler and the\n * `nexus-agents improvement-review` CLI subcommand (#2444). Pure dependencies\n * — pass a logger and an OutcomeStore-query result if you want to inject test\n * data; defaults read the global store and a no-op logger.\n */\nexport async function runImprovementReview(\n input: ImprovementReviewInput,\n deps: { readonly logger?: ReturnType<typeof createLogger> } = {}\n): Promise<ImprovementReviewResponse> {\n const logger = deps.logger ?? createLogger({ component: 'improvement_review' });\n const { lookbackDays, fileIssues, minSampleSize, fitnessFloor, selfEvalReportPath } = input;\n const now = Date.now();\n const windowLabel = `${String(lookbackDays)}d`;\n\n const allOutcomes = getOutcomeStore().query();\n const windowed = filterByLookback(allOutcomes, lookbackDays, now);\n const audit = safeFitnessAudit(now, { logger } as HandlerContext);\n\n // Surface high-confidence unanimous self-eval findings as tech-debt signals\n // (#3224) — opt-in via selfEvalReportPath, fail-soft (no path / bad file → none).\n const selfEvalSignals =\n selfEvalReportPath !== undefined\n ? await loadSelfEvalSignals(selfEvalReportPath, windowLabel, logger)\n : [];\n\n // Recurring consensus-rejection patterns (#3259). `consensus_vote` buffers a\n // `signal.vote_rejected` event per rejected plan on the pipeline bus; read the\n // buffered history (not a live subscription — this is a one-shot tool) and\n // window-filter by event timestamp before aggregating.\n const rejectionEvents = readBufferedVoteRejections(now, lookbackDays);\n\n const signals: ImprovementSignal[] = [\n ...detectCliPerformanceFloor(windowed, minSampleSize, windowLabel),\n ...detectFailureCategoryConcentration(windowed, windowLabel),\n ...detectFitnessSignals(audit, fitnessFloor),\n ...detectConsensusRejectionSignals(rejectionEvents, windowLabel),\n ...selfEvalSignals,\n ];\n signals.sort((a, b) => SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity]);\n\n // Close the self-tuning loop: a below-floor fitness audit emits\n // signal.fitness_declined onto the typed pipeline bus for the shadow\n // TuneStage (#3147; #3289 Option 2 — observability signals route through bus A).\n emitFitnessDeclinedSignal(audit, fitnessFloor, getPipelineEventBus(), logger);\n\n const { issuesFiled, issuesSkipped } = fileIssues\n ? await fileSignalsAsIssues(signals, { logger } as HandlerContext)\n : { issuesFiled: [], issuesSkipped: [] };\n\n return {\n window: windowLabel,\n totalOutcomes: windowed.length,\n signals,\n issuesFiled,\n issuesSkipped,\n };\n}\n\nasync function reviewHandler(args: unknown, ctx: HandlerContext): Promise<ToolResult> {\n const parsed = ImprovementReviewInputSchema.safeParse(args);\n if (!parsed.success) {\n return toolStructuredError({\n errorCategory: 'validation',\n message: `Validation error: ${formatZodError(parsed.error)}`,\n });\n }\n const response = await runImprovementReview(parsed.data, { logger: ctx.logger });\n return toolSuccessStructured(response as unknown as Record<string, unknown>);\n}\n\n// ============================================================================\n// Registration\n// ============================================================================\n\nexport type ImprovementReviewDeps = BaseMcpToolDeps;\n\nconst description =\n 'Periodic threshold-gated observability-driven improvement loop. Reads OutcomeStore + ' +\n 'fitness audit, surfaces patterns crossing documented thresholds as candidate findings. ' +\n 'When fileIssues=true, files candidate GitHub issues via `gh issue create` (rate-limited ' +\n 'to 5 per run, deduped against open issues). Never auto-merges. Replaces the deleted ' +\n 'self-development engine (#2402).';\n\nconst TOOL_INPUT_SCHEMA = {\n lookbackDays: z\n .number()\n .int()\n .min(1)\n .max(90)\n .optional()\n .describe('Lookback window for outcome data, in days. Default 7.'),\n fileIssues: z\n .boolean()\n .optional()\n .describe(\n 'When true, file candidate issues for crossed thresholds (default false — return signals only)'\n ),\n minSampleSize: z\n .number()\n .int()\n .min(1)\n .max(1000)\n .optional()\n .describe('Minimum sample size before a CLI/category signal fires (default 5).'),\n fitnessFloor: z\n .number()\n .int()\n .min(0)\n .max(100)\n .optional()\n .describe('Fitness score below this threshold triggers a tech-debt signal (default 90).'),\n selfEvalReportPath: z\n .string()\n .optional()\n .describe(\n 'Optional path to a self-eval JSON report. High-confidence unanimous ' +\n 'deprecate/refactor findings surface as tech-debt signals (#3224).'\n ),\n};\n\n/** @category MCP */\nexport function registerImprovementReviewTool(\n server: McpServer,\n deps: ImprovementReviewDeps\n): void {\n const logger = deps.logger ?? createLogger({ tool: 'improvement_review' });\n const secureHandler = createSecureHandler(reviewHandler, {\n toolName: 'improvement_review',\n rateLimiter: deps.rateLimiter,\n logger,\n });\n const guardedHandler = withPrerequisite('improvement_review', secureHandler);\n const timeoutMs = getToolTimeout('improvement_review', deps.security);\n const wrappedHandler = wrapToolWithTimeout('improvement_review', guardedHandler, {\n timeoutMs,\n logger,\n });\n server.registerTool(\n 'improvement_review',\n {\n description,\n inputSchema: TOOL_INPUT_SCHEMA,\n annotations: getToolAnnotations('improvement_review'),\n },\n toSdkCallback(wrappedHandler)\n );\n logger.info('Registered improvement_review tool');\n}\n","/**\n * nexus-agents/mcp - Tool Prerequisite Gates\n *\n * Blocks sensitive MCP tools from running unless a **world-state\n * precondition** holds at call time (Issue #2652, Epic B).\n *\n * DESIGN — predicate, not session-ordering. A prerequisite is a predicate\n * over observable world state (is `gh` installed? is the data dir\n * writable?), evaluated on every invocation. It is NOT \"tool A must have\n * been called before tool B\" — MCP `tools/call` invocations are\n * independent, and a session-ordering gate is satisfied by an LLM calling\n * the prior tool pointlessly without making the precondition true. If a\n * requirement can only be expressed as \"call X first,\" it is not a\n * prerequisite — it is the tool's own internal responsibility (e.g.\n * untrusted-input trust-tier classification stays inside `issue_triage`\n * per `.rules/untrusted-input.md`, it is not gated here).\n *\n * Fail-closed: a predicate that throws blocks the tool.\n *\n * @module mcp/middleware/tool-prerequisites\n * @see Issue #2652\n */\n\nimport { execFile } from 'node:child_process';\nimport { access, constants } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { promisify } from 'node:util';\nimport { getErrorMessage } from '../../core/index.js';\nimport { getNexusDataDir } from '../../config/nexus-data-dir.js';\nimport { toolStructuredError, type ToolResult } from '../tools/tool-result.js';\nimport type { ContextAwareToolHandler, ToolHandler } from './middleware-chain.js';\n\nconst execFileAsync = promisify(execFile);\n\n/** Outcome of evaluating a prerequisite predicate. */\nexport interface PrerequisiteResult {\n ok: boolean;\n /** When `!ok`: what would make the predicate pass. Surfaced to the caller. */\n remediation?: string;\n}\n\n/** A world-state precondition a guarded tool requires at call time. */\nexport interface ToolPrerequisite {\n /** Stable identifier, e.g. `data-dir-writable`. */\n name: string;\n /** Why the tool needs it — for `.rules/tool-prerequisites.md` + the block envelope. */\n rationale: string;\n /** World-state predicate. MUST be cheap and side-effect-free. */\n check: () => Promise<PrerequisiteResult> | PrerequisiteResult;\n}\n\n// ============================================================================\n// Predicates\n// ============================================================================\n\n/** The `gh` CLI is on PATH — required by tools that file/read GitHub state. */\nasync function ghCliAvailable(): Promise<PrerequisiteResult> {\n try {\n await execFileAsync('gh', ['--version'], { timeout: 5000 });\n return { ok: true };\n } catch (err) {\n return {\n ok: false,\n remediation: `the 'gh' CLI is not available (${getErrorMessage(err)}) — install GitHub CLI and authenticate (\\`gh auth login\\`)`,\n };\n }\n}\n\n/**\n * The runtime data directory is writable, or — if it does not exist yet —\n * creatable (its parent is writable). Memory/registry backends create the\n * dir on demand, so \"not yet created\" is not a failure; an unwritable\n * parent is.\n */\nasync function dataDirWritable(): Promise<PrerequisiteResult> {\n const dir = getNexusDataDir();\n try {\n await access(dir, constants.W_OK);\n return { ok: true };\n } catch {\n // Dir may not exist yet — backends create it on demand. Treat a\n // writable parent (creatable) as satisfying the precondition.\n try {\n await access(dirname(dir), constants.W_OK);\n return { ok: true };\n } catch (err) {\n return {\n ok: false,\n remediation: `NEXUS_DATA_DIR (${dir}) is not writable or creatable (${getErrorMessage(err)}) — fix its permissions; run \\`nexus-agents doctor\\` to diagnose`,\n };\n }\n }\n}\n\n// ============================================================================\n// Registry\n// ============================================================================\n\n/**\n * Tools guarded by a call-time prerequisite. Keep this in sync with\n * `.rules/tool-prerequisites.md` — the `check:tool-prerequisites` CI gate\n * verifies every non-read-only tool is either listed here or in\n * `NO_PREREQUISITE` with a reason.\n */\nexport const TOOL_PREREQUISITES: Record<string, ToolPrerequisite> = {\n improvement_review: {\n name: 'gh-cli-available',\n rationale:\n \"improvement_review's fileIssues mode shells out to `gh` to file candidate issues; without it the write path fails mid-operation\",\n check: ghCliAvailable,\n },\n memory_write: {\n name: 'data-dir-writable',\n rationale:\n 'memory_write persists entries under NEXUS_DATA_DIR — an unwritable data dir fails the write confusingly mid-operation',\n check: dataDirWritable,\n },\n registry_import: {\n name: 'data-dir-writable',\n rationale:\n 'registry_import persists a draft registry entry under NEXUS_DATA_DIR when not in dryRun mode',\n check: dataDirWritable,\n },\n};\n\n/**\n * Non-read-only tools that deliberately have NO call-time prerequisite,\n * with the reason. The `check:tool-prerequisites` gate requires every\n * non-read-only tool to appear here or in `TOOL_PREREQUISITES`, so a newly\n * added sensitive tool can't ship ungated by omission.\n */\nexport const NO_PREREQUISITE: Record<string, string> = {\n orchestrate: 'orchestration is self-contained; sub-tool calls carry their own gates',\n create_expert: 'in-memory expert creation; no external precondition',\n execute_expert:\n 'adapter availability is handled by the resilient-adapter circuit breaker, not a pre-gate',\n run_workflow: 'workflow execution is self-contained; step tools carry their own gates',\n run_graph_workflow: 'graph execution is self-contained; node tools carry their own gates',\n run_pipeline: 'pipeline execution is self-contained; stage tools carry their own gates',\n run_dev_pipeline: 'pipeline execution is self-contained; stage tools carry their own gates',\n execute_spec: 'spec execution is self-contained; stage tools carry their own gates',\n consensus_vote: 'voter-CLI availability is handled by per-voter fallback, not a pre-gate',\n ci_health_check:\n 'reads upstream CI status + appends a telemetry event (#3530); no world-state precondition to gate',\n supply_chain_tradeoff_panel: 'wraps consensus_vote; same per-voter fallback applies',\n pr_review: 'wraps consensus_vote; same per-voter fallback applies',\n research_add:\n 'arXiv fetch failures surface as a transient envelope from the handler; no useful pre-gate',\n research_add_source:\n 'GitHub metadata fetch is best-effort with graceful fallback; no useful pre-gate',\n research_catalog_review: 'operates on local catalog state already loaded by the handler',\n issue_triage:\n 'untrusted-input safety (trust-tier classification, Rule of Two) is internal-handler logic per .rules/untrusted-input.md — not a call-time world-state predicate',\n cancel_job:\n 'reads + writes the local sidecar file only; cancel-after-complete is an idempotent no-op (first-wins) so misuse is bounded — no pre-gate needed',\n run_quality_gate:\n 'stateless QA gate over the given projectDir; a missing toolchain (tsc/eslint/vitest/build) surfaces as a check failure in the verdict, not a call-time world-state precondition — no pre-gate needed',\n};\n\n// ============================================================================\n// Middleware\n// ============================================================================\n\n/** Either MCP handler shape, both structurally callable with `(args, ctx?)`. */\ntype AnyToolHandler = ContextAwareToolHandler | ToolHandler;\n/** Concrete callable accepting an optional context — what the gate produces. */\ntype GuardedHandler = (args: unknown, ctx?: unknown) => Promise<ToolResult>;\n\n/**\n * Wrap `handler` so `prereq` is evaluated before it runs. A failing or\n * throwing predicate returns a structured `permission` error envelope\n * (#2649) carrying the failed prerequisite + a remediation hint in\n * `detail` — so the caller knows how to recover, not just that it was\n * blocked. Exported for testing; production code uses `withPrerequisite`.\n */\nexport function applyPrerequisite(\n toolName: string,\n prereq: ToolPrerequisite,\n handler: AnyToolHandler\n): GuardedHandler {\n return async (args: unknown, ctx?: unknown): Promise<ToolResult> => {\n let result: PrerequisiteResult;\n try {\n result = await prereq.check();\n } catch (err) {\n // Fail closed — a predicate that throws blocks the tool.\n result = { ok: false, remediation: `prerequisite check threw: ${getErrorMessage(err)}` };\n }\n if (!result.ok) {\n return toolStructuredError({\n errorCategory: 'permission',\n message: `${toolName} blocked: prerequisite '${prereq.name}' not satisfied`,\n detail: {\n failedPrerequisite: prereq.name,\n rationale: prereq.rationale,\n remediation: result.remediation ?? 'see .rules/tool-prerequisites.md',\n },\n });\n }\n return (handler as GuardedHandler)(args, ctx);\n };\n}\n\n/**\n * Wrap a handler so its tool's prerequisite (if any) is evaluated before\n * the handler runs. Tools with no entry in `TOOL_PREREQUISITES` pass\n * through untouched.\n */\nexport function withPrerequisite(toolName: string, handler: AnyToolHandler): AnyToolHandler {\n const prereq = TOOL_PREREQUISITES[toolName];\n if (prereq === undefined) return handler;\n return applyPrerequisite(toolName, prereq, handler);\n}\n","/**\n * CLI Orchestration Fitness Score — real filesystem analysis.\n * Penalizes duplicate paths, hidden behavior, non-determinism, poor\n * observability, config sprawl, cross-layer coupling. Rewards canonical\n * paths, determinism, telemetry, CLI ergonomics, governance.\n * @module governance/fitness-score\n */\n\n/* eslint-disable max-lines -- cohesive fitness calculator (governance allows 400-600) */\n\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createLogger, type ILogger } from '../core/index.js';\n\n/** Find package root by walking up from current dir to find package.json with our name */\nfunction findPkgRoot(): string {\n let dir = import.meta.dirname;\n for (let i = 0; i < 10; i++) {\n const pkgPath = join(dir, 'package.json');\n if (existsSync(pkgPath)) {\n const content = readFileSync(pkgPath, 'utf-8');\n if (content.includes('\"nexus-agents\"')) return dir;\n }\n dir = join(dir, '..');\n }\n return join(import.meta.dirname, '../..');\n}\n\nconst PKG_ROOT = findPkgRoot();\nconst SRC_ROOT = join(PKG_ROOT, 'src');\nconst REPO_ROOT = join(PKG_ROOT, '../..');\nconst DOCS_ROOT = join(REPO_ROOT, 'docs');\n\nconst DETERMINISM_EXCLUDES: RegExp[] = [\n /\\.test\\.ts$/,\n /\\.spec\\.ts$/,\n /random-provider\\.ts$/,\n /time-provider\\.ts$/,\n];\n\n// =========================================================================\n// Filesystem utility methods (inlined from scripts/fitness-utils.ts)\n// =========================================================================\n\nfunction countFiles(dir: string, pattern: RegExp): number {\n if (!existsSync(dir)) return 0;\n let count = 0;\n for (const entry of readdirSync(dir)) {\n const fullPath = join(dir, entry);\n const stat = statSync(fullPath);\n if (stat.isDirectory() && !entry.startsWith('.')) {\n count += countFiles(fullPath, pattern);\n } else if (pattern.test(entry)) {\n count++;\n }\n }\n return count;\n}\n\nfunction fileContains(filePath: string, pattern: RegExp): boolean {\n if (!existsSync(filePath)) return false;\n return pattern.test(readFileSync(filePath, 'utf-8'));\n}\n\nfunction isExcluded(entry: string, excludePatterns?: RegExp[]): boolean {\n return excludePatterns?.some((p) => p.test(entry)) ?? false;\n}\n\nfunction countMatchesInFile(fullPath: string, contentPattern: RegExp): number {\n const matches = readFileSync(fullPath, 'utf-8').match(contentPattern);\n return matches?.length ?? 0;\n}\n\nfunction countPatternInDir(\n dir: string,\n filePattern: RegExp,\n contentPattern: RegExp,\n excludePatterns?: RegExp[]\n): number {\n if (!existsSync(dir)) return 0;\n let count = 0;\n for (const entry of readdirSync(dir)) {\n const fullPath = join(dir, entry);\n const stat = statSync(fullPath);\n if (stat.isDirectory() && !entry.startsWith('.') && entry !== 'node_modules') {\n count += countPatternInDir(fullPath, filePattern, contentPattern, excludePatterns);\n } else if (filePattern.test(entry) && !isExcluded(entry, excludePatterns)) {\n count += countMatchesInFile(fullPath, contentPattern);\n }\n }\n return count;\n}\n\n// =========================================================================\n// Public types\n// =========================================================================\n\n/**\n * Individual fitness dimension scores.\n */\nexport interface FitnessDimensions {\n /** Penalty: duplicate paths to same workflow (0-20, higher = better) */\n readonly canonicalPaths: number;\n /** Penalty: hidden/magic behavior (0-15, higher = better) */\n readonly explicitBehavior: number;\n /** Reward: deterministic execution (0-15, higher = better) */\n readonly determinism: number;\n /** Reward: observability coverage (0-15, higher = better) */\n readonly observability: number;\n /** Penalty: config surface area (0-10, higher = better) */\n readonly configSimplicity: number;\n /** Penalty: cross-layer coupling (0-10, higher = better) */\n readonly layerSeparation: number;\n /** Reward: CLI ergonomics (0-10, higher = better) */\n readonly operatorErgonomics: number;\n /** Reward: governance injection (0-5, higher = better) */\n readonly governanceIntegration: number;\n}\n\n/**\n * Detailed fitness audit result.\n */\nexport interface FitnessAudit {\n /** Overall score (0-100) */\n readonly score: number;\n /** Individual dimension scores */\n readonly dimensions: FitnessDimensions;\n /** Specific findings */\n readonly findings: readonly FitnessFinding[];\n /** Timestamp of audit */\n readonly timestamp: string;\n /** Version/commit reference */\n readonly version: string;\n}\n\n/**\n * Individual finding from audit.\n */\nexport interface FitnessFinding {\n /** Dimension affected */\n readonly dimension: keyof FitnessDimensions;\n /** Issue severity: 'info' | 'warning' | 'critical' */\n readonly severity: 'info' | 'warning' | 'critical';\n /** Description */\n readonly description: string;\n /** Points deducted */\n readonly pointsDeducted: number;\n /** Location in code (optional) */\n readonly location?: string;\n /** Suggested fix (optional) */\n readonly suggestion?: string;\n}\n\n/**\n * Fitness check definition.\n */\ninterface FitnessCheck {\n readonly dimension: keyof FitnessDimensions;\n readonly maxPoints: number;\n readonly name: string;\n readonly check: () => FitnessCheckResult;\n}\n\n/**\n * Result of a single fitness check.\n */\ninterface FitnessCheckResult {\n readonly score: number;\n readonly findings: FitnessFinding[];\n}\n\n/** Clamp score to [0, max]. */\nfunction clamp(score: number, max: number): number {\n return Math.max(0, Math.min(max, score));\n}\n\n/**\n * CLI Orchestration Fitness Score calculator.\n */\nexport class FitnessScoreCalculator {\n private readonly logger: ILogger;\n private readonly checks: FitnessCheck[] = [];\n\n constructor(logger?: ILogger) {\n this.logger = logger ?? createLogger({ component: 'FitnessScoreCalculator' });\n this.registerDefaultChecks();\n }\n\n /** Register default fitness checks. */\n private registerDefaultChecks(): void {\n const reg = (\n dimension: keyof FitnessDimensions,\n maxPoints: number,\n name: string,\n check: () => FitnessCheckResult\n ): void => {\n this.checks.push({ dimension, maxPoints, name, check });\n };\n reg('canonicalPaths', 20, 'Canonical Paths', () => this.checkCanonicalPaths());\n reg('explicitBehavior', 15, 'Explicit Behavior', () => this.checkExplicitBehavior());\n reg('determinism', 15, 'Determinism', () => this.checkDeterminism());\n reg('observability', 15, 'Observability', () => this.checkObservability());\n reg('configSimplicity', 10, 'Config Simplicity', () => this.checkConfigSimplicity());\n reg('layerSeparation', 10, 'Layer Separation', () => this.checkLayerSeparation());\n reg('operatorErgonomics', 10, 'Operator Ergonomics', () => this.checkOperatorErgonomics());\n reg('governanceIntegration', 5, 'Governance Integration', () =>\n this.checkGovernanceIntegration()\n );\n }\n\n /** Run full fitness audit. */\n audit(version: string): FitnessAudit {\n const findings: FitnessFinding[] = [];\n const dimensions: Record<string, number> = {};\n\n // #2716 — the audit's existsSync checks look at SRC_ROOT-relative paths\n // (cli-adapters/composite-router.ts, cli/doctor.ts, etc). When run from\n // an `npm install -g nexus-agents` copy, SRC_ROOT points at the installed\n // package's `src/` which only contains workflow templates — not the full\n // source tree. Result: every existsSync returns false and the audit\n // emits a parade of fictional \"missing\" findings against a healthy\n // source tree. (`npx nexus-agents fitness-audit` from a repo root hits\n // this path because npx resolves to the GLOBAL bin, not the local\n // workspace bundle.) Bail with a clear single-finding result instead.\n const cliAdaptersDir = join(SRC_ROOT, 'cli-adapters');\n if (!existsSync(cliAdaptersDir)) {\n return this.notSourceRepoResult(version);\n }\n\n for (const check of this.checks) {\n this.logger.debug(`Running fitness check: ${check.name}`);\n const result = check.check();\n dimensions[check.dimension] = result.score;\n findings.push(...result.findings);\n }\n\n const score = Object.values(dimensions).reduce((sum, val) => sum + val, 0);\n this.logger.info('Fitness audit complete', { score, version });\n\n // Build a strictly-typed FitnessDimensions instead of `as unknown as` cast\n // (#1913 Class G). If a check skipped a dimension it defaults to 0,\n // making it explicit rather than UB.\n const safeDim = (k: keyof FitnessDimensions): number => dimensions[k] ?? 0;\n const typedDimensions: FitnessDimensions = {\n canonicalPaths: safeDim('canonicalPaths'),\n explicitBehavior: safeDim('explicitBehavior'),\n determinism: safeDim('determinism'),\n observability: safeDim('observability'),\n configSimplicity: safeDim('configSimplicity'),\n layerSeparation: safeDim('layerSeparation'),\n operatorErgonomics: safeDim('operatorErgonomics'),\n governanceIntegration: safeDim('governanceIntegration'),\n };\n\n return {\n score,\n dimensions: typedDimensions,\n findings,\n timestamp: new Date().toISOString(),\n version,\n };\n }\n\n /**\n * Return when the runtime SRC_ROOT doesn't look like the nexus-agents\n * source tree (#2716). One finding, score 0 — distinct from \"the source\n * tree is broken\" because every existsSync would falsely report missing.\n */\n private notSourceRepoResult(version: string): FitnessAudit {\n const finding: FitnessFinding = {\n dimension: 'governanceIntegration',\n severity: 'info',\n description:\n 'fitness-audit must run against the nexus-agents source repo, ' +\n `but ${SRC_ROOT}/cli-adapters does not exist. You are likely ` +\n 'running the installed npm package via `npx nexus-agents`, which ' +\n 'ships only the bundled dist/. Clone the source repo and run ' +\n '`node packages/nexus-agents/dist/cli.js fitness-audit` (or invoke ' +\n '`pnpm fitness-audit` from the workspace root).',\n pointsDeducted: 0,\n };\n return {\n score: 0,\n dimensions: {\n canonicalPaths: 0,\n explicitBehavior: 0,\n determinism: 0,\n observability: 0,\n configSimplicity: 0,\n layerSeparation: 0,\n operatorErgonomics: 0,\n governanceIntegration: 0,\n },\n findings: [finding],\n timestamp: new Date().toISOString(),\n version,\n };\n }\n\n // =========================================================================\n // Individual Checks — real filesystem analysis\n // =========================================================================\n\n /**\n * Check canonical paths: penalize duplicate router implementations.\n *\n * The current minimum is 6 (raised from 5 in #2063 after an audit):\n * 1. composite-router — pipeline orchestrator\n * 2. budget-router — budget/cost filtering\n * 3. zero-router — hard-constraint exclusion\n * 4. preference-router — user/task preference application\n * 5. topsis-router — TOPSIS multi-criteria scoring\n * 6. agreement-cascade-router — agreement-based cascade retry\n *\n * Each stage is distinct per CLAUDE.md's documented pipeline:\n * Task → BudgetRouter → ZeroRouter → PreferenceRouter → TopsisRouter → Agreement → Model\n */\n private checkCanonicalPaths(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 20;\n\n const routerCount = countFiles(join(SRC_ROOT, 'cli-adapters'), /router\\.ts$/);\n const ROUTER_COUNT_THRESHOLD = 6;\n if (routerCount > ROUTER_COUNT_THRESHOLD) {\n const excess = routerCount - ROUTER_COUNT_THRESHOLD;\n const deduction = Math.min(5, excess);\n score -= deduction;\n findings.push(\n this.finding(\n 'canonicalPaths',\n 'warning',\n `${String(routerCount)} router implementations found (target: <=${String(ROUTER_COUNT_THRESHOLD)})`,\n deduction,\n 'Consolidate duplicate routers into CompositeRouter'\n )\n );\n }\n\n if (existsSync(join(SRC_ROOT, 'cli-adapters/composite-router.ts'))) {\n score += 2;\n } else {\n score -= 3;\n findings.push(\n this.finding(\n 'canonicalPaths',\n 'critical',\n 'CompositeRouter missing — no unified routing entry point',\n 3\n )\n );\n }\n\n score = this.checkOrchestratorInterface(score, findings);\n\n return { score: clamp(score, 20), findings };\n }\n\n /** Sub-check for IOrchestrator interface and adapter wiring. */\n private checkOrchestratorInterface(score: number, findings: FitnessFinding[]): number {\n const orchPath = join(SRC_ROOT, 'core/types/orchestrator.ts');\n if (existsSync(orchPath) && fileContains(orchPath, /interface IOrchestrator/)) {\n score += 3;\n } else {\n score -= 2;\n findings.push(\n this.finding('canonicalPaths', 'warning', 'No IOrchestrator interface in core/types', 2)\n );\n }\n\n const adapterPath = join(SRC_ROOT, 'orchestration/orchestrator-adapters.ts');\n if (existsSync(adapterPath) && fileContains(adapterPath, /TechLeadAdapter|PuppeteerAdapter/)) {\n score += 2;\n }\n\n return score;\n }\n\n /**\n * Check explicit behavior: penalize hidden/magic behavior.\n *\n * Implementation is intentionally filesystem-signal-based (no AST parse).\n * The `NEXUS_ALLOW_MOCK_ORCHESTRATION` guard and magic-routing pattern\n * grep capture the observable failure modes that historically slipped\n * past review. AST-based detection of implicit fallbacks was considered\n * but not pursued — it would significantly widen this function's\n * footprint and the filesystem signals already catch the recurring\n * regressions. Revisit only if a new class of hidden-behavior bug\n * surfaces that this grep-over-source approach can't catch.\n */\n private checkExplicitBehavior(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 15;\n\n // Check: mock orchestration requires explicit env var opt-in\n const mockGuardCount = countPatternInDir(\n SRC_ROOT,\n /\\.ts$/,\n /NEXUS_ALLOW_MOCK_ORCHESTRATION/g,\n DETERMINISM_EXCLUDES\n );\n if (mockGuardCount === 0) {\n score -= 3;\n findings.push(\n this.finding(\n 'explicitBehavior',\n 'warning',\n 'No NEXUS_ALLOW_MOCK_ORCHESTRATION guard found — mock fallback may be implicit',\n 3,\n 'Require explicit env var for mock orchestration'\n )\n );\n }\n\n // Check: magic routing patterns (delegate without explicit capability match)\n const magicRouting = countPatternInDir(\n SRC_ROOT,\n /\\.ts$/,\n /fallback.*=.*true|implicitRoute/g,\n DETERMINISM_EXCLUDES\n );\n if (magicRouting > 5) {\n const deduction = Math.min(3, Math.floor(magicRouting / 3));\n score -= deduction;\n findings.push(\n this.finding(\n 'explicitBehavior',\n 'info',\n `${String(magicRouting)} implicit fallback/routing patterns detected`,\n deduction\n )\n );\n }\n\n return { score: clamp(score, 15), findings };\n }\n\n /** Check determinism: penalize unseeded random and raw Date.now(). */\n private checkDeterminism(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 15;\n\n score = this.checkRandomDeterminism(score, findings);\n score = this.checkTimeDeterminism(score, findings);\n\n return { score: clamp(score, 15), findings };\n }\n\n /** Sub-check for Math.random() and injectable random provider. */\n private checkRandomDeterminism(score: number, findings: FitnessFinding[]): number {\n const randomCount = countPatternInDir(\n SRC_ROOT,\n /\\.ts$/,\n /Math\\.random\\(\\)/g,\n DETERMINISM_EXCLUDES\n );\n if (randomCount > 10) {\n const deduction = Math.min(5, Math.floor(randomCount / 5));\n score -= deduction;\n findings.push(\n this.finding(\n 'determinism',\n 'warning',\n `${String(randomCount)} unseeded Math.random() calls in production code`,\n deduction,\n 'Use getRandomProvider() for injectable randomness'\n )\n );\n } else if (randomCount === 0) {\n score += 2;\n }\n\n if (existsSync(join(SRC_ROOT, 'core/random-provider.ts'))) {\n score += 1;\n }\n const randomUsage = countPatternInDir(\n SRC_ROOT,\n /\\.ts$/,\n /getRandomProvider\\(\\)/g,\n DETERMINISM_EXCLUDES\n );\n if (randomUsage > 5) {\n score += 1;\n }\n\n return score;\n }\n\n /** Sub-check for Date.now() and injectable time provider. */\n private checkTimeDeterminism(score: number, findings: FitnessFinding[]): number {\n const dateNowCount = countPatternInDir(\n SRC_ROOT,\n /\\.ts$/,\n /Date\\.now\\(\\)/g,\n DETERMINISM_EXCLUDES\n );\n if (dateNowCount > 50) {\n score -= 2;\n findings.push(\n this.finding(\n 'determinism',\n 'info',\n `${String(dateNowCount)} Date.now() calls in production code`,\n 2,\n 'Use getTimeProvider() for injectable time'\n )\n );\n }\n\n if (existsSync(join(SRC_ROOT, 'core/time-provider.ts'))) {\n score += 1;\n }\n const timeUsage = countPatternInDir(\n SRC_ROOT,\n /\\.ts$/,\n /getTimeProvider\\(\\)/g,\n DETERMINISM_EXCLUDES\n );\n if (timeUsage > 10) {\n score += 1;\n }\n\n return score;\n }\n\n /** Check observability: reward tracing, logging, and audit coverage. */\n private checkObservability(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 15;\n\n if (existsSync(join(SRC_ROOT, 'observability/swarm-observer.ts'))) {\n score += 3;\n } else {\n score -= 3;\n findings.push(\n this.finding(\n 'observability',\n 'warning',\n 'No SwarmObserver found',\n 3,\n 'Add observability/swarm-observer.ts'\n )\n );\n }\n\n if (existsSync(join(SRC_ROOT, 'core/trace.ts'))) {\n score += 2;\n }\n\n const loggerCount = countPatternInDir(SRC_ROOT, /\\.ts$/, /createLogger\\(/g);\n if (loggerCount > 50) {\n score += 2;\n } else {\n findings.push(\n this.finding(\n 'observability',\n 'info',\n `Only ${String(loggerCount)} createLogger() calls (target: >50)`,\n 0\n )\n );\n }\n\n if (existsSync(join(SRC_ROOT, 'audit'))) {\n score += 2;\n }\n\n return { score: clamp(score, 15), findings };\n }\n\n /** Check config simplicity: penalize excessive schema sprawl. */\n private checkConfigSimplicity(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 10;\n\n const schemaCount = countFiles(join(SRC_ROOT, 'config'), /schema.*\\.ts$/);\n if (schemaCount > 10) {\n score -= 2;\n findings.push(\n this.finding(\n 'configSimplicity',\n 'info',\n `${String(schemaCount)} config schemas (target: <=10)`,\n 2,\n 'Consolidate related schemas'\n )\n );\n } else {\n score += 1;\n }\n\n if (existsSync(join(SRC_ROOT, 'config/config-loader.ts'))) {\n score += 2;\n }\n if (existsSync(join(SRC_ROOT, 'config/config-manager.ts'))) {\n score += 1;\n }\n\n return { score: clamp(score, 10), findings };\n }\n\n /** Check layer separation: penalize cross-layer imports. */\n private checkLayerSeparation(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 10;\n\n const adapterAgentImports = countPatternInDir(\n join(SRC_ROOT, 'adapters'),\n /\\.ts$/,\n /from ['\"]\\.\\.\\/agents\\//g\n );\n if (adapterAgentImports > 0) {\n const deduction = Math.min(5, adapterAgentImports);\n score -= deduction;\n findings.push(\n this.finding(\n 'layerSeparation',\n 'warning',\n `${String(adapterAgentImports)} adapter->agent import violations`,\n deduction,\n 'Adapters should not import from agents layer'\n )\n );\n } else {\n score += 2;\n }\n\n const coreMcpImports = countPatternInDir(\n join(SRC_ROOT, 'core'),\n /\\.ts$/,\n /from ['\"]\\.\\.\\/mcp\\//g\n );\n if (coreMcpImports > 0) {\n const deduction = Math.min(3, coreMcpImports);\n score -= deduction;\n findings.push(\n this.finding(\n 'layerSeparation',\n 'critical',\n `${String(coreMcpImports)} core->MCP import violations`,\n deduction,\n 'Core must not depend on MCP layer'\n )\n );\n } else {\n score += 1;\n }\n\n return { score: clamp(score, 10), findings };\n }\n\n /** Check operator ergonomics: reward rich CLI commands. */\n private checkOperatorErgonomics(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 10;\n\n const commandCount = countFiles(join(SRC_ROOT, 'cli'), /\\.ts$/);\n if (commandCount >= 20) {\n score += 3;\n } else {\n findings.push(\n this.finding(\n 'operatorErgonomics',\n 'info',\n `${String(commandCount)} CLI commands (target: >=20)`,\n 0\n )\n );\n }\n\n score = this.checkCliCommands(score, findings);\n\n return { score: clamp(score, 10), findings };\n }\n\n /** Sub-check for essential CLI commands (doctor, setup, demo, config). */\n private checkCliCommands(score: number, findings: FitnessFinding[]): number {\n const commands: Array<[string, string, number]> = [\n ['cli/doctor.ts', 'Doctor command', 2],\n ['cli/setup-command.ts', 'Setup wizard', 2],\n ['cli/demo-command.ts', 'Demo command', 1],\n ['cli/config-command.ts', 'Config command', 1],\n ];\n\n for (const [path, name, bonus] of commands) {\n if (existsSync(join(SRC_ROOT, path))) {\n score += bonus;\n } else {\n findings.push(this.finding('operatorErgonomics', 'info', `Missing ${name} (${path})`, 0));\n }\n }\n\n return score;\n }\n\n /** Check governance integration: policy firewall, rate limiter, docs. */\n private checkGovernanceIntegration(): FitnessCheckResult {\n const findings: FitnessFinding[] = [];\n let score = 5;\n\n score = this.checkGovernanceDocs(score, findings);\n score = this.checkGovernanceInfra(score, findings);\n\n return { score: clamp(score, 5), findings };\n }\n\n /** Sub-check for governance documentation artifacts. */\n private checkGovernanceDocs(score: number, findings: FitnessFinding[]): number {\n if (!existsSync(join(REPO_ROOT, 'CLAUDE.md'))) {\n score -= 3;\n findings.push(\n this.finding('governanceIntegration', 'critical', 'No CLAUDE.md governance document', 3)\n );\n } else {\n score += 1;\n }\n\n if (existsSync(join(DOCS_ROOT, 'architecture/wiring-graph.json'))) {\n score += 1;\n }\n\n if (existsSync(join(DOCS_ROOT, 'adr'))) {\n score += 1;\n } else {\n findings.push(this.finding('governanceIntegration', 'info', 'No ADR directory', 0));\n }\n\n return score;\n }\n\n /** Sub-check for governance runtime infrastructure. */\n private checkGovernanceInfra(score: number, findings: FitnessFinding[]): number {\n const hasPolicyFirewall =\n countPatternInDir(join(SRC_ROOT, 'security'), /\\.ts$/, /PolicyGate|policyFirewall/g) > 0;\n if (hasPolicyFirewall) {\n score += 1;\n } else {\n findings.push(\n this.finding(\n 'governanceIntegration',\n 'warning',\n 'No policy firewall detected in security layer',\n 0\n )\n );\n }\n\n const hasRateLimiter = countPatternInDir(SRC_ROOT, /\\.ts$/, /RateLimiter|rateLimiter/g) > 0;\n if (hasRateLimiter) {\n score += 1;\n }\n\n return score;\n }\n\n /** Helper to create a FitnessFinding with defaults. */\n private finding(\n dimension: keyof FitnessDimensions,\n severity: FitnessFinding['severity'],\n description: string,\n pointsDeducted: number,\n suggestion?: string\n ): FitnessFinding {\n const base: FitnessFinding = { dimension, severity, description, pointsDeducted };\n if (suggestion !== undefined) {\n return { ...base, suggestion };\n }\n return base;\n }\n}\n\n/**\n * Create a fitness score calculator.\n */\nexport function createFitnessScoreCalculator(logger?: ILogger): FitnessScoreCalculator {\n return new FitnessScoreCalculator(logger);\n}\n\n/**\n * Quick function to get current fitness score.\n */\nexport function calculateFitnessScore(version: string): FitnessAudit {\n const calculator = createFitnessScoreCalculator();\n return calculator.audit(version);\n}\n","/**\n * improvement_review → pipeline-bus signal emitter (#3147, epic #3143 P2).\n *\n * Emits `signal.fitness_declined` onto the typed pipeline event bus when the\n * fitness audit score falls below the governance floor. Runs in the\n * `improvement_review` MCP tool (server context), so the live shadow TuneStage\n * consumes it. Lives at the MCP layer to keep `governance/fitness-score`\n * decoupled from the pipeline bus, preserving the `A = observability /\n * B = messaging` boundary adopted for #3289 (scope Option 2).\n *\n * @module mcp/tools/improvement-review-signals\n */\n\nimport { getErrorMessage, getTimeProvider } from '../../core/index.js';\nimport type { ILogger } from '../../core/index.js';\nimport type { FitnessAudit } from '../../governance/fitness-score.js';\nimport type { IEventBus } from '../../pipeline/event-types.js';\n\n/** The dimension of the finding that deducted the most points, if any. */\nfunction worstDimension(audit: FitnessAudit): string | undefined {\n let worst: { dimension: string; pointsDeducted: number } | undefined;\n for (const finding of audit.findings) {\n if (worst === undefined || finding.pointsDeducted > worst.pointsDeducted) {\n worst = { dimension: finding.dimension, pointsDeducted: finding.pointsDeducted };\n }\n }\n return worst?.dimension;\n}\n\n/**\n * Emit `signal.fitness_declined` onto `bus` when `audit.score < fitnessFloor`.\n * No-op at or above floor. Emission errors are swallowed and logged — signalling\n * must never break the improvement-review path.\n */\nexport function emitFitnessDeclinedSignal(\n audit: FitnessAudit,\n fitnessFloor: number,\n bus: IEventBus,\n logger: ILogger\n): void {\n if (audit.score >= fitnessFloor) return;\n try {\n const dimension = worstDimension(audit);\n bus.emit({\n type: 'signal.fitness_declined',\n timestamp: getTimeProvider().now(),\n score: audit.score,\n floor: fitnessFloor,\n ...(dimension !== undefined ? { dimension } : {}),\n });\n } catch (error) {\n logger.warn('Failed to emit signal.fitness_declined', { error: getErrorMessage(error) });\n }\n}\n"],"mappings":"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","names":["execFile","promisify","description","execFileAsync","promisify","execFile"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|