octocode-cli 1.2.6 → 1.2.8

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 (303) hide show
  1. package/LICENSE +21 -63
  2. package/README.md +85 -142
  3. package/out/octocode-cli.js +7063 -6934
  4. package/package.json +8 -6
  5. package/skills/README.md +97 -120
  6. package/skills/octocode-code-engineer/.claude/settings.local.json +18 -0
  7. package/skills/octocode-code-engineer/.octocode/rfc/RFC-code-engineer-weakness-fixes.md +255 -0
  8. package/skills/octocode-code-engineer/.plan/VALIDATED_PLAN.md +223 -0
  9. package/skills/octocode-code-engineer/README.md +178 -0
  10. package/skills/octocode-code-engineer/SKILL.md +418 -0
  11. package/skills/octocode-code-engineer/coverage/architecture.ts.html +7828 -0
  12. package/skills/octocode-code-engineer/coverage/ast-helpers.ts.html +211 -0
  13. package/skills/octocode-code-engineer/coverage/ast-search.ts.html +1795 -0
  14. package/skills/octocode-code-engineer/coverage/base.css +224 -0
  15. package/skills/octocode-code-engineer/coverage/block-navigation.js +87 -0
  16. package/skills/octocode-code-engineer/coverage/cache.ts.html +376 -0
  17. package/skills/octocode-code-engineer/coverage/cli.ts.html +982 -0
  18. package/skills/octocode-code-engineer/coverage/clover.xml +3217 -0
  19. package/skills/octocode-code-engineer/coverage/collect-effects.ts.html +664 -0
  20. package/skills/octocode-code-engineer/coverage/collect-input-sources.ts.html +577 -0
  21. package/skills/octocode-code-engineer/coverage/collect-performance.ts.html +331 -0
  22. package/skills/octocode-code-engineer/coverage/collect-prototype-pollution.ts.html +421 -0
  23. package/skills/octocode-code-engineer/coverage/collect-security.ts.html +604 -0
  24. package/skills/octocode-code-engineer/coverage/collect-test-profile.ts.html +589 -0
  25. package/skills/octocode-code-engineer/coverage/coverage-final.json +30 -0
  26. package/skills/octocode-code-engineer/coverage/dependencies.ts.html +997 -0
  27. package/skills/octocode-code-engineer/coverage/dependency-summary.ts.html +688 -0
  28. package/skills/octocode-code-engineer/coverage/discovery.ts.html +322 -0
  29. package/skills/octocode-code-engineer/coverage/favicon.png +0 -0
  30. package/skills/octocode-code-engineer/coverage/graph-analytics.ts.html +1510 -0
  31. package/skills/octocode-code-engineer/coverage/index.html +536 -0
  32. package/skills/octocode-code-engineer/coverage/index.ts.html +826 -0
  33. package/skills/octocode-code-engineer/coverage/metrics.ts.html +553 -0
  34. package/skills/octocode-code-engineer/coverage/pipeline.ts.html +2044 -0
  35. package/skills/octocode-code-engineer/coverage/prettify.css +1 -0
  36. package/skills/octocode-code-engineer/coverage/prettify.js +2 -0
  37. package/skills/octocode-code-engineer/coverage/report-analysis.ts.html +1570 -0
  38. package/skills/octocode-code-engineer/coverage/report-writer.ts.html +1102 -0
  39. package/skills/octocode-code-engineer/coverage/security-detectors.ts.html +1747 -0
  40. package/skills/octocode-code-engineer/coverage/semantic-detectors.ts.html +2152 -0
  41. package/skills/octocode-code-engineer/coverage/semantic.ts.html +1897 -0
  42. package/skills/octocode-code-engineer/coverage/sort-arrow-sprite.png +0 -0
  43. package/skills/octocode-code-engineer/coverage/sorter.js +210 -0
  44. package/skills/octocode-code-engineer/coverage/summary-md.ts.html +1222 -0
  45. package/skills/octocode-code-engineer/coverage/test-quality-detectors.ts.html +1039 -0
  46. package/skills/octocode-code-engineer/coverage/tree-sitter-analyzer.ts.html +955 -0
  47. package/skills/octocode-code-engineer/coverage/ts-analyzer.ts.html +1213 -0
  48. package/skills/octocode-code-engineer/coverage/types.ts.html +2473 -0
  49. package/skills/octocode-code-engineer/coverage/utils.ts.html +820 -0
  50. package/skills/octocode-code-engineer/eslint.config.mjs +54 -0
  51. package/skills/octocode-code-engineer/minify-scripts.mjs +32 -0
  52. package/skills/octocode-code-engineer/package.json +54 -0
  53. package/skills/octocode-code-engineer/references/agent-ast-reading-rfc.md +95 -0
  54. package/skills/octocode-code-engineer/references/architecture-techniques.md +121 -0
  55. package/skills/octocode-code-engineer/references/ast-search.md +210 -0
  56. package/skills/octocode-code-engineer/references/ast-tree-search.md +151 -0
  57. package/skills/octocode-code-engineer/references/cli-reference.md +167 -0
  58. package/skills/octocode-code-engineer/references/concepts.md +107 -0
  59. package/skills/octocode-code-engineer/references/finding-categories.md +128 -0
  60. package/skills/octocode-code-engineer/references/improvement-roadmap.md +304 -0
  61. package/skills/octocode-code-engineer/references/output-files.md +144 -0
  62. package/skills/octocode-code-engineer/references/playbooks.md +204 -0
  63. package/skills/octocode-code-engineer/references/present-results.md +136 -0
  64. package/skills/octocode-code-engineer/references/tool-workflows.md +566 -0
  65. package/skills/octocode-code-engineer/references/validate-investigate.md +225 -0
  66. package/skills/octocode-code-engineer/scripts/analysis/dependencies.js +1 -0
  67. package/skills/octocode-code-engineer/scripts/analysis/dependency-summary.js +1 -0
  68. package/skills/octocode-code-engineer/scripts/analysis/discovery.js +1 -0
  69. package/skills/octocode-code-engineer/scripts/analysis/graph-analytics.js +1 -0
  70. package/skills/octocode-code-engineer/scripts/analysis/semantic.js +1 -0
  71. package/skills/octocode-code-engineer/scripts/ast/helpers.js +1 -0
  72. package/skills/octocode-code-engineer/scripts/ast/metrics.js +1 -0
  73. package/skills/octocode-code-engineer/scripts/ast/search.js +2 -0
  74. package/skills/octocode-code-engineer/scripts/ast/tree-search.js +2 -0
  75. package/skills/octocode-code-engineer/scripts/ast/tree-sitter.js +1 -0
  76. package/skills/octocode-code-engineer/scripts/ast/ts-analyzer.js +1 -0
  77. package/skills/octocode-code-engineer/scripts/collectors/chains.js +1 -0
  78. package/skills/octocode-code-engineer/scripts/collectors/effects.js +1 -0
  79. package/skills/octocode-code-engineer/scripts/collectors/input-sources.js +1 -0
  80. package/skills/octocode-code-engineer/scripts/collectors/performance.js +1 -0
  81. package/skills/octocode-code-engineer/scripts/collectors/prototype-pollution.js +1 -0
  82. package/skills/octocode-code-engineer/scripts/collectors/security.js +1 -0
  83. package/skills/octocode-code-engineer/scripts/collectors/test-profile.js +1 -0
  84. package/skills/octocode-code-engineer/scripts/common/is-direct-run.js +1 -0
  85. package/skills/octocode-code-engineer/scripts/common/utils.js +1 -0
  86. package/skills/octocode-code-engineer/scripts/detectors/code-quality.js +1 -0
  87. package/skills/octocode-code-engineer/scripts/detectors/cohesion.js +1 -0
  88. package/skills/octocode-code-engineer/scripts/detectors/coupling.js +1 -0
  89. package/skills/octocode-code-engineer/scripts/detectors/cycle.js +1 -0
  90. package/skills/octocode-code-engineer/scripts/detectors/dead-code.js +1 -0
  91. package/skills/octocode-code-engineer/scripts/detectors/import-style.js +1 -0
  92. package/skills/octocode-code-engineer/scripts/detectors/index.js +1 -0
  93. package/skills/octocode-code-engineer/scripts/detectors/security.js +1 -0
  94. package/skills/octocode-code-engineer/scripts/detectors/semantic.js +1 -0
  95. package/skills/octocode-code-engineer/scripts/detectors/shared.js +1 -0
  96. package/skills/octocode-code-engineer/scripts/detectors/test-quality.js +1 -0
  97. package/skills/octocode-code-engineer/scripts/index.js +1 -0
  98. package/skills/octocode-code-engineer/scripts/pipeline/cache.js +1 -0
  99. package/skills/octocode-code-engineer/scripts/pipeline/cli.js +1 -0
  100. package/skills/octocode-code-engineer/scripts/pipeline/main.js +2 -0
  101. package/skills/octocode-code-engineer/scripts/reporting/analysis.js +1 -0
  102. package/skills/octocode-code-engineer/scripts/reporting/summary-md.js +1 -0
  103. package/skills/octocode-code-engineer/scripts/reporting/writer.js +1 -0
  104. package/skills/octocode-code-engineer/scripts/types/constants.js +1 -0
  105. package/skills/octocode-code-engineer/scripts/types/index.js +1 -0
  106. package/skills/octocode-code-engineer/scripts/types/interfaces.js +1 -0
  107. package/skills/octocode-code-engineer/src/analysis/dependencies.test.ts +545 -0
  108. package/skills/octocode-code-engineer/src/analysis/dependencies.ts +406 -0
  109. package/skills/octocode-code-engineer/src/analysis/dependency-summary.test.ts +566 -0
  110. package/skills/octocode-code-engineer/src/analysis/dependency-summary.ts +257 -0
  111. package/skills/octocode-code-engineer/src/analysis/discovery.test.ts +420 -0
  112. package/skills/octocode-code-engineer/src/analysis/discovery.ts +87 -0
  113. package/skills/octocode-code-engineer/src/analysis/graph-analytics.test.ts +449 -0
  114. package/skills/octocode-code-engineer/src/analysis/graph-analytics.ts +534 -0
  115. package/skills/octocode-code-engineer/src/analysis/semantic.test.ts +1533 -0
  116. package/skills/octocode-code-engineer/src/analysis/semantic.ts +830 -0
  117. package/skills/octocode-code-engineer/src/ast/helpers.test.ts +185 -0
  118. package/skills/octocode-code-engineer/src/ast/helpers.ts +62 -0
  119. package/skills/octocode-code-engineer/src/ast/metrics.test.ts +304 -0
  120. package/skills/octocode-code-engineer/src/ast/metrics.ts +204 -0
  121. package/skills/octocode-code-engineer/src/ast/search.test.ts +647 -0
  122. package/skills/octocode-code-engineer/src/ast/search.ts +648 -0
  123. package/skills/octocode-code-engineer/src/ast/tree-search.test.ts +199 -0
  124. package/skills/octocode-code-engineer/src/ast/tree-search.ts +392 -0
  125. package/skills/octocode-code-engineer/src/ast/tree-sitter.test.ts +407 -0
  126. package/skills/octocode-code-engineer/src/ast/tree-sitter.ts +402 -0
  127. package/skills/octocode-code-engineer/src/ast/ts-analyzer.test.ts +1864 -0
  128. package/skills/octocode-code-engineer/src/ast/ts-analyzer.ts +509 -0
  129. package/skills/octocode-code-engineer/src/collectors/chains.ts +74 -0
  130. package/skills/octocode-code-engineer/src/collectors/effects.test.ts +490 -0
  131. package/skills/octocode-code-engineer/src/collectors/effects.ts +332 -0
  132. package/skills/octocode-code-engineer/src/collectors/input-sources.test.ts +144 -0
  133. package/skills/octocode-code-engineer/src/collectors/input-sources.ts +196 -0
  134. package/skills/octocode-code-engineer/src/collectors/performance.test.ts +82 -0
  135. package/skills/octocode-code-engineer/src/collectors/performance.ts +141 -0
  136. package/skills/octocode-code-engineer/src/collectors/prototype-pollution.test.ts +55 -0
  137. package/skills/octocode-code-engineer/src/collectors/prototype-pollution.ts +162 -0
  138. package/skills/octocode-code-engineer/src/collectors/security.test.ts +124 -0
  139. package/skills/octocode-code-engineer/src/collectors/security.ts +309 -0
  140. package/skills/octocode-code-engineer/src/collectors/test-profile.test.ts +97 -0
  141. package/skills/octocode-code-engineer/src/collectors/test-profile.ts +269 -0
  142. package/skills/octocode-code-engineer/src/common/is-direct-run.test.ts +32 -0
  143. package/skills/octocode-code-engineer/src/common/is-direct-run.ts +13 -0
  144. package/skills/octocode-code-engineer/src/common/utils.test.ts +463 -0
  145. package/skills/octocode-code-engineer/src/common/utils.ts +304 -0
  146. package/skills/octocode-code-engineer/src/detectors/code-quality.ts +966 -0
  147. package/skills/octocode-code-engineer/src/detectors/cohesion.ts +539 -0
  148. package/skills/octocode-code-engineer/src/detectors/coupling.ts +323 -0
  149. package/skills/octocode-code-engineer/src/detectors/cycle.ts +349 -0
  150. package/skills/octocode-code-engineer/src/detectors/dead-code.ts +320 -0
  151. package/skills/octocode-code-engineer/src/detectors/import-style.ts +376 -0
  152. package/skills/octocode-code-engineer/src/detectors/index.test.ts +3061 -0
  153. package/skills/octocode-code-engineer/src/detectors/index.ts +88 -0
  154. package/skills/octocode-code-engineer/src/detectors/security.test.ts +882 -0
  155. package/skills/octocode-code-engineer/src/detectors/security.ts +821 -0
  156. package/skills/octocode-code-engineer/src/detectors/semantic.ts +758 -0
  157. package/skills/octocode-code-engineer/src/detectors/shared.ts +49 -0
  158. package/skills/octocode-code-engineer/src/detectors/test-quality.test.ts +388 -0
  159. package/skills/octocode-code-engineer/src/detectors/test-quality.ts +367 -0
  160. package/skills/octocode-code-engineer/src/index.test.ts +4425 -0
  161. package/skills/octocode-code-engineer/src/index.ts +403 -0
  162. package/skills/octocode-code-engineer/src/pipeline/cache.test.ts +199 -0
  163. package/skills/octocode-code-engineer/src/pipeline/cache.ts +130 -0
  164. package/skills/octocode-code-engineer/src/pipeline/cli.test.ts +493 -0
  165. package/skills/octocode-code-engineer/src/pipeline/cli.ts +344 -0
  166. package/skills/octocode-code-engineer/src/pipeline/main.test.ts +174 -0
  167. package/skills/octocode-code-engineer/src/pipeline/main.ts +1074 -0
  168. package/skills/octocode-code-engineer/src/pipeline.test.ts +84 -0
  169. package/skills/octocode-code-engineer/src/reporting/analysis.test.ts +782 -0
  170. package/skills/octocode-code-engineer/src/reporting/analysis.ts +688 -0
  171. package/skills/octocode-code-engineer/src/reporting/output-contract.test.ts +463 -0
  172. package/skills/octocode-code-engineer/src/reporting/summary-md.test.ts +421 -0
  173. package/skills/octocode-code-engineer/src/reporting/summary-md.ts +714 -0
  174. package/skills/octocode-code-engineer/src/reporting/writer.ts +430 -0
  175. package/skills/octocode-code-engineer/src/sanity.test.ts +47 -0
  176. package/skills/octocode-code-engineer/src/types/constants.ts +248 -0
  177. package/skills/octocode-code-engineer/src/types/index.ts +80 -0
  178. package/skills/octocode-code-engineer/src/types/interfaces.ts +682 -0
  179. package/skills/octocode-code-engineer/tsconfig.json +17 -0
  180. package/skills/octocode-code-engineer/vitest.config.ts +8 -0
  181. package/skills/octocode-documentation-writer/README.md +113 -0
  182. package/skills/octocode-documentation-writer/SKILL.md +886 -0
  183. package/skills/octocode-documentation-writer/references/agent-discovery-analysis.md +453 -0
  184. package/skills/octocode-documentation-writer/references/agent-documentation-writer.md +255 -0
  185. package/skills/octocode-documentation-writer/references/agent-engineer-questions.md +247 -0
  186. package/skills/octocode-documentation-writer/references/agent-orchestrator.md +370 -0
  187. package/skills/octocode-documentation-writer/references/agent-qa-validator.md +227 -0
  188. package/skills/octocode-documentation-writer/references/agent-researcher.md +250 -0
  189. package/skills/octocode-documentation-writer/schemas/analysis-schema.json +886 -0
  190. package/skills/octocode-documentation-writer/schemas/discovery-tasks.json +96 -0
  191. package/skills/octocode-documentation-writer/schemas/documentation-structure.json +373 -0
  192. package/skills/octocode-documentation-writer/schemas/partial-discovery-schema.json +102 -0
  193. package/skills/octocode-documentation-writer/schemas/partial-research-schema.json +98 -0
  194. package/skills/octocode-documentation-writer/schemas/qa-results-schema.json +113 -0
  195. package/skills/octocode-documentation-writer/schemas/questions-schema.json +228 -0
  196. package/skills/octocode-documentation-writer/schemas/research-schema.json +104 -0
  197. package/skills/octocode-documentation-writer/schemas/state-schema.json +222 -0
  198. package/skills/octocode-documentation-writer/schemas/work-assignments-schema.json +74 -0
  199. package/skills/octocode-plan/SKILL.md +122 -116
  200. package/skills/octocode-prompt-optimizer/SKILL.md +617 -0
  201. package/skills/octocode-pull-request-reviewer/README.md +249 -0
  202. package/skills/octocode-pull-request-reviewer/SKILL.md +479 -0
  203. package/skills/octocode-pull-request-reviewer/references/dependency-check.md +74 -0
  204. package/skills/octocode-pull-request-reviewer/references/domain-reviewers.md +24 -0
  205. package/skills/octocode-pull-request-reviewer/references/execution-lifecycle.md +441 -0
  206. package/skills/octocode-pull-request-reviewer/references/flow-analysis-protocol.md +64 -0
  207. package/skills/octocode-pull-request-reviewer/references/output-template.md +174 -0
  208. package/skills/octocode-pull-request-reviewer/references/parallel-agent-protocol.md +182 -0
  209. package/skills/octocode-pull-request-reviewer/references/review-guidelines.md +26 -0
  210. package/skills/octocode-pull-request-reviewer/references/verification-checklist.md +40 -0
  211. package/skills/octocode-research/.claude/settings.local.json +46 -0
  212. package/skills/octocode-research/.octocode/plan/code-review-fixes/plan.md +312 -0
  213. package/skills/octocode-research/.octocode/plan/code-review-fixes/research.md +212 -0
  214. package/skills/octocode-research/.octocode/plans/NODE_SERVER_START_PLAN.md +755 -0
  215. package/skills/octocode-research/.octocode/research/code-review/research.md +371 -0
  216. package/skills/octocode-research/.octocode/review/IMPROVEMENTS.md +391 -0
  217. package/skills/octocode-research/.octocode/review/REVIEW_PLAN.md +289 -0
  218. package/skills/octocode-research/.octocode/review/REVIEW_REPORT.md +356 -0
  219. package/skills/octocode-research/AGENTS.md +349 -0
  220. package/skills/octocode-research/README.md +494 -0
  221. package/skills/octocode-research/SKILL.md +652 -274
  222. package/skills/octocode-research/docs/API_REFERENCE.md +562 -0
  223. package/skills/octocode-research/docs/ARCHITECTURE.md +554 -0
  224. package/skills/octocode-research/docs/FLOWS.md +577 -0
  225. package/skills/octocode-research/docs/OVERVIEW.md +564 -0
  226. package/skills/octocode-research/docs/SERVER_FLOWS.md +631 -0
  227. package/skills/octocode-research/ecosystem.config.cjs +88 -0
  228. package/skills/octocode-research/eslint.config.mjs +27 -0
  229. package/skills/octocode-research/package.json +84 -0
  230. package/skills/octocode-research/references/GUARDRAILS.md +40 -0
  231. package/skills/octocode-research/references/PARALLEL_AGENT_PROTOCOL.md +178 -0
  232. package/skills/octocode-research/references/roast-prompt.md +149 -0
  233. package/skills/octocode-research/scripts/server-init.d.ts +2 -0
  234. package/skills/octocode-research/scripts/server-init.js +2 -0
  235. package/skills/octocode-research/scripts/server.d.ts +8 -0
  236. package/skills/octocode-research/scripts/server.js +445 -0
  237. package/skills/octocode-research/src/__tests__/integration/circuitBreaker.test.ts +205 -0
  238. package/skills/octocode-research/src/__tests__/integration/routes.test.ts +374 -0
  239. package/skills/octocode-research/src/__tests__/unit/circuitBreaker.test.ts +245 -0
  240. package/skills/octocode-research/src/__tests__/unit/errorHandler.test.ts +183 -0
  241. package/skills/octocode-research/src/__tests__/unit/httpPreprocess.test.ts +157 -0
  242. package/skills/octocode-research/src/__tests__/unit/logger.test.ts +143 -0
  243. package/skills/octocode-research/src/__tests__/unit/queryParser.test.ts +130 -0
  244. package/skills/octocode-research/src/__tests__/unit/responseBuilder.test.ts +469 -0
  245. package/skills/octocode-research/src/__tests__/unit/retry.test.ts +205 -0
  246. package/skills/octocode-research/src/index.ts +186 -0
  247. package/skills/octocode-research/src/mcpCache.ts +49 -0
  248. package/skills/octocode-research/src/middleware/errorHandler.ts +65 -0
  249. package/skills/octocode-research/src/middleware/logger.ts +61 -0
  250. package/skills/octocode-research/src/middleware/queryParser.ts +115 -0
  251. package/skills/octocode-research/src/middleware/readiness.ts +17 -0
  252. package/skills/octocode-research/src/routes/github.ts +197 -0
  253. package/skills/octocode-research/src/routes/local.ts +175 -0
  254. package/skills/octocode-research/src/routes/lsp.ts +177 -0
  255. package/skills/octocode-research/src/routes/package.ts +127 -0
  256. package/skills/octocode-research/src/routes/prompts.ts +138 -0
  257. package/skills/octocode-research/src/routes/tools.ts +677 -0
  258. package/skills/octocode-research/src/server-init.ts +363 -0
  259. package/skills/octocode-research/src/server.ts +285 -0
  260. package/skills/octocode-research/src/types/errorGuards.ts +151 -0
  261. package/skills/octocode-research/src/types/express.d.ts +76 -0
  262. package/skills/octocode-research/src/types/guards.ts +98 -0
  263. package/skills/octocode-research/src/types/mcp.ts +119 -0
  264. package/skills/octocode-research/src/types/responses.ts +199 -0
  265. package/skills/octocode-research/src/types/toolTypes.ts +33 -0
  266. package/skills/octocode-research/src/utils/asyncTimeout.ts +116 -0
  267. package/skills/octocode-research/src/utils/circuitBreaker.ts +492 -0
  268. package/skills/octocode-research/src/utils/colors.ts +53 -0
  269. package/skills/octocode-research/src/utils/errorQueue.ts +71 -0
  270. package/skills/octocode-research/src/utils/logEmoji.ts +103 -0
  271. package/skills/octocode-research/src/utils/logger.ts +413 -0
  272. package/skills/octocode-research/src/utils/resilience.ts +169 -0
  273. package/skills/octocode-research/src/utils/responseBuilder.ts +495 -0
  274. package/skills/octocode-research/src/utils/responseFactory.ts +100 -0
  275. package/skills/octocode-research/src/utils/responseParser.ts +272 -0
  276. package/skills/octocode-research/src/utils/retry.ts +280 -0
  277. package/skills/octocode-research/src/utils/routeFactory.ts +117 -0
  278. package/skills/octocode-research/src/utils/url.ts +20 -0
  279. package/skills/octocode-research/src/validation/httpPreprocess.ts +155 -0
  280. package/skills/octocode-research/src/validation/index.ts +2 -0
  281. package/skills/octocode-research/src/validation/schemas.ts +578 -0
  282. package/skills/octocode-research/src/validation/toolCallSchema.ts +132 -0
  283. package/skills/octocode-research/tsconfig.json +21 -0
  284. package/skills/octocode-research/tsdown.config.ts +42 -0
  285. package/skills/octocode-research/vitest.config.ts +20 -0
  286. package/skills/octocode-researcher/SKILL.md +461 -0
  287. package/skills/octocode-researcher/references/fallbacks.md +120 -0
  288. package/skills/{octocode-local-search → octocode-researcher}/references/tool-reference.md +132 -49
  289. package/skills/{octocode-local-search → octocode-researcher}/references/workflow-patterns.md +204 -4
  290. package/skills/octocode-rfc-generator/SKILL.md +223 -0
  291. package/skills/octocode-rfc-generator/references/rfc-template.md +193 -0
  292. package/skills/octocode-roast/SKILL.md +63 -21
  293. package/skills/octocode-implement/SKILL.md +0 -293
  294. package/skills/octocode-implement/references/execution-phases.md +0 -317
  295. package/skills/octocode-implement/references/tool-reference.md +0 -403
  296. package/skills/octocode-implement/references/workflow-patterns.md +0 -385
  297. package/skills/octocode-local-search/SKILL.md +0 -449
  298. package/skills/octocode-pr-review/SKILL.md +0 -391
  299. package/skills/octocode-pr-review/references/domain-reviewers.md +0 -105
  300. package/skills/octocode-pr-review/references/execution-lifecycle.md +0 -116
  301. package/skills/octocode-pr-review/references/research-flows.md +0 -75
  302. package/skills/octocode-research/references/tool-reference.md +0 -304
  303. package/skills/octocode-research/references/workflow-patterns.md +0 -325
@@ -0,0 +1,782 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import {
4
+ computeReportAnalysisSummary,
5
+ enrichFileInventoryEntries,
6
+ enrichFindings,
7
+ } from './analysis.js';
8
+
9
+ import type { GraphAnalyticsSummary } from '../analysis/graph-analytics.js';
10
+ import type { FileEntry, Finding } from '../types/index.js';
11
+
12
+ function makeFileEntry(override: Partial<FileEntry> = {}): FileEntry {
13
+ return {
14
+ package: 'pkg',
15
+ file: 'src/file.ts',
16
+ parseEngine: 'typescript',
17
+ nodeCount: 1,
18
+ kindCounts: {},
19
+ functions: [],
20
+ flows: [],
21
+ dependencyProfile: {
22
+ internalDependencies: [],
23
+ externalDependencies: [],
24
+ unresolvedDependencies: [],
25
+ declaredExports: [],
26
+ importedSymbols: [],
27
+ reExports: [],
28
+ },
29
+ ...override,
30
+ };
31
+ }
32
+
33
+ function makeFinding(override: Partial<Finding> = {}): Finding {
34
+ return {
35
+ id: 'test-1',
36
+ severity: 'medium',
37
+ category: 'function-optimization',
38
+ file: 'src/file.ts',
39
+ lineStart: 10,
40
+ lineEnd: 20,
41
+ title: 'Test finding',
42
+ reason: 'Test reason',
43
+ files: ['src/file.ts'],
44
+ suggestedFix: { strategy: 'strategy', steps: ['step1'] },
45
+ ...override,
46
+ };
47
+ }
48
+
49
+ function makeGraphAnalytics(
50
+ override: Partial<GraphAnalyticsSummary> = {}
51
+ ): GraphAnalyticsSummary {
52
+ return {
53
+ sccClusters: [],
54
+ chokepoints: [],
55
+ packageGraphSummary: {
56
+ packageCount: 0,
57
+ edgeCount: 0,
58
+ packages: [],
59
+ hotspots: [],
60
+ },
61
+ articulationPoints: [],
62
+ bridgeEdges: [],
63
+ ...override,
64
+ };
65
+ }
66
+
67
+ describe('enrichFileInventoryEntries', () => {
68
+ it('adds effectProfile when topLevelEffects present', () => {
69
+ const entry = makeFileEntry({
70
+ topLevelEffects: [
71
+ {
72
+ kind: 'eval',
73
+ lineStart: 1,
74
+ lineEnd: 1,
75
+ detail: 'eval call',
76
+ weight: 10,
77
+ confidence: 'high',
78
+ },
79
+ ],
80
+ });
81
+ const [enriched] = enrichFileInventoryEntries([entry]);
82
+ expect(enriched.effectProfile).toBeDefined();
83
+ expect(enriched.effectProfile!.totalEffects).toBe(1);
84
+ expect(enriched.effectProfile!.highestRisk).toBe('eval');
85
+ });
86
+
87
+ it('adds symbolUsageSummary with declaredExportCount and importedSymbolCount', () => {
88
+ const entry = makeFileEntry({
89
+ dependencyProfile: {
90
+ internalDependencies: [],
91
+ externalDependencies: ['lodash'],
92
+ unresolvedDependencies: [],
93
+ declaredExports: [
94
+ { name: 'foo', kind: 'value' },
95
+ { name: 'bar', kind: 'value' },
96
+ ],
97
+ importedSymbols: [
98
+ {
99
+ sourceModule: 'lodash',
100
+ importedName: 'get',
101
+ localName: 'get',
102
+ isTypeOnly: false,
103
+ },
104
+ ],
105
+ reExports: [],
106
+ },
107
+ });
108
+ const [enriched] = enrichFileInventoryEntries([entry]);
109
+ expect(enriched.symbolUsageSummary).toBeDefined();
110
+ expect(enriched.symbolUsageSummary!.declaredExportCount).toBe(2);
111
+ expect(enriched.symbolUsageSummary!.importedSymbolCount).toBe(1);
112
+ });
113
+
114
+ it('adds boundaryRoleHints based on file path', () => {
115
+ const entry = makeFileEntry({ file: 'src/index.ts' });
116
+ const [enriched] = enrichFileInventoryEntries([entry]);
117
+ expect(enriched.boundaryRoleHints).toBeDefined();
118
+ expect(enriched.boundaryRoleHints!.length).toBeGreaterThan(0);
119
+ expect(enriched.boundaryRoleHints!.some(h => h.role === 'entrypoint')).toBe(
120
+ true
121
+ );
122
+ });
123
+
124
+ it('adds cfgFlags when flowEnabled=true', () => {
125
+ const entry = makeFileEntry();
126
+ const [enriched] = enrichFileInventoryEntries([entry], {
127
+ flowEnabled: true,
128
+ });
129
+ expect(enriched.cfgFlags).toBeDefined();
130
+ expect(typeof enriched.cfgFlags!.exitPointCount).toBe('number');
131
+ expect(typeof enriched.cfgFlags!.hasValidationChecks).toBe('boolean');
132
+ });
133
+
134
+ it('does NOT add cfgFlags when flowEnabled=false', () => {
135
+ const entry = makeFileEntry();
136
+ const [enriched] = enrichFileInventoryEntries([entry], {
137
+ flowEnabled: false,
138
+ });
139
+ expect(enriched.cfgFlags).toBeUndefined();
140
+ });
141
+
142
+ it('preserves existing effectProfile if already set', () => {
143
+ const existing = {
144
+ totalEffects: 99,
145
+ totalWeight: 100,
146
+ byKind: {},
147
+ highestRisk: null,
148
+ };
149
+ const entry = makeFileEntry({
150
+ effectProfile: existing,
151
+ topLevelEffects: [
152
+ {
153
+ kind: 'eval',
154
+ lineStart: 1,
155
+ lineEnd: 1,
156
+ detail: 'eval call',
157
+ weight: 10,
158
+ confidence: 'high',
159
+ },
160
+ ],
161
+ });
162
+ const [enriched] = enrichFileInventoryEntries([entry]);
163
+ expect(enriched.effectProfile!.totalEffects).toBe(99);
164
+ });
165
+
166
+ it('empty entry gets symbolUsageSummary with zeros', () => {
167
+ const entry = makeFileEntry();
168
+ const [enriched] = enrichFileInventoryEntries([entry]);
169
+ expect(enriched.symbolUsageSummary).toBeDefined();
170
+ expect(enriched.symbolUsageSummary!.declaredExportCount).toBe(0);
171
+ expect(enriched.symbolUsageSummary!.importedSymbolCount).toBe(0);
172
+ expect(enriched.symbolUsageSummary!.internalImportCount).toBe(0);
173
+ expect(enriched.symbolUsageSummary!.externalImportCount).toBe(0);
174
+ expect(enriched.symbolUsageSummary!.reExportCount).toBe(0);
175
+ });
176
+
177
+ it('adds shared-utility boundary role hint when many exports and few imports', () => {
178
+ const entry = makeFileEntry({
179
+ file: 'src/utils/helpers.ts',
180
+ dependencyProfile: {
181
+ internalDependencies: [],
182
+ externalDependencies: [],
183
+ unresolvedDependencies: [],
184
+ declaredExports: Array.from({ length: 10 }, (_, i) => ({
185
+ name: `fn${i}`,
186
+ kind: 'value' as const,
187
+ })),
188
+ importedSymbols: [
189
+ {
190
+ sourceModule: './other',
191
+ resolvedModule: 'src/other.ts',
192
+ importedName: 'x',
193
+ localName: 'x',
194
+ isTypeOnly: false,
195
+ },
196
+ ],
197
+ reExports: [],
198
+ },
199
+ });
200
+ const [enriched] = enrichFileInventoryEntries([entry]);
201
+ expect(
202
+ enriched.boundaryRoleHints!.some(h => h.role === 'shared-utility')
203
+ ).toBe(true);
204
+ });
205
+
206
+ it('adds runtime-bootstrap hint when topLevelEffects present', () => {
207
+ const entry = makeFileEntry({
208
+ file: 'src/bootstrap.ts',
209
+ topLevelEffects: [
210
+ {
211
+ kind: 'eval',
212
+ lineStart: 1,
213
+ lineEnd: 1,
214
+ detail: 'eval',
215
+ weight: 5,
216
+ confidence: 'medium',
217
+ },
218
+ ],
219
+ });
220
+ const [enriched] = enrichFileInventoryEntries([entry]);
221
+ expect(
222
+ enriched.boundaryRoleHints!.some(h => h.role === 'runtime-bootstrap')
223
+ ).toBe(true);
224
+ });
225
+ });
226
+
227
+ describe('enrichFindings', () => {
228
+ it('adds analysisLens based on category', () => {
229
+ const graphFinding = makeFinding({
230
+ id: 'g1',
231
+ category: 'dependency-cycle',
232
+ });
233
+ const astFinding = makeFinding({
234
+ id: 'a1',
235
+ category: 'function-optimization',
236
+ });
237
+ const hybridFinding = makeFinding({
238
+ id: 'h1',
239
+ category: 'hardcoded-secret',
240
+ });
241
+ const results = enrichFindings(
242
+ [graphFinding, astFinding, hybridFinding],
243
+ [],
244
+ [],
245
+ null
246
+ );
247
+ expect(results[0].analysisLens).toBe('graph');
248
+ expect(results[1].analysisLens).toBe('ast');
249
+ expect(results[2].analysisLens).toBe('hybrid');
250
+ });
251
+
252
+ it('adds ruleId in format {lens}.{category} when not set', () => {
253
+ const finding = makeFinding({ category: 'function-optimization' });
254
+ const [enriched] = enrichFindings([finding], [], [], null);
255
+ expect(enriched.ruleId).toBe('ast.function-optimization');
256
+ });
257
+
258
+ it('preserves existing ruleId when already set', () => {
259
+ const finding = makeFinding({ ruleId: 'custom.rule' });
260
+ const [enriched] = enrichFindings([finding], [], [], null);
261
+ expect(enriched.ruleId).toBe('custom.rule');
262
+ });
263
+
264
+ it('adds confidence based on severity and lens', () => {
265
+ const critical = makeFinding({ id: 'c1', severity: 'critical' });
266
+ const graphMedium = makeFinding({
267
+ id: 'g1',
268
+ severity: 'medium',
269
+ category: 'dependency-cycle',
270
+ });
271
+ const astLow = makeFinding({
272
+ id: 'a1',
273
+ severity: 'low',
274
+ category: 'function-optimization',
275
+ });
276
+ const results = enrichFindings(
277
+ [critical, graphMedium, astLow],
278
+ [],
279
+ [],
280
+ null
281
+ );
282
+ expect(results[0].confidence).toBe('high');
283
+ expect(results[1].confidence).toBe('medium');
284
+ expect(results[2].confidence).toBe('low');
285
+ });
286
+
287
+ it('adds correlatedSignals including hot-file when file is in hotFiles', () => {
288
+ const finding = makeFinding({ file: 'src/hot.ts' });
289
+ const hotFiles = [
290
+ {
291
+ file: 'src/hot.ts',
292
+ riskScore: 10,
293
+ fanIn: 5,
294
+ fanOut: 5,
295
+ complexityScore: 3,
296
+ exportCount: 2,
297
+ inCycle: false,
298
+ onCriticalPath: false,
299
+ },
300
+ ];
301
+ const [enriched] = enrichFindings([finding], [], hotFiles, null);
302
+ expect(enriched.correlatedSignals).toContain('hot-file');
303
+ });
304
+
305
+ it('adds correlatedSignals cycle-context when file is in SCC cluster', () => {
306
+ const finding = makeFinding({ file: 'src/cycle.ts' });
307
+ const ga = makeGraphAnalytics({
308
+ sccClusters: [
309
+ {
310
+ id: 'scc-0',
311
+ files: ['src/cycle.ts', 'src/other.ts'],
312
+ nodeCount: 2,
313
+ edgeCount: 2,
314
+ entryEdges: 1,
315
+ exitEdges: 1,
316
+ hubFiles: [],
317
+ },
318
+ ],
319
+ });
320
+ const [enriched] = enrichFindings([finding], [], [], ga);
321
+ expect(enriched.correlatedSignals).toContain('cycle-context');
322
+ });
323
+
324
+ it('adds recommendedValidation with tools array', () => {
325
+ const finding = makeFinding();
326
+ const [enriched] = enrichFindings([finding], [], [], null);
327
+ expect(enriched.recommendedValidation).toBeDefined();
328
+ expect(Array.isArray(enriched.recommendedValidation!.tools)).toBe(true);
329
+ expect(enriched.recommendedValidation!.tools.length).toBeGreaterThan(0);
330
+ });
331
+
332
+ it('adds flowTrace when flowEnabled=true and evidence has propagationSteps', () => {
333
+ const finding = makeFinding({
334
+ evidence: { propagationSteps: ['src/a.ts:10-20', 'src/b.ts:30'] },
335
+ });
336
+ const [enriched] = enrichFindings([finding], [], [], null, {
337
+ flowEnabled: true,
338
+ });
339
+ expect(enriched.flowTrace).toBeDefined();
340
+ expect(enriched.flowTrace!.length).toBe(2);
341
+ expect(enriched.flowTrace![0].file).toBe('src/a.ts');
342
+ });
343
+
344
+ it('does NOT add flowTrace when flowEnabled=false', () => {
345
+ const finding = makeFinding({
346
+ evidence: { propagationSteps: ['src/a.ts:10-20'] },
347
+ });
348
+ const [enriched] = enrichFindings([finding], [], [], null, {
349
+ flowEnabled: false,
350
+ });
351
+ expect(enriched.flowTrace).toBeUndefined();
352
+ });
353
+
354
+ it('adds paired:{category} to correlatedSignals for multiple findings on same file', () => {
355
+ const f1 = makeFinding({
356
+ id: 'f1',
357
+ category: 'function-optimization',
358
+ file: 'src/shared.ts',
359
+ });
360
+ const f2 = makeFinding({
361
+ id: 'f2',
362
+ category: 'cognitive-complexity',
363
+ file: 'src/shared.ts',
364
+ });
365
+ const results = enrichFindings([f1, f2], [], [], null);
366
+ expect(results[0].correlatedSignals).toContain(
367
+ 'paired:cognitive-complexity'
368
+ );
369
+ expect(results[1].correlatedSignals).toContain(
370
+ 'paired:function-optimization'
371
+ );
372
+ });
373
+ });
374
+
375
+ describe('computeReportAnalysisSummary', () => {
376
+ it('returns graphSignals when graphAnalytics has chokepoints', () => {
377
+ const ga = makeGraphAnalytics({
378
+ chokepoints: [
379
+ {
380
+ file: 'src/hub.ts',
381
+ score: 50,
382
+ reasons: ['high fan-in'],
383
+ fanIn: 10,
384
+ fanOut: 5,
385
+ articulation: true,
386
+ bridgeCount: 1,
387
+ cycleClusterCount: 0,
388
+ onCriticalPath: true,
389
+ },
390
+ ],
391
+ });
392
+ const result = computeReportAnalysisSummary([], [], [], ga);
393
+ expect(result.graphSignals.length).toBeGreaterThan(0);
394
+ expect(result.graphSignals[0].kind).toBe('structural-chokepoint');
395
+ });
396
+
397
+ it('returns graphSignals for cycle clusters', () => {
398
+ const ga = makeGraphAnalytics({
399
+ sccClusters: [
400
+ {
401
+ id: 'scc-0',
402
+ files: ['a.ts', 'b.ts'],
403
+ nodeCount: 2,
404
+ edgeCount: 3,
405
+ entryEdges: 1,
406
+ exitEdges: 1,
407
+ hubFiles: ['a.ts'],
408
+ },
409
+ ],
410
+ });
411
+ const result = computeReportAnalysisSummary([], [], [], ga);
412
+ expect(result.graphSignals.some(s => s.kind === 'cycle-cluster')).toBe(
413
+ true
414
+ );
415
+ });
416
+
417
+ it('returns astSignals for low-cohesion + feature-envy pair', () => {
418
+ const entry = makeFileEntry({ file: 'src/leak.ts' });
419
+ const findings = [
420
+ makeFinding({ id: 'lc', category: 'low-cohesion', file: 'src/leak.ts' }),
421
+ makeFinding({ id: 'fe', category: 'feature-envy', file: 'src/leak.ts' }),
422
+ ];
423
+ const enriched = enrichFindings(findings, [entry], [], null);
424
+ const result = computeReportAnalysisSummary(enriched, [entry], [], null);
425
+ expect(result.astSignals.length).toBeGreaterThan(0);
426
+ expect(result.astSignals[0].kind).toBe('boundary-leak-shape');
427
+ });
428
+
429
+ it('returns combined interpretation with shared file and confidence high', () => {
430
+ const entry = makeFileEntry({ file: 'src/shared.ts' });
431
+ const ga = makeGraphAnalytics({
432
+ chokepoints: [
433
+ {
434
+ file: 'src/shared.ts',
435
+ score: 50,
436
+ reasons: ['high fan-in'],
437
+ fanIn: 10,
438
+ fanOut: 5,
439
+ articulation: true,
440
+ bridgeCount: 1,
441
+ cycleClusterCount: 0,
442
+ onCriticalPath: true,
443
+ },
444
+ ],
445
+ });
446
+ const findings = [
447
+ makeFinding({
448
+ id: 'lc',
449
+ category: 'low-cohesion',
450
+ file: 'src/shared.ts',
451
+ }),
452
+ makeFinding({
453
+ id: 'fe',
454
+ category: 'feature-envy',
455
+ file: 'src/shared.ts',
456
+ }),
457
+ ];
458
+ const enriched = enrichFindings(findings, [entry], [], ga);
459
+ const result = computeReportAnalysisSummary(enriched, [entry], [], ga);
460
+ expect(result.combinedInterpretation).not.toBeNull();
461
+ expect(result.combinedInterpretation!.confidence).toBe('high');
462
+ });
463
+
464
+ it('returns combined interpretation with different files and confidence medium', () => {
465
+ const entry1 = makeFileEntry({ file: 'src/graph-file.ts' });
466
+ const entry2 = makeFileEntry({ file: 'src/ast-file.ts' });
467
+ const ga = makeGraphAnalytics({
468
+ chokepoints: [
469
+ {
470
+ file: 'src/graph-file.ts',
471
+ score: 50,
472
+ reasons: ['high fan-in'],
473
+ fanIn: 10,
474
+ fanOut: 5,
475
+ articulation: false,
476
+ bridgeCount: 0,
477
+ cycleClusterCount: 0,
478
+ onCriticalPath: true,
479
+ },
480
+ ],
481
+ });
482
+ const findings = [
483
+ makeFinding({
484
+ id: 'lc',
485
+ category: 'low-cohesion',
486
+ file: 'src/ast-file.ts',
487
+ }),
488
+ makeFinding({
489
+ id: 'fe',
490
+ category: 'feature-envy',
491
+ file: 'src/ast-file.ts',
492
+ }),
493
+ ];
494
+ const enriched = enrichFindings(findings, [entry1, entry2], [], ga);
495
+ const result = computeReportAnalysisSummary(
496
+ enriched,
497
+ [entry1, entry2],
498
+ [],
499
+ ga
500
+ );
501
+ expect(result.combinedInterpretation).not.toBeNull();
502
+ expect(result.combinedInterpretation!.confidence).toBe('medium');
503
+ });
504
+
505
+ it('returns investigationPrompts based on signals', () => {
506
+ const ga = makeGraphAnalytics({
507
+ chokepoints: [
508
+ {
509
+ file: 'src/hub.ts',
510
+ score: 50,
511
+ reasons: ['high fan-in'],
512
+ fanIn: 10,
513
+ fanOut: 5,
514
+ articulation: true,
515
+ bridgeCount: 1,
516
+ cycleClusterCount: 0,
517
+ onCriticalPath: true,
518
+ },
519
+ ],
520
+ });
521
+ const result = computeReportAnalysisSummary([], [], [], ga);
522
+ expect(Array.isArray(result.investigationPrompts)).toBe(true);
523
+ expect(result.investigationPrompts.length).toBeGreaterThan(0);
524
+ });
525
+
526
+ it('empty inputs produce all fields present but empty/null', () => {
527
+ const result = computeReportAnalysisSummary([], [], [], null);
528
+ expect(result.graphSignals).toEqual([]);
529
+ expect(result.astSignals).toEqual([]);
530
+ expect(result.combinedSignals).toEqual([]);
531
+ expect(result.strongestGraphSignal).toBeNull();
532
+ expect(result.strongestAstSignal).toBeNull();
533
+ expect(result.combinedInterpretation).toBeNull();
534
+ expect(result.recommendedValidation).toBeNull();
535
+ expect(Array.isArray(result.investigationPrompts)).toBe(true);
536
+ });
537
+
538
+ it('only graph signal produces combined interpretation using that signal', () => {
539
+ const ga = makeGraphAnalytics({
540
+ chokepoints: [
541
+ {
542
+ file: 'src/hub.ts',
543
+ score: 50,
544
+ reasons: ['high fan-in'],
545
+ fanIn: 10,
546
+ fanOut: 5,
547
+ articulation: false,
548
+ bridgeCount: 0,
549
+ cycleClusterCount: 0,
550
+ onCriticalPath: false,
551
+ },
552
+ ],
553
+ });
554
+ const result = computeReportAnalysisSummary([], [], [], ga);
555
+ expect(result.strongestGraphSignal).not.toBeNull();
556
+ expect(result.strongestAstSignal).toBeNull();
557
+ expect(result.combinedInterpretation).not.toBeNull();
558
+ expect(result.combinedInterpretation!.lens).toBe('graph');
559
+ });
560
+
561
+ it('returns high confidence for cycle cluster with nodeCount >= 5', () => {
562
+ const ga = makeGraphAnalytics({
563
+ sccClusters: [
564
+ {
565
+ id: 'scc-large',
566
+ files: ['a.ts', 'b.ts', 'c.ts', 'd.ts', 'e.ts'],
567
+ nodeCount: 5,
568
+ edgeCount: 8,
569
+ entryEdges: 1,
570
+ exitEdges: 1,
571
+ hubFiles: ['a.ts'],
572
+ },
573
+ ],
574
+ });
575
+ const result = computeReportAnalysisSummary([], [], [], ga);
576
+ const cycleSignal = result.graphSignals.find(
577
+ s => s.kind === 'cycle-cluster'
578
+ );
579
+ expect(cycleSignal).toBeDefined();
580
+ expect(cycleSignal!.confidence).toBe('high');
581
+ });
582
+
583
+ it('adds hybrid investigation prompt when combinedInterpretation exists but confidence is not high', () => {
584
+ const entry1 = makeFileEntry({ file: 'src/graph-only.ts' });
585
+ const entry2 = makeFileEntry({ file: 'src/ast-only.ts' });
586
+ const ga = makeGraphAnalytics({
587
+ chokepoints: [
588
+ {
589
+ file: 'src/graph-only.ts',
590
+ score: 50,
591
+ reasons: ['high fan-in'],
592
+ fanIn: 10,
593
+ fanOut: 5,
594
+ articulation: false,
595
+ bridgeCount: 0,
596
+ cycleClusterCount: 0,
597
+ onCriticalPath: true,
598
+ },
599
+ ],
600
+ });
601
+ const findings = [
602
+ makeFinding({
603
+ id: 'lc',
604
+ category: 'low-cohesion',
605
+ file: 'src/ast-only.ts',
606
+ }),
607
+ makeFinding({
608
+ id: 'fe',
609
+ category: 'feature-envy',
610
+ file: 'src/ast-only.ts',
611
+ }),
612
+ ];
613
+ const enriched = enrichFindings(findings, [entry1, entry2], [], ga);
614
+ const result = computeReportAnalysisSummary(
615
+ enriched,
616
+ [entry1, entry2],
617
+ [],
618
+ ga
619
+ );
620
+ expect(result.combinedInterpretation).not.toBeNull();
621
+ expect(result.combinedInterpretation!.confidence).toBe('medium');
622
+ expect(
623
+ result.investigationPrompts.some(p => p.includes('hybrid investigation'))
624
+ ).toBe(true);
625
+ });
626
+
627
+ it('returns high confidence for package hotspot with edges >= 8', () => {
628
+ const ga = makeGraphAnalytics({
629
+ packageGraphSummary: {
630
+ packageCount: 2,
631
+ edgeCount: 20,
632
+ packages: [],
633
+ hotspots: [{ from: 'pkg-a', to: 'pkg-b', edges: 10 }],
634
+ },
635
+ });
636
+ const result = computeReportAnalysisSummary([], [], [], ga);
637
+ const pkgSignal = result.graphSignals.find(
638
+ s => s.kind === 'package-chatter'
639
+ );
640
+ expect(pkgSignal).toBeDefined();
641
+ expect(pkgSignal!.confidence).toBe('high');
642
+ });
643
+
644
+ it('returns mega-folder graph signal when mega-folder finding is present', () => {
645
+ const findings = [
646
+ makeFinding({
647
+ id: 'mega',
648
+ category: 'mega-folder',
649
+ file: 'src/core/index.ts',
650
+ files: ['src/core/a.ts', 'src/core/b.ts'],
651
+ evidence: {
652
+ folderPath: 'src/core',
653
+ fileCount: 42,
654
+ concentration: 0.54,
655
+ },
656
+ }),
657
+ ];
658
+ const result = computeReportAnalysisSummary(findings, [], [], null);
659
+ const mega = result.graphSignals.find(
660
+ s => s.kind === 'mega-folder-cluster'
661
+ );
662
+ expect(mega).toBeDefined();
663
+ expect(mega!.summary).toContain('src/core');
664
+ expect(
665
+ result.investigationPrompts.some(p => p.includes('migration script'))
666
+ ).toBe(true);
667
+ });
668
+
669
+ it('returns hidden-initialization ast signal when entry has effects and import-side-effect-risk', () => {
670
+ const entry = makeFileEntry({
671
+ file: 'src/init.ts',
672
+ effectProfile: {
673
+ totalEffects: 2,
674
+ totalWeight: 15,
675
+ byKind: {},
676
+ highestRisk: 'eval' as const,
677
+ },
678
+ topLevelEffects: [
679
+ {
680
+ kind: 'eval',
681
+ lineStart: 1,
682
+ lineEnd: 1,
683
+ detail: 'eval',
684
+ weight: 10,
685
+ confidence: 'high',
686
+ },
687
+ ],
688
+ });
689
+ const findings = [
690
+ makeFinding({
691
+ id: 'es',
692
+ category: 'import-side-effect-risk',
693
+ file: 'src/init.ts',
694
+ }),
695
+ ];
696
+ const enriched = enrichFindings(findings, [entry], [], null);
697
+ const result = computeReportAnalysisSummary(enriched, [entry], [], null);
698
+ const hiddenSignal = result.astSignals.find(
699
+ s => s.kind === 'hidden-initialization'
700
+ );
701
+ expect(hiddenSignal).toBeDefined();
702
+ });
703
+
704
+ it('returns orchestration-duplication ast signal when file has duplicate-flow-structure and function-optimization', () => {
705
+ const entry = makeFileEntry({ file: 'src/orchestrate.ts' });
706
+ const findings = [
707
+ makeFinding({
708
+ id: 'df',
709
+ category: 'duplicate-flow-structure',
710
+ file: 'src/orchestrate.ts',
711
+ }),
712
+ makeFinding({
713
+ id: 'fo',
714
+ category: 'function-optimization',
715
+ file: 'src/orchestrate.ts',
716
+ }),
717
+ ];
718
+ const enriched = enrichFindings(findings, [entry], [], null);
719
+ const result = computeReportAnalysisSummary(enriched, [entry], [], null);
720
+ const orchSignal = result.astSignals.find(
721
+ s => s.kind === 'orchestration-duplication'
722
+ );
723
+ expect(orchSignal).toBeDefined();
724
+ });
725
+
726
+ it('adds hotFiles prompt when hotFiles provided', () => {
727
+ const hotFiles = [
728
+ {
729
+ file: 'src/hot.ts',
730
+ riskScore: 50,
731
+ fanIn: 5,
732
+ fanOut: 5,
733
+ complexityScore: 3,
734
+ exportCount: 2,
735
+ inCycle: false,
736
+ onCriticalPath: false,
737
+ },
738
+ ];
739
+ const result = computeReportAnalysisSummary([], [], hotFiles, null);
740
+ expect(
741
+ result.investigationPrompts.some(
742
+ p => p.includes('hotspot') && p.includes('hot.ts')
743
+ )
744
+ ).toBe(true);
745
+ });
746
+
747
+ it('adds critical-path-context to correlatedSignals when finding file is on critical path', () => {
748
+ const finding = makeFinding({ file: 'src/critical.ts' });
749
+ const ga = makeGraphAnalytics({
750
+ chokepoints: [
751
+ {
752
+ file: 'src/critical.ts',
753
+ score: 50,
754
+ reasons: ['on critical path'],
755
+ fanIn: 5,
756
+ fanOut: 5,
757
+ articulation: false,
758
+ bridgeCount: 0,
759
+ cycleClusterCount: 0,
760
+ onCriticalPath: true,
761
+ },
762
+ ],
763
+ });
764
+ const [enriched] = enrichFindings([finding], [], [], ga);
765
+ expect(enriched.correlatedSignals).toContain('critical-path-context');
766
+ });
767
+
768
+ it('adds top-level-effects to correlatedSignals when entry has effectProfile', () => {
769
+ const entry = makeFileEntry({
770
+ file: 'src/effects.ts',
771
+ effectProfile: {
772
+ totalEffects: 2,
773
+ totalWeight: 10,
774
+ byKind: {},
775
+ highestRisk: 'eval' as const,
776
+ },
777
+ });
778
+ const finding = makeFinding({ file: 'src/effects.ts' });
779
+ const [enriched] = enrichFindings([finding], [entry], [], null);
780
+ expect(enriched.correlatedSignals).toContain('top-level-effects');
781
+ });
782
+ });