nexus-agents 2.97.1 → 2.99.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/{child-mcp-config-WVPJIK2J.js → child-mcp-config-OWCVT4NN.js} +2 -2
- package/dist/{chunk-D3OT7TOA.js → chunk-3XSEFOI5.js} +3 -3
- package/dist/{chunk-KKVH3PDK.js → chunk-5T6S6HFY.js} +4 -4
- package/dist/{chunk-T5TYWM5S.js → chunk-5WY3N7VX.js} +2 -2
- package/dist/{chunk-6IN4MKDA.js → chunk-6IHEDRKI.js} +7 -7
- package/dist/{chunk-674NONPG.js → chunk-A7XUXJWL.js} +2 -2
- package/dist/{chunk-HZGHPBTV.js → chunk-AH67WRET.js} +2 -2
- package/dist/{chunk-T7IIFT3B.js → chunk-AN3IGMJT.js} +10 -10
- package/dist/{chunk-WXDWDGVL.js → chunk-BKUKBOGV.js} +2 -2
- package/dist/{chunk-GERVGPTF.js → chunk-BO6QUVXI.js} +2 -2
- package/dist/{chunk-OSHCOBDK.js → chunk-CJODZY4U.js} +2 -2
- package/dist/{chunk-HIWO2WWP.js → chunk-DLNCQO6L.js} +2 -2
- package/dist/{chunk-ML4IF3PS.js → chunk-EM7NUGMG.js} +22 -5
- package/dist/{chunk-ML4IF3PS.js.map → chunk-EM7NUGMG.js.map} +1 -1
- package/dist/{chunk-N5656LE3.js → chunk-HBZUXO4Q.js} +2 -2
- package/dist/{chunk-NTBVUWU4.js → chunk-HFNHJZOK.js} +2 -2
- package/dist/{chunk-EY7LL4F4.js → chunk-J545CO5K.js} +2 -2
- package/dist/{chunk-65LE457J.js → chunk-J76KHBF3.js} +2 -2
- package/dist/{chunk-5LGAPYX7.js → chunk-JFFI54DW.js} +12 -2
- package/dist/{chunk-5LGAPYX7.js.map → chunk-JFFI54DW.js.map} +1 -1
- package/dist/{chunk-JTQLV374.js → chunk-M774MKHE.js} +3 -2
- package/dist/chunk-M774MKHE.js.map +1 -0
- package/dist/{chunk-FB6AQ2SF.js → chunk-O6EXYWHP.js} +428 -212
- package/dist/chunk-O6EXYWHP.js.map +1 -0
- package/dist/{chunk-SAUBPHQ7.js → chunk-Q3IFS7UA.js} +4 -4
- package/dist/{chunk-HWCMNFIS.js → chunk-SU7RKNIZ.js} +3 -3
- package/dist/{chunk-7BLBXITB.js → chunk-T5KDRR2I.js} +3 -3
- package/dist/{chunk-FDTIRCSL.js → chunk-UWQ3BALH.js} +2 -2
- package/dist/{chunk-E43RUPLP.js → chunk-V2C2MC6H.js} +3 -3
- package/dist/{chunk-SZNNT2DH.js → chunk-VD4TXDMR.js} +2 -2
- package/dist/{chunk-5F7LHFAU.js → chunk-VPH2M5H7.js} +7 -7
- package/dist/{chunk-Y4TTYQUK.js → chunk-WHFCVKAV.js} +5 -5
- package/dist/{chunk-JX6VL7JF.js → chunk-WYDK6V7W.js} +3 -3
- package/dist/{chunk-UNOOL6EN.js → chunk-XO25FS24.js} +2 -2
- package/dist/{chunk-P2BKWVKF.js → chunk-YREYQSYA.js} +3 -3
- package/dist/chunk-YREYQSYA.js.map +1 -0
- package/dist/{chunk-IHKPGTF3.js → chunk-ZOBDTJNG.js} +4 -4
- package/dist/{chunk-OKRTOMKX.js → chunk-ZPCDZMLK.js} +2 -2
- package/dist/{cli-circuit-breaker-STKW4DTL.js → cli-circuit-breaker-IPNNNVIT.js} +4 -4
- package/dist/cli.js +41 -39
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-POFAM7T4.js → composite-router-JJNQIHX6.js} +2 -2
- package/dist/{consensus-vote-F6HORSU6.js → consensus-vote-5D7FNWYM.js} +13 -13
- package/dist/{context-retriever-H22L3WFV.js → context-retriever-2MOJ446P.js} +6 -6
- package/dist/{doctor-deep-HGAC6N5Y.js → doctor-deep-D6E5IWXB.js} +3 -3
- package/dist/{expert-bridge-IAQPOJAQ.js → expert-bridge-EOVHUCJ4.js} +4 -4
- package/dist/{factory-ZIZYUDKH.js → factory-NJRJAZKK.js} +5 -5
- package/dist/{factory-P2SQS7UM.js → factory-UCRIJY6Y.js} +5 -5
- package/dist/{improvement-review-G2HAMGZP.js → improvement-review-IWV2BMR7.js} +4 -4
- package/dist/index.js +28 -28
- package/dist/{init-opencode-RHCYZDZW.js → init-opencode-PB4G7RJR.js} +5 -5
- package/dist/{issue-triage-VVNQIQW5.js → issue-triage-EMYHDDTR.js} +5 -5
- package/dist/{pr-reviewer-helpers-UN7RDPDN.js → pr-reviewer-helpers-DZQDKMMF.js} +4 -4
- package/dist/{registry-command-OVRRKYHO.js → registry-command-AX7Z4K4W.js} +47 -243
- package/dist/registry-command-AX7Z4K4W.js.map +1 -0
- package/dist/{repo-security-plan-X74TBYOV.js → repo-security-plan-N2GNWFER.js} +3 -3
- package/dist/{research-helpers-synthesize-OSP6FGNV.js → research-helpers-synthesize-OKNU245Z.js} +3 -3
- package/dist/{routing-memory-5T5QJF47.js → routing-memory-3QXWGWB5.js} +2 -2
- package/dist/{session-memory-X7CJ6X4A.js → session-memory-AK4AJXGI.js} +3 -3
- package/dist/{setup-command-7KP3O3P3.js → setup-command-PHTP43V7.js} +11 -11
- package/dist/{setup-config-YVIKUNOB.js → setup-config-ANAFKZGE.js} +3 -3
- package/dist/{setup-custom-api-FLV4SELI.js → setup-custom-api-FUA2ZUDD.js} +4 -4
- package/dist/{tool-memory-QNEAKRKV.js → tool-memory-ZP3EMUP5.js} +5 -5
- package/dist/{weather-report-SUVIXWKI.js → weather-report-54XDO6GO.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-FB6AQ2SF.js.map +0 -1
- package/dist/chunk-JTQLV374.js.map +0 -1
- package/dist/chunk-P2BKWVKF.js.map +0 -1
- package/dist/registry-command-OVRRKYHO.js.map +0 -1
- /package/dist/{child-mcp-config-WVPJIK2J.js.map → child-mcp-config-OWCVT4NN.js.map} +0 -0
- /package/dist/{chunk-D3OT7TOA.js.map → chunk-3XSEFOI5.js.map} +0 -0
- /package/dist/{chunk-KKVH3PDK.js.map → chunk-5T6S6HFY.js.map} +0 -0
- /package/dist/{chunk-T5TYWM5S.js.map → chunk-5WY3N7VX.js.map} +0 -0
- /package/dist/{chunk-6IN4MKDA.js.map → chunk-6IHEDRKI.js.map} +0 -0
- /package/dist/{chunk-674NONPG.js.map → chunk-A7XUXJWL.js.map} +0 -0
- /package/dist/{chunk-HZGHPBTV.js.map → chunk-AH67WRET.js.map} +0 -0
- /package/dist/{chunk-T7IIFT3B.js.map → chunk-AN3IGMJT.js.map} +0 -0
- /package/dist/{chunk-WXDWDGVL.js.map → chunk-BKUKBOGV.js.map} +0 -0
- /package/dist/{chunk-GERVGPTF.js.map → chunk-BO6QUVXI.js.map} +0 -0
- /package/dist/{chunk-OSHCOBDK.js.map → chunk-CJODZY4U.js.map} +0 -0
- /package/dist/{chunk-HIWO2WWP.js.map → chunk-DLNCQO6L.js.map} +0 -0
- /package/dist/{chunk-N5656LE3.js.map → chunk-HBZUXO4Q.js.map} +0 -0
- /package/dist/{chunk-NTBVUWU4.js.map → chunk-HFNHJZOK.js.map} +0 -0
- /package/dist/{chunk-EY7LL4F4.js.map → chunk-J545CO5K.js.map} +0 -0
- /package/dist/{chunk-65LE457J.js.map → chunk-J76KHBF3.js.map} +0 -0
- /package/dist/{chunk-SAUBPHQ7.js.map → chunk-Q3IFS7UA.js.map} +0 -0
- /package/dist/{chunk-HWCMNFIS.js.map → chunk-SU7RKNIZ.js.map} +0 -0
- /package/dist/{chunk-7BLBXITB.js.map → chunk-T5KDRR2I.js.map} +0 -0
- /package/dist/{chunk-FDTIRCSL.js.map → chunk-UWQ3BALH.js.map} +0 -0
- /package/dist/{chunk-E43RUPLP.js.map → chunk-V2C2MC6H.js.map} +0 -0
- /package/dist/{chunk-SZNNT2DH.js.map → chunk-VD4TXDMR.js.map} +0 -0
- /package/dist/{chunk-5F7LHFAU.js.map → chunk-VPH2M5H7.js.map} +0 -0
- /package/dist/{chunk-Y4TTYQUK.js.map → chunk-WHFCVKAV.js.map} +0 -0
- /package/dist/{chunk-JX6VL7JF.js.map → chunk-WYDK6V7W.js.map} +0 -0
- /package/dist/{chunk-UNOOL6EN.js.map → chunk-XO25FS24.js.map} +0 -0
- /package/dist/{chunk-IHKPGTF3.js.map → chunk-ZOBDTJNG.js.map} +0 -0
- /package/dist/{chunk-OKRTOMKX.js.map → chunk-ZPCDZMLK.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-STKW4DTL.js.map → cli-circuit-breaker-IPNNNVIT.js.map} +0 -0
- /package/dist/{composite-router-POFAM7T4.js.map → composite-router-JJNQIHX6.js.map} +0 -0
- /package/dist/{consensus-vote-F6HORSU6.js.map → consensus-vote-5D7FNWYM.js.map} +0 -0
- /package/dist/{context-retriever-H22L3WFV.js.map → context-retriever-2MOJ446P.js.map} +0 -0
- /package/dist/{doctor-deep-HGAC6N5Y.js.map → doctor-deep-D6E5IWXB.js.map} +0 -0
- /package/dist/{expert-bridge-IAQPOJAQ.js.map → expert-bridge-EOVHUCJ4.js.map} +0 -0
- /package/dist/{factory-P2SQS7UM.js.map → factory-NJRJAZKK.js.map} +0 -0
- /package/dist/{factory-ZIZYUDKH.js.map → factory-UCRIJY6Y.js.map} +0 -0
- /package/dist/{improvement-review-G2HAMGZP.js.map → improvement-review-IWV2BMR7.js.map} +0 -0
- /package/dist/{init-opencode-RHCYZDZW.js.map → init-opencode-PB4G7RJR.js.map} +0 -0
- /package/dist/{issue-triage-VVNQIQW5.js.map → issue-triage-EMYHDDTR.js.map} +0 -0
- /package/dist/{pr-reviewer-helpers-UN7RDPDN.js.map → pr-reviewer-helpers-DZQDKMMF.js.map} +0 -0
- /package/dist/{repo-security-plan-X74TBYOV.js.map → repo-security-plan-N2GNWFER.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-OSP6FGNV.js.map → research-helpers-synthesize-OKNU245Z.js.map} +0 -0
- /package/dist/{routing-memory-5T5QJF47.js.map → routing-memory-3QXWGWB5.js.map} +0 -0
- /package/dist/{session-memory-X7CJ6X4A.js.map → session-memory-AK4AJXGI.js.map} +0 -0
- /package/dist/{setup-command-7KP3O3P3.js.map → setup-command-PHTP43V7.js.map} +0 -0
- /package/dist/{setup-config-YVIKUNOB.js.map → setup-config-ANAFKZGE.js.map} +0 -0
- /package/dist/{setup-custom-api-FLV4SELI.js.map → setup-custom-api-FUA2ZUDD.js.map} +0 -0
- /package/dist/{tool-memory-QNEAKRKV.js.map → tool-memory-ZP3EMUP5.js.map} +0 -0
- /package/dist/{weather-report-SUVIXWKI.js.map → weather-report-54XDO6GO.js.map} +0 -0
|
@@ -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 { 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';\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 * 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 * 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 const signals: ImprovementSignal[] = [\n ...detectCliPerformanceFloor(windowed, minSampleSize, windowLabel),\n ...detectFailureCategoryConcentration(windowed, windowLabel),\n ...detectFitnessSignals(audit, fitnessFloor),\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 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};\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"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/registry-command.ts","../src/config/capability-discovery.ts","../src/config/capability-overlay.ts"],"sourcesContent":["/**\n * `nexus-agents registry` CLI subcommands (epic #2174 / issue #2179).\n *\n * Two subcommands:\n *\n * - `doctor` — inspect CapabilityDiscovery state: tier counts, overlay /\n * bundled paths and status, configured conservative default. Surfaces\n * whatever T3 overlay parse rejections occurred at load. Read-only.\n *\n * - `refresh` — download a signed `model-registry.generated.json` from a\n * URL, SHA256-verify against a `.sha256` sidecar, write to the user's\n * overlay location. Requires `--source=<url>` today; the GitHub-latest-\n * release automation is #2180's concern.\n *\n * No runtime hot path touches the network — refresh is a one-shot,\n * user-initiated operation.\n *\n * @module cli/registry-command\n */\n\nimport { createHash } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { nexusDataPath } from '../config/nexus-data-dir.js';\n\nimport {\n defaultGeneratedRegistryPath,\n getCapabilityDiscovery,\n loadBundledGeneratedRegistry,\n type ResolutionTier,\n} from '../config/capability-discovery.js';\nimport {\n OVERLAY_ENV_VAR,\n OVERLAY_MAX_BYTES,\n defaultOverlayPath,\n loadCapabilityOverlay,\n resolveOverlayPath,\n} from '../config/capability-overlay.js';\n\n// ---------------------------------------------------------------------------\n// Dispatch\n// ---------------------------------------------------------------------------\n\nexport type RegistrySubcommand = 'doctor' | 'refresh';\n\nconst VALID_SUBCOMMANDS: readonly RegistrySubcommand[] = ['doctor', 'refresh'];\n\nexport function isValidRegistrySubcommand(v: string | undefined): v is RegistrySubcommand {\n return v !== undefined && (VALID_SUBCOMMANDS as readonly string[]).includes(v);\n}\n\nexport interface RegistryCommandOptions {\n readonly json?: boolean;\n readonly source?: string;\n readonly dryRun?: boolean;\n readonly overlayPath?: string;\n /** For tests: a fetch function. Defaults to `globalThis.fetch`. */\n readonly fetchImpl?: typeof fetch;\n /** For tests: override the default destination path. */\n readonly destPath?: string;\n}\n\nexport interface RegistryCommandResult {\n readonly text: string;\n readonly exitCode: number;\n}\n\nexport async function registryCommand(\n subcommand: RegistrySubcommand,\n options: RegistryCommandOptions = {}\n): Promise<RegistryCommandResult> {\n if (subcommand === 'doctor') return doctorCommand(options);\n return refreshCommand(options);\n}\n\n// ---------------------------------------------------------------------------\n// doctor\n// ---------------------------------------------------------------------------\n\ninterface DoctorReport {\n readonly tierCounts: Record<ResolutionTier, number>;\n readonly bundled: {\n readonly path: string;\n readonly present: boolean;\n readonly entryCount: number | null;\n readonly generatedAt: string | null;\n };\n readonly overlay: {\n readonly path: string;\n readonly status: 'missing' | 'empty' | 'malformed' | 'too-large' | 'loaded';\n readonly entryCount: number;\n readonly rejections: readonly { index: number; id?: string; reason: string }[];\n readonly envOverride: string | undefined;\n };\n readonly conservativeDefault: {\n readonly contextWindow: number;\n readonly maxOutputTokens: number | null;\n };\n}\n\nfunction doctorCommand(options: RegistryCommandOptions): RegistryCommandResult {\n const report = buildDoctorReport(options);\n if (options.json === true) {\n return { text: JSON.stringify(report, null, 2), exitCode: 0 };\n }\n return { text: formatDoctorReport(report), exitCode: 0 };\n}\n\nfunction buildDoctorReport(options: RegistryCommandOptions): DoctorReport {\n const bundledPath = defaultGeneratedRegistryPath();\n const bundled = loadBundledGeneratedRegistry(bundledPath);\n const overlay = loadCapabilityOverlay(options.overlayPath ?? process.env);\n const discovery = getCapabilityDiscovery();\n const fallback = discovery.getConservativeDefault();\n\n return {\n tierCounts: discovery.getTierCounts(),\n bundled: {\n path: bundledPath,\n present: bundled !== null,\n entryCount: bundled !== null ? bundled.entryCount : null,\n generatedAt: bundled !== null ? bundled.generatedAt : null,\n },\n overlay: {\n path: overlay.path,\n status: overlay.status,\n entryCount: overlay.entries.length,\n rejections: overlay.rejections.map((r) => ({\n index: r.index,\n ...(r.id !== undefined ? { id: r.id } : {}),\n reason: r.reason,\n })),\n envOverride: process.env[OVERLAY_ENV_VAR],\n },\n conservativeDefault: {\n contextWindow: fallback.contextWindow,\n maxOutputTokens: fallback.maxOutputTokens ?? null,\n },\n };\n}\n\nfunction formatDoctorReport(r: DoctorReport): string {\n const lines: string[] = [];\n lines.push('nexus-agents registry doctor');\n lines.push('============================');\n lines.push('');\n lines.push('Tier counts (T3 overlay → T1 canonical → T2 bundled → T4 fallback):');\n lines.push(` T3 overlay : ${String(r.tierCounts.t3)}`);\n lines.push(` T1 canonical : ${String(r.tierCounts.t1)}`);\n lines.push(` T2 bundled : ${String(r.tierCounts.t2)}`);\n lines.push('');\n lines.push('T2 bundled registry:');\n lines.push(` path : ${r.bundled.path}`);\n lines.push(` present : ${r.bundled.present ? 'yes' : 'no (using T1 + T4 only)'}`);\n if (r.bundled.present) {\n lines.push(` entryCount : ${String(r.bundled.entryCount ?? '?')}`);\n lines.push(` generatedAt : ${r.bundled.generatedAt ?? '?'}`);\n }\n lines.push('');\n lines.push('T3 user overlay:');\n lines.push(` path : ${r.overlay.path}`);\n lines.push(` status : ${r.overlay.status}`);\n lines.push(` entryCount : ${String(r.overlay.entryCount)}`);\n lines.push(` env override: ${r.overlay.envOverride ?? '(not set)'}`);\n if (r.overlay.rejections.length > 0) {\n lines.push(' rejections :');\n for (const rej of r.overlay.rejections) {\n const idPart = rej.id !== undefined ? ` id=${rej.id}` : '';\n lines.push(` - [${String(rej.index)}]${idPart} ${rej.reason}`);\n }\n }\n lines.push('');\n lines.push('T4 conservative default (for unknown ids):');\n lines.push(` contextWindow : ${String(r.conservativeDefault.contextWindow)}`);\n if (r.conservativeDefault.maxOutputTokens !== null) {\n lines.push(` maxOutputTokens: ${String(r.conservativeDefault.maxOutputTokens)}`);\n }\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// refresh\n// ---------------------------------------------------------------------------\n\nconst MAX_REFRESH_BYTES = 5 * 1024 * 1024;\n\nfunction missingSourceResult(): RegistryCommandResult {\n return {\n text: [\n 'registry refresh requires --source=<url>.',\n '',\n 'The url should point at a model-registry.generated.json file with a',\n 'matching <url>.sha256 sidecar (single line containing the SHA256 hash).',\n '',\n 'A signed GitHub release artifact is a planned default but not wired yet;',\n `that is tracked in #2180. Use --source=<your-mirror-url> in the meantime.`,\n ].join('\\n'),\n exitCode: 2,\n };\n}\n\ninterface VerifiedArtifact {\n readonly body: string;\n readonly sha256: string;\n}\n\nasync function fetchAndVerify(\n source: string,\n fetchImpl: typeof fetch\n): Promise<VerifiedArtifact | RegistryCommandResult> {\n const body = await fetchWithCap(source, fetchImpl);\n if (!body.ok || body.body === undefined) {\n return { text: `Failed to fetch ${source}: ${body.error ?? 'unknown'}`, exitCode: 1 };\n }\n const sha = await fetchWithCap(`${source}.sha256`, fetchImpl);\n if (!sha.ok || sha.body === undefined) {\n return {\n text: `Failed to fetch ${source}.sha256 for integrity check: ${sha.error ?? 'unknown'}`,\n exitCode: 1,\n };\n }\n const expected = sha.body.trim().split(/\\s+/)[0] ?? '';\n if (expected === '') {\n return { text: `SHA256 sidecar at ${source}.sha256 is empty`, exitCode: 1 };\n }\n const actual = createHash('sha256').update(body.body, 'utf-8').digest('hex');\n if (actual.toLowerCase() !== expected.toLowerCase()) {\n return {\n text: `SHA256 mismatch: expected ${expected}, got ${actual}. Aborting write.`,\n exitCode: 1,\n };\n }\n return { body: body.body, sha256: actual };\n}\n\nfunction formatRefreshReport(\n verb: 'would write to' | 'wrote to',\n source: string,\n artifact: VerifiedArtifact,\n dest: string,\n extraTail: readonly string[] = []\n): string {\n return [\n `registry refresh${verb.startsWith('would') ? ' --dry-run' : ''}`,\n `source : ${source}`,\n `sha256 : ${artifact.sha256} (verified)`,\n `bytes : ${String(artifact.body.length)}`,\n `${verb}: ${dest}`,\n ...extraTail,\n ].join('\\n');\n}\n\nasync function refreshCommand(options: RegistryCommandOptions): Promise<RegistryCommandResult> {\n const source = options.source;\n if (source === undefined || source === '') return missingSourceResult();\n\n const artifact = await fetchAndVerify(source, options.fetchImpl ?? fetch);\n if ('text' in artifact) return artifact;\n\n const dest = options.destPath ?? nexusDataPath('model-registry.generated.json');\n if (options.dryRun === true) {\n return { text: formatRefreshReport('would write to', source, artifact, dest), exitCode: 0 };\n }\n\n mkdirSync(dirname(dest), { recursive: true });\n writeFileSync(dest, artifact.body, 'utf-8');\n return {\n text: formatRefreshReport('wrote to', source, artifact, dest, [\n '',\n 'The refreshed file takes precedence over the bundled registry on the next',\n 'run. Restart any running CLI / MCP server for the change to take effect.',\n ]),\n exitCode: 0,\n };\n}\n\ninterface FetchResult {\n readonly ok: boolean;\n readonly body?: string;\n readonly error?: string;\n}\n\nasync function fetchWithCap(url: string, fetchImpl: typeof fetch): Promise<FetchResult> {\n try {\n const response = await fetchImpl(url, { signal: AbortSignal.timeout(30_000) });\n if (!response.ok) {\n return { ok: false, error: `HTTP ${String(response.status)}` };\n }\n const body = await response.text();\n if (body.length > MAX_REFRESH_BYTES) {\n return {\n ok: false,\n error: `payload ${String(body.length)} bytes exceeds cap ${String(MAX_REFRESH_BYTES)}`,\n };\n }\n return { ok: true, body };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, error: message };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Usage\n// ---------------------------------------------------------------------------\n\nexport function formatRegistryUsage(): string {\n return [\n 'Usage:',\n ' nexus-agents registry doctor [--json]',\n ' Inspect the four-tier capability discovery state.',\n '',\n ' nexus-agents registry refresh --source=<url> [--dry-run]',\n ' Download a signed model-registry.generated.json from <url>,',\n ' SHA256-verify against <url>.sha256, and write to:',\n ` ${nexusDataPath('model-registry.generated.json')}`,\n '',\n `Overlay path (T3) is ${defaultOverlayPath()} by default,`,\n `or whatever ${OVERLAY_ENV_VAR} points to. Overlay max size is ${String(OVERLAY_MAX_BYTES)} bytes.`,\n ].join('\\n');\n}\n\n// Dummy references to satisfy unused-var lint when destructuring is conditional.\nvoid existsSync;\nvoid readFileSync;\nvoid resolveOverlayPath;\n","/**\n * CapabilityDiscovery — synchronous four-tier model capability resolution\n * for epic #2174 (child issue #2176).\n *\n * Lookup order: **T3 user YAML overlay → T1 hardcoded canonical → T2 bundled\n * generated → T4 conservative default**. User overlay wins so operators can\n * fix a broken bundled or canonical entry. No runtime network fetch — T2 is\n * loaded once from the bundled JSON (or skipped if the file is missing /\n * corrupt). Injection points exist for tests so no test ever touches the\n * real filesystem or network.\n *\n * This issue (#2176) only delivers the class + tests. Existing call sites\n * keep using the direct T1 helpers in `model-config-helpers.ts` (the\n * registry-backed surface that replaced the legacy `model-capabilities.ts`\n * after #2546 slice E) — those get migrated when #2177 flips the\n * conservative default from the legacy 200 K fall-through to fail-closed\n * 8 K, and when #2178 wires the T3 YAML loader in.\n *\n * @module config/capability-discovery\n */\n\nimport { readFileSync, existsSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\nimport { z } from 'zod';\n\nimport type { ILogger } from '../core/index.js';\nimport { createLogger } from '../core/index.js';\nimport { getInTreeCapabilitiesMatrix } from './model-config-helpers.js';\nimport type {\n ModelCapabilitiesMatrix,\n ModelCapability,\n Pricing,\n} from './model-capabilities-types.js';\nimport { loadCapabilityOverlay } from './capability-overlay.js';\n\n// ---------------------------------------------------------------------------\n// Generated (T2) shape — mirrors scripts/build-model-registry-types.ts\n// ---------------------------------------------------------------------------\n\nconst GeneratedProvenanceSchema = z.object({\n source: z.enum(['models.dev', 'litellm']),\n fetchedAt: z.string(),\n upstreamUrl: z.string(),\n});\n\nexport type GeneratedProvenance = z.infer<typeof GeneratedProvenanceSchema>;\n\nconst GeneratedModelEntrySchema = z.object({\n id: z.string().min(1),\n displayName: z.string().min(1),\n provider: z.string().min(1),\n contextWindow: z.number().int().positive(),\n pricing: z\n .object({\n inputPer1M: z.number().nonnegative(),\n outputPer1M: z.number().nonnegative(),\n })\n .optional(),\n maxOutputTokens: z.number().int().positive().optional(),\n deprecated: z.boolean().optional(),\n provenance: GeneratedProvenanceSchema,\n});\n\nexport type GeneratedModelEntry = z.infer<typeof GeneratedModelEntrySchema>;\n\nconst GeneratedRegistrySchema = z.object({\n version: z.literal(1),\n generatedAt: z.string(),\n entryCount: z.number().int().nonnegative(),\n entries: z.array(GeneratedModelEntrySchema),\n});\n\nexport type GeneratedRegistry = z.infer<typeof GeneratedRegistrySchema>;\n\n// ---------------------------------------------------------------------------\n// T4 conservative-default toggles\n// ---------------------------------------------------------------------------\n\n/** Conservative default returned when no tier resolves a model id. */\nexport interface ConservativeDefault {\n readonly contextWindow: number;\n readonly maxOutputTokens?: number;\n}\n\n/**\n * Legacy default matching today's `getModelContextWindow` 200 K fall-through.\n * Preserved so this issue (#2176) is a pure addition. Issue #2177 will\n * switch the default to `FAIL_CLOSED_DEFAULT` and update the routing paths\n * to skip models resolved at T4.\n */\nexport const LEGACY_200K_DEFAULT: ConservativeDefault = { contextWindow: 200_000 };\n\n/** Fail-closed default that #2177 will flip on. */\nexport const FAIL_CLOSED_DEFAULT: ConservativeDefault = { contextWindow: 8_192 };\n\n// ---------------------------------------------------------------------------\n// ResolvedCapability — unified shape returned by resolve()\n// ---------------------------------------------------------------------------\n\nexport type ResolutionTier = 't1' | 't2' | 't3' | 't4';\n\nexport interface ResolvedCapability {\n readonly tier: ResolutionTier;\n readonly id: string;\n readonly displayName: string;\n readonly provider: string;\n readonly contextWindow: number;\n readonly pricing?: Pricing;\n readonly maxOutputTokens?: number;\n readonly deprecated?: boolean;\n /** Full T1/T3 entry when resolved from the canonical-shaped tiers. */\n readonly canonical?: ModelCapability;\n /** Provenance when resolved from T2. */\n readonly provenance?: GeneratedProvenance;\n}\n\n// ---------------------------------------------------------------------------\n// Config + construction\n// ---------------------------------------------------------------------------\n\nexport interface CapabilityDiscoveryConfig {\n /** T1 canonical registry. Defaults to the in-tree matrix from the ModelRegistry. */\n readonly canonical?: ModelCapabilitiesMatrix;\n /** T2 bundled generated registry. Pass `null` to force-skip T2. */\n readonly generated?: GeneratedRegistry | null;\n /** T3 user overlay entries. Defaults to empty. Loader is #2178. */\n readonly overlay?: readonly ModelCapability[];\n /** T4 fallback. Defaults to `LEGACY_200K_DEFAULT` until #2177 flips it. */\n readonly conservativeDefault?: ConservativeDefault;\n /** Logger; defaults to a named logger. Inject a mock in tests. */\n readonly logger?: ILogger;\n}\n\nexport class CapabilityDiscovery {\n private readonly canonical: ModelCapabilitiesMatrix;\n private readonly generated: GeneratedRegistry | null;\n private readonly overlay: readonly ModelCapability[];\n private readonly fallback: ConservativeDefault;\n private readonly logger: ILogger;\n private readonly generatedById: Map<string, GeneratedModelEntry>;\n\n constructor(config: CapabilityDiscoveryConfig = {}) {\n // The helper returns a readonly view; loosen here because\n // `ModelCapabilitiesMatrix` predates the registry and uses mutable\n // arrays. Callers in this class only read.\n this.canonical = config.canonical ?? (getInTreeCapabilitiesMatrix() as ModelCapabilitiesMatrix);\n this.generated = config.generated ?? null;\n this.overlay = config.overlay ?? [];\n this.fallback = config.conservativeDefault ?? LEGACY_200K_DEFAULT;\n this.logger = config.logger ?? createLogger({ component: 'capability-discovery' });\n\n this.generatedById = new Map();\n if (this.generated !== null) {\n for (const entry of this.generated.entries) {\n this.generatedById.set(entry.id, entry);\n }\n }\n }\n\n /** Synchronously resolve a model id through the four-tier chain. */\n resolve(modelId: string): ResolvedCapability {\n const t3 = this.lookupOverlay(modelId);\n if (t3 !== undefined) return this.fromCanonical('t3', t3);\n\n const t1 = this.lookupCanonical(modelId);\n if (t1 !== undefined) return this.fromCanonical('t1', t1);\n\n const t2 = this.lookupGenerated(modelId);\n if (t2 !== undefined) return this.fromGenerated('t2', t2);\n\n return this.fromFallback(modelId);\n }\n\n /** Exposes the configured fallback for testing / doctor command. */\n getConservativeDefault(): ConservativeDefault {\n return this.fallback;\n }\n\n /** Count of entries per tier — used by `registry doctor` (#2179). */\n getTierCounts(): Record<ResolutionTier, number> {\n return {\n t3: this.overlay.length,\n t1: this.canonical.models.length,\n t2: this.generatedById.size,\n t4: 0,\n };\n }\n\n // -------------------------------------------------------------------------\n // Tier lookups\n // -------------------------------------------------------------------------\n\n private lookupOverlay(modelId: string): ModelCapability | undefined {\n return this.overlay.find((m) => m.id === modelId);\n }\n\n private lookupCanonical(modelId: string): ModelCapability | undefined {\n return this.canonical.models.find((m) => m.id === modelId);\n }\n\n private lookupGenerated(modelId: string): GeneratedModelEntry | undefined {\n const direct = this.generatedById.get(modelId);\n if (direct !== undefined) return direct;\n for (const candidate of buildAliasCandidates(modelId)) {\n const hit = this.generatedById.get(candidate);\n if (hit !== undefined) return hit;\n }\n return undefined;\n }\n\n // -------------------------------------------------------------------------\n // Result shaping\n // -------------------------------------------------------------------------\n\n private fromCanonical(tier: 't1' | 't3', entry: ModelCapability): ResolvedCapability {\n const base: ResolvedCapability = {\n tier,\n id: entry.id,\n displayName: entry.displayName,\n provider: entry.provider,\n contextWindow: entry.contextWindow,\n canonical: entry,\n ...(entry.pricing !== undefined ? { pricing: entry.pricing } : {}),\n ...(entry.maxOutputTokens !== undefined ? { maxOutputTokens: entry.maxOutputTokens } : {}),\n ...(entry.deprecated !== undefined ? { deprecated: entry.deprecated } : {}),\n };\n return base;\n }\n\n private fromGenerated(tier: 't2', entry: GeneratedModelEntry): ResolvedCapability {\n return {\n tier,\n id: entry.id,\n displayName: entry.displayName,\n provider: entry.provider,\n contextWindow: entry.contextWindow,\n provenance: entry.provenance,\n ...(entry.pricing !== undefined ? { pricing: entry.pricing } : {}),\n ...(entry.maxOutputTokens !== undefined ? { maxOutputTokens: entry.maxOutputTokens } : {}),\n ...(entry.deprecated !== undefined ? { deprecated: entry.deprecated } : {}),\n };\n }\n\n private fromFallback(modelId: string): ResolvedCapability {\n this.logger.warn('Model resolved at T4 conservative default', {\n modelId,\n contextWindow: this.fallback.contextWindow,\n });\n return {\n tier: 't4',\n id: modelId,\n displayName: modelId,\n provider: 'unknown',\n contextWindow: this.fallback.contextWindow,\n ...(this.fallback.maxOutputTokens !== undefined\n ? { maxOutputTokens: this.fallback.maxOutputTokens }\n : {}),\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Alias resolution helpers\n// ---------------------------------------------------------------------------\n\nconst KNOWN_PROVIDER_PREFIXES: readonly string[] = [\n 'amazon-bedrock',\n 'google-vertex',\n 'azure-openai',\n 'openrouter',\n 'anthropic',\n 'openai',\n 'google',\n 'deepseek',\n];\n\n/**\n * Generate candidate alias forms so versioned / prefix-stripped ids still\n * resolve to their T2 entry. Example inputs:\n * anthropic.claude-3-5-sonnet-20241022-v2:0\n * openrouter/anthropic/claude-3-5-sonnet\n * gpt-5-codex\n */\nexport function buildAliasCandidates(modelId: string): readonly string[] {\n const seen = new Set<string>([modelId]);\n for (const prefix of KNOWN_PROVIDER_PREFIXES) {\n seen.add(`${prefix}/${modelId}`);\n }\n const slash = modelId.indexOf('/');\n if (slash !== -1) {\n const tail = modelId.slice(slash + 1);\n for (const prefix of KNOWN_PROVIDER_PREFIXES) {\n seen.add(`${prefix}/${tail}`);\n }\n }\n seen.delete(modelId);\n return [...seen];\n}\n\n// ---------------------------------------------------------------------------\n// Bundled T2 loader — used by the global singleton only, injectable for tests\n// ---------------------------------------------------------------------------\n\n/** Path to the bundled generated registry. Test-only export. */\nexport function defaultGeneratedRegistryPath(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n return join(here, 'model-registry.generated.json');\n}\n\n/**\n * Loads the bundled T2 registry synchronously. Returns `null` if the file\n * is missing or fails Zod validation — callers should treat null as \"T2\n * unavailable\" and fall through to T1 + T4. Logs but never throws.\n */\nexport function loadBundledGeneratedRegistry(\n path: string = defaultGeneratedRegistryPath(),\n logger?: ILogger\n): GeneratedRegistry | null {\n const log = logger ?? createLogger({ component: 'capability-discovery' });\n if (!existsSync(path)) {\n log.warn('T2 generated registry file missing; falling back to T1 + T4', { path });\n return null;\n }\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf-8'));\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n log.warn('T2 generated registry JSON parse failed; falling back to T1 + T4', {\n path,\n errorMessage: error.message,\n });\n return null;\n }\n const parsed = GeneratedRegistrySchema.safeParse(raw);\n if (!parsed.success) {\n log.warn('T2 generated registry schema validation failed; falling back to T1 + T4', {\n path,\n errorMessage: parsed.error.message,\n });\n return null;\n }\n return parsed.data;\n}\n\n// ---------------------------------------------------------------------------\n// Global singleton\n// ---------------------------------------------------------------------------\n\nlet globalDiscovery: CapabilityDiscovery | undefined;\n\n/**\n * Global singleton. Lazily constructed on first access using the bundled T2\n * registry + canonical T1. Tests MUST call `setCapabilityDiscovery` with an\n * injected instance to avoid touching the real file.\n */\nexport function getCapabilityDiscovery(): CapabilityDiscovery {\n globalDiscovery ??= new CapabilityDiscovery({\n generated: loadBundledGeneratedRegistry(),\n overlay: loadCapabilityOverlay().entries,\n // Fail-closed default (#2177): unknown models get 8 K context and a\n // structured warn instead of the silent 200 K fall-through the legacy\n // getModelContextWindow used to return.\n conservativeDefault: FAIL_CLOSED_DEFAULT,\n });\n return globalDiscovery;\n}\n\n/** Test-only: inject a discovery instance. */\nexport function setCapabilityDiscovery(discovery: CapabilityDiscovery | undefined): void {\n globalDiscovery = discovery;\n}\n","/**\n * User YAML overlay loader for CapabilityDiscovery's T3 tier (#2178).\n *\n * Reads user-supplied model capability overrides from a YAML file. Fully\n * optional — missing file, empty file, malformed YAML, and schema-invalid\n * entries all return the empty overlay with structured warnings instead of\n * throwing. Operators use this to fix broken bundled / canonical entries\n * without needing an npm release, or to declare models the curated T1 /\n * generated T2 tiers don't cover.\n *\n * Precedent: LiteLLM's `register_model({...})` + aider's\n * `aider/resources/model-settings.yml`.\n *\n * @module config/capability-overlay\n */\n\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { parse as parseYaml } from 'yaml';\nimport { nexusDataPath } from './nexus-data-dir.js';\n\nimport type { ILogger } from '../core/index.js';\nimport { createLogger } from '../core/index.js';\nimport { ModelCapabilitySchema } from './model-capabilities-types.js';\nimport type { ModelCapability } from './model-capabilities-types.js';\n\n/** Environment variable an operator can set to override the default path. */\nexport const OVERLAY_ENV_VAR = 'NEXUS_MODEL_REGISTRY_OVERLAY';\n\n/** Max file size accepted for the overlay (1 MB — far larger than expected). */\nexport const OVERLAY_MAX_BYTES = 1 * 1024 * 1024;\n\n/**\n * Default overlay location: `<NEXUS_DATA_DIR>/models.yaml`. Returns the\n * absolute path without checking if it exists.\n */\nexport function defaultOverlayPath(): string {\n return nexusDataPath('models.yaml');\n}\n\n/**\n * Resolves the overlay path: `$NEXUS_MODEL_REGISTRY_OVERLAY` wins if set,\n * otherwise the default `~/.nexus-agents/models.yaml`.\n */\nexport function resolveOverlayPath(env: NodeJS.ProcessEnv = process.env): string {\n const override = env[OVERLAY_ENV_VAR];\n if (override !== undefined && override !== '') return override;\n return defaultOverlayPath();\n}\n\n// ---------------------------------------------------------------------------\n// Result shape\n// ---------------------------------------------------------------------------\n\n/** Structured reason for a rejected or skipped entry. */\nexport interface OverlayRejection {\n readonly index: number;\n readonly id?: string;\n readonly reason: string;\n}\n\nexport interface OverlayLoadResult {\n readonly entries: readonly ModelCapability[];\n readonly rejections: readonly OverlayRejection[];\n readonly path: string;\n readonly status: 'missing' | 'empty' | 'malformed' | 'too-large' | 'loaded';\n}\n\n// ---------------------------------------------------------------------------\n// Loader\n// ---------------------------------------------------------------------------\n\n/**\n * Expected YAML root shape:\n *\n * version: 1\n * models:\n * - id: claude-opus\n * displayName: \"Claude Opus (overridden)\"\n * provider: anthropic\n * contextWindow: 1000000\n * ...\n * - ...\n *\n * or simply:\n *\n * - id: ...\n * ...\n *\n * Both a top-level array and an object with `models:` are accepted for\n * ergonomics; everything else is rejected with a structured reason.\n */\nexport function loadCapabilityOverlay(\n pathOrEnv?: string | NodeJS.ProcessEnv,\n logger?: ILogger\n): OverlayLoadResult {\n const log = logger ?? createLogger({ component: 'capability-overlay' });\n const path = resolvePath(pathOrEnv);\n\n if (!existsSync(path)) {\n return { entries: [], rejections: [], path, status: 'missing' };\n }\n\n const sizeStatus = checkSize(path, log);\n if (sizeStatus !== undefined) return sizeStatus;\n\n const bodyResult = readBody(path, log);\n if ('result' in bodyResult) return bodyResult.result;\n const body = bodyResult.body;\n if (body === '') {\n log.info('Model registry overlay file is empty', { path });\n return { entries: [], rejections: [], path, status: 'empty' };\n }\n\n const parseResult = parseBody(body, path, log);\n if ('result' in parseResult) return parseResult.result;\n const parsed = parseResult.parsed;\n\n const rawEntries = extractEntries(parsed);\n if (rawEntries === undefined) {\n log.warn('Model registry overlay has unrecognized shape; treated as empty', {\n path,\n });\n return {\n entries: [],\n rejections: [{ index: -1, reason: 'Expected array or { models: [...] }' }],\n path,\n status: 'malformed',\n };\n }\n\n const { entries, rejections } = validateEntries(rawEntries, log, path);\n return { entries, rejections, path, status: 'loaded' };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction resolvePath(pathOrEnv: string | NodeJS.ProcessEnv | undefined): string {\n if (typeof pathOrEnv === 'string') return pathOrEnv;\n if (pathOrEnv !== undefined) return resolveOverlayPath(pathOrEnv);\n return resolveOverlayPath();\n}\n\ntype ReadBodyResult = { body: string } | { result: OverlayLoadResult };\nfunction readBody(path: string, log: ILogger): ReadBodyResult {\n try {\n return { body: readFileSync(path, 'utf-8').trim() };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n log.warn('Model registry overlay file read failed; treated as empty', {\n path,\n errorMessage: message,\n });\n return {\n result: {\n entries: [],\n rejections: [{ index: -1, reason: `file read error: ${message}` }],\n path,\n status: 'malformed',\n },\n };\n }\n}\n\ntype ParseBodyResult = { parsed: unknown } | { result: OverlayLoadResult };\nfunction parseBody(body: string, path: string, log: ILogger): ParseBodyResult {\n try {\n return { parsed: parseYaml(body) };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n log.warn('Model registry overlay YAML parse failed; treated as empty', {\n path,\n errorMessage: message,\n });\n return {\n result: {\n entries: [],\n rejections: [{ index: -1, reason: `YAML parse error: ${message}` }],\n path,\n status: 'malformed',\n },\n };\n }\n}\n\nfunction checkSize(path: string, log: ILogger): OverlayLoadResult | undefined {\n let size: number;\n try {\n size = statSync(path).size;\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n log.warn('Model registry overlay statSync failed; treated as missing', {\n path,\n errorMessage: message,\n });\n return { entries: [], rejections: [], path, status: 'missing' };\n }\n if (size <= OVERLAY_MAX_BYTES) return undefined;\n log.warn('Model registry overlay exceeds size cap; refusing to load', {\n path,\n size,\n maxBytes: OVERLAY_MAX_BYTES,\n });\n return {\n entries: [],\n rejections: [\n {\n index: -1,\n reason: `file size ${String(size)} exceeds cap ${String(OVERLAY_MAX_BYTES)}`,\n },\n ],\n path,\n status: 'too-large',\n };\n}\n\nfunction extractIdForError(raw: unknown): string | undefined {\n if (raw === null || typeof raw !== 'object' || !('id' in raw)) return undefined;\n const idValue = raw.id;\n if (typeof idValue === 'string' && idValue !== '') return idValue;\n return undefined;\n}\n\nfunction extractEntries(parsed: unknown): unknown[] | undefined {\n if (Array.isArray(parsed)) return parsed as unknown[];\n if (parsed !== null && typeof parsed === 'object') {\n const obj = parsed as { models?: unknown };\n if (Array.isArray(obj.models)) return obj.models as unknown[];\n }\n return undefined;\n}\n\ninterface ValidatedEntries {\n readonly entries: readonly ModelCapability[];\n readonly rejections: readonly OverlayRejection[];\n}\n\nfunction validateEntries(\n rawEntries: readonly unknown[],\n log: ILogger,\n path: string\n): ValidatedEntries {\n const entries: ModelCapability[] = [];\n const rejections: OverlayRejection[] = [];\n for (let i = 0; i < rawEntries.length; i++) {\n const raw = rawEntries[i];\n const idCandidate = extractIdForError(raw);\n const parsed = ModelCapabilitySchema.safeParse(raw);\n if (!parsed.success) {\n const rejection: OverlayRejection = {\n index: i,\n ...(idCandidate !== undefined && idCandidate !== '' ? { id: idCandidate } : {}),\n reason: parsed.error.message,\n };\n rejections.push(rejection);\n log.warn('Model registry overlay entry rejected by schema', {\n path,\n index: i,\n id: idCandidate,\n errorMessage: parsed.error.message,\n });\n continue;\n }\n entries.push(parsed.data);\n }\n return { entries, rejections };\n}\n"],"mappings":"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","names":["existsSync","readFileSync","dirname","readFileSync","existsSync","existsSync","readFileSync","dirname"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|