octocode-cli 1.2.6 → 1.2.7

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 +7026 -6945
  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,320 @@
1
+ import { findImportLine, isLikelyEntrypoint } from './shared.js';
2
+ import { isTestFile } from '../common/utils.js';
3
+
4
+ import type { FindingDraft } from './shared.js';
5
+ import type { DependencyState } from '../types/index.js';
6
+
7
+ export function buildConsumedFromModule(dependencyState: DependencyState): {
8
+ production: Map<string, Set<string>>;
9
+ test: Map<string, Set<string>>;
10
+ } {
11
+ const production = new Map<string, Set<string>>();
12
+ const test = new Map<string, Set<string>>();
13
+ for (const [
14
+ file,
15
+ imports,
16
+ ] of dependencyState.importedSymbolsByFile.entries()) {
17
+ const targetMap = isTestFile(file) ? test : production;
18
+ for (const symbol of imports) {
19
+ const target = symbol.resolvedModule;
20
+ if (!target) continue;
21
+ if (!targetMap.has(target)) targetMap.set(target, new Set());
22
+ targetMap.get(target)!.add(symbol.importedName);
23
+ }
24
+ }
25
+ for (const [file, reexports] of dependencyState.reExportsByFile.entries()) {
26
+ const targetMap = isTestFile(file) ? test : production;
27
+ for (const reexport of reexports) {
28
+ const target = reexport.resolvedModule;
29
+ if (!target) continue;
30
+ if (!targetMap.has(target)) targetMap.set(target, new Set());
31
+ targetMap.get(target)!.add(reexport.importedName);
32
+ }
33
+ }
34
+ return { production, test };
35
+ }
36
+
37
+ export function detectDeadExports(
38
+ dependencyState: DependencyState,
39
+ consumedFromModule: Map<string, Set<string>>,
40
+ testConsumedFromModule?: Map<string, Set<string>>
41
+ ): FindingDraft[] {
42
+ const findings: FindingDraft[] = [];
43
+ for (const [
44
+ file,
45
+ exportsList,
46
+ ] of dependencyState.declaredExportsByFile.entries()) {
47
+ if (isTestFile(file)) continue;
48
+ if (isLikelyEntrypoint(file)) continue;
49
+ const consumed = consumedFromModule.get(file) || new Set<string>();
50
+ const testConsumed = testConsumedFromModule?.get(file) || new Set<string>();
51
+ const hasNamespaceUse = consumed.has('*');
52
+ const hasTestNamespaceUse = testConsumed.has('*');
53
+ for (const exported of exportsList) {
54
+ if (exported.name === 'default' && isLikelyEntrypoint(file)) continue;
55
+ if (hasNamespaceUse || consumed.has(exported.name)) continue;
56
+ if (hasTestNamespaceUse || testConsumed.has(exported.name)) continue;
57
+ findings.push({
58
+ severity: exported.kind === 'type' ? 'medium' : 'high',
59
+ category: 'dead-export',
60
+ file,
61
+ lineStart: exported.lineStart || 1,
62
+ lineEnd: exported.lineEnd || exported.lineStart || 1,
63
+ title: `Unused export: ${exported.name}`,
64
+ reason: `Exported symbol "${exported.name}" has no observed import or re-export usage in production or test files.`,
65
+ files: [
66
+ `${file}:${exported.lineStart || 1}-${exported.lineEnd || exported.lineStart || 1}`,
67
+ ],
68
+ suggestedFix: {
69
+ strategy: 'Remove or internalize unused exports.',
70
+ steps: [
71
+ 'Confirm symbol is not part of intentional public API surface.',
72
+ 'Remove export modifier or delete symbol if truly unused.',
73
+ 'Re-run scan and tests to ensure no hidden runtime usage.',
74
+ ],
75
+ },
76
+ impact: 'Shrinks public API surface and reduces accidental coupling.',
77
+ tags: ['dead-code', 'api-surface', 'cleanup'],
78
+ lspHints: [
79
+ {
80
+ tool: 'lspFindReferences',
81
+ symbolName: exported.name,
82
+ lineHint: exported.lineStart || 1,
83
+ file,
84
+ expectedResult: `confirm "${exported.name}" has no import references before removing`,
85
+ },
86
+ ],
87
+ });
88
+ }
89
+ }
90
+ return findings;
91
+ }
92
+
93
+ export function detectDeadReExports(
94
+ dependencyState: DependencyState,
95
+ consumedFromModule: Map<string, Set<string>>
96
+ ): FindingDraft[] {
97
+ const findings: FindingDraft[] = [];
98
+ for (const [
99
+ barrelFile,
100
+ reexports,
101
+ ] of dependencyState.reExportsByFile.entries()) {
102
+ if (isTestFile(barrelFile)) continue;
103
+ const consumed = consumedFromModule.get(barrelFile) || new Set<string>();
104
+ const hasNamespaceUse = consumed.has('*');
105
+ const sourceByExportedAs = new Map<string, Set<string>>();
106
+ const localExportNames = new Set(
107
+ (dependencyState.declaredExportsByFile.get(barrelFile) || []).map(
108
+ entry => entry.name
109
+ )
110
+ );
111
+
112
+ for (const ref of reexports) {
113
+ const exportedAs = ref.exportedAs;
114
+ if (!sourceByExportedAs.has(exportedAs))
115
+ sourceByExportedAs.set(exportedAs, new Set());
116
+ sourceByExportedAs
117
+ .get(exportedAs)!
118
+ .add(ref.resolvedModule || ref.sourceModule);
119
+
120
+ const isUsed =
121
+ hasNamespaceUse ||
122
+ consumed.has(exportedAs) ||
123
+ (ref.isStar && consumed.size > 0);
124
+ if (!isUsed) {
125
+ findings.push({
126
+ severity: 'medium',
127
+ category: 'dead-re-export',
128
+ file: barrelFile,
129
+ lineStart: ref.lineStart || 1,
130
+ lineEnd: ref.lineEnd || ref.lineStart || 1,
131
+ title: `Unused re-export: ${exportedAs}`,
132
+ reason: `Re-exported symbol "${exportedAs}" from ${ref.sourceModule} has no observed downstream imports from this module.`,
133
+ files: [
134
+ `${barrelFile}:${ref.lineStart || 1}-${ref.lineEnd || ref.lineStart || 1}`,
135
+ ],
136
+ suggestedFix: {
137
+ strategy: 'Remove stale barrel re-exports.',
138
+ steps: [
139
+ 'Verify no dynamic import/runtime reflection depends on this export.',
140
+ 'Remove the re-export clause.',
141
+ 'Re-run scan to confirm barrel surface is still complete.',
142
+ ],
143
+ },
144
+ impact: 'Keeps barrel modules focused and easier to reason about.',
145
+ tags: ['dead-code', 'barrel', 'cleanup'],
146
+ });
147
+ }
148
+ }
149
+
150
+ for (const [name, sources] of sourceByExportedAs.entries()) {
151
+ if (sources.size > 1) {
152
+ findings.push({
153
+ severity: 'medium',
154
+ category: 're-export-duplication',
155
+ file: barrelFile,
156
+ lineStart: 1,
157
+ lineEnd: 1,
158
+ title: `Duplicate re-export paths: ${name}`,
159
+ reason: `Symbol "${name}" is re-exported from multiple sources in the same barrel.`,
160
+ files: [barrelFile],
161
+ suggestedFix: {
162
+ strategy: 'Keep one canonical re-export source per symbol.',
163
+ steps: [
164
+ 'Select a canonical module for the symbol.',
165
+ 'Remove duplicate re-export paths.',
166
+ 'Document intended public export map for the barrel.',
167
+ ],
168
+ },
169
+ impact: 'Reduces API ambiguity and import inconsistency.',
170
+ tags: ['duplication', 'barrel', 'api-surface'],
171
+ });
172
+ }
173
+ if (name !== '*' && localExportNames.has(name)) {
174
+ findings.push({
175
+ severity: 'high',
176
+ category: 're-export-shadowed',
177
+ file: barrelFile,
178
+ lineStart: 1,
179
+ lineEnd: 1,
180
+ title: `Shadowed export in barrel: ${name}`,
181
+ reason: `Barrel exports "${name}" both locally and through re-export, which can hide origin and create ambiguity.`,
182
+ files: [barrelFile],
183
+ suggestedFix: {
184
+ strategy: 'Disambiguate local vs re-exported symbol ownership.',
185
+ steps: [
186
+ 'Pick a single source of truth for the symbol in this barrel.',
187
+ 'Rename or remove the conflicting export path.',
188
+ 'Update import call-sites to use the canonical export.',
189
+ ],
190
+ },
191
+ impact: 'Prevents subtle API conflicts and shadowing confusion.',
192
+ tags: ['barrel', 'api-surface', 'ambiguity'],
193
+ });
194
+ }
195
+ }
196
+ }
197
+ return findings;
198
+ }
199
+
200
+ export function detectUnusedNpmDeps(
201
+ externalDeps: Map<string, Set<string>>,
202
+ packageJsonDeps: Record<string, string>,
203
+ devDeps: Record<string, string> = {}
204
+ ): FindingDraft[] {
205
+ const findings: FindingDraft[] = [];
206
+
207
+ const usedPackages = new Set<string>();
208
+ for (const depSet of externalDeps.values()) {
209
+ for (const dep of depSet) {
210
+ const parts = dep.split('/');
211
+ usedPackages.add(
212
+ dep.startsWith('@') && parts.length >= 2
213
+ ? `${parts[0]}/${parts[1]}`
214
+ : parts[0]
215
+ );
216
+ }
217
+ }
218
+
219
+ for (const pkgName of Object.keys(packageJsonDeps)) {
220
+ if (!usedPackages.has(pkgName)) {
221
+ findings.push({
222
+ severity: 'medium',
223
+ category: 'unused-npm-dependency',
224
+ file: 'package.json',
225
+ lineStart: 1,
226
+ lineEnd: 1,
227
+ title: `Unused dependency: ${pkgName}`,
228
+ reason: `Package "${pkgName}" is in dependencies but no import was found.`,
229
+ files: ['package.json'],
230
+ suggestedFix: {
231
+ strategy: 'Remove unused dependency from package.json.',
232
+ steps: [
233
+ 'Verify the package is not loaded dynamically or via CLI scripts.',
234
+ 'Check if it is a peer dependency required at runtime.',
235
+ 'Run `npm uninstall` or remove from package.json.',
236
+ ],
237
+ },
238
+ impact: 'Reduces install size and attack surface.',
239
+ tags: ['dependency', 'hygiene', 'bundle-size'],
240
+ });
241
+ }
242
+ }
243
+
244
+ for (const pkgName of Object.keys(devDeps)) {
245
+ if (!usedPackages.has(pkgName)) {
246
+ findings.push({
247
+ severity: 'low',
248
+ category: 'unused-npm-dependency',
249
+ file: 'package.json',
250
+ lineStart: 1,
251
+ lineEnd: 1,
252
+ title: `Unused devDependency: ${pkgName}`,
253
+ reason: `Package "${pkgName}" is in devDependencies but no import was found.`,
254
+ files: ['package.json'],
255
+ suggestedFix: {
256
+ strategy: 'Remove unused devDependency from package.json.',
257
+ steps: [
258
+ 'Verify the package is not used by build scripts, config files, or CLI tools.',
259
+ 'Run `npm uninstall` or remove from package.json.',
260
+ ],
261
+ },
262
+ impact: 'Reduces install size and dependency maintenance burden.',
263
+ tags: ['dependency', 'hygiene', 'dev-tooling'],
264
+ });
265
+ }
266
+ }
267
+
268
+ return findings;
269
+ }
270
+
271
+ export function detectBoundaryViolations(
272
+ dependencyState: DependencyState
273
+ ): FindingDraft[] {
274
+ const findings: FindingDraft[] = [];
275
+
276
+ for (const file of dependencyState.files) {
277
+ if (isTestFile(file)) continue;
278
+
279
+ const fileMatch = file.match(/^packages\/([^/]+)\//);
280
+ if (!fileMatch) continue;
281
+ const filePkg = fileMatch[1];
282
+
283
+ for (const dep of dependencyState.outgoing.get(file) || new Set()) {
284
+ const depMatch = dep.match(/^packages\/([^/]+)\//);
285
+ if (!depMatch) continue;
286
+ if (depMatch[1] === filePkg) continue;
287
+
288
+ const isPublicApi = /^packages\/[^/]+\/(src\/)?index\.[mc]?[jt]sx?$/.test(
289
+ dep
290
+ );
291
+ if (!isPublicApi) {
292
+ const isDeep = dep.includes('/internal/') || dep.includes('/private/');
293
+ const importRef = findImportLine(dependencyState, file, dep);
294
+ findings.push({
295
+ severity: isDeep ? 'high' : 'medium',
296
+ category: 'package-boundary-violation',
297
+ file,
298
+ lineStart: importRef.lineStart,
299
+ lineEnd: importRef.lineEnd,
300
+ title: `Cross-package import bypasses public API`,
301
+ reason: `"${file}" imports "${dep}" directly instead of through the package public entry.`,
302
+ files: [file, dep],
303
+ suggestedFix: {
304
+ strategy: 'Import through the package public API (index file).',
305
+ steps: [
306
+ 'Re-export the needed symbol from the target package index.',
307
+ 'Update the import to use the package name or index path.',
308
+ 'If the symbol is internal, reconsider the dependency.',
309
+ ],
310
+ },
311
+ impact:
312
+ 'Enforces clean package boundaries and prevents coupling to internals.',
313
+ tags: ['boundary', 'coupling', 'encapsulation'],
314
+ });
315
+ }
316
+ }
317
+ }
318
+
319
+ return findings;
320
+ }
@@ -0,0 +1,376 @@
1
+ import { isLikelyEntrypoint } from './shared.js';
2
+ import { canAddFinding } from './shared.js';
3
+ import { isTestFile } from '../common/utils.js';
4
+
5
+ import type { FindingDraft } from './shared.js';
6
+ import type {
7
+ DependencyState,
8
+ DependencySummary,
9
+ FileEntry,
10
+ Finding,
11
+ HotFile,
12
+ } from '../types/index.js';
13
+
14
+ export function computeBarrelDepth(
15
+ file: string,
16
+ dependencyState: DependencyState,
17
+ visited: Set<string> = new Set()
18
+ ): number {
19
+ if (visited.has(file)) return 0;
20
+ visited.add(file);
21
+
22
+ const reexports = dependencyState.reExportsByFile.get(file);
23
+ if (!reexports || reexports.length === 0) return 0;
24
+
25
+ let maxChild = 0;
26
+ for (const re of reexports) {
27
+ const target = re.resolvedModule;
28
+ if (!target) continue;
29
+ const targetRe = dependencyState.reExportsByFile.get(target);
30
+ if (targetRe && targetRe.length > 0) {
31
+ maxChild = Math.max(
32
+ maxChild,
33
+ computeBarrelDepth(target, dependencyState, visited)
34
+ );
35
+ }
36
+ }
37
+
38
+ return 1 + maxChild;
39
+ }
40
+
41
+ export function detectBarrelExplosion(
42
+ dependencyState: DependencyState,
43
+ symbolThreshold: number = 30
44
+ ): FindingDraft[] {
45
+ const findings: FindingDraft[] = [];
46
+
47
+ for (const [file, reexports] of dependencyState.reExportsByFile.entries()) {
48
+ if (isTestFile(file)) continue;
49
+ if (reexports.length === 0) continue;
50
+
51
+ if (reexports.length > symbolThreshold) {
52
+ findings.push({
53
+ severity: reexports.length > symbolThreshold * 2 ? 'high' : 'medium',
54
+ category: 'barrel-explosion',
55
+ file,
56
+ lineStart: 1,
57
+ lineEnd: 1,
58
+ title: `Barrel explosion: ${file}`,
59
+ reason: `Barrel re-exports ${reexports.length} symbols (threshold: ${symbolThreshold}). Large barrels hurt bundling.`,
60
+ files: [file],
61
+ suggestedFix: {
62
+ strategy:
63
+ 'Split barrel or use direct imports to reduce bundler cost.',
64
+ steps: [
65
+ 'Group re-exports by domain into sub-barrels.',
66
+ 'Let consumers import directly from source modules.',
67
+ 'Remove unused re-exports (check dead-re-export findings).',
68
+ ],
69
+ },
70
+ impact: 'Reduces bundle size and speeds up IDE/tooling.',
71
+ tags: ['barrel', 'bundle-size', 'tree-shaking'],
72
+ });
73
+ }
74
+
75
+ const depth = computeBarrelDepth(file, dependencyState);
76
+ if (depth > 2) {
77
+ findings.push({
78
+ severity: 'high',
79
+ category: 'barrel-explosion',
80
+ file,
81
+ lineStart: 1,
82
+ lineEnd: 1,
83
+ title: `Deep barrel chain: ${file} (depth ${depth})`,
84
+ reason: `Barrel chain is ${depth} levels deep. Deep chains defeat tree-shaking.`,
85
+ files: [file],
86
+ suggestedFix: {
87
+ strategy: 'Flatten barrel chain to at most 2 levels.',
88
+ steps: [
89
+ 'Re-export directly from source modules instead of intermediate barrels.',
90
+ 'Remove intermediate barrel layers that add no value.',
91
+ ],
92
+ },
93
+ impact: 'Improves tree-shaking efficiency and import resolution speed.',
94
+ tags: ['barrel', 'bundle-size', 'tree-shaking'],
95
+ });
96
+ }
97
+ }
98
+
99
+ return findings;
100
+ }
101
+
102
+ export function detectImportSideEffectRisk(
103
+ fileSummaries: FileEntry[],
104
+ dependencyState: DependencyState,
105
+ dependencySummary: DependencySummary,
106
+ hotFiles: HotFile[]
107
+ ): FindingDraft[] {
108
+ const findings: FindingDraft[] = [];
109
+
110
+ const cycleFiles = new Set<string>();
111
+ for (const cycle of dependencySummary.cycles) {
112
+ for (const node of cycle.path) cycleFiles.add(node);
113
+ }
114
+ const criticalPathFiles = new Set<string>();
115
+ for (const cp of dependencySummary.criticalPaths) {
116
+ for (const node of cp.path) criticalPathFiles.add(node);
117
+ }
118
+ const hotFileMap = new Map<string, HotFile>();
119
+ for (const hf of hotFiles) hotFileMap.set(hf.file, hf);
120
+
121
+ for (const entry of fileSummaries) {
122
+ if (isTestFile(entry.file)) continue;
123
+ const effects = entry.topLevelEffects;
124
+ if (!effects || effects.length === 0) continue;
125
+
126
+ let astBase = 0;
127
+ for (const eff of effects) astBase += eff.weight;
128
+
129
+ const fanIn = (dependencyState.incoming.get(entry.file) || new Set()).size;
130
+ let impactBoost = 0;
131
+ if (fanIn >= 20) impactBoost += 8;
132
+ else if (fanIn >= 8) impactBoost += 4;
133
+ if (criticalPathFiles.has(entry.file)) impactBoost += 6;
134
+ if (cycleFiles.has(entry.file)) impactBoost += 3;
135
+
136
+ let roleDiscount = 0;
137
+ if (isLikelyEntrypoint(entry.file)) roleDiscount += 4;
138
+
139
+ const totalRisk = astBase + impactBoost - roleDiscount;
140
+ if (totalRisk < 4) continue;
141
+
142
+ const severity: Finding['severity'] =
143
+ totalRisk >= 18
144
+ ? 'critical'
145
+ : totalRisk >= 12
146
+ ? 'high'
147
+ : totalRisk >= 7
148
+ ? 'medium'
149
+ : 'low';
150
+
151
+ const highConfidenceEffects = effects.filter(e => e.confidence === 'high');
152
+ const confidence: 'high' | 'medium' | 'low' =
153
+ highConfidenceEffects.length > 0
154
+ ? 'high'
155
+ : effects.some(e => e.confidence === 'medium')
156
+ ? 'medium'
157
+ : 'low';
158
+
159
+ const effectDetails = effects
160
+ .map(e => `${e.detail} (line ${e.lineStart})`)
161
+ .join('; ');
162
+ const impactDetails: string[] = [];
163
+ if (fanIn >= 8) impactDetails.push(`fan-in=${fanIn}`);
164
+ if (criticalPathFiles.has(entry.file))
165
+ impactDetails.push('on critical path');
166
+ if (cycleFiles.has(entry.file)) impactDetails.push('in dependency cycle');
167
+ if (isLikelyEntrypoint(entry.file))
168
+ impactDetails.push('entrypoint (discounted)');
169
+ const impactSuffix =
170
+ impactDetails.length > 0
171
+ ? ` Architecture context: ${impactDetails.join(', ')}.`
172
+ : '';
173
+
174
+ const firstEffect = effects[0];
175
+ if (!canAddFinding(findings)) break;
176
+ findings.push({
177
+ severity,
178
+ category: 'import-side-effect-risk',
179
+ file: entry.file,
180
+ lineStart: firstEffect.lineStart,
181
+ lineEnd: firstEffect.lineEnd,
182
+ title: `Import-time side effect${effects.length > 1 ? `s (${effects.length})` : ''}: ${entry.file}`,
183
+ reason: `Module executes work at import time: ${effectDetails}. Risk score: ${totalRisk} (ast=${astBase}, impact=+${impactBoost}, role=-${roleDiscount}). Confidence: ${confidence}.${impactSuffix}`,
184
+ files: [entry.file],
185
+ suggestedFix: {
186
+ strategy:
187
+ 'Move import-time side effects behind explicit initialization or lazy loading.',
188
+ steps: [
189
+ 'Wrap startup logic in an exported init() function instead of running at module scope.',
190
+ 'Replace synchronous I/O with async alternatives called at runtime.',
191
+ 'Guard side-effect imports with dynamic import() behind feature checks.',
192
+ 'If this is an intentional entrypoint, consider adding a suppression comment.',
193
+ ],
194
+ },
195
+ impact: `Importing this module triggers ${effects.length} side effect(s). With fan-in=${fanIn}, unintended imports can degrade startup latency and cause surprising runtime behavior.`,
196
+ tags: ['import-side-effect', 'startup', 'architecture', 'performance'],
197
+ lspHints: [
198
+ {
199
+ tool: 'lspFindReferences',
200
+ symbolName:
201
+ entry.file
202
+ .split('/')
203
+ .pop()
204
+ ?.replace(/\.[^.]+$/, '') || entry.file,
205
+ lineHint: 1,
206
+ file: entry.file,
207
+ expectedResult: `find all modules that import this file and may trigger side effects`,
208
+ },
209
+ ],
210
+ });
211
+ }
212
+
213
+ return findings;
214
+ }
215
+
216
+ export function detectNamespaceImport(
217
+ dependencyState: DependencyState
218
+ ): FindingDraft[] {
219
+ const findings: FindingDraft[] = [];
220
+
221
+ for (const [
222
+ file,
223
+ imports,
224
+ ] of dependencyState.importedSymbolsByFile.entries()) {
225
+ if (isTestFile(file)) continue;
226
+
227
+ for (const ref of imports) {
228
+ if (ref.importedName !== '*') continue;
229
+ if (ref.isTypeOnly) continue;
230
+ if (ref.localName === 'require') continue;
231
+
232
+ const isInternal = ref.resolvedModule != null;
233
+ const fanIn = isInternal
234
+ ? (dependencyState.incoming.get(ref.resolvedModule!) || new Set()).size
235
+ : 0;
236
+
237
+ findings.push({
238
+ severity: isInternal && fanIn > 5 ? 'high' : 'medium',
239
+ category: 'namespace-import',
240
+ file,
241
+ lineStart: ref.lineStart || 1,
242
+ lineEnd: ref.lineEnd || ref.lineStart || 1,
243
+ title: `Namespace import blocks tree-shaking: import * as ${ref.localName}`,
244
+ reason: `\`import * as ${ref.localName} from '${ref.sourceModule}'\` forces bundlers to include the entire module. Named imports allow dead-code elimination of unused exports.${isInternal ? ` Target module has fan-in=${fanIn}.` : ''}`,
245
+ files: [
246
+ `${file}:${ref.lineStart || 1}-${ref.lineEnd || ref.lineStart || 1}`,
247
+ ],
248
+ suggestedFix: {
249
+ strategy:
250
+ 'Replace namespace import with named imports for used symbols.',
251
+ steps: [
252
+ `Find which properties of \`${ref.localName}\` are actually accessed in this file.`,
253
+ `Replace \`import * as ${ref.localName}\` with \`import { usedA, usedB } from '${ref.sourceModule}'\`.`,
254
+ 'If many properties are used, consider splitting the source module into smaller modules.',
255
+ ],
256
+ },
257
+ impact:
258
+ 'Enables bundlers to tree-shake unused exports, reducing bundle size.',
259
+ tags: ['tree-shaking', 'bundle-size', 'namespace-import'],
260
+ });
261
+ }
262
+ }
263
+
264
+ return findings;
265
+ }
266
+
267
+ export function detectCommonJsInEsm(
268
+ dependencyState: DependencyState
269
+ ): FindingDraft[] {
270
+ const findings: FindingDraft[] = [];
271
+
272
+ for (const [
273
+ file,
274
+ imports,
275
+ ] of dependencyState.importedSymbolsByFile.entries()) {
276
+ if (isTestFile(file)) continue;
277
+
278
+ const requireImports = imports.filter(
279
+ r => r.localName === 'require' && !r.isTypeOnly
280
+ );
281
+ if (requireImports.length === 0) continue;
282
+
283
+ const hasEsmImport = imports.some(r => r.localName !== 'require');
284
+ const severity = hasEsmImport ? 'high' : 'medium';
285
+
286
+ for (const ref of requireImports) {
287
+ findings.push({
288
+ severity,
289
+ category: hasEsmImport ? 'mixed-module-format' : 'commonjs-in-esm',
290
+ file,
291
+ lineStart: ref.lineStart || 1,
292
+ lineEnd: ref.lineEnd || ref.lineStart || 1,
293
+ title: hasEsmImport
294
+ ? `Mixed ESM/CJS: require('${ref.sourceModule}') in ESM file`
295
+ : `CommonJS require blocks tree-shaking: require('${ref.sourceModule}')`,
296
+ reason: hasEsmImport
297
+ ? `File uses both ESM \`import\` and CJS \`require()\`. Mixed formats force bundlers to treat the module as CJS, disabling tree-shaking entirely. Found ${requireImports.length} require() call(s).`
298
+ : `\`require('${ref.sourceModule}')\` is a CommonJS pattern that bundlers cannot statically analyze. ESM \`import\` enables tree-shaking.`,
299
+ files: [
300
+ `${file}:${ref.lineStart || 1}-${ref.lineEnd || ref.lineStart || 1}`,
301
+ ],
302
+ suggestedFix: {
303
+ strategy: 'Convert require() to ESM import.',
304
+ steps: [
305
+ `Replace \`const mod = require('${ref.sourceModule}')\` with \`import mod from '${ref.sourceModule}'\` or named imports.`,
306
+ 'If the require is conditional, use dynamic `import()` instead.',
307
+ 'Ensure the target module supports ESM (check package.json "type" or "module" field).',
308
+ ],
309
+ },
310
+ impact:
311
+ 'ESM imports enable tree-shaking; CJS requires pull the entire module.',
312
+ tags: ['tree-shaking', 'bundle-size', 'commonjs', 'module-format'],
313
+ });
314
+ }
315
+ }
316
+
317
+ return findings;
318
+ }
319
+
320
+ export function detectExportStarLeak(
321
+ dependencyState: DependencyState
322
+ ): FindingDraft[] {
323
+ const findings: FindingDraft[] = [];
324
+
325
+ for (const [file, reexports] of dependencyState.reExportsByFile.entries()) {
326
+ if (isTestFile(file)) continue;
327
+
328
+ const starReexports = reexports.filter(r => r.isStar && !r.isTypeOnly);
329
+ if (starReexports.length === 0) continue;
330
+
331
+ for (const ref of starReexports) {
332
+ const targetExportCount = ref.resolvedModule
333
+ ? (dependencyState.declaredExportsByFile.get(ref.resolvedModule) || [])
334
+ .length
335
+ : 0;
336
+
337
+ const targetHasStars = ref.resolvedModule
338
+ ? (dependencyState.reExportsByFile.get(ref.resolvedModule) || []).some(
339
+ r => r.isStar
340
+ )
341
+ : false;
342
+
343
+ const severity = targetHasStars
344
+ ? 'high'
345
+ : targetExportCount > 20
346
+ ? 'high'
347
+ : 'medium';
348
+
349
+ findings.push({
350
+ severity,
351
+ category: 'export-star-leak',
352
+ file,
353
+ lineStart: ref.lineStart || 1,
354
+ lineEnd: ref.lineEnd || ref.lineStart || 1,
355
+ title: `export * leaks entire module surface: ${ref.sourceModule}`,
356
+ reason: `\`export * from '${ref.sourceModule}'\` re-exports every symbol from the source, defeating granular tree-shaking.${targetExportCount > 0 ? ` Target exports ${targetExportCount} symbols.` : ''}${targetHasStars ? ' Target itself contains export-star chains, amplifying the leak.' : ''}`,
357
+ files: [
358
+ `${file}:${ref.lineStart || 1}-${ref.lineEnd || ref.lineStart || 1}`,
359
+ ],
360
+ suggestedFix: {
361
+ strategy: 'Replace export * with explicit named re-exports.',
362
+ steps: [
363
+ `List the symbols actually consumed from \`${ref.sourceModule}\` by downstream modules.`,
364
+ `Replace \`export * from '${ref.sourceModule}'\` with \`export { A, B, C } from '${ref.sourceModule}'\`.`,
365
+ 'This lets bundlers eliminate unused re-exports during tree-shaking.',
366
+ ],
367
+ },
368
+ impact:
369
+ 'Explicit re-exports enable precise tree-shaking and make the public API surface visible.',
370
+ tags: ['tree-shaking', 'bundle-size', 'export-star', 'api-surface'],
371
+ });
372
+ }
373
+ }
374
+
375
+ return findings;
376
+ }