nexus-agents 2.55.1 → 2.57.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/{adaptive-memory-SUNFPY2W.js → adaptive-memory-TSZEJUJC.js} +3 -3
- package/dist/{chunk-4FVISCDB.js → chunk-6QU4DJYW.js} +2 -2
- package/dist/{chunk-NYNBDP7M.js → chunk-7Y36JLES.js} +2 -2
- package/dist/{chunk-FWSTXEG2.js → chunk-AFSIP6JH.js} +99 -23
- package/dist/chunk-AFSIP6JH.js.map +1 -0
- package/dist/{chunk-BPMQRYGU.js → chunk-BOZ26RIB.js} +283 -79
- package/dist/chunk-BOZ26RIB.js.map +1 -0
- package/dist/{chunk-VKZKC4SM.js → chunk-EDGG3RQE.js} +2 -2
- package/dist/{chunk-2SPRLBOS.js → chunk-EZXOJZYE.js} +2 -2
- package/dist/{chunk-W5AJRK4U.js → chunk-GMOGKX4E.js} +2 -2
- package/dist/chunk-H43PABG4.js +402 -0
- package/dist/chunk-H43PABG4.js.map +1 -0
- package/dist/{chunk-IOU7F5PH.js → chunk-K7EA5OV4.js} +2 -2
- package/dist/chunk-NUBSJGQZ.js +14 -0
- package/dist/chunk-NUBSJGQZ.js.map +1 -0
- package/dist/{chunk-KRIFBGWZ.js → chunk-PTGBJFSD.js} +3 -3
- package/dist/{chunk-EKYT4NMD.js → chunk-QGZBCD2A.js} +24 -9
- package/dist/chunk-QGZBCD2A.js.map +1 -0
- package/dist/{chunk-XYCS5X3H.js → chunk-QNYNQ257.js} +422 -72
- package/dist/chunk-QNYNQ257.js.map +1 -0
- package/dist/{chunk-UOUJZIKH.js → chunk-R2Y57PM3.js} +38 -15
- package/dist/chunk-R2Y57PM3.js.map +1 -0
- package/dist/{chunk-RSUCXOQM.js → chunk-SXWZS2V4.js} +26 -53
- package/dist/chunk-SXWZS2V4.js.map +1 -0
- package/dist/{chunk-JERFBN73.js → chunk-TC46TRLR.js} +7 -17
- package/dist/chunk-TC46TRLR.js.map +1 -0
- package/dist/{chunk-3IDJSFWT.js → chunk-TFEFN37P.js} +2 -2
- package/dist/{chunk-Q5TKQWOI.js → chunk-V5CGWMYL.js} +2 -2
- package/dist/{chunk-TCQNNY4J.js → chunk-XEMRMZUN.js} +4 -4
- package/dist/chunk-Y7CD6AZW.js +2136 -0
- package/dist/chunk-Y7CD6AZW.js.map +1 -0
- package/dist/{chunk-R66AWJJ7.js → chunk-YU4NABXM.js} +2 -2
- package/dist/{chunk-KVWHK72T.js → chunk-ZL3IBCH6.js} +2356 -3687
- package/dist/chunk-ZL3IBCH6.js.map +1 -0
- package/dist/{chunk-VLVHPC72.js → chunk-ZUWOFHNC.js} +6 -6
- package/dist/{cli-circuit-breaker-7MCMHSDY.js → cli-circuit-breaker-SL73NWX2.js} +4 -4
- package/dist/cli.d.ts +9 -2
- package/dist/cli.js +468 -311
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-LXFOSMSE.js → composite-router-A7URDW4X.js} +2 -2
- package/dist/{consensus-vote-G6H532ME.js → consensus-vote-CQ2JP6DC.js} +9 -8
- package/dist/{doctor-deep-RKMOZSIS.js → doctor-deep-VN6KMUCG.js} +3 -3
- package/dist/{expert-bridge-KHHE42JP.js → expert-bridge-LT7PKUPS.js} +3 -3
- package/dist/{factory-KRNR7XHD.js → factory-FA7WDPZW.js} +5 -5
- package/dist/{factory-JVN47MFN.js → factory-FZ2KSVYC.js} +4 -4
- package/dist/index.d.ts +324 -16
- package/dist/index.js +84 -68
- package/dist/index.js.map +1 -1
- package/dist/{issue-triage-O3C7P66H.js → issue-triage-YYTE6KTC.js} +4 -4
- package/dist/{mcp-config-QRERKGR4.js → mcp-config-34XMRM64.js} +3 -3
- package/dist/{mobimem-FAOAXV3B.js → mobimem-QDBP37H7.js} +2 -2
- package/dist/model-registry.generated.json +17033 -0
- package/dist/registry-command-S46JJ2SX.js +580 -0
- package/dist/registry-command-S46JJ2SX.js.map +1 -0
- package/dist/{repo-security-plan-AZ5HMGFC.js → repo-security-plan-C3LLE3Z7.js} +3 -3
- package/dist/research-helpers-synthesize-NVQIWLQL.js +11 -0
- package/dist/{routing-memory-MXF45FXT.js → routing-memory-W3YWMLJM.js} +2 -2
- package/dist/{session-memory-HL5XDBIL.js → session-memory-DWF5Z2LC.js} +3 -3
- package/dist/{setup-command-B6AFJGZB.js → setup-command-6EJONTOU.js} +10 -7
- package/dist/{setup-config-PWK6WHMG.js → setup-config-JA5IX53Q.js} +3 -3
- package/dist/{setup-custom-api-XAWKRDWV.js → setup-custom-api-CSB26HWD.js} +7 -5
- package/dist/setup-custom-api-CSB26HWD.js.map +1 -0
- package/dist/{weather-report-XZ5CENHE.js → weather-report-YQSLX4MS.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-BPMQRYGU.js.map +0 -1
- package/dist/chunk-EKYT4NMD.js.map +0 -1
- package/dist/chunk-FWSTXEG2.js.map +0 -1
- package/dist/chunk-JERFBN73.js.map +0 -1
- package/dist/chunk-KVWHK72T.js.map +0 -1
- package/dist/chunk-OC7RMLN2.js +0 -839
- package/dist/chunk-OC7RMLN2.js.map +0 -1
- package/dist/chunk-RSUCXOQM.js.map +0 -1
- package/dist/chunk-UOUJZIKH.js.map +0 -1
- package/dist/chunk-XYCS5X3H.js.map +0 -1
- package/dist/research-helpers-synthesize-TFZIXBX3.js +0 -10
- package/dist/setup-custom-api-XAWKRDWV.js.map +0 -1
- /package/dist/{adaptive-memory-SUNFPY2W.js.map → adaptive-memory-TSZEJUJC.js.map} +0 -0
- /package/dist/{chunk-4FVISCDB.js.map → chunk-6QU4DJYW.js.map} +0 -0
- /package/dist/{chunk-NYNBDP7M.js.map → chunk-7Y36JLES.js.map} +0 -0
- /package/dist/{chunk-VKZKC4SM.js.map → chunk-EDGG3RQE.js.map} +0 -0
- /package/dist/{chunk-2SPRLBOS.js.map → chunk-EZXOJZYE.js.map} +0 -0
- /package/dist/{chunk-W5AJRK4U.js.map → chunk-GMOGKX4E.js.map} +0 -0
- /package/dist/{chunk-IOU7F5PH.js.map → chunk-K7EA5OV4.js.map} +0 -0
- /package/dist/{chunk-KRIFBGWZ.js.map → chunk-PTGBJFSD.js.map} +0 -0
- /package/dist/{chunk-3IDJSFWT.js.map → chunk-TFEFN37P.js.map} +0 -0
- /package/dist/{chunk-Q5TKQWOI.js.map → chunk-V5CGWMYL.js.map} +0 -0
- /package/dist/{chunk-TCQNNY4J.js.map → chunk-XEMRMZUN.js.map} +0 -0
- /package/dist/{chunk-R66AWJJ7.js.map → chunk-YU4NABXM.js.map} +0 -0
- /package/dist/{chunk-VLVHPC72.js.map → chunk-ZUWOFHNC.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-7MCMHSDY.js.map → cli-circuit-breaker-SL73NWX2.js.map} +0 -0
- /package/dist/{composite-router-LXFOSMSE.js.map → composite-router-A7URDW4X.js.map} +0 -0
- /package/dist/{consensus-vote-G6H532ME.js.map → consensus-vote-CQ2JP6DC.js.map} +0 -0
- /package/dist/{doctor-deep-RKMOZSIS.js.map → doctor-deep-VN6KMUCG.js.map} +0 -0
- /package/dist/{expert-bridge-KHHE42JP.js.map → expert-bridge-LT7PKUPS.js.map} +0 -0
- /package/dist/{factory-JVN47MFN.js.map → factory-FA7WDPZW.js.map} +0 -0
- /package/dist/{factory-KRNR7XHD.js.map → factory-FZ2KSVYC.js.map} +0 -0
- /package/dist/{issue-triage-O3C7P66H.js.map → issue-triage-YYTE6KTC.js.map} +0 -0
- /package/dist/{mcp-config-QRERKGR4.js.map → mcp-config-34XMRM64.js.map} +0 -0
- /package/dist/{mobimem-FAOAXV3B.js.map → mobimem-QDBP37H7.js.map} +0 -0
- /package/dist/{repo-security-plan-AZ5HMGFC.js.map → repo-security-plan-C3LLE3Z7.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-TFZIXBX3.js.map → research-helpers-synthesize-NVQIWLQL.js.map} +0 -0
- /package/dist/{routing-memory-MXF45FXT.js.map → routing-memory-W3YWMLJM.js.map} +0 -0
- /package/dist/{session-memory-HL5XDBIL.js.map → session-memory-DWF5Z2LC.js.map} +0 -0
- /package/dist/{setup-command-B6AFJGZB.js.map → setup-command-6EJONTOU.js.map} +0 -0
- /package/dist/{setup-config-PWK6WHMG.js.map → setup-config-JA5IX53Q.js.map} +0 -0
- /package/dist/{weather-report-XZ5CENHE.js.map → weather-report-YQSLX4MS.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/setup-config.ts"],"sourcesContent":["/**\n * Synchronous config file generation for setup command.\n *\n * Reuses the CONFIG_TEMPLATE from config-init.ts pattern but provides\n * a synchronous API suitable for the setup command flow.\n *\n * @module cli/setup-config\n * (Source: Issue #1252 - Setup auto-generates nexus-agents.yaml)\n */\n\nimport { existsSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { getErrorMessage } from '../core/index.js';\n\n/** Default configuration file name. */\nconst DEFAULT_CONFIG_FILE = 'nexus-agents.yaml';\n\n/** Result of the config generation step. */\nexport interface ConfigStepResult {\n readonly success: boolean;\n readonly path: string;\n readonly created: boolean;\n readonly message: string;\n}\n\n/**\n * Minimal YAML config template for setup command.\n * Intentionally brief — just enough to get started.\n * Users can run `nexus-agents config init` for the full template.\n */\nconst SETUP_CONFIG_TEMPLATE = `# Nexus Agents Configuration\n# Generated by: nexus-agents setup\n# Full template: nexus-agents config init\n\nmodels:\n default: claude-sonnet-4\n\nexperts:\n builtin: true\n\nlogging:\n level: info\n format: json\n`;\n\n/**\n * Generates a nexus-agents.yaml config file synchronously.\n *\n * @param projectRoot - Directory to create config in.\n * @param force - Overwrite existing config.\n * @param dryRun - Report what would happen without writing.\n */\nexport function runConfigInitSync(\n projectRoot: string,\n force: boolean,\n dryRun: boolean\n): ConfigStepResult {\n const outputPath = resolve(projectRoot, DEFAULT_CONFIG_FILE);\n\n if (existsSync(outputPath) && !force) {\n return {\n success: true,\n path: outputPath,\n created: false,\n message: 'Config already exists (use --force to overwrite)',\n };\n }\n\n if (dryRun) {\n return {\n success: true,\n path: outputPath,\n created: true,\n message: `Would create: ${outputPath}`,\n };\n }\n\n try {\n writeFileSync(outputPath, SETUP_CONFIG_TEMPLATE, 'utf-8');\n return {\n success: true,\n path: outputPath,\n created: true,\n message: `Created: ${outputPath}`,\n };\n } catch (error: unknown) {\n return {\n success: false,\n path: outputPath,\n created: false,\n message: `Failed: ${getErrorMessage(error)}`,\n };\n }\n}\n"],"mappings":";;;;;AAUA,SAAS,YAAY,qBAAqB;AAC1C,SAAS,eAAe;AAIxB,IAAM,sBAAsB;AAe5B,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBvB,SAAS,kBACd,aACA,OACA,QACkB;AAClB,QAAM,aAAa,QAAQ,aAAa,mBAAmB;AAE3D,MAAI,WAAW,UAAU,KAAK,CAAC,OAAO;AACpC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI,QAAQ;AACV,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,iBAAiB,UAAU;AAAA,IACtC;AAAA,EACF;AAEA,MAAI;AACF,kBAAc,YAAY,uBAAuB,OAAO;AACxD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,YAAY,UAAU;AAAA,IACjC;AAAA,EACF,SAAS,OAAgB;AACvB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,WAAW,gBAAgB,KAAK,CAAC;AAAA,IAC5C;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/security/trust-types.ts","../src/security/input-sanitizer.ts","../src/security/trust-classifier.ts","../src/security/policy-gate.ts","../src/security/action-schema.ts","../src/security/corroboration-validator.ts","../src/security/reputation-model.ts","../src/dogfooding/github-client.ts","../src/scm/github-provider-traits.ts","../src/dogfooding/issue-triage-types.ts","../src/dogfooding/issue-triage-helpers.ts","../src/dogfooding/issue-triage.ts"],"sourcesContent":["/**\n * nexus-agents/security - Trust Types\n *\n * Zod schemas and TypeScript types for the untrusted input hardening\n * framework. Defines trust tiers, sanitized input, user roles, and\n * injection detection flags.\n *\n * @module security/trust-types\n * (Source: Issue #818, #819 — Phase 1: Input Sanitization)\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Trust Tiers\n// ============================================================================\n\n/**\n * Trust tier classification for input sources.\n * Lower number = higher trust.\n *\n * 1 = Authoritative (repo files, CI, CLAUDE.md, allowlisted maintainers)\n * 2 = Semi-trusted (collaborator issue body, contributor PR metadata)\n * 3 = Untrusted (unknown user comments, non-collaborator issue body)\n * 4 = Hostile (injection patterns, hidden HTML, instruction-like content)\n */\nexport const TrustTierSchema = z.enum(['1', '2', '3', '4']);\nexport type TrustTier = z.infer<typeof TrustTierSchema>;\n\n/** Numeric trust tier for comparisons. Higher number = lower trust. */\nexport const TRUST_TIER_NUMERIC: Record<TrustTier, number> = {\n '1': 1,\n '2': 2,\n '3': 3,\n '4': 4,\n};\n\n// ============================================================================\n// GitHub User Roles\n// ============================================================================\n\n/**\n * GitHub user relationship to the repository.\n */\nexport const GitHubUserRoleSchema = z.enum([\n 'owner',\n 'maintainer',\n 'collaborator',\n 'contributor',\n 'member',\n 'unknown',\n]);\nexport type GitHubUserRole = z.infer<typeof GitHubUserRoleSchema>;\n\n/**\n * Default trust tier mapping for each GitHub role.\n * Can be overridden by injection pattern detection (downgrade only).\n */\nexport const ROLE_DEFAULT_TRUST: Record<GitHubUserRole, TrustTier> = {\n owner: '1',\n maintainer: '1',\n collaborator: '2',\n contributor: '2',\n member: '3',\n unknown: '3',\n};\n\n// ============================================================================\n// Injection Detection\n// ============================================================================\n\n/**\n * Categories of injection patterns detected in content.\n */\nexport const InjectionFlagSchema = z.enum([\n 'authority_claim',\n 'instruction_pattern',\n 'system_prompt_manipulation',\n 'hidden_content',\n 'urgency_manipulation',\n 'fake_conversation',\n 'base64_encoded',\n 'external_link_instruction',\n]);\nexport type InjectionFlag = z.infer<typeof InjectionFlagSchema>;\n\n/**\n * An element stripped during sanitization, preserved for audit trail.\n */\nexport const StrippedElementSchema = z.object({\n /** Type of element stripped. */\n tag: z.string().min(1),\n /** Reason for stripping. */\n reason: z.string().min(1),\n /** Start index in original content. */\n startIndex: z.number().int().nonnegative(),\n /** Length of stripped content. */\n length: z.number().int().positive(),\n});\nexport type StrippedElement = z.infer<typeof StrippedElementSchema>;\n\n// ============================================================================\n// Sanitized Input\n// ============================================================================\n\n/**\n * The result of sanitizing untrusted input.\n * Contains cleaned content, trust classification, and audit data.\n */\nexport const SanitizedInputSchema = z.object({\n /** Sanitized content with dangerous elements removed. */\n content: z.string(),\n /** Original content before sanitization (for audit). */\n originalLength: z.number().int().nonnegative(),\n /** Assigned trust tier based on user role and content analysis. */\n trustTier: TrustTierSchema,\n /** GitHub user role of the input source. */\n userRole: GitHubUserRoleSchema,\n /** Injection patterns detected in content. */\n injectionFlags: z.array(InjectionFlagSchema),\n /** Elements stripped during sanitization (audit trail). */\n strippedElements: z.array(StrippedElementSchema),\n /** Whether any dangerous content was detected and stripped. */\n wasModified: z.boolean(),\n /** Timestamp of sanitization (ISO 8601). */\n sanitizedAt: z.iso.datetime(),\n});\nexport type SanitizedInput = z.infer<typeof SanitizedInputSchema>;\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\n/**\n * Configuration for the input sanitizer.\n */\nexport const SanitizerConfigSchema = z.object({\n /** GitHub usernames that are always Tier 1 (allowlisted maintainers). */\n allowlistedMaintainers: z.array(z.string().min(1)).default([]),\n /** Whether to fail open (log only) or fail closed (block). Phase 1 = open. */\n failOpen: z.boolean().default(true),\n /** Maximum input length before truncation. */\n maxInputLength: z.number().int().positive().default(50_000),\n});\nexport type SanitizerConfig = z.infer<typeof SanitizerConfigSchema>;\n","/**\n * nexus-agents/security - Input Sanitizer\n *\n * Sanitizes untrusted GitHub input by stripping dangerous HTML/XML tags,\n * detecting injection patterns, and producing a SanitizedInput result\n * with full audit trail.\n *\n * Defense layer 1 of the three-layer hardening architecture.\n * See: docs/architecture/UNTRUSTED_INPUT_HARDENING.md\n *\n * @module security/input-sanitizer\n * (Source: Issue #818, #819 — Phase 1: Input Sanitization)\n */\n\nimport type {\n InjectionFlag,\n SanitizedInput,\n SanitizerConfig,\n StrippedElement,\n TrustTier,\n GitHubUserRole,\n} from './trust-types.js';\nimport { ROLE_DEFAULT_TRUST, SanitizerConfigSchema } from './trust-types.js';\n\n// ============================================================================\n// Dangerous HTML Patterns (Trail of Bits / GitHub Copilot vectors)\n// ============================================================================\n\n/**\n * HTML tags to strip. These are known injection vectors:\n * - `<picture>` / `<source>`: Trail of Bits GitHub Copilot injection\n * - `<img>`: Can carry injection via alt text or onerror\n */\nconst DANGEROUS_HTML_PATTERN =\n /<(picture|source|img)\\b[^>]*>[\\s\\S]*?<\\/\\1>|<(picture|source|img)\\b[^>]*\\/?>/gi;\n\n// ============================================================================\n// XML-like Tags (Conversation History Injection)\n// ============================================================================\n\n/**\n * XML-like tags that mimic conversation structure or system prompts.\n */\nconst XML_INJECTION_PATTERN =\n /<\\/?(system|human|assistant|instructions|user|prompt|context|tool_use|tool_result)\\b[^>]*>/gi;\n\n// ============================================================================\n// HTML Comments with Instructions\n// ============================================================================\n\nconst HTML_COMMENT_PATTERN = /<!--[\\s\\S]*?-->/g;\n\n// ============================================================================\n// Injection Pattern Detectors\n// ============================================================================\n\ninterface PatternMatch {\n flag: InjectionFlag;\n pattern: RegExp;\n}\n\nconst INJECTION_PATTERNS: readonly PatternMatch[] = [\n {\n flag: 'authority_claim',\n pattern: /\\b(as (?:a|the) (?:maintainer|admin|owner|security lead|repo owner|developer))\\b/i,\n },\n {\n flag: 'authority_claim',\n pattern: /\\b(i(?:'m| am) the (?:repo |project )?(?:owner|maintainer|admin))\\b/i,\n },\n {\n flag: 'instruction_pattern',\n pattern: /\\b(please (?:close|merge|label|mark|apply|delete|remove|approve|reject))\\b/i,\n },\n {\n flag: 'instruction_pattern',\n pattern: /\\b(you (?:should|must|need to) (?:close|merge|label|apply|delete))\\b/i,\n },\n {\n flag: 'system_prompt_manipulation',\n pattern: /\\b(ignore (?:all )?previous (?:instructions|rules|prompts))\\b/i,\n },\n {\n flag: 'system_prompt_manipulation',\n pattern: /\\b(forget (?:your |all )?(?:instructions|rules|safety))\\b/i,\n },\n {\n flag: 'system_prompt_manipulation',\n pattern: /\\b(new (?:instructions|rules|system prompt|directives))\\b/i,\n },\n {\n flag: 'urgency_manipulation',\n pattern: /\\b(critical|emergency|urgent|must act now|immediately|time[- ]?sensitive)\\b/i,\n },\n {\n flag: 'fake_conversation',\n pattern: /<(?:assistant|human|user|system)>/i,\n },\n {\n flag: 'base64_encoded',\n // Requires at least one base64-discriminating char (g-z/G-Z or +, /, =)\n // to avoid false positives on SHA-1 / SHA-256 hex hashes (#1811).\n pattern: /(?=[A-Za-z0-9+/]*[g-zG-Z+/=])[A-Za-z0-9+/]{40,}={0,2}/,\n },\n {\n flag: 'external_link_instruction',\n pattern: /(?:apply|run|execute|install)\\s+(?:this\\s+)?(?:from\\s+)?https?:\\/\\//i,\n },\n];\n\n// ============================================================================\n// Core Sanitization Functions\n// ============================================================================\n\n/** Strips dangerous HTML tags and records what was removed.\n * Loops until stable to prevent reconstructed patterns after removal (#1496). */\nfunction stripDangerousHtml(content: string): {\n cleaned: string;\n stripped: StrippedElement[];\n} {\n const stripped: StrippedElement[] = [];\n let cleaned = content;\n const MAX_PASSES = 5;\n for (let pass = 0; pass < MAX_PASSES; pass++) {\n DANGEROUS_HTML_PATTERN.lastIndex = 0;\n if (!DANGEROUS_HTML_PATTERN.test(cleaned)) break;\n cleaned = cleaned.replace(DANGEROUS_HTML_PATTERN, (match, _g1, _g2, offset: number) => {\n stripped.push({\n tag: match.slice(0, 30) + (match.length > 30 ? '...' : ''),\n reason: 'Dangerous HTML tag (Trail of Bits injection vector)',\n startIndex: offset,\n length: match.length,\n });\n return '';\n });\n }\n return { cleaned, stripped };\n}\n\n/** Strips XML-like tags that mimic conversation structure.\n * Loops until stable to prevent reconstructed patterns after removal (#1496). */\nfunction stripXmlTags(content: string): {\n cleaned: string;\n stripped: StrippedElement[];\n} {\n const stripped: StrippedElement[] = [];\n let cleaned = content;\n const MAX_PASSES = 5;\n for (let pass = 0; pass < MAX_PASSES; pass++) {\n XML_INJECTION_PATTERN.lastIndex = 0;\n if (!XML_INJECTION_PATTERN.test(cleaned)) break;\n cleaned = cleaned.replace(XML_INJECTION_PATTERN, (match, _g1, offset: number) => {\n stripped.push({\n tag: match,\n reason: 'XML-like conversation injection tag',\n startIndex: offset,\n length: match.length,\n });\n return '';\n });\n }\n return { cleaned, stripped };\n}\n\n/** Strips HTML comments that may contain hidden instructions.\n * Loops until stable to prevent reconstructed comment patterns (#1496). */\nfunction stripHtmlComments(content: string): {\n cleaned: string;\n stripped: StrippedElement[];\n} {\n const stripped: StrippedElement[] = [];\n let cleaned = content;\n // Loop until stable: stripping may reveal new instruction-bearing comments\n const MAX_PASSES = 5;\n for (let pass = 0; pass < MAX_PASSES; pass++) {\n HTML_COMMENT_PATTERN.lastIndex = 0;\n const prevLength = cleaned.length;\n cleaned = cleaned.replace(HTML_COMMENT_PATTERN, (match, offset: number) => {\n const hasInstruction = /\\b(ignore|execute|close|merge|delete|apply)\\b/i.test(match);\n if (!hasInstruction) return match;\n\n stripped.push({\n tag: '<!-- ... -->',\n reason: 'HTML comment with instruction-like content',\n startIndex: offset,\n length: match.length,\n });\n return '';\n });\n if (cleaned.length === prevLength) break;\n }\n // Second pass: strip unclosed <!-- tags (incomplete comment injection)\n let searchFrom = 0;\n while (searchFrom < cleaned.length) {\n const openIdx = cleaned.indexOf('<!--', searchFrom);\n if (openIdx === -1) break;\n const closeIdx = cleaned.indexOf('-->', openIdx + 4);\n if (closeIdx === -1) {\n stripped.push({\n tag: '<!--',\n reason: 'Unclosed HTML comment (potential injection vector)',\n startIndex: openIdx,\n length: cleaned.length - openIdx,\n });\n cleaned = cleaned.slice(0, openIdx);\n break;\n }\n searchFrom = closeIdx + 3;\n }\n return { cleaned, stripped };\n}\n\n/** Detects injection patterns in content without modifying it. */\nfunction detectInjectionPatterns(content: string): InjectionFlag[] {\n const flags = new Set<InjectionFlag>();\n for (const { flag, pattern } of INJECTION_PATTERNS) {\n // Reset lastIndex for global patterns\n pattern.lastIndex = 0;\n if (pattern.test(content)) {\n flags.add(flag);\n }\n }\n return Array.from(flags);\n}\n\n/**\n * Assigns trust tier based on user role and injection analysis.\n * Injection patterns can only DOWNGRADE trust, never upgrade.\n */\nfunction assignTrustTier(\n userRole: GitHubUserRole,\n injectionFlags: readonly InjectionFlag[],\n allowlisted: boolean\n): TrustTier {\n if (allowlisted) return '1';\n\n const baseTier = ROLE_DEFAULT_TRUST[userRole];\n\n // Content with injection patterns is downgraded to Tier 4 (hostile)\n const hostileFlags: InjectionFlag[] = ['system_prompt_manipulation', 'fake_conversation'];\n if (injectionFlags.some((f) => hostileFlags.includes(f))) return '4';\n\n // Content with authority claims from non-maintainers is suspicious\n if (\n injectionFlags.includes('authority_claim') &&\n userRole !== 'owner' &&\n userRole !== 'maintainer'\n ) {\n return '4';\n }\n\n return baseTier;\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Sanitizes untrusted GitHub input through the full Layer 1 pipeline:\n * 1. HTML stripping (picture/source/img tags)\n * 2. XML tag stripping (system/human/assistant)\n * 3. HTML comment stripping (instruction-bearing comments only)\n * 4. Injection pattern detection\n * 5. Trust tier assignment\n *\n * @param content - Raw untrusted content from GitHub\n * @param userRole - GitHub user's relationship to the repository\n * @param username - GitHub username (for allowlist check)\n * @param config - Optional sanitizer configuration\n * @returns SanitizedInput with cleaned content and audit data\n */\nexport function sanitizeInput(\n content: string,\n userRole: GitHubUserRole,\n username: string,\n config?: Partial<SanitizerConfig>\n): SanitizedInput {\n const cfg = SanitizerConfigSchema.parse(config ?? {});\n const truncated = content.slice(0, cfg.maxInputLength);\n const allowlisted = cfg.allowlistedMaintainers.includes(username);\n\n // Pipeline: strip dangerous content\n const html = stripDangerousHtml(truncated);\n const xml = stripXmlTags(html.cleaned);\n const comments = stripHtmlComments(xml.cleaned);\n const allStripped = [...html.stripped, ...xml.stripped, ...comments.stripped];\n\n // Detect injection patterns on ORIGINAL content (before stripping)\n const injectionFlags = detectInjectionPatterns(truncated);\n\n // Assign trust tier\n const trustTier = assignTrustTier(userRole, injectionFlags, allowlisted);\n\n return {\n content: comments.cleaned,\n originalLength: content.length,\n trustTier,\n userRole,\n injectionFlags,\n strippedElements: allStripped,\n wasModified: allStripped.length > 0,\n sanitizedAt: new Date().toISOString(),\n };\n}\n","/**\n * nexus-agents/security - Trust Classifier\n *\n * Classifies GitHub users and content into trust tiers based on\n * repository relationship, allowlist membership, and content analysis.\n * Works with the input sanitizer to determine how agent decisions\n * should weight each input source.\n *\n * @module security/trust-classifier\n * (Source: Issue #818, #819 — Phase 1: Input Sanitization)\n */\n\nimport type { TrustTier, GitHubUserRole, SanitizedInput, SanitizerConfig } from './trust-types.js';\nimport { ROLE_DEFAULT_TRUST, TRUST_TIER_NUMERIC } from './trust-types.js';\n\n// ============================================================================\n// GitHub Author Association Mapping\n// ============================================================================\n\n/**\n * Maps GitHub API author_association values to our GitHubUserRole enum.\n * See: https://docs.github.com/en/graphql/reference/enums#commentauthorassociation\n */\nexport function mapAuthorAssociation(association: string): GitHubUserRole {\n switch (association.toUpperCase()) {\n case 'OWNER':\n return 'owner';\n case 'MEMBER':\n return 'member';\n case 'COLLABORATOR':\n return 'collaborator';\n case 'CONTRIBUTOR':\n return 'contributor';\n case 'FIRST_TIMER':\n case 'FIRST_TIME_CONTRIBUTOR':\n case 'NONE':\n return 'unknown';\n case 'MANNEQUIN':\n return 'unknown';\n default:\n return 'unknown';\n }\n}\n\n// ============================================================================\n// Trust Classification\n// ============================================================================\n\n/**\n * Input for trust classification.\n */\nexport interface ClassifyInput {\n /** GitHub username. */\n readonly username: string;\n /** GitHub API author_association value. */\n readonly authorAssociation: string;\n /** Sanitized input (if content has already been through the sanitizer). */\n readonly sanitizedInput?: SanitizedInput;\n /** Sanitizer config (for allowlist check). */\n readonly config?: Partial<SanitizerConfig>;\n}\n\n/**\n * Result of trust classification.\n */\nexport interface ClassifyResult {\n /** Assigned trust tier. */\n readonly trustTier: TrustTier;\n /** GitHub user role. */\n readonly userRole: GitHubUserRole;\n /** Whether the user is on the maintainer allowlist. */\n readonly isAllowlisted: boolean;\n /** Whether content triggered a trust downgrade. */\n readonly wasDowngraded: boolean;\n /** Reason for the assigned tier. */\n readonly reason: string;\n}\n\n/**\n * Classifies a GitHub user and their content into a trust tier.\n *\n * The trust tier is determined by:\n * 1. Allowlist membership (always Tier 1)\n * 2. GitHub author_association → role → default tier\n * 3. Content injection analysis (can only downgrade, never upgrade)\n */\nexport function classifyTrust(input: ClassifyInput): ClassifyResult {\n const allowlistedMaintainers = input.config?.allowlistedMaintainers ?? [];\n const isAllowlisted = allowlistedMaintainers.includes(input.username);\n const userRole = mapAuthorAssociation(input.authorAssociation);\n\n if (isAllowlisted) {\n return {\n trustTier: '1',\n userRole,\n isAllowlisted: true,\n wasDowngraded: false,\n reason: `User ${input.username} is on the maintainer allowlist`,\n };\n }\n\n const baseTier = ROLE_DEFAULT_TRUST[userRole];\n\n // If sanitized input available, check for downgrade\n if (input.sanitizedInput !== undefined) {\n const contentTier = input.sanitizedInput.trustTier;\n const downgraded = TRUST_TIER_NUMERIC[contentTier] > TRUST_TIER_NUMERIC[baseTier];\n\n return {\n trustTier: downgraded ? contentTier : baseTier,\n userRole,\n isAllowlisted: false,\n wasDowngraded: downgraded,\n reason: downgraded\n ? `Downgraded from Tier ${baseTier} to ${contentTier}: injection patterns detected`\n : `Role ${userRole} → Tier ${baseTier}`,\n };\n }\n\n return {\n trustTier: baseTier,\n userRole,\n isAllowlisted: false,\n wasDowngraded: false,\n reason: `Role ${userRole} → Tier ${baseTier}`,\n };\n}\n\n/**\n * Checks whether a trust tier can influence agent decisions.\n * Tiers 3-4 are informational only — they cannot drive actions.\n */\nexport function canInfluenceDecisions(tier: TrustTier): boolean {\n return TRUST_TIER_NUMERIC[tier] <= 2;\n}\n\n/**\n * Checks whether a trust tier requires corroboration with Tier 1 sources.\n * Tier 2 requires corroboration; Tier 1 is self-sufficient.\n */\nexport function requiresCorroboration(tier: TrustTier): boolean {\n return tier === '2';\n}\n\n/**\n * Returns the minimum trust tier required for a given action type.\n * Actions that modify state require higher trust.\n */\nexport function getRequiredTrustTier(actionType: string): TrustTier {\n switch (actionType) {\n case 'GeneratePatchPlan':\n return '1'; // Requires maintainer-level trust\n case 'DraftReply':\n case 'ProposeLabels':\n return '2'; // Requires at least collaborator-level trust\n case 'SummarizeIssue':\n case 'ClassifyIssue':\n case 'IdentifyDuplicates':\n return '3'; // Read-only, can use any input\n case 'RequestHumanApproval':\n case 'RefuseAction':\n return '4'; // Always allowed (safety actions)\n default:\n return '1'; // Unknown actions require highest trust\n }\n}\n","/**\n * nexus-agents/security - Policy Gate\n *\n * Deterministic rule engine that validates all agent actions before\n * GitHub state mutations can occur. No LLM in the validation path.\n *\n * Defense layer 2 of the three-layer hardening architecture.\n * See: docs/architecture/UNTRUSTED_INPUT_HARDENING.md\n *\n * @module security/policy-gate\n * (Source: Issue #818, #822 — Phase 2: Policy Gate)\n */\n\nimport { z } from 'zod';\n\nimport type { AgentAction, AgentActionType, SourceCitation } from './action-schema.js';\nimport { isMutatingAction, isReadOnlyAction, requiresCitation } from './action-schema.js';\nimport type { TrustTier } from './trust-types.js';\nimport { TRUST_TIER_NUMERIC } from './trust-types.js';\nimport { getRequiredTrustTier, canInfluenceDecisions } from './trust-classifier.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Violation detected by the policy gate.\n */\nexport const ViolationSchema = z.object({\n /** Machine-readable rule identifier. */\n rule: z.string().min(1),\n /** Human-readable description of the violation. */\n message: z.string().min(1),\n /** Severity: 'block' prevents execution, 'warn' logs only. */\n severity: z.enum(['block', 'warn']),\n});\nexport type Violation = z.infer<typeof ViolationSchema>;\n\n/**\n * Decision returned by the policy gate.\n */\nexport interface PolicyDecision {\n /** Whether the action is allowed to proceed. */\n readonly allowed: boolean;\n /** Whether human approval is required before execution. */\n readonly requiresApproval: boolean;\n /** All detected violations (blocking and warnings). */\n readonly violations: readonly Violation[];\n /** Timestamp of the evaluation (ISO 8601). */\n readonly evaluatedAt: string;\n}\n\n/**\n * Context for evaluating a policy decision.\n */\nexport interface ActionContext {\n /** Trust tier of the primary input source. */\n readonly inputTrustTier: TrustTier;\n /** Whether the agent currently has write access to the repository. */\n readonly hasWriteAccess: boolean;\n /** Whether the agent currently has access to secrets/tokens. */\n readonly hasSecretAccess: boolean;\n /** Set of labels that exist on the repository (for ProposeLabels validation). */\n readonly existingLabels?: ReadonlySet<string>;\n}\n\n// ============================================================================\n// Policy Rules\n// ============================================================================\n\n/** Extract sources from an action, handling actions that lack a sources field. */\nfunction getActionSources(action: AgentAction): readonly SourceCitation[] {\n if ('sources' in action) {\n return action.sources;\n }\n return [];\n}\n\n/** Check that citations exist for actions that require them. */\nfunction checkCitationRequirement(action: AgentAction): Violation | undefined {\n if (!requiresCitation(action.type)) return undefined;\n const sources = getActionSources(action);\n if (sources.length === 0) {\n return {\n rule: 'REQUIRE_CITATION',\n message: `Action '${action.type}' requires at least one source citation`,\n severity: 'block',\n };\n }\n return undefined;\n}\n\n/** Check that the input trust tier meets action requirements. */\nfunction checkTrustRequirement(action: AgentAction, context: ActionContext): Violation | undefined {\n const requiredTier = getRequiredTrustTier(action.type);\n const requiredNumeric = TRUST_TIER_NUMERIC[requiredTier];\n const inputNumeric = TRUST_TIER_NUMERIC[context.inputTrustTier];\n\n if (inputNumeric > requiredNumeric) {\n return {\n rule: 'INSUFFICIENT_TRUST',\n message: `Action '${action.type}' requires Tier ${requiredTier} but input is Tier ${context.inputTrustTier}`,\n severity: 'block',\n };\n }\n return undefined;\n}\n\n/** Check that Tier 3-4 input cannot drive decisions. */\nfunction checkInfluenceBlock(action: AgentAction, context: ActionContext): Violation | undefined {\n if (!canInfluenceDecisions(context.inputTrustTier) && isMutatingAction(action.type)) {\n return {\n rule: 'UNTRUSTED_INFLUENCE',\n message: `Tier ${context.inputTrustTier} input cannot drive mutating action '${action.type}'`,\n severity: 'block',\n };\n }\n return undefined;\n}\n\n/**\n * Enforce the Rule of Two: no agent may simultaneously\n * (a) process untrusted input, (b) have write access, AND (c) access secrets.\n */\nfunction checkRuleOfTwo(context: ActionContext): Violation | undefined {\n const isUntrusted = TRUST_TIER_NUMERIC[context.inputTrustTier] >= 3;\n if (isUntrusted && context.hasWriteAccess && context.hasSecretAccess) {\n return {\n rule: 'RULE_OF_TWO',\n message:\n 'Rule of Two violation: agent simultaneously processes untrusted input, has write access, and accesses secrets',\n severity: 'block',\n };\n }\n return undefined;\n}\n\n/** Check that proposed labels exist in the repository's label set. */\nfunction checkLabelValidity(action: AgentAction, context: ActionContext): Violation | undefined {\n if (action.type !== 'ProposeLabels') return undefined;\n const labels = context.existingLabels;\n if (labels === undefined) return undefined;\n\n const invalid = action.labels.filter((l) => !labels.has(l));\n if (invalid.length > 0) {\n return {\n rule: 'INVALID_LABELS',\n message: `Proposed labels not in repository: ${invalid.join(', ')}`,\n severity: 'block',\n };\n }\n return undefined;\n}\n\n/** Check that source citations meet trust requirements for the action. */\nfunction checkSourceTrustTiers(action: AgentAction): Violation | undefined {\n const sources = getActionSources(action);\n if (sources.length === 0) return undefined;\n\n const requiredTier = getRequiredTrustTier(action.type);\n const requiredNumeric = TRUST_TIER_NUMERIC[requiredTier];\n\n for (const source of sources) {\n if (source.type === 'issueComment') {\n const sourceTierNumeric = TRUST_TIER_NUMERIC[source.authorTrustTier];\n if (sourceTierNumeric > requiredNumeric) {\n return {\n rule: 'SOURCE_TRUST_MISMATCH',\n message: `Source from '${source.author}' (Tier ${source.authorTrustTier}) insufficient for action requiring Tier ${requiredTier}`,\n severity: 'warn',\n };\n }\n }\n }\n return undefined;\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Evaluate an agent action against the policy gate.\n *\n * This is a deterministic check — no LLM in the loop. Returns a\n * PolicyDecision indicating whether the action is allowed, requires\n * human approval, or is blocked.\n *\n * @param action - The validated AgentAction to evaluate.\n * @param context - The current execution context.\n * @returns PolicyDecision with violations and approval requirements.\n */\nexport function evaluatePolicy(action: AgentAction, context: ActionContext): PolicyDecision {\n const violations: Violation[] = [];\n\n const checks = [\n checkCitationRequirement(action),\n checkTrustRequirement(action, context),\n checkInfluenceBlock(action, context),\n checkRuleOfTwo(context),\n checkLabelValidity(action, context),\n checkSourceTrustTiers(action),\n ];\n\n for (const violation of checks) {\n if (violation !== undefined) {\n violations.push(violation);\n }\n }\n\n const hasBlockingViolation = violations.some((v) => v.severity === 'block');\n const needsApproval = !hasBlockingViolation && isMutatingAction(action.type);\n\n return {\n allowed: !hasBlockingViolation,\n requiresApproval: needsApproval,\n violations,\n evaluatedAt: new Date().toISOString(),\n };\n}\n\n/**\n * Quick check: can this action type proceed at all given the input trust tier?\n * Useful for early rejection before full policy evaluation.\n */\nexport function canProceed(actionType: AgentActionType, inputTrustTier: TrustTier): boolean {\n if (isReadOnlyAction(actionType)) {\n const requiredTier = getRequiredTrustTier(actionType);\n return TRUST_TIER_NUMERIC[inputTrustTier] <= TRUST_TIER_NUMERIC[requiredTier];\n }\n return canInfluenceDecisions(inputTrustTier);\n}\n","/**\n * nexus-agents/security - Typed Action Schema\n *\n * Zod schemas and TypeScript types for the typed action constraint system.\n * Agents processing untrusted GitHub input MUST emit only predefined typed\n * actions (never free-form tool calls). This module defines those action\n * schemas, validates them at runtime, and classifies them as read-only or\n * mutating for the policy gate.\n *\n * @module security/action-schema\n * (Source: Issue #818, #820)\n */\n\nimport { z } from 'zod';\n\nimport { TrustTierSchema } from './trust-types.js';\n\n// ============================================================================\n// Result Type (local — avoids circular dependency with core/types)\n// ============================================================================\n\n/** Validation result using the project Result pattern. */\nexport type ActionValidationResult =\n | { ok: true; value: AgentAction }\n | { ok: false; error: string };\n\n// ============================================================================\n// Source Citations\n// ============================================================================\n\n/** Source citation from a file tracked in the repository. */\nconst RepoFileSource = z.object({\n type: z.literal('repoFile'),\n path: z.string().min(1),\n line: z.number().int().positive().optional(),\n commit: z\n .string()\n .regex(/^[a-f0-9]{7,40}$/)\n .optional(),\n});\n\n/** Source citation from a GitHub issue comment. */\nconst IssueCommentSource = z.object({\n type: z.literal('issueComment'),\n issueNumber: z.number().int().positive(),\n commentId: z.number().int().positive(),\n author: z.string().min(1),\n authorTrustTier: TrustTierSchema,\n});\n\n/** Source citation from a CI pipeline result. */\nconst CIResultSource = z.object({\n type: z.literal('ciResult'),\n runId: z.number().int().positive(),\n status: z.enum(['pass', 'fail']),\n job: z.string().min(1),\n});\n\n/** Source citation from a policy or governance document. */\nconst PolicyDocSource = z.object({\n type: z.literal('policyDoc'),\n path: z.string().min(1),\n section: z.string().min(1),\n});\n\n/** Source citation from a maintainer slash-command or explicit instruction. */\nconst MaintainerCommandSource = z.object({\n type: z.literal('maintainerCommand'),\n username: z.string().min(1),\n commentId: z.number().int().positive(),\n});\n\n/**\n * Discriminated union of all valid source citation types.\n * Every decision-making action MUST cite at least one source.\n */\nexport const SourceCitationSchema = z.discriminatedUnion('type', [\n RepoFileSource,\n IssueCommentSource,\n CIResultSource,\n PolicyDocSource,\n MaintainerCommandSource,\n]);\n\n/** Inferred TypeScript type for a source citation. */\nexport type SourceCitation = z.infer<typeof SourceCitationSchema>;\n\n// ============================================================================\n// Typed Actions\n// ============================================================================\n\n/** Read-only analysis action: summarize an issue with citations. */\nconst SummarizeIssueAction = z.object({\n type: z.literal('SummarizeIssue'),\n summary: z.string().min(10).max(2000),\n sources: z.array(SourceCitationSchema).min(1).max(20),\n});\n\n/** Suggest labels for an issue (max 5, must match existing label set). */\nconst ProposeLabelsAction = z.object({\n type: z.literal('ProposeLabels'),\n labels: z.array(z.string()).min(1).max(5),\n reason: z.string().min(10).max(500),\n sources: z.array(SourceCitationSchema).min(1).max(20),\n});\n\n/** Draft a reply comment (always requires human approval before posting). */\nconst DraftReplyAction = z.object({\n type: z.literal('DraftReply'),\n body: z.string().min(10).max(2000),\n requiresApproval: z.literal(true),\n sources: z.array(SourceCitationSchema).min(1).max(20),\n});\n\n/** Explicit escalation to a human maintainer with reason and context. */\nconst RequestHumanApprovalAction = z.object({\n type: z.literal('RequestHumanApproval'),\n reason: z.string().min(10).max(500),\n context: z.string().min(10).max(2000),\n});\n\n/**\n * Propose a set of file modifications (requires maintainer corroboration).\n * Forbidden from Tier 3-4 input without maintainer corroboration.\n */\nconst GeneratePatchPlanAction = z.object({\n type: z.literal('GeneratePatchPlan'),\n files: z\n .array(\n z.object({\n path: z.string().min(1),\n operation: z.enum(['modify', 'create', 'delete']),\n description: z.string().min(10).max(500),\n })\n )\n .min(1)\n .max(10),\n rationale: z.string().min(10).max(1000),\n requiresApproval: z.literal(true),\n sources: z.array(SourceCitationSchema).min(2).max(20),\n});\n\n/** Categorize an issue by type with confidence score. */\nconst ClassifyIssueAction = z.object({\n type: z.literal('ClassifyIssue'),\n category: z.enum(['bug', 'feature', 'question', 'documentation', 'security', 'performance']),\n confidence: z.number().min(0).max(1),\n sources: z.array(SourceCitationSchema).min(1).max(20),\n});\n\n/** Identify potential duplicate issues with similarity scores. */\nconst IdentifyDuplicatesAction = z.object({\n type: z.literal('IdentifyDuplicates'),\n candidates: z.array(z.number().int().positive()).min(1).max(10),\n similarity: z.array(z.number().min(0).max(1)),\n sources: z.array(SourceCitationSchema).min(1).max(20),\n});\n\n/** Explicit refusal to act, with escalation target. */\nconst RefuseActionAction = z.object({\n type: z.literal('RefuseAction'),\n reason: z.string().min(10).max(500),\n escalateTo: z.enum(['maintainer', 'security']),\n});\n\n/** Handoff delegation from one agent to another by capability. (Issue #834) */\nconst HandoffMessageAction = z.object({\n type: z.literal('HandoffMessage'),\n targetCapability: z.string().min(1).max(100),\n reason: z.string().min(5).max(500),\n inputTrustTier: z.enum(['1', '2', '3', '4']),\n sources: z.array(SourceCitationSchema).min(1).max(20),\n});\n\n/**\n * Discriminated union of all valid agent actions.\n * This is the ONLY schema agents may emit when processing untrusted input.\n */\nexport const AgentActionSchema = z.discriminatedUnion('type', [\n SummarizeIssueAction,\n ProposeLabelsAction,\n DraftReplyAction,\n RequestHumanApprovalAction,\n GeneratePatchPlanAction,\n ClassifyIssueAction,\n IdentifyDuplicatesAction,\n RefuseActionAction,\n HandoffMessageAction,\n]);\n\n/** Inferred TypeScript type for an agent action. */\nexport type AgentAction = z.infer<typeof AgentActionSchema>;\n\n/** All valid action type discriminator values. */\nexport type AgentActionType = AgentAction['type'];\n\n// ============================================================================\n// Action Classification\n// ============================================================================\n\n/**\n * Action types that are read-only and do not modify GitHub state.\n * These can be executed without human approval (subject to policy gate).\n */\nconst READ_ONLY_ACTIONS: ReadonlySet<AgentActionType> = new Set<AgentActionType>([\n 'SummarizeIssue',\n 'ClassifyIssue',\n 'IdentifyDuplicates',\n 'RefuseAction',\n 'RequestHumanApproval',\n 'HandoffMessage',\n]);\n\n/**\n * Action types that can modify GitHub state (labels, comments, code).\n * These always require human approval before execution.\n */\nconst MUTATING_ACTIONS: ReadonlySet<AgentActionType> = new Set<AgentActionType>([\n 'ProposeLabels',\n 'DraftReply',\n 'GeneratePatchPlan',\n]);\n\n/**\n * Action types that MUST include at least one source citation.\n * Escalation and refusal actions are exempt (they report inability to act).\n */\nconst CITATION_REQUIRED_ACTIONS: ReadonlySet<AgentActionType> = new Set<AgentActionType>([\n 'SummarizeIssue',\n 'ProposeLabels',\n 'DraftReply',\n 'GeneratePatchPlan',\n 'ClassifyIssue',\n 'IdentifyDuplicates',\n 'HandoffMessage',\n]);\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Validate an unknown value against the AgentActionSchema.\n * Returns a Result: `{ ok: true; value }` on success or `{ ok: false; error }` on failure.\n *\n * @param input - The value to validate (typically parsed JSON from an agent).\n * @returns Validation result following the project Result pattern.\n */\nexport function validateAgentAction(input: unknown): ActionValidationResult {\n const result = AgentActionSchema.safeParse(input);\n if (result.success) {\n return { ok: true, value: result.data };\n }\n const messages = result.error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`);\n return { ok: false, error: `Action validation failed: ${messages.join('; ')}` };\n}\n\n/**\n * Check whether an action type is read-only (does not modify GitHub state).\n *\n * @param actionType - The action type discriminator value.\n * @returns True if the action is read-only.\n */\nexport function isReadOnlyAction(actionType: AgentActionType): boolean {\n return READ_ONLY_ACTIONS.has(actionType);\n}\n\n/**\n * Check whether an action type can modify GitHub state.\n * Mutating actions always require human approval before execution.\n *\n * @param actionType - The action type discriminator value.\n * @returns True if the action can modify state.\n */\nexport function isMutatingAction(actionType: AgentActionType): boolean {\n return MUTATING_ACTIONS.has(actionType);\n}\n\n/**\n * Check whether an action type requires at least one source citation.\n * Escalation (RequestHumanApproval) and refusal (RefuseAction) are exempt.\n *\n * @param actionType - The action type discriminator value.\n * @returns True if the action must include source citations.\n */\nexport function requiresCitation(actionType: AgentActionType): boolean {\n return CITATION_REQUIRED_ACTIONS.has(actionType);\n}\n","/**\n * nexus-agents/security - Corroboration Validator\n *\n * Validates that agent decisions are backed by sufficient evidence from\n * authoritative sources. Each action type has specific corroboration\n * requirements (e.g., closing issues requires CI pass or maintainer comment).\n *\n * Defense layer 3 of the three-layer hardening architecture.\n * See: docs/architecture/UNTRUSTED_INPUT_HARDENING.md\n *\n * @module security/corroboration-validator\n * (Source: Issue #818, #823 — Phase 2: Corroboration Validator)\n */\n\nimport type { AgentAction, AgentActionType, SourceCitation } from './action-schema.js';\nimport type { TrustTier } from './trust-types.js';\nimport { TRUST_TIER_NUMERIC } from './trust-types.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Result of corroboration validation.\n */\nexport interface CorroborationResult {\n /** Whether corroboration requirements are satisfied. */\n readonly satisfied: boolean;\n /** Sources that contributed to corroboration. */\n readonly corroboratingSources: readonly SourceCitation[];\n /** Missing corroboration requirements (empty when satisfied). */\n readonly missing: readonly string[];\n /** Action type that was validated. */\n readonly actionType: AgentActionType;\n}\n\n/**\n * Rule defining what corroboration an action requires.\n */\nexport interface CorroborationRule {\n /** Human-readable description of what's required. */\n readonly description: string;\n /** Predicate: does this set of sources satisfy the requirement? */\n readonly isSatisfied: (sources: readonly SourceCitation[]) => boolean;\n}\n\n// ============================================================================\n// Source Helpers\n// ============================================================================\n\n/** Check if sources include a passing CI result. */\nfunction hasCIPass(sources: readonly SourceCitation[]): boolean {\n return sources.some((s) => s.type === 'ciResult' && s.status === 'pass');\n}\n\n/** Check if sources include a maintainer command. */\nfunction hasMaintainerCommand(sources: readonly SourceCitation[]): boolean {\n return sources.some((s) => s.type === 'maintainerCommand');\n}\n\n/** Check if sources include a Tier 1 issue comment. */\nfunction hasTier1Comment(sources: readonly SourceCitation[]): boolean {\n return sources.some((s) => s.type === 'issueComment' && s.authorTrustTier === '1');\n}\n\n/** Check if sources include a repo file reference. */\nfunction hasRepoFileRef(sources: readonly SourceCitation[]): boolean {\n return sources.some((s) => s.type === 'repoFile');\n}\n\n/** Check if sources include a repo file with line reference. */\nfunction hasCodeLevelEvidence(sources: readonly SourceCitation[]): boolean {\n return sources.some((s) => s.type === 'repoFile' && s.line !== undefined);\n}\n\n/** Check if sources include a policy document reference. */\nfunction hasPolicyDocRef(sources: readonly SourceCitation[]): boolean {\n return sources.some((s) => s.type === 'policyDoc');\n}\n\n/** Check if at least one source meets a minimum trust tier. */\nfunction hasSourceAtTier(sources: readonly SourceCitation[], maxTier: TrustTier): boolean {\n const maxNumeric = TRUST_TIER_NUMERIC[maxTier];\n return sources.some((s) => {\n if (s.type === 'issueComment') {\n return TRUST_TIER_NUMERIC[s.authorTrustTier] <= maxNumeric;\n }\n // Repo files, CI results, policy docs, maintainer commands = Tier 1\n return true;\n });\n}\n\n// ============================================================================\n// Per-Action Corroboration Rules\n// ============================================================================\n\n/**\n * Corroboration rules for each action type.\n * See CLAUDE.md \"Corroboration Requirements\" table.\n */\nconst ACTION_CORROBORATION_RULES: Readonly<Record<AgentActionType, readonly CorroborationRule[]>> =\n {\n SummarizeIssue: [\n {\n description: 'At least one Tier 1/2 source',\n isSatisfied: (s) => hasSourceAtTier(s, '2'),\n },\n ],\n ProposeLabels: [\n {\n description: 'Keyword match in issue body (repo file) OR maintainer instruction',\n isSatisfied: (s) => hasRepoFileRef(s) || hasMaintainerCommand(s) || hasPolicyDocRef(s),\n },\n ],\n DraftReply: [\n {\n description: 'At least one Tier 1 source citation',\n isSatisfied: (s) =>\n hasRepoFileRef(s) ||\n hasCIPass(s) ||\n hasMaintainerCommand(s) ||\n hasPolicyDocRef(s) ||\n hasTier1Comment(s),\n },\n ],\n GeneratePatchPlan: [\n {\n description: 'Failing test OR bug reproduction steps (code-level evidence)',\n isSatisfied: (s) => hasCodeLevelEvidence(s) || hasCIPass(s),\n },\n {\n description: 'Maintainer corroboration',\n isSatisfied: (s) => hasMaintainerCommand(s) || hasTier1Comment(s),\n },\n ],\n ClassifyIssue: [\n {\n description: 'At least one source citation',\n isSatisfied: (s) => s.length > 0,\n },\n ],\n IdentifyDuplicates: [\n {\n description: 'At least one source citation',\n isSatisfied: (s) => s.length > 0,\n },\n ],\n RequestHumanApproval: [],\n RefuseAction: [],\n HandoffMessage: [\n {\n description: 'At least one source citation for trust tier propagation',\n isSatisfied: (s) => s.length > 0,\n },\n ],\n };\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Validate that an agent action has sufficient corroboration from\n * authoritative sources.\n *\n * @param action - The validated AgentAction to check.\n * @returns CorroborationResult indicating whether requirements are met.\n */\nexport function validateCorroboration(action: AgentAction): CorroborationResult {\n const rules = ACTION_CORROBORATION_RULES[action.type];\n const sources: readonly SourceCitation[] = 'sources' in action ? action.sources : [];\n\n if (rules.length === 0) {\n return {\n satisfied: true,\n corroboratingSources: sources,\n missing: [],\n actionType: action.type,\n };\n }\n\n const missing: string[] = [];\n const corroborating: SourceCitation[] = [];\n\n for (const rule of rules) {\n if (rule.isSatisfied(sources)) {\n for (const s of sources) {\n if (!corroborating.includes(s)) {\n corroborating.push(s);\n }\n }\n } else {\n missing.push(rule.description);\n }\n }\n\n return {\n satisfied: missing.length === 0,\n corroboratingSources: corroborating,\n missing,\n actionType: action.type,\n };\n}\n\n/**\n * Get the corroboration rules for an action type.\n * Useful for displaying requirements to users.\n */\nexport function getCorroborationRules(actionType: AgentActionType): readonly CorroborationRule[] {\n return ACTION_CORROBORATION_RULES[actionType];\n}\n","/**\n * nexus-agents/security - Reputation Model\n *\n * Lightweight trust model for GitHub users that assesses reputation\n * based on account age, contribution history, and behavioral signals.\n * Integrates with the trust classifier for comprehensive trust assessment.\n *\n * @module security/reputation-model\n * (Source: Issue #818, #824 — Phase 3: Reputation Model)\n */\n\nimport { z } from 'zod';\n\nimport { getTimeProvider } from '../core/index.js';\nimport type { TrustTier, GitHubUserRole, InjectionFlag } from './trust-types.js';\nimport { TRUST_TIER_NUMERIC, ROLE_DEFAULT_TRUST } from './trust-types.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Signals that indicate a suspicious actor.\n */\nexport const SuspiciousSignalSchema = z.enum([\n 'new_account',\n 'no_prior_contributions',\n 'injection_patterns_detected',\n 'rapid_comments',\n 'mismatched_authority_claim',\n]);\nexport type SuspiciousSignal = z.infer<typeof SuspiciousSignalSchema>;\n\n/**\n * GitHub user metadata for reputation assessment.\n */\nexport interface GitHubUserMetadata {\n readonly username: string;\n readonly accountAgeDays: number;\n readonly priorContributions: number;\n readonly recentCommentCount: number;\n readonly recentCommentWindowMinutes: number;\n readonly authorAssociation: string;\n readonly injectionFlags: readonly InjectionFlag[];\n}\n\n/**\n * Result of a reputation assessment.\n */\nexport interface ReputationAssessment {\n readonly username: string;\n readonly userRole: GitHubUserRole;\n readonly suspiciousSignals: readonly SuspiciousSignal[];\n readonly isSuspicious: boolean;\n readonly effectiveTrustTier: TrustTier;\n readonly reputationScore: number;\n readonly reason: string;\n readonly assessedAt: string;\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\n/** Thresholds for suspicious behavior detection. */\n/** Approximate days per year, used to normalize account age to a 0–10 scale. */\nconst DAYS_PER_YEAR_APPROX = 36.5;\n\nconst SUSPICIOUS_THRESHOLDS = {\n /** Account younger than this (days) is flagged. */\n newAccountDays: 30,\n /** Fewer contributions than this is flagged. */\n minContributions: 1,\n /** More comments than this in the window triggers rapid-comment flag. */\n rapidCommentThreshold: 5,\n /** Time window (minutes) for rapid comment detection. */\n rapidCommentWindowMinutes: 10,\n} as const;\n\n// ============================================================================\n// Reputation Cache\n// ============================================================================\n\ninterface CacheEntry {\n assessment: ReputationAssessment;\n expiresAt: number;\n}\n\n// Canonical source: config/timeouts.ts (Issue #1046)\nimport { CACHE_TIMEOUTS } from '../config/timeouts.js';\n\nconst DEFAULT_TTL_MS: number = CACHE_TIMEOUTS.reputationTtlMs;\nconst DEFAULT_MAX_SIZE = 1000;\n\n/**\n * In-memory reputation cache with TTL and max size.\n * Reduces redundant assessments for the same user within a short window.\n * Evicts oldest entries when max size is exceeded.\n */\nexport class ReputationCache {\n private readonly cache = new Map<string, CacheEntry>();\n private readonly ttlMs: number;\n private readonly maxSize: number;\n\n constructor(ttlMs = DEFAULT_TTL_MS, maxSize = DEFAULT_MAX_SIZE) {\n this.ttlMs = ttlMs;\n this.maxSize = maxSize;\n }\n\n get(username: string): ReputationAssessment | undefined {\n const entry = this.cache.get(username);\n if (entry === undefined) return undefined;\n if (getTimeProvider().now() > entry.expiresAt) {\n this.cache.delete(username);\n return undefined;\n }\n return entry.assessment;\n }\n\n set(username: string, assessment: ReputationAssessment): void {\n if (this.cache.size >= this.maxSize && !this.cache.has(username)) {\n this.evictOldest();\n }\n this.cache.set(username, {\n assessment,\n expiresAt: getTimeProvider().now() + this.ttlMs,\n });\n }\n\n /** Evict a batch of oldest entries (10% of maxSize, minimum 1). */\n private evictOldest(): void {\n const batchSize = Math.max(1, Math.floor(this.maxSize * 0.1));\n const keys = this.cache.keys();\n for (let i = 0; i < batchSize; i++) {\n const next = keys.next();\n if (next.done === true) break;\n this.cache.delete(next.value);\n }\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n get size(): number {\n return this.cache.size;\n }\n}\n\n// ============================================================================\n// Suspicious Signal Detection\n// ============================================================================\n\n/** Detect all suspicious signals from user metadata. */\nfunction detectSuspiciousSignals(metadata: GitHubUserMetadata): SuspiciousSignal[] {\n const signals: SuspiciousSignal[] = [];\n\n if (metadata.accountAgeDays < SUSPICIOUS_THRESHOLDS.newAccountDays) {\n signals.push('new_account');\n }\n\n if (metadata.priorContributions < SUSPICIOUS_THRESHOLDS.minContributions) {\n signals.push('no_prior_contributions');\n }\n\n // Only count hostile-tier injection flags — benign flags like\n // instruction_pattern (triggered by \"please remove\") should not\n // trigger the injection_patterns_detected signal.\n const hostileInjectionFlags: readonly InjectionFlag[] = [\n 'system_prompt_manipulation',\n 'fake_conversation',\n 'authority_claim',\n 'hidden_content',\n ];\n const hasHostileFlags = metadata.injectionFlags.some((f) => hostileInjectionFlags.includes(f));\n if (hasHostileFlags) {\n signals.push('injection_patterns_detected');\n }\n\n if (\n metadata.recentCommentCount > SUSPICIOUS_THRESHOLDS.rapidCommentThreshold &&\n metadata.recentCommentWindowMinutes <= SUSPICIOUS_THRESHOLDS.rapidCommentWindowMinutes\n ) {\n signals.push('rapid_comments');\n }\n\n // Authority claim from non-maintainer role\n const hasAuthorityClaim = metadata.injectionFlags.includes('authority_claim');\n const association = metadata.authorAssociation.toUpperCase();\n const isAuthoritative = association === 'OWNER' || association === 'MEMBER';\n if (hasAuthorityClaim && !isAuthoritative) {\n signals.push('mismatched_authority_claim');\n }\n\n return signals;\n}\n\n/** Calculate a 0-100 reputation score. */\nfunction calculateReputationScore(\n metadata: GitHubUserMetadata,\n signals: readonly SuspiciousSignal[],\n userRole: GitHubUserRole\n): number {\n let score = 50; // baseline\n\n // Role bonus\n const roleBonus: Record<GitHubUserRole, number> = {\n owner: 40,\n maintainer: 35,\n collaborator: 25,\n contributor: 15,\n member: 5,\n unknown: 0,\n };\n score += roleBonus[userRole];\n\n // Account age bonus (max +10)\n score += Math.min(metadata.accountAgeDays / DAYS_PER_YEAR_APPROX, 10);\n\n // Contribution bonus (max +10)\n score += Math.min(metadata.priorContributions, 10);\n\n // Suspicious signal penalties\n const signalPenalty: Record<SuspiciousSignal, number> = {\n new_account: -15,\n no_prior_contributions: -10,\n injection_patterns_detected: -25,\n rapid_comments: -20,\n mismatched_authority_claim: -30,\n };\n for (const signal of signals) {\n score += signalPenalty[signal];\n }\n\n return Math.max(0, Math.min(100, Math.round(score)));\n}\n\n/** Map role string to GitHubUserRole. */\nfunction mapRole(association: string): GitHubUserRole {\n switch (association.toUpperCase()) {\n case 'OWNER':\n return 'owner';\n case 'MEMBER':\n return 'member';\n case 'COLLABORATOR':\n return 'collaborator';\n case 'CONTRIBUTOR':\n return 'contributor';\n default:\n return 'unknown';\n }\n}\n\n/** Determine effective trust tier from signals and role. */\nfunction determineEffectiveTier(\n userRole: GitHubUserRole,\n signals: readonly SuspiciousSignal[]\n): TrustTier {\n const baseTier = ROLE_DEFAULT_TRUST[userRole];\n\n // Hostile signals → Tier 4\n const hostileSignals: SuspiciousSignal[] = [\n 'injection_patterns_detected',\n 'mismatched_authority_claim',\n ];\n if (signals.some((s) => hostileSignals.includes(s))) return '4';\n\n // Multiple suspicious signals → downgrade by 1\n if (signals.length >= 2) {\n const baseNumeric = TRUST_TIER_NUMERIC[baseTier];\n const downgraded = Math.min(baseNumeric + 1, 4);\n return String(downgraded) as TrustTier;\n }\n\n return baseTier;\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Assess a GitHub user's reputation for trust classification.\n *\n * @param metadata - User metadata from GitHub API or local context.\n * @param cache - Optional cache instance for TTL-based deduplication.\n * @returns ReputationAssessment with trust tier and suspicious signals.\n */\nexport function assessReputation(\n metadata: GitHubUserMetadata,\n cache?: ReputationCache\n): ReputationAssessment {\n // Check cache first\n const cached = cache?.get(metadata.username);\n if (cached !== undefined) return cached;\n\n const userRole = mapRole(metadata.authorAssociation);\n const signals = detectSuspiciousSignals(metadata);\n const score = calculateReputationScore(metadata, signals, userRole);\n const effectiveTier = determineEffectiveTier(userRole, signals);\n\n const assessment: ReputationAssessment = {\n username: metadata.username,\n userRole,\n suspiciousSignals: signals,\n isSuspicious: signals.length > 0,\n effectiveTrustTier: effectiveTier,\n reputationScore: score,\n reason: buildReason(userRole, signals, effectiveTier),\n assessedAt: new Date().toISOString(),\n };\n\n cache?.set(metadata.username, assessment);\n return assessment;\n}\n\n/** Build a human-readable reason string. */\nfunction buildReason(\n role: GitHubUserRole,\n signals: readonly SuspiciousSignal[],\n tier: TrustTier\n): string {\n if (signals.length === 0) {\n return `Role ${role} → Tier ${tier} (no suspicious signals)`;\n }\n const signalList = signals.join(', ');\n return `Role ${role} → Tier ${tier} (signals: ${signalList})`;\n}\n","/**\n * nexus-agents/dogfooding - GitHub API Client\n *\n * Minimal GitHub REST API client for PR review operations.\n * Uses native fetch API (Node.js 22+).\n *\n * @module dogfooding/github-client\n * (Source: Issue #161, Alignment Roadmap Phase 3)\n * (Source: GitHub REST API v2022-11-28)\n */\n\nimport { execFileSync } from 'node:child_process';\nimport type { Result } from '../core/index.js';\nimport { ok, err, createLogger } from '../core/index.js';\nimport type { PRMetadata, PRFileChange, ReviewDecision } from './pr-review-types.js';\nimport type { IssueMetadata, IssueComment } from './issue-triage-types.js';\n\nconst logger = createLogger({ component: 'GitHubClient' });\n\n// ============================================================================\n// Safe extraction helpers for untyped API responses\n// ============================================================================\n\n/** Safely extract a string from an unknown value. */\nfunction str(val: unknown, fallback = ''): string {\n return typeof val === 'string' ? val : fallback;\n}\n\n/** Safely extract a number from an unknown value. */\nfunction num(val: unknown, fallback = 0): number {\n return typeof val === 'number' ? val : fallback;\n}\n\n/** Safely extract a boolean from an unknown value. */\nfunction bool(val: unknown, fallback = false): boolean {\n return typeof val === 'boolean' ? val : fallback;\n}\n\n/** Safely extract .login from a nested user-like object. */\nfunction login(val: unknown): string {\n if (typeof val === 'object' && val !== null && 'login' in val) {\n const rec = val as Record<string, unknown>;\n return str(rec.login);\n }\n return '';\n}\n\n/** Safely extract .ref from a branch-like object. */\nfunction ref(val: unknown): string {\n if (typeof val === 'object' && val !== null && 'ref' in val) {\n const rec = val as Record<string, unknown>;\n return str(rec.ref);\n }\n return '';\n}\n\n/** Safely extract .sha from a branch-like object. */\nfunction sha(val: unknown): string {\n if (typeof val === 'object' && val !== null && 'sha' in val) {\n const rec = val as Record<string, unknown>;\n return str(rec.sha);\n }\n return '';\n}\n\n/** Safely extract label names from an array of label objects. */\nfunction labelNames(val: unknown): string[] {\n if (!Array.isArray(val)) return [];\n return val\n .filter((item): item is Record<string, unknown> => typeof item === 'object' && item !== null)\n .map((item) => str(item.name))\n .filter((name) => name.length > 0);\n}\n\n/**\n * GitHub API error.\n */\nexport class GitHubError extends Error {\n constructor(\n message: string,\n readonly statusCode: number,\n readonly context?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'GitHubError';\n }\n}\n\n/**\n * GitHub API client configuration.\n */\nexport interface GitHubClientConfig {\n /** GitHub token for authentication */\n readonly token: string;\n /** API base URL (for GitHub Enterprise) */\n readonly baseUrl?: string;\n /** Request timeout in ms */\n readonly timeoutMs?: number;\n}\n\n/**\n * Default GitHub API configuration.\n */\nconst DEFAULT_CONFIG = {\n baseUrl: 'https://api.github.com',\n timeoutMs: 30000,\n};\n\n/**\n * GitHub API version header.\n */\nconst API_VERSION = '2022-11-28';\n\n/**\n * GitHub REST API client for PR operations.\n */\nexport class GitHubClient {\n private readonly config: Required<Omit<GitHubClientConfig, 'token'>> & { token: string };\n\n constructor(config: GitHubClientConfig) {\n this.config = {\n token: config.token,\n baseUrl: config.baseUrl ?? DEFAULT_CONFIG.baseUrl,\n timeoutMs: config.timeoutMs ?? DEFAULT_CONFIG.timeoutMs,\n };\n }\n\n /**\n * Fetches pull request metadata including file changes.\n */\n async getPullRequest(\n owner: string,\n repo: string,\n prNumber: number\n ): Promise<Result<PRMetadata, GitHubError>> {\n const prResult = await this.fetchPRData(owner, repo, prNumber);\n if (!prResult.ok) return prResult;\n\n const filesResult = await this.fetchPRFiles(owner, repo, prNumber);\n if (!filesResult.ok) return filesResult;\n\n const pr = prResult.value;\n const files = filesResult.value;\n\n const metadata: PRMetadata = {\n number: num(pr.number),\n title: str(pr.title),\n body: str(pr.body),\n author: login(pr.user),\n authorAssociation: str(pr.author_association, 'NONE'),\n base: ref(pr.base),\n head: ref(pr.head),\n headSha: sha(pr.head),\n owner,\n repo,\n url: str(pr.html_url),\n draft: bool(pr.draft),\n labels: labelNames(pr.labels),\n files,\n additions: num(pr.additions),\n deletions: num(pr.deletions),\n };\n\n logger.info('Fetched PR metadata', {\n prNumber,\n fileCount: files.length,\n additions: metadata.additions,\n deletions: metadata.deletions,\n });\n\n return ok(metadata);\n }\n\n /**\n * Posts a review comment to a pull request.\n */\n async createReview(\n owner: string,\n repo: string,\n prNumber: number,\n body: string,\n event: ReviewDecision\n ): Promise<Result<{ id: number }, GitHubError>> {\n const ghEvent = mapDecisionToGitHubEvent(event);\n\n const result = await this.request<{ id: number }>(\n 'POST',\n `/repos/${owner}/${repo}/pulls/${String(prNumber)}/reviews`,\n { body, event: ghEvent }\n );\n\n if (result.ok) {\n logger.info('Created PR review', { prNumber, event: ghEvent, reviewId: result.value.id });\n }\n\n return result;\n }\n\n /**\n * Posts a general comment on a pull request.\n */\n async createComment(\n owner: string,\n repo: string,\n prNumber: number,\n body: string\n ): Promise<Result<{ id: number }, GitHubError>> {\n const result = await this.request<{ id: number }>(\n 'POST',\n `/repos/${owner}/${repo}/issues/${String(prNumber)}/comments`,\n { body }\n );\n\n if (result.ok) {\n logger.info('Created PR comment', { prNumber, commentId: result.value.id });\n }\n\n return result;\n }\n\n /**\n * Fetches issue metadata from GitHub API.\n */\n async getIssue(\n owner: string,\n repo: string,\n issueNumber: number\n ): Promise<Result<IssueMetadata, GitHubError>> {\n const result = await this.request<Record<string, unknown>>(\n 'GET',\n `/repos/${owner}/${repo}/issues/${String(issueNumber)}`\n );\n\n if (!result.ok) return result;\n\n const issue = result.value;\n const metadata: IssueMetadata = {\n number: num(issue.number),\n title: str(issue.title),\n body: str(issue.body),\n author: login(issue.user),\n authorAssociation: str(issue.author_association, 'NONE'),\n owner,\n repo,\n url: str(issue.html_url),\n state: str(issue.state),\n labels: labelNames(issue.labels),\n createdAt: str(issue.created_at),\n };\n\n logger.info('Fetched issue metadata', { issueNumber, state: metadata.state });\n return ok(metadata);\n }\n\n /**\n * Fetches comments on a GitHub issue.\n */\n async listIssueComments(\n owner: string,\n repo: string,\n issueNumber: number\n ): Promise<Result<IssueComment[], GitHubError>> {\n const result = await this.request<Array<Record<string, unknown>>>(\n 'GET',\n `/repos/${owner}/${repo}/issues/${String(issueNumber)}/comments`\n );\n\n if (!result.ok) return result;\n\n const comments: IssueComment[] = result.value.map((c) => ({\n id: num(c.id),\n body: str(c.body),\n author: login(c.user),\n authorAssociation: str(c.author_association, 'NONE'),\n createdAt: str(c.created_at),\n }));\n\n logger.info('Fetched issue comments', { issueNumber, count: comments.length });\n return ok(comments);\n }\n\n /**\n * Adds labels to a GitHub issue.\n */\n async addLabels(\n owner: string,\n repo: string,\n issueNumber: number,\n labels: readonly string[]\n ): Promise<Result<readonly string[], GitHubError>> {\n const result = await this.request<Array<{ name: string }>>(\n 'POST',\n `/repos/${owner}/${repo}/issues/${String(issueNumber)}/labels`,\n { labels: [...labels] }\n );\n\n if (!result.ok) return result;\n\n const addedLabels = result.value.map((l) => l.name);\n logger.info('Added labels to issue', { issueNumber, labels: addedLabels });\n return ok(addedLabels);\n }\n\n /**\n * Fetches PR data from GitHub API.\n */\n private async fetchPRData(\n owner: string,\n repo: string,\n prNumber: number\n ): Promise<Result<Record<string, unknown>, GitHubError>> {\n return this.request<Record<string, unknown>>(\n 'GET',\n `/repos/${owner}/${repo}/pulls/${String(prNumber)}`\n );\n }\n\n /**\n * Fetches PR file changes from GitHub API.\n */\n private async fetchPRFiles(\n owner: string,\n repo: string,\n prNumber: number\n ): Promise<Result<PRFileChange[], GitHubError>> {\n const result = await this.request<Array<Record<string, unknown>>>(\n 'GET',\n `/repos/${owner}/${repo}/pulls/${String(prNumber)}/files`\n );\n\n if (!result.ok) return result;\n\n const files: PRFileChange[] = result.value.map((f) => ({\n filename: str(f.filename),\n status: mapFileStatus(str(f.status)),\n additions: num(f.additions),\n deletions: num(f.deletions),\n ...(typeof f.patch === 'string' ? { patch: f.patch } : {}),\n ...(typeof f.previous_filename === 'string' ? { previousFilename: f.previous_filename } : {}),\n }));\n\n return ok(files);\n }\n\n /**\n * Makes a request to the GitHub API.\n */\n private async request<T>(\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n path: string,\n body?: Record<string, unknown>\n ): Promise<Result<T, GitHubError>> {\n const url = `${this.config.baseUrl}${path}`;\n const controller = new AbortController();\n const timeout = setTimeout(() => {\n controller.abort();\n }, this.config.timeoutMs);\n\n try {\n const fetchOptions: RequestInit = {\n method,\n headers: {\n Authorization: `Bearer ${this.config.token}`,\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': API_VERSION,\n 'User-Agent': 'nexus-agents/1.0',\n ...(body !== undefined && { 'Content-Type': 'application/json' }),\n },\n signal: controller.signal,\n };\n\n if (body !== undefined) {\n fetchOptions.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, fetchOptions);\n\n clearTimeout(timeout);\n\n if (!response.ok) {\n const errorBody = await response.text();\n logger.error('GitHub API error', new Error(errorBody), {\n status: response.status,\n path,\n });\n return err(\n new GitHubError(`GitHub API error: ${response.statusText}`, response.status, {\n path,\n body: errorBody,\n })\n );\n }\n\n const data = (await response.json()) as T;\n return ok(data);\n } catch (error) {\n clearTimeout(timeout);\n const message = error instanceof Error ? error.message : 'Unknown error';\n logger.error('GitHub request failed', error instanceof Error ? error : new Error(message));\n return err(new GitHubError(message, 0, { path }));\n }\n }\n}\n\n/**\n * Maps GitHub file status to our enum.\n */\nfunction mapFileStatus(status: string): PRFileChange['status'] {\n switch (status) {\n case 'added':\n return 'added';\n case 'removed':\n return 'removed';\n case 'modified':\n return 'modified';\n case 'renamed':\n return 'renamed';\n case 'copied':\n return 'copied';\n default:\n return 'modified';\n }\n}\n\n/**\n * Maps our review decision to GitHub event type.\n */\nfunction mapDecisionToGitHubEvent(decision: ReviewDecision): string {\n switch (decision) {\n case 'approve':\n return 'APPROVE';\n case 'request_changes':\n return 'REQUEST_CHANGES';\n case 'comment':\n return 'COMMENT';\n }\n}\n\n/**\n * Parses a PR URL into owner, repo, and number.\n */\nexport function parsePRUrl(url: string): Result<\n {\n owner: string;\n repo: string;\n prNumber: number;\n },\n Error\n> {\n // Handle formats:\n // https://github.com/owner/repo/pull/123\n // owner/repo#123\n // owner/repo/pull/123\n\n const httpPattern = /github\\.com\\/([^/]+)\\/([^/]+)\\/pull\\/(\\d+)/;\n const shortPattern = /^([^/]+)\\/([^/#]+)(?:#|\\/pull\\/)(\\d+)$/;\n\n const match = httpPattern.exec(url) ?? shortPattern.exec(url);\n\n if (match === null) {\n return err(new Error(`Invalid PR URL format: ${url}`));\n }\n\n const owner = match[1];\n const repo = match[2];\n const numberStr = match[3];\n\n if (owner === undefined || repo === undefined || numberStr === undefined) {\n return err(new Error(`Invalid PR URL format: ${url}`));\n }\n\n const prNumber = parseInt(numberStr, 10);\n\n if (isNaN(prNumber)) {\n return err(new Error(`Invalid PR URL format: ${url}`));\n }\n\n return ok({ owner, repo, prNumber });\n}\n\n/**\n * Parses an issue URL into owner, repo, and number.\n */\nexport function parseIssueUrl(url: string): Result<\n {\n owner: string;\n repo: string;\n issueNumber: number;\n },\n Error\n> {\n // Handle formats:\n // https://github.com/owner/repo/issues/123\n // owner/repo#123\n\n const httpPattern = /github\\.com\\/([^/]+)\\/([^/]+)\\/issues\\/(\\d+)/;\n const shortPattern = /^([^/]+)\\/([^/#]+)#(\\d+)$/;\n\n const match = httpPattern.exec(url) ?? shortPattern.exec(url);\n\n if (match === null) {\n return err(new Error(`Invalid issue URL format: ${url}`));\n }\n\n const owner = match[1];\n const repo = match[2];\n const numberStr = match[3];\n\n if (owner === undefined || repo === undefined || numberStr === undefined) {\n return err(new Error(`Invalid issue URL format: ${url}`));\n }\n\n const issueNumber = parseInt(numberStr, 10);\n\n if (isNaN(issueNumber)) {\n return err(new Error(`Invalid issue URL format: ${url}`));\n }\n\n return ok({ owner, repo, issueNumber });\n}\n\n/**\n * Try to resolve token from `gh auth token` CLI (synchronous).\n * Returns the token string or undefined if gh CLI is unavailable.\n */\nfunction tryGhCliToken(): string | undefined {\n try {\n const stdout = execFileSync('gh', ['auth', 'token'], {\n timeout: 5_000,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n const trimmed = stdout.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Creates a GitHub client from environment variables.\n * Falls back to `gh auth token` CLI when env vars are not set (#1131).\n */\nexport function createGitHubClientFromEnv(): Result<GitHubClient, Error> {\n const token = process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN ?? tryGhCliToken();\n\n if (token === undefined) {\n return err(\n new Error(\n 'GitHub token not found. Set GITHUB_TOKEN or GH_TOKEN, or authenticate with `gh auth login`.'\n )\n );\n }\n\n return ok(\n new GitHubClient({\n token,\n baseUrl: process.env.GITHUB_API_URL ?? 'https://api.github.com',\n })\n );\n}\n","/**\n * nexus-agents/scm - GitHub Provider Trait Implementations\n *\n * Implements IScmReviewer and IScmUserInfo trait interfaces for GitHub.\n * Uses `gh api` for REST API access to get detailed data.\n *\n * @module scm/github-provider-traits\n * (Source: Issue #1136 — Centralized SCM Provider Module)\n */\n\nimport type { Result } from '../core/index.js';\nimport { ok, err, createLogger } from '../core/index.js';\nimport type {\n IScmReviewer,\n IScmUserInfo,\n ScmPullRequestDetail,\n ScmIssueDetail,\n ScmCommentDetail,\n ScmReviewDecision,\n ScmUserMetadata,\n ScmFileChange,\n} from './types.js';\nimport { ScmError } from './types.js';\nimport { GitHubProvider } from './github-provider.js';\n\nconst logger = createLogger({ component: 'GitHubProviderTraits' });\n\n// ============================================================================\n// gh API JSON types (internal)\n// ============================================================================\n\ninterface GhApiPrJson {\n number: number;\n title: string;\n body: string | null;\n html_url: string;\n user: { login: string };\n author_association: string;\n base: { ref: string };\n head: { ref: string; sha: string };\n draft: boolean;\n labels: Array<{ name: string }>;\n additions: number;\n deletions: number;\n}\n\ninterface GhApiFileJson {\n filename: string;\n status: string;\n additions: number;\n deletions: number;\n patch?: string;\n previous_filename?: string;\n}\n\ninterface GhApiIssueJson {\n number: number;\n title: string;\n body: string | null;\n user: { login: string };\n author_association: string;\n state: string;\n html_url: string;\n labels: Array<{ name: string }>;\n created_at: string;\n}\n\ninterface GhApiCommentJson {\n id: number;\n body: string;\n user: { login: string };\n author_association: string;\n created_at: string;\n}\n\ninterface GhApiUserJson {\n login: string;\n name: string | null;\n company: string | null;\n followers: number;\n following: number;\n public_repos: number;\n created_at: string;\n}\n\n// ============================================================================\n// gh API executor\n// ============================================================================\n\n/**\n * Resolves a GitHub token from env vars or `gh auth token`.\n * Caches the result to avoid repeated subprocess calls.\n */\nlet cachedGhToken: string | undefined | null = null;\nlet ghTokenPromise: Promise<string | undefined> | undefined;\n\n/** Reset the cached token (for testing). */\nexport function resetGhTokenCache(): void {\n cachedGhToken = null;\n ghTokenPromise = undefined;\n}\n\nasync function resolveGhToken(): Promise<string | undefined> {\n if (cachedGhToken !== null) return cachedGhToken;\n\n ghTokenPromise ??= resolveGhTokenImpl().finally(() => {\n ghTokenPromise = undefined;\n });\n return ghTokenPromise;\n}\n\nasync function resolveGhTokenImpl(): Promise<string | undefined> {\n const envToken = process.env['GITHUB_TOKEN'] ?? process.env['GH_TOKEN'];\n if (envToken !== undefined && envToken.length > 0) {\n cachedGhToken = envToken;\n return envToken;\n }\n\n try {\n const { execFile } = await import('node:child_process');\n const { promisify } = await import('node:util');\n const exec = promisify(execFile);\n const { stdout } = await exec('gh', ['auth', 'token'], { timeout: 5_000 });\n const token = stdout.trim();\n cachedGhToken = token.length > 0 ? token : undefined;\n } catch {\n cachedGhToken = undefined;\n }\n return cachedGhToken;\n}\n\nasync function execGhApi(endpoint: string, method?: string): Promise<Result<string, ScmError>> {\n const { execFile } = await import('node:child_process');\n const { promisify } = await import('node:util');\n const exec = promisify(execFile);\n\n const args = ['api', endpoint];\n if (method !== undefined) args.push('--method', method);\n\n // Inject token into subprocess environment to prevent keyring access failures\n const token = await resolveGhToken();\n const env = token !== undefined ? { ...process.env, GH_TOKEN: token } : undefined;\n\n try {\n const { stdout } = await exec('gh', args, {\n maxBuffer: 10 * 1024 * 1024,\n timeout: 30_000,\n ...(env !== undefined ? { env } : {}),\n });\n return ok(stdout.trim());\n } catch (error) {\n const execError = error as { message: string; stderr?: string };\n return err(\n new ScmError(`gh api failed: ${execError.message}`, 'github', undefined, {\n endpoint,\n stderr: execError.stderr,\n })\n );\n }\n}\n\n// ============================================================================\n// Mappers\n// ============================================================================\n\nfunction mapFileChange(raw: GhApiFileJson): ScmFileChange {\n const statusMap: Record<string, ScmFileChange['status']> = {\n added: 'added',\n removed: 'removed',\n modified: 'modified',\n renamed: 'renamed',\n copied: 'copied',\n };\n return {\n filename: raw.filename,\n status: statusMap[raw.status] ?? 'modified',\n additions: raw.additions,\n deletions: raw.deletions,\n ...(raw.patch !== undefined ? { patch: raw.patch } : {}),\n ...(raw.previous_filename !== undefined ? { previousFilename: raw.previous_filename } : {}),\n };\n}\n\n// ============================================================================\n// GitHubReviewer — implements IScmReviewer\n// ============================================================================\n\n/**\n * GitHub-specific reviewer that adds PR detail and review capabilities\n * to a GitHubProvider. Implements IScmReviewer trait.\n *\n * @example\n * ```typescript\n * const provider = createGitHubProvider('owner/repo');\n * const reviewer = new GitHubReviewer(provider);\n * const detail = await reviewer.getPullRequestDetail(42);\n * ```\n */\nexport class GitHubReviewer implements IScmReviewer {\n constructor(private readonly provider: GitHubProvider) {}\n\n async getPullRequestDetail(prNumber: number): Promise<Result<ScmPullRequestDetail, ScmError>> {\n const repo = this.provider.repo;\n logger.debug('Getting PR detail', { repo, prNumber });\n\n const prResult = await execGhApi(`repos/${repo}/pulls/${String(prNumber)}`);\n if (!prResult.ok) return prResult;\n\n const filesResult = await execGhApi(`repos/${repo}/pulls/${String(prNumber)}/files`);\n if (!filesResult.ok) return filesResult;\n\n try {\n const pr = JSON.parse(prResult.value) as GhApiPrJson;\n const files = JSON.parse(filesResult.value) as GhApiFileJson[];\n\n return ok({\n number: pr.number,\n title: pr.title,\n body: pr.body ?? '',\n author: pr.user.login,\n base: pr.base.ref,\n head: pr.head.ref,\n url: pr.html_url,\n draft: pr.draft,\n authorAssociation: pr.author_association,\n labels: pr.labels.map((l) => l.name),\n files: files.map(mapFileChange),\n additions: pr.additions,\n deletions: pr.deletions,\n headSha: pr.head.sha,\n });\n } catch {\n return err(new ScmError('Failed to parse PR detail JSON', 'github'));\n }\n }\n\n async createReview(\n prNumber: number,\n body: string,\n decision: ScmReviewDecision\n ): Promise<Result<void, ScmError>> {\n const repo = this.provider.repo;\n const eventMap: Record<ScmReviewDecision, string> = {\n approve: 'APPROVE',\n request_changes: 'REQUEST_CHANGES',\n comment: 'COMMENT',\n };\n\n logger.info('Creating review', { repo, prNumber, decision });\n\n const { execFile } = await import('node:child_process');\n const { promisify } = await import('node:util');\n const exec = promisify(execFile);\n\n try {\n await exec(\n 'gh',\n [\n 'api',\n `repos/${repo}/pulls/${String(prNumber)}/reviews`,\n '--method',\n 'POST',\n '-f',\n `body=${body}`,\n '-f',\n `event=${eventMap[decision]}`,\n ],\n { maxBuffer: 10 * 1024 * 1024, timeout: 30_000 }\n );\n return ok(undefined);\n } catch (error) {\n const execError = error as { message: string };\n return err(new ScmError(`Failed to create review: ${execError.message}`, 'github'));\n }\n }\n\n async getIssueDetail(issueNumber: number): Promise<Result<ScmIssueDetail, ScmError>> {\n const repo = this.provider.repo;\n logger.debug('Getting issue detail', { repo, issueNumber });\n\n const result = await execGhApi(`repos/${repo}/issues/${String(issueNumber)}`);\n if (!result.ok) return result;\n\n try {\n const raw = JSON.parse(result.value) as GhApiIssueJson;\n return ok({\n number: raw.number,\n title: raw.title,\n body: raw.body ?? '',\n labels: raw.labels.map((l) => l.name),\n author: raw.user.login,\n createdAt: raw.created_at,\n authorAssociation: raw.author_association,\n state: raw.state,\n url: raw.html_url,\n });\n } catch {\n return err(new ScmError('Failed to parse issue detail JSON', 'github'));\n }\n }\n\n async listCommentDetails(\n issueNumber: number\n ): Promise<Result<readonly ScmCommentDetail[], ScmError>> {\n const repo = this.provider.repo;\n logger.debug('Listing comment details', { repo, issueNumber });\n\n const result = await execGhApi(`repos/${repo}/issues/${String(issueNumber)}/comments`);\n if (!result.ok) return result;\n\n try {\n const comments = JSON.parse(result.value) as GhApiCommentJson[];\n return ok(\n comments.map((c) => ({\n id: c.id,\n body: c.body,\n author: c.user.login,\n createdAt: c.created_at,\n authorAssociation: c.author_association,\n }))\n );\n } catch {\n return err(new ScmError('Failed to parse comment details JSON', 'github'));\n }\n }\n}\n\n// ============================================================================\n// GitHubUserInfo — implements IScmUserInfo\n// ============================================================================\n\n/**\n * GitHub-specific user info provider. Implements IScmUserInfo trait.\n */\nexport class GitHubUserInfo implements IScmUserInfo {\n async fetchUserMetadata(username: string): Promise<Result<ScmUserMetadata, ScmError>> {\n logger.debug('Fetching user metadata', { username });\n\n const result = await execGhApi(`users/${username}`);\n if (!result.ok) return result;\n\n try {\n const raw = JSON.parse(result.value) as GhApiUserJson;\n return ok({\n login: raw.login,\n name: raw.name,\n company: raw.company,\n followers: raw.followers,\n following: raw.following,\n publicRepos: raw.public_repos,\n createdAt: raw.created_at,\n });\n } catch {\n return err(new ScmError('Failed to parse user metadata JSON', 'github'));\n }\n }\n}\n\n// ============================================================================\n// Factory — compose provider with traits\n// ============================================================================\n\n/**\n * Creates a full-capability GitHub provider with all traits.\n *\n * Returns an object that implements IScmProvider & IScmReviewer & IScmUserInfo.\n * Consumers can narrow the type to only the traits they need.\n *\n * @example\n * ```typescript\n * const provider = createFullGitHubProvider('owner/repo');\n * // Use as ReviewCapableProvider\n * const detail = await provider.getPullRequestDetail(42);\n * // Use as IScmUserInfo\n * const user = await provider.fetchUserMetadata('octocat');\n * ```\n */\nexport function createFullGitHubProvider(\n repo: string\n): GitHubProvider & IScmReviewer & IScmUserInfo {\n const base = new GitHubProvider(repo);\n const reviewer = new GitHubReviewer(base);\n const userInfo = new GitHubUserInfo();\n\n // Compose all trait methods onto the provider\n return Object.assign(base, {\n getPullRequestDetail: reviewer.getPullRequestDetail.bind(reviewer),\n createReview: reviewer.createReview.bind(reviewer),\n getIssueDetail: reviewer.getIssueDetail.bind(reviewer),\n listCommentDetails: reviewer.listCommentDetails.bind(reviewer),\n fetchUserMetadata: userInfo.fetchUserMetadata.bind(userInfo),\n });\n}\n","/**\n * nexus-agents/dogfooding - Issue Triage Types\n *\n * Type definitions for automated GitHub issue triage using\n * the security pipeline (trust classification, corroboration,\n * reputation model).\n *\n * @module dogfooding/issue-triage-types\n * (Source: Issue #828 — Wire remaining security modules)\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Issue Metadata\n// ============================================================================\n\n/**\n * GitHub issue metadata from the API.\n */\nexport interface IssueMetadata {\n /** Issue number */\n readonly number: number;\n /** Issue title */\n readonly title: string;\n /** Issue body/description */\n readonly body: string;\n /** Author username */\n readonly author: string;\n /** GitHub API author_association (e.g., 'OWNER', 'COLLABORATOR', 'NONE') */\n readonly authorAssociation: string;\n /** Repository owner */\n readonly owner: string;\n /** Repository name */\n readonly repo: string;\n /** Issue URL */\n readonly url: string;\n /** Issue state ('open' | 'closed') */\n readonly state: string;\n /** Issue labels */\n readonly labels: readonly string[];\n /** Creation timestamp (ISO 8601) */\n readonly createdAt: string;\n}\n\n/**\n * GitHub issue comment from the API.\n */\nexport interface IssueComment {\n /** Comment ID */\n readonly id: number;\n /** Comment body */\n readonly body: string;\n /** Author username */\n readonly author: string;\n /** GitHub API author_association */\n readonly authorAssociation: string;\n /** Creation timestamp (ISO 8601) */\n readonly createdAt: string;\n}\n\n// ============================================================================\n// Issue Classification\n// ============================================================================\n\n/**\n * Issue category determined by keyword-based classification.\n */\nexport type IssueCategory =\n | 'bug'\n | 'feature'\n | 'question'\n | 'documentation'\n | 'security'\n | 'performance';\n\n/**\n * Display names for issue categories.\n */\nexport const CATEGORY_DISPLAY_NAMES: Record<IssueCategory, string> = {\n bug: 'Bug Report',\n feature: 'Feature Request',\n question: 'Question',\n documentation: 'Documentation',\n security: 'Security',\n performance: 'Performance',\n};\n\n/**\n * Emoji for issue categories (GitHub markdown).\n */\nexport const CATEGORY_EMOJI: Record<IssueCategory, string> = {\n bug: ':bug:',\n feature: ':sparkles:',\n question: ':question:',\n documentation: ':books:',\n security: ':lock:',\n performance: ':zap:',\n};\n\n// ============================================================================\n// Triage Configuration\n// ============================================================================\n\n/**\n * Configuration for issue triage.\n */\nexport interface IssueTriageConfig {\n /** Whether to run in dry-run mode (no GitHub mutations). Default: true */\n readonly dryRun: boolean;\n /** GitHub token for API access */\n readonly githubToken?: string | undefined;\n /** Maximum comments to fetch per issue */\n readonly maxComments: number;\n /** Whether to use reputation model for trust assessment */\n readonly enableReputation: boolean;\n}\n\n/**\n * Default issue triage configuration.\n * Read-only by default — proposes actions without executing them.\n */\nexport const DEFAULT_ISSUE_TRIAGE_CONFIG: IssueTriageConfig = {\n dryRun: true,\n maxComments: 50,\n enableReputation: true,\n};\n\n/**\n * Zod schema for issue triage configuration.\n */\nexport const IssueTriageConfigSchema = z.object({\n dryRun: z.boolean().default(true),\n githubToken: z.string().optional(),\n maxComments: z.number().int().min(1).max(100).default(50),\n enableReputation: z.boolean().default(true),\n});\n\n// ============================================================================\n// Proposed Actions\n// ============================================================================\n\n/**\n * A proposed action from the triage pipeline.\n * All actions are validated through the security pipeline before output.\n */\nexport interface ProposedAction {\n /** Action type (matches AgentActionType from security/action-schema) */\n readonly type: string;\n /** Human-readable description of the proposed action */\n readonly description: string;\n /** Whether this action was approved by the policy gate */\n readonly policyApproved: boolean;\n /** Whether corroboration requirements were satisfied */\n readonly corroborated: boolean;\n /** Details specific to the action type */\n readonly details: Record<string, unknown>;\n}\n\n// ============================================================================\n// Trust Assessment\n// ============================================================================\n\n/**\n * Trust assessment summary for the triage result.\n */\nexport interface TrustAssessment {\n /** Author's trust tier (1-4) */\n readonly trustTier: string;\n /** Author's GitHub role */\n readonly userRole: string;\n /** Whether the author is on the maintainer allowlist */\n readonly isAllowlisted: boolean;\n /** Reputation score (0-100) if reputation model is enabled */\n readonly reputationScore?: number | undefined;\n /** Suspicious signals detected */\n readonly suspiciousSignals: readonly string[];\n /** Whether the author is flagged as suspicious */\n readonly isSuspicious: boolean;\n}\n\n// ============================================================================\n// Triage Result\n// ============================================================================\n\n/**\n * Complete triage result for a GitHub issue.\n */\nexport interface IssueTriageResult {\n /** Issue number */\n readonly issueNumber: number;\n /** Repository (owner/repo) */\n readonly repository: string;\n /** Proposed actions (validated through security pipeline) */\n readonly proposedActions: readonly ProposedAction[];\n /** Trust assessment of the issue author */\n readonly trustAssessment: TrustAssessment;\n /** Detected issue category */\n readonly category: IssueCategory;\n /** Category confidence (0-1) */\n readonly categoryConfidence: number;\n /** Total execution time in ms */\n readonly totalDurationMs: number;\n /** Timestamp of triage (ISO 8601) */\n readonly timestamp: string;\n}\n","/**\n * nexus-agents/dogfooding - Issue Triage Helpers\n *\n * Pure helper functions for issue classification, label extraction,\n * and result formatting. No side effects or API calls.\n *\n * @module dogfooding/issue-triage-helpers\n * (Source: Issue #828 — Wire remaining security modules)\n */\n\nimport type { IssueCategory, IssueTriageResult, ProposedAction } from './issue-triage-types.js';\nimport { CATEGORY_DISPLAY_NAMES, CATEGORY_EMOJI } from './issue-triage-types.js';\n\n// ============================================================================\n// Issue Classification\n// ============================================================================\n\n/**\n * Keyword sets for each issue category.\n * Lower-cased for case-insensitive matching.\n */\nconst CATEGORY_KEYWORDS: Record<IssueCategory, readonly string[]> = {\n bug: ['bug', 'error', 'crash', 'broken', 'fix', 'fail', 'issue', 'wrong', 'unexpected'],\n feature: ['feature', 'request', 'enhancement', 'proposal', 'add', 'support', 'implement'],\n question: ['question', 'how to', 'help', 'confused', 'explain', 'documentation'],\n documentation: ['docs', 'documentation', 'readme', 'typo', 'example', 'guide'],\n security: ['security', 'vulnerability', 'cve', 'exploit', 'injection', 'xss', 'csrf'],\n performance: ['performance', 'slow', 'memory', 'leak', 'optimize', 'latency', 'timeout'],\n};\n\n/**\n * Classifies an issue by matching keywords in the title and body.\n * Returns the category with the highest keyword match count.\n *\n * @param title - Issue title\n * @param body - Issue body\n * @returns Tuple of [category, confidence]\n */\nexport function categorizeIssue(title: string, body: string): [IssueCategory, number] {\n const text = `${title} ${body}`.toLowerCase();\n const scores: Record<IssueCategory, number> = {\n bug: 0,\n feature: 0,\n question: 0,\n documentation: 0,\n security: 0,\n performance: 0,\n };\n\n let totalMatches = 0;\n\n for (const [category, keywords] of Object.entries(CATEGORY_KEYWORDS)) {\n for (const keyword of keywords) {\n if (text.includes(keyword)) {\n scores[category as IssueCategory]++;\n totalMatches++;\n }\n }\n }\n\n // Find category with highest score\n let bestCategory: IssueCategory = 'bug';\n let bestScore = 0;\n for (const [category, score] of Object.entries(scores)) {\n if (score > bestScore) {\n bestScore = score;\n bestCategory = category as IssueCategory;\n }\n }\n\n // Confidence: ratio of best score to total matches, minimum 0.1\n const confidence = totalMatches > 0 ? Math.min(bestScore / totalMatches, 1) : 0.1;\n\n return [bestCategory, Math.round(confidence * 100) / 100];\n}\n\n// ============================================================================\n// Label Extraction\n// ============================================================================\n\n/**\n * Common label patterns that can be extracted from issue text.\n */\nconst LABEL_HINTS: ReadonlyMap<string, string> = new Map([\n ['bug', 'bug'],\n ['feature request', 'enhancement'],\n ['enhancement', 'enhancement'],\n ['breaking change', 'breaking-change'],\n ['documentation', 'documentation'],\n ['help wanted', 'help wanted'],\n ['good first issue', 'good first issue'],\n ['security', 'security'],\n ['performance', 'performance'],\n ['regression', 'regression'],\n]);\n\n/**\n * Extracts suggested labels from issue title and body text.\n *\n * @param title - Issue title\n * @param body - Issue body\n * @returns Array of suggested label strings (max 5)\n */\nexport function extractLabelsFromBody(title: string, body: string): string[] {\n const text = `${title} ${body}`.toLowerCase();\n const labels: string[] = [];\n\n for (const [pattern, label] of LABEL_HINTS) {\n if (text.includes(pattern) && !labels.includes(label)) {\n labels.push(label);\n }\n }\n\n return labels.slice(0, 5);\n}\n\n// ============================================================================\n// Result Formatting\n// ============================================================================\n\n/**\n * Formats a triage result as a GitHub markdown comment.\n *\n * @param result - The complete triage result\n * @returns Formatted markdown string\n */\nexport function formatTriageComment(result: IssueTriageResult): string {\n const emoji = CATEGORY_EMOJI[result.category];\n const categoryName = CATEGORY_DISPLAY_NAMES[result.category];\n const lines: string[] = [];\n\n lines.push(`## ${emoji} Issue Triage: ${categoryName}`);\n lines.push('');\n lines.push(\n `**Category:** ${categoryName} (${String(Math.round(result.categoryConfidence * 100))}% confidence)`\n );\n lines.push(\n `**Trust Tier:** ${result.trustAssessment.trustTier} (${result.trustAssessment.userRole})`\n );\n\n if (result.trustAssessment.reputationScore !== undefined) {\n lines.push(`**Reputation Score:** ${String(result.trustAssessment.reputationScore)}/100`);\n }\n\n if (result.trustAssessment.isSuspicious) {\n lines.push('');\n lines.push(':warning: **Suspicious signals detected:**');\n for (const signal of result.trustAssessment.suspiciousSignals) {\n lines.push(`- ${signal}`);\n }\n }\n\n if (result.proposedActions.length > 0) {\n lines.push('');\n lines.push('### Proposed Actions');\n lines.push('');\n for (const action of result.proposedActions) {\n const status = formatActionStatus(action);\n lines.push(`- ${status} **${action.type}**: ${action.description}`);\n }\n }\n\n lines.push('');\n lines.push(`---`);\n lines.push(`_Triage completed in ${String(result.totalDurationMs)}ms_`);\n\n return lines.join('\\n');\n}\n\n/**\n * Formats the policy/corroboration status of an action.\n */\nfunction formatActionStatus(action: ProposedAction): string {\n if (action.policyApproved && action.corroborated) return ':white_check_mark:';\n if (action.policyApproved && !action.corroborated) return ':yellow_circle:';\n return ':no_entry:';\n}\n","/**\n * nexus-agents/dogfooding - Issue Triage Processor\n *\n * Deterministic GitHub issue triage using the full security pipeline:\n * - Input sanitization (input-sanitizer.ts)\n * - Trust classification (trust-classifier.ts)\n * - Reputation assessment (reputation-model.ts) [NEW — #828]\n * - Typed agent actions (action-schema.ts)\n * - Policy gate validation (policy-gate.ts)\n * - Corroboration validation (corroboration-validator.ts) [NEW — #828]\n *\n * Read-only by default (dryRun: true). Proposes actions but never\n * auto-posts to GitHub without explicit opt-in.\n *\n * @module dogfooding/issue-triage\n * (Source: Issue #828 — Wire remaining security modules)\n */\n\nimport type { Result } from '../core/index.js';\nimport { ok, err, createLogger, getTimeProvider } from '../core/index.js';\nimport { sanitizeInput } from '../security/input-sanitizer.js';\nimport { classifyTrust } from '../security/trust-classifier.js';\nimport type { ClassifyResult } from '../security/trust-classifier.js';\nimport { evaluatePolicy } from '../security/policy-gate.js';\nimport type { ActionContext } from '../security/policy-gate.js';\nimport { validateCorroboration } from '../security/corroboration-validator.js';\nimport type { CorroborationResult } from '../security/corroboration-validator.js';\nimport { assessReputation, ReputationCache } from '../security/reputation-model.js';\nimport type { ReputationAssessment, GitHubUserMetadata } from '../security/reputation-model.js';\nimport type { AgentAction, SourceCitation } from '../security/action-schema.js';\nimport { parseIssueUrl } from './github-client.js';\nimport { createFullGitHubProvider } from '../scm/github-provider-traits.js';\nimport { categorizeIssue, extractLabelsFromBody } from './issue-triage-helpers.js';\nimport type {\n IssueMetadata,\n IssueComment,\n IssueTriageConfig,\n IssueTriageResult,\n ProposedAction,\n TrustAssessment,\n} from './issue-triage-types.js';\nimport { DEFAULT_ISSUE_TRIAGE_CONFIG } from './issue-triage-types.js';\n\n// Re-export for convenience\nexport { formatTriageComment } from './issue-triage-helpers.js';\n\nconst logger = createLogger({ component: 'IssueTriage' });\n\n/**\n * GitHub issue triage processor.\n *\n * Wires all 8 security modules into a read-only triage pipeline:\n * 1. Fetch issue + comments from GitHub API\n * 2. Sanitize untrusted content (input-sanitizer)\n * 3. Classify author trust (trust-classifier)\n * 4. Assess author reputation (reputation-model) [#828]\n * 5. Generate typed actions (action-schema)\n * 6. Validate through policy gate (policy-gate)\n * 7. Validate corroboration (corroboration-validator) [#828]\n * 8. Return proposed actions\n */\nexport class IssueTriage {\n private readonly config: IssueTriageConfig;\n private readonly reputationCache: ReputationCache;\n\n constructor(config?: Partial<IssueTriageConfig>) {\n this.config = { ...DEFAULT_ISSUE_TRIAGE_CONFIG, ...config };\n this.reputationCache = new ReputationCache();\n }\n\n /**\n * Triages a GitHub issue through the full security pipeline.\n */\n async triageIssue(issueUrl: string): Promise<Result<IssueTriageResult, Error>> {\n const startTime = getTimeProvider().now();\n\n logger.info('Starting issue triage', { issueUrl });\n\n const parseResult = parseIssueUrl(issueUrl);\n if (!parseResult.ok) return parseResult;\n\n const { owner, repo, issueNumber } = parseResult.value;\n\n const fetchResult = await this.fetchIssueData(owner, repo, issueNumber);\n if (!fetchResult.ok) return fetchResult;\n\n const { issue: issueResult, comments } = fetchResult.value;\n\n // Sanitize untrusted content (Issue #828 — input-sanitizer wiring)\n const safeTitle = this.sanitizeContent(issueResult.title, issueResult.author);\n const safeBody = this.sanitizeContent(issueResult.body, issueResult.author);\n\n // Classify trust + assess reputation (Issue #828 — new wiring)\n const trustResult = this.classifyAuthor(issueResult);\n const reputation = this.assessAuthorReputation(issueResult, comments);\n\n // Generate and validate actions\n const actions = this.generateActions(safeTitle, safeBody, issueResult, trustResult);\n const validatedActions = this.validateActions(actions, trustResult);\n\n const result = this.buildResult({\n issue: issueResult,\n actions: validatedActions,\n trustResult,\n reputation,\n safeContent: { title: safeTitle, body: safeBody },\n startTime,\n });\n\n logger.info('Issue triage completed', {\n issueNumber,\n category: result.category,\n actionCount: result.proposedActions.length,\n durationMs: result.totalDurationMs,\n });\n\n return ok(result);\n }\n\n /**\n * Sanitizes untrusted issue content before processing.\n * (Source: Issue #828 — input-sanitizer wiring)\n */\n private sanitizeContent(text: string, author: string): string {\n if (text.length === 0) return text;\n const result = sanitizeInput(text, 'unknown', author);\n if (result.wasModified) {\n logger.warn('Issue content sanitized', {\n author,\n strippedCount: result.strippedElements.length,\n injectionFlags: result.injectionFlags,\n });\n }\n return result.content;\n }\n\n /**\n * Classifies the issue author's trust tier.\n * (Source: Issue #828 — trust-classifier wiring)\n */\n private classifyAuthor(issue: IssueMetadata): ClassifyResult {\n return classifyTrust({\n username: issue.author,\n authorAssociation: issue.authorAssociation,\n });\n }\n\n /**\n * Assesses the issue author's reputation using the reputation model.\n * This is one of the two NEW security module wirings completing #828.\n * (Source: Issue #828 — reputation-model wiring)\n */\n private assessAuthorReputation(\n issue: IssueMetadata,\n comments: readonly IssueComment[]\n ): ReputationAssessment | undefined {\n if (!this.config.enableReputation) return undefined;\n\n const sanitizeResult = sanitizeInput(issue.body, 'unknown', issue.author);\n\n const metadata: GitHubUserMetadata = {\n username: issue.author,\n accountAgeDays: estimateAccountAge(issue.createdAt),\n priorContributions: countAuthorComments(issue.author, comments),\n recentCommentCount: countRecentComments(issue.author, comments),\n recentCommentWindowMinutes: 10,\n authorAssociation: issue.authorAssociation,\n injectionFlags: sanitizeResult.injectionFlags,\n };\n\n return assessReputation(metadata, this.reputationCache);\n }\n\n /**\n * Generates typed agent actions based on issue analysis.\n */\n private generateActions(\n safeTitle: string,\n safeBody: string,\n issue: IssueMetadata,\n trustResult: ClassifyResult\n ): AgentAction[] {\n const actions: AgentAction[] = [];\n const source = this.createRepoSource(issue);\n\n // Always generate ClassifyIssue action\n const [category, confidence] = categorizeIssue(safeTitle, safeBody);\n actions.push({\n type: 'ClassifyIssue',\n category,\n confidence,\n sources: [source],\n });\n\n // Generate ProposeLabels if we found label hints\n const labels = extractLabelsFromBody(safeTitle, safeBody);\n if (labels.length > 0) {\n actions.push({\n type: 'ProposeLabels',\n labels,\n reason: `Keyword-based label extraction from issue #${String(issue.number)}`,\n sources: [source],\n });\n }\n\n // Generate SummarizeIssue for semi-trusted+ authors\n if (trustResult.trustTier === '1' || trustResult.trustTier === '2') {\n const summary = `Issue #${String(issue.number)} \"${safeTitle}\" by ${issue.author} (${trustResult.userRole})`;\n actions.push({\n type: 'SummarizeIssue',\n summary: summary.length >= 10 ? summary : `${summary} — awaiting further analysis`,\n sources: [source],\n });\n }\n\n return actions;\n }\n\n /**\n * Validates all actions through policy gate and corroboration validator.\n * This completes the #828 wiring by integrating corroboration-validator.\n * (Source: Issue #828 — policy-gate + corroboration-validator wiring)\n */\n private validateActions(\n actions: readonly AgentAction[],\n trustResult: ClassifyResult\n ): ProposedAction[] {\n const context: ActionContext = {\n inputTrustTier: trustResult.trustTier,\n hasWriteAccess: !this.config.dryRun,\n hasSecretAccess: false,\n };\n\n return actions.map((action) => {\n const policyDecision = evaluatePolicy(action, context);\n const corrobResult = this.validateActionCorroboration(action);\n\n return {\n type: action.type,\n description: describeAction(action),\n policyApproved: policyDecision.allowed,\n corroborated: corrobResult.satisfied,\n details: buildActionDetails(action, policyDecision, corrobResult),\n };\n });\n }\n\n /**\n * Validates corroboration for a single action.\n * This is the second NEW security module wiring completing #828.\n * (Source: Issue #828 — corroboration-validator wiring)\n */\n private validateActionCorroboration(action: AgentAction): CorroborationResult {\n return validateCorroboration(action);\n }\n\n /**\n * Builds the final triage result.\n */\n private buildResult(opts: {\n issue: IssueMetadata;\n actions: readonly ProposedAction[];\n trustResult: ClassifyResult;\n reputation: ReputationAssessment | undefined;\n safeContent: { title: string; body: string };\n startTime: number;\n }): IssueTriageResult {\n const { issue, actions, trustResult, reputation, safeContent, startTime } = opts;\n const [category, confidence] = categorizeIssue(safeContent.title, safeContent.body);\n\n // Tier 1 actors (owner/maintainer) cannot be suspicious — reconcile\n // the trust-classifier result with the reputation-model result.\n const isTier1 = trustResult.trustTier === '1';\n\n const trustAssessment: TrustAssessment = {\n trustTier: trustResult.trustTier,\n userRole: trustResult.userRole,\n isAllowlisted: trustResult.isAllowlisted,\n reputationScore: reputation?.reputationScore,\n suspiciousSignals: isTier1 ? [] : (reputation?.suspiciousSignals ?? []),\n isSuspicious: isTier1 ? false : (reputation?.isSuspicious ?? false),\n };\n\n return {\n issueNumber: issue.number,\n repository: `${issue.owner}/${issue.repo}`,\n proposedActions: actions,\n trustAssessment,\n category,\n categoryConfidence: confidence,\n totalDurationMs: getTimeProvider().now() - startTime,\n timestamp: getTimeProvider().nowIso(),\n };\n }\n\n /**\n * Creates a repo file source citation for the triage.\n */\n private createRepoSource(issue: IssueMetadata): SourceCitation {\n return {\n type: 'repoFile',\n path: `issues/${String(issue.number)}`,\n };\n }\n\n /**\n * Fetches issue data from the SCM provider and maps to dogfooding types.\n */\n private async fetchIssueData(\n owner: string,\n repo: string,\n issueNumber: number\n ): Promise<Result<{ issue: IssueMetadata; comments: IssueComment[] }, Error>> {\n const provider = createFullGitHubProvider(`${owner}/${repo}`);\n\n const detailResult = await provider.getIssueDetail(issueNumber);\n if (!detailResult.ok) return err(detailResult.error);\n\n const detail = detailResult.value;\n const issue: IssueMetadata = {\n number: detail.number,\n title: detail.title,\n body: detail.body,\n author: detail.author,\n authorAssociation: detail.authorAssociation,\n owner,\n repo,\n url: detail.url,\n state: detail.state,\n labels: [...detail.labels],\n createdAt: detail.createdAt,\n };\n\n const commentsResult = await provider.listCommentDetails(issueNumber);\n const comments: IssueComment[] = commentsResult.ok\n ? commentsResult.value.map((c) => ({\n id: c.id,\n body: c.body,\n author: c.author,\n authorAssociation: c.authorAssociation,\n createdAt: c.createdAt,\n }))\n : [];\n\n return ok({ issue, comments });\n }\n}\n\n// ============================================================================\n// Private Helpers\n// ============================================================================\n\n/**\n * Returns a safe default account age when the actual user creation date\n * is unavailable. The triage pipeline only has issue.createdAt (the date\n * the issue was filed), NOT the user's account creation date. Using the\n * issue date would make recently filed issues appear to come from new\n * accounts, incorrectly triggering the new_account signal.\n *\n * Default: 365 days — assumes an established account unless the GitHub\n * user profile is fetched to provide the real value.\n */\nconst DEFAULT_ACCOUNT_AGE_DAYS = 365;\n\nfunction estimateAccountAge(_createdAt: string): number {\n return DEFAULT_ACCOUNT_AGE_DAYS;\n}\n\n/** Counts how many comments the author has made on the issue. */\nfunction countAuthorComments(author: string, comments: readonly IssueComment[]): number {\n return comments.filter((c) => c.author === author).length;\n}\n\n/** Counts recent comments from the author (within 10 minutes). */\nfunction countRecentComments(author: string, comments: readonly IssueComment[]): number {\n const tenMinutesAgo = Date.now() - 10 * 60 * 1000;\n return comments.filter(\n (c) => c.author === author && new Date(c.createdAt).getTime() > tenMinutesAgo\n ).length;\n}\n\n/** Creates a human-readable description for a typed action. */\nfunction describeAction(action: AgentAction): string {\n switch (action.type) {\n case 'ClassifyIssue':\n return `Classified as ${action.category} (${String(Math.round(action.confidence * 100))}% confidence)`;\n case 'ProposeLabels':\n return `Suggest labels: ${action.labels.join(', ')}`;\n case 'SummarizeIssue':\n return action.summary.slice(0, 100);\n default:\n return `${action.type} action`;\n }\n}\n\n/** Builds details object for a proposed action. */\nfunction buildActionDetails(\n action: AgentAction,\n policy: { allowed: boolean; violations: readonly { rule: string; message: string }[] },\n corrob: CorroborationResult\n): Record<string, unknown> {\n return {\n policyViolations: policy.violations.map((v) => v.rule),\n missingCorroboration: corrob.missing,\n ...(action.type === 'ClassifyIssue' && { category: action.category }),\n ...(action.type === 'ProposeLabels' && { labels: action.labels }),\n };\n}\n\n/**\n * Creates an IssueTriage instance.\n */\nexport function createIssueTriage(config?: Partial<IssueTriageConfig>): IssueTriage {\n return new IssueTriage(config);\n}\n"],"mappings":"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","names":["z","z","z","z","z","z","logger","logger","z","logger"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/research-helpers-io.ts","../src/security/safe-path.ts","../src/cli/research-alignment-map.ts","../src/research/topic-aliases.ts","../src/cli/research-helpers-synthesize.ts"],"sourcesContent":["/**\n * Research Registry I/O Operations\n *\n * File operations for loading and saving research registry YAML files.\n * Includes path traversal protection per Issue #353.\n *\n * @see docs/research/RESEARCH_INDEX.md\n * @see Issue #237 (Epic #225)\n * @see Issue #353 (Security - Path traversal fix)\n */\n\nimport * as fs from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { resolveInsideRoot } from '../security/safe-path.js';\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport type { Result } from '../core/index.js';\nimport { SecurityError, getErrorMessage } from '../core/index.js';\nimport { ParseError } from '../core/types/workflow.js';\nimport type { TechniquesRegistry, PapersRegistry } from './research-types.js';\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/** Path to research registry directory relative to project root */\nexport const REGISTRY_PATH = 'docs/research/registry';\n\n/** Filename for techniques registry */\nexport const TECHNIQUES_FILE = 'techniques.yaml';\n\n/** Filename for papers registry */\nexport const PAPERS_FILE = 'papers.yaml';\n\n// =============================================================================\n// PROJECT ROOT\n// =============================================================================\n\n/**\n * Get the project root directory.\n * Note: Returns cwd since registry operations use explicit rootDir parameter\n */\nexport function getProjectRoot(): string {\n return process.cwd();\n}\n\n// =============================================================================\n// PATH VALIDATION\n// =============================================================================\n\n/**\n * Validates that a constructed path stays within the allowed root directory.\n * Prevents path traversal attacks (e.g., ../../../etc/passwd).\n *\n * @param constructedPath - The full path to validate\n * @param allowedRoot - The root directory that paths must be within\n * @returns Result with validated absolute path or SecurityError\n */\nfunction validatePath(constructedPath: string, allowedRoot: string): Result<string, SecurityError> {\n const resolved = resolveInsideRoot(constructedPath, allowedRoot);\n if (resolved === null) {\n return {\n ok: false,\n error: new SecurityError('Path traversal detected: path escapes allowed root directory', {\n context: { constructedPath, allowedRoot: resolve(allowedRoot) },\n }),\n };\n }\n return { ok: true, value: resolved };\n}\n\n// =============================================================================\n// LOAD OPERATIONS\n// =============================================================================\n\n/**\n * Load techniques registry from YAML file.\n * Validates path to prevent directory traversal attacks.\n *\n * @param rootDir - Project root directory (defaults to cwd)\n * @returns Result with TechniquesRegistry or SecurityError/ParseError\n */\nexport async function loadTechniquesRegistry(\n rootDir?: string\n): Promise<Result<TechniquesRegistry, SecurityError | ParseError>> {\n const root = rootDir ?? process.cwd();\n const filePath = join(root, REGISTRY_PATH, TECHNIQUES_FILE);\n\n const pathValidation = validatePath(filePath, root);\n if (!pathValidation.ok) {\n return pathValidation;\n }\n\n try {\n const content = await fs.readFile(pathValidation.value, 'utf-8');\n return { ok: true, value: parseYaml(content) as TechniquesRegistry };\n } catch (error) {\n const message = getErrorMessage(error);\n return { ok: false, error: new ParseError(`Failed to load techniques registry: ${message}`) };\n }\n}\n\n/**\n * Load papers registry from YAML file.\n * Validates path to prevent directory traversal attacks.\n *\n * @param rootDir - Project root directory (defaults to cwd)\n * @returns Result with PapersRegistry or SecurityError/ParseError\n */\nexport async function loadPapersRegistry(\n rootDir?: string\n): Promise<Result<PapersRegistry, SecurityError | ParseError>> {\n const root = rootDir ?? process.cwd();\n const filePath = join(root, REGISTRY_PATH, PAPERS_FILE);\n\n const pathValidation = validatePath(filePath, root);\n if (!pathValidation.ok) {\n return pathValidation;\n }\n\n try {\n const content = await fs.readFile(pathValidation.value, 'utf-8');\n return { ok: true, value: parseYaml(content) as PapersRegistry };\n } catch (error) {\n const message = getErrorMessage(error);\n return { ok: false, error: new ParseError(`Failed to load papers registry: ${message}`) };\n }\n}\n\n// =============================================================================\n// SAVE OPERATIONS\n// =============================================================================\n\n/**\n * Save techniques registry to YAML file.\n * Validates path to prevent directory traversal attacks.\n *\n * @param registry - The techniques registry to save\n * @param rootDir - Project root directory (defaults to cwd)\n * @returns Result with void on success or SecurityError/ParseError on failure\n */\nexport async function saveTechniquesRegistry(\n registry: TechniquesRegistry,\n rootDir?: string\n): Promise<Result<void, SecurityError | ParseError>> {\n const root = rootDir ?? process.cwd();\n const filePath = join(root, REGISTRY_PATH, TECHNIQUES_FILE);\n\n const pathValidation = validatePath(filePath, root);\n if (!pathValidation.ok) {\n return pathValidation;\n }\n\n try {\n const content = stringifyYaml(registry, { lineWidth: 100 });\n await fs.writeFile(pathValidation.value, content, 'utf-8');\n return { ok: true, value: undefined };\n } catch (error) {\n const message = getErrorMessage(error);\n return { ok: false, error: new ParseError(`Failed to save techniques registry: ${message}`) };\n }\n}\n\n/**\n * Save papers registry to YAML file.\n * Validates path to prevent directory traversal attacks.\n *\n * @param registry - The papers registry to save\n * @param rootDir - Project root directory (defaults to cwd)\n * @returns Result with void on success or SecurityError/ParseError on failure\n */\nexport async function savePapersRegistry(\n registry: PapersRegistry,\n rootDir?: string\n): Promise<Result<void, SecurityError | ParseError>> {\n const root = rootDir ?? process.cwd();\n const filePath = join(root, REGISTRY_PATH, PAPERS_FILE);\n\n const pathValidation = validatePath(filePath, root);\n if (!pathValidation.ok) {\n return pathValidation;\n }\n\n try {\n const content = stringifyYaml(registry, { lineWidth: 100 });\n await fs.writeFile(pathValidation.value, content, 'utf-8');\n return { ok: true, value: undefined };\n } catch (error) {\n const message = getErrorMessage(error);\n return { ok: false, error: new ParseError(`Failed to save papers registry: ${message}`) };\n }\n}\n","/**\n * Safe Path — Path traversal guards for scanner-controlled inputs (#1813, #1814)\n *\n * When reading files whose path comes from untrusted input (e.g., SARIF\n * scanner output), we must verify the resolved path stays within the\n * workspace root. Without this, a malicious scanner can cause arbitrary\n * file reads whose contents are exfiltrated via downstream LLM prompts\n * (CWE-22).\n *\n * Shared helper to prevent the finding-triage/fix-generator drift that\n * required two separate fixes.\n *\n * @module security/safe-path\n */\n\nimport { resolve, sep } from 'node:path';\n\n/**\n * Resolve a scanner-supplied path against the workspace root, returning null\n * if it escapes. Null means the caller must fall back to a safe alternative\n * (e.g., scanner-provided snippet) rather than reading the file.\n *\n * @param filePath - Scanner-supplied path (may be relative or absolute)\n * @param root - Workspace root (defaults to process.cwd())\n * @returns Resolved absolute path if inside root, null otherwise\n */\nexport function resolveInsideRoot(filePath: string, root: string = process.cwd()): string | null {\n const resolvedRoot = resolve(root);\n const resolved = resolve(resolvedRoot, filePath);\n if (resolved === resolvedRoot) return resolved;\n if (resolved.startsWith(resolvedRoot + sep)) return resolved;\n return null;\n}\n","/**\n * Research Alignment Map\n *\n * Maps technique names from the research registry to canonical code paths\n * in the nexus-agents codebase. Used by research synthesis to determine\n * which paper techniques are implemented, partially implemented, or new.\n *\n * @module cli/research-alignment-map\n * (Source: Issue #1386 — Research Synthesis Pipeline)\n */\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/** Implementation status for a mapped technique. */\nexport interface TechniqueMapping {\n readonly status: 'implemented' | 'partial';\n readonly path: string;\n readonly hint?: string | undefined;\n}\n\n/** A feature gate that controls an implementation. */\nexport interface FeatureGate {\n /** Environment variable or config key. */\n readonly envVar: string;\n /** Default value when not explicitly set. */\n readonly defaultValue: string;\n /** Brief description of what the gate controls. */\n readonly description: string;\n /** Related technique names from the alignment map (if any). */\n readonly techniques?: readonly string[];\n}\n\n// =============================================================================\n// MAP\n// =============================================================================\n\n/**\n * Maps technique names to canonical code paths.\n * 'implemented' = full implementation exists matching the technique.\n * 'partial' = related code exists but doesn't fully implement the technique.\n */\nexport const TECHNIQUE_IMPLEMENTATION_MAP: ReadonlyMap<string, TechniqueMapping> = new Map([\n // Routing techniques\n ['linucb-routing', { status: 'implemented', path: 'cli-adapters/linucb-bandit.ts' }],\n ['topsis-routing', { status: 'implemented', path: 'cli-adapters/topsis-router.ts' }],\n [\n 'cascade-routing',\n { status: 'implemented', path: 'routing/stages/confidence-cascade-stage.ts' },\n ],\n [\n 'complexity-based-routing',\n { status: 'implemented', path: 'routing/stages/confidence-cascade-stage.ts' },\n ],\n [\n 'moe-routing',\n {\n status: 'implemented',\n path: 'cli-adapters/composite-router.ts',\n hint: '5-stage composite routing selects among specialized CLI experts based on task features',\n },\n ],\n ['two-stage-routing', { status: 'implemented', path: 'cli-adapters/composite-router-stages.ts' }],\n [\n 'capability-instruction-tuning',\n {\n status: 'partial',\n path: 'routing/stages/capability-match-stage.ts',\n hint: 'Static capability profiles, not instruction-tuned',\n },\n ],\n [\n 'knn-routing',\n {\n status: 'implemented',\n path: 'routing/stages/knn-routing-stage.ts',\n hint: 'KnnRoutingStage: cosine similarity over keyword vectors, K-nearest experience patterns, weighted by success rate',\n },\n ],\n ['pilot-budget-routing', { status: 'implemented', path: 'cli-adapters/budget-router.ts' }],\n [\n 'tolerance-routing',\n {\n status: 'implemented',\n path: 'cli-adapters/composite-router-helpers.ts',\n hint: 'TOPSIS_TOLERANCE_BAND_PERCENT (5%) identifies quality-equivalent candidates after TOPSIS ranking',\n },\n ],\n [\n 'sater-routing',\n {\n status: 'implemented',\n path: 'routing/stages/quality-constraint-stage.ts',\n hint: 'QualityConstraintStage filters models by min quality (0.7), max cost, max latency before selection',\n },\n ],\n [\n 'preference-trained-routing',\n { status: 'implemented', path: 'cli-adapters/preference-router.ts' },\n ],\n [\n 'strmac-state-routing',\n {\n status: 'implemented',\n path: 'context/routing-memory.ts',\n hint: 'RoutingMemory maintains state across calls (profile, experience, action cache) feeding LinUCB + weather bonus stages',\n },\n ],\n [\n 'cross-attention-routing',\n {\n status: 'implemented',\n path: 'routing/stages/capability-match-stage.ts',\n hint: 'AttentionMatrix maps task features to capability weights (configurable cross-attention)',\n },\n ],\n\n // Consensus techniques\n ['consensus-protocol', { status: 'implemented', path: 'consensus/engine.ts' }],\n ['majority-voting', { status: 'implemented', path: 'consensus/engine.ts' }],\n ['higher-order-voting', { status: 'implemented', path: 'consensus/higher-order-strategy.ts' }],\n [\n 'anti-conformity-weighting',\n { status: 'implemented', path: 'consensus/higher-order-strategy.ts' },\n ],\n [\n 'agreement-based-cascading',\n {\n status: 'implemented',\n path: 'consensus/engine.ts',\n hint: 'canCascadeEarly() closes proposals when outcome is mathematically determined',\n },\n ],\n [\n 'incremental-quorum',\n {\n status: 'implemented',\n path: 'consensus/incremental-quorum.ts',\n hint: 'Ambiguity detection + voter expansion via VoterExpansionCallback (#1408)',\n },\n ],\n [\n 'aegean-consensus',\n { status: 'partial', path: 'consensus/engine.ts', hint: 'Byzantine tolerance not implemented' },\n ],\n [\n 'cp-wbft-consensus',\n {\n status: 'partial',\n path: 'consensus/engine.ts',\n hint: 'No weighted Byzantine fault tolerance',\n },\n ],\n\n // Memory techniques\n ['adaptive-memory', { status: 'implemented', path: 'memory/adaptive/' }],\n ['mirix-six-type-memory', { status: 'implemented', path: 'memory/typed/' }],\n [\n 'mem0-memory-architecture',\n { status: 'partial', path: 'memory/', hint: 'Multi-backend memory but not mem0 pattern' },\n ],\n [\n 'graph-based-memory',\n {\n status: 'partial',\n path: 'memory/belief/',\n hint: 'Belief triples are graph-like but not full graph DB',\n },\n ],\n ['experience-memory', { status: 'implemented', path: 'memory/session/' }],\n ['hindsight-belief-memory', { status: 'implemented', path: 'memory/belief/' }],\n [\n 'profile-memory',\n {\n status: 'implemented',\n path: 'context/routing-memory.ts',\n hint: 'RoutingMemory stores model preferences per task type and feeds recommendations into composite router via PERSISTENCE_AWARE_FLAGS',\n },\n ],\n [\n 'action-memory',\n {\n status: 'implemented',\n path: 'orchestration/outcomes/',\n hint: 'OutcomeStore records actions+results+context with query-by-category/CLI/time and cross-session persistence',\n },\n ],\n ['reflection-memory', { status: 'implemented', path: 'mcp/tools/orchestrate-reflection.ts' }],\n [\n 'history-encoding',\n {\n status: 'partial',\n path: 'context/token-counter.ts',\n hint: 'Token counting exists but no learned history encoding',\n },\n ],\n\n // Orchestration techniques\n [\n 'aflow-mcts-workflows',\n {\n status: 'partial',\n path: 'workflows/aflow/',\n hint: 'AFlow scaffolding exists but MCTS not implemented',\n },\n ],\n [\n 'dynamic-agent-selection',\n { status: 'implemented', path: 'orchestration/aorchestra/agent-planner.ts' },\n ],\n ['dynamic-subagent-creation', { status: 'implemented', path: 'mcp/tools/create-expert.ts' }],\n ['role-based-protocols', { status: 'implemented', path: 'agents/expert-roles.ts' }],\n [\n 'rule-based-coordination',\n { status: 'implemented', path: 'orchestration/aorchestra/worker-dispatcher.ts' },\n ],\n [\n 'temporal-graph-orchestration',\n {\n status: 'partial',\n path: 'orchestration/graph/',\n hint: 'Graph workflows exist but not temporal-aware',\n },\n ],\n [\n 'model-based-coordination',\n {\n status: 'partial',\n path: 'orchestration/aorchestra/',\n hint: 'Worker dispatch but not model-based coordination theory',\n },\n ],\n [\n 'trinity-roles',\n {\n status: 'partial',\n path: 'agents/expert-roles.ts',\n hint: '10 expert roles, not trinity pattern',\n },\n ],\n [\n 'sew-self-evolving-workflows',\n {\n status: 'partial',\n path: 'workflows/aflow/',\n hint: 'AFlow framework but no self-evolution loop',\n },\n ],\n [\n 'scaling-coordination-predictor',\n {\n status: 'partial',\n path: 'orchestration/aorchestra/agent-planner.ts',\n hint: 'Wave sizing but no scaling prediction',\n },\n ],\n\n // Learning techniques\n [\n 'self-refine-loop',\n {\n status: 'implemented',\n path: 'mcp/tools/orchestrate-dispatch.ts',\n },\n ],\n [\n 'recursive-improvement',\n {\n status: 'implemented',\n path: 'mcp/tools/orchestrate-dispatch.ts',\n },\n ],\n [\n 'rl-orchestrator',\n {\n status: 'implemented',\n path: 'cli-adapters/linucb-bandit.ts',\n hint: 'LinUCB contextual bandit actively selects models via explore-exploit in routing pipeline',\n },\n ],\n ['reflexion-verbal-rl', { status: 'implemented', path: 'mcp/tools/orchestrate-reflection.ts' }],\n\n // Source-derived techniques (Wave 6 — from open-source project analysis)\n ['failure-lesson-injection', { status: 'implemented', path: 'orchestration/failure-lessons.ts' }],\n [\n 'skill-relevance-matching',\n {\n status: 'implemented',\n path: 'agents/experts/skill-matcher.ts',\n hint: 'Matches task keywords to agent skill descriptions for optimal routing',\n },\n ],\n [\n 'context-rot-prevention',\n {\n status: 'implemented',\n path: 'agents/context-pruner.ts',\n hint: 'Token-efficient context pruning prevents quality degradation in long sessions',\n },\n ],\n [\n 'wave-based-parallel-execution',\n {\n status: 'implemented',\n path: 'orchestration/aorchestra/worker-dispatcher.ts',\n hint: 'AOrchestra worker dispatch with cross-wave context sharing',\n },\n ],\n [\n 'write-time-deduplication',\n {\n status: 'implemented',\n path: 'mcp/tools/memory-write.ts',\n hint: 'Semantic dedup at write time prevents memory bloat',\n },\n ],\n]);\n\n// =============================================================================\n// FEATURE GATE INVENTORY\n// =============================================================================\n\n/** Inventory of feature gates linked to research-aligned techniques. */\nexport const FEATURE_GATE_INVENTORY: readonly FeatureGate[] = [\n {\n envVar: 'NEXUS_V2_MODE',\n defaultValue: 'full',\n description: 'V2 pipeline mode (off/partial/full)',\n techniques: ['two-stage-routing', 'cascade-routing'],\n },\n {\n envVar: 'NEXUS_AORCHESTRA',\n defaultValue: 'true',\n description: 'AOrchestra dynamic agent planning',\n techniques: ['dynamic-agent-selection', 'model-based-coordination'],\n },\n {\n envVar: 'NEXUS_AORCHESTRA_DISPATCH',\n defaultValue: 'true',\n description: 'AOrchestra worker dispatch',\n techniques: ['rule-based-coordination', 'self-refine-loop'],\n },\n {\n envVar: 'NEXUS_PERSIST_LEARNING',\n defaultValue: 'true',\n description: 'Cross-session routing persistence',\n techniques: ['linucb-routing', 'preference-trained-routing', 'experience-memory'],\n },\n {\n envVar: 'NEXUS_REFLECTIVE_MEMORY',\n defaultValue: 'shadow',\n description: 'Reflective memory retrieval (shadow=default, true=full, false=off)',\n techniques: ['reflection-memory', 'adaptive-memory', 'reflexion-verbal-rl'],\n },\n {\n envVar: 'NEXUS_BILLING_MODE',\n defaultValue: 'plan',\n description: 'Cost mode (plan=strongest, api=cost-aware)',\n techniques: ['pilot-budget-routing', 'topsis-routing'],\n },\n {\n envVar: 'NEXUS_WORKER_MAX_CALLS',\n defaultValue: '6',\n description: 'Max model calls per orchestrate',\n techniques: ['self-refine-loop', 'recursive-improvement'],\n },\n { envVar: 'NEXUS_AUTH_ENABLED', defaultValue: 'true', description: 'Server authentication' },\n { envVar: 'NEXUS_EVENTBUS_ENABLED', defaultValue: 'true', description: 'EventBus A2A bridge' },\n {\n envVar: 'NEXUS_RATE_LIMIT_ENABLED',\n defaultValue: 'true',\n description: 'Token-bucket rate limiter',\n },\n {\n envVar: 'NEXUS_CIRCUIT_BREAKER_THRESHOLD',\n defaultValue: '5',\n description: 'Circuit breaker failure threshold',\n },\n {\n envVar: 'NEXUS_V2_POLICY_MODE',\n defaultValue: 'block',\n description: 'Policy enforcement (off/warn/block)',\n },\n { envVar: 'NEXUS_LOG_LEVEL', defaultValue: 'info', description: 'Logging verbosity' },\n {\n envVar: 'NEXUS_DISABLE_SESSIONS',\n defaultValue: 'false',\n description: 'Disable session tracking',\n },\n {\n envVar: 'NEXUS_DISABLE_METRICS',\n defaultValue: 'false',\n description: 'Disable metrics tracking',\n },\n {\n envVar: 'NEXUS_ALLOW_MOCK_ORCHESTRATION',\n defaultValue: 'false',\n description: 'Allow mock orchestration (test/CI)',\n },\n {\n envVar: 'NEXUS_MAX_CONCURRENT_EXPERTS',\n defaultValue: '6',\n description: 'Expert pool semaphore capacity',\n },\n {\n envVar: 'NEXUS_VOTE_TIMEOUT_MS',\n defaultValue: '60000',\n description: 'Consensus vote timeout override',\n },\n {\n envVar: 'NEXUS_EXPERT_TIMEOUT_MS',\n defaultValue: '120000',\n description: 'Expert handler timeout override',\n },\n {\n envVar: 'NEXUS_WORKER_TIMEOUT_MS',\n defaultValue: '60000',\n description: 'Worker subprocess timeout override',\n },\n];\n","/**\n * Topic alias map for normalizing free-form topic strings to canonical topics.\n *\n * Maps 200+ free-form topic strings found in papers.yaml to 12 canonical topics.\n * Used by normalizeTopicToCanonical() in research-schemas.ts.\n *\n * @module research/topic-aliases\n * @see Issue #1578 — Topic taxonomy normalization\n */\n\n/**\n * Map of free-form topic strings to canonical topics.\n */\nexport const TOPIC_ALIASES: Readonly<Record<string, string>> = {\n // → consensus\n voting: 'consensus',\n 'consensus-voting': 'consensus',\n debate: 'consensus',\n quorum: 'consensus',\n byzantine: 'consensus',\n 'anti-conformity': 'consensus',\n 'agreement-based': 'consensus',\n 'correlation-aware': 'consensus',\n 'LLM consensus and multi-agent voting mechanisms': 'consensus',\n 'tolerance-parameter': 'consensus',\n\n // → routing\n 'model-routing': 'routing',\n 'model routing': 'routing',\n 'llm-routing': 'routing',\n cascade: 'routing',\n 'cascade-routing': 'routing',\n 'cost-optimization': 'routing',\n 'cost-reduction': 'routing',\n 'model-selection': 'routing',\n topsis: 'routing',\n linucb: 'routing',\n 'contextual-bandit': 'routing',\n 'quality-constrained': 'routing',\n 'budget-constraints': 'routing',\n 'unified-routing': 'routing',\n 'query-model-matching': 'routing',\n 'adaptive model routing and selection optimization': 'routing',\n 'multi-model routing optimization': 'routing',\n 'Single-head cross-attention for query-model matching': 'routing',\n 'performance-cost-tradeoff': 'routing',\n 'task-routing': 'routing',\n 'difficulty-estimation': 'routing',\n 'score-based': 'routing',\n 'optimal-weighting': 'routing',\n 'hierarchical-filtering': 'routing',\n 'preference-optimization': 'routing',\n 'preference-data': 'routing',\n dpo: 'routing',\n 'cross-attention': 'routing',\n 'cma-es': 'routing',\n profile: 'routing',\n prediction: 'routing',\n lightweight: 'routing',\n bayesian: 'routing',\n 'quality-diversity': 'routing',\n 'resource-optimization': 'routing',\n 'routing-latency': 'routing',\n optimization: 'routing',\n 'model-merging': 'routing',\n 'model-zoo': 'routing',\n\n // → memory\n 'context-management': 'memory',\n 'context-compression': 'memory',\n 'context-control': 'memory',\n compression: 'memory',\n 'kv-cache': 'memory',\n 'long-context': 'memory',\n 'long-term-memory': 'memory',\n 'episodic-memory': 'memory',\n 'graph-memory': 'memory',\n 'hierarchical-memory': 'memory',\n 'agentic-memory': 'memory',\n 'lifelong-learning': 'memory',\n 'cross-session-learning': 'memory',\n 'continual-learning': 'memory',\n 'self-editing-memory': 'memory',\n 'six-type-memory': 'memory',\n 'belief-memory': 'memory',\n 'belief-state': 'memory',\n 'action-memory': 'memory',\n 'memory-evolution': 'memory',\n 'virtual-context': 'memory',\n paging: 'memory',\n 'prompt-compression': 'memory',\n 'learned-compression': 'memory',\n zettelkasten: 'memory',\n 'knowledge-distillation': 'memory',\n 'history-encoding': 'memory',\n 'ictm-tuple': 'memory',\n 'latent-space': 'memory',\n 'vector-db': 'memory',\n embedding: 'memory',\n 'Taxonomy of context management strategies': 'memory',\n 'Task-specific context compression': 'memory',\n 'Learned compression modules': 'memory',\n rag: 'memory',\n 'retrieval augmented generation': 'memory',\n svd: 'memory',\n 'svd-mutation': 'memory',\n vae: 'memory',\n knn: 'memory',\n experience: 'memory',\n 'state-aware': 'memory',\n 'temporal-graph': 'memory',\n versioning: 'memory',\n\n // → code-generation\n 'code-repair': 'code-generation',\n 'code-agent': 'code-generation',\n 'code-review': 'code-generation',\n 'software-engineering': 'code-generation',\n 'swe-bench': 'code-generation',\n 'self-improvement': 'code-generation',\n 'self-evolving': 'code-generation',\n 'self-debug': 'code-generation',\n 'self-modification': 'code-generation',\n 'skill-library': 'code-generation',\n 'skill-discovery': 'code-generation',\n 'code review benchmarks': 'code-generation',\n 'code generation evaluation': 'code-generation',\n 'execution-feedback': 'code-generation',\n\n // → cli-tools\n mcp: 'cli-tools',\n 'MCP protocol': 'cli-tools',\n 'MCP security': 'cli-tools',\n 'MCP Security': 'cli-tools',\n 'mcp-applications': 'cli-tools',\n 'model-context-protocol': 'cli-tools',\n puppeteer: 'cli-tools',\n streaming: 'cli-tools',\n integration: 'cli-tools',\n\n // → orchestration\n 'multi-agent': 'orchestration',\n 'multi-agent-systems': 'orchestration',\n 'multi-agent orchestration': 'orchestration',\n 'Multi-Agent Orchestration': 'orchestration',\n 'multi-agent-orchestration': 'orchestration',\n 'multi-agent coordination': 'orchestration',\n 'multi-agent-coordination': 'orchestration',\n 'multi-agent-worker-dispatch': 'orchestration',\n 'multi-agent reliability': 'orchestration',\n 'multi-agent-rl': 'orchestration',\n coordination: 'orchestration',\n coordinator: 'orchestration',\n collaboration: 'orchestration',\n 'graph-orchestration': 'orchestration',\n 'agent architecture': 'orchestration',\n 'dynamic-agent-creation': 'orchestration',\n 'specialized-agents': 'orchestration',\n 'thinker-worker-verifier': 'orchestration',\n 'two-agent': 'orchestration',\n 'meta-agent': 'orchestration',\n agents: 'orchestration',\n 'workflow-optimization': 'orchestration',\n 'workflow-generation': 'orchestration',\n 'agent-communication': 'orchestration',\n 'inter-agent': 'orchestration',\n 'gvu-operator': 'orchestration',\n 'rubber-duck': 'orchestration',\n 'parallel-exploration': 'orchestration',\n kubernetes: 'orchestration',\n 'scale-to-zero': 'orchestration',\n edge: 'orchestration',\n llm: 'orchestration',\n multimodal: 'orchestration',\n production: 'orchestration',\n hybrid: 'orchestration',\n 'automatic-discovery': 'orchestration',\n roadmap: 'orchestration',\n\n // → security\n 'prompt injection defense': 'security',\n 'inter-agent-security': 'security',\n 'agent security': 'security',\n compliance: 'security',\n 'formal-verification': 'security',\n 'formal-safety': 'security',\n\n // → evaluation\n benchmark: 'evaluation',\n benchmarking: 'evaluation',\n survey: 'evaluation',\n 'autonomous agent evaluation benchmarks': 'evaluation',\n 'evaluation-methods': 'evaluation',\n 'LLM evaluation': 'evaluation',\n 'hallucination-detection': 'evaluation',\n 'self-evaluation': 'evaluation',\n 'confidence-probe': 'evaluation',\n 'confidence-aware': 'evaluation',\n verifier: 'evaluation',\n observability: 'evaluation',\n theoretical: 'evaluation',\n 'post-deployment': 'evaluation',\n capability: 'evaluation',\n 'knowledge-gaps': 'evaluation',\n helm: 'evaluation',\n\n // → safety\n 'agentic-safety': 'safety',\n 'agentic AI safety': 'safety',\n 'safety-evaluation': 'safety',\n 'reward-modeling': 'safety',\n 'constitutional-ai': 'safety',\n 'hazard-analysis': 'safety',\n stpa: 'safety',\n 'risk-assessment': 'safety',\n 'fault-tolerance': 'safety',\n 'ai-feedback': 'safety',\n rlaif: 'safety',\n 'human-in-the-loop': 'safety',\n feedback: 'safety',\n 'feedback-loop': 'safety',\n 'feedback-learning': 'safety',\n anthropic: 'safety',\n\n // → planning\n 'decision-making': 'planning',\n 'tree-search': 'planning',\n 'tree-structure': 'planning',\n 'multi-tree': 'planning',\n mcts: 'planning',\n backtrack: 'planning',\n hindsight: 'planning',\n 'task-specific': 'planning',\n\n // → tool-use\n 'tool use': 'tool-use',\n 'tool-augmented reasoning and function calling': 'tool-use',\n 'tool routing optimization': 'tool-use',\n 'dynamic-linking': 'tool-use',\n 'Sparse outcome rewards reduce tool calls by 72%': 'tool-use',\n\n // → reasoning\n 'test-time': 'reasoning',\n 'test-time-scaling': 'reasoning',\n 'inference-scaling': 'reasoning',\n 'inference-optimization': 'reasoning',\n 'self-critique': 'reasoning',\n 'self-reflection': 'reasoning',\n 'self-referential': 'reasoning',\n 'self-play': 'reasoning',\n reflexion: 'reasoning',\n reflection: 'reasoning',\n 'reasoning-optimization': 'reasoning',\n 'meta-thinking': 'reasoning',\n scaling: 'reasoning',\n recursive: 'reasoning',\n 'trajectory-abstraction': 'reasoning',\n 'verbal-rl': 'reasoning',\n exploration: 'reasoning',\n 'Reducible uncertainty modeling across agent trajectories': 'reasoning',\n 'Environmental feedback reduces uncertainty at decision gates': 'reasoning',\n 'reinforcement-learning': 'reasoning',\n transformer: 'reasoning',\n ssm: 'reasoning',\n 'sparse-activation': 'reasoning',\n 'behavior-distillation': 'reasoning',\n 'training-free': 'reasoning',\n 'transfer-learning': 'reasoning',\n 'instruction-tuning': 'reasoning',\n 'Dense process rewards improve performance by 22%': 'reasoning',\n 'prompt-optimization': 'reasoning',\n};\n\n/**\n * Normalize a free-form topic string to a canonical topic.\n * Returns the canonical topic if a mapping exists, otherwise the original string.\n */\nexport function normalizeTopicToCanonical(topic: string): string {\n return TOPIC_ALIASES[topic] ?? topic;\n}\n","/**\n * Research Synthesis Helper\n *\n * Groups papers by topic cluster and generates structured synthesis\n * summaries with themes, findings, and implementation opportunities.\n *\n * @module cli/research-helpers-synthesize\n * (Source: Issue #1386 — Research Synthesis Pipeline)\n */\n\nimport { loadPapersRegistry } from './research-helpers-io.js';\nimport type { PapersRegistry } from './research-types.js';\nimport type { Result } from '../core/result.js';\nimport { getErrorMessage } from '../core/index.js';\nimport { TECHNIQUE_IMPLEMENTATION_MAP, FEATURE_GATE_INVENTORY } from './research-alignment-map.js';\nimport { normalizeTopicToCanonical } from '../research/topic-aliases.js';\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/** A paper entry from the registry, simplified for synthesis. */\nexport interface SynthesisPaper {\n readonly id: string;\n readonly title: string;\n readonly topics: readonly string[];\n readonly tags: readonly string[];\n readonly summary: string;\n readonly keyFindings: readonly string[];\n readonly relevance: string;\n readonly implementationStatus: string;\n readonly techniquesExtracted: readonly string[];\n readonly qualityScore: number;\n readonly evidenceTier: 'high' | 'medium' | 'low';\n}\n\n/** A cluster of related papers grouped by topic. */\nexport interface PaperCluster {\n readonly topic: string;\n readonly papers: readonly SynthesisPaper[];\n readonly paperCount: number;\n}\n\n/** A technique aligned to an existing implementation. */\nexport interface TechniqueAlignment {\n readonly technique: string;\n readonly status: 'implemented' | 'partial' | 'not-started';\n readonly canonicalPath?: string | undefined;\n readonly improvementHint?: string | undefined;\n}\n\n/** Quality distribution within a cluster. */\nexport interface QualityDistribution {\n readonly avgScore: number;\n readonly high: number;\n readonly medium: number;\n readonly low: number;\n}\n\n/** Synthesis output for a single topic cluster. */\nexport interface ClusterSynthesis {\n readonly topic: string;\n readonly paperCount: number;\n readonly papers: readonly string[];\n readonly commonThemes: readonly string[];\n readonly keyInsights: readonly string[];\n readonly techniques: readonly string[];\n readonly implementationOpportunities: readonly string[];\n readonly gaps: readonly string[];\n readonly alignedTechniques: readonly TechniqueAlignment[];\n readonly qualityDistribution: QualityDistribution;\n}\n\n/** Summary of alignment between research and implementation. */\nexport interface AlignmentSummary {\n readonly implemented: number;\n readonly partial: number;\n readonly notStarted: number;\n readonly total: number;\n readonly topOpportunities: readonly string[];\n}\n\n/** Summary of a single feature gate for synthesis output. */\nexport interface FeatureGateStatus {\n readonly envVar: string;\n readonly defaultValue: string;\n readonly description: string;\n readonly linkedTechniqueCount: number;\n}\n\n/** Full synthesis result across all clusters. */\nexport interface SynthesisResult {\n readonly clusters: readonly ClusterSynthesis[];\n readonly totalPapers: number;\n readonly topicCount: number;\n readonly crossCuttingThemes: readonly string[];\n readonly alignmentSummary: AlignmentSummary;\n readonly featureGates: readonly FeatureGateStatus[];\n}\n\n/** Error for synthesis operations. */\nexport interface SynthesisError {\n readonly code: 'LOAD_ERROR' | 'NO_PAPERS';\n readonly message: string;\n}\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/** Minimum papers in a cluster to generate cross-cutting themes. */\nconst MIN_CROSS_CUTTING_CLUSTER_SIZE = 2;\n\n/** Tags that appear across many topics and indicate cross-cutting themes. */\nconst CROSS_CUTTING_TAG_THRESHOLD = 3;\n\n// =============================================================================\n// PUBLIC API\n// =============================================================================\n\n/**\n * Synthesize the research registry by grouping papers into topic clusters\n * and generating structured summaries.\n *\n * @param topicFilter - Optional topic to filter to a single cluster\n * @returns Structured synthesis result\n */\nexport async function synthesizeResearch(\n topicFilter?: string\n): Promise<Result<SynthesisResult, SynthesisError>> {\n const registryResult = await loadPapersRegistry();\n if (!registryResult.ok) {\n return {\n ok: false,\n error: {\n code: 'LOAD_ERROR',\n message: `Failed to load papers: ${getErrorMessage(registryResult.error)}`,\n },\n };\n }\n\n const papers = extractPapers(registryResult.value);\n if (papers.length === 0) {\n return {\n ok: false,\n error: { code: 'NO_PAPERS', message: 'No papers found in registry' },\n };\n }\n\n const clusters = groupByTopic(papers);\n const filtered =\n topicFilter !== undefined ? clusters.filter((c) => c.topic === topicFilter) : clusters;\n\n const syntheses = filtered.map(synthesizeCluster);\n const crossCutting = findCrossCuttingThemes(filtered);\n const alignmentSummary = buildAlignmentSummary(syntheses);\n const featureGates = buildFeatureGateSummary();\n\n return {\n ok: true,\n value: {\n clusters: syntheses,\n totalPapers: papers.length,\n topicCount: filtered.length,\n crossCuttingThemes: crossCutting,\n alignmentSummary,\n featureGates,\n },\n };\n}\n\n// =============================================================================\n// EXTRACTION\n// =============================================================================\n\n/**\n * Safely convert a field that types say is `readonly string[]` but may be\n * null/undefined at runtime (YAML parsing of empty array fields).\n */\nfunction safeArray(value: readonly string[]): string[] {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- YAML parsing can yield null despite type\n if (value === null || value === undefined) return [];\n return Array.from(value);\n}\n\n/** Extract papers from the registry structure. */\nfunction extractPapers(registry: PapersRegistry): SynthesisPaper[] {\n return Object.entries(registry.papers).map(([id, p]) => ({\n id,\n title: p.title,\n topics: safeArray(p.topics),\n tags: safeArray(p.tags),\n summary: p.summary.trim(),\n keyFindings: safeArray(p.key_findings),\n relevance: p.relevance,\n implementationStatus: p.implementation_status,\n techniquesExtracted: safeArray(p.techniques_extracted),\n qualityScore: p.quality_score ?? 0,\n evidenceTier: p.evidence_tier ?? 'low',\n }));\n}\n\n// =============================================================================\n// GROUPING\n// =============================================================================\n\n/** Group papers by primary topic into clusters, normalizing free-form topics. */\nfunction groupByTopic(papers: readonly SynthesisPaper[]): PaperCluster[] {\n const topicMap = new Map<string, SynthesisPaper[]>();\n\n for (const paper of papers) {\n for (const rawTopic of paper.topics) {\n const topic = normalizeTopicToCanonical(rawTopic);\n const existing = topicMap.get(topic);\n if (existing !== undefined) {\n existing.push(paper);\n } else {\n topicMap.set(topic, [paper]);\n }\n }\n }\n\n const clusters: PaperCluster[] = [];\n for (const [topic, unsortedPapers] of topicMap) {\n // Sort papers within cluster by quality_score descending (high-quality first)\n const topicPapers = [...unsortedPapers].sort((a, b) => b.qualityScore - a.qualityScore);\n clusters.push({\n topic,\n papers: topicPapers,\n paperCount: topicPapers.length,\n });\n }\n\n return clusters.sort((a, b) => b.paperCount - a.paperCount);\n}\n\n// =============================================================================\n// SYNTHESIS\n// =============================================================================\n\n/** Generate synthesis for a single topic cluster. */\n/** Compute quality score distribution for a set of papers. */\nfunction computeClusterQuality(papers: readonly SynthesisPaper[]): QualityDistribution {\n const scores = papers.map((p) => p.qualityScore);\n const totalScore = scores.reduce((sum, s) => sum + s, 0);\n return {\n avgScore: scores.length > 0 ? Math.round((totalScore / scores.length) * 10) / 10 : 0,\n high: papers.filter((p) => p.evidenceTier === 'high').length,\n medium: papers.filter((p) => p.evidenceTier === 'medium').length,\n low: papers.filter((p) => p.evidenceTier === 'low').length,\n };\n}\n\nfunction synthesizeCluster(cluster: PaperCluster): ClusterSynthesis {\n const allTags = collectFrequencies(cluster.papers.flatMap((p) => [...p.tags]));\n const allTechniques = collectFrequencies(\n cluster.papers.flatMap((p) => [...p.techniquesExtracted])\n );\n const allFindings = cluster.papers.flatMap((p) => [...p.keyFindings]);\n\n // Common themes: tags that appear in 2+ papers\n const commonThemes = [...allTags.entries()]\n .filter(([, count]) => count >= MIN_CROSS_CUTTING_CLUSTER_SIZE)\n .sort((a, b) => b[1] - a[1])\n .map(([tag]) => tag);\n\n // Techniques across the cluster\n const techniques = [...allTechniques.entries()]\n .sort((a, b) => b[1] - a[1])\n .map(([tech, count]) => (count > 1 ? `${tech} (${String(count)} papers)` : tech));\n\n // Implementation opportunities: techniques not yet implemented\n const notStarted = cluster.papers\n .filter((p) => p.implementationStatus === 'not-started')\n .flatMap((p) => [...p.techniquesExtracted]);\n const uniqueOpportunities = [...new Set(notStarted)];\n\n // Gaps: topics with few papers or missing techniques\n const gaps: string[] = [];\n if (cluster.paperCount === 1) {\n gaps.push(`Only 1 paper — more research needed on ${cluster.topic}`);\n }\n const highRelevanceUnimplemented = cluster.papers.filter(\n (p) => p.relevance === 'high' && p.implementationStatus === 'not-started'\n );\n if (highRelevanceUnimplemented.length > 0) {\n gaps.push(\n `${String(highRelevanceUnimplemented.length)} high-relevance paper(s) not yet implemented`\n );\n }\n\n // Alignment analysis: map techniques to existing implementations\n const allTechNames = [...allTechniques.keys()];\n const alignedTechniques = analyzeClusterAlignment(allTechNames);\n\n const qualityDistribution = computeClusterQuality(cluster.papers);\n\n // Add quality gap if most papers are low-quality\n if (qualityDistribution.low > qualityDistribution.high + qualityDistribution.medium) {\n gaps.push(\n `Mostly low-evidence papers (${String(qualityDistribution.low)}/${String(cluster.paperCount)}) — findings need stronger validation`\n );\n }\n\n return {\n topic: cluster.topic,\n paperCount: cluster.paperCount,\n papers: cluster.papers.map((p) => p.title),\n commonThemes,\n keyInsights: deduplicateFindings(allFindings).slice(0, 10),\n techniques,\n implementationOpportunities: uniqueOpportunities,\n gaps,\n alignedTechniques,\n qualityDistribution,\n };\n}\n\n/** Find themes that span multiple topic clusters. */\nfunction findCrossCuttingThemes(clusters: readonly PaperCluster[]): string[] {\n const tagToTopics = new Map<string, Set<string>>();\n\n for (const cluster of clusters) {\n for (const paper of cluster.papers) {\n for (const tag of paper.tags) {\n const existing = tagToTopics.get(tag);\n if (existing !== undefined) {\n existing.add(cluster.topic);\n } else {\n tagToTopics.set(tag, new Set([cluster.topic]));\n }\n }\n }\n }\n\n return [...tagToTopics.entries()]\n .filter(([, topics]) => topics.size >= CROSS_CUTTING_TAG_THRESHOLD)\n .sort((a, b) => b[1].size - a[1].size)\n .map(([tag, topics]) => `${tag} (spans: ${[...topics].join(', ')})`);\n}\n\n// =============================================================================\n// ALIGNMENT ANALYSIS\n// =============================================================================\n\n/** Analyze technique alignment for a cluster. */\nfunction analyzeClusterAlignment(techniques: readonly string[]): TechniqueAlignment[] {\n const alignments: TechniqueAlignment[] = [];\n\n for (const tech of techniques) {\n // Strip count annotation like \"technique (2 papers)\"\n const baseTech = tech.replace(/\\s*\\(\\d+\\s*papers?\\)$/, '');\n const mapping = TECHNIQUE_IMPLEMENTATION_MAP.get(baseTech);\n\n if (mapping !== undefined) {\n alignments.push({\n technique: baseTech,\n status: mapping.status,\n canonicalPath: mapping.path,\n ...(mapping.hint !== undefined ? { improvementHint: mapping.hint } : {}),\n });\n } else {\n alignments.push({ technique: baseTech, status: 'not-started' });\n }\n }\n\n return alignments;\n}\n\n/** Build alignment summary across all clusters. */\nfunction buildAlignmentSummary(clusters: readonly ClusterSynthesis[]): AlignmentSummary {\n const allAlignments = clusters.flatMap((c) => c.alignedTechniques);\n const implemented = allAlignments.filter((a) => a.status === 'implemented').length;\n const partial = allAlignments.filter((a) => a.status === 'partial').length;\n const notStarted = allAlignments.filter((a) => a.status === 'not-started').length;\n\n // Top opportunities: partial implementations with hints (most improvable)\n const opportunities = allAlignments\n .filter((a) => a.status === 'partial' && a.improvementHint !== undefined)\n .map((a) => `${a.technique}: ${a.improvementHint ?? ''}`)\n .slice(0, 10);\n\n return {\n implemented,\n partial,\n notStarted,\n total: allAlignments.length,\n topOpportunities: opportunities,\n };\n}\n\n/** Build feature gate summary from the inventory. */\nfunction buildFeatureGateSummary(): FeatureGateStatus[] {\n return FEATURE_GATE_INVENTORY.map((g) => ({\n envVar: g.envVar,\n defaultValue: g.defaultValue,\n description: g.description,\n linkedTechniqueCount: g.techniques?.length ?? 0,\n }));\n}\n\n// =============================================================================\n// UTILITIES\n// =============================================================================\n\nfunction collectFrequencies(items: readonly string[]): Map<string, number> {\n const counts = new Map<string, number>();\n for (const item of items) {\n counts.set(item, (counts.get(item) ?? 0) + 1);\n }\n return counts;\n}\n\n/** Deduplicate findings by removing near-identical strings. */\nfunction deduplicateFindings(findings: readonly string[]): string[] {\n const seen = new Set<string>();\n const result: string[] = [];\n for (const finding of findings) {\n const normalized = finding.toLowerCase().trim();\n if (normalized.length === 0) continue;\n if (seen.has(normalized)) continue;\n seen.add(normalized);\n result.push(finding);\n }\n return result;\n}\n"],"mappings":"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","names":["resolve","resolve"]}
|