nexus-agents 2.168.0 → 2.170.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.
Files changed (130) hide show
  1. package/README.md +1 -1
  2. package/dist/{child-mcp-config-FAWSJFMQ.js → child-mcp-config-3RYBPZNE.js} +2 -2
  3. package/dist/{chunk-HZNOSJOO.js → chunk-57RYP435.js} +3 -3
  4. package/dist/{chunk-IAGLVGHN.js → chunk-5N5XURKV.js} +2 -2
  5. package/dist/{chunk-3KID7AIF.js → chunk-6TN2Z2AQ.js} +3 -3
  6. package/dist/{chunk-GNCUZDQI.js → chunk-75AUSQL4.js} +7 -7
  7. package/dist/{chunk-P7RBQUAG.js → chunk-BGV3IF3G.js} +8 -8
  8. package/dist/{chunk-F5JDQXHJ.js → chunk-C6IAXFNC.js} +2 -2
  9. package/dist/{chunk-2Z4QECP7.js → chunk-DCXCVEZP.js} +2 -2
  10. package/dist/{chunk-G7NDNFIE.js → chunk-DDQXPARJ.js} +3 -3
  11. package/dist/{chunk-UN7PYUJB.js → chunk-DEE2UTYV.js} +2 -2
  12. package/dist/{chunk-OKAHIWG4.js → chunk-GVTXP6F6.js} +25 -4
  13. package/dist/chunk-GVTXP6F6.js.map +1 -0
  14. package/dist/{chunk-6ERIC5NJ.js → chunk-HTM32H2E.js} +2 -2
  15. package/dist/{chunk-VQE3OSUW.js → chunk-JLG5AUZB.js} +2 -2
  16. package/dist/{chunk-MSBYVBPX.js → chunk-JOYOOEPJ.js} +2 -2
  17. package/dist/{chunk-N56C2MWI.js → chunk-JYDXHV4L.js} +2 -2
  18. package/dist/{chunk-CPS2HN4T.js → chunk-LDZEYJP3.js} +2 -2
  19. package/dist/{chunk-ELWMGKVP.js → chunk-LOKT6EW7.js} +8 -8
  20. package/dist/{chunk-LNPKBBPG.js → chunk-LYWNKEGM.js} +4 -4
  21. package/dist/{chunk-2ANAH2UU.js → chunk-MG4JBADQ.js} +4 -4
  22. package/dist/{chunk-TORS5V2C.js → chunk-NXSY4G4Y.js} +2 -2
  23. package/dist/{chunk-EQLJYWLP.js → chunk-OFVUBY6Z.js} +3 -3
  24. package/dist/{chunk-OLCDGMEO.js → chunk-OIT75IRK.js} +4 -4
  25. package/dist/{chunk-RJHLNI37.js → chunk-OYBAKU7N.js} +2 -2
  26. package/dist/{chunk-I3LGUSZ3.js → chunk-P4PLZZCR.js} +5 -5
  27. package/dist/{chunk-MX3XD2ML.js → chunk-PIODB4SW.js} +2 -2
  28. package/dist/{chunk-52T2MJDS.js → chunk-QMOJJ6A2.js} +732 -598
  29. package/dist/chunk-QMOJJ6A2.js.map +1 -0
  30. package/dist/{chunk-ETFCT2CH.js → chunk-RJDJMOX6.js} +4 -4
  31. package/dist/{chunk-5LPPJIZ4.js → chunk-RZJQZ5P3.js} +2 -2
  32. package/dist/{chunk-7IUVW67T.js → chunk-SCHD7NZD.js} +7 -7
  33. package/dist/{chunk-HJA3Z56H.js → chunk-URRNWRI4.js} +234 -20
  34. package/dist/chunk-URRNWRI4.js.map +1 -0
  35. package/dist/{chunk-UGJRDFMN.js → chunk-UXXNNT5D.js} +2 -2
  36. package/dist/{chunk-TZK7VQAW.js → chunk-WKW5SEP7.js} +5 -5
  37. package/dist/{chunk-AO4X3BMP.js → chunk-YF35FKKD.js} +2 -1
  38. package/dist/chunk-YF35FKKD.js.map +1 -0
  39. package/dist/{chunk-RQNBJ7AS.js → chunk-Z4AWOPXA.js} +2 -2
  40. package/dist/{chunk-CJLMB7MO.js → chunk-ZW7544DX.js} +3 -3
  41. package/dist/{cli-circuit-breaker-JDGZ25MD.js → cli-circuit-breaker-4GJA2IXC.js} +4 -4
  42. package/dist/cli.js +43 -41
  43. package/dist/cli.js.map +1 -1
  44. package/dist/codebase-search-LUF5YJLQ.js +14 -0
  45. package/dist/{composite-router-EZPPVCMD.js → composite-router-UBZO4YR7.js} +2 -2
  46. package/dist/{consensus-vote-YKKJHLOD.js → consensus-vote-USZFJO2K.js} +15 -15
  47. package/dist/{context-retriever-EGMARBAC.js → context-retriever-C5C7RFQE.js} +8 -8
  48. package/dist/{doctor-deep-QTBDR3VV.js → doctor-deep-2N3F7EV6.js} +3 -3
  49. package/dist/{expert-bridge-FZYJ3XAL.js → expert-bridge-B3EFTAID.js} +4 -4
  50. package/dist/{factory-SABHBAHC.js → factory-LKQKU3SD.js} +8 -8
  51. package/dist/{factory-NDMPXPYE.js → factory-SURRFPSV.js} +5 -5
  52. package/dist/{improvement-review-WYFGNEVP.js → improvement-review-75OCZ5K7.js} +5 -5
  53. package/dist/index.d.ts +40 -1
  54. package/dist/index.js +35 -31
  55. package/dist/index.js.map +1 -1
  56. package/dist/{init-opencode-CMGJ3TXZ.js → init-opencode-LDI5E5LW.js} +5 -5
  57. package/dist/{issue-triage-NHRZGMKC.js → issue-triage-WWQEY7PL.js} +6 -6
  58. package/dist/{pr-reviewer-helpers-HJRFRUZX.js → pr-reviewer-helpers-HDP24LGZ.js} +4 -4
  59. package/dist/{registry-command-JCOZA7TM.js → registry-command-PZY7HWKO.js} +2 -2
  60. package/dist/{repo-security-plan-OMY33VHA.js → repo-security-plan-IYKDY5PW.js} +3 -3
  61. package/dist/{research-helpers-synthesize-DFINP3KN.js → research-helpers-synthesize-XSOFXRFK.js} +4 -4
  62. package/dist/{routing-memory-KK4GPB64.js → routing-memory-JTNH2BXS.js} +2 -2
  63. package/dist/{session-memory-QTHGU2XM.js → session-memory-RJZ447UX.js} +3 -3
  64. package/dist/{setup-command-CURZCHSQ.js → setup-command-35MCRS33.js} +13 -13
  65. package/dist/{setup-config-FX6SJXGQ.js → setup-config-JV23ZYPO.js} +3 -3
  66. package/dist/{setup-custom-api-MYN4EVT2.js → setup-custom-api-LMA445OB.js} +3 -3
  67. package/dist/{tool-memory-3W5NXR4P.js → tool-memory-K6EYH3FQ.js} +5 -5
  68. package/dist/{unified-registry-PKPNJ3G7.js → unified-registry-MJA6IBDD.js} +9 -9
  69. package/dist/{weather-report-46ZY3X2Z.js → weather-report-ID4ZNUAF.js} +2 -2
  70. package/package.json +2 -1
  71. package/dist/chunk-52T2MJDS.js.map +0 -1
  72. package/dist/chunk-AO4X3BMP.js.map +0 -1
  73. package/dist/chunk-HJA3Z56H.js.map +0 -1
  74. package/dist/chunk-OKAHIWG4.js.map +0 -1
  75. package/dist/codebase-search-DKLEA4PR.js +0 -12
  76. /package/dist/{child-mcp-config-FAWSJFMQ.js.map → child-mcp-config-3RYBPZNE.js.map} +0 -0
  77. /package/dist/{chunk-HZNOSJOO.js.map → chunk-57RYP435.js.map} +0 -0
  78. /package/dist/{chunk-IAGLVGHN.js.map → chunk-5N5XURKV.js.map} +0 -0
  79. /package/dist/{chunk-3KID7AIF.js.map → chunk-6TN2Z2AQ.js.map} +0 -0
  80. /package/dist/{chunk-GNCUZDQI.js.map → chunk-75AUSQL4.js.map} +0 -0
  81. /package/dist/{chunk-P7RBQUAG.js.map → chunk-BGV3IF3G.js.map} +0 -0
  82. /package/dist/{chunk-F5JDQXHJ.js.map → chunk-C6IAXFNC.js.map} +0 -0
  83. /package/dist/{chunk-2Z4QECP7.js.map → chunk-DCXCVEZP.js.map} +0 -0
  84. /package/dist/{chunk-G7NDNFIE.js.map → chunk-DDQXPARJ.js.map} +0 -0
  85. /package/dist/{chunk-UN7PYUJB.js.map → chunk-DEE2UTYV.js.map} +0 -0
  86. /package/dist/{chunk-6ERIC5NJ.js.map → chunk-HTM32H2E.js.map} +0 -0
  87. /package/dist/{chunk-VQE3OSUW.js.map → chunk-JLG5AUZB.js.map} +0 -0
  88. /package/dist/{chunk-MSBYVBPX.js.map → chunk-JOYOOEPJ.js.map} +0 -0
  89. /package/dist/{chunk-N56C2MWI.js.map → chunk-JYDXHV4L.js.map} +0 -0
  90. /package/dist/{chunk-CPS2HN4T.js.map → chunk-LDZEYJP3.js.map} +0 -0
  91. /package/dist/{chunk-ELWMGKVP.js.map → chunk-LOKT6EW7.js.map} +0 -0
  92. /package/dist/{chunk-LNPKBBPG.js.map → chunk-LYWNKEGM.js.map} +0 -0
  93. /package/dist/{chunk-2ANAH2UU.js.map → chunk-MG4JBADQ.js.map} +0 -0
  94. /package/dist/{chunk-TORS5V2C.js.map → chunk-NXSY4G4Y.js.map} +0 -0
  95. /package/dist/{chunk-EQLJYWLP.js.map → chunk-OFVUBY6Z.js.map} +0 -0
  96. /package/dist/{chunk-OLCDGMEO.js.map → chunk-OIT75IRK.js.map} +0 -0
  97. /package/dist/{chunk-RJHLNI37.js.map → chunk-OYBAKU7N.js.map} +0 -0
  98. /package/dist/{chunk-I3LGUSZ3.js.map → chunk-P4PLZZCR.js.map} +0 -0
  99. /package/dist/{chunk-MX3XD2ML.js.map → chunk-PIODB4SW.js.map} +0 -0
  100. /package/dist/{chunk-ETFCT2CH.js.map → chunk-RJDJMOX6.js.map} +0 -0
  101. /package/dist/{chunk-5LPPJIZ4.js.map → chunk-RZJQZ5P3.js.map} +0 -0
  102. /package/dist/{chunk-7IUVW67T.js.map → chunk-SCHD7NZD.js.map} +0 -0
  103. /package/dist/{chunk-UGJRDFMN.js.map → chunk-UXXNNT5D.js.map} +0 -0
  104. /package/dist/{chunk-TZK7VQAW.js.map → chunk-WKW5SEP7.js.map} +0 -0
  105. /package/dist/{chunk-RQNBJ7AS.js.map → chunk-Z4AWOPXA.js.map} +0 -0
  106. /package/dist/{chunk-CJLMB7MO.js.map → chunk-ZW7544DX.js.map} +0 -0
  107. /package/dist/{cli-circuit-breaker-JDGZ25MD.js.map → cli-circuit-breaker-4GJA2IXC.js.map} +0 -0
  108. /package/dist/{codebase-search-DKLEA4PR.js.map → codebase-search-LUF5YJLQ.js.map} +0 -0
  109. /package/dist/{composite-router-EZPPVCMD.js.map → composite-router-UBZO4YR7.js.map} +0 -0
  110. /package/dist/{consensus-vote-YKKJHLOD.js.map → consensus-vote-USZFJO2K.js.map} +0 -0
  111. /package/dist/{context-retriever-EGMARBAC.js.map → context-retriever-C5C7RFQE.js.map} +0 -0
  112. /package/dist/{doctor-deep-QTBDR3VV.js.map → doctor-deep-2N3F7EV6.js.map} +0 -0
  113. /package/dist/{expert-bridge-FZYJ3XAL.js.map → expert-bridge-B3EFTAID.js.map} +0 -0
  114. /package/dist/{factory-NDMPXPYE.js.map → factory-LKQKU3SD.js.map} +0 -0
  115. /package/dist/{factory-SABHBAHC.js.map → factory-SURRFPSV.js.map} +0 -0
  116. /package/dist/{improvement-review-WYFGNEVP.js.map → improvement-review-75OCZ5K7.js.map} +0 -0
  117. /package/dist/{init-opencode-CMGJ3TXZ.js.map → init-opencode-LDI5E5LW.js.map} +0 -0
  118. /package/dist/{issue-triage-NHRZGMKC.js.map → issue-triage-WWQEY7PL.js.map} +0 -0
  119. /package/dist/{pr-reviewer-helpers-HJRFRUZX.js.map → pr-reviewer-helpers-HDP24LGZ.js.map} +0 -0
  120. /package/dist/{registry-command-JCOZA7TM.js.map → registry-command-PZY7HWKO.js.map} +0 -0
  121. /package/dist/{repo-security-plan-OMY33VHA.js.map → repo-security-plan-IYKDY5PW.js.map} +0 -0
  122. /package/dist/{research-helpers-synthesize-DFINP3KN.js.map → research-helpers-synthesize-XSOFXRFK.js.map} +0 -0
  123. /package/dist/{routing-memory-KK4GPB64.js.map → routing-memory-JTNH2BXS.js.map} +0 -0
  124. /package/dist/{session-memory-QTHGU2XM.js.map → session-memory-RJZ447UX.js.map} +0 -0
  125. /package/dist/{setup-command-CURZCHSQ.js.map → setup-command-35MCRS33.js.map} +0 -0
  126. /package/dist/{setup-config-FX6SJXGQ.js.map → setup-config-JV23ZYPO.js.map} +0 -0
  127. /package/dist/{setup-custom-api-MYN4EVT2.js.map → setup-custom-api-LMA445OB.js.map} +0 -0
  128. /package/dist/{tool-memory-3W5NXR4P.js.map → tool-memory-K6EYH3FQ.js.map} +0 -0
  129. /package/dist/{unified-registry-PKPNJ3G7.js.map → unified-registry-MJA6IBDD.js.map} +0 -0
  130. /package/dist/{weather-report-46ZY3X2Z.js.map → weather-report-ID4ZNUAF.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/learning/strategy-distiller-persistence.ts","../src/cli/research-helpers-status.ts","../src/cli/research-helpers-overlap.ts","../src/research/research-quality.ts","../src/cli/research-helpers-registry.ts","../src/cli/research-helpers-arxiv.ts","../src/cli/research-helpers-sources.ts","../src/cli/research-helpers-sources-io.ts","../src/cli/research-helpers-sources-academic.ts","../src/cli/research-helpers-scoring.ts","../src/cli/research-helpers-index-ops.ts","../src/indexer/research-index/research-index-base-types.ts","../src/indexer/research-index/research-index-stats-types.ts","../src/indexer/research-index/research-index-parser.ts","../src/research/source-quality.ts","../src/indexer/research-index/research-index-generator-helpers.ts","../src/indexer/research-index/research-index-generator.ts","../src/cli/research-helpers-issues.ts","../src/context/context-retriever-helpers.ts","../src/context/token-counter.ts","../src/context/token-counter-types.ts","../src/context/token-ledger.ts","../src/indexer/category-detection.ts","../src/indexer/export-extraction.ts","../src/indexer/dependency-extraction.ts","../src/indexer/description-extraction.ts","../src/indexer/project-extraction.ts","../src/indexer/types.ts","../src/indexer/analyzer.ts","../src/context/repo-map-callsites.ts","../src/indexer/usage-ast.ts","../src/context/repo-map.ts","../src/context/context-retriever.ts"],"sourcesContent":["/**\n * Persistent StrategyDistiller — JSON-backed cross-session persistence.\n *\n * Extends StrategyDistiller with atomic disk writes (write tmp + rename)\n * for distilled rules. Hydrates from a versioned JSON snapshot on\n * construction; saves after every distill() call.\n *\n * @module learning/strategy-distiller-persistence\n * (Source: Issue #1009 — Cross-session persistence)\n */\n\nimport { writeFileSync, readFileSync, renameSync, unlinkSync, existsSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { z } from 'zod';\nimport { CLI_NAMES } from '../config/model-capabilities-types.js';\n\nimport type { ILogger } from '../core/index.js';\nimport { createLogger } from '../core/index.js';\nimport type { OutcomeStore } from '../orchestration/outcomes/outcome-store.js';\nimport type { DistilledRule, DistillerConfig } from './strategy-distiller-types.js';\nimport { StrategyDistiller, registerPersistentDistillerFactory } from './strategy-distiller.js';\nimport { ensureLearningDir, getRulesFile } from '../config/learning-persistence.js';\n\n// ============================================================================\n// Versioned Schema\n// ============================================================================\n\nconst DistilledRuleSchema = z.object({\n id: z.string(),\n patternType: z.enum(['failure-rate', 'success-rate', 'latency-spike']),\n cli: z.enum(CLI_NAMES),\n category: z.string(),\n action: z.enum(['penalize', 'boost', 'avoid']),\n confidence: z.number(),\n observationCount: z.number(),\n metric: z.number(),\n status: z.enum(['draft', 'active', 'promoted', 'expired']),\n createdAt: z.number(),\n updatedAt: z.number(),\n tainted: z.boolean(),\n});\n\n/** Versioned snapshot schema for atomic saves. */\nexport const RulesSnapshotSchema = z.object({\n version: z.literal(1),\n savedAt: z.string(),\n rules: z.array(DistilledRuleSchema),\n});\n\nexport type RulesSnapshot = z.infer<typeof RulesSnapshotSchema>;\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport interface PersistentDistillerConfig {\n /** Override the file path (useful for testing). */\n readonly filePath?: string;\n /** Override the data directory (useful for testing). */\n readonly dataDir?: string;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * StrategyDistiller that persists distilled rules to a JSON file.\n *\n * - Construction: hydrates from rules.json via Zod validation\n * - distill(): calls super.distill() then atomically saves snapshot\n * - Corruption: warn + start fresh (no partial loads)\n */\nexport class PersistentStrategyDistiller extends StrategyDistiller {\n private readonly filePath: string;\n private readonly persistLogger: ILogger;\n\n constructor(\n outcomeStore: OutcomeStore,\n persistConfig?: PersistentDistillerConfig,\n logger?: ILogger,\n distillerConfig?: Partial<DistillerConfig>\n ) {\n super(outcomeStore, logger, distillerConfig);\n this.filePath = persistConfig?.filePath ?? getRulesFile();\n this.persistLogger = logger ?? createLogger({ component: 'PersistentStrategyDistiller' });\n\n const dataDir = persistConfig?.dataDir;\n ensureLearningDir(dataDir);\n this.hydrate();\n }\n\n /** Override distill to persist rules after each run. */\n override distill(): void {\n super.distill();\n this.saveSnapshot();\n }\n\n // ==========================================================================\n // Private\n // ==========================================================================\n\n private hydrate(): void {\n if (!existsSync(this.filePath)) {\n this.persistLogger.debug('No rules file found, starting fresh', {\n path: this.filePath,\n });\n return;\n }\n\n try {\n const content = readFileSync(this.filePath, 'utf-8');\n const parsed: unknown = JSON.parse(content);\n const result = RulesSnapshotSchema.safeParse(parsed);\n\n if (!result.success) {\n this.persistLogger.warn('Rules file failed validation, starting fresh', {\n path: this.filePath,\n error: result.error.message,\n });\n return;\n }\n\n this.loadRules(result.data.rules);\n this.persistLogger.info('Hydrated distilled rules from disk', {\n ruleCount: result.data.rules.length,\n savedAt: result.data.savedAt,\n path: this.filePath,\n });\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n this.persistLogger.warn('Failed to hydrate rules from disk', {\n error: msg,\n path: this.filePath,\n });\n }\n }\n\n private saveSnapshot(): void {\n const rules = this.getRules();\n const snapshot: RulesSnapshot = {\n version: 1,\n savedAt: new Date().toISOString(),\n rules: rules as DistilledRule[],\n };\n\n // PID-suffixed temp path so two processes saving concurrently don't truncate each\n // other's temp file mid-renameSync. Matches the convention in correlation-persistence.ts\n // and research-auto-catalog.ts. Closes #2972.\n const tmpPath = `${this.filePath}.tmp.${String(process.pid)}`;\n try {\n // Ensure parent directory exists\n ensureLearningDir(dirname(this.filePath));\n // Atomic write: temp file + rename\n writeFileSync(tmpPath, JSON.stringify(snapshot, null, 2), 'utf-8');\n renameSync(tmpPath, this.filePath);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n this.persistLogger.warn('Failed to persist rules to disk', {\n error: msg,\n path: this.filePath,\n });\n // Clean up temp file on failure\n try {\n if (existsSync(tmpPath)) unlinkSync(tmpPath);\n } catch (cleanupErr: unknown) {\n const msg = cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr);\n this.persistLogger.debug('Failed to clean up temp file during persist', {\n path: tmpPath,\n error: msg,\n });\n }\n }\n }\n}\n\n// Self-register factory so CompositeRouter can create PersistentStrategyDistiller\n// without a circular top-level import.\nregisterPersistentDistillerFactory(\n (outcomeStore, logger) => new PersistentStrategyDistiller(outcomeStore, undefined, logger)\n);\n\n/**\n * Phase 5 of #2792 — read the persisted distilled rules from disk\n * without needing a live `StrategyDistiller` instance.\n *\n * `ContextRetriever` uses this so `UnifiedContext.priorStrategies`\n * surfaces the routing learnings the CompositeRouter has already\n * derived, even when the consumer is in a different process / scope\n * (e.g. an `orchestrate` invocation that hasn't constructed its own\n * router yet).\n *\n * Returns `[]` when the file is missing, corrupt, or unreadable; never\n * throws. The caller is responsible for filtering to status / category /\n * tainted as appropriate — this loader returns the raw rule set so\n * future consumers can apply their own predicates.\n */\nexport function loadPersistedRules(filePath: string = getRulesFile()): readonly DistilledRule[] {\n if (!existsSync(filePath)) return [];\n try {\n const content = readFileSync(filePath, 'utf-8');\n const parsed: unknown = JSON.parse(content);\n const result = RulesSnapshotSchema.safeParse(parsed);\n if (!result.success) return [];\n return result.data.rules;\n } catch {\n // Disk read / parse failures contribute an empty list — the consumer\n // contract is \"absence means no signal,\" never an exception.\n return [];\n }\n}\n","/**\n * Research Registry Status Helpers\n *\n * Functions for computing and formatting technique status information.\n *\n * @see docs/research/RESEARCH_INDEX.md\n * @see Issue #237 (Epic #225)\n */\n\nimport type {\n TechniqueEntry,\n TechniqueStatus,\n TechniqueStatusSummary,\n ResearchStatusOptions,\n ResearchStatusResult,\n} from './research-types.js';\nimport { loadTechniquesRegistry } from './research-helpers-io.js';\n\n// =============================================================================\n// CONVERSION HELPERS\n// =============================================================================\n\n/**\n * Convert technique entry to status summary.\n */\nexport function toStatusSummary(id: string, entry: TechniqueEntry): TechniqueStatusSummary {\n return {\n id,\n name: entry.name,\n status: entry.status,\n priority: entry.priority,\n topic: entry.topic,\n implementationIssue: entry.implementation_issue,\n };\n}\n\n// =============================================================================\n// FILTERING\n// =============================================================================\n\n/**\n * Filter techniques by status.\n */\nexport function filterByStatus(\n techniques: Record<string, TechniqueEntry>,\n status: TechniqueStatus | 'all'\n): TechniqueStatusSummary[] {\n return Object.entries(techniques)\n .filter(([, entry]) => status === 'all' || entry.status === status)\n .map(([id, entry]) => toStatusSummary(id, entry))\n .sort((a, b) => {\n // Sort by priority (P1 first), then by name\n const priorityOrder: Record<string, number> = { P1: 0, P2: 1, P3: 2, P4: 3 };\n const aPriority = a.priority !== null ? (priorityOrder[a.priority] ?? 4) : 4;\n const bPriority = b.priority !== null ? (priorityOrder[b.priority] ?? 4) : 4;\n if (aPriority !== bPriority) return aPriority - bPriority;\n return a.name.localeCompare(b.name);\n });\n}\n\n// =============================================================================\n// COUNTING\n// =============================================================================\n\n/**\n * Count techniques by status.\n */\nexport function countByStatus(\n techniques: Record<string, TechniqueEntry>\n): ResearchStatusResult['counts'] {\n let implemented = 0;\n let planned = 0;\n let notStarted = 0;\n let rejected = 0;\n\n for (const entry of Object.values(techniques)) {\n switch (entry.status) {\n case 'implemented':\n implemented++;\n break;\n case 'planned':\n case 'in-progress':\n planned++;\n break;\n case 'not-started':\n notStarted++;\n break;\n case 'rejected':\n rejected++;\n break;\n }\n }\n\n return {\n implemented,\n planned,\n notStarted,\n rejected,\n total: implemented + planned + notStarted + rejected,\n };\n}\n\n// =============================================================================\n// MAIN STATUS FUNCTION\n// =============================================================================\n\n/**\n * Get status of techniques.\n */\nexport async function getResearchStatus(\n options: ResearchStatusOptions\n): Promise<ResearchStatusResult> {\n const result = await loadTechniquesRegistry();\n if (!result.ok) {\n return {\n success: false,\n techniques: [],\n counts: { implemented: 0, planned: 0, notStarted: 0, rejected: 0, total: 0 },\n };\n }\n const registry = result.value;\n\n // If specific technique requested\n if (options.techniqueId !== undefined && options.techniqueId !== '') {\n const entry = registry.techniques[options.techniqueId];\n if (entry === undefined) {\n return {\n success: false,\n techniques: [],\n counts: countByStatus(registry.techniques),\n };\n }\n return {\n success: true,\n techniques: [toStatusSummary(options.techniqueId, entry)],\n counts: countByStatus(registry.techniques),\n };\n }\n\n // Filter by status\n const statusFilter = options.status === 'all' ? 'all' : (options.status as TechniqueStatus);\n const techniques = filterByStatus(registry.techniques, statusFilter);\n\n return {\n success: true,\n techniques,\n counts: countByStatus(registry.techniques),\n };\n}\n\n// =============================================================================\n// FORMATTING\n// =============================================================================\n\n/**\n * Format status result for display.\n */\nexport function formatStatusResult(\n result: ResearchStatusResult,\n format: 'table' | 'json' | 'compact'\n): string {\n if (format === 'json') {\n return JSON.stringify(result, null, 2);\n }\n\n if (format === 'compact') {\n const lines = result.techniques.map(\n (t) => `${t.status.padEnd(12)} ${(t.priority ?? '-').padEnd(3)} ${t.id}`\n );\n return lines.join('\\n');\n }\n\n // Table format\n const lines: string[] = [];\n lines.push('Research Registry Status');\n lines.push('='.repeat(60));\n lines.push('');\n\n // Summary counts\n const { counts } = result;\n lines.push(\n `Implemented: ${String(counts.implemented)} | Planned: ${String(counts.planned)} | Not Started: ${String(counts.notStarted)} | Rejected: ${String(counts.rejected)}`\n );\n lines.push(`Total: ${String(counts.total)}`);\n lines.push('');\n\n if (result.techniques.length === 0) {\n lines.push('No techniques found matching criteria.');\n return lines.join('\\n');\n }\n\n // Table header\n lines.push('Status | Pri | Topic | ID');\n lines.push('-'.repeat(60));\n\n for (const tech of result.techniques) {\n const status = tech.status.padEnd(12);\n const priority = (tech.priority ?? '-').padEnd(3);\n const topic = tech.topic.slice(0, 14).padEnd(14);\n lines.push(`${status} | ${priority} | ${topic} | ${tech.id}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * Research Registry Overlap Helpers\n *\n * Functions for detecting and analyzing technique overlaps.\n *\n * @see docs/research/RESEARCH_INDEX.md\n * @see Issue #237 (Epic #225)\n */\n\nimport type {\n TechniqueEntry,\n ResearchOverlapOptions,\n ResearchOverlapResult,\n OverlapMatch,\n} from './research-types.js';\nimport { loadTechniquesRegistry } from './research-helpers-io.js';\n\n// =============================================================================\n// TAG OPERATIONS\n// =============================================================================\n\n/**\n * Calculate tag overlap score between two techniques.\n * Returns Jaccard similarity (intersection / union).\n */\nexport function calculateTagOverlap(tags1: readonly string[], tags2: readonly string[]): number {\n const set1 = new Set(tags1);\n const set2 = new Set(tags2);\n const intersection = [...set1].filter((tag) => set2.has(tag));\n const union = new Set([...set1, ...set2]);\n return union.size === 0 ? 0 : intersection.length / union.size;\n}\n\n/**\n * Find shared tags between two techniques.\n */\nexport function findSharedTags(tags1: readonly string[], tags2: readonly string[]): string[] {\n const set2 = new Set(tags2);\n return tags1.filter((tag) => set2.has(tag));\n}\n\n// =============================================================================\n// RELATIONSHIP DETERMINATION\n// =============================================================================\n\n/**\n * Determine relationship type based on overlap characteristics.\n */\nexport function determineRelationship(\n source: TechniqueEntry,\n target: TechniqueEntry,\n overlapScore: number\n): OverlapMatch['relationship'] {\n // High overlap in same topic = overlapping\n if (source.topic === target.topic && overlapScore > 0.5) {\n return 'overlapping';\n }\n\n // Same topic but lower overlap = complementary\n if (source.topic === target.topic) {\n return 'complementary';\n }\n\n // Different topic with some overlap = enhances\n if (overlapScore > 0.3) {\n return 'enhances';\n }\n\n return 'complementary';\n}\n\n// =============================================================================\n// MAIN OVERLAP FUNCTION\n// =============================================================================\n\n/**\n * Find overlapping techniques.\n */\nexport async function findOverlaps(\n options: ResearchOverlapOptions\n): Promise<ResearchOverlapResult> {\n const result = await loadTechniquesRegistry();\n if (!result.ok) {\n return {\n success: false,\n sourceId: options.techniqueId,\n matches: [],\n suggestedAlignments: [],\n };\n }\n const registry = result.value;\n\n const sourceEntry = registry.techniques[options.techniqueId];\n if (!sourceEntry) {\n return {\n success: false,\n sourceId: options.techniqueId,\n matches: [],\n suggestedAlignments: [],\n };\n }\n\n const matches: OverlapMatch[] = [];\n\n for (const [id, entry] of Object.entries(registry.techniques)) {\n if (id === options.techniqueId) continue;\n\n const overlapScore = calculateTagOverlap(sourceEntry.tags, entry.tags);\n const sharedTopic = sourceEntry.topic === entry.topic;\n\n // Apply threshold\n if (overlapScore >= options.threshold || sharedTopic) {\n matches.push({\n techniqueId: id,\n name: entry.name,\n overlapScore,\n sharedTags: findSharedTags(sourceEntry.tags, entry.tags),\n sharedTopic,\n relationship: determineRelationship(sourceEntry, entry, overlapScore),\n });\n }\n }\n\n // Sort by overlap score descending\n matches.sort((a, b) => b.overlapScore - a.overlapScore);\n\n // Generate suggested alignments\n const suggestedAlignments = matches\n .filter((m) => m.relationship === 'overlapping' || m.relationship === 'enhances')\n .slice(0, 3)\n .map((m) => `${options.techniqueId} -> ${m.techniqueId}: ${m.relationship}`);\n\n return {\n success: true,\n sourceId: options.techniqueId,\n matches,\n suggestedAlignments,\n };\n}\n\n// =============================================================================\n// FORMATTING\n// =============================================================================\n\n/**\n * Format overlap result for display.\n */\nexport function formatOverlapResult(\n result: ResearchOverlapResult,\n format: 'table' | 'json'\n): string {\n if (format === 'json') {\n return JSON.stringify(result, null, 2);\n }\n\n const lines: string[] = [];\n lines.push(`Overlap Analysis: ${result.sourceId}`);\n lines.push('='.repeat(60));\n lines.push('');\n\n if (!result.success) {\n lines.push(`Technique '${result.sourceId}' not found in registry.`);\n return lines.join('\\n');\n }\n\n if (result.matches.length === 0) {\n lines.push('No overlapping techniques found.');\n return lines.join('\\n');\n }\n\n lines.push(`Found ${String(result.matches.length)} related technique(s):`);\n lines.push('');\n\n for (const match of result.matches) {\n const score = (match.overlapScore * 100).toFixed(0);\n lines.push(` ${match.techniqueId}`);\n lines.push(` Name: ${match.name}`);\n lines.push(` Overlap: ${score}% | Relationship: ${match.relationship}`);\n if (match.sharedTags.length > 0) {\n lines.push(` Shared tags: ${match.sharedTags.join(', ')}`);\n }\n lines.push('');\n }\n\n if (result.suggestedAlignments.length > 0) {\n lines.push('Suggested alignments.yaml entries:');\n for (const alignment of result.suggestedAlignments) {\n lines.push(` - ${alignment}`);\n }\n }\n\n return lines.join('\\n');\n}\n","/**\n * Research paper quality scoring and evidence tier assessment.\n *\n * Computes a composite quality score (0-10) from verifiable signals:\n * citation count, venue tier, code availability, recency, and rigor tags.\n *\n * Evidence tiers (high/medium/low) determine how much weight to give\n * techniques extracted from a paper when making implementation decisions.\n *\n * @module research/research-quality\n */\n\nimport type { ResearchPaper } from './research-schemas.js';\n\n/** Top-tier venues (score 3). */\nconst TIER_3_VENUES = new Set([\n 'neurips',\n 'nips',\n 'icml',\n 'iclr',\n 'aaai',\n 'acl',\n 'emnlp',\n 'cvpr',\n 'iccv',\n 'eccv',\n 'sigir',\n 'kdd',\n 'www',\n 'icse',\n 'fse',\n]);\n\n/** Good venues (score 2). */\nconst TIER_2_VENUES = new Set([\n 'naacl',\n 'coling',\n 'eacl',\n 'ijcai',\n 'ecai',\n 'aistats',\n 'uai',\n 'colt',\n 'interspeech',\n 'ase',\n 'issta',\n]);\n\n/**\n * Classify venue into tier (0-3).\n */\nexport function classifyVenue(venue: string | null | undefined): number {\n if (venue === null || venue === undefined || venue.length === 0) return 0;\n const normalized = venue.toLowerCase().replace(/[^a-z]/g, '');\n if (TIER_3_VENUES.has(normalized)) return 3;\n if (TIER_2_VENUES.has(normalized)) return 2;\n // Any non-empty venue that's not arXiv is at least tier 1 (workshop/journal)\n if (!normalized.includes('arxiv')) return 1;\n return 0;\n}\n\n/**\n * Compute recency boost (0-2 points).\n * Papers < 6 months = 2, < 1 year = 1, older = 0.\n */\nexport function recencyBoost(publicationDate: string | undefined): number {\n if (publicationDate === undefined) return 0;\n const now = new Date();\n const pubDate = new Date(publicationDate);\n const monthsAgo = (now.getTime() - pubDate.getTime()) / (30 * 24 * 60 * 60 * 1000);\n if (monthsAgo < 6) return 2;\n if (monthsAgo < 12) return 1;\n return 0;\n}\n\n/**\n * Compute citation score (0-3 points).\n * Logarithmic: 0=no citations, 1=1-9, 2=10-99, 3=100+\n */\nexport function citationScore(count: number | undefined): number {\n if (count === undefined || count === 0) return 0;\n if (count < 10) return 1;\n if (count < 100) return 2;\n return 3;\n}\n\n/** Citation threshold that bypasses the preprint quality cap. */\nconst PREPRINT_CAP_CITATION_BYPASS = 100;\n\n/** Maximum quality score for unreviewed preprints without high citations. */\nconst PREPRINT_QUALITY_CAP = 6;\n\n/**\n * Check if a paper is a preprint-only submission (no peer review).\n * Returns true when source is 'arxiv', venue is empty/null, and venue_tier is 0.\n */\nexport function isPreprintOnly(paper: ResearchPaper): boolean {\n const venueTier = paper.venue_tier ?? classifyVenue(paper.venue);\n const hasNoVenue = paper.venue === null || paper.venue === undefined || paper.venue.length === 0;\n return (paper.source === 'arxiv' || paper.source === 'preprint') && hasNoVenue && venueTier === 0;\n}\n\n/**\n * Compute composite quality score (0-10) for a paper.\n *\n * Breakdown:\n * - Citation score: 0-3 (logarithmic)\n * - Venue tier: 0-3\n * - Has code: 0 or 2\n * - Recency boost: 0-2\n *\n * Preprint cap (Issue #1579): arXiv-only papers without peer review\n * are capped at 6 unless they have ≥100 citations (field-validated).\n *\n * Total max: 10\n */\nexport function computeQualityScore(paper: ResearchPaper): number {\n const citations = citationScore(paper.citation_count);\n const venue = paper.venue_tier ?? classifyVenue(paper.venue);\n const code = paper.has_code === true ? 2 : 0;\n const recency = recencyBoost(paper.publication_date);\n\n let score = Math.min(10, citations + venue + code + recency);\n\n // Preprint cap: unreviewed papers can't exceed 6 without high citations\n const citationCount = paper.citation_count ?? 0;\n if (isPreprintOnly(paper) && citationCount < PREPRINT_CAP_CITATION_BYPASS) {\n score = Math.min(score, PREPRINT_QUALITY_CAP);\n }\n\n return score;\n}\n\n/**\n * Determine evidence tier based on quality score and rigor tags.\n *\n * - high: peer-reviewed + has-code + has-baselines (or quality >= 7)\n * - medium: has-code OR quality >= 4\n * - low: everything else\n */\nexport function computeEvidenceTier(paper: ResearchPaper): 'high' | 'medium' | 'low' {\n const score = paper.quality_score ?? computeQualityScore(paper);\n const tags = new Set(paper.rigor_tags);\n\n if (tags.has('peer-reviewed') && tags.has('has-code') && tags.has('has-baselines')) {\n return 'high';\n }\n if (score >= 7) return 'high';\n if (tags.has('has-code') || score >= 4) return 'medium';\n return 'low';\n}\n","/**\n * Research Registry Paper Operations\n *\n * Functions for adding papers to the research registry with proper YAML formatting.\n * Supports auto-add from arXiv fetch with duplicate detection.\n *\n * @see docs/research/RESEARCH_INDEX.md\n * @see Issue #299 (Auto-add papers to registry from arXiv fetch)\n * @see Issue #237 (Epic #225)\n */\n\nimport type { Result } from '../core/result.js';\nimport { getTimeProvider } from '../core/index.js';\nimport type { ArxivMetadata, PaperEntry, PapersRegistry } from './research-types.js';\nimport { loadPapersRegistry, savePapersRegistry } from './research-helpers-io.js';\nimport { computeQualityScore, computeEvidenceTier } from '../research/research-quality.js';\nimport type { ResearchPaper } from '../research/research-schemas.js';\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * Error codes for registry operations.\n */\nexport type RegistryErrorCode =\n | 'LOAD_ERROR'\n | 'SAVE_ERROR'\n | 'DUPLICATE'\n | 'INVALID_METADATA'\n | 'VALIDATION_ERROR';\n\n/**\n * Structured error for registry operations.\n */\nexport interface RegistryError {\n readonly code: RegistryErrorCode;\n readonly message: string;\n readonly paperId?: string;\n readonly cause?: unknown;\n}\n\n/**\n * Options for adding a paper to the registry.\n */\nexport interface AddPaperOptions {\n /** The arXiv metadata to convert to a registry entry */\n readonly metadata: ArxivMetadata;\n /** Optional topic override (defaults to detecting from metadata) */\n readonly topic?: string;\n /** Whether this is a dry run (no actual changes) */\n readonly dryRun?: boolean;\n /** Project root directory (defaults to cwd) */\n readonly rootDir?: string;\n}\n\n/**\n * Result of adding a paper to the registry.\n */\nexport interface AddPaperResult {\n readonly success: boolean;\n readonly paperId: string;\n readonly entry?: PaperEntry;\n readonly message: string;\n readonly dryRun: boolean;\n}\n\n// =============================================================================\n// HELPER FUNCTIONS\n// =============================================================================\n\n/**\n * Get current date in YYYY-MM-DD format (America/New_York timezone).\n */\nexport function getCurrentDate(): string {\n const now = new Date(getTimeProvider().now());\n return now.toLocaleDateString('en-CA', { timeZone: 'America/New_York' });\n}\n\n/**\n * Extract publication month from arXiv ID.\n * arXiv IDs have format YYMM.NNNNN (e.g., 2501.06322 = January 2025)\n */\nfunction extractPublicationDate(arxivId: string): string {\n const match = /^(\\d{2})(\\d{2})\\./.exec(arxivId);\n const yearStr = match?.[1];\n const monthStr = match?.[2];\n if (yearStr === undefined || monthStr === undefined) {\n return '';\n }\n const year = parseInt(yearStr, 10);\n const month = monthStr;\n // Convert 2-digit year to 4-digit (assume 20XX for years 00-99)\n const fullYear = year < 50 ? 2000 + year : 1900 + year;\n return `${String(fullYear)}-${month}`;\n}\n\n/**\n * Detect topic from arXiv metadata.\n * Uses keywords in title and summary to infer topic.\n */\nfunction detectTopicFromMetadata(metadata: ArxivMetadata): string | undefined {\n const text = `${metadata.title} ${metadata.summary}`.toLowerCase();\n\n // Topic detection based on keywords\n const topicKeywords: Record<string, readonly string[]> = {\n consensus: ['consensus', 'voting', 'agreement', 'byzantine', 'debate'],\n routing: ['routing', 'route', 'cascade', 'model selection', 'cost-quality'],\n memory: ['memory', 'context', 'kv-cache', 'long-term', 'retrieval'],\n 'code-generation': ['code', 'self-improve', 'refine', 'debug', 'skill'],\n orchestration: ['orchestration', 'multi-agent', 'coordination', 'workflow'],\n security: ['safety', 'security', 'adversarial', 'harmful', 'jailbreak'],\n };\n\n for (const [topic, keywords] of Object.entries(topicKeywords)) {\n for (const keyword of keywords) {\n if (text.includes(keyword)) {\n return topic;\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Generate tags from arXiv metadata.\n * Extracts relevant keywords from title and categories.\n */\nfunction generateTagsFromMetadata(metadata: ArxivMetadata): readonly string[] {\n const tags: string[] = [];\n const title = metadata.title.toLowerCase();\n\n // Common tag patterns\n const tagPatterns: Record<string, readonly string[]> = {\n survey: ['survey', 'review', 'overview'],\n benchmark: ['benchmark', 'evaluation', 'dataset'],\n 'multi-agent': ['multi-agent', 'multiagent', 'multiple agents'],\n llm: ['llm', 'large language model', 'language model'],\n 'reinforcement-learning': ['reinforcement learning', 'rl', 'reward'],\n };\n\n for (const [tag, patterns] of Object.entries(tagPatterns)) {\n for (const pattern of patterns) {\n if (title.includes(pattern)) {\n tags.push(tag);\n break;\n }\n }\n }\n\n return tags;\n}\n\n// =============================================================================\n// REGISTRY OPERATIONS\n// =============================================================================\n\n/**\n * Creates a structured registry error.\n */\nfunction createRegistryError(\n code: RegistryErrorCode,\n message: string,\n paperId: string | undefined,\n cause?: unknown\n): RegistryError {\n const error: RegistryError = { code, message };\n if (paperId !== undefined) {\n return { ...error, paperId, cause };\n }\n if (cause !== undefined) {\n return { ...error, cause };\n }\n return error;\n}\n\n/**\n * Convert a `PaperEntry` into the Zod-derived `ResearchPaper` shape expected\n * by the quality helpers (#2943). PaperEntry now mirrors all of ResearchPaper's\n * rigor fields, so the conversion is a straightforward typed mapping — no\n * `as unknown as` required. The readonly array fields are copied to mutable\n * arrays because ResearchPaper's Zod inference yields mutable types.\n */\nexport function paperEntryToResearchPaper(entry: PaperEntry): ResearchPaper {\n return {\n title: entry.title,\n authors: [...entry.authors],\n source: entry.source,\n arxiv_id: entry.arxiv_id,\n url: entry.url,\n publication_date: entry.publication_date,\n venue: entry.venue,\n topics: [...entry.topics],\n tags: [...entry.tags],\n reviewed_date: entry.reviewed_date,\n reviewed_in: entry.reviewed_in,\n summary: entry.summary,\n key_findings: [...entry.key_findings],\n relevance: entry.relevance,\n techniques_extracted: [...entry.techniques_extracted],\n related_issues: [...entry.related_issues],\n implementation_status: entry.implementation_status,\n rigor_tags: entry.rigor_tags ? [...entry.rigor_tags] : [],\n ...(entry.venue_tier !== undefined ? { venue_tier: entry.venue_tier } : {}),\n ...(entry.quality_score !== undefined ? { quality_score: entry.quality_score } : {}),\n ...(entry.evidence_tier !== undefined ? { evidence_tier: entry.evidence_tier } : {}),\n ...(entry.citation_count !== undefined ? { citation_count: entry.citation_count } : {}),\n ...(entry.has_code !== undefined ? { has_code: entry.has_code } : {}),\n ...(entry.code_url !== undefined ? { code_url: entry.code_url } : {}),\n ...(entry.quality_notes !== undefined ? { quality_notes: entry.quality_notes } : {}),\n ...(entry.last_quality_check !== undefined\n ? { last_quality_check: entry.last_quality_check }\n : {}),\n };\n}\n\n/**\n * Generate a PaperEntry from arXiv metadata.\n *\n * @param metadata - The arXiv paper metadata\n * @param topic - Optional topic override\n * @returns A PaperEntry suitable for papers.yaml\n */\nexport function generateRegistryEntry(\n metadata: ArxivMetadata,\n topic?: string\n): Result<PaperEntry, RegistryError> {\n if (metadata.id === '' || metadata.title === '') {\n return {\n ok: false,\n error: createRegistryError(\n 'INVALID_METADATA',\n 'arXiv metadata is missing required fields (id or title)',\n undefined,\n undefined\n ),\n };\n }\n\n const detectedTopic = topic ?? detectTopicFromMetadata(metadata);\n const topics = detectedTopic !== undefined ? [detectedTopic] : [];\n const tags = generateTagsFromMetadata(metadata);\n const publicationDate = extractPublicationDate(metadata.id);\n\n const entry: PaperEntry = {\n title: metadata.title,\n authors: metadata.authors,\n source: 'arxiv',\n arxiv_id: metadata.id,\n url: `https://arxiv.org/abs/${metadata.id}`,\n publication_date: publicationDate,\n venue: null,\n topics,\n tags,\n reviewed_date: getCurrentDate(),\n reviewed_in: '',\n summary: '',\n key_findings: [],\n relevance: 'medium',\n techniques_extracted: [],\n related_issues: [],\n implementation_status: 'not-started',\n };\n\n // Auto-compute quality score from available signals (Issue #1576 Wave 4)\n // At ingestion: venue=null, no citations, no code — but recency IS available.\n // computeQualityScore handles undefined fields gracefully.\n // Preprint cap (isPreprintOnly) applies automatically via computeQualityScore.\n //\n // #2943: PaperEntry now mirrors ResearchPaper's optional rigor fields, so\n // a typed coercion replaces the prior `as unknown as ResearchPaper` cast.\n // The conversion is read-only on `entry`; we make the array fields mutable\n // copies because the Zod-derived ResearchPaper infers mutable arrays.\n const paperForScoring = paperEntryToResearchPaper(entry);\n const qualityScore = computeQualityScore(paperForScoring);\n const evidenceTier = computeEvidenceTier({ ...paperForScoring, quality_score: qualityScore });\n\n const scoredEntry: PaperEntry = {\n ...entry,\n venue_tier: 0,\n quality_score: qualityScore,\n evidence_tier: evidenceTier,\n };\n\n return { ok: true, value: scoredEntry };\n}\n\n/**\n * Check if a paper already exists in the registry.\n *\n * @param arxivId - The arXiv paper ID (e.g., \"2501.06322\")\n * @param registry - The papers registry to check\n * @returns true if paper exists, false otherwise\n */\nexport function paperExistsInRegistry(arxivId: string, registry: PapersRegistry): boolean {\n const paperId = `arxiv-${arxivId}`;\n return paperId in registry.papers;\n}\n\n/**\n * Create a successful add paper result.\n */\nfunction createAddResult(\n paperId: string,\n entry: PaperEntry,\n message: string,\n dryRun: boolean\n): Result<AddPaperResult, RegistryError> {\n return { ok: true, value: { success: true, paperId, entry, message, dryRun } };\n}\n\n/**\n * Persist a paper entry to the registry file.\n */\nasync function persistPaperEntry(\n registry: PapersRegistry,\n paperId: string,\n entry: PaperEntry,\n rootDir: string | undefined\n): Promise<Result<void, RegistryError>> {\n const updated: PapersRegistry = {\n schema_version: registry.schema_version,\n papers: { ...registry.papers, [paperId]: entry },\n };\n const saveResult = await savePapersRegistry(updated, rootDir);\n if (!saveResult.ok) {\n return {\n ok: false,\n error: createRegistryError(\n 'SAVE_ERROR',\n `Failed to save papers registry: ${saveResult.error.message}`,\n paperId,\n saveResult.error\n ),\n };\n }\n return { ok: true, value: undefined };\n}\n\n/**\n * Add a paper entry to the registry.\n *\n * @param options - Options for adding the paper\n * @returns Result with AddPaperResult on success or RegistryError on failure\n */\nexport async function addPaperToRegistry(\n options: AddPaperOptions\n): Promise<Result<AddPaperResult, RegistryError>> {\n const { metadata, topic, dryRun = false, rootDir } = options;\n const paperId = `arxiv-${metadata.id}`;\n\n const entryResult = generateRegistryEntry(metadata, topic);\n if (!entryResult.ok) return entryResult;\n const entry = entryResult.value;\n\n const loadResult = await loadPapersRegistry(rootDir);\n if (!loadResult.ok) {\n return {\n ok: false,\n error: createRegistryError(\n 'LOAD_ERROR',\n `Failed to load papers registry: ${loadResult.error.message}`,\n paperId,\n loadResult.error\n ),\n };\n }\n\n if (paperExistsInRegistry(metadata.id, loadResult.value)) {\n return {\n ok: false,\n error: createRegistryError(\n 'DUPLICATE',\n `Paper ${paperId} already exists in registry`,\n paperId\n ),\n };\n }\n\n if (dryRun) {\n return createAddResult(paperId, entry, `[DRY RUN] Would add paper: ${metadata.title}`, true);\n }\n\n const persistResult = await persistPaperEntry(loadResult.value, paperId, entry, rootDir);\n if (!persistResult.ok) return { ok: false, error: persistResult.error };\n\n return createAddResult(paperId, entry, `Added paper: ${metadata.title}`, false);\n}\n","/**\n * Research Registry arXiv Helpers\n *\n * Functions for fetching and parsing arXiv paper metadata.\n *\n * @see docs/research/RESEARCH_INDEX.md\n * @see Issue #237 (Epic #225)\n * @see Issue #350 (timeout configuration)\n */\n\nimport type { Result } from '../core/result.js';\nimport type { ArxivMetadata, ResearchAddOptions, ResearchAddResult } from './research-types.js';\nimport { loadPapersRegistry } from './research-helpers-io.js';\nimport { addPaperToRegistry } from './research-helpers-registry.js';\nimport { API_TIMEOUTS } from '../config/timeouts.js';\n\n/** Timeout for arXiv API requests in milliseconds. */\nconst ARXIV_API_TIMEOUT_MS = API_TIMEOUTS.arxivMs;\n\n/**\n * Error codes for arXiv API operations.\n */\nexport type ArxivFetchErrorCode = 'TIMEOUT' | 'NETWORK' | 'HTTP_ERROR' | 'PARSE_ERROR';\n\n/**\n * Structured error for arXiv fetch failures.\n */\nexport interface ArxivFetchError {\n readonly code: ArxivFetchErrorCode;\n readonly message: string;\n readonly arxivId: string;\n readonly cause?: unknown;\n}\n\n// =============================================================================\n// ARXIV PARSING\n// =============================================================================\n\n/**\n * Extracts the first &lt;entry&gt; block from arXiv Atom XML to avoid\n * matching feed-level metadata (e.g., feed title \"arXiv Query: ...\").\n */\nfunction extractEntryXml(xml: string): string | null {\n const entryMatch = xml.match(/<entry>([\\s\\S]*?)<\\/entry>/);\n // Pre-#2719 this fell back to returning the full feed XML when no\n // <entry> tag was present. The feed-level <title> for a no-results\n // query is literally \"arXiv Query: search_query=&id_list=X&start=0&\n // max_results=10\" — which then got persisted as the paper's \"title\"\n // and recorded as a belief learning. Return null so the caller surfaces\n // a genuine \"paper not found\" instead of inventing one.\n return entryMatch?.[1] ?? null;\n}\n\n/**\n * Decode the XML entities arXiv encodes in `<title>` / `<summary>` content.\n *\n * Single-pass to avoid the `js/double-escaping` class of bugs CodeQL flagged\n * as alert #217 — chaining `.replace(/&amp;/g, '&')` followed by\n * `.replace(/&lt;/g, '<')` double-decodes input like `&amp;lt;` (the XML\n * encoding of a literal `&lt;`) into `<`. A single regex with a switch\n * keeps each entity atomic.\n */\nconst XML_ENTITIES: Readonly<Record<string, string>> = {\n '&amp;': '&',\n '&lt;': '<',\n '&gt;': '>',\n '&quot;': '\"',\n '&apos;': \"'\",\n};\nfunction decodeXmlEntities(s: string): string {\n return s.replace(/&(?:amp|lt|gt|quot|apos);/g, (m) => XML_ENTITIES[m] ?? m);\n}\n\n/**\n * Parse arXiv XML response into metadata.\n */\nfunction parseArxivXml(arxivId: string, xml: string): ArxivMetadata | null {\n const entryXml = extractEntryXml(xml);\n // No <entry> tag → no paper. Return null so the caller treats this as\n // a fetch miss (#2719) rather than synthesizing data from the feed.\n if (entryXml === null) return null;\n\n const titleMatch = entryXml.match(/<title>([^<]+)<\\/title>/);\n const summaryMatch = entryXml.match(/<summary>([^<]+)<\\/summary>/s);\n const publishedMatch = entryXml.match(/<published>([^<]+)<\\/published>/);\n\n const titleContent = titleMatch?.[1];\n if (titleContent === undefined || titleContent === '') return null;\n\n // Decode XML entities (`&amp;` → `&` etc.) so persisted titles are plain\n // text. Pre-#2719 a title like \"Stats &amp; ML\" kept the literal token.\n return {\n id: arxivId,\n title: decodeXmlEntities(titleContent.trim().replace(/\\s+/g, ' ')),\n authors: [], // Would need more complex parsing\n summary: decodeXmlEntities(summaryMatch?.[1]?.trim().replace(/\\s+/g, ' ') ?? ''),\n published: publishedMatch?.[1] ?? '',\n updated: '',\n categories: [],\n pdfUrl: `https://arxiv.org/pdf/${arxivId}.pdf`,\n };\n}\n\n// =============================================================================\n// ARXIV API\n// =============================================================================\n\n/**\n * Creates a structured arXiv fetch error.\n */\nfunction createArxivError(\n code: ArxivFetchErrorCode,\n arxivId: string,\n message: string,\n cause?: unknown\n): ArxivFetchError {\n return { code, message, arxivId, cause };\n}\n\n/**\n * Determines error code from caught exception.\n */\nfunction getErrorCodeFromException(err: unknown): ArxivFetchErrorCode {\n if (err instanceof Error && err.name === 'TimeoutError') {\n return 'TIMEOUT';\n }\n return 'NETWORK';\n}\n\n/**\n * Fetch paper metadata from arXiv API with timeout and structured error handling.\n *\n * @param arxivId - The arXiv paper ID (e.g., \"2401.12345\")\n * @returns Result containing metadata or structured error\n */\nexport async function fetchArxivMetadataResult(\n arxivId: string\n): Promise<Result<ArxivMetadata, ArxivFetchError>> {\n const url = `https://export.arxiv.org/api/query?id_list=${arxivId}`;\n\n try {\n const response = await fetch(url, {\n signal: AbortSignal.timeout(ARXIV_API_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n return {\n ok: false,\n error: createArxivError(\n 'HTTP_ERROR',\n arxivId,\n `arXiv API returned ${String(response.status)} ${response.statusText}`\n ),\n };\n }\n\n const xml = await response.text();\n const metadata = parseArxivXml(arxivId, xml);\n\n if (metadata === null) {\n return {\n ok: false,\n error: createArxivError('PARSE_ERROR', arxivId, 'Failed to parse arXiv XML response'),\n };\n }\n\n return { ok: true, value: metadata };\n } catch (err) {\n const code = getErrorCodeFromException(err);\n const message =\n code === 'TIMEOUT'\n ? `arXiv API request timed out after ${String(ARXIV_API_TIMEOUT_MS / 1000)} seconds`\n : 'Network error while fetching from arXiv API';\n return { ok: false, error: createArxivError(code, arxivId, message, err) };\n }\n}\n\n// =============================================================================\n// REGISTRY OPERATIONS\n// =============================================================================\n\n/**\n * Check if paper already exists in registry.\n * Returns false if registry cannot be loaded.\n */\nexport async function paperExists(arxivId: string): Promise<boolean> {\n const result = await loadPapersRegistry();\n if (!result.ok) {\n return false;\n }\n const paperId = `arxiv-${arxivId}`;\n return paperId in result.value.papers;\n}\n\n/**\n * Add a paper to the registry.\n *\n * Fetches paper metadata from arXiv API, generates a registry entry,\n * and persists it to docs/research/registry/papers.yaml.\n *\n * @param options - Options for adding the paper\n * @returns Result indicating success or failure with details\n *\n * @see Issue #299 - Auto-add papers to registry from arXiv fetch\n */\nexport async function addResearchPaper(options: ResearchAddOptions): Promise<ResearchAddResult> {\n const paperId = `arxiv-${options.arxivId}`;\n\n // Fetch metadata using Result pattern\n const metadataResult = await fetchArxivMetadataResult(options.arxivId);\n if (!metadataResult.ok) {\n return {\n success: false,\n paperId,\n title: '',\n message: `Could not fetch metadata for arXiv ID ${options.arxivId}: ${metadataResult.error.message}`,\n dryRun: options.dryRun,\n };\n }\n const metadata = metadataResult.value;\n\n // Add to registry using the registry helper\n const addOptions: {\n metadata: ArxivMetadata;\n topic?: string;\n dryRun?: boolean;\n } = {\n metadata,\n dryRun: options.dryRun,\n };\n if (options.topic !== undefined) {\n addOptions.topic = options.topic;\n }\n const addResult = await addPaperToRegistry(addOptions);\n\n if (!addResult.ok) {\n return {\n success: false,\n paperId,\n title: metadata.title,\n message: addResult.error.message,\n dryRun: options.dryRun,\n };\n }\n\n return {\n success: addResult.value.success,\n paperId: addResult.value.paperId,\n title: metadata.title,\n message: addResult.value.message,\n dryRun: addResult.value.dryRun,\n };\n}\n","/**\n * Research Source Discovery Providers\n *\n * Functions for discovering research from external sources:\n * GitHub, Google AI, Meta FAIR, Microsoft Research, DeepMind.\n *\n * @module cli/research-helpers-sources\n * (Source: Research System Enhancement - Phase 3)\n * (Source: Issue #1136 — SCM token for GitHub search auth)\n */\n\nimport { z } from 'zod';\nimport type { Result } from '../core/result.js';\nimport { resolveToken } from '../scm/token-resolver.js';\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/** Timeout for external API requests. */\nconst SOURCE_API_TIMEOUT_MS = 30_000;\n\n/** Error codes for source discovery. */\nexport type DiscoverErrorCode = 'TIMEOUT' | 'NETWORK' | 'HTTP_ERROR' | 'PARSE_ERROR' | 'RATE_LIMIT';\n\n/** Structured error for discovery failures. */\nexport interface DiscoverError {\n readonly code: DiscoverErrorCode;\n readonly message: string;\n readonly source: string;\n readonly cause?: unknown;\n}\n\n/** A discovered source item. */\nexport interface DiscoveredSource {\n readonly source: string;\n readonly title: string;\n readonly url: string;\n readonly description: string;\n readonly relevance: 'high' | 'medium' | 'low';\n readonly discoveredAt: string;\n}\n\n// =============================================================================\n// ZOD SCHEMAS FOR EXTERNAL API RESPONSES\n// =============================================================================\n\n/** Zod schema for GitHub search API response. */\nconst GitHubRepoSchema = z.object({\n full_name: z.string().optional(),\n html_url: z.string().optional(),\n description: z.string().nullable().optional(),\n stargazers_count: z.number().optional(),\n});\n\nconst GitHubSearchResponseSchema = z.object({\n items: z.array(GitHubRepoSchema).optional(),\n});\n\n// =============================================================================\n// HELPERS\n// =============================================================================\n/** Creates a discover error. */\nfunction createError(\n code: DiscoverErrorCode,\n source: string,\n message: string,\n cause?: unknown\n): DiscoverError {\n return { code, message, source, cause };\n}\n\n/** Gets today's date in YYYY-MM-DD format (ET timezone). */\nfunction getToday(): string {\n return new Date().toISOString().split('T')[0] ?? '';\n}\n\n// =============================================================================\n// SHARED FETCH HELPER\n// =============================================================================\n/** Options for fetchSource helper. */\ninterface FetchSourceOptions {\n readonly url: string;\n readonly source: string;\n readonly headers?: Record<string, string>;\n readonly timeoutMs?: number;\n}\n\n/** Builds a typed error from a non-ok HTTP response.\n *\n * Surfaces rate-limiting separately so callers distinguish \"your key is\n * missing / quota exhausted\" from \"the API is broken\" (#2234). GitHub uses\n * GITHUB_TOKEN (not the *_API_KEY convention) — caught by the v5 pr_review\n * experiment when devex flagged the message pointing at a non-existent env\n * var. */\nfunction buildHttpErrorResult(status: number, source: string): DiscoverError {\n const isRateLimit = status === 429;\n const envHint = source === 'github' ? 'GITHUB_TOKEN' : `${source.toUpperCase()}_API_KEY`;\n const message = isRateLimit\n ? `${source} rate-limited (HTTP 429) — set ${envHint} or retry later`\n : `API returned ${String(status)}`;\n return createError(isRateLimit ? 'RATE_LIMIT' : 'HTTP_ERROR', source, message);\n}\n\n/**\n * Shared fetch-and-error-handle helper for source providers.\n * Centralizes timeout handling, HTTP error detection, and error classification.\n */\nexport async function fetchSource(\n options: FetchSourceOptions\n): Promise<Result<Response, DiscoverError>> {\n const { url, source, headers, timeoutMs = SOURCE_API_TIMEOUT_MS } = options;\n try {\n const fetchInit: RequestInit = { signal: AbortSignal.timeout(timeoutMs) };\n if (headers !== undefined) fetchInit.headers = headers;\n const response = await fetch(url, fetchInit);\n if (!response.ok) {\n return { ok: false, error: buildHttpErrorResult(response.status, source) };\n }\n return { ok: true, value: response };\n } catch (error) {\n const isTimeout = error instanceof Error && error.name === 'TimeoutError';\n return {\n ok: false,\n error: createError(\n isTimeout ? 'TIMEOUT' : 'NETWORK',\n source,\n isTimeout ? `${source} API timed out` : `Network error querying ${source}`,\n error\n ),\n };\n }\n}\n\n// =============================================================================\n// GITHUB DISCOVERY\n// =============================================================================\n\n/** Converts validated GitHub API response items to DiscoveredSource[]. */\nfunction parseGitHubRepos(data: z.infer<typeof GitHubSearchResponseSchema>): DiscoveredSource[] {\n return (data.items ?? []).map((repo) => ({\n source: 'github',\n title: repo.full_name ?? '',\n url: repo.html_url ?? '',\n description: repo.description ?? '',\n relevance:\n (repo.stargazers_count ?? 0) > 1000\n ? 'high'\n : (repo.stargazers_count ?? 0) > 100\n ? 'medium'\n : 'low',\n discoveredAt: getToday(),\n }));\n}\n\n/**\n * Discover relevant GitHub repositories for a topic.\n *\n * @param topic - Search topic\n * @param maxResults - Maximum results (default 10)\n * @returns Result containing discovered repositories\n */\nexport async function discoverGitHubRepos(\n topic: string,\n maxResults = 10\n): Promise<Result<DiscoveredSource[], DiscoverError>> {\n // GitHub's search API parses bare `OR` as a top-level operator, which\n // splits the query into two unrelated clauses and zeroes out matches\n // when the topic has multiple distinguishing tokens (#2234). Parenthesizing\n // qualifiers does NOT work either. Best fix: drop the language filter and\n // let the topic terms drive matching; downstream relevance scoring handles\n // quality. Confirmed empirically against api.github.com.\n const query = encodeURIComponent(topic);\n const url = `https://api.github.com/search/repositories?q=${query}&sort=stars&order=desc&per_page=${String(maxResults)}`;\n\n // Use SCM token-resolver for optional auth (Issue #1136)\n // Authenticated: 5000 req/hr; unauthenticated: 60 req/hr\n const headers: Record<string, string> = {\n Accept: 'application/vnd.github.v3+json',\n 'User-Agent': 'nexus-agents',\n };\n const tokenResult = await resolveToken({ platform: 'github' });\n if (tokenResult.ok) {\n headers['Authorization'] = `Bearer ${tokenResult.value.value}`;\n }\n\n const fetchResult = await fetchSource({ url, source: 'github', headers });\n if (!fetchResult.ok) return fetchResult;\n\n let raw: unknown;\n try {\n raw = await fetchResult.value.json();\n } catch {\n return {\n ok: false,\n error: createError('PARSE_ERROR', 'github', 'Response is not valid JSON'),\n };\n }\n const parsed = GitHubSearchResponseSchema.safeParse(raw);\n if (!parsed.success) {\n return {\n ok: false,\n error: createError('PARSE_ERROR', 'github', 'GitHub API response schema mismatch'),\n };\n }\n return { ok: true, value: parseGitHubRepos(parsed.data) };\n}\n\n// =============================================================================\n// ARXIV-BASED DISCOVERY (shared helper)\n// =============================================================================\n\n/** Options for arXiv-based discovery. */\ninterface ArxivQueryOptions {\n readonly topic: string;\n readonly authorFilter: string;\n readonly maxResults: number;\n readonly sinceDate?: string | undefined;\n}\n\n/**\n * Builds an arXiv API search URL with targeted field queries.\n * Uses ti: (title) and abs: (abstract) instead of all: for better relevance.\n * Optionally adds a submittedDate range filter when sinceDate is provided.\n *\n * Exported for testability.\n */\nexport function buildArxivUrl(opts: ArxivQueryOptions): string {\n // OR-join keywords for multi-word queries and let arXiv rank by relevance;\n // the caller's coverage-based relevance filter (#3542) refines the set.\n // AND-joining every term required all of them to co-occur in one paper, which\n // returned 0 results for normal multi-word topics (#3543); and pairing OR with\n // a date sort would fetch recent-but-off-topic papers, so we sort by relevance.\n const words = opts.topic.split(/\\s+/).filter((w) => w.length > 0);\n const topicQuery =\n words.length <= 1\n ? `(ti:${opts.topic} OR abs:${opts.topic})`\n : `(${words.map((w) => `ti:${w} OR abs:${w}`).join(' OR ')})`;\n let fullQuery = opts.authorFilter !== '' ? `${topicQuery} AND ${opts.authorFilter}` : topicQuery;\n\n // Add date range filter if sinceDate provided (format: YYYYMMDD)\n if (opts.sinceDate !== undefined && /^\\d{4}-\\d{2}-\\d{2}$/.test(opts.sinceDate)) {\n const dateNum = opts.sinceDate.replace(/-/g, '');\n const today = new Date().toISOString().split('T')[0]?.replace(/-/g, '') ?? '';\n fullQuery = `${fullQuery} AND submittedDate:[${dateNum} TO ${today}]`;\n }\n\n const encoded = encodeURIComponent(fullQuery);\n return `https://export.arxiv.org/api/query?search_query=${encoded}&start=0&max_results=${String(opts.maxResults)}&sortBy=relevance&sortOrder=descending`;\n}\n\n/**\n * Shared arXiv-based discovery provider. Used by Google AI, Meta FAIR,\n * Microsoft Research, and DeepMind discovery functions.\n */\nasync function discoverFromArxiv(\n topic: string,\n authorFilter: string,\n source: string,\n maxResults: number,\n sinceDate?: string\n): Promise<Result<DiscoveredSource[], DiscoverError>> {\n const url = buildArxivUrl({ topic, authorFilter, maxResults, sinceDate });\n const fetchResult = await fetchSource({ url, source });\n if (!fetchResult.ok) return fetchResult;\n\n const xml = await fetchResult.value.text();\n const items = parseArxivEntries(xml, source, topic);\n return { ok: true, value: items };\n}\n\n// =============================================================================\n// ARXIV DISCOVERY (direct, no author filter)\n// =============================================================================\n\n/**\n * Discover papers from arXiv without author affiliation filters.\n * Uses targeted ti:/abs: field queries for better relevance.\n *\n * @param topic - Search topic\n * @param maxResults - Maximum results (default 10)\n * @param sinceDate - Optional date filter (YYYY-MM-DD)\n * @returns Result containing discovered items\n */\nexport async function discoverArxiv(\n topic: string,\n maxResults = 10,\n sinceDate?: string\n): Promise<Result<DiscoveredSource[], DiscoverError>> {\n return discoverFromArxiv(topic, '', 'arxiv', maxResults, sinceDate);\n}\n\n// =============================================================================\n// GOOGLE AI DISCOVERY\n// =============================================================================\n\n/**\n * Discover Google AI research publications via arXiv with author affiliation filter.\n *\n * @param topic - Search topic\n * @param maxResults - Maximum results (default 10)\n * @returns Result containing discovered items\n */\nexport async function discoverGoogleAI(\n topic: string,\n maxResults = 10,\n sinceDate?: string\n): Promise<Result<DiscoveredSource[], DiscoverError>> {\n // arXiv au: field only searches author names, not affiliations.\n // Drop author filter — use topic-only search (same quality as direct arxiv).\n return discoverFromArxiv(topic, '', 'google_ai', maxResults, sinceDate);\n}\n\n// =============================================================================\n// META FAIR DISCOVERY\n// =============================================================================\n\n/**\n * Discover Meta FAIR research publications.\n *\n * @param topic - Search topic\n * @param maxResults - Maximum results (default 10)\n * @returns Result containing discovered items\n */\nexport async function discoverMetaFAIR(\n topic: string,\n maxResults = 10,\n sinceDate?: string\n): Promise<Result<DiscoveredSource[], DiscoverError>> {\n // arXiv au: field only searches author names, not affiliations.\n // Drop author filter — use topic-only search (same quality as direct arxiv).\n return discoverFromArxiv(topic, '', 'meta_fair', maxResults, sinceDate);\n}\n\n// =============================================================================\n// MICROSOFT RESEARCH DISCOVERY\n// =============================================================================\n\n/**\n * Discover Microsoft Research publications.\n *\n * @param topic - Search topic\n * @param maxResults - Maximum results (default 10)\n * @returns Result containing discovered items\n */\nexport async function discoverMicrosoftResearch(\n topic: string,\n maxResults = 10,\n sinceDate?: string\n): Promise<Result<DiscoveredSource[], DiscoverError>> {\n // arXiv au: field only searches author names, not affiliations.\n // Drop author filter — use topic-only search (same quality as direct arxiv).\n return discoverFromArxiv(topic, '', 'microsoft', maxResults, sinceDate);\n}\n\n// =============================================================================\n// DEEPMIND DISCOVERY\n// =============================================================================\n\n/**\n * Discover DeepMind research publications.\n *\n * @param topic - Search topic\n * @param maxResults - Maximum results (default 10)\n * @returns Result containing discovered items\n */\nexport async function discoverDeepMind(\n topic: string,\n maxResults = 10,\n sinceDate?: string\n): Promise<Result<DiscoveredSource[], DiscoverError>> {\n // arXiv au: field only searches author names, not affiliations.\n // Drop author filter — use topic-only search (same quality as direct arxiv).\n return discoverFromArxiv(topic, '', 'deepmind', maxResults, sinceDate);\n}\n\n// =============================================================================\n// SHARED PARSING\n// =============================================================================\n\n/** Extract a tag value from XML. */\nfunction extractTag(entry: string, tag: string): string {\n const escaped = tag.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regex = new RegExp(`<${escaped}>(.*?)</${escaped}>`, 's');\n return regex.exec(entry)?.[1]?.trim().replace(/\\s+/g, ' ') ?? '';\n}\n\n/** Truncate text to max length. */\nfunction truncate(text: string, maxLen = 200): string {\n return text.length > maxLen ? text.slice(0, maxLen - 3) + '...' : text;\n}\n\n/** Score relevance based on topic word match ratio in title. */\nexport function scoreRelevance(title: string, topic: string): 'high' | 'medium' | 'low' {\n const titleLower = title.toLowerCase();\n const topicWords = topic\n .toLowerCase()\n .split(/\\s+/)\n .filter((w) => w.length > 2);\n if (topicWords.length === 0) return 'medium';\n const matched = topicWords.filter((w) => titleLower.includes(w)).length;\n const ratio = matched / topicWords.length;\n if (ratio >= 0.6) return 'high';\n if (ratio >= 0.3) return 'medium';\n return 'low';\n}\n\n/** Parse arXiv XML entries into DiscoveredSource items. */\nfunction parseArxivEntries(xml: string, source: string, topic = ''): DiscoveredSource[] {\n const items: DiscoveredSource[] = [];\n const entryRegex = /<entry>([\\s\\S]*?)<\\/entry>/g;\n let match: RegExpExecArray | null;\n\n while ((match = entryRegex.exec(xml)) !== null) {\n const entry = match[1];\n if (entry === undefined) continue;\n const title = extractTag(entry, 'title');\n if (title === '') continue;\n const id = extractTag(entry, 'id');\n const arxivId = id.match(/(\\d{4}\\.\\d{4,5})/)?.[1] ?? '';\n items.push({\n source,\n title,\n url: arxivId !== '' ? `https://arxiv.org/abs/${arxivId}` : id,\n description: truncate(extractTag(entry, 'summary')),\n relevance: topic !== '' ? scoreRelevance(title, topic) : 'medium',\n discoveredAt: getToday(),\n });\n }\n return items;\n}\n","/**\n * Research Sources Registry I/O\n *\n * Functions for loading, saving, and querying the sources.yaml registry.\n *\n * @module cli/research-helpers-sources-io\n * (Source: Research System Enhancement - Phase 3)\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport type { Result } from '../core/result.js';\nimport { REGISTRY_PATH, getProjectRoot } from './research-helpers-io.js';\nimport { resolveInsideRoot } from '../security/safe-path.js';\nimport { getErrorMessage } from '../core/index.js';\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/** Sources registry file name. */\nconst SOURCES_FILE = 'sources.yaml';\n\n/** Source entry in sources.yaml. Aligned with ResearchSource schema. */\nexport interface SourceEntry {\n readonly name: string;\n readonly type:\n | 'product_docs'\n | 'specification'\n | 'research_blog'\n | 'code_analysis'\n | 'open_source_repo';\n readonly url: string;\n readonly vendor?: string;\n readonly topics?: readonly string[];\n readonly tags?: readonly string[];\n readonly reviewed_date?: string;\n readonly reviewed_in?: string | null;\n readonly key_info?: readonly string[];\n readonly quality_signals?: {\n readonly stars_at_review?: number;\n readonly language?: string;\n readonly has_tests?: boolean;\n readonly has_docs?: boolean;\n readonly has_paper?: boolean;\n readonly arxiv_id?: string;\n };\n readonly techniques_extracted?: readonly string[];\n readonly verdict?: 'adopted' | 'partially_adopted' | 'rejected' | 'monitoring' | 'planned';\n readonly verdict_notes?: string;\n readonly quality_score?: number;\n readonly evidence_tier?: 'high' | 'medium' | 'low';\n}\n\n/** Sources registry structure. */\nexport interface SourcesRegistry {\n readonly schema_version: string;\n readonly sources: Record<string, SourceEntry>;\n}\n\n/** Error for sources I/O operations. */\nexport interface SourcesIOError {\n readonly code: 'NOT_FOUND' | 'PARSE_ERROR' | 'WRITE_ERROR' | 'PATH_TRAVERSAL';\n readonly message: string;\n}\n\n// =============================================================================\n// VALIDATION\n// =============================================================================\n\n/** Validates a file path is within allowed root. */\nfunction validatePath(\n constructedPath: string,\n allowedRoot: string\n): Result<string, SourcesIOError> {\n const resolved = resolveInsideRoot(constructedPath, allowedRoot);\n if (resolved === null) {\n const root = path.resolve(allowedRoot);\n return {\n ok: false,\n error: {\n code: 'PATH_TRAVERSAL',\n message: `Path ${path.resolve(constructedPath)} is outside ${root}`,\n },\n };\n }\n return { ok: true, value: resolved };\n}\n\n// =============================================================================\n// LOAD / SAVE\n// =============================================================================\n\n/**\n * Load the sources registry from disk.\n *\n * @param rootDir - Optional root directory override\n * @returns Result containing the sources registry\n */\nexport async function loadSourcesRegistry(\n rootDir?: string\n): Promise<Result<SourcesRegistry, SourcesIOError>> {\n const root = rootDir ?? getProjectRoot();\n const filePath = path.join(root, REGISTRY_PATH, SOURCES_FILE);\n const pathResult = validatePath(filePath, root);\n if (!pathResult.ok) return pathResult;\n\n try {\n const content = await fs.readFile(pathResult.value, 'utf-8');\n const parsed = parseYaml(content) as SourcesRegistry;\n return { ok: true, value: parsed };\n } catch (error: unknown) {\n const code =\n error instanceof Error && 'code' in error ? (error as { code?: string }).code : undefined;\n if (code === 'ENOENT') {\n // Return empty registry if file doesn't exist\n return {\n ok: true,\n value: { schema_version: '1.0', sources: {} },\n };\n }\n return {\n ok: false,\n error: {\n code: 'PARSE_ERROR',\n message: `Failed to load sources: ${getErrorMessage(error)}`,\n },\n };\n }\n}\n\n/**\n * Save the sources registry to disk.\n *\n * @param registry - Sources registry to save\n * @param rootDir - Optional root directory override\n * @returns Result indicating success or failure\n */\nexport async function saveSourcesRegistry(\n registry: SourcesRegistry,\n rootDir?: string\n): Promise<Result<void, SourcesIOError>> {\n const root = rootDir ?? getProjectRoot();\n const filePath = path.join(root, REGISTRY_PATH, SOURCES_FILE);\n const pathResult = validatePath(filePath, root);\n if (!pathResult.ok) return pathResult;\n\n try {\n const yaml = stringifyYaml(registry, { indent: 2 });\n await fs.writeFile(pathResult.value, yaml, 'utf-8');\n return { ok: true, value: undefined };\n } catch (error) {\n return {\n ok: false,\n error: {\n code: 'WRITE_ERROR',\n message: `Failed to save sources: ${getErrorMessage(error)}`,\n },\n };\n }\n}\n\n/**\n * Check if a source already exists in the registry.\n *\n * @param url - Source URL to check\n * @param rootDir - Optional root directory override\n * @returns true if source exists\n */\nexport async function sourceExistsInRegistry(url: string, rootDir?: string): Promise<boolean> {\n const result = await loadSourcesRegistry(rootDir);\n if (!result.ok) return false;\n\n return Object.values(result.value.sources).some((s) => s.url === url);\n}\n\n/**\n * Add a source to the registry.\n *\n * @param id - Source identifier\n * @param entry - Source entry to add\n * @param rootDir - Optional root directory override\n * @returns Result indicating success or failure\n */\nexport async function addSourceToRegistry(\n id: string,\n entry: SourceEntry,\n rootDir?: string\n): Promise<Result<void, SourcesIOError>> {\n const loadResult = await loadSourcesRegistry(rootDir);\n if (!loadResult.ok) return loadResult;\n\n const registry = loadResult.value;\n const updatedSources = { ...registry.sources, [id]: entry };\n const updatedRegistry: SourcesRegistry = {\n ...registry,\n sources: updatedSources,\n };\n\n return saveSourcesRegistry(updatedRegistry, rootDir);\n}\n","/**\n * Academic Source Discovery Providers\n *\n * Semantic Scholar, Papers with Code, and OpenAlex discovery providers.\n * Separate from research-helpers-sources.ts (anti-sprawl exception: new capability).\n *\n * @module cli/research-helpers-sources-academic\n * (Source: Research System Enhancement - Phase 2A/2B)\n * (OpenAlex: Issue #750)\n */\n\nimport { z } from 'zod';\nimport type { Result } from '../core/result.js';\nimport type { DiscoverError, DiscoveredSource } from './research-helpers-sources.js';\nimport { fetchSource } from './research-helpers-sources.js';\n\n// =============================================================================\n// HELPERS\n// =============================================================================\n\n/** Gets today's date in YYYY-MM-DD format. */\nfunction getToday(): string {\n return new Date().toISOString().split('T')[0] ?? '';\n}\n\n/** Truncate text to max length. */\nfunction truncate(text: string, maxLen = 200): string {\n return text.length > maxLen ? text.slice(0, maxLen - 3) + '...' : text;\n}\n\n// =============================================================================\n// ZOD SCHEMAS FOR EXTERNAL API RESPONSES\n// =============================================================================\n\n/** Zod schema for Semantic Scholar paper. */\nconst SemanticScholarPaperSchema = z.object({\n paperId: z.string().optional(),\n title: z.string().optional(),\n url: z.string().optional(),\n abstract: z.string().nullable().optional(),\n citationCount: z.number().optional(),\n year: z.number().optional(),\n isOpenAccess: z.boolean().optional(),\n externalIds: z\n .object({\n ArXiv: z.string().optional(),\n DOI: z.string().optional(),\n })\n .optional(),\n});\n\nconst SemanticScholarResponseSchema = z.object({\n data: z.array(SemanticScholarPaperSchema).optional(),\n});\n\n/** Zod schema for Papers with Code paper. */\nconst PapersWithCodePaperSchema = z.object({\n id: z.string().optional(),\n title: z.string().optional(),\n url_abs: z.string().optional(),\n url_pdf: z.string().optional(),\n abstract: z.string().nullable().optional(),\n proceeding: z.string().nullable().optional(),\n repository_count: z.number().optional(),\n});\n\nconst PapersWithCodeResponseSchema = z.object({\n results: z.array(PapersWithCodePaperSchema).optional(),\n});\n\n// =============================================================================\n// SEMANTIC SCHOLAR DISCOVERY\n// =============================================================================\n\n/** Determine relevance from citation count. */\nfunction citationRelevance(count: number): 'high' | 'medium' | 'low' {\n if (count > 100) return 'high';\n if (count > 20) return 'medium';\n return 'low';\n}\n\n/** Map validated Semantic Scholar paper to DiscoveredSource. */\nfunction mapSemanticScholarPaper(\n paper: z.infer<typeof SemanticScholarPaperSchema>\n): DiscoveredSource {\n const arxivId = paper.externalIds?.ArXiv;\n const paperUrl =\n arxivId !== undefined\n ? `https://arxiv.org/abs/${arxivId}`\n : (paper.url ?? `https://api.semanticscholar.org/paper/${paper.paperId ?? ''}`);\n\n return {\n source: 'semantic_scholar',\n title: paper.title ?? '',\n url: paperUrl,\n description: truncate(paper.abstract ?? ''),\n relevance: citationRelevance(paper.citationCount ?? 0),\n discoveredAt: getToday(),\n };\n}\n\n/**\n * Discover research papers from Semantic Scholar.\n *\n * @param topic - Search topic\n * @param maxResults - Maximum results (default 10)\n * @returns Result containing discovered papers\n */\nexport async function discoverSemanticScholar(\n topic: string,\n maxResults = 10\n): Promise<Result<DiscoveredSource[], DiscoverError>> {\n const query = encodeURIComponent(topic);\n const fields = 'title,url,abstract,citationCount,year,isOpenAccess,externalIds';\n // Note: sort parameter only works on /paper/search/bulk, not /paper/search\n const url = `https://api.semanticscholar.org/graph/v1/paper/search?query=${query}&limit=${String(maxResults)}&fields=${fields}`;\n\n // Unauthenticated requests are aggressively rate-limited (HTTP 429) by\n // semantic_scholar, which surfaced as a 100% failure rate in #2234. Honor\n // SEMANTIC_SCHOLAR_API_KEY when set so users can opt into the higher quota.\n const headers: Record<string, string> = {\n 'User-Agent': 'nexus-agents',\n Accept: 'application/json',\n };\n const apiKey = process.env['SEMANTIC_SCHOLAR_API_KEY'];\n if (apiKey !== undefined && apiKey !== '') {\n headers['x-api-key'] = apiKey;\n }\n\n const fetchResult = await fetchSource({\n url,\n source: 'semantic_scholar',\n headers,\n });\n if (!fetchResult.ok) return fetchResult;\n\n let raw: unknown;\n try {\n raw = await fetchResult.value.json();\n } catch {\n return {\n ok: false,\n error: {\n code: 'PARSE_ERROR',\n source: 'semantic_scholar',\n message: 'Response is not valid JSON',\n },\n };\n }\n const parsed = SemanticScholarResponseSchema.safeParse(raw);\n if (!parsed.success) {\n return {\n ok: false,\n error: {\n code: 'PARSE_ERROR',\n source: 'semantic_scholar',\n message: 'Response schema mismatch',\n },\n };\n }\n\n const items = (parsed.data.data ?? [])\n .filter((p) => p.title !== undefined && p.title !== '')\n .map(mapSemanticScholarPaper);\n\n return { ok: true, value: items };\n}\n\n// =============================================================================\n// PAPERS WITH CODE DISCOVERY\n// =============================================================================\n\n/** Map validated PwC paper to DiscoveredSource. */\nfunction mapPwcPaper(paper: z.infer<typeof PapersWithCodePaperSchema>): DiscoveredSource {\n const hasCode = (paper.repository_count ?? 0) > 0;\n return {\n source: 'papers_with_code',\n title: paper.title ?? '',\n url: paper.url_abs ?? '',\n description: truncate(paper.abstract ?? ''),\n relevance: hasCode ? 'high' : 'medium',\n discoveredAt: getToday(),\n };\n}\n\n/** Parse error for a source. */\nfunction pwcParseError(message: string): { ok: false; error: DiscoverError } {\n return { ok: false, error: { code: 'PARSE_ERROR', source: 'papers_with_code', message } };\n}\n\n/** Check if a Response has a non-JSON content type (e.g., HTML from redirect). */\nfunction isNonJsonResponse(response: Response): boolean {\n const contentType = response.headers.get('content-type') ?? '';\n return contentType !== '' && !contentType.includes('application/json');\n}\n\n/**\n * Discover research papers from Papers with Code.\n *\n * NOTE: As of 2026-02, the PwC API redirects to HuggingFace and returns HTML\n * instead of JSON. This function handles that gracefully by detecting non-JSON\n * responses and returning an empty result set rather than a failure.\n */\nexport async function discoverPapersWithCode(\n topic: string,\n maxResults = 10\n): Promise<Result<DiscoveredSource[], DiscoverError>> {\n const query = encodeURIComponent(topic);\n const url = `https://paperswithcode.com/api/v1/papers/?q=${query}&items_per_page=${String(maxResults)}`;\n\n const fetchResult = await fetchSource({\n url,\n source: 'papers_with_code',\n headers: { 'User-Agent': 'nexus-agents', Accept: 'application/json' },\n });\n if (!fetchResult.ok) return fetchResult;\n\n // PwC API may redirect to HuggingFace and return HTML instead of JSON.\n if (isNonJsonResponse(fetchResult.value)) return { ok: true, value: [] };\n\n let raw: unknown;\n try {\n raw = await fetchResult.value.json();\n } catch {\n return pwcParseError('Response is not valid JSON (possible HTML error page)');\n }\n const parsed = PapersWithCodeResponseSchema.safeParse(raw);\n if (!parsed.success) return pwcParseError('Response schema mismatch');\n\n const items = (parsed.data.results ?? [])\n .filter((p) => p.title !== undefined && p.title !== '')\n .map(mapPwcPaper);\n\n return { ok: true, value: items };\n}\n\n// =============================================================================\n// OPENALEX DISCOVERY (Issue #750)\n// =============================================================================\n\n/** Zod schema for OpenAlex work (paper). */\nconst OpenAlexWorkSchema = z.object({\n id: z.string().optional(),\n title: z.string().optional(),\n doi: z.string().nullable().optional(),\n publication_date: z.string().nullable().optional(),\n cited_by_count: z.number().optional(),\n is_oa: z.boolean().optional(),\n abstract_inverted_index: z.record(z.string(), z.array(z.number())).nullable().optional(),\n primary_location: z\n .object({\n landing_page_url: z.string().nullable().optional(),\n })\n .nullable()\n .optional(),\n ids: z\n .object({\n openalex: z.string().optional(),\n doi: z.string().optional(),\n })\n .optional(),\n});\n\nconst OpenAlexResponseSchema = z.object({\n results: z.array(OpenAlexWorkSchema).optional(),\n});\n\n/**\n * Reconstruct abstract from OpenAlex inverted index format.\n * OpenAlex stores abstracts as {word: [positions]} for compression.\n */\nfunction reconstructAbstract(invertedIndex: Record<string, number[]> | null | undefined): string {\n if (!invertedIndex) return '';\n const words: Array<[string, number]> = [];\n for (const [word, positions] of Object.entries(invertedIndex)) {\n for (const pos of positions) {\n words.push([word, pos]);\n }\n }\n words.sort((a, b) => a[1] - b[1]);\n return words.map(([w]) => w).join(' ');\n}\n\n/** Map validated OpenAlex work to DiscoveredSource. */\nfunction mapOpenAlexWork(work: z.infer<typeof OpenAlexWorkSchema>): DiscoveredSource {\n const url = work.primary_location?.landing_page_url ?? work.ids?.doi ?? work.id ?? '';\n\n return {\n source: 'openalex',\n title: work.title ?? '',\n url,\n description: truncate(reconstructAbstract(work.abstract_inverted_index)),\n relevance: citationRelevance(work.cited_by_count ?? 0),\n discoveredAt: getToday(),\n };\n}\n\n/** Parse error for OpenAlex. */\nfunction openAlexParseError(message: string): { ok: false; error: DiscoverError } {\n return { ok: false, error: { code: 'PARSE_ERROR', source: 'openalex', message } };\n}\n\n/**\n * Discover research papers from OpenAlex.\n *\n * OpenAlex is a free, open catalog of scholarly works with 250M+ papers.\n * Uses polite API with email parameter for higher rate limits.\n *\n * @param topic - Search topic\n * @param maxResults - Maximum results (default 10)\n * @param apiKey - Optional API key for authenticated access\n * @returns Result containing discovered papers\n */\nexport async function discoverOpenAlex(\n topic: string,\n maxResults = 10,\n apiKey?: string\n): Promise<Result<DiscoveredSource[], DiscoverError>> {\n const query = encodeURIComponent(topic);\n // Use polite API with mailto for better rate limits\n const mailto = 'nexus-agents@example.com';\n const url = `https://api.openalex.org/works?search=${query}&per_page=${String(maxResults)}&mailto=${mailto}`;\n\n // Add API key if provided\n const headers: Record<string, string> = {\n 'User-Agent': 'nexus-agents',\n Accept: 'application/json',\n };\n if (apiKey !== undefined && apiKey !== '') {\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n const fetchResult = await fetchSource({\n url,\n source: 'openalex',\n headers,\n });\n if (!fetchResult.ok) return fetchResult;\n\n let raw: unknown;\n try {\n raw = await fetchResult.value.json();\n } catch {\n return openAlexParseError('Response is not valid JSON');\n }\n\n const parsed = OpenAlexResponseSchema.safeParse(raw);\n if (!parsed.success) return openAlexParseError('Response schema mismatch');\n\n const items = (parsed.data.results ?? [])\n .filter((w) => w.title !== undefined && w.title !== '')\n .map(mapOpenAlexWork);\n\n return { ok: true, value: items };\n}\n","/**\n * Research Quality Scoring\n *\n * Scores discovered research items by relevance, impact, recency,\n * and reproducibility to aid prioritization.\n *\n * @module cli/research-helpers-scoring\n * (Source: Research System Enhancement - Phase 2E)\n */\n\nimport type { DiscoveredSource } from './research-helpers-sources.js';\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/** Quality score for a discovered research item. */\nexport interface QualityScore {\n /** Topic keyword match ratio (0-1). */\n readonly relevance: number;\n /** Normalized impact metric (0-1) - citation count or star count. */\n readonly impact: number;\n /** Recency decay (0-1) - newer items score higher. */\n readonly recency: number;\n /** Code availability (0-1) - items with repos score higher. */\n readonly reproducibility: number;\n /** Weighted composite score (0-1). */\n readonly composite: number;\n}\n\n/** Weights for composite score calculation. */\nconst WEIGHTS = {\n relevance: 0.35,\n impact: 0.25,\n recency: 0.2,\n reproducibility: 0.2,\n} as const;\n\n// =============================================================================\n// SCORING FUNCTIONS\n// =============================================================================\n\n/** Score topic relevance from a title against a topic string. */\nfunction scoreRelevance(title: string, topic: string): number {\n const titleLower = title.toLowerCase();\n const topicWords = topic\n .toLowerCase()\n .split(/\\s+/)\n .filter((w) => w.length > 2);\n if (topicWords.length === 0) return 0.5;\n const matched = topicWords.filter((w) => titleLower.includes(w)).length;\n return matched / topicWords.length;\n}\n\n/** Convert relevance label to numeric score. */\nfunction relevanceLabelToScore(relevance: string): number {\n switch (relevance) {\n case 'high':\n return 0.9;\n case 'medium':\n return 0.5;\n case 'low':\n return 0.2;\n default:\n return 0.5;\n }\n}\n\n/** Score recency based on discovered date. Decays over 2 years. */\nfunction scoreRecency(discoveredAt: string): number {\n const discoveredDate = new Date(discoveredAt);\n if (isNaN(discoveredDate.getTime())) return 0.5;\n const now = new Date();\n const daysSince = (now.getTime() - discoveredDate.getTime()) / (1000 * 60 * 60 * 24);\n // Linear decay over 730 days (2 years)\n return Math.max(0, 1 - daysSince / 730);\n}\n\n/** Score reproducibility based on source type. */\nfunction scoreReproducibility(source: string): number {\n // Sources with code get higher scores\n switch (source) {\n case 'github':\n return 1.0;\n case 'papers_with_code':\n return 0.8;\n default:\n return 0.3;\n }\n}\n\n/**\n * Score a discovered research item for quality.\n *\n * @param item - The discovered source to score\n * @param topic - The search topic for relevance scoring\n * @returns Quality score breakdown and composite\n */\nexport function scoreDiscoveredItem(item: DiscoveredSource, topic: string): QualityScore {\n const relevance =\n topic !== '' ? scoreRelevance(item.title, topic) : relevanceLabelToScore(item.relevance);\n const impact = relevanceLabelToScore(item.relevance);\n const recency = scoreRecency(item.discoveredAt);\n const reproducibility = scoreReproducibility(item.source);\n\n const composite =\n WEIGHTS.relevance * relevance +\n WEIGHTS.impact * impact +\n WEIGHTS.recency * recency +\n WEIGHTS.reproducibility * reproducibility;\n\n return {\n relevance: Math.round(relevance * 100) / 100,\n impact: Math.round(impact * 100) / 100,\n recency: Math.round(recency * 100) / 100,\n reproducibility: Math.round(reproducibility * 100) / 100,\n composite: Math.round(composite * 100) / 100,\n };\n}\n\n/**\n * Score and sort a list of discovered items by quality.\n *\n * @param items - Items to score\n * @param topic - Topic for relevance scoring\n * @returns Items sorted by composite score (descending) with scores\n */\nexport function rankDiscoveredItems(\n items: readonly DiscoveredSource[],\n topic: string\n): Array<{ item: DiscoveredSource; score: QualityScore }> {\n return items\n .map((item) => ({ item, score: scoreDiscoveredItem(item, topic) }))\n .sort((a, b) => b.score.composite - a.score.composite);\n}\n","/**\n * Research Index Operations\n *\n * Extracted from research-command.ts to stay under file size limits.\n * Handles stats, refresh, and check operations on the research index.\n *\n * @module cli/research-helpers-index-ops\n * @see Issue #237 (Epic #225)\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport {\n parseRegistry,\n generateIndexMarkdown,\n generateStatsJson,\n generateSummaryReport,\n} from '../indexer/research-index/index.js';\n\n/** Gets the registry path. */\nfunction getRegistryPath(): string {\n return path.resolve(process.cwd(), 'docs/research/registry');\n}\n\n/** Gets the index output path. */\nfunction getIndexPath(): string {\n return path.resolve(process.cwd(), 'docs/research/RESEARCH_INDEX.md');\n}\n\n/**\n * Handle stats subcommand - show research statistics.\n */\nexport async function handleStatsCommand(options: Record<string, unknown>): Promise<string> {\n const registryPath = getRegistryPath();\n const result = parseRegistry({ registryPath });\n\n if (!result.ok) {\n return `Error: Failed to parse registry: ${result.error.message}`;\n }\n\n const index = result.value;\n const formatVal = options['format'];\n const format = typeof formatVal === 'string' ? formatVal : undefined;\n\n // Ensure async compliance (future: may add async registry operations)\n await Promise.resolve();\n\n if (format === 'json') {\n return generateStatsJson(index);\n }\n\n return generateSummaryReport(index);\n}\n\n/**\n * Handle refresh subcommand - regenerate RESEARCH_INDEX.md.\n */\nexport async function handleRefreshCommand(options: Record<string, unknown>): Promise<string> {\n const outputVal = options['output'];\n const outputPath = (typeof outputVal === 'string' ? outputVal : undefined) ?? getIndexPath();\n const registryPath = getRegistryPath();\n const result = parseRegistry({ registryPath });\n\n if (!result.ok) {\n return `Error: Failed to parse registry: ${result.error.message}`;\n }\n\n const index = result.value;\n const mdResult = generateIndexMarkdown(index);\n\n if (!mdResult.ok) {\n return `Error: Failed to generate markdown: ${mdResult.error.message}`;\n }\n\n // Write the index\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, mdResult.value, 'utf-8');\n\n const stats = index.stats;\n return [\n `Research index regenerated successfully`,\n ` Output: ${outputPath}`,\n ` Papers: ${String(stats.totalPapers)}`,\n ` Techniques: ${String(stats.totalTechniques)}`,\n ` Implemented: ${String(stats.techniquesByStatus.implemented)}`,\n ].join('\\n');\n}\n\n/**\n * Handle check subcommand - check if index is up to date.\n */\nexport async function handleCheckCommand(): Promise<string> {\n const indexPath = getIndexPath();\n\n // Check if index exists\n try {\n await fs.access(indexPath);\n } catch {\n return `Error: Research index not found: ${indexPath}. Run 'nexus-agents research refresh' first.`;\n }\n\n // Parse registry and generate fresh index\n const registryPath = getRegistryPath();\n const result = parseRegistry({ registryPath });\n\n if (!result.ok) {\n return `Error: Failed to parse registry: ${result.error.message}`;\n }\n\n const mdResult = generateIndexMarkdown(result.value);\n if (!mdResult.ok) {\n return `Error: Failed to generate markdown: ${mdResult.error.message}`;\n }\n\n // Read existing index\n const existingContent = await fs.readFile(indexPath, 'utf-8');\n const freshContent = mdResult.value;\n\n // Compare (normalize whitespace for comparison)\n const normalize = (s: string): string => s.replace(/\\s+/g, ' ').trim();\n const isFresh = normalize(existingContent) === normalize(freshContent);\n\n if (isFresh) {\n return `Research index is up to date (${String(result.value.stats.totalTechniques)} techniques)`;\n }\n\n return `Research index is out of date. Run \"nexus-agents research refresh\" to update.`;\n}\n","/**\n * nexus-agents/indexer/research-index - Base Type Definitions\n *\n * Fundamental types for research registry entries.\n * Extracted to break circular dependency between research-index-types\n * and research-index-stats-types.\n *\n * @module indexer/research-index/research-index-base-types\n * (Source: Issue #392 - Circular dependency resolution)\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Schema Version\n// ============================================================================\n\nexport const RESEARCH_INDEX_SCHEMA_VERSION = '1.0' as const;\n\n// ============================================================================\n// Topic & Status Enums\n// ============================================================================\n\n/**\n * Research topics tracked in the registry.\n */\n// Topics are free-form strings — the registry has 56+ unique topics.\nexport const ResearchTopicSchema = z.string().min(1);\nexport type ResearchTopic = z.infer<typeof ResearchTopicSchema>;\n\n/**\n * Technique implementation status.\n */\nexport const TechniqueStatusSchema = z.enum([\n 'implemented',\n 'planned',\n 'in-progress',\n 'not-started',\n 'rejected',\n]);\nexport type TechniqueStatus = z.infer<typeof TechniqueStatusSchema>;\n\n/**\n * Paper implementation status. Canonical source for this enum (#2717).\n * Other files MUST import this; do not re-declare a parallel z.enum.\n *\n * `deferred` is its own state — distinct from `rejected` (won't-do-ever),\n * `not-started` (haven't-gotten-to-it), and `in-progress` (working-on-it).\n * Used by papers that the team consciously deferred with a documented\n * `deferral_rationale` + explicit `Re-open triggers:` block. Pre-#2717 the\n * 2 papers using it failed strict validation against this schema.\n */\nexport const PaperStatusSchema = z.enum([\n 'implemented',\n 'planned',\n 'partial',\n 'in-progress',\n 'not-started',\n 'rejected',\n 'deferred',\n]);\nexport type PaperStatus = z.infer<typeof PaperStatusSchema>;\n\n/**\n * Technique priority levels.\n */\nexport const TechniquePrioritySchema = z.enum(['P1', 'P2', 'P3', 'P4']).nullable();\nexport type TechniquePriority = z.infer<typeof TechniquePrioritySchema>;\n\n/**\n * Technique complexity levels.\n */\nexport const TechniqueComplexitySchema = z.enum(['low', 'medium', 'high']);\nexport type TechniqueComplexity = z.infer<typeof TechniqueComplexitySchema>;\n\n/**\n * Source types for non-paper sources.\n */\nexport const SourceTypeSchema = z.enum([\n 'product_docs',\n 'specification',\n 'research_blog',\n 'code_analysis',\n 'open_source_repo',\n]);\nexport type SourceType = z.infer<typeof SourceTypeSchema>;\n\n// ============================================================================\n// Decision History\n// ============================================================================\n\n/**\n * A single decision entry in technique history.\n */\nexport const DecisionHistoryEntrySchema = z.object({\n date: z.string(),\n decision: z.string(),\n rationale: z.string(),\n});\nexport type DecisionHistoryEntry = z.infer<typeof DecisionHistoryEntrySchema>;\n\n// ============================================================================\n// Research Paper\n// ============================================================================\n\n/**\n * Metrics associated with a paper (key-value pairs).\n */\nexport const PaperMetricsSchema = z.record(z.string(), z.string());\nexport type PaperMetrics = z.infer<typeof PaperMetricsSchema>;\n\n/**\n * A research paper entry from papers.yaml.\n */\nexport const ResearchPaperSchema = z.object({\n /** Paper title */\n title: z.string(),\n /** Paper authors */\n authors: z.array(z.string()).optional().default([]),\n /** Source type (arxiv, conference, journal, preprint) */\n source: z.string().optional(),\n /** arXiv ID (e.g., '2501.06322') */\n arxiv_id: z.string().optional(),\n /** URL to the paper */\n url: z.string().optional(),\n /** Publication date (YYYY-MM format) */\n publication_date: z.string().optional(),\n /** Publication venue */\n venue: z.string().nullable().optional(),\n\n /** Research topics */\n topics: z.array(ResearchTopicSchema).optional().default([]),\n /** Tags for searching */\n tags: z.array(z.string()).optional().default([]),\n\n /** Date when the paper was reviewed */\n reviewed_date: z.string().optional(),\n /** File where the paper is reviewed */\n reviewed_in: z.string().optional(),\n /** Summary of the paper */\n summary: z.string().optional(),\n\n /** Key findings from the paper */\n key_findings: z.array(z.string()).optional().default([]),\n\n /** Relevance to the project */\n relevance: z.enum(['high', 'medium', 'low']).optional(),\n /** Techniques extracted from this paper */\n techniques_extracted: z.array(z.string()).optional().default([]),\n\n /** Related GitHub issues */\n related_issues: z.array(z.number()).optional().default([]),\n /** Implementation status */\n implementation_status: PaperStatusSchema.optional().default('not-started'),\n\n // ── Quality Assessment (Issue #1571) ──────────────────────────\n /** Citation count from Semantic Scholar */\n citation_count: z.number().nonnegative().optional(),\n /** Venue quality tier: 3=top, 2=good, 1=workshop, 0=preprint */\n venue_tier: z.number().min(0).max(3).optional(),\n /** Whether the paper links to a code repository */\n has_code: z.boolean().optional(),\n /** Code repository URL */\n code_url: z.string().optional(),\n /** Rigor assessment tags */\n rigor_tags: z\n .array(\n z.enum(['has-code', 'has-dataset', 'has-baselines', 'peer-reviewed', 'single-model-eval'])\n )\n .optional()\n .default([]),\n /** Composite quality score (0-10) */\n quality_score: z.number().min(0).max(10).optional(),\n /** Evidence confidence tier */\n evidence_tier: z.enum(['high', 'medium', 'low']).optional(),\n /** Quality notes for low-scoring papers */\n quality_notes: z.string().optional(),\n /** When quality was last assessed (ISO date) */\n last_quality_check: z.string().optional(),\n});\nexport type ResearchPaper = z.infer<typeof ResearchPaperSchema>;\n\n// ============================================================================\n// Research Technique\n// ============================================================================\n\n/**\n * A technique entry from techniques.yaml.\n */\nexport const ResearchTechniqueSchema = z.object({\n /** Technique name */\n name: z.string(),\n /** Description of the technique */\n description: z.string(),\n\n /** Source papers (arXiv IDs) */\n source_papers: z.array(z.string()).optional().default([]),\n\n /** Primary topic */\n topic: ResearchTopicSchema,\n /** Tags for searching */\n tags: z.array(z.string()).optional().default([]),\n\n /** Metrics associated with this technique */\n metrics: z.record(z.string(), z.string()).optional().default({}),\n\n /** Implementation status */\n status: TechniqueStatusSchema,\n /** Priority level */\n priority: TechniquePrioritySchema.optional().default(null),\n /** Complexity level */\n complexity: TechniqueComplexitySchema.optional(),\n\n /** Files where this technique is implemented */\n integration_files: z.array(z.string()).optional().default([]),\n\n /** GitHub issue number for implementation */\n implementation_issue: z.number().nullable().optional().default(null),\n /** Related PR numbers */\n related_prs: z.array(z.number()).optional().default([]),\n\n /** Implementation notes */\n notes: z.string().optional(),\n\n /** Dependent techniques */\n dependencies: z.array(z.string()).optional().default([]),\n\n /** Decision history */\n decision_history: z.array(DecisionHistoryEntrySchema).optional().default([]),\n\n // ── Evaluation Plan (Issue #1576 Wave 6) ──────────────────────\n /** Structured evaluation plan for keeping or removing the technique */\n evaluation_plan: z\n .object({\n success_criteria: z.string().optional(),\n evaluation_method: z.string().optional(),\n evaluation_deadline: z.string().optional(),\n removal_criteria: z.string().optional(),\n })\n .optional(),\n /** Evaluation status: pending (not yet evaluated), passed, failed, deferred */\n evaluation_status: z.enum(['pending', 'passed', 'failed', 'deferred']).optional(),\n});\nexport type ResearchTechnique = z.infer<typeof ResearchTechniqueSchema>;\n\n// ============================================================================\n// Research Source (Non-Paper)\n// ============================================================================\n\n/**\n * A non-paper source entry from sources.yaml.\n */\nexport const ResearchSourceSchema = z.object({\n /** Source name */\n name: z.string(),\n /** Source type */\n type: SourceTypeSchema,\n /** URL */\n url: z.string(),\n /** Vendor/organization */\n vendor: z.string().optional(),\n\n /** Topics covered */\n topics: z.array(ResearchTopicSchema).optional().default([]),\n /** Tags for searching */\n tags: z.array(z.string()).optional().default([]),\n\n /** Date when reviewed */\n reviewed_date: z.string().optional(),\n /** File where reviewed */\n reviewed_in: z.string().nullable().optional(),\n\n /** Key information extracted */\n key_info: z.array(z.string()).optional().default([]),\n /** Best practices documented */\n best_practices: z.array(z.string()).optional().default([]),\n\n /** Version checked */\n version_checked: z.string().optional(),\n\n // ── Repo/Tool Quality Signals (for open_source_repo type) ──────\n /** Quality signals for repositories and tools */\n quality_signals: z\n .object({\n stars_at_review: z.number().nonnegative().optional(),\n language: z.string().optional(),\n has_tests: z.boolean().optional(),\n has_docs: z.boolean().optional(),\n has_paper: z.boolean().optional(),\n arxiv_id: z.string().optional(),\n })\n .optional(),\n /** Techniques extracted from this source */\n techniques_extracted: z.array(z.string()).optional().default([]),\n /** Adoption verdict: adopted, partially_adopted, rejected, monitoring, planned */\n verdict: z.enum(['adopted', 'partially_adopted', 'rejected', 'monitoring', 'planned']).optional(),\n /** Notes explaining the verdict */\n verdict_notes: z.string().optional(),\n /** Composite quality score (0-10) */\n quality_score: z.number().min(0).max(10).optional(),\n /** Evidence confidence tier */\n evidence_tier: z.enum(['high', 'medium', 'low']).optional(),\n});\nexport type ResearchSource = z.infer<typeof ResearchSourceSchema>;\n\n// ============================================================================\n// Registry Collections\n// ============================================================================\n\n/**\n * Schema for papers.yaml file structure.\n */\nexport const PapersRegistrySchema = z.object({\n schema_version: z.string(),\n papers: z.record(z.string(), ResearchPaperSchema),\n});\nexport type PapersRegistry = z.infer<typeof PapersRegistrySchema>;\n\n/**\n * Schema for techniques.yaml file structure.\n */\nexport const TechniquesRegistrySchema = z.object({\n schema_version: z.string(),\n techniques: z.record(z.string(), ResearchTechniqueSchema),\n});\nexport type TechniquesRegistry = z.infer<typeof TechniquesRegistrySchema>;\n\n/**\n * Schema for sources.yaml file structure.\n */\nexport const SourcesRegistrySchema = z.object({\n schema_version: z.string(),\n sources: z.record(z.string(), ResearchSourceSchema),\n});\nexport type SourcesRegistry = z.infer<typeof SourcesRegistrySchema>;\n","/**\n * nexus-agents/indexer/research-index - Statistics & Configuration Types\n *\n * Types for research index statistics, parser/generator options, and errors.\n * Extracted from research-index-types.ts to maintain file size limits.\n *\n * (Source: Research Tracking System - docs/research/RESEARCH_INDEX.md)\n */\n\nimport type {\n ResearchTopic,\n ResearchPaper,\n ResearchTechnique,\n ResearchSource,\n} from './research-index-base-types.js';\n\n// ============================================================================\n// Statistics Types\n// ============================================================================\n\n/**\n * Statistics for a single topic.\n */\nexport interface TopicStats {\n /** Topic name */\n readonly topic: ResearchTopic;\n /** Number of papers in this topic */\n readonly paperCount: number;\n /** Number of techniques in this topic */\n readonly techniqueCount: number;\n}\n\n/**\n * Statistics by technique status.\n */\nexport interface TechniqueStatusStats {\n /** Number of implemented techniques */\n readonly implemented: number;\n /** Number of planned techniques */\n readonly planned: number;\n /** Number of in-progress techniques */\n readonly inProgress: number;\n /** Number of not-started techniques */\n readonly notStarted: number;\n /** Number of rejected techniques */\n readonly rejected: number;\n}\n\n/**\n * Statistics by technique priority.\n */\nexport interface TechniquePriorityStats {\n /** P1 techniques count */\n readonly P1: number;\n /** P2 techniques count */\n readonly P2: number;\n /** P3 techniques count */\n readonly P3: number;\n /** P4 techniques count */\n readonly P4: number;\n /** No priority assigned */\n readonly none: number;\n}\n\n/**\n * Complete research index statistics.\n */\nexport interface ResearchIndexStats {\n /** Total number of papers */\n readonly totalPapers: number;\n /** Total number of techniques */\n readonly totalTechniques: number;\n /** Total number of sources */\n readonly totalSources: number;\n /** Total number of topics */\n readonly totalTopics: number;\n\n /** Techniques grouped by status */\n readonly techniquesByStatus: TechniqueStatusStats;\n /** Techniques grouped by priority */\n readonly techniquesByPriority: TechniquePriorityStats;\n /** Statistics per topic */\n readonly topicStats: readonly TopicStats[];\n /** Quality distribution (evidence tiers) */\n readonly qualityDistribution?: {\n readonly high: number;\n readonly medium: number;\n readonly low: number;\n readonly unscored: number;\n readonly averageScore: number;\n };\n}\n\n// ============================================================================\n// Research Index (Complete Data Structure)\n// ============================================================================\n\n/**\n * Paper with its ID included.\n */\nexport interface ResearchPaperWithId extends ResearchPaper {\n /** Paper ID (e.g., 'arxiv-2501.06322') */\n readonly id: string;\n}\n\n/**\n * Technique with its ID included.\n */\nexport interface ResearchTechniqueWithId extends ResearchTechnique {\n /** Technique ID (e.g., 'aegean-consensus') */\n readonly id: string;\n}\n\n/**\n * Source with its ID included.\n */\nexport interface ResearchSourceWithId extends ResearchSource {\n /** Source ID (e.g., 'claude-code-docs') */\n readonly id: string;\n}\n\n/**\n * Complete parsed research index.\n */\nexport interface ResearchIndex {\n /** Schema version */\n readonly schemaVersion: string;\n /** Generation timestamp (ISO 8601, ET timezone) */\n readonly generatedAt: string;\n /** Parsed papers */\n readonly papers: readonly ResearchPaperWithId[];\n /** Parsed techniques */\n readonly techniques: readonly ResearchTechniqueWithId[];\n /** Parsed sources */\n readonly sources: readonly ResearchSourceWithId[];\n /** Computed statistics */\n readonly stats: ResearchIndexStats;\n}\n\n// ============================================================================\n// Parser Options\n// ============================================================================\n\n/**\n * Options for the research index parser.\n */\nexport interface ResearchIndexParserOptions {\n /** Path to the research registry directory */\n readonly registryPath: string;\n /** Whether to validate all entries strictly */\n readonly strictValidation: boolean;\n}\n\n/**\n * Default parser options.\n */\nexport const DEFAULT_RESEARCH_INDEX_PARSER_OPTIONS: ResearchIndexParserOptions = {\n registryPath: 'docs/research/registry',\n strictValidation: true,\n};\n\n// ============================================================================\n// Generator Options\n// ============================================================================\n\n/**\n * Options for the research index generator.\n */\nexport interface ResearchIndexGeneratorOptions {\n /** Include P1 techniques table */\n readonly includeP1Table: boolean;\n /** Include P2 techniques table */\n readonly includeP2Table: boolean;\n /** Include recently reviewed papers section */\n readonly includeRecentPapers: boolean;\n /** Number of recent papers to show */\n readonly recentPapersLimit: number;\n /** Include papers by topic section */\n readonly includePapersByTopic: boolean;\n /** Include GitHub issues section */\n readonly includeGitHubIssues: boolean;\n}\n\n/**\n * Default generator options.\n */\nexport const DEFAULT_RESEARCH_INDEX_GENERATOR_OPTIONS: ResearchIndexGeneratorOptions = {\n includeP1Table: true,\n includeP2Table: true,\n includeRecentPapers: true,\n recentPapersLimit: 5,\n includePapersByTopic: true,\n includeGitHubIssues: true,\n};\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\n/**\n * Parser error types.\n */\nexport class ResearchIndexParseError extends Error {\n constructor(\n message: string,\n public readonly file: string,\n public readonly details?: unknown\n ) {\n super(message);\n this.name = 'ResearchIndexParseError';\n }\n}\n\n/**\n * Generator error types.\n */\nexport class ResearchIndexGeneratorError extends Error {\n constructor(\n message: string,\n public readonly details?: unknown\n ) {\n super(message);\n this.name = 'ResearchIndexGeneratorError';\n }\n}\n","/**\n * nexus-agents/indexer/research-index - Registry Parser\n *\n * Parses papers.yaml, techniques.yaml, and sources.yaml from the\n * research registry directory.\n *\n * (Source: Research Tracking System - docs/research/RESEARCH_INDEX.md)\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as yaml from 'yaml';\nimport { getErrorMessage, getTimeProvider } from '../../core/index.js';\nimport {\n computeSourceQualityScore,\n computeSourceEvidenceTier,\n} from '../../research/source-quality.js';\nimport type { Result } from '../../core/result.js';\nimport {\n type ResearchIndex,\n type ResearchIndexParserOptions,\n type ResearchIndexStats,\n type ResearchPaperWithId,\n type ResearchSourceWithId,\n type ResearchTechniqueWithId,\n type ResearchTopic,\n type TechniquePriorityStats,\n type TechniqueStatus,\n type TechniqueStatusStats,\n type TopicStats,\n DEFAULT_RESEARCH_INDEX_PARSER_OPTIONS,\n PapersRegistrySchema,\n ResearchIndexParseError,\n SourcesRegistrySchema,\n TechniquesRegistrySchema,\n} from './research-index-types.js';\n\n// ============================================================================\n// File Reading\n// ============================================================================\n\n/**\n * Read and parse a YAML file.\n *\n * #2470: when `defaultIfMissing` is provided and the file doesn't exist, the\n * caller gets that default back instead of an error. This lets the research-\n * index commands operate cleanly on a fresh install / sandboxed clone where\n * the registries haven't been populated yet, without the indexer needing to\n * import the cli-layer scaffolder (which would create a layering cycle).\n * The cli/research-helpers-io.ts path still scaffolds files on disk; this\n * one just doesn't fail loudly when nothing's there.\n */\n/**\n * Build a ResearchIndexParseError that surfaces Zod issue details (#2717).\n * Pre-fix the user-facing message was just `Validation failed for <path>`\n * even though the Zod result.error carried the issues array.\n */\nfunction buildValidationError(filePath: string, validationErr: unknown): ResearchIndexParseError {\n const zodErr = validationErr as {\n issues?: ReadonlyArray<{ path: ReadonlyArray<string | number>; message: string }>;\n };\n const issues = zodErr.issues ?? [];\n const issuesPreview = issues\n .slice(0, 5)\n .map((i) => `${i.path.slice(0, 4).join('.')}: ${i.message}`)\n .join('; ');\n const more = issues.length > 5 ? ` (+${String(issues.length - 5)} more)` : '';\n return new ResearchIndexParseError(\n issuesPreview.length > 0\n ? `Validation failed for ${filePath} — ${issuesPreview}${more}`\n : `Validation failed for ${filePath}`,\n filePath,\n validationErr\n );\n}\n\nfunction readYamlFile<T>(\n filePath: string,\n schema: { safeParse: (data: unknown) => { success: boolean; data?: T; error?: unknown } },\n defaultIfMissing?: T\n): Result<T, ResearchIndexParseError> {\n try {\n if (!fs.existsSync(filePath)) {\n if (defaultIfMissing !== undefined) {\n return { ok: true, value: defaultIfMissing };\n }\n return {\n ok: false,\n error: new ResearchIndexParseError(\n `File not found: ${filePath}. Run 'nexus-agents research add ...' to create it.`,\n filePath\n ),\n };\n }\n\n const content = fs.readFileSync(filePath, 'utf-8');\n const parsed: unknown = yaml.parse(content);\n\n const result = schema.safeParse(parsed);\n if (!result.success) {\n return { ok: false, error: buildValidationError(filePath, result.error) };\n }\n\n return { ok: true, value: result.data as T };\n } catch (error) {\n return {\n ok: false,\n error: new ResearchIndexParseError(\n `Failed to parse ${filePath}: ${getErrorMessage(error)}`,\n filePath,\n error\n ),\n };\n }\n}\n\n// ============================================================================\n// Paper Parsing\n// ============================================================================\n\n/**\n * Parse papers.yaml into structured paper entries.\n */\nexport function parsePapersRegistry(\n registryPath: string\n): Result<readonly ResearchPaperWithId[], ResearchIndexParseError> {\n const filePath = path.join(registryPath, 'papers.yaml');\n // #2470: graceful empty default when papers.yaml doesn't exist yet.\n const result = readYamlFile(filePath, PapersRegistrySchema, {\n schema_version: '1.0',\n papers: {},\n });\n\n if (!result.ok) {\n return result;\n }\n\n const papers: ResearchPaperWithId[] = Object.entries(result.value.papers).map(([id, paper]) => ({\n id,\n ...paper,\n }));\n\n return { ok: true, value: papers };\n}\n\n// ============================================================================\n// Technique Parsing\n// ============================================================================\n\n/**\n * Parse techniques.yaml into structured technique entries.\n */\nexport function parseTechniquesRegistry(\n registryPath: string\n): Result<readonly ResearchTechniqueWithId[], ResearchIndexParseError> {\n const filePath = path.join(registryPath, 'techniques.yaml');\n // #2470: graceful empty default when techniques.yaml doesn't exist yet.\n const result = readYamlFile(filePath, TechniquesRegistrySchema, {\n schema_version: '1.0',\n techniques: {},\n });\n\n if (!result.ok) {\n return result;\n }\n\n const techniques: ResearchTechniqueWithId[] = Object.entries(result.value.techniques).map(\n ([id, technique]) => ({\n id,\n ...technique,\n })\n );\n\n return { ok: true, value: techniques };\n}\n\n// ============================================================================\n// Source Parsing\n// ============================================================================\n\n/**\n * Parse sources.yaml into structured source entries.\n */\nexport function parseSourcesRegistry(\n registryPath: string\n): Result<readonly ResearchSourceWithId[], ResearchIndexParseError> {\n const filePath = path.join(registryPath, 'sources.yaml');\n // #2470: graceful empty default when sources.yaml doesn't exist yet.\n const result = readYamlFile(filePath, SourcesRegistrySchema, {\n schema_version: '1.0',\n sources: {},\n });\n\n if (!result.ok) {\n return result;\n }\n\n const sources: ResearchSourceWithId[] = Object.entries(result.value.sources).map(\n ([id, source]) => {\n const score = source.quality_score ?? computeSourceQualityScore(source);\n const tier =\n source.evidence_tier ?? computeSourceEvidenceTier({ ...source, quality_score: score });\n return { id, ...source, quality_score: score, evidence_tier: tier };\n }\n );\n\n return { ok: true, value: sources };\n}\n\n// ============================================================================\n// Statistics Computation\n// ============================================================================\n\n/**\n * Count techniques by status.\n */\nfunction countTechniquesByStatus(\n techniques: readonly ResearchTechniqueWithId[]\n): TechniqueStatusStats {\n const counts: Record<TechniqueStatus, number> = {\n implemented: 0,\n planned: 0,\n 'in-progress': 0,\n 'not-started': 0,\n rejected: 0,\n };\n\n for (const technique of techniques) {\n counts[technique.status]++;\n }\n\n return {\n implemented: counts['implemented'],\n planned: counts['planned'],\n inProgress: counts['in-progress'],\n notStarted: counts['not-started'],\n rejected: counts['rejected'],\n };\n}\n\n/**\n * Count techniques by priority.\n */\nfunction countTechniquesByPriority(\n techniques: readonly ResearchTechniqueWithId[]\n): TechniquePriorityStats {\n const counts = {\n P1: 0,\n P2: 0,\n P3: 0,\n P4: 0,\n none: 0,\n };\n\n for (const technique of techniques) {\n const priority = technique.priority;\n if (priority === null) {\n counts.none++;\n } else {\n counts[priority]++;\n }\n }\n\n return counts;\n}\n\n/**\n * Compute statistics per topic.\n */\n/** Derive all unique topics from actual paper + technique data. */\nfunction deriveAllTopics(\n papers: readonly ResearchPaperWithId[],\n techniques: readonly ResearchTechniqueWithId[]\n): ResearchTopic[] {\n const topicSet = new Set<string>();\n for (const p of papers) {\n for (const t of p.topics) topicSet.add(t);\n }\n for (const t of techniques) {\n topicSet.add(t.topic);\n }\n return [...topicSet].sort();\n}\n\nfunction computeTopicStats(\n papers: readonly ResearchPaperWithId[],\n techniques: readonly ResearchTechniqueWithId[]\n): readonly TopicStats[] {\n const allTopics = deriveAllTopics(papers, techniques);\n return allTopics.map((topic) => {\n const paperCount = papers.filter((p) => p.topics.includes(topic)).length;\n const techniqueCount = techniques.filter((t) => t.topic === topic).length;\n\n return {\n topic,\n paperCount,\n techniqueCount,\n };\n });\n}\n\n/**\n * Compute complete statistics for the research index.\n */\nexport function computeStats(\n papers: readonly ResearchPaperWithId[],\n techniques: readonly ResearchTechniqueWithId[],\n sources: readonly ResearchSourceWithId[]\n): ResearchIndexStats {\n return {\n totalPapers: papers.length,\n totalTechniques: techniques.length,\n totalSources: sources.length,\n totalTopics: deriveAllTopics(papers, techniques).length,\n techniquesByStatus: countTechniquesByStatus(techniques),\n techniquesByPriority: countTechniquesByPriority(techniques),\n topicStats: computeTopicStats(papers, techniques),\n qualityDistribution: computeQualityDistribution(papers),\n };\n}\n\n/** Compute evidence tier distribution across papers. */\nfunction computeQualityDistribution(papers: readonly ResearchPaperWithId[]): {\n high: number;\n medium: number;\n low: number;\n unscored: number;\n averageScore: number;\n} {\n let high = 0;\n let medium = 0;\n let low = 0;\n let unscored = 0;\n let totalScore = 0;\n let scored = 0;\n\n for (const p of papers) {\n const tier = p.evidence_tier;\n if (tier === 'high') high++;\n else if (tier === 'medium') medium++;\n else if (tier === 'low') low++;\n else unscored++;\n\n const score = p.quality_score;\n if (score !== undefined) {\n totalScore += score;\n scored++;\n }\n }\n\n return {\n high,\n medium,\n low,\n unscored,\n averageScore: scored > 0 ? Math.round((totalScore / scored) * 10) / 10 : 0,\n };\n}\n\n// ============================================================================\n// Main Parser Function\n// ============================================================================\n\n/**\n * Parse the complete research registry.\n */\nexport function parseRegistry(\n options: Partial<ResearchIndexParserOptions> = {}\n): Result<ResearchIndex, ResearchIndexParseError> {\n const opts = { ...DEFAULT_RESEARCH_INDEX_PARSER_OPTIONS, ...options };\n\n // Parse papers\n const papersResult = parsePapersRegistry(opts.registryPath);\n if (!papersResult.ok) {\n return papersResult;\n }\n\n // Parse techniques\n const techniquesResult = parseTechniquesRegistry(opts.registryPath);\n if (!techniquesResult.ok) {\n return techniquesResult;\n }\n\n // Parse sources\n const sourcesResult = parseSourcesRegistry(opts.registryPath);\n if (!sourcesResult.ok) {\n return sourcesResult;\n }\n\n // Compute statistics\n const stats = computeStats(papersResult.value, techniquesResult.value, sourcesResult.value);\n\n // Generate timestamp in ET\n const now = new Date(getTimeProvider().now());\n const etFormatter = new Intl.DateTimeFormat('en-US', {\n timeZone: 'America/New_York',\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false,\n });\n const parts = etFormatter.formatToParts(now);\n const getPartValue = (type: string): string => parts.find((p) => p.type === type)?.value ?? '';\n const generatedAt = `${getPartValue('year')}-${getPartValue('month')}-${getPartValue('day')} (ET)`;\n\n return {\n ok: true,\n value: {\n schemaVersion: '1.0',\n generatedAt,\n papers: papersResult.value,\n techniques: techniquesResult.value,\n sources: sourcesResult.value,\n stats,\n },\n };\n}\n\n// ============================================================================\n// Query Helpers\n// ============================================================================\n\n/**\n * Get techniques filtered by status.\n */\nexport function getTechniquesByStatus(\n index: ResearchIndex,\n status: TechniqueStatus\n): readonly ResearchTechniqueWithId[] {\n return index.techniques.filter((t) => t.status === status);\n}\n\n/**\n * Get techniques filtered by priority.\n */\nexport function getTechniquesByPriority(\n index: ResearchIndex,\n priority: 'P1' | 'P2' | 'P3' | 'P4'\n): readonly ResearchTechniqueWithId[] {\n return index.techniques.filter((t) => t.priority === priority);\n}\n\n/**\n * Get techniques filtered by topic.\n */\nexport function getTechniquesByTopic(\n index: ResearchIndex,\n topic: ResearchTopic\n): readonly ResearchTechniqueWithId[] {\n return index.techniques.filter((t) => t.topic === topic);\n}\n\n/**\n * Get papers filtered by topic.\n */\nexport function getPapersByTopic(\n index: ResearchIndex,\n topic: ResearchTopic\n): readonly ResearchPaperWithId[] {\n return index.papers.filter((p) => p.topics.includes(topic));\n}\n\n/**\n * Get recently reviewed papers (sorted by review date descending).\n */\nexport function getRecentlyReviewedPapers(\n index: ResearchIndex,\n limit: number = 5\n): readonly ResearchPaperWithId[] {\n return [...index.papers]\n .filter(\n (p): p is ResearchPaperWithId & { reviewed_date: string } =>\n typeof p.reviewed_date === 'string'\n )\n .sort((a, b) => b.reviewed_date.localeCompare(a.reviewed_date))\n .slice(0, limit);\n}\n\n/**\n * Get techniques with GitHub issues.\n */\nexport function getTechniquesWithIssues(index: ResearchIndex): readonly ResearchTechniqueWithId[] {\n return index.techniques.filter((t) => t.implementation_issue !== null);\n}\n","/**\n * Source quality scoring for non-paper research sources (repos, tools, blogs).\n *\n * Computes a composite quality score (0-10) from verifiable signals\n * already stored in sources.yaml quality_signals fields.\n * No external API calls — scoring is purely local.\n *\n * @module research/source-quality\n * @see Issue #1577\n */\n\nimport type { ResearchSource } from '../indexer/research-index/research-index-base-types.js';\n\n/**\n * Star count score (0-3, logarithmic, matching paper citation scale).\n * 0=none/unknown, 1=1-99, 2=100-999, 3=1000+\n */\nexport function starScore(stars: number | undefined): number {\n if (stars === undefined || stars === 0) return 0;\n if (stars < 100) return 1;\n if (stars < 1000) return 2;\n return 3;\n}\n\n/**\n * Review recency score (0-2).\n * 2=reviewed within 6 months, 1=within 1 year, 0=older or unknown.\n */\nexport function reviewRecencyScore(reviewedDate: string | undefined): number {\n if (reviewedDate === undefined) return 0;\n const now = new Date();\n const reviewed = new Date(reviewedDate);\n const monthsAgo = (now.getTime() - reviewed.getTime()) / (30 * 24 * 60 * 60 * 1000);\n if (monthsAgo < 6) return 2;\n if (monthsAgo < 12) return 1;\n return 0;\n}\n\n/**\n * Compute composite quality score (0-10) for a non-paper source.\n *\n * Breakdown (raw max = 8):\n * - Star count: 0-3 (logarithmic, same scale as paper citations)\n * - has_tests: 0 or 1\n * - has_docs: 0 or 1\n * - Review recency: 0-2\n * - has_paper: 0 or 1 (associated academic paper adds credibility)\n *\n * Normalized: raw * 10/8, capped at 10.\n */\nexport function computeSourceQualityScore(source: ResearchSource): number {\n const signals = source.quality_signals;\n if (signals === undefined) {\n // No quality signals available — return baseline score\n return source.type === 'open_source_repo' ? 0 : 3;\n }\n\n const stars = starScore(signals.stars_at_review);\n const tests = signals.has_tests === true ? 1 : 0;\n const docs = signals.has_docs === true ? 1 : 0;\n const recency = reviewRecencyScore(source.reviewed_date);\n const paper = signals.has_paper === true ? 1 : 0;\n\n const raw = stars + tests + docs + recency + paper;\n return Math.min(10, Math.round((raw * 10) / 8));\n}\n\n/**\n * Determine evidence tier for a source based on quality score and signals.\n *\n * - high: quality >= 7 AND (has_tests OR has_paper)\n * - medium: quality >= 4 OR has_tests\n * - low: everything else\n */\nexport function computeSourceEvidenceTier(source: ResearchSource): 'high' | 'medium' | 'low' {\n const score = source.quality_score ?? computeSourceQualityScore(source);\n const signals = source.quality_signals;\n\n const hasTests = signals?.has_tests === true;\n const hasPaper = signals?.has_paper === true;\n\n if (score >= 7 && (hasTests || hasPaper)) return 'high';\n if (score >= 4 || hasTests) return 'medium';\n return 'low';\n}\n","/**\n * nexus-agents/indexer/research-index - Markdown Generator Helpers\n *\n * Pure helper functions for generating markdown sections from research index data.\n *\n * (Source: Research Tracking System - docs/research/RESEARCH_INDEX.md)\n */\n\nimport { getTimeProvider } from '../../core/index.js';\nimport type {\n ResearchIndex,\n ResearchIndexGeneratorOptions,\n ResearchTechniqueWithId,\n ResearchTopic,\n} from './research-index-types.js';\nimport {\n getPapersByTopic,\n getRecentlyReviewedPapers,\n getTechniquesByPriority,\n getTechniquesWithIssues,\n} from './research-index-parser.js';\nimport { capitalizeWords as capitalize } from '../../utils/text-utils.js';\n\n// Re-export for backward compatibility\nexport { capitalize };\n\n// ============================================================================\n// Header & Stats Sections\n// ============================================================================\n\n/**\n * Generate the header section.\n */\nexport function generateHeader(index: ResearchIndex): string {\n const { stats } = index;\n return `# Nexus-Agents Research Index\n\n**Generated:** ${index.generatedAt}\n**Total Papers:** ${String(stats.totalPapers)} | **Techniques:** ${String(stats.totalTechniques)} | **Topics:** ${String(stats.totalTopics)}\n\n---`;\n}\n\n/**\n * Generate the quick stats table.\n */\nexport function generateQuickStats(index: ResearchIndex): string {\n const { techniquesByStatus } = index.stats;\n return `## Quick Stats\n\n| Status | Papers | Techniques |\n| ----------- | ------ | ---------- |\n| Implemented | - | ${String(techniquesByStatus.implemented)} |\n| In Progress | - | ${String(techniquesByStatus.inProgress)} |\n| Planned | - | ${String(techniquesByStatus.planned)} |\n| Not Started | - | ${String(techniquesByStatus.notStarted)} |\n| Rejected | - | ${String(techniquesByStatus.rejected)} |\n\n> **Note:** Paper-level status tracking deprecated. Technique status is source of truth.`;\n}\n\n// ============================================================================\n// Topics Section\n// ============================================================================\n\n/**\n * Generate the topics table.\n */\nexport function generateTopicsTable(index: ResearchIndex): string {\n const { topicStats } = index.stats;\n const topicDescriptions: Record<ResearchTopic, string> = {\n consensus: 'Multi-agent decision protocols',\n routing: 'Cost-efficient model routing',\n memory: 'Context and long-term memory',\n 'code-generation': 'Self-improvement and skill learning',\n 'cli-tools': 'External CLI integration',\n orchestration: 'Multi-agent coordination',\n security: 'Agent safety and security evaluation',\n 'multi-agent-worker-dispatch': 'Worker dispatch and wave execution',\n };\n\n const rows = topicStats.map((stat) => {\n const description = topicDescriptions[stat.topic];\n const topicLink = `[${capitalize(stat.topic.replaceAll('-', ' '))}](topics/${stat.topic}/README.md)`;\n return `| ${topicLink} | ${String(stat.paperCount)} | ${String(stat.techniqueCount)} | ${description ?? ''} |`;\n });\n\n return `---\n\n## Topics\n\n| Topic | Papers | Techniques | Description |\n| ----- | ------ | ---------- | ----------- |\n${rows.join('\\n')}`;\n}\n\n// ============================================================================\n// Technique Sections\n// ============================================================================\n\n/**\n * Generate technique table row.\n */\nexport function generateTechniqueRow(technique: ResearchTechniqueWithId): string {\n const name = `[${technique.name}](registry/techniques.yaml#${technique.id})`;\n const topic = technique.topic;\n // metrics has default {} so always defined\n const metricsEntries = Object.entries(technique.metrics);\n const metrics =\n metricsEntries.length > 0\n ? metricsEntries.map(([key, value]) => `${key}: ${value}`).join(', ')\n : '-';\n // implementation_issue is nullable\n const issue =\n technique.implementation_issue !== null ? `#${String(technique.implementation_issue)}` : '-';\n\n return `| ${name} | ${topic} | ${metrics} | ${issue} |`;\n}\n\n/**\n * Generate P1 techniques table.\n */\nexport function generateP1Table(index: ResearchIndex): string {\n const p1Techniques = getTechniquesByPriority(index, 'P1');\n\n if (p1Techniques.length === 0) {\n return '';\n }\n\n const rows = p1Techniques.map(generateTechniqueRow);\n\n return `---\n\n## Priority 1 (P1) Techniques\n\nThese techniques are high-impact and align well with the current architecture.\n\n| Technique | Topic | Key Metrics | Issue |\n| --------- | ----- | ----------- | ----- |\n${rows.join('\\n')}`;\n}\n\n/**\n * Generate P2 techniques table.\n */\nexport function generateP2Table(index: ResearchIndex): string {\n const p2Techniques = getTechniquesByPriority(index, 'P2');\n\n if (p2Techniques.length === 0) {\n return '';\n }\n\n const rows = p2Techniques.map(generateTechniqueRow);\n\n return `---\n\n## Priority 2 (P2) Techniques\n\nMedium-impact or requiring moderate changes.\n\n| Technique | Topic | Key Metrics | Issue |\n| --------- | ----- | ----------- | ----- |\n${rows.join('\\n')}`;\n}\n\n// ============================================================================\n// Papers Sections\n// ============================================================================\n\n/**\n * Generate recently reviewed papers section.\n */\nexport function generateRecentPapers(index: ResearchIndex, limit: number): string {\n const recentPapers = getRecentlyReviewedPapers(index, limit);\n\n if (recentPapers.length === 0) {\n return '';\n }\n\n const rows = recentPapers.map((paper) => {\n // url is optional\n const paperUrl = paper.url ?? '';\n const title =\n paperUrl !== ''\n ? `[${paper.title.replace(/\\|/g, '-')}](${paperUrl})`\n : paper.title.replace(/\\|/g, '-');\n // topics has default [] so always defined\n const topic = paper.topics[0] ?? '-';\n const priority = '-'; // Papers don't have priority\n // reviewed_date is optional\n const dateStr = paper.reviewed_date ?? '-';\n return `| ${dateStr} | ${title} | ${topic} | ${priority} |`;\n });\n\n return `---\n\n## Recently Reviewed Papers\n\n| Date | Paper | Topic | Priority |\n| ---- | ----- | ----- | -------- |\n${rows.join('\\n')}`;\n}\n\n/**\n * Generate papers by topic section.\n */\nexport function generatePapersByTopic(index: ResearchIndex): string {\n const topics: ResearchTopic[] = [\n 'consensus',\n 'routing',\n 'memory',\n 'code-generation',\n 'orchestration',\n ];\n\n const sections = topics.map((topic) => {\n const papers = getPapersByTopic(index, topic);\n if (papers.length === 0) {\n return '';\n }\n\n const paperList = papers\n .map((paper) => {\n // url is optional\n const paperUrl = paper.url ?? '';\n const title = paperUrl !== '' ? `[${paper.title}](${paperUrl})` : paper.title;\n // summary is optional\n const summaryText = paper.summary?.trim().split('\\n')[0] ?? '';\n const summaryPart = summaryText !== '' ? ` - ${summaryText}` : '';\n return `- ${title}${summaryPart}`;\n })\n .join('\\n');\n\n return `### ${capitalize(topic.replaceAll('-', ' '))} (${String(papers.length)} papers)\n\n${paperList}`;\n });\n\n const nonEmptySections = sections.filter((s) => s.length > 0);\n\n if (nonEmptySections.length === 0) {\n return '';\n }\n\n return `---\n\n## Papers by Topic\n\n${nonEmptySections.join('\\n\\n')}`;\n}\n\n// ============================================================================\n// Metadata Sections\n// ============================================================================\n\n/**\n * Generate GitHub issues section.\n */\nexport function generateGitHubIssues(index: ResearchIndex): string {\n const techniquesWithIssues = getTechniquesWithIssues(index);\n\n if (techniquesWithIssues.length === 0) {\n return '';\n }\n\n const rows = techniquesWithIssues.map((technique) => {\n // source_papers has default [] so always defined\n const papers = technique.source_papers.length > 0 ? technique.source_papers.join(', ') : '-';\n // implementation_issue is nullable - guaranteed to have value here since filtered\n const issueStr = String(technique.implementation_issue ?? 0);\n return `| #${issueStr} | ${technique.name} | ${papers} |`;\n });\n\n return `---\n\n## GitHub Issues\n\n| Issue | Feature | Related Papers |\n| ----- | ------- | -------------- |\n${rows.join('\\n')}`;\n}\n\n/**\n * Generate search tags section.\n */\nexport function generateSearchTags(index: ResearchIndex): string {\n // Collect all unique tags from techniques (tags has default [] so always defined)\n const allTags = new Set<string>();\n\n for (const technique of index.techniques) {\n for (const tag of technique.tags) {\n allTags.add(tag);\n }\n }\n\n const tagList = Array.from(allTags)\n .sort()\n .slice(0, 20)\n .map((tag) => `\\`#${tag}\\``)\n .join(' ');\n\n return `---\n\n## Search Tags\n\n${tagList}`;\n}\n\n/**\n * Generate registry files section.\n */\nexport function generateRegistryFiles(index: ResearchIndex): string {\n const paperCount = String(index.stats.totalPapers);\n const techniqueCount = String(index.stats.totalTechniques);\n return `---\n\n## Registry Files\n\n- [papers.yaml](registry/papers.yaml) - All ${paperCount} papers with metadata\n- [techniques.yaml](registry/techniques.yaml) - All ${techniqueCount} techniques with status\n- [sources.yaml](registry/sources.yaml) - Product docs and other sources`;\n}\n\n/**\n * Generate how to contribute section.\n */\nexport function generateContributingSection(): string {\n const dateStr = getTimeProvider().nowDateString();\n return `---\n\n## How to Contribute\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on adding new research.\n\n---\n\n_Generated from YAML registries. Last updated: ${dateStr} (ET)_`;\n}\n\n// ============================================================================\n// Section Building Helpers\n// ============================================================================\n\n/**\n * Add a non-empty section to the sections array.\n */\nexport function addSection(sections: string[], section: string): void {\n if (section !== '') {\n sections.push(section);\n }\n}\n\n/**\n * Build optional sections based on options.\n */\nexport function buildOptionalSections(\n index: ResearchIndex,\n opts: ResearchIndexGeneratorOptions\n): string[] {\n const sections: string[] = [];\n\n if (opts.includeP1Table) {\n addSection(sections, generateP1Table(index));\n }\n if (opts.includeP2Table) {\n addSection(sections, generateP2Table(index));\n }\n if (opts.includeRecentPapers) {\n addSection(sections, generateRecentPapers(index, opts.recentPapersLimit));\n }\n if (opts.includePapersByTopic) {\n addSection(sections, generatePapersByTopic(index));\n }\n if (opts.includeGitHubIssues) {\n addSection(sections, generateGitHubIssues(index));\n }\n\n return sections;\n}\n","/**\n * nexus-agents/indexer/research-index - Markdown Generator\n *\n * Generates RESEARCH_INDEX.md from parsed research registry data.\n *\n * (Source: Research Tracking System - docs/research/RESEARCH_INDEX.md)\n */\n\nimport type { Result } from '../../core/result.js';\nimport {\n type ResearchIndex,\n type ResearchIndexGeneratorOptions,\n DEFAULT_RESEARCH_INDEX_GENERATOR_OPTIONS,\n ResearchIndexGeneratorError,\n} from './research-index-types.js';\nimport {\n buildOptionalSections,\n generateContributingSection,\n generateHeader,\n generateQuickStats,\n generateRegistryFiles,\n generateSearchTags,\n generateTopicsTable,\n} from './research-index-generator-helpers.js';\nimport { getErrorMessage } from '../../core/index.js';\n\n// ============================================================================\n// Main Generator Functions\n// ============================================================================\n\n/**\n * Generate the complete RESEARCH_INDEX.md content.\n */\nexport function generateIndexMarkdown(\n index: ResearchIndex,\n options: Partial<ResearchIndexGeneratorOptions> = {}\n): Result<string, ResearchIndexGeneratorError> {\n try {\n const opts = { ...DEFAULT_RESEARCH_INDEX_GENERATOR_OPTIONS, ...options };\n\n const sections: string[] = [\n generateHeader(index),\n generateQuickStats(index),\n generateTopicsTable(index),\n ...buildOptionalSections(index, opts),\n generateSearchTags(index),\n generateRegistryFiles(index),\n generateContributingSection(),\n ];\n\n const markdown = sections.join('\\n\\n');\n\n return { ok: true, value: markdown };\n } catch (error) {\n return {\n ok: false,\n error: new ResearchIndexGeneratorError(\n `Failed to generate markdown: ${getErrorMessage(error)}`,\n error\n ),\n };\n }\n}\n\n/**\n * Generate a JSON stats export.\n */\nexport function generateStatsJson(index: ResearchIndex): string {\n return JSON.stringify(\n {\n schemaVersion: index.schemaVersion,\n generatedAt: index.generatedAt,\n stats: index.stats,\n },\n null,\n 2\n );\n}\n\n/**\n * Generate a summary report (shorter than full markdown).\n */\nexport function generateSummaryReport(index: ResearchIndex): string {\n const { stats } = index;\n const { techniquesByStatus } = stats;\n\n const implementedPercent =\n stats.totalTechniques > 0\n ? Math.round((techniquesByStatus.implemented / stats.totalTechniques) * 100)\n : 0;\n\n const topicLines = stats.topicStats\n .map(\n (t) => `- ${t.topic}: ${String(t.techniqueCount)} techniques, ${String(t.paperCount)} papers`\n )\n .join('\\n');\n\n return `# Research Index Summary\n\n**Generated:** ${index.generatedAt}\n\n## Overview\n- **Total Papers:** ${String(stats.totalPapers)}\n- **Total Techniques:** ${String(stats.totalTechniques)}\n- **Implementation Rate:** ${String(implementedPercent)}%\n\n## Technique Status\n- Implemented: ${String(techniquesByStatus.implemented)}\n- Planned: ${String(techniquesByStatus.planned)}\n- Not Started: ${String(techniquesByStatus.notStarted)}\n- Rejected: ${String(techniquesByStatus.rejected)}\n\n## Evidence Quality Distribution\n${\n stats.qualityDistribution !== undefined\n ? `- High evidence: ${String(stats.qualityDistribution.high)} papers\n- Medium evidence: ${String(stats.qualityDistribution.medium)} papers\n- Low evidence: ${String(stats.qualityDistribution.low)} papers\n- Unscored: ${String(stats.qualityDistribution.unscored)} papers\n- Average quality score: ${String(stats.qualityDistribution.averageScore)}/10`\n : '- Quality scoring not yet applied'\n}\n\n## Topics Coverage\n${topicLines}\n`;\n}\n","/**\n * Research Issue Helpers\n *\n * Functions for creating GitHub issues from research findings.\n * Uses the `gh` CLI tool for issue creation.\n *\n * @module cli/research-helpers-issues\n * (Source: Research System Enhancement - Phase 4)\n */\n\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport type { Result } from '../core/result.js';\nimport { getErrorMessage } from '../core/index.js';\nimport { CLI_SUBPROCESS_TIMEOUTS } from '../config/timeouts.js';\n\nconst execFileAsync = promisify(execFile);\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/** Options for creating a research issue. */\nexport interface CreateResearchIssueOptions {\n /** Issue title */\n readonly title: string;\n /** Issue body */\n readonly body: string;\n /** Labels to apply */\n readonly labels: readonly string[];\n /** Optional assignee */\n readonly assignee?: string;\n}\n\n/** Result of creating a research issue. */\nexport interface CreateResearchIssueResult {\n /** Whether the issue was created successfully */\n readonly success: boolean;\n /** Issue URL (if created) */\n readonly url: string;\n /** Human-readable message */\n readonly message: string;\n}\n\n/** Error for issue creation. */\nexport interface IssueCreationError {\n readonly code: 'GH_NOT_FOUND' | 'GH_AUTH_FAILED' | 'GH_ERROR';\n readonly message: string;\n}\n\n/** Vote result summary for issue body formatting. */\nexport interface VoteResultSummary {\n readonly decision: string;\n readonly approvalPercentage: number;\n readonly strategy: string;\n}\n\n/** Research finding for issue body formatting. */\nexport interface ResearchFinding {\n readonly title: string;\n readonly source: string;\n readonly url: string;\n readonly description: string;\n readonly relevance: string;\n readonly priority?: string;\n}\n\n// =============================================================================\n// ISSUE BODY FORMATTING\n// =============================================================================\n\n/**\n * Format a research issue body from findings and vote results.\n *\n * @param findings - Research findings to include\n * @param voteResult - Optional vote result summary\n * @returns Formatted markdown issue body\n */\nexport function formatResearchIssueBody(\n findings: readonly ResearchFinding[],\n voteResult?: VoteResultSummary\n): string {\n const lines: string[] = [];\n\n lines.push('## Research Findings');\n lines.push('');\n\n for (const finding of findings) {\n lines.push(`### ${finding.title}`);\n lines.push('');\n lines.push(`- **Source:** ${finding.source}`);\n lines.push(`- **URL:** ${finding.url}`);\n lines.push(`- **Relevance:** ${finding.relevance}`);\n if (finding.priority !== undefined) {\n lines.push(`- **Priority:** ${finding.priority}`);\n }\n lines.push('');\n lines.push(finding.description);\n lines.push('');\n }\n\n if (voteResult !== undefined) {\n lines.push('## Consensus Vote Result');\n lines.push('');\n lines.push(`- **Decision:** ${voteResult.decision}`);\n lines.push(`- **Approval:** ${String(voteResult.approvalPercentage)}%`);\n lines.push(`- **Strategy:** ${voteResult.strategy}`);\n lines.push('');\n }\n\n lines.push('---');\n lines.push('*Created by nexus-agents research workflow*');\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// ISSUE CREATION\n// =============================================================================\n\n/** Build gh CLI arguments for issue creation. */\nfunction buildIssueArgs(options: CreateResearchIssueOptions): string[] {\n const args = ['issue', 'create', '--title', options.title, '--body', options.body];\n if (options.labels.length > 0) args.push('--label', options.labels.join(','));\n if (options.assignee !== undefined) args.push('--assignee', options.assignee);\n return args;\n}\n\n/** Map error message to structured error. */\nfunction mapGhError(message: string): IssueCreationError {\n if (message.includes('not found') || message.includes('ENOENT')) {\n return { code: 'GH_NOT_FOUND', message: 'GitHub CLI (gh) not found' };\n }\n if (message.includes('auth') || message.includes('401')) {\n return { code: 'GH_AUTH_FAILED', message: 'GitHub CLI not authenticated' };\n }\n return { code: 'GH_ERROR', message: `Failed to create issue: ${message}` };\n}\n\n/**\n * Create a GitHub issue for research findings.\n *\n * @param options - Issue creation options\n * @returns Result indicating success or failure\n */\nexport async function createResearchIssue(\n options: CreateResearchIssueOptions\n): Promise<Result<CreateResearchIssueResult, IssueCreationError>> {\n try {\n const { stdout } = await execFileAsync('gh', buildIssueArgs(options), {\n timeout: CLI_SUBPROCESS_TIMEOUTS.ghCommandMs,\n });\n const url = stdout.trim();\n return { ok: true, value: { success: true, url, message: `Issue created: ${url}` } };\n } catch (error) {\n const message = getErrorMessage(error);\n return { ok: false, error: mapGhError(message) };\n }\n}\n","/**\n * Unified memory cross-ranker (#3236).\n *\n * `getContextForTask` fans out across ~6 memory backends and returns parallel,\n * independently-ranked lists on incomparable scales — a belief's `confidence`\n * enum, an adaptive entry's priority score, an experience pattern's success\n * rate. A consumer (a voter, a planning step) that wants \"the single most\n * relevant thing we know\" has no way to compare across those lists.\n *\n * This module lexically cross-ranks every per-backend item into ONE comparable,\n * sorted `RankedMemoryItem[]`. It reuses the keyword-coverage relevance pattern\n * from `research-discover.computeRelevanceScore` (a deliberate, cheap lexical\n * score — no embeddings) and combines it with temporal decay and a per-source\n * confidence weight. The aggregate `outcomes` summary is excluded: it is a\n * rollup, not a per-item memory, so it has nothing to cross-rank against.\n *\n * Pure and synchronous: no I/O, no throws. Missing/invalid timestamps degrade\n * to neutral recency rather than failing (fail-soft, #3236 vote condition 5).\n *\n * @module context/context-retriever-helpers\n * (Source: #3236)\n */\n\nimport type { UnifiedContext } from './context-retriever.js';\nimport type { Belief } from './belief-core-types.js';\nimport type { AgenticMemoryEntry } from './agentic-memory-types.js';\nimport type { ScoredMemoryEntry } from './adaptive-memory-types.js';\nimport type { ExperienceEntry } from './mobimem-types.js';\nimport type { DistilledRule } from '../learning/strategy-distiller-types.js';\nimport type { TechniqueStatusSummary } from '../cli/research-types.js';\n\n/** The discriminated set of cross-rankable backends (the aggregate `outcomes` is excluded). */\nexport type RankedMemorySource =\n 'belief' | 'agentic' | 'adaptive' | 'experience' | 'strategy' | 'research';\n\n/** A backend item lifted onto a single comparable scale. */\nexport interface RankedMemoryItem {\n /** Which backend the item came from. */\n readonly source: RankedMemorySource;\n /** Combined cross-source score in [0, 1]; higher is more relevant. */\n readonly relevanceScore: number;\n /** The original backend item, untouched, so consumers can still render its native shape. */\n readonly item:\n | Belief\n | AgenticMemoryEntry\n | ScoredMemoryEntry\n | ExperienceEntry\n | DistilledRule\n | TechniqueStatusSummary\n | string;\n /** Normalized free-text used for lexical scoring + rendering (already a single line). */\n readonly text: string;\n /** Age of the item in milliseconds at ranking time (0 when no timestamp). */\n readonly ageMs: number;\n /** Per-item confidence in [0, 1] (belief enum, rule confidence, success rate, …). */\n readonly sourceConfidence: number;\n}\n\n/** Options for {@link rankMemories}. */\nexport interface RankMemoriesOptions {\n /** Injectable clock for deterministic recency tests. Defaults to `Date.now()`. */\n readonly now?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Scoring weights — PROVISIONAL (#3236).\n//\n// These three weights sum to 1.0 and combine the lexical relevance, temporal\n// decay, and per-source confidence into the final cross-source score. They are\n// a first cut chosen to make text relevance dominate (the consumer is asking\n// \"what's relevant to THIS task\") while letting recency and source confidence\n// break ties and rescue strong-but-older signal. Tune against the ranked-render\n// flag's outcome telemetry before promoting any of these.\n// See https://github.com/nexus-substrate/nexus-agents/issues/3236\n// ---------------------------------------------------------------------------\n/** Weight on lexical text relevance. PROVISIONAL — see #3236. */\nconst W_TEXT = 0.6;\n/** Weight on temporal recency (exponential decay). PROVISIONAL — see #3236. */\nconst W_RECENCY = 0.25;\n/** Weight on per-source confidence. PROVISIONAL — see #3236. */\nconst W_SOURCE = 0.15;\n\n/**\n * Per-source baseline trust applied when an item carries no intrinsic\n * confidence (e.g. an agentic note). PROVISIONAL — see #3236. Beliefs and\n * distilled strategies are the most curated; raw agentic notes the least.\n */\nconst SOURCE_WEIGHT: Readonly<Record<RankedMemorySource, number>> = {\n belief: 0.9,\n strategy: 0.85,\n research: 0.8,\n experience: 0.75,\n adaptive: 0.65,\n agentic: 0.55,\n};\n\n/** Recency half-life: signal older than this contributes ~half its recency score. PROVISIONAL — see #3236. */\nconst RECENCY_HALF_LIFE_MS = 30 * 24 * 60 * 60 * 1000; // 30 days\n\n/** Distinct keywords ≥ this many chars are discriminating enough to score against. */\nconst MIN_KEYWORD_LEN = 3;\n\n/** Rough chars-per-token used to budget the rendered prefix (matches token-counter ~4). */\nconst CHARS_PER_TOKEN = 4;\n\n/**\n * Cross-rank every per-backend list in `ctx` into one comparable, sorted list.\n *\n * Score = W_TEXT·textRelevance + W_RECENCY·decay(ageMs) + W_SOURCE·sourceWeight,\n * where `sourceWeight` blends the per-item confidence with the source baseline.\n * Higher score first; ties fall back to source baseline then text length so the\n * order is deterministic. The aggregate `outcomes` summary is intentionally\n * never included.\n */\nexport function rankMemories(\n ctx: UnifiedContext,\n task: string,\n options: RankMemoriesOptions = {}\n): readonly RankedMemoryItem[] {\n const now = options.now ?? Date.now();\n const keywords = extractKeywords(task);\n\n const normalized: RankedMemoryItem[] = [\n ...ctx.beliefs.map((b) => normalizeBelief(b, now)),\n ...ctx.similarMemories.map((m) => normalizeAgentic(m, now)),\n ...ctx.recentLearnings.map((s) => normalizeAdaptive(s, now)),\n ...ctx.experiencePatterns.map((e) => normalizeExperience(e, now)),\n ...ctx.priorStrategies.map((r) => normalizeStrategy(r, now)),\n ...ctx.researchInsights.map((t) => normalizeResearch(t, now)),\n ];\n\n const scored = normalized.map((n) => ({\n ...n,\n relevanceScore: combinedScore(n, keywords),\n }));\n\n return scored.sort((a, b) => {\n if (b.relevanceScore !== a.relevanceScore) return b.relevanceScore - a.relevanceScore;\n const sw = SOURCE_WEIGHT[b.source] - SOURCE_WEIGHT[a.source];\n if (sw !== 0) return sw;\n return b.text.length - a.text.length;\n });\n}\n\n/**\n * Take items off the front of an already-ranked list until adding the next one\n * would exceed `maxTokens` (estimated). Order-preserving; never throws. A\n * zero/negative budget yields `[]`.\n */\nexport function topRankedWithinBudget(\n items: readonly RankedMemoryItem[],\n maxTokens: number\n): readonly RankedMemoryItem[] {\n if (maxTokens <= 0) return [];\n const kept: RankedMemoryItem[] = [];\n let used = 0;\n for (const item of items) {\n const cost = estimateTokens(item.text);\n if (used + cost > maxTokens) break;\n used += cost;\n kept.push(item);\n }\n return kept;\n}\n\n// ---------------------------------------------------------------------------\n// Scoring internals\n// ---------------------------------------------------------------------------\n\nfunction combinedScore(item: RankedMemoryItem, keywords: readonly string[]): number {\n const text = textRelevance(item.text, keywords);\n const recency = recencyDecay(item.ageMs);\n const source = 0.5 * item.sourceConfidence + 0.5 * SOURCE_WEIGHT[item.source];\n const score = W_TEXT * text + W_RECENCY * recency + W_SOURCE * source;\n return Number.isFinite(score) ? Math.min(1, Math.max(0, score)) : 0;\n}\n\n/**\n * Keyword-coverage relevance in [0, 1], reusing the\n * `research-discover.computeRelevanceScore` pattern: fraction of distinct task\n * keywords present in the item text. No keywords → neutral 0 (recency + source\n * still rank the item).\n */\nfunction textRelevance(text: string, keywords: readonly string[]): number {\n if (keywords.length === 0) return 0;\n const lower = text.toLowerCase();\n let matched = 0;\n for (const kw of keywords) {\n if (lower.includes(kw)) matched++;\n }\n return matched / keywords.length;\n}\n\n/** Exponential decay on age; fail-soft to neutral 0.5 for non-finite ages. */\nfunction recencyDecay(ageMs: number): number {\n if (!Number.isFinite(ageMs) || ageMs < 0) return 0.5;\n return Math.pow(2, -ageMs / RECENCY_HALF_LIFE_MS);\n}\n\nfunction extractKeywords(task: string): readonly string[] {\n return [\n ...new Set(\n task\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((w) => w.length >= MIN_KEYWORD_LEN)\n ),\n ];\n}\n\nfunction estimateTokens(text: string): number {\n return Math.ceil(text.length / CHARS_PER_TOKEN);\n}\n\n/** Result of {@link clampToTokenBudget}. */\nexport interface TokenBudgetClampResult {\n /** The (possibly truncated) text, always a prefix of the input. */\n readonly text: string;\n /** Whether truncation occurred. */\n readonly clipped: boolean;\n /** Chars removed from the input (0 when not clipped). */\n readonly omittedChars: number;\n}\n\n/**\n * Clamp `text` to an estimated `maxTokens` budget using the same char/4\n * heuristic as {@link topRankedWithinBudget} (#4253 — per-call context budget\n * guard). Order-preserving prefix cut; never throws, never grows the input.\n */\nexport function clampToTokenBudget(text: string, maxTokens: number): TokenBudgetClampResult {\n if (maxTokens <= 0) {\n return { text: '', clipped: text.length > 0, omittedChars: text.length };\n }\n const maxChars = maxTokens * CHARS_PER_TOKEN;\n if (text.length <= maxChars) {\n return { text, clipped: false, omittedChars: 0 };\n }\n const kept = text.slice(0, maxChars);\n return { text: kept, clipped: true, omittedChars: text.length - kept.length };\n}\n\n/** Age in ms from a possibly-invalid Date; non-finite timestamps → neutral 0. */\nfunction ageFrom(date: Date | undefined, now: number): number {\n const t = date?.getTime();\n if (t === undefined || !Number.isFinite(t)) return 0;\n return Math.max(0, now - t);\n}\n\n/** Collapse whitespace + cap length so every normalized text is a single bounded line. */\nconst MAX_TEXT_LEN = 200;\nfunction oneLine(value: string): string {\n return value.replace(/\\s+/g, ' ').trim().slice(0, MAX_TEXT_LEN);\n}\n\n// ---------------------------------------------------------------------------\n// Per-source normalization → {text, ageMs, sourceConfidence}\n// ---------------------------------------------------------------------------\n\nconst BELIEF_CONFIDENCE: Readonly<Record<string, number>> = {\n high: 0.9,\n medium: 0.6,\n low: 0.35,\n speculative: 0.15,\n};\n\nfunction normalizeBelief(b: Belief, now: number): RankedMemoryItem {\n return {\n source: 'belief',\n relevanceScore: 0,\n item: b,\n text: oneLine(`${b.subject} ${b.predicate} ${b.object}`),\n ageMs: ageFrom(b.updatedAt, now),\n sourceConfidence: BELIEF_CONFIDENCE[b.confidence] ?? 0.5,\n };\n}\n\nfunction normalizeAgentic(m: AgenticMemoryEntry, now: number): RankedMemoryItem {\n return {\n source: 'agentic',\n relevanceScore: 0,\n item: m,\n text: oneLine(m.attributes.contextDescription),\n ageMs: ageFrom(m.createdAt, now),\n sourceConfidence: 0.5,\n };\n}\n\nfunction normalizeAdaptive(s: ScoredMemoryEntry, now: number): RankedMemoryItem {\n const value = typeof s.entry.value === 'string' ? s.entry.value : s.entry.key;\n return {\n source: 'adaptive',\n relevanceScore: 0,\n item: s,\n text: oneLine(value),\n ageMs: ageFrom(s.entry.createdAt, now),\n sourceConfidence: clamp01(s.priority.components.relevance),\n };\n}\n\nfunction normalizeExperience(e: ExperienceEntry, now: number): RankedMemoryItem {\n return {\n source: 'experience',\n relevanceScore: 0,\n item: e,\n text: oneLine(e.taskType),\n ageMs: ageFrom(e.lastUsedAt, now),\n sourceConfidence: clamp01(e.successRate),\n };\n}\n\nfunction normalizeStrategy(r: DistilledRule, now: number): RankedMemoryItem {\n return {\n source: 'strategy',\n relevanceScore: 0,\n item: r,\n text: oneLine(`${r.category} ${r.patternType} ${r.action} ${r.cli}`),\n ageMs: ageFrom(new Date(r.updatedAt), now),\n sourceConfidence: clamp01(r.confidence),\n };\n}\n\nfunction normalizeResearch(t: TechniqueStatusSummary, now: number): RankedMemoryItem {\n return {\n source: 'research',\n relevanceScore: 0,\n item: t,\n // Research summaries carry no timestamp; treat as neutral-recency (ageMs 0).\n text: oneLine(`${t.name} ${t.topic} ${t.status}`),\n ageMs: ageFrom(undefined, now),\n sourceConfidence: 0.6,\n };\n}\n\nfunction clamp01(n: number): number {\n if (!Number.isFinite(n)) return 0.5;\n return Math.min(1, Math.max(0, n));\n}\n","/**\n * nexus-agents/context - Universal Token Counter\n *\n * Provides token counting across all supported providers using their native APIs\n * or local estimation. Implements caching for repeated content to improve performance.\n *\n * Provider APIs:\n * - Anthropic: /v1/messages/count_tokens (free)\n * - Gemini: countTokens endpoint (free)\n * - OpenAI: tiktoken local library (free)\n *\n * Verified 2026-01-05: tiktoken@1.0.22 is current stable\n * (Source: npm registry)\n */\n\nimport Anthropic from '@anthropic-ai/sdk';\nimport { GoogleGenAI } from '@google/genai';\nimport { type Tiktoken, encoding_for_model } from 'tiktoken';\nimport type { Result, Message } from '../core/index.js';\nimport { ok, err, getTimeProvider } from '../core/index.js';\nimport type {\n TokenCounterConfig,\n TokenCountResult,\n CacheEntry,\n ITokenCounter,\n} from './token-counter-types.js';\nimport {\n TokenCounterProvider,\n TokenCountError,\n CHARS_PER_TOKEN,\n DEFAULT_MAX_CACHE_SIZE,\n DEFAULT_CACHE_TTL_MS,\n TIKTOKEN_MODEL_MAP,\n DEFAULT_TIKTOKEN_MODEL,\n} from './token-counter-types.js';\nimport {\n generateCacheKey,\n messagesToAnthropicFormat,\n extractSystemPrompt,\n} from './token-counter-helpers.js';\n\n// Re-export types for backward compatibility\nexport type {\n TokenCounterConfig,\n TokenCountResult,\n CacheEntry,\n ITokenCounter,\n} from './token-counter-types.js';\nexport {\n TokenCounterProvider,\n TokenCountError,\n CHARS_PER_TOKEN,\n DEFAULT_MAX_CACHE_SIZE,\n DEFAULT_CACHE_TTL_MS,\n TIKTOKEN_MODEL_MAP,\n DEFAULT_TIKTOKEN_MODEL,\n} from './token-counter-types.js';\n\n// ============================================================================\n// Token Counter Implementation\n// ============================================================================\n\n/**\n * Universal token counter supporting multiple providers.\n *\n * Provides accurate token counting via provider APIs (Anthropic, Gemini)\n * or local tiktoken (OpenAI), with fallback to character-based estimation.\n *\n * @example\n * ```typescript\n * const counter = new TokenCounter({\n * anthropicApiKey: process.env.ANTHROPIC_API_KEY,\n * googleApiKey: process.env.GOOGLE_AI_API_KEY,\n * });\n *\n * // Count via Anthropic API\n * const result = await counter.countAnthropic(messages, 'claude-sonnet-4');\n *\n * // Count via local tiktoken\n * const openaiResult = counter.countOpenAI('Hello world', 'gpt-4o');\n *\n * // Offline estimation\n * const estimate = counter.estimate('Some text');\n * ```\n */\nexport class TokenCounter implements ITokenCounter {\n private readonly anthropicClient: Anthropic | undefined;\n private readonly geminiClient: GoogleGenAI | undefined;\n private readonly cache: Map<string, CacheEntry>;\n private readonly maxCacheSize: number;\n private readonly cacheTtlMs: number;\n private tiktokenEncoder: Tiktoken | undefined;\n private currentTiktokenModel: string | undefined;\n\n /**\n * Creates a new TokenCounter instance.\n *\n * @param config - Token counter configuration\n */\n constructor(config: TokenCounterConfig = {}) {\n this.maxCacheSize = config.maxCacheSize ?? DEFAULT_MAX_CACHE_SIZE;\n this.cacheTtlMs = config.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;\n this.cache = new Map();\n\n // Initialize Anthropic client if API key provided\n if (config.anthropicApiKey !== undefined && config.anthropicApiKey !== '') {\n this.anthropicClient = new Anthropic({ apiKey: config.anthropicApiKey });\n }\n\n // Initialize Gemini client if API key provided\n if (config.googleApiKey !== undefined && config.googleApiKey !== '') {\n this.geminiClient = new GoogleGenAI({ apiKey: config.googleApiKey });\n }\n }\n\n /**\n * Count tokens for Anthropic/Claude models via API.\n */\n async countAnthropic(\n messages: Message[],\n model: string\n ): Promise<Result<TokenCountResult, TokenCountError>> {\n // Check cache first\n const cacheKey = generateCacheKey(messages, TokenCounterProvider.ANTHROPIC, model);\n const cached = this.getCached(cacheKey);\n if (cached !== undefined) {\n return ok({ count: cached.count, cached: true, provider: cached.provider, model });\n }\n\n // Validate client availability\n if (this.anthropicClient === undefined) {\n return err(\n new TokenCountError('Anthropic API key not configured', {\n context: { provider: 'anthropic', model },\n })\n );\n }\n\n try {\n const anthropicMessages = messagesToAnthropicFormat(messages);\n const systemPrompt = extractSystemPrompt(messages);\n\n const params: Anthropic.Messages.MessageCountTokensParams = {\n model,\n messages: anthropicMessages,\n };\n\n if (systemPrompt !== undefined) {\n params.system = systemPrompt;\n }\n\n const response = await this.anthropicClient.messages.countTokens(params);\n const count = response.input_tokens;\n\n // Cache result\n this.setCache(cacheKey, {\n count,\n provider: TokenCounterProvider.ANTHROPIC,\n model,\n timestamp: getTimeProvider().now(),\n });\n\n return ok({ count, cached: false, provider: TokenCounterProvider.ANTHROPIC, model });\n } catch (error) {\n const cause = error instanceof Error ? error : new Error(String(error));\n return err(\n new TokenCountError(`Anthropic token counting failed: ${cause.message}`, {\n cause,\n context: { provider: 'anthropic', model },\n })\n );\n }\n }\n\n /**\n * Count tokens for Gemini models via API.\n */\n async countGemini(\n content: string,\n model: string\n ): Promise<Result<TokenCountResult, TokenCountError>> {\n // Check cache first\n const cacheKey = generateCacheKey(content, TokenCounterProvider.GEMINI, model);\n const cached = this.getCached(cacheKey);\n if (cached !== undefined) {\n return ok({ count: cached.count, cached: true, provider: cached.provider, model });\n }\n\n // Validate client availability\n if (this.geminiClient === undefined) {\n return err(\n new TokenCountError('Google API key not configured', {\n context: { provider: 'gemini', model },\n })\n );\n }\n\n try {\n const response = await this.geminiClient.models.countTokens({\n model,\n contents: content,\n });\n const count = response.totalTokens ?? 0;\n\n // Cache result\n this.setCache(cacheKey, {\n count,\n provider: TokenCounterProvider.GEMINI,\n model,\n timestamp: getTimeProvider().now(),\n });\n\n return ok({ count, cached: false, provider: TokenCounterProvider.GEMINI, model });\n } catch (error) {\n const cause = error instanceof Error ? error : new Error(String(error));\n return err(\n new TokenCountError(`Gemini token counting failed: ${cause.message}`, {\n cause,\n context: { provider: 'gemini', model },\n })\n );\n }\n }\n\n /**\n * Count tokens for OpenAI models using local tiktoken.\n */\n countOpenAI(\n text: string,\n model: string = DEFAULT_TIKTOKEN_MODEL\n ): Result<TokenCountResult, TokenCountError> {\n // Check cache first\n const cacheKey = generateCacheKey(text, TokenCounterProvider.OPENAI, model);\n const cached = this.getCached(cacheKey);\n if (cached !== undefined) {\n return ok({ count: cached.count, cached: true, provider: cached.provider, model });\n }\n\n try {\n const encoder = this.getOrCreateTiktokenEncoder(model);\n const tokens = encoder.encode(text);\n const count = tokens.length;\n\n // Cache result\n this.setCache(cacheKey, {\n count,\n provider: TokenCounterProvider.OPENAI,\n model,\n timestamp: getTimeProvider().now(),\n });\n\n return ok({ count, cached: false, provider: TokenCounterProvider.OPENAI, model });\n } catch (error) {\n const cause = error instanceof Error ? error : new Error(String(error));\n return err(\n new TokenCountError(`OpenAI token counting failed: ${cause.message}`, {\n cause,\n context: { provider: 'openai', model },\n })\n );\n }\n }\n\n /**\n * Estimate tokens offline using character-based heuristic.\n * Uses ~4 characters per token as a general approximation.\n */\n estimate(text: string): number {\n if (text.length === 0) {\n return 0;\n }\n return Math.ceil(text.length / CHARS_PER_TOKEN.default);\n }\n\n /**\n * Estimate tokens for a specific provider.\n */\n estimateForProvider(text: string, provider: TokenCounterProvider): number {\n if (text.length === 0) {\n return 0;\n }\n const charsPerToken = CHARS_PER_TOKEN[provider];\n return Math.ceil(text.length / charsPerToken);\n }\n\n /**\n * Clear the token count cache.\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * Get current cache statistics.\n */\n getCacheStats(): { size: number; maxSize: number; ttlMs: number } {\n return {\n size: this.cache.size,\n maxSize: this.maxCacheSize,\n ttlMs: this.cacheTtlMs,\n };\n }\n\n /**\n * Gets or creates a tiktoken encoder for the specified model.\n */\n private getOrCreateTiktokenEncoder(model: string): Tiktoken {\n // Map model to tiktoken model name\n const tiktokenModel = TIKTOKEN_MODEL_MAP[model] ?? DEFAULT_TIKTOKEN_MODEL;\n\n // Reuse encoder if same model\n if (this.tiktokenEncoder !== undefined && this.currentTiktokenModel === tiktokenModel) {\n return this.tiktokenEncoder;\n }\n\n // Free previous encoder\n if (this.tiktokenEncoder !== undefined) {\n this.tiktokenEncoder.free();\n }\n\n // Create new encoder\n // encoding_for_model expects TiktokenModel type\n this.tiktokenEncoder = encoding_for_model(\n tiktokenModel as Parameters<typeof encoding_for_model>[0]\n );\n this.currentTiktokenModel = tiktokenModel;\n\n return this.tiktokenEncoder;\n }\n\n /**\n * Gets a cached entry if valid.\n */\n private getCached(key: string): CacheEntry | undefined {\n const entry = this.cache.get(key);\n if (entry === undefined) {\n return undefined;\n }\n\n // Check TTL\n if (getTimeProvider().now() - entry.timestamp > this.cacheTtlMs) {\n this.cache.delete(key);\n return undefined;\n }\n\n return entry;\n }\n\n /**\n * Sets a cache entry, evicting oldest if at capacity.\n */\n private setCache(key: string, entry: CacheEntry): void {\n // Evict oldest entries if at capacity\n if (this.cache.size >= this.maxCacheSize) {\n const firstKey = this.cache.keys().next();\n if (firstKey.done !== true) {\n this.cache.delete(firstKey.value);\n }\n }\n\n this.cache.set(key, entry);\n }\n\n /**\n * Frees resources (tiktoken encoder).\n * Call this when done with the counter.\n */\n dispose(): void {\n if (this.tiktokenEncoder !== undefined) {\n this.tiktokenEncoder.free();\n this.tiktokenEncoder = undefined;\n this.currentTiktokenModel = undefined;\n }\n this.cache.clear();\n }\n}\n\n/**\n * Creates a TokenCounter instance with the specified configuration.\n *\n * @param config - Token counter configuration\n * @returns Configured TokenCounter instance\n *\n * @example\n * ```typescript\n * const counter = createTokenCounter({\n * anthropicApiKey: process.env.ANTHROPIC_API_KEY,\n * googleApiKey: process.env.GOOGLE_AI_API_KEY,\n * });\n * ```\n */\nexport function createTokenCounter(config: TokenCounterConfig = {}): TokenCounter {\n return new TokenCounter(config);\n}\n","/**\n * nexus-agents/context - Token Counter Types\n *\n * Type definitions for universal token counting.\n *\n * @module context/token-counter-types\n */\n\nimport type { Result, Message } from '../core/index.js';\nimport { NexusError, ErrorCode } from '../core/index.js';\n\n// ============================================================================\n// Provider Types\n// ============================================================================\n\n/**\n * Supported model families for token counting.\n */\nexport const TokenCounterProvider = {\n ANTHROPIC: 'anthropic',\n GEMINI: 'gemini',\n OPENAI: 'openai',\n} as const;\n\nexport type TokenCounterProvider = (typeof TokenCounterProvider)[keyof typeof TokenCounterProvider];\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\n/**\n * Error specific to token counting operations.\n */\nexport class TokenCountError extends NexusError {\n constructor(message: string, options?: { cause?: Error; context?: Record<string, unknown> }) {\n super(message, { code: ErrorCode.MODEL_ERROR, ...options });\n this.name = 'TokenCountError';\n }\n}\n\n// ============================================================================\n// Configuration Types\n// ============================================================================\n\n/**\n * Configuration for the token counter.\n */\nexport interface TokenCounterConfig {\n /** Anthropic API key (optional, required for Anthropic counting) */\n anthropicApiKey?: string;\n /** Google API key (optional, required for Gemini counting) */\n googleApiKey?: string;\n /** Maximum cache entries (default: 1000) */\n maxCacheSize?: number;\n /** Cache TTL in milliseconds (default: 5 minutes) */\n cacheTtlMs?: number;\n}\n\n// ============================================================================\n// Result Types\n// ============================================================================\n\n/**\n * Token counting result with metadata.\n */\nexport interface TokenCountResult {\n /** Number of tokens */\n count: number;\n /** Whether the result was from cache */\n cached: boolean;\n /** Provider used for counting */\n provider: TokenCounterProvider | 'estimate';\n /** Model used (if applicable) */\n model?: string;\n}\n\n/**\n * Cache entry for token counts.\n */\nexport interface CacheEntry {\n count: number;\n provider: TokenCounterProvider | 'estimate';\n model?: string;\n timestamp: number;\n}\n\n// ============================================================================\n// Interface\n// ============================================================================\n\n/**\n * Interface for token counting operations.\n */\nexport interface ITokenCounter {\n /**\n * Count tokens for Anthropic/Claude models via API.\n * @param messages - Messages to count tokens for\n * @param model - Model identifier (e.g., 'claude-sonnet-4')\n * @returns Promise with token count result\n */\n countAnthropic(\n messages: Message[],\n model: string\n ): Promise<Result<TokenCountResult, TokenCountError>>;\n\n /**\n * Count tokens for Gemini models via API.\n * @param content - Text content to count tokens for\n * @param model - Model identifier (e.g., 'gemini-2.0-flash')\n * @returns Promise with token count result\n */\n countGemini(content: string, model: string): Promise<Result<TokenCountResult, TokenCountError>>;\n\n /**\n * Count tokens for OpenAI models using local tiktoken.\n * @param text - Text to count tokens for\n * @param model - Model identifier (default: 'gpt-4o')\n * @returns Token count result (synchronous, local)\n */\n countOpenAI(text: string, model?: string): Result<TokenCountResult, TokenCountError>;\n\n /**\n * Estimate tokens offline using character-based heuristic.\n * @param text - Text to estimate tokens for\n * @returns Estimated token count\n */\n estimate(text: string): number;\n\n /**\n * Clear the token count cache.\n */\n clearCache(): void;\n\n /**\n * Get current cache statistics.\n */\n getCacheStats(): { size: number; maxSize: number; ttlMs: number };\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Characters per token estimates by provider.\n * (Source: Provider documentation and empirical testing)\n */\nexport const CHARS_PER_TOKEN = {\n anthropic: 3.5, // Claude models\n gemini: 4.0, // Gemini models\n openai: 4.0, // GPT models\n default: 4.0, // Generic fallback\n} as const;\n\n/**\n * Default maximum cache entries.\n */\nexport const DEFAULT_MAX_CACHE_SIZE = 1000;\n\n/**\n * Default cache TTL (5 minutes).\n */\nexport const DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000;\n\n/**\n * Default tiktoken model for encoding fallback (uses o200k_base encoding).\n * NOTE: This is a tiktoken library model name, not a nexus-agents model ID.\n * It maps to the o200k_base encoding used for token counting.\n */\nexport const DEFAULT_TIKTOKEN_MODEL = 'gpt-4o';\n\n/**\n * Tiktoken model mappings for OpenAI token counting.\n * Maps OpenAI model names to tiktoken encoding model names.\n * NOTE: These are tiktoken library identifiers, not nexus-agents model IDs.\n * They exist outside the canonical model registry intentionally.\n */\nexport const TIKTOKEN_MODEL_MAP: Record<string, string> = {\n 'gpt-4o': 'gpt-4o',\n 'gpt-4o-mini': 'gpt-4o',\n 'gpt-4-turbo': 'gpt-4-turbo',\n 'gpt-4': 'gpt-4',\n 'gpt-3.5-turbo': 'gpt-3.5-turbo',\n o1: 'o1',\n 'o1-mini': 'o1',\n 'o1-preview': 'o1',\n} as const;\n","/**\n * Per-call token ledger tagged by context-source (#4252, Phase 0 of epic #4251).\n *\n * Why: the token-optimization vote (#4251) found that without a per-call,\n * per-source token record, none of the claimed savings from later phases\n * (#4253 per-call context caps, #4254 repo-map) are falsifiable — there is\n * no baseline to diff against. `TokenBudgetTracker` (`token-budget-tracker.ts`)\n * already tracks usage, but only as a running SESSION/task total — it cannot\n * answer \"how many tokens came from the memory backends vs. a raw grep vs.\n * research synthesis, for this one call.\" This module adds that dimension.\n *\n * ## Extend, don't fork\n *\n * This deliberately reuses rather than reinvents:\n * - **Fields**: `inputTokens`/`outputTokens`/`taskId` mirror\n * {@link TokenUsageRecord} in `token-budget-tracker.ts` — this is the same\n * vocabulary, widened with `tool` and `contextSource` (the two dimensions\n * {@link TokenBudgetTracker} does not carry per-event).\n * - **Estimation**: callers that need to turn rendered text into a token count\n * (e.g. the `context-retriever.ts` wiring, #4252 acceptance) should use\n * {@link TokenCounter.estimate} (`token-counter.ts`) rather than a third\n * copy of the chars-per-token heuristic.\n * - **Persistence**: the shared {@link JsonlStore} primitive (`config/jsonl-store`,\n * #3762) — the same hydrate-on-construct / append-on-write / Zod-validate-\n * each-line mechanism that backs {@link PersistentOutcomeStore}, the\n * `ci-health` event log, and `governance/tool-fitness-ledger.ts` (#3851),\n * which this module's shape most closely mirrors. Bounded by\n * oldest-eviction rotation so the file can never grow without limit.\n * - **Path**: resolves via {@link nexusDataPath} at `token-ledger/ledger.jsonl`.\n * `token-ledger` is NOT in `PER_REPO_SUBDIRS`, so it routes cross-repo\n * (homedir-scoped) like `tool-fitness` — token usage is an operator-wide\n * telemetry signal, not scoped to one codebase.\n * - Append is best-effort: a telemetry sink must never throw into the\n * operation it observes (inherited from the JsonlStore contract).\n *\n * ## Scope\n *\n * DATA LAYER + a minimal query surface ({@link TokenLedger.summarize}). The\n * full A/B diff harness that fixes a task sample and diffs `getContextForTask`\n * token counts across two configurations (the #4251 acceptance criterion) is\n * OUT of scope for this issue — `summarize()` accepts a `{ sinceMs, untilMs }`\n * window so a before/after comparison is already possible by calling it twice\n * with windows that bracket a change (e.g. a deploy timestamp). The dedicated\n * harness is a documented follow-up tracked under epic #4251.\n *\n * @module context/token-ledger\n */\n\nimport { z } from 'zod';\n\nimport { JsonlStore } from '../config/jsonl-store.js';\nimport { nexusDataPath } from '../config/nexus-data-dir.js';\n\n// ============================================================================\n// Context-source tags\n// ============================================================================\n\n/**\n * Known context-source tags (#4252). This list documents the vocabulary call\n * sites should draw from — it is NOT a closed enum enforced by the schema\n * (see {@link TokenLedgerEventSchema}), so a later phase can introduce a new\n * tag (e.g. #4254's repo-map, already listed here in anticipation) without a\n * ledger schema migration.\n */\nexport const CONTEXT_SOURCE_TAGS = [\n /** Assembled context from `getContextForTask` / the shared memory backends. */\n 'memory-backend',\n /** Content synthesized from the research registry/pipeline. */\n 'research-synthesis',\n /** Content from a repo-map / codebase-structure summary (#4254). */\n 'repo-map',\n /** Unclassified free-text input (e.g. a raw grep/file dump). */\n 'raw',\n /** Output returned by a tool call, fed back in as input elsewhere. */\n 'tool-output',\n /** System-prompt / instruction scaffolding, not task-specific content. */\n 'system',\n] as const;\n\n/** A known context-source tag. See {@link CONTEXT_SOURCE_TAGS}. */\nexport type ContextSourceTag = (typeof CONTEXT_SOURCE_TAGS)[number];\n\n// ============================================================================\n// Schema\n// ============================================================================\n\n/**\n * One recorded per-call token event. Versioned (`v`) for forward-compatible\n * on-disk evolution, matching the `tool-fitness` / `ci-health` event idiom.\n * `contextSource` is a bounded-length string rather than a `z.enum` of\n * {@link CONTEXT_SOURCE_TAGS} so a future tag never fails validation and gets\n * silently dropped by {@link JsonlStore} (see its `append` contract).\n */\nexport const TokenLedgerEventSchema = z.object({\n /** Schema version. Forward-compat for on-disk evolution. */\n v: z.literal(1),\n /** ISO-8601 timestamp of the call. */\n ts: z.iso.datetime(),\n /** Tool/call-site identifier (e.g. an MCP tool name or module.function). */\n tool: z.string().min(1).max(200),\n /** Context-source classification. See {@link CONTEXT_SOURCE_TAGS}. */\n contextSource: z.string().min(1).max(64),\n /** Input tokens attributed to this call/source. */\n inputTokens: z.number().nonnegative(),\n /** Output tokens attributed to this call. `0` when the call is context-only. */\n outputTokens: z.number().nonnegative(),\n /** Model identifier, when the calling surface exposes one. */\n model: z.string().min(1).max(200).optional(),\n /** Task/operation identifier, mirroring {@link TokenUsageRecord.taskId}. */\n taskId: z.string().min(1).max(200).optional(),\n /**\n * Free-form call-site variant (e.g. `'ranked' | 'legacy'` for the\n * `context-retriever.ts` rendering path, #4252 wiring). Optional dimension\n * so producers that have no variant to report don't need a placeholder.\n */\n variant: z.string().min(1).max(100).optional(),\n});\nexport type TokenLedgerEvent = z.infer<typeof TokenLedgerEventSchema>;\n\n// ============================================================================\n// Aggregates\n// ============================================================================\n\n/** Summed token counts for one group (a source tag, a tool, or the whole ledger). */\nexport interface TokenLedgerAggregate {\n /** Number of recorded calls in this group. */\n readonly entries: number;\n /** Sum of `inputTokens`. */\n readonly inputTokens: number;\n /** Sum of `outputTokens`. */\n readonly outputTokens: number;\n /** `inputTokens + outputTokens`. */\n readonly totalTokens: number;\n}\n\n/** Result of {@link TokenLedger.summarize} — the #4252 query surface. */\nexport interface TokenLedgerSummary {\n /** Totals across every event in the queried window. */\n readonly overall: TokenLedgerAggregate;\n /** Totals grouped by `contextSource` tag. */\n readonly bySource: Readonly<Record<string, TokenLedgerAggregate>>;\n /** Totals grouped by `tool`. */\n readonly byTool: Readonly<Record<string, TokenLedgerAggregate>>;\n}\n\n/** Optional time window for {@link TokenLedger.summarize}. Both bounds are epoch ms. */\nexport interface TokenLedgerWindow {\n /** Inclusive lower bound. Omit for no lower bound. */\n readonly sinceMs?: number;\n /** Exclusive upper bound. Omit for no upper bound. */\n readonly untilMs?: number;\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\n/** Default retained-event cap. Bounds disk + hydrate cost (the #3089 concern). */\nconst DEFAULT_MAX_EVENTS = 50_000;\n\n/** Subdir + file name under the nexus data dir (cross-repo / homedir-scoped). */\nconst LEDGER_SUBDIR = 'token-ledger';\nconst LEDGER_FILE = 'ledger.jsonl';\n\nexport interface TokenLedgerConfig {\n /**\n * Absolute path to the JSONL file. Defaults to\n * `<nexusDataDir>/token-ledger/ledger.jsonl`. Pass an explicit path in tests\n * to isolate from the real data dir.\n */\n readonly filePath?: string;\n /** Max retained events before oldest-eviction. Defaults to {@link DEFAULT_MAX_EVENTS}. */\n readonly maxEvents?: number;\n}\n\n// ============================================================================\n// Ledger\n// ============================================================================\n\n/**\n * Per-call token ledger. A thin record/aggregate/query API over the shared\n * {@link JsonlStore} primitive — it owns the token-ledger SCHEMA and\n * aggregation, and delegates all persistence plumbing to JsonlStore.\n */\nexport class TokenLedger {\n private readonly store: JsonlStore<TokenLedgerEvent>;\n\n constructor(config?: TokenLedgerConfig) {\n this.store = new JsonlStore<TokenLedgerEvent>({\n filePath: config?.filePath ?? nexusDataPath(LEDGER_SUBDIR, LEDGER_FILE),\n schema: TokenLedgerEventSchema,\n maxRecords: config?.maxEvents ?? DEFAULT_MAX_EVENTS,\n component: 'TokenLedger',\n });\n }\n\n /**\n * Record one call's token usage. `v`/`ts` are stamped here so callers pass\n * only the observed signal. Best-effort durability (inherited from\n * JsonlStore): never throws into the observed operation.\n */\n record(event: {\n tool: string;\n contextSource: string;\n inputTokens: number;\n outputTokens?: number;\n model?: string;\n taskId?: string;\n variant?: string;\n /** Override the timestamp (defaults to now). Mainly for tests/backfill. */\n ts?: string;\n }): void {\n const record: TokenLedgerEvent = {\n v: 1,\n ts: event.ts ?? new Date().toISOString(),\n tool: event.tool,\n contextSource: event.contextSource,\n inputTokens: event.inputTokens,\n outputTokens: event.outputTokens ?? 0,\n ...(event.model !== undefined ? { model: event.model } : {}),\n ...(event.taskId !== undefined ? { taskId: event.taskId } : {}),\n ...(event.variant !== undefined ? { variant: event.variant } : {}),\n };\n this.store.append(record);\n }\n\n /** Total retained events. */\n size(): number {\n return this.store.count();\n }\n\n /** All retained events, oldest first. Mainly for tests/inspection. */\n all(): readonly TokenLedgerEvent[] {\n return this.store.all();\n }\n\n /**\n * Aggregate totals by `contextSource` tag and by `tool`, optionally\n * restricted to a time window (#4252 query surface). Pure over the current\n * retained event set — no I/O.\n *\n * Manual before/after comparison (the #4251 A/B measurement need) is\n * possible today by calling this twice with windows that bracket a change,\n * e.g. `summarize({ untilMs: deployedAt })` vs.\n * `summarize({ sinceMs: deployedAt })`. A dedicated harness that fixes a\n * task sample and runs it under two configurations is deliberately out of\n * scope here — tracked as a follow-up under epic #4251.\n */\n summarize(window: TokenLedgerWindow = {}): TokenLedgerSummary {\n const events = this.store.all().filter((e) => withinWindow(e.ts, window));\n return aggregateEvents(events);\n }\n}\n\n/** Whether an ISO timestamp falls within `window`. Missing bounds never exclude. */\nfunction withinWindow(ts: string, window: TokenLedgerWindow): boolean {\n const t = Date.parse(ts);\n if (window.sinceMs !== undefined && t < window.sinceMs) return false;\n if (window.untilMs !== undefined && t >= window.untilMs) return false;\n return true;\n}\n\n/** A zeroed {@link TokenLedgerAggregate}. */\nfunction emptyAggregate(): TokenLedgerAggregate {\n return { entries: 0, inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n}\n\n/** Fold one event into an aggregate. Pure. */\nfunction addEvent(agg: TokenLedgerAggregate, e: TokenLedgerEvent): TokenLedgerAggregate {\n return {\n entries: agg.entries + 1,\n inputTokens: agg.inputTokens + e.inputTokens,\n outputTokens: agg.outputTokens + e.outputTokens,\n totalTokens: agg.totalTokens + e.inputTokens + e.outputTokens,\n };\n}\n\n/** Fold an event list into overall + by-source + by-tool aggregates. Pure. */\nfunction aggregateEvents(events: readonly TokenLedgerEvent[]): TokenLedgerSummary {\n let overall = emptyAggregate();\n const bySource = new Map<string, TokenLedgerAggregate>();\n const byTool = new Map<string, TokenLedgerAggregate>();\n for (const e of events) {\n overall = addEvent(overall, e);\n bySource.set(e.contextSource, addEvent(bySource.get(e.contextSource) ?? emptyAggregate(), e));\n byTool.set(e.tool, addEvent(byTool.get(e.tool) ?? emptyAggregate(), e));\n }\n return {\n overall,\n bySource: Object.fromEntries(bySource),\n byTool: Object.fromEntries(byTool),\n };\n}\n\n// ============================================================================\n// Singleton\n// ============================================================================\n\nlet singleton: TokenLedger | undefined;\n\n/**\n * Process-wide ledger backed by the default on-disk path. Lazily constructed\n * so tests that never touch it don't create a data dir. Tests that DO\n * exercise persistence should construct their own {@link TokenLedger} with an\n * explicit `filePath` to stay isolated.\n */\nexport function getTokenLedger(): TokenLedger {\n singleton ??= new TokenLedger();\n return singleton;\n}\n\n/** Test helper — drops the process singleton so the next get reconstructs it. */\nexport function _resetTokenLedgerForTests(): void {\n singleton = undefined;\n}\n","/**\n * nexus-agents/indexer - Category Detection\n *\n * File category detection utilities based on path and content.\n *\n * (Source: Issue #240)\n */\n\nimport type { SourceFile } from 'ts-morph';\nimport * as path from 'node:path';\nimport type { FileCategory } from './types.js';\n\n/** File name suffix patterns mapped to categories. */\nconst FILE_SUFFIX_PATTERNS: ReadonlyArray<[string, FileCategory]> = [\n ['.test.ts', 'test'],\n ['.spec.ts', 'test'],\n ['-types.ts', 'types'],\n ['.types.ts', 'types'],\n ['-command.ts', 'cli'],\n];\n\n/** File name/directory patterns for category detection. */\nconst FILE_PATH_PATTERNS: ReadonlyArray<{\n test: (f: string, d: string) => boolean;\n category: FileCategory;\n}> = [\n { test: (f) => f === 'index.ts', category: 'index' },\n { test: (_, d) => d.includes('/cli'), category: 'cli' },\n { test: (f, d) => d.includes('config') || f.includes('config'), category: 'config' },\n { test: (f) => f.includes('helper') || f.includes('util'), category: 'util' },\n];\n\n/** Detects category from file path patterns. */\nfunction detectCategoryFromPath(fileName: string, dirName: string): FileCategory | undefined {\n for (const [suffix, category] of FILE_SUFFIX_PATTERNS) {\n if (fileName.endsWith(suffix)) return category;\n }\n for (const { test, category } of FILE_PATH_PATTERNS) {\n if (test(fileName, dirName)) return category;\n }\n return undefined;\n}\n\n/** Detects if file is types-only based on content. */\nfunction isTypesOnlyFile(sourceFile: SourceFile): boolean {\n const typeCount = sourceFile.getTypeAliases().length + sourceFile.getInterfaces().length;\n const implCount =\n sourceFile.getFunctions().length +\n sourceFile.getClasses().length +\n sourceFile.getVariableDeclarations().length;\n return typeCount > 0 && implCount === 0;\n}\n\n/**\n * Detects the category of a file based on its path and content.\n */\nexport function detectFileCategory(filePath: string, sourceFile: SourceFile): FileCategory {\n const pathCategory = detectCategoryFromPath(path.basename(filePath), path.dirname(filePath));\n if (pathCategory !== undefined) return pathCategory;\n if (isTypesOnlyFile(sourceFile)) return 'types';\n return 'implementation';\n}\n","/**\n * nexus-agents/indexer - Export Extraction\n *\n * Export extraction utilities from TypeScript source files.\n *\n * (Source: Issue #240)\n */\n\nimport type { SourceFile } from 'ts-morph';\nimport type { ExportEntry } from './types.js';\n\n/** Export collection state passed to helper functions. */\ninterface ExportState {\n readonly exports: ExportEntry[];\n readonly seenNames: Set<string>;\n}\n\n/** Adds an export entry if not already seen. */\nfunction addExport(\n state: ExportState,\n name: string,\n kind: ExportEntry['kind'],\n reExportInfo?: { sourceModule: string }\n): void {\n if (state.seenNames.has(name)) return;\n state.seenNames.add(name);\n const entry: ExportEntry = { name, kind, isReExport: reExportInfo !== undefined };\n if (reExportInfo !== undefined)\n (entry as { sourceModule: string }).sourceModule = reExportInfo.sourceModule;\n state.exports.push(entry);\n}\n\n/** Extracts function and class exports. */\nfunction extractFunctionClassExports(sourceFile: SourceFile, state: ExportState): void {\n for (const fn of sourceFile.getFunctions()) {\n if (fn.isExported()) {\n const name = fn.getName();\n if (name !== undefined) addExport(state, name, 'function');\n }\n }\n for (const cls of sourceFile.getClasses()) {\n if (cls.isExported()) {\n const name = cls.getName();\n if (name !== undefined) addExport(state, name, 'class');\n }\n }\n}\n\n/** Extracts type, interface, and enum exports. */\nfunction extractTypeExports(sourceFile: SourceFile, state: ExportState): void {\n for (const iface of sourceFile.getInterfaces()) {\n if (iface.isExported()) addExport(state, iface.getName(), 'interface');\n }\n for (const typeAlias of sourceFile.getTypeAliases()) {\n if (typeAlias.isExported()) addExport(state, typeAlias.getName(), 'type');\n }\n for (const enumDecl of sourceFile.getEnums()) {\n if (enumDecl.isExported()) addExport(state, enumDecl.getName(), 'enum');\n }\n}\n\n/** Extracts variable (const) exports. */\nfunction extractVariableExports(sourceFile: SourceFile, state: ExportState): void {\n for (const varStmt of sourceFile.getVariableStatements()) {\n if (varStmt.isExported()) {\n for (const decl of varStmt.getDeclarations()) addExport(state, decl.getName(), 'const');\n }\n }\n}\n\n/** Extracts re-exports (export { foo } from './bar'). */\nfunction extractReExports(sourceFile: SourceFile, state: ExportState): void {\n for (const exportDecl of sourceFile.getExportDeclarations()) {\n const moduleSpecifier = exportDecl.getModuleSpecifierValue();\n const namedExports = exportDecl.getNamedExports();\n const reExportInfo =\n moduleSpecifier !== undefined ? { sourceModule: moduleSpecifier } : undefined;\n for (const namedExport of namedExports) {\n const name = namedExport.getAliasNode()?.getText() ?? namedExport.getName();\n addExport(state, name, 'unknown', reExportInfo);\n }\n if (namedExports.length === 0 && reExportInfo !== undefined) {\n addExport(state, '*', 'unknown', reExportInfo);\n }\n }\n}\n\n/**\n * Extracts all exports from a source file.\n */\nexport function extractExports(sourceFile: SourceFile): ExportEntry[] {\n const state: ExportState = { exports: [], seenNames: new Set<string>() };\n extractFunctionClassExports(sourceFile, state);\n extractTypeExports(sourceFile, state);\n extractVariableExports(sourceFile, state);\n extractReExports(sourceFile, state);\n return state.exports;\n}\n","/**\n * nexus-agents/indexer - Dependency Extraction\n *\n * Dependency and import extraction utilities.\n *\n * (Source: Issue #240)\n */\n\nimport type { SourceFile } from 'ts-morph';\nimport type { DependencyEntry } from './types.js';\n\n/**\n * Determines if an import specifier is external (from node_modules).\n */\nfunction isExternalImport(specifier: string): boolean {\n // Relative imports start with . or /\n if (specifier.startsWith('.') || specifier.startsWith('/')) {\n return false;\n }\n // Node built-ins\n if (specifier.startsWith('node:')) {\n return true;\n }\n // Everything else is external (npm packages)\n return true;\n}\n\n/**\n * Extracts all dependencies (imports) from a source file.\n */\nexport function extractDependencies(sourceFile: SourceFile): DependencyEntry[] {\n const deps: DependencyEntry[] = [];\n const seenSpecifiers = new Set<string>();\n\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const specifier = importDecl.getModuleSpecifierValue();\n if (seenSpecifiers.has(specifier)) continue;\n seenSpecifiers.add(specifier);\n\n const imports: string[] = [];\n\n // Named imports\n const namedImports = importDecl.getNamedImports();\n for (const namedImport of namedImports) {\n imports.push(namedImport.getName());\n }\n\n // Default import\n const defaultImport = importDecl.getDefaultImport();\n if (defaultImport !== undefined) {\n imports.push(defaultImport.getText());\n }\n\n // Namespace import (import * as X)\n const namespaceImport = importDecl.getNamespaceImport();\n if (namespaceImport !== undefined) {\n imports.push(`* as ${namespaceImport.getText()}`);\n }\n\n deps.push({\n specifier,\n isExternal: isExternalImport(specifier),\n imports,\n });\n }\n\n return deps;\n}\n","/**\n * nexus-agents/indexer - Description Extraction\n *\n * JSDoc comment and description extraction utilities.\n *\n * (Source: Issue #240)\n */\n\nimport type { SourceFile } from 'ts-morph';\nimport { truncateSentence } from '../utils/text-utils.js';\n\n/** Result of processing a single line in JSDoc extraction. */\ntype LineResult = 'start' | 'startEnd' | 'end' | 'stop' | 'skip' | 'content';\n\n/** True for a self-contained block comment that is not a JSDoc header (e.g. `/* eslint-disable *\\/`). */\nfunction isPlainBlockComment(trimmed: string): boolean {\n return trimmed.startsWith('/*') && trimmed.endsWith('*/');\n}\n\n/** Classifies a line encountered before any JSDoc block has been entered. */\nfunction classifyOutsideComment(trimmed: string): LineResult {\n if (isPlainBlockComment(trimmed)) return 'skip';\n if (trimmed.length > 0 && !trimmed.startsWith('//')) return 'stop';\n return 'skip';\n}\n\n/** Classifies a line encountered inside an open JSDoc block. */\nfunction classifyInsideComment(trimmed: string): LineResult {\n if (trimmed.endsWith('*/')) return 'end';\n if (trimmed.startsWith('* @') || trimmed.startsWith('@')) return 'skip';\n return 'content';\n}\n\n/** Determines how to handle a line during JSDoc extraction. */\nfunction classifyJsDocLine(trimmed: string, inComment: boolean): LineResult {\n if (trimmed.startsWith('/**')) {\n // Single-line JSDoc header, e.g. `/** Utils. */` — opens and closes on\n // the same line, so it must not leave `inComment` dangling true.\n return trimmed.endsWith('*/') ? 'startEnd' : 'start';\n }\n return inComment ? classifyInsideComment(trimmed) : classifyOutsideComment(trimmed);\n}\n\n/** Extracts content from a JSDoc comment line (strips leading * and whitespace). */\nfunction extractJsDocLineContent(trimmed: string): string {\n return trimmed.startsWith('*') ? trimmed.slice(1).trim() : trimmed;\n}\n\n/** Extracts the inner text of a single-line JSDoc header like `/** text *\\/`. */\nfunction extractInlineJsDocContent(trimmed: string): string {\n return trimmed.slice(3, -2).trim();\n}\n\n/**\n * Truncates text to first sentence or max 150 chars.\n * Uses truncateSentence from utils/text-utils.ts.\n */\nfunction truncateDescription(full: string): string {\n return truncateSentence(full, 150);\n}\n\n/**\n * Extracts a description from the file's leading comment or JSDoc.\n */\nexport function extractDescription(sourceFile: SourceFile): string | undefined {\n const lines = sourceFile.getFullText().split('\\n');\n let inComment = false;\n const description: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n const result = classifyJsDocLine(trimmed, inComment);\n\n if (result === 'start') {\n inComment = true;\n continue;\n }\n if (result === 'startEnd') {\n const inline = extractInlineJsDocContent(trimmed);\n if (inline.length > 0) description.push(inline);\n break;\n }\n if (result === 'end' || result === 'stop') break;\n if (result === 'skip') continue;\n\n const content = extractJsDocLineContent(trimmed);\n if (content.length > 0) description.push(content);\n }\n\n if (description.length === 0) return undefined;\n return truncateDescription(description.join(' '));\n}\n","/**\n * nexus-agents/indexer - Project Extraction\n *\n * Project-level extraction and file entry creation.\n *\n * (Source: Issue #240)\n */\n\nimport { Project, type SourceFile } from 'ts-morph';\nimport * as path from 'node:path';\nimport { getTimeProvider } from '../core/index.js';\nimport type { FileEntry, ExtractorOptions } from './types.js';\nimport { DEFAULT_EXTRACTOR_OPTIONS } from './types.js';\nimport { detectFileCategory } from './category-detection.js';\nimport { extractExports } from './export-extraction.js';\nimport { extractDependencies } from './dependency-extraction.js';\nimport { extractDescription } from './description-extraction.js';\n\n/**\n * Result of extracting a project.\n */\nexport interface ExtractionResult {\n /** Extracted file entries */\n readonly files: readonly FileEntry[];\n /** Any errors encountered */\n readonly errors: readonly string[];\n /** Duration in milliseconds */\n readonly durationMs: number;\n}\n\n/**\n * Extracts metadata from a single source file.\n */\nexport function extractFileEntry(\n sourceFile: SourceFile,\n rootDir: string,\n extractDescriptions: boolean\n): FileEntry {\n const absolutePath = sourceFile.getFilePath();\n const relativePath = path.relative(rootDir, absolutePath);\n const lineCount = sourceFile.getEndLineNumber();\n\n const entry: FileEntry = {\n path: relativePath,\n lines: lineCount,\n category: detectFileCategory(relativePath, sourceFile),\n exports: extractExports(sourceFile),\n dependencies: extractDependencies(sourceFile),\n };\n\n if (extractDescriptions) {\n const desc = extractDescription(sourceFile);\n if (desc !== undefined) {\n (entry as { description: string }).description = desc;\n }\n }\n\n return entry;\n}\n\n/**\n * Processes source files and extracts metadata.\n *\n * Exclusion is enforced by ts-morph itself via negated glob patterns passed\n * to `addSourceFilesAtPaths` (see `extractProject`), so every source file\n * already in the project is eligible for extraction here.\n */\nfunction processSourceFiles(\n project: Project,\n rootDir: string,\n extractDescriptions: boolean\n): { files: FileEntry[]; errors: string[] } {\n const files: FileEntry[] = [];\n const errors: string[] = [];\n\n for (const sourceFile of project.getSourceFiles()) {\n const filePath = sourceFile.getFilePath();\n\n try {\n files.push(extractFileEntry(sourceFile, rootDir, extractDescriptions));\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n errors.push(`Error extracting ${filePath}: ${message}`);\n }\n }\n\n return { files, errors };\n}\n\n/**\n * Extracts metadata from all TypeScript files in a project.\n */\nexport function extractProject(options: Partial<ExtractorOptions> = {}): ExtractionResult {\n const opts: ExtractorOptions = { ...DEFAULT_EXTRACTOR_OPTIONS, ...options };\n const startTime = getTimeProvider().now();\n\n const project = new Project({\n skipAddingFilesFromTsConfig: true,\n skipFileDependencyResolution: true,\n });\n\n const rootDir = path.resolve(process.cwd(), opts.rootDir);\n const includePatterns = opts.include.map((p) => path.join(rootDir, p));\n // Negated glob patterns: ts-morph forwards these straight through to\n // tinyglobby, which honors `!`-prefixed entries as exclusions within the\n // same pattern list passed to `addSourceFilesAtPaths`.\n const excludePatterns = opts.exclude.map((p) => `!${path.join(rootDir, p)}`);\n\n try {\n project.addSourceFilesAtPaths([...includePatterns, ...excludePatterns]);\n const { files, errors } = processSourceFiles(project, rootDir, opts.extractDescriptions);\n return { files, errors, durationMs: getTimeProvider().now() - startTime };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n files: [],\n errors: [`Error loading project: ${message}`],\n durationMs: getTimeProvider().now() - startTime,\n };\n }\n}\n","/**\n * nexus-agents/indexer - Type Definitions\n *\n * Types for the codebase index feature that tracks all source files,\n * exports, dependencies, and generates documentation artifacts.\n *\n * (Source: Issue #240)\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Schema Version\n// ============================================================================\n\nexport const SCHEMA_VERSION = '1.0' as const;\n\n// ============================================================================\n// File Entry Types\n// ============================================================================\n\n/**\n * Category of a source file based on its purpose.\n */\nexport type FileCategory =\n | 'types' // Type definitions, interfaces\n | 'implementation' // Core implementation\n | 'test' // Test files\n | 'config' // Configuration files\n | 'cli' // CLI commands\n | 'util' // Utility/helper functions\n | 'index'; // Barrel exports\n\n/**\n * A single exported symbol from a file.\n */\nexport interface ExportEntry {\n /** Name of the exported symbol */\n readonly name: string;\n /** Type of export: type, interface, class, function, const, enum */\n readonly kind: 'type' | 'interface' | 'class' | 'function' | 'const' | 'enum' | 'unknown';\n /** Whether this is a re-export from another module */\n readonly isReExport: boolean;\n /** Source module for re-exports */\n readonly sourceModule?: string;\n}\n\n/**\n * A dependency import in a file.\n */\nexport interface DependencyEntry {\n /** Import specifier (e.g., './types.js', 'zod') */\n readonly specifier: string;\n /** Whether this is an external package */\n readonly isExternal: boolean;\n /** Imported symbols (empty for namespace imports) */\n readonly imports: readonly string[];\n}\n\n/**\n * Metadata for a single source file.\n */\nexport interface FileEntry {\n /** Relative path from package root */\n readonly path: string;\n /** Number of lines in the file */\n readonly lines: number;\n /** Detected category */\n readonly category: FileCategory;\n /** Exported symbols */\n readonly exports: readonly ExportEntry[];\n /** Dependencies (imports) */\n readonly dependencies: readonly DependencyEntry[];\n /** Brief description extracted from JSDoc or first comment */\n readonly description?: string;\n}\n\n// ============================================================================\n// Module Types\n// ============================================================================\n\n/**\n * Aggregated statistics for a module.\n */\nexport interface ModuleStats {\n /** Total number of files */\n readonly fileCount: number;\n /** Total lines of code */\n readonly totalLines: number;\n /** Number of exported symbols */\n readonly exportCount: number;\n /** Number of internal dependencies */\n readonly internalDeps: number;\n /** Number of external dependencies */\n readonly externalDeps: number;\n}\n\n/**\n * A module (directory) in the codebase.\n */\nexport interface ModuleEntry {\n /** Module name (directory name) */\n readonly name: string;\n /** Relative path from package root */\n readonly path: string;\n /** Brief purpose description */\n readonly purpose: string;\n /** Files in this module */\n readonly files: readonly FileEntry[];\n /** Aggregated statistics */\n readonly stats: ModuleStats;\n /** Modules this module depends on */\n readonly dependsOn: readonly string[];\n}\n\n// ============================================================================\n// Index Types\n// ============================================================================\n\n/**\n * Global statistics for the entire codebase.\n */\nexport interface IndexStats {\n /** Total number of files indexed */\n readonly totalFiles: number;\n /** Total lines of code */\n readonly totalLines: number;\n /** Total exported symbols */\n readonly totalExports: number;\n /** Number of modules */\n readonly moduleCount: number;\n /** External package dependencies */\n readonly externalPackages: readonly string[];\n}\n\n/**\n * The complete codebase index.\n */\nexport interface CodebaseIndex {\n /** Schema version for migrations */\n readonly schemaVersion: typeof SCHEMA_VERSION;\n /** Generation timestamp (ISO 8601, ET timezone) */\n readonly generatedAt: string;\n /** Global statistics */\n readonly stats: IndexStats;\n /** Indexed modules */\n readonly modules: Record<string, ModuleEntry>;\n}\n\n// ============================================================================\n// Zod Schemas (for validation)\n// ============================================================================\n\nexport const ExportEntrySchema = z.object({\n name: z.string(),\n kind: z.enum(['type', 'interface', 'class', 'function', 'const', 'enum', 'unknown']),\n isReExport: z.boolean(),\n sourceModule: z.string().optional(),\n});\n\nexport const DependencyEntrySchema = z.object({\n specifier: z.string(),\n isExternal: z.boolean(),\n imports: z.array(z.string()).readonly(),\n});\n\nexport const FileEntrySchema = z.object({\n path: z.string(),\n lines: z.number().int().nonnegative(),\n category: z.enum(['types', 'implementation', 'test', 'config', 'cli', 'util', 'index']),\n exports: z.array(ExportEntrySchema).readonly(),\n dependencies: z.array(DependencyEntrySchema).readonly(),\n description: z.string().optional(),\n});\n\nexport const ModuleStatsSchema = z.object({\n fileCount: z.number().int().nonnegative(),\n totalLines: z.number().int().nonnegative(),\n exportCount: z.number().int().nonnegative(),\n internalDeps: z.number().int().nonnegative(),\n externalDeps: z.number().int().nonnegative(),\n});\n\nexport const ModuleEntrySchema = z.object({\n name: z.string(),\n path: z.string(),\n purpose: z.string(),\n files: z.array(FileEntrySchema).readonly(),\n stats: ModuleStatsSchema,\n dependsOn: z.array(z.string()).readonly(),\n});\n\nexport const IndexStatsSchema = z.object({\n totalFiles: z.number().int().nonnegative(),\n totalLines: z.number().int().nonnegative(),\n totalExports: z.number().int().nonnegative(),\n moduleCount: z.number().int().nonnegative(),\n externalPackages: z.array(z.string()).readonly(),\n});\n\nexport const CodebaseIndexSchema = z.object({\n schemaVersion: z.literal(SCHEMA_VERSION),\n generatedAt: z.string(),\n stats: IndexStatsSchema,\n modules: z.record(z.string(), ModuleEntrySchema),\n});\n\n// ============================================================================\n// Extractor Options\n// ============================================================================\n\n/**\n * Options for the file extractor.\n */\nexport interface ExtractorOptions {\n /** Root directory to scan */\n readonly rootDir: string;\n /** Glob patterns to include */\n readonly include: readonly string[];\n /** Glob patterns to exclude */\n readonly exclude: readonly string[];\n /** Whether to extract JSDoc descriptions */\n readonly extractDescriptions: boolean;\n}\n\n/**\n * Default extractor options.\n */\nexport const DEFAULT_EXTRACTOR_OPTIONS: ExtractorOptions = {\n rootDir: 'src',\n include: ['**/*.ts'],\n exclude: ['**/*.test.ts', '**/*.d.ts', '**/node_modules/**'],\n extractDescriptions: true,\n};\n\n// ============================================================================\n// Generator Options\n// ============================================================================\n\n/**\n * Output format for the index.\n */\nexport type OutputFormat = 'yaml' | 'json';\n\n/**\n * Options for the index generator.\n */\nexport interface GeneratorOptions {\n /** Output format */\n readonly format: OutputFormat;\n /** Output file path */\n readonly outputPath: string;\n /** Whether to generate Mermaid diagram */\n readonly generateDiagram: boolean;\n /** Diagram output path (if generating) */\n readonly diagramPath?: string;\n}\n\n/**\n * Default generator options.\n */\nexport const DEFAULT_GENERATOR_OPTIONS: GeneratorOptions = {\n format: 'yaml',\n outputPath: 'docs/codebase-index.yaml',\n generateDiagram: true,\n diagramPath: 'docs/dependency-graph.md',\n};\n","/**\n * nexus-agents/indexer - Module Analyzer\n *\n * Analyzes extracted file entries to build module dependency graphs\n * and aggregate statistics.\n *\n * (Source: Issue #240)\n */\n\nimport * as path from 'node:path';\nimport { getTimeProvider } from '../core/index.js';\nimport type { FileEntry, ModuleEntry, ModuleStats, IndexStats, CodebaseIndex } from './types.js';\nimport { SCHEMA_VERSION } from './types.js';\n\n// ============================================================================\n// Module Purpose Detection\n// ============================================================================\n\n/**\n * Purpose descriptions for known modules.\n */\nconst MODULE_PURPOSES: Record<string, string> = {\n core: 'Types, Result<T,E>, errors, logger',\n config: 'Configuration loading, validation, Zod schemas',\n adapters: 'Model adapters (Claude, OpenAI, Gemini, Ollama)',\n agents: 'Agent framework, Orchestrator, Experts, collaboration',\n workflows: 'Workflow engine, templates, execution',\n mcp: 'MCP server, tool definitions',\n cli: 'CLI interface, mode detection, commands',\n 'cli-adapters': 'External CLI integrations (Claude, Gemini, Codex)',\n context: 'Context management, token counting, memory',\n consensus: 'Multi-agent consensus, voting strategies',\n learning: 'Feedback collection, outcome tracking',\n indexer: 'Codebase indexing and documentation',\n security: 'Sandbox execution, secrets management',\n};\n\n/**\n * Detects the purpose of a module based on its name and content.\n */\nexport function detectModulePurpose(moduleName: string, files: readonly FileEntry[]): string {\n // Check known purposes\n const known = MODULE_PURPOSES[moduleName];\n if (known !== undefined) {\n return known;\n }\n\n // Generate purpose from file descriptions\n const descriptions = files\n .filter((f) => f.description !== undefined)\n .map((f) => f.description)\n .slice(0, 3);\n\n if (descriptions.length > 0) {\n return descriptions.join('; ');\n }\n\n // Fallback to generic purpose based on name\n return `${moduleName} module`;\n}\n\n// ============================================================================\n// Package Name Extraction\n// ============================================================================\n\n/**\n * Extracts package name from an import specifier.\n * Handles scoped packages (@scope/package), node: builtins, and regular packages.\n */\nfunction extractPackageName(specifier: string): string | undefined {\n if (specifier.startsWith('@')) {\n // Scoped package: @scope/package\n const parts = specifier.split('/');\n const scope = parts[0];\n const name = parts[1];\n if (scope !== undefined && name !== undefined) {\n return `${scope}/${name}`;\n }\n return undefined;\n }\n\n if (specifier.startsWith('node:')) {\n return specifier;\n }\n\n // Regular package\n const parts = specifier.split('/');\n return parts[0];\n}\n\n// ============================================================================\n// Module Analysis\n// ============================================================================\n\n/**\n * Groups files by their top-level module directory.\n */\nexport function groupFilesByModule(files: readonly FileEntry[]): Map<string, FileEntry[]> {\n const modules = new Map<string, FileEntry[]>();\n\n for (const file of files) {\n // Get the top-level directory as the module name\n const parts = file.path.split('/');\n const moduleName = parts.length > 1 ? (parts[0] ?? 'root') : 'root';\n\n const existing = modules.get(moduleName);\n if (existing !== undefined) {\n existing.push(file);\n } else {\n modules.set(moduleName, [file]);\n }\n }\n\n return modules;\n}\n\n/**\n * Collects external package names from a single file's dependencies.\n */\nfunction collectExternalPackages(file: FileEntry, packages: Set<string>): void {\n for (const dep of file.dependencies) {\n if (dep.isExternal) {\n const pkgName = extractPackageName(dep.specifier);\n if (pkgName !== undefined) {\n packages.add(pkgName);\n }\n }\n }\n}\n\n/**\n * Extracts unique external package names from dependencies.\n */\nexport function extractExternalPackages(files: readonly FileEntry[]): string[] {\n const packages = new Set<string>();\n\n for (const file of files) {\n collectExternalPackages(file, packages);\n }\n\n return Array.from(packages).sort();\n}\n\n/**\n * Computes statistics for a module.\n */\nexport function computeModuleStats(files: readonly FileEntry[]): ModuleStats {\n let totalLines = 0;\n let exportCount = 0;\n let internalDeps = 0;\n let externalDeps = 0;\n\n for (const file of files) {\n totalLines += file.lines;\n exportCount += file.exports.length;\n\n for (const dep of file.dependencies) {\n if (dep.isExternal) {\n externalDeps++;\n } else {\n internalDeps++;\n }\n }\n }\n\n return {\n fileCount: files.length,\n totalLines,\n exportCount,\n internalDeps,\n externalDeps,\n };\n}\n\n/** Resolves a relative import to its target module name. */\nfunction resolveTargetModule(filePath: string, specifier: string): string | undefined {\n if (!specifier.startsWith('.')) return undefined;\n const resolved = path.join(path.dirname(filePath), specifier);\n const parts = resolved.split('/');\n return parts[0];\n}\n\n/** Checks if a target module is a valid cross-module dependency. */\nfunction isValidModuleDep(\n targetModule: string | undefined,\n moduleName: string,\n allModules: Set<string>\n): targetModule is string {\n return targetModule !== undefined && targetModule !== moduleName && allModules.has(targetModule);\n}\n\n/**\n * Detects which other modules a module depends on.\n */\nexport function detectModuleDependencies(\n moduleName: string,\n files: readonly FileEntry[],\n allModules: Set<string>\n): string[] {\n const deps = new Set<string>();\n\n for (const file of files) {\n for (const dep of file.dependencies) {\n if (dep.isExternal) continue;\n\n const targetModule = resolveTargetModule(file.path, dep.specifier);\n if (isValidModuleDep(targetModule, moduleName, allModules)) {\n deps.add(targetModule);\n }\n }\n }\n\n return Array.from(deps).sort();\n}\n\n/**\n * Analyzes files and builds module entries.\n */\nexport function analyzeModules(files: readonly FileEntry[]): Map<string, ModuleEntry> {\n const filesByModule = groupFilesByModule(files);\n const moduleNames = new Set(filesByModule.keys());\n const modules = new Map<string, ModuleEntry>();\n\n for (const [moduleName, moduleFiles] of filesByModule) {\n modules.set(moduleName, {\n name: moduleName,\n path: moduleName === 'root' ? '.' : moduleName,\n purpose: detectModulePurpose(moduleName, moduleFiles),\n files: moduleFiles,\n stats: computeModuleStats(moduleFiles),\n dependsOn: detectModuleDependencies(moduleName, moduleFiles, moduleNames),\n });\n }\n\n return modules;\n}\n\n// ============================================================================\n// Index Building\n// ============================================================================\n\n/**\n * Computes global index statistics.\n */\nexport function computeIndexStats(modules: Map<string, ModuleEntry>): IndexStats {\n let totalFiles = 0;\n let totalLines = 0;\n let totalExports = 0;\n const externalPackages = new Set<string>();\n\n for (const module of modules.values()) {\n totalFiles += module.stats.fileCount;\n totalLines += module.stats.totalLines;\n totalExports += module.stats.exportCount;\n\n // Collect external packages using the shared helper\n for (const file of module.files) {\n collectExternalPackages(file, externalPackages);\n }\n }\n\n return {\n totalFiles,\n totalLines,\n totalExports,\n moduleCount: modules.size,\n externalPackages: Array.from(externalPackages).sort(),\n };\n}\n\n/**\n * Builds a complete codebase index from extracted files.\n */\nexport function buildIndex(files: readonly FileEntry[]): CodebaseIndex {\n const modules = analyzeModules(files);\n const stats = computeIndexStats(modules);\n\n // Generate timestamp in ET timezone\n const now = new Date(getTimeProvider().now());\n const etFormatter = new Intl.DateTimeFormat('en-US', {\n timeZone: 'America/New_York',\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false,\n });\n const parts = etFormatter.formatToParts(now);\n const getPart = (type: string): string => parts.find((p) => p.type === type)?.value ?? '00';\n\n // Compute the actual ET offset (EST=-05:00, EDT=-04:00) dynamically\n const utcFormatter = new Intl.DateTimeFormat('en-US', {\n timeZone: 'UTC',\n hour: 'numeric',\n hour12: false,\n });\n const utcHour = Number(\n utcFormatter.formatToParts(now).find((p) => p.type === 'hour')?.value ?? '0'\n );\n const etHour = Number(getPart('hour'));\n const rawDiff = etHour - utcHour;\n const offsetHours = rawDiff > 12 ? rawDiff - 24 : rawDiff < -12 ? rawDiff + 24 : rawDiff;\n const offsetSign = offsetHours <= 0 ? '-' : '+';\n const absOffset = String(Math.abs(offsetHours)).padStart(2, '0');\n const timestamp = `${getPart('year')}-${getPart('month')}-${getPart('day')}T${getPart('hour')}:${getPart('minute')}:${getPart('second')}${offsetSign}${absOffset}:00`;\n\n // Convert modules map to record\n const modulesRecord: Record<string, ModuleEntry> = {};\n for (const [name, entry] of modules) {\n modulesRecord[name] = entry;\n }\n\n return {\n schemaVersion: SCHEMA_VERSION,\n generatedAt: timestamp,\n stats,\n modules: modulesRecord,\n };\n}\n","/**\n * Repo-map call-site signal (#4268, enhancement of #4254 / epic #4251).\n *\n * Turns the `search_usages` ast-grep machinery (#4265, shared via\n * `indexer/usage-ast.ts`) into a per-module **call-site frequency** signal the\n * repo-map ranker blends with import-graph PageRank, so ranking reflects which\n * modules are actually *called*, not just imported.\n *\n * ## Cost bound (call-site extraction is heavier than the import graph)\n *\n * The signal is deliberately bounded so a flag-on structural call cannot blow\n * the per-call budget or add unbounded latency:\n * 1. **Probe symbols come only from the TOP-N import-ranked modules**\n * ({@link CALLSITE_TOP_N_MODULES}); the whole probe set is capped at\n * {@link MAX_PROBE_SYMBOLS}.\n * 2. **Each source file is parsed at most ONCE** — {@link countCallSitesInSource}\n * tallies every probe symbol in a single parse (not one parse per symbol).\n * 3. **Total files scanned is capped** at {@link MAX_CALLSITE_FILES}.\n *\n * Best-effort: any read/parse failure degrades to a partial/empty count (the\n * ranker then falls back toward import-only ordering) — it never throws into\n * context assembly.\n *\n * @module context/repo-map-callsites\n */\n\nimport { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport type { CodebaseIndex, ModuleEntry } from '../indexer/types.js';\nimport type { ILogger } from '../core/logger.js';\nimport { createLogger } from '../core/logger.js';\nimport { countCallSitesInSource, inferLang } from '../indexer/usage-ast.js';\n\n/** How many top import-ranked modules contribute probe symbols. */\nexport const CALLSITE_TOP_N_MODULES = 25;\n/** Hard cap on the total number of probe symbols scanned per repo-map build. */\nexport const MAX_PROBE_SYMBOLS = 60;\n/** Hard cap on files parsed per repo-map build, to bound worst-case latency. */\nexport const MAX_CALLSITE_FILES = 4000;\n\n/** Options for {@link computeCallSiteCounts}. */\nexport interface CallSiteCountOptions {\n /**\n * Root the index's relative file paths resolve against. Defaults to\n * `<cwd>/src`, matching the default index provider (`extractProject` rootDir).\n */\n readonly sourceRoot?: string;\n /** Cap on files parsed. Defaults to {@link MAX_CALLSITE_FILES}. */\n readonly maxFiles?: number;\n /** Optional logger override. */\n readonly logger?: ILogger;\n}\n\n/** The bounded probe: the tracked symbols + which module each belongs to. */\ninterface ProbeSet {\n readonly symbols: ReadonlySet<string>;\n readonly owner: ReadonlyMap<string, string>;\n}\n\ninterface FileRef {\n readonly abs: string;\n readonly rel: string;\n}\n\nfunction defaultSourceRoot(): string {\n return resolve(process.cwd(), 'src');\n}\n\n/** Add a module's own (non-re-exported) symbol names to the probe owner map. */\nfunction addModuleExports(mod: ModuleEntry, name: string, owner: Map<string, string>): void {\n for (const file of mod.files) {\n for (const exp of file.exports) {\n if (exp.isReExport) continue;\n if (!owner.has(exp.name)) owner.set(exp.name, name);\n if (owner.size >= MAX_PROBE_SYMBOLS) return;\n }\n }\n}\n\n/** Build the bounded probe set from the top import-ranked modules' exports. */\nfunction buildProbeSet(index: CodebaseIndex, topModuleNames: readonly string[]): ProbeSet {\n const owner = new Map<string, string>();\n for (const name of topModuleNames) {\n const mod = index.modules[name];\n if (mod === undefined) continue;\n addModuleExports(mod, name, owner);\n if (owner.size >= MAX_PROBE_SYMBOLS) break;\n }\n return { symbols: new Set(owner.keys()), owner };\n}\n\n/** Deduplicated, capped list of every source file the index knows about. */\nfunction collectFiles(index: CodebaseIndex, sourceRoot: string, maxFiles: number): FileRef[] {\n const refs: FileRef[] = [];\n const seen = new Set<string>();\n for (const mod of Object.values(index.modules)) {\n for (const file of mod.files) {\n if (seen.has(file.path)) continue;\n seen.add(file.path);\n refs.push({ abs: resolve(sourceRoot, file.path), rel: file.path });\n if (refs.length >= maxFiles) return refs;\n }\n }\n return refs;\n}\n\n/** Parse one file once and fold its probe-symbol call-sites into per-module counts. */\nfunction tallyFile(probe: ProbeSet, ref: FileRef, counts: Map<string, number>, log: ILogger): void {\n let src: string;\n try {\n src = readFileSync(ref.abs, 'utf8');\n } catch {\n log.debug('repo-map call-site: unreadable file', { file: ref.rel });\n return;\n }\n for (const [sym, n] of countCallSitesInSource(probe.symbols, src, inferLang(ref.rel))) {\n const owner = probe.owner.get(sym);\n if (owner !== undefined) counts.set(owner, (counts.get(owner) ?? 0) + n);\n }\n}\n\n/**\n * Count structural call-sites of the top import-ranked modules' exported\n * symbols across the codebase, returning a `module → call-site count` map used\n * as a secondary rank signal (#4268). Bounded per the module docstring and\n * best-effort — a failure yields a partial/empty map, never a throw.\n */\nexport function computeCallSiteCounts(\n index: CodebaseIndex,\n topModuleNames: readonly string[],\n options: CallSiteCountOptions = {}\n): Map<string, number> {\n const log = options.logger ?? createLogger({ component: 'RepoMapCallSites' });\n const counts = new Map<string, number>();\n try {\n const probe = buildProbeSet(index, topModuleNames);\n if (probe.symbols.size === 0) return counts;\n const sourceRoot = options.sourceRoot ?? defaultSourceRoot();\n const maxFiles = options.maxFiles ?? MAX_CALLSITE_FILES;\n for (const ref of collectFiles(index, sourceRoot, maxFiles)) {\n tallyFile(probe, ref, counts, log);\n }\n } catch (error: unknown) {\n log.debug('repo-map call-site counting failed', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n return counts;\n}\n","/**\n * nexus-agents/indexer - Shared structural usage / call-site AST core.\n *\n * The ast-grep (`@ast-grep/napi`, MIT, Rust + tree-sitter) primitives that\n * answer \"where is symbol X used / called\". Extracted from the `search_usages`\n * MCP tool (#4265 / epic #4249 Child A) so a SECOND consumer — the repo-map\n * ranker (#4268) — can reuse the exact same call-site-finding logic instead of\n * duplicating the ast-grep querying or going through the MCP tool layer.\n *\n * Two entry points share the same classification core:\n * - {@link findUsagesInSource} — every usage of ONE symbol (call, member call,\n * `new`, import, reference), the `search_usages` tool's per-symbol scan.\n * - {@link countCallSitesInSource} — a SINGLE-parse tally of how often each of\n * MANY symbols is *called* (call / member-call / `new`) in a source, the\n * bounded signal the repo-map needs (one parse per file, not one per symbol).\n *\n * Syntactic, not type-aware: matches are structural and are NOT resolved\n * against a type checker — a member call on an unrelated object of the same\n * property name will match. That is the documented ast-grep trade-off.\n *\n * @module indexer/usage-ast\n */\n\nimport { extname } from 'node:path';\nimport { Lang, parse } from '@ast-grep/napi';\nimport type { NapiConfig, SgNode } from '@ast-grep/napi';\n\n// ============================================================================\n// Language + identifier primitives\n// ============================================================================\n\nexport const LANG_VALUES = ['typescript', 'tsx', 'javascript'] as const;\nexport type SupportedLang = (typeof LANG_VALUES)[number];\n\n/** Per-match snippet char cap. */\nconst MAX_SNIPPET_CHARS = 200;\n\n/** A single JS identifier — anchored so a symbol can't smuggle ast-grep pattern metachars. */\nexport const IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\n/** The kind of a usage site. Declarations are excluded (that is the name index's job). */\nexport type UsageKind = 'call' | 'method-call' | 'new' | 'import' | 'reference';\n\n/** Usage kinds that represent an actual call-site (what the repo-map ranks on). */\nconst CALL_USAGE_KINDS: ReadonlySet<UsageKind> = new Set<UsageKind>(['call', 'method-call', 'new']);\n\n/** A single usage match within one source string. */\nexport interface UsageMatch {\n /** 1-based line number. */\n line: number;\n /** 1-based column number. */\n column: number;\n kind: UsageKind;\n /** Trimmed, length-capped source line for the match. */\n snippet: string;\n}\n\n/** Identifier parents whose matched identifier IS the declared name — not a usage. */\nconst DECLARATION_PARENT_KINDS = new Set<string>([\n 'function_declaration',\n 'generator_function_declaration',\n 'class_declaration',\n 'interface_declaration',\n 'type_alias_declaration',\n 'enum_declaration',\n 'function_signature',\n 'method_definition',\n 'abstract_method_signature',\n]);\n\n/** Identifier parents that denote an import binding. */\nconst IMPORT_PARENT_KINDS = new Set<string>([\n 'import_specifier',\n 'namespace_import',\n 'import_clause',\n]);\n\nfunction langToNapi(lang: SupportedLang): Lang {\n if (lang === 'tsx') return Lang.Tsx;\n if (lang === 'javascript') return Lang.JavaScript;\n return Lang.TypeScript;\n}\n\n/** Infer the ast-grep language for a file from its extension. */\nexport function inferLang(file: string): SupportedLang {\n const ext = extname(file).toLowerCase();\n if (ext === '.tsx' || ext === '.jsx') return 'tsx';\n if (ext === '.js' || ext === '.mjs' || ext === '.cjs') return 'javascript';\n return 'typescript';\n}\n\n/** Escape regex metacharacters so a `$`-bearing identifier anchors correctly. */\nfunction escapeRegex(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n// ============================================================================\n// Classification\n// ============================================================================\n\n/** True when the identifier `node` is the `name` field of its variable_declarator parent. */\nfunction isDeclaredName(declarator: SgNode, node: SgNode): boolean {\n const name = declarator.field('name');\n return name !== null && name.id() === node.id();\n}\n\n/** Classify a plain `identifier` occurrence; returns null when it is a declaration name to skip. */\nfunction classifyIdentifier(node: SgNode): UsageKind | null {\n const parent = node.parent();\n if (parent === null) return 'reference';\n const pk = String(parent.kind());\n if (DECLARATION_PARENT_KINDS.has(pk)) return null;\n if (pk === 'variable_declarator') return isDeclaredName(parent, node) ? null : 'reference';\n if (IMPORT_PARENT_KINDS.has(pk)) return 'import';\n if (pk === 'call_expression') return 'call';\n if (pk === 'new_expression') return 'new';\n return 'reference';\n}\n\n/** Classify a `property_identifier` occurrence (member access): method-call vs plain reference. */\nfunction classifyProperty(node: SgNode): UsageKind {\n const member = node.parent();\n const grandparent = member === null ? null : member.parent();\n if (grandparent !== null && String(grandparent.kind()) === 'call_expression')\n return 'method-call';\n return 'reference';\n}\n\nfunction toMatch(node: SgNode, kind: UsageKind, lines: readonly string[]): UsageMatch {\n const { start } = node.range();\n const rawLine = lines[start.line] ?? node.text();\n return {\n line: start.line + 1,\n column: start.column + 1,\n kind,\n snippet: rawLine.trim().slice(0, MAX_SNIPPET_CHARS),\n };\n}\n\n// ============================================================================\n// Single-symbol scan (search_usages)\n// ============================================================================\n\n/**\n * Find every structural usage of `symbol` in `src`. Returns call-sites, member\n * calls, `new` expressions, imports, and bare references — but NOT the symbol's\n * own declaration (that is what `search_codebase`'s name index already covers).\n * Sorted by position. This is the capability `search_codebase` cannot provide.\n */\nexport function findUsagesInSource(symbol: string, src: string, lang: SupportedLang): UsageMatch[] {\n if (!IDENTIFIER_RE.test(symbol)) return [];\n const root = parse(langToNapi(lang), src).root();\n const lines = src.split('\\n');\n const out: UsageMatch[] = [];\n\n for (const node of root.findAll(symbol)) {\n const kind = classifyIdentifier(node);\n if (kind !== null) out.push(toMatch(node, kind, lines));\n }\n\n // Member-access occurrences are `property_identifier` nodes, which the bare\n // identifier pattern above does not match — collect them via a kind rule.\n const propRule: NapiConfig = {\n rule: { kind: 'property_identifier', regex: `^${escapeRegex(symbol)}$` },\n };\n for (const node of root.findAll(propRule)) {\n out.push(toMatch(node, classifyProperty(node), lines));\n }\n\n return out.sort((a, b) => a.line - b.line || a.column - b.column);\n}\n\n// ============================================================================\n// Multi-symbol call-site tally (repo-map ranking, #4268)\n// ============================================================================\n\n/** Bump the tally for `name` when it is one of the tracked symbols. */\nfunction bump(counts: Map<string, number>, symbols: ReadonlySet<string>, name: string): void {\n if (symbols.has(name)) counts.set(name, (counts.get(name) ?? 0) + 1);\n}\n\n/** Tally call-kind occurrences of tracked plain-identifier symbols in one parse. */\nfunction tallyIdentifierCalls(\n root: SgNode,\n symbols: ReadonlySet<string>,\n counts: Map<string, number>\n): void {\n for (const node of root.findAll({ rule: { kind: 'identifier' } })) {\n const kind = classifyIdentifier(node);\n if (kind !== null && CALL_USAGE_KINDS.has(kind)) bump(counts, symbols, node.text());\n }\n}\n\n/** Tally method-call occurrences of tracked member-access symbols in one parse. */\nfunction tallyPropertyCalls(\n root: SgNode,\n symbols: ReadonlySet<string>,\n counts: Map<string, number>\n): void {\n for (const node of root.findAll({ rule: { kind: 'property_identifier' } })) {\n if (CALL_USAGE_KINDS.has(classifyProperty(node))) bump(counts, symbols, node.text());\n }\n}\n\n/**\n * Count structural CALL-SITES (call / member-call / `new`) of any symbol in\n * `symbols` within `src`, in a SINGLE parse — the bounded signal the repo-map\n * ranks on (#4268). Returns per-symbol counts (symbols with zero call-sites are\n * absent). Excludes declarations, imports, and bare references — only actual\n * call-sites, since that is what \"how used is this module\" means for ranking.\n * Syntactic like {@link findUsagesInSource}: same-named members on unrelated\n * objects can match; that is the documented ast-grep trade-off.\n */\nexport function countCallSitesInSource(\n symbols: ReadonlySet<string>,\n src: string,\n lang: SupportedLang\n): Map<string, number> {\n const counts = new Map<string, number>();\n if (symbols.size === 0) return counts;\n const root = parse(langToNapi(lang), src).root();\n tallyIdentifierCalls(root, symbols, counts);\n tallyPropertyCalls(root, symbols, counts);\n return counts;\n}\n","/**\n * Repo-map context provider — pull-shaped, usage-aware, measured (#4254,\n * Phase 3 of epic #4251; call-site signal added in #4268).\n *\n * Wires the EXISTING module-import graph (`indexer/types.ts`\n * `ModuleEntry.dependsOn`, built by `analyzer.ts buildIndex`, until now\n * emitted only as docs/mermaid) into context assembly as a **ranked,\n * token-budgeted repo-map**. Modules are ordered by import-graph PageRank\n * centrality **blended with real call-site frequency** (#4268 — the\n * `search_usages` ast-grep signal, `context/repo-map-callsites.ts`), then\n * budget-clipped to a small token target so heavily-*called* modules surface,\n * not just heavily-imported ones.\n *\n * ## Shaped exactly as the consensus vote (#4251) constrained it\n *\n * 1. **Default OFF / opt-in.** {@link getRepoMapForTask} contributes only when\n * `NEXUS_REPO_MAP=1` (mirrors the `NEXUS_CONTEXT_RANKED` pattern). Flag off\n * ⇒ it returns `undefined` before doing any work, so `getContextForTask`\n * output is byte-for-byte unchanged.\n * 2. **Pull-shaped / rank-gated.** Even with the flag on, the map is produced\n * ONLY for tasks that plausibly span multiple modules ({@link taskNeedsRepoMap}) —\n * never pushed onto 100% of calls (the rejected eager-RAG anti-pattern).\n * 3. **PageRank + call-site ranking.** Import-graph PageRank is the base score;\n * a bounded per-module call-site count ({@link computeCallSiteCounts}) is\n * blended in as a secondary signal ({@link blendRankScore}). The block is\n * then clipped to a token budget (reusing the #4253 char/4 mechanism —\n * {@link clampToTokenBudget}).\n * 4. **Honest caveat.** Call-site data IS incorporated, but structural matching\n * is syntactic (no type checker): dynamic dispatch, computed/string-keyed\n * calls, and same-named members on unrelated objects are not resolved, and\n * the call-site signal only samples the top import-ranked modules. Every\n * rendered map carries an explicit {@link REPO_MAP_CAVEAT} at the top so\n * agents treat centrality as an approximate structural+usage signal, not an\n * exact call graph.\n * 5. **Measured.** The emitted token count is recorded in the token ledger\n * tagged `contextSource: 'repo-map'` by the `context-retriever.ts` wiring.\n * 6. **Fresh, not persisted.** The default index provider builds from the\n * CURRENT source tree each call ({@link buildLiveIndex}) — no persisted\n * stale-map path. (A scoped index cache is a tracked follow-up; the\n * provider is opt-in + rank-gated so the build cost is only paid when asked.)\n *\n * Pure builder + fail-soft provider: a build (or call-site) failure degrades to\n * import-only ranking / `undefined`, never a throw into context assembly.\n *\n * @module context/repo-map\n */\n\nimport type { CodebaseIndex, ModuleEntry } from '../indexer/types.js';\nimport type { TaskCategory } from '../config/task-specialization-types.js';\nimport type { ILogger } from '../core/logger.js';\nimport { createLogger } from '../core/logger.js';\nimport { extractProject } from '../indexer/extractor.js';\nimport { buildIndex } from '../indexer/analyzer.js';\nimport { clampToTokenBudget } from './context-retriever-helpers.js';\nimport { CALLSITE_TOP_N_MODULES, computeCallSiteCounts } from './repo-map-callsites.js';\n\n// ============================================================================\n// Public constants\n// ============================================================================\n\n/** Env flag gating the repo-map provider (#4254). `1` enables; default off. */\nexport const REPO_MAP_FLAG = 'NEXUS_REPO_MAP';\n\n/** Default token budget for the rendered repo-map block. Small — it is a map, not a dump. */\nexport const DEFAULT_REPO_MAP_TOKEN_BUDGET = 400;\n\n/**\n * Mandatory honesty caveat (#4254 constraint 4, updated in #4268 once call-site\n * data landed). Ranking now blends import PageRank with real call-site\n * frequency, so the old \"no call-site data\" wording is gone. The remaining,\n * honest limitation is that call-site matching is structural/syntactic (no type\n * checker). Rendered at the TOP of every map so a prefix-cut budget clamp can\n * never remove it.\n */\nexport const REPO_MAP_CAVEAT =\n 'Ranking blends import-graph PageRank with structural call-site frequency ' +\n '(ast-grep, sampled over the top import-ranked modules). Call-site matching is ' +\n 'syntactic, not type-aware: dynamic dispatch, computed/string-keyed calls, and ' +\n 'same-named members on unrelated objects are not resolved — treat centrality as ' +\n 'an approximate structural+usage signal, not an exact call graph.';\n\n/** Section header for the rendered repo-map block. */\nconst REPO_MAP_HEADER = '## Repo Map (module import graph + call-site usage — ranked)';\n\n// ============================================================================\n// PageRank over the module-import graph\n// ============================================================================\n\n/** PageRank damping factor (the standard 0.85). */\nconst PAGERANK_DAMPING = 0.85;\n/** Max PageRank iterations. Module-scale graphs converge in far fewer. */\nconst PAGERANK_MAX_ITERATIONS = 100;\n/** Convergence threshold on the L1 delta between successive iterations. */\nconst PAGERANK_EPSILON = 1e-6;\n\n/**\n * Compute PageRank centrality over the module-import graph. An edge `A → B`\n * exists when `B ∈ A.dependsOn` (A imports B), so PageRank scores a module\n * high when many/important modules depend on it — i.e. the foundational\n * modules surface first. Restricted to intra-index edges (unknown/self\n * targets are dropped). Returns a probability distribution summing to ~1.\n * Pure; never throws; empty graph → empty map.\n */\nexport function computeModulePageRank(modules: Record<string, ModuleEntry>): Map<string, number> {\n const names = Object.keys(modules);\n const n = names.length;\n if (n === 0) return new Map();\n const outEdges = buildOutEdges(modules, names);\n let ranks = new Map(names.map((name) => [name, 1 / n]));\n for (let iter = 0; iter < PAGERANK_MAX_ITERATIONS; iter++) {\n const next = pageRankStep(names, outEdges, ranks, n);\n if (l1Delta(ranks, next) < PAGERANK_EPSILON) return next;\n ranks = next;\n }\n return ranks;\n}\n\n/** Out-edge adjacency restricted to known modules, self-edges removed. */\nfunction buildOutEdges(\n modules: Record<string, ModuleEntry>,\n names: readonly string[]\n): Map<string, readonly string[]> {\n const known = new Set(names);\n const out = new Map<string, readonly string[]>();\n for (const name of names) {\n const deps = modules[name]?.dependsOn ?? [];\n out.set(\n name,\n deps.filter((d) => known.has(d) && d !== name)\n );\n }\n return out;\n}\n\n/** One power-iteration step, redistributing dangling-node rank uniformly. */\nfunction pageRankStep(\n names: readonly string[],\n outEdges: Map<string, readonly string[]>,\n ranks: Map<string, number>,\n n: number\n): Map<string, number> {\n const danglingShare = (PAGERANK_DAMPING * sumDanglingRank(names, outEdges, ranks)) / n;\n const base = (1 - PAGERANK_DAMPING) / n + danglingShare;\n const next = new Map<string, number>(names.map((name) => [name, base]));\n for (const src of names) {\n const targets = outEdges.get(src) ?? [];\n if (targets.length === 0) continue;\n const share = (PAGERANK_DAMPING * (ranks.get(src) ?? 0)) / targets.length;\n for (const t of targets) {\n next.set(t, (next.get(t) ?? 0) + share);\n }\n }\n return next;\n}\n\n/** Total rank held by dangling nodes (no outgoing edges). */\nfunction sumDanglingRank(\n names: readonly string[],\n outEdges: Map<string, readonly string[]>,\n ranks: Map<string, number>\n): number {\n let sum = 0;\n for (const name of names) {\n if ((outEdges.get(name) ?? []).length === 0) sum += ranks.get(name) ?? 0;\n }\n return sum;\n}\n\n/** L1 distance between two rank vectors, used as the convergence signal. */\nfunction l1Delta(a: Map<string, number>, b: Map<string, number>): number {\n let d = 0;\n for (const [k, v] of a) d += Math.abs(v - (b.get(k) ?? 0));\n return d;\n}\n\n// ============================================================================\n// Ranked entries\n// ============================================================================\n\n/** One repo-map row: a module with its centrality, call-site count, and import edges. */\nexport interface RepoMapEntry {\n /** Module name. */\n readonly module: string;\n /** PageRank centrality in [0, 1]. */\n readonly centrality: number;\n /** Structural call-sites of this module's exported symbols (#4268; 0 when no call-site data). */\n readonly callSites: number;\n /** Module purpose (from the index). */\n readonly purpose: string;\n /** Modules this module imports (out-edges). */\n readonly dependsOn: readonly string[];\n /** File count, for a rough size signal. */\n readonly fileCount: number;\n}\n\n/**\n * Weight of the call-site signal relative to import centrality (#4268). At\n * `2`, a max-called module scores up to 3× its centrality, so a heavily-called\n * but lightly-imported module can overtake a lightly-called one with up to ~3×\n * its centrality — enough to measurably reorder toward actually-used modules\n * while keeping import centrality as the base signal.\n */\nconst CALL_SITE_WEIGHT = 2;\n\n/** Blend import centrality with a normalized call-site count into the sort score (#4268). */\nexport function blendRankScore(\n centrality: number,\n callSites: number,\n maxCallSites: number\n): number {\n if (maxCallSites <= 0) return centrality;\n return centrality * (1 + CALL_SITE_WEIGHT * (callSites / maxCallSites));\n}\n\n/** Largest call-site count across modules, used to normalize the blend. */\nfunction maxCount(counts: ReadonlyMap<string, number>): number {\n let max = 0;\n for (const v of counts.values()) if (v > max) max = v;\n return max;\n}\n\n/**\n * Rank every module in the index by import-graph PageRank centrality blended\n * with call-site frequency (#4268) — descending, ties broken by name for a\n * deterministic order. With no `callSiteCounts` (or all-zero counts) the score\n * reduces to pure centrality, so import-only callers rank identically. Pure.\n */\nexport function rankRepoMapEntries(\n index: CodebaseIndex,\n callSiteCounts?: ReadonlyMap<string, number>\n): readonly RepoMapEntry[] {\n const ranks = computeModulePageRank(index.modules);\n const counts = callSiteCounts ?? new Map<string, number>();\n const max = maxCount(counts);\n const scored = Object.entries(index.modules).map(([name, mod]) => {\n const centrality = ranks.get(name) ?? 0;\n const callSites = counts.get(name) ?? 0;\n const entry: RepoMapEntry = {\n module: name,\n centrality,\n callSites,\n purpose: mod.purpose,\n dependsOn: mod.dependsOn,\n fileCount: mod.stats.fileCount,\n };\n return { entry, score: blendRankScore(centrality, callSites, max) };\n });\n scored.sort((a, b) =>\n b.score !== a.score ? b.score - a.score : a.entry.module.localeCompare(b.entry.module)\n );\n return scored.map((s) => s.entry);\n}\n\n// ============================================================================\n// Rendering\n// ============================================================================\n\n/** Options for {@link buildRepoMap}. */\nexport interface BuildRepoMapOptions {\n /** Token budget for the rendered block. Defaults to {@link DEFAULT_REPO_MAP_TOKEN_BUDGET}. */\n readonly budgetTokens?: number;\n /** Per-module call-site counts to blend into ranking (#4268). Absent ⇒ import-only order. */\n readonly callSiteCounts?: ReadonlyMap<string, number>;\n}\n\n/** Rough chars-per-token estimate, matching {@link clampToTokenBudget} / token-counter (~4). */\nconst CHARS_PER_TOKEN = 4;\n/** Cap on how many import edges to list per module line (keeps lines bounded). */\nconst MAX_DEPS_PER_LINE = 6;\n/** Cap on a single rendered line's chars (defense against a pathological purpose string). */\nconst MAX_LINE_CHARS = 200;\n\n/**\n * Build a ranked, token-budgeted repo-map from a codebase index. Modules are\n * ordered by PageRank centrality; lower-centrality modules are clipped to fit\n * `budgetTokens` worth of module-list content (with a visible \"+N omitted\"\n * notice). The header + mandatory {@link REPO_MAP_CAVEAT} always lead the block\n * in full — `budgetTokens` governs the clippable module list, never the safety\n * caveat (#4254 constraint 4). Empty index → empty string. Pure.\n */\nexport function buildRepoMap(index: CodebaseIndex, options: BuildRepoMapOptions = {}): string {\n const entries = rankRepoMapEntries(index, options.callSiteCounts);\n if (entries.length === 0) return '';\n const budget = options.budgetTokens ?? DEFAULT_REPO_MAP_TOKEN_BUDGET;\n return renderRepoMap(entries, budget);\n}\n\n/** Assemble preamble (header + caveat) + budget-fitted module lines + omission notice. */\nfunction renderRepoMap(entries: readonly RepoMapEntry[], budgetTokens: number): string {\n const preamble = `${REPO_MAP_HEADER}\\n> ${REPO_MAP_CAVEAT}`;\n const lines = entries.map(formatEntryLine);\n const { kept, omitted } = fitLinesWithinBudget(lines, budgetTokens);\n // Defensive re-clamp of the module list reusing the #4253 char/4 mechanism\n // ({@link clampToTokenBudget}); a no-op once the greedy fit has kept lines.\n const bodyText = kept.length > 0 ? clampToTokenBudget(kept.join('\\n'), budgetTokens).text : '';\n const body = bodyText === '' ? '' : `\\n${bodyText}`;\n const notice =\n omitted > 0\n ? `\\n_(+${String(omitted)} lower-centrality modules omitted for the ~${String(budgetTokens)}-token module budget — #4254)_`\n : '';\n return `${preamble}${body}${notice}`;\n}\n\n/** Render one module row: `- name (centrality, N call-sites, files): purpose → dep, dep`. */\nfunction formatEntryLine(e: RepoMapEntry): string {\n const shownDeps = e.dependsOn.slice(0, MAX_DEPS_PER_LINE);\n const more = e.dependsOn.length > MAX_DEPS_PER_LINE ? ', …' : '';\n const deps = shownDeps.length > 0 ? ` → ${shownDeps.join(', ')}${more}` : '';\n const calls = e.callSites > 0 ? `, ${String(e.callSites)} call-sites` : '';\n const line = `- ${e.module} (centrality ${e.centrality.toFixed(3)}${calls}, ${String(e.fileCount)} files): ${oneLine(e.purpose)}${deps}`;\n return line.slice(0, MAX_LINE_CHARS);\n}\n\n/** Greedily keep module lines while the running estimate stays within the list budget. */\nfunction fitLinesWithinBudget(\n lines: readonly string[],\n budgetTokens: number\n): { kept: string[]; omitted: number } {\n let used = 0;\n const kept: string[] = [];\n for (const line of lines) {\n const cost = estimateTokens(line) + 1; // +1 for the joining newline\n if (used + cost > budgetTokens) break;\n used += cost;\n kept.push(line);\n }\n return { kept, omitted: lines.length - kept.length };\n}\n\nfunction estimateTokens(text: string): number {\n return Math.ceil(text.length / CHARS_PER_TOKEN);\n}\n\n/** Collapse whitespace + trim so a purpose never breaks the single-line framing. */\nfunction oneLine(value: string): string {\n return value.replace(/\\s+/g, ' ').trim();\n}\n\n// ============================================================================\n// Pull-shaped rank-gate\n// ============================================================================\n\n/** Categories whose tasks plausibly span multiple modules and benefit from a repo-map. */\nconst STRUCTURAL_CATEGORIES: ReadonlySet<TaskCategory> = new Set<TaskCategory>([\n 'architecture',\n 'planning',\n 'code_generation',\n 'code_review',\n 'security_review',\n]);\n\n/** Task-text signals that a task spans cross-file / cross-module structure. */\nconst STRUCTURAL_TASK_PATTERN =\n /architect|refactor|depend|module|cross[- ]file|structure|integrat|migrat|coupl|call ?graph|import ?graph|repo.?map|entry ?point|wiring|data ?flow/i;\n\n/**\n * Rank-gate (#4254 constraint 2): decide whether a task plausibly needs a\n * cross-file repo-map. True for structural categories OR task text that\n * mentions cross-file/module structure. This keeps the provider PULL-shaped —\n * it never contributes on tasks that don't plausibly need a global map.\n */\nexport function taskNeedsRepoMap(task: string, category: TaskCategory): boolean {\n if (STRUCTURAL_CATEGORIES.has(category)) return true;\n return STRUCTURAL_TASK_PATTERN.test(task);\n}\n\n// ============================================================================\n// Provider\n// ============================================================================\n\n/** Options for {@link getRepoMapForTask}. */\nexport interface RepoMapProviderOptions {\n /** Free-text task description (drives the rank-gate). */\n readonly task: string;\n /** Task category (drives the rank-gate). */\n readonly category: TaskCategory;\n /** Token budget for the rendered map. Defaults to {@link DEFAULT_REPO_MAP_TOKEN_BUDGET}. */\n readonly budgetTokens?: number;\n /**\n * Injectable index source. Defaults to {@link buildLiveIndex} (a fresh index\n * built from the current source tree — #4254 constraint 6, no persisted\n * stale map). Injected in tests for a deterministic fixture graph.\n */\n readonly indexProvider?: () => CodebaseIndex;\n /**\n * Injectable per-module call-site counts (#4268). Defaults to a live,\n * bounded {@link computeCallSiteCounts} pass over the index. Injected in tests\n * for a deterministic call-site signal without touching disk.\n */\n readonly callSiteCounts?: ReadonlyMap<string, number>;\n /** Optional logger override. */\n readonly logger?: ILogger;\n}\n\n/**\n * Produce a ranked, budgeted repo-map for a task — or `undefined`. Returns\n * `undefined` (doing no work) when the `NEXUS_REPO_MAP` flag is off or the\n * task doesn't plausibly need cross-file structure, so it is safe to call\n * unconditionally from context assembly. Ranking blends import PageRank with a\n * bounded call-site signal (#4268). Fail-soft: any index-build, call-site, or\n * render error is logged at debug and yields `undefined` / import-only order,\n * never a throw.\n */\nexport function getRepoMapForTask(options: RepoMapProviderOptions): string | undefined {\n if (process.env[REPO_MAP_FLAG] !== '1') return undefined;\n if (!taskNeedsRepoMap(options.task, options.category)) return undefined;\n const log = options.logger ?? createLogger({ component: 'RepoMap' });\n try {\n const index = (options.indexProvider ?? buildLiveIndex)();\n const callSiteCounts = options.callSiteCounts ?? liveCallSiteCounts(index, log);\n const map = buildRepoMap(index, {\n budgetTokens: options.budgetTokens ?? DEFAULT_REPO_MAP_TOKEN_BUDGET,\n callSiteCounts,\n });\n return map === '' ? undefined : map;\n } catch (error: unknown) {\n log.debug('repo-map build failed', {\n error: error instanceof Error ? error.message : String(error),\n });\n return undefined;\n }\n}\n\n/**\n * Compute the bounded call-site signal for a live index: take the TOP-N\n * import-ranked modules ({@link CALLSITE_TOP_N_MODULES}) and count structural\n * call-sites of their exported symbols across the tree (#4268). Best-effort —\n * {@link computeCallSiteCounts} never throws; a failure yields an empty map and\n * ranking degrades to import-only order.\n */\nfunction liveCallSiteCounts(index: CodebaseIndex, log: ILogger): ReadonlyMap<string, number> {\n const topModules = rankRepoMapEntries(index)\n .slice(0, CALLSITE_TOP_N_MODULES)\n .map((e) => e.module);\n return computeCallSiteCounts(index, topModules, { logger: log });\n}\n\n/**\n * Build a FRESH index from the current source tree (#4254 constraint 6 — no\n * persisted/stale map). `extractDescriptions: false` keeps it cheap: the\n * repo-map needs only the module graph + purposes, not per-file JSDoc.\n */\nfunction buildLiveIndex(): CodebaseIndex {\n const extraction = extractProject({ extractDescriptions: false });\n return buildIndex(extraction.files);\n}\n","/**\n * ContextRetriever — the unified read surface every entry point should call\n * to learn what we already know about a task.\n *\n * Phase 2 of #2792. Before this module, each entry point (routing, orchestration,\n * graph workflow, expert creation) reinvented memory access — or, more commonly,\n * skipped it entirely. That made every backend write-only in practice.\n *\n * `getContextForTask({ task, category })` is the one function every entry point\n * calls. It fans out across the shared backends in parallel, tolerates\n * individual failures (never throws), and returns a typed `UnifiedContext`\n * the consumer can either use directly or summarize into a prompt.\n *\n * **Implementation choice — typed singletons, not registry fan-out.**\n * Phase 1 (#2793) made `IMemoryBackend.query()` real on every attached\n * domain, so a registry-level `Promise.all(...domains.map(d => d.query()))`\n * would now work. But the result type is `unknown[]` per domain, which\n * loses the typed shapes consumers want. For typed reads, reaching into\n * `getToolMemory()` and `getOutcomeStore()` directly is cleaner. The\n * registry-level fan-out remains the right path for opaque/observability\n * consumers like `memory_stats`.\n *\n * @module context/context-retriever\n * (Source: #2792 / #2794)\n */\n\nimport type { Belief } from './belief-core-types.js';\nimport type { AgenticMemoryEntry } from './agentic-memory.js';\nimport type { ScoredMemoryEntry } from './adaptive-memory-types.js';\nimport type { ExperienceEntry } from './mobimem-types.js';\nimport type { PerformanceSummary } from '../orchestration/outcomes/outcome-types.js';\nimport type { TaskCategory } from '../config/task-specialization-types.js';\nimport type { DistilledRule } from '../learning/strategy-distiller-types.js';\nimport type { ILogger } from '../core/logger.js';\nimport { createLogger } from '../core/logger.js';\nimport { getToolMemory } from '../mcp/tools/tool-memory.js';\nimport { getOutcomeStore } from '../orchestration/outcomes/outcome-store.js';\nimport { loadPersistedRules } from '../learning/strategy-distiller-persistence.js';\nimport { getResearchStatus } from '../cli/research-helpers.js';\nimport type { TechniqueStatusSummary } from '../cli/research-types.js';\nimport {\n rankMemories,\n topRankedWithinBudget,\n clampToTokenBudget,\n type RankedMemoryItem,\n} from './context-retriever-helpers.js';\nimport { createTokenCounter } from './token-counter.js';\nimport { getTokenLedger } from './token-ledger.js';\nimport { getRepoMapForTask, REPO_MAP_FLAG } from './repo-map.js';\n\n/**\n * What we know about a task, derived from every shared memory backend.\n *\n * Every field is `readonly` and may be empty — consumers should treat\n * absence as \"no signal,\" not failure. Errors fetching any single backend\n * are logged and produce empty results for that field; the function as a\n * whole never throws.\n */\nexport interface UnifiedContext {\n /** Beliefs whose subject matches the task text. */\n readonly beliefs: readonly Belief[];\n /** A-MEM Zettelkasten entries similar to the task. */\n readonly similarMemories: readonly AgenticMemoryEntry[];\n /** Adaptive priority-scored entries ranked by relevance + recency + importance. */\n readonly recentLearnings: readonly ScoredMemoryEntry[];\n /** MobiMem patterns observed for the task type. */\n readonly experiencePatterns: readonly ExperienceEntry[];\n /** Performance summary scoped to the requested category. */\n readonly outcomes: PerformanceSummary | null;\n /** Distilled routing rules — populated once #2797 lands; empty until then. */\n readonly priorStrategies: readonly DistilledRule[];\n /**\n * Prior research techniques from the research registry whose topic/name is\n * relevant to the task (#3148 / #2792 research→context loop). Surfaces what\n * we have already investigated — and its status (implemented / rejected /\n * planned) — so planning reuses research instead of re-proposing settled or\n * already-rejected approaches. Empty when nothing matches or no registry.\n */\n readonly researchInsights: readonly TechniqueStatusSummary[];\n /**\n * All non-aggregate backend items lexically cross-ranked into one comparable,\n * sorted list (#3236). The seven lists above are per-backend and on\n * incomparable scales; this is the single \"globally-best signal first\" view a\n * voter/planning step can read without comparing across backends itself. The\n * aggregate `outcomes` summary is excluded (it is a rollup, not a per-item\n * memory). Additive — the existing lists are unchanged; this is derived from\n * them by {@link rankMemories}.\n */\n readonly rankedMemories: readonly RankedMemoryItem[];\n /**\n * Ranked, token-budgeted repo-map (#4254, Phase 3 of epic #4251): the module\n * import graph ordered by PageRank centrality, carrying an explicit\n * \"import-graph only, no call-site data\" caveat. **Present ONLY when\n * `NEXUS_REPO_MAP=1` AND the task plausibly needs cross-file structure**\n * (pull-shaped / rank-gated — see {@link getRepoMapForTask}). Absent\n * (`undefined`) on every other call, so flag-off `getContextForTask` output\n * is byte-for-byte unchanged. Rendered into the prompt — and measured in the\n * token ledger tagged `repo-map` — by {@link summarizeContextForPrompt}.\n */\n readonly repoMap?: string;\n}\n\n/** Options accepted by {@link getContextForTask}. */\nexport interface ContextRetrieverOptions {\n /** Free-text description of the task. Used as the search term. */\n readonly task: string;\n /** Canonical category for outcome scoping. */\n readonly category: TaskCategory;\n /** Per-backend cap on returned rows. Defaults to 5. */\n readonly limit?: number;\n /** Optional logger override. */\n readonly logger?: ILogger;\n /**\n * Optional correlation id for the calling execution (#3180). When present it\n * is bound to a child logger so every per-backend log line for this retrieval\n * carries the same `executionId`, making a failure traceable back to its\n * graph run. Backward-compatible: the four existing callers omit it.\n */\n readonly executionId?: string;\n}\n\n/** Sensible default — small enough to embed in a prompt, large enough to be useful. */\nconst DEFAULT_LIMIT = 5;\n\n/**\n * The canonical \"what do we already know about this task\" read.\n *\n * Wire this at the top of every entry point: `CompositeRouter.route`,\n * `orchestrate`, graph workflow start, `create_expert`. Even if the\n * consumer initially just logs the result, every backend's read path\n * gets exercised and the silos visibly converge.\n *\n * Latency: O(slowest individual backend). Each backend's call is wrapped\n * so a slow/failing one doesn't block the others. No caching in this\n * version — if a hot caller emerges, layer a TTL cache on top.\n */\nexport async function getContextForTask(options: ContextRetrieverOptions): Promise<UnifiedContext> {\n const limit = options.limit ?? DEFAULT_LIMIT;\n const baseLogger = options.logger ?? createLogger({ component: 'ContextRetriever' });\n // Bind the correlation id to every per-backend log line for this retrieval (#3180).\n const logger =\n options.executionId !== undefined\n ? baseLogger.child({ executionId: options.executionId })\n : baseLogger;\n\n const [\n beliefs,\n similarMemories,\n recentLearnings,\n experiencePatterns,\n outcomes,\n researchInsights,\n ] = await Promise.all([\n fetchBeliefs(options.task, limit, logger),\n fetchSimilarMemories(options.task, limit, logger),\n fetchRecentLearnings(options.task, limit, logger),\n fetchExperiencePatterns(options.task, limit, logger),\n fetchOutcomes(options.category, logger),\n getResearchInsightsForTask(options.task, limit, logger),\n ]);\n\n const priorStrategies = fetchPriorStrategies(options.category, limit, logger);\n\n const base = {\n beliefs,\n similarMemories,\n recentLearnings,\n experiencePatterns,\n outcomes,\n priorStrategies,\n researchInsights,\n };\n\n // Derive the cross-ranked view from the seven per-backend lists (#3236). Pure\n // + fail-soft, so this never affects the lists above or throws.\n const result: UnifiedContext = {\n ...base,\n rankedMemories: rankMemories({ ...base, rankedMemories: [] }, options.task),\n };\n\n // Pull-shaped repo-map (#4254). Returns undefined — doing no work — unless\n // NEXUS_REPO_MAP=1 AND the task plausibly needs cross-file structure, so the\n // key is only added on those calls. Flag off ⇒ `result` is byte-identical to\n // the pre-#4254 return value (the byte-unchanged constraint). Fail-soft.\n const repoMap = getRepoMapForTask({ task: options.task, category: options.category, logger });\n return repoMap === undefined ? result : { ...result, repoMap };\n}\n\n/** Tokens shorter than this are too generic to anchor research relevance. */\nconst MIN_RELEVANCE_TOKEN = 4;\n\n/**\n * Pure relevance filter: select research techniques whose `topic` or `name`\n * shares a meaningful word (≥{@link MIN_RELEVANCE_TOKEN} chars) with the task\n * text. Order-preserving; returns at most `limit`. Exported for direct unit\n * testing of the matching logic (the network/registry read is wrapped\n * separately in {@link getResearchInsightsForTask}).\n */\nexport function selectRelevantResearch(\n techniques: readonly TechniqueStatusSummary[],\n task: string,\n limit: number\n): readonly TechniqueStatusSummary[] {\n const taskTokens = tokenize(task);\n if (taskTokens.size === 0) return [];\n const matches: TechniqueStatusSummary[] = [];\n for (const t of techniques) {\n const fieldTokens = tokenize(`${t.name} ${t.topic}`);\n let hit = false;\n for (const tok of fieldTokens) {\n if (taskTokens.has(tok)) {\n hit = true;\n break;\n }\n }\n if (hit) {\n matches.push(t);\n if (matches.length >= limit) break;\n }\n }\n return matches;\n}\n\n/** Lowercase word set, keeping only tokens long enough to be discriminating. */\nfunction tokenize(text: string): Set<string> {\n const tokens = new Set<string>();\n for (const raw of text.toLowerCase().split(/[^a-z0-9]+/)) {\n if (raw.length >= MIN_RELEVANCE_TOKEN) tokens.add(raw);\n }\n return tokens;\n}\n\n/**\n * Read research-registry techniques relevant to the task. Fail-soft: a missing\n * registry, a failed status read, or any throw yields `[]` so the caller never\n * breaks on the research backend. Uses the lightweight status read (not full\n * synthesis) so it stays cheap enough for a per-task call.\n *\n * Exported so consumers outside the {@link getContextForTask} fan-out can reuse\n * the same relevance read — e.g. the dev-pipeline surfacing prior research to\n * its plan/vote stages (#3472) — without duplicating the fetch+select logic.\n */\nexport async function getResearchInsightsForTask(\n task: string,\n limit: number,\n logger?: ILogger\n): Promise<readonly TechniqueStatusSummary[]> {\n const log = logger ?? createLogger({ component: 'ContextRetriever' });\n try {\n const result = await getResearchStatus({ status: 'all', format: 'json' });\n if (!result.success) return [];\n return selectRelevantResearch(result.techniques, task, limit);\n } catch (error: unknown) {\n log.debug('research insights fetch failed', { error: formatError(error) });\n return [];\n }\n}\n\n/**\n * Phase 5 of #2792 — surface distilled routing rules in the unified\n * context. Reads from the persisted rules file (written by\n * `PersistentStrategyDistiller`) so consumers see the same learnings the\n * CompositeRouter applies at decision time, without needing a live\n * router instance.\n *\n * Filters to (a) `status === 'active'` (rules that aren't deprecated or\n * shadowed), (b) `tainted === false` (security gate — tainted rules\n * never reach consumers per Phase 5 acceptance), and (c) category\n * matching the task's category or a global rule.\n */\nfunction fetchPriorStrategies(\n category: TaskCategory,\n limit: number,\n logger: ILogger\n): readonly DistilledRule[] {\n try {\n const all = loadPersistedRules();\n return all\n .filter((r) => r.status === 'active' && !r.tainted)\n .filter((r) => r.category === category || r.category === '*')\n .slice(0, limit);\n } catch (error: unknown) {\n logger.debug('ContextRetriever: prior-strategies fetch failed', {\n error: formatError(error),\n });\n return [];\n }\n}\n\nasync function fetchBeliefs(\n task: string,\n limit: number,\n logger: ILogger\n): Promise<readonly Belief[]> {\n try {\n const tm = getToolMemory(logger);\n const beliefs = tm.getBeliefMemory();\n const result = await beliefs.recallBySubject(task, limit);\n return result.ok ? result.value : [];\n } catch (error: unknown) {\n logger.debug('ContextRetriever: belief fetch failed', { error: formatError(error) });\n return [];\n }\n}\n\nasync function fetchSimilarMemories(\n task: string,\n limit: number,\n logger: ILogger\n): Promise<readonly AgenticMemoryEntry[]> {\n try {\n const tm = getToolMemory(logger);\n const agentic = tm.getAgenticMemoryBackend();\n if (agentic === null) return [];\n const result = await agentic.searchAgentic(task, limit);\n return result.ok ? result.value : [];\n } catch (error: unknown) {\n logger.debug('ContextRetriever: agentic search failed', { error: formatError(error) });\n return [];\n }\n}\n\nasync function fetchRecentLearnings(\n task: string,\n limit: number,\n logger: ILogger\n): Promise<readonly ScoredMemoryEntry[]> {\n try {\n const tm = getToolMemory(logger);\n const adaptive = tm.getAdaptiveMemoryBackend();\n if (adaptive === null) return [];\n const result = await adaptive.retrieveByPriority({ query: task, limit });\n return result.ok ? result.value : [];\n } catch (error: unknown) {\n logger.debug('ContextRetriever: adaptive fetch failed', { error: formatError(error) });\n return [];\n }\n}\n\nfunction fetchExperiencePatterns(\n task: string,\n limit: number,\n logger: ILogger\n): Promise<readonly ExperienceEntry[]> {\n try {\n const tm = getToolMemory(logger);\n const mobimem = tm.getMobiMem();\n if (mobimem === null) return Promise.resolve([]);\n return Promise.resolve(mobimem.experience.findPatterns(task, limit));\n } catch (error: unknown) {\n logger.debug('ContextRetriever: mobimem fetch failed', { error: formatError(error) });\n return Promise.resolve([]);\n }\n}\n\nfunction fetchOutcomes(\n category: TaskCategory,\n logger: ILogger\n): Promise<PerformanceSummary | null> {\n try {\n const store = getOutcomeStore();\n return Promise.resolve(store.summarize({ category }));\n } catch (error: unknown) {\n logger.debug('ContextRetriever: outcomes fetch failed', { error: formatError(error) });\n return Promise.resolve(null);\n }\n}\n\nfunction formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Best-effort {@link TaskCategory} inference from free-text task content.\n * Used by entry-point wiring (Phase 3 / #2795) when the caller doesn't\n * carry a structured category. Keyword-based; if nothing matches,\n * returns `'exploration'` (which scopes the outcomes summary to the\n * broadest historical baseline).\n *\n * Intentionally simple — this is a *fallback*, not a classifier. Real\n * classification happens at routing time via `cli-adapters/task-classifier`.\n */\nexport function inferTaskCategory(task: string): TaskCategory {\n const t = task.toLowerCase();\n if (/security|vulnerab|cve|threat|owasp|injection|xss/.test(t)) return 'security_review';\n if (/architect|design doc|rfc|adr|system design/.test(t)) return 'architecture';\n if (/test|spec|coverage|vitest|jest|pytest/.test(t)) return 'testing';\n if (/review|audit|critique|feedback/.test(t)) return 'code_review';\n if (/docs|documentation|readme|tutorial|guide/.test(t)) return 'documentation';\n if (/plan|roadmap|epic|sprint|breakdown/.test(t)) return 'planning';\n if (/research|investigate|explore|survey|analyze/.test(t)) return 'research';\n if (/deploy| ci |\\bcd\\b|pipeline|kubernetes|docker|infra|terraform/.test(t)) return 'devops';\n if (/implement|build|create|add|refactor|fix|bug|feature/.test(t)) return 'code_generation';\n return 'exploration';\n}\n\n/** Max chars per interpolated free-text field in a prompt-summary line. */\nconst MAX_SUMMARY_FIELD = 200;\n\n/**\n * Collapse whitespace (including newlines) and cap length for a single backend\n * value before it is interpolated into a prompt-summary line.\n *\n * Defense-in-depth (#3471): every section below renders backend strings into an\n * LLM system-prompt prefix. Without this, a value containing a newline could\n * inject extra un-prefixed lines that escape the `- ` data-framing — a weak\n * prompt-injection vector. Current sources are all T1 repo/internal data so\n * nothing reachable exploits it today, but collapsing + capping makes the\n * framing a local guarantee rather than a cross-module trust inference, and\n * mirrors the hardening already applied to dev-pipeline hindsight recall (#3257).\n */\nfunction oneLine(value: string): string {\n return value.replace(/\\s+/g, ' ').trim().slice(0, MAX_SUMMARY_FIELD);\n}\n\n/**\n * Project a {@link UnifiedContext} into a compact human-readable block\n * suitable for prepending to a system prompt. Skips empty sections so\n * the prefix never wastes tokens on \\\"no signal.\\\"\n *\n * Phase 3 of #2792 — used by `orchestrate` and graph workflow start to\n * surface accumulated memory at the entry point. Every interpolated free-text\n * field is passed through {@link oneLine} (#3471).\n *\n * When `NEXUS_CONTEXT_RANKED=1` (#3236), the per-backend sections are replaced\n * by a single globally-cross-ranked \"Most relevant prior context\" block drawn\n * from {@link UnifiedContext.rankedMemories} within a token budget. Flag-off\n * output is byte-identical to the legacy per-section rendering (as long as\n * the result stays under `budgetTokens` — see the budget guard below).\n *\n * **Per-call context budget guard (#4253):** the assembled block — on BOTH\n * the ranked and legacy rendering paths — is clamped to `budgetTokens`\n * (default {@link DEFAULT_CONTEXT_BUDGET_TOKENS}, the CLAUDE.md \"Standard\"\n * context-budget tier) via {@link clampToTokenBudget}'s char/4 estimate.\n * Before this guard, the legacy path had no cap at all — only per-section\n * `.slice(0, 3-5)` limits, which bound item *count* but not total size. When\n * clamping actually truncates, a trailing notice reports it so callers see\n * backpressure instead of a silent cut. This does not change the\n * memory-backend fan-out or ranking semantics (including the ranked path's\n * own internal {@link RANKED_PREFIX_TOKEN_BUDGET}) — it is a final clamp\n * applied after rendering.\n *\n * **Token ledger wiring (#4252, Phase 0 of epic #4251):** every non-empty\n * result is also recorded in the {@link getTokenLedger} as one `memory-backend`\n * entry, tagged with `variant: 'ranked' | 'legacy'` for which rendering path\n * produced it. This is the single highest-value measurement point named by\n * #4252 — without it, the C3 (#4253 caps) and C1' (#4254 repo-map) savings\n * have no per-call baseline to diff against.\n */\nexport function summarizeContextForPrompt(\n ctx: UnifiedContext,\n budgetTokens: number = DEFAULT_CONTEXT_BUDGET_TOKENS\n): string {\n const ranked = process.env[CONTEXT_RANKED_FLAG] === '1';\n const rendered = ranked ? summarizeRankedContext(ctx) : summarizeLegacyContext(ctx);\n const clamped = clampRenderedContext(rendered, budgetTokens);\n recordAssembledContextTokens(clamped, ranked);\n return appendRepoMapSection(clamped, ctx);\n}\n\n/**\n * Append the ranked repo-map block (#4254) after the memory-backend block when\n * `ctx.repoMap` is present. Its emitted token count is recorded in the token\n * ledger tagged `contextSource: 'repo-map'` — a SEPARATE entry from the\n * memory-backend one — so the repo-map's cost is independently visible for the\n * #4251 A/B. Best-effort (the ledger never throws). When `ctx.repoMap` is\n * absent (flag off / rank-gated out) this returns the memory block unchanged,\n * so flag-off output stays byte-for-byte identical and no `repo-map` ledger\n * entry is written.\n */\nfunction appendRepoMapSection(memoryBlock: string, ctx: UnifiedContext): string {\n const map = ctx.repoMap;\n if (map === undefined || map === '') return memoryBlock;\n recordRepoMapTokens(map);\n return memoryBlock === '' ? map : `${memoryBlock}\\n\\n${map}`;\n}\n\n/** Variant tag recording the flag config that produced a repo-map ledger entry (#4254). */\nconst REPO_MAP_LEDGER_VARIANT = `${REPO_MAP_FLAG}=1`;\n\n/** Record the repo-map's token count in the ledger, tagged `repo-map` (#4254 constraint 5). */\nfunction recordRepoMapTokens(rendered: string): void {\n getTokenLedger().record({\n tool: 'context-retriever.summarizeContextForPrompt',\n contextSource: 'repo-map',\n inputTokens: contextTokenCounter.estimate(rendered),\n variant: REPO_MAP_LEDGER_VARIANT,\n });\n}\n\n/** Shared estimator for the ledger wiring below — builds on `token-counter.ts` (#4252). */\nconst contextTokenCounter = createTokenCounter();\n\n/**\n * Record the assembled-context token count in the per-call token ledger\n * (#4252). Best-effort: {@link getTokenLedger}'s persistence never throws\n * (inherited from the `JsonlStore` contract), so this cannot break context\n * assembly. Skipped for an empty block — there is nothing to measure, and\n * recording it would add \"0 tokens\" noise to every no-signal call.\n */\nfunction recordAssembledContextTokens(rendered: string, ranked: boolean): void {\n if (rendered === '') return;\n getTokenLedger().record({\n tool: 'context-retriever.summarizeContextForPrompt',\n contextSource: 'memory-backend',\n inputTokens: contextTokenCounter.estimate(rendered),\n variant: ranked ? 'ranked' : 'legacy',\n });\n}\n\n/** Default per-call context budget (tokens), applied by {@link summarizeContextForPrompt} (#4253). Matches the CLAUDE.md \"Standard\" context-budget tier (~2,500); pass a different value for a caller in the Minimal (~800) / Research (~1,500) / Full (~6,000) tier. */\nexport const DEFAULT_CONTEXT_BUDGET_TOKENS = 2500;\n\n/** Tokens reserved for the trailing clip notice so the final block stays close to `budgetTokens` once the notice is appended. */\nconst CLIP_NOTICE_RESERVE_TOKENS = 30;\n\n/**\n * Apply the final per-call budget clamp (#4253) to an already-rendered\n * context block, appending a visible notice when clamping actually\n * truncated something. No-op on an empty or already-in-budget block.\n */\nfunction clampRenderedContext(rendered: string, budgetTokens: number): string {\n if (rendered === '') return rendered;\n const contentBudget = Math.max(0, budgetTokens - CLIP_NOTICE_RESERVE_TOKENS);\n const { text: kept, clipped, omittedChars } = clampToTokenBudget(rendered, contentBudget);\n if (!clipped) return rendered;\n return `${kept}\\n\\n_(context clipped to fit the ~${String(budgetTokens)}-token budget; ~${String(omittedChars)} chars omitted — #4253)_`;\n}\n\n/** The legacy (flag-off) per-backend-section rendering (#3148 / #3471). Extracted from {@link summarizeContextForPrompt} so the budget guard wraps both rendering paths identically (#4253). */\nfunction summarizeLegacyContext(ctx: UnifiedContext): string {\n const sections: string[] = [];\n\n if (ctx.beliefs.length > 0) {\n const lines = ctx.beliefs\n .slice(0, 5)\n .map(\n (b) =>\n `- ${oneLine(b.subject)} ${oneLine(b.predicate)} ${oneLine(b.object)} (confidence: ${b.confidence})`\n );\n sections.push(`### Beliefs\\n${lines.join('\\n')}`);\n }\n\n if (ctx.similarMemories.length > 0) {\n const lines = ctx.similarMemories\n .slice(0, 3)\n .map((m) => `- ${oneLine(m.attributes.contextDescription)}`);\n sections.push(`### Similar prior work\\n${lines.join('\\n')}`);\n }\n\n if (ctx.experiencePatterns.length > 0) {\n const lines = ctx.experiencePatterns\n .slice(0, 3)\n .map(\n (p) =>\n `- ${oneLine(p.taskType)}: ${(p.successRate * 100).toFixed(0)}% success over ${String(p.attemptCount)} attempts`\n );\n sections.push(`### Observed patterns\\n${lines.join('\\n')}`);\n }\n\n if (ctx.outcomes !== null && ctx.outcomes.totalTasks > 0) {\n sections.push(\n `### Outcomes for this category\\n- ${String(ctx.outcomes.totalTasks)} prior tasks, ${(ctx.outcomes.successRate * 100).toFixed(0)}% success`\n );\n }\n\n if (ctx.researchInsights.length > 0) {\n const lines = ctx.researchInsights\n .slice(0, 5)\n .map((r) => `- ${oneLine(r.name)} (${oneLine(r.status)}) — ${oneLine(r.topic)}`);\n sections.push(`### Prior research on this topic\\n${lines.join('\\n')}`);\n }\n\n return sections.length === 0 ? '' : `## Prior Context (Nexus Memory)\\n${sections.join('\\n\\n')}`;\n}\n\n/** Rollout gate for the unified cross-ranked prefix rendering (#3236). Default off. */\nconst CONTEXT_RANKED_FLAG = 'NEXUS_CONTEXT_RANKED';\n\n/** Token budget for the ranked prefix block (#3236). Small enough to stay cheap in a system prompt. */\nconst RANKED_PREFIX_TOKEN_BUDGET = 400;\n\n/** Human label per cross-ranked source for the rendered prefix line. */\nconst RANKED_SOURCE_LABEL: Readonly<Record<RankedMemoryItem['source'], string>> = {\n belief: 'belief',\n agentic: 'prior work',\n adaptive: 'learning',\n experience: 'pattern',\n strategy: 'strategy',\n research: 'research',\n};\n\n/**\n * Ranked-mode rendering (#3236): collapse the per-backend sections into one\n * globally-best-first block. Reuses {@link rankMemories} (already applied at\n * retrieval, re-derived here so direct callers of this pure function get the\n * same view) and {@link topRankedWithinBudget} for truncation. Every rendered\n * field still flows through {@link oneLine} — the same sanitization the legacy\n * path applies (#3236 vote condition 3; memory backends are untrusted).\n */\nfunction summarizeRankedContext(ctx: UnifiedContext): string {\n const ranked =\n ctx.rankedMemories.length > 0 ? ctx.rankedMemories : rankMemories(ctx, deriveRankTask(ctx));\n const top = topRankedWithinBudget(ranked, RANKED_PREFIX_TOKEN_BUDGET);\n if (top.length === 0) return '';\n const lines = top.map(\n (r) =>\n `- [${RANKED_SOURCE_LABEL[r.source]}] ${oneLine(r.text)} (relevance: ${r.relevanceScore.toFixed(2)})`\n );\n return `## Prior Context (Nexus Memory)\\n### Most relevant prior context\\n${lines.join('\\n')}`;\n}\n\n/**\n * When `summarizeContextForPrompt` is called directly (not via the retriever),\n * `rankedMemories` may be empty even though the per-backend lists are populated.\n * Derive a task string from the highest-signal backend text so a direct call can\n * still rank. Empty when nothing is present.\n */\nfunction deriveRankTask(ctx: UnifiedContext): string {\n const first = ctx.beliefs[0];\n if (first !== undefined) return `${first.subject} ${first.predicate} ${first.object}`;\n return ctx.similarMemories[0]?.attributes.contextDescription ?? '';\n}\n\n/** Rollout gate for injecting unified context into entry-point prompts (#2921). */\nconst CONTEXT_INJECT_FLAG = 'NEXUS_CONTEXT_RETRIEVER_INJECT';\n\n/**\n * One-call helper for entry points that want to prepend accumulated context to a\n * prompt: returns the {@link summarizeContextForPrompt} block for `task`, or\n * `undefined` when the rollout flag is unset or there is no signal.\n *\n * Centralizes the `NEXUS_CONTEXT_RETRIEVER_INJECT` gate (#2921) and the\n * fetch→summarize sequence so each consumer (orchestrate, execute_expert,\n * pipeline stage-wrappers …) doesn't re-implement it. Default-off and fail-soft:\n * any retrieval error yields `undefined`. Callers whose prompt also feeds a\n * security decision (e.g. an access policy) must still treat the block as\n * untrusted — the underlying memory backends are writable via `memory_write`.\n */\nexport async function getContextPromptPrefix(\n task: string,\n logger?: ILogger\n): Promise<string | undefined> {\n if (process.env[CONTEXT_INJECT_FLAG] !== '1') return undefined;\n const log = logger ?? createLogger({ component: 'ContextRetriever' });\n try {\n const ctx = await getContextForTask({ task, category: inferTaskCategory(task), logger: log });\n const summary = summarizeContextForPrompt(ctx);\n return summary === '' ? undefined : summary;\n } catch (error: unknown) {\n log.debug('context prompt prefix failed', { error: formatError(error) });\n return undefined;\n }\n}\n"],"mappings":"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","names":["msg","lines","err","z","z","yaml","z","getToday","truncate","z","scoreRelevance","fs","path","z","z","fs","path","CHARS_PER_TOKEN","CHARS_PER_TOKEN","z","z","path","path","z","err","path","parts","readFileSync","resolve","parse","resolve","readFileSync","CHARS_PER_TOKEN","oneLine","estimateTokens","oneLine"]}